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;
71 case ISD::FP_ROUND: R = ScalarizeVecRes_FP_ROUND(N); break;
73 R = ScalarizeVecRes_CONVERT_FROM_ARBITRARY_FP(N);
74 break;
76 R = ScalarizeVecRes_CONVERT_TO_ARBITRARY_FP(N);
77 break;
78 case ISD::AssertZext:
79 case ISD::AssertSext:
80 case ISD::FPOWI:
82 R = ScalarizeVecRes_UnaryOpWithExtraInput(N);
83 break;
84 case ISD::INSERT_VECTOR_ELT: R = ScalarizeVecRes_INSERT_VECTOR_ELT(N); break;
86 R = ScalarizeVecRes_ATOMIC_LOAD(cast<AtomicSDNode>(N));
87 break;
111 R = ScalarizeVecRes_ATOMIC_RMW(cast<AtomicSDNode>(N));
112 break;
113 case ISD::LOAD: R = ScalarizeVecRes_LOAD(cast<LoadSDNode>(N));break;
114 case ISD::SCALAR_TO_VECTOR: R = ScalarizeVecRes_SCALAR_TO_VECTOR(N); break;
117 R = ScalarizeVecRes_VECTOR_INTERLEAVE_DEINTERLEAVE(N);
118 break;
119 case ISD::SIGN_EXTEND_INREG: R = ScalarizeVecRes_InregOp(N); break;
120 case ISD::VSELECT: R = ScalarizeVecRes_VSELECT(N); break;
121 case ISD::SELECT: R = ScalarizeVecRes_SELECT(N); break;
122 case ISD::SELECT_CC: R = ScalarizeVecRes_SELECT_CC(N); break;
123 case ISD::SETCC: R = ScalarizeVecRes_SETCC(N); break;
125 R = ScalarizeVecRes_VECTOR_MATCH(N);
126 break;
127 case ISD::POISON:
128 case ISD::UNDEF: R = ScalarizeVecRes_UNDEF(N); break;
129 case ISD::VECTOR_SHUFFLE: R = ScalarizeVecRes_VECTOR_SHUFFLE(N); break;
130 case ISD::IS_FPCLASS: R = ScalarizeVecRes_IS_FPCLASS(N); break;
134 R = ScalarizeVecRes_VecInregOp(N);
135 break;
136 case ISD::ABS:
138 case ISD::ANY_EXTEND:
139 case ISD::BITREVERSE:
140 case ISD::BSWAP:
141 case ISD::CTLZ:
143 case ISD::CTPOP:
144 case ISD::CTTZ:
146 case ISD::FABS:
147 case ISD::FACOS:
148 case ISD::FASIN:
149 case ISD::FATAN:
150 case ISD::FCEIL:
151 case ISD::FCOS:
152 case ISD::FCOSH:
153 case ISD::FEXP:
154 case ISD::FEXP2:
155 case ISD::FEXP10:
156 case ISD::FFLOOR:
157 case ISD::FLOG:
158 case ISD::FLOG10:
159 case ISD::FLOG2:
160 case ISD::FNEARBYINT:
161 case ISD::FNEG:
162 case ISD::FREEZE:
163 case ISD::ARITH_FENCE:
164 case ISD::FP_EXTEND:
165 case ISD::FP_TO_SINT:
166 case ISD::FP_TO_UINT:
167 case ISD::FRINT:
168 case ISD::LRINT:
169 case ISD::LLRINT:
170 case ISD::FROUND:
171 case ISD::FROUNDEVEN:
172 case ISD::LROUND:
173 case ISD::LLROUND:
174 case ISD::FSIN:
175 case ISD::FSINH:
176 case ISD::FSQRT:
177 case ISD::FTAN:
178 case ISD::FTANH:
179 case ISD::FTRUNC:
180 case ISD::SIGN_EXTEND:
181 case ISD::SINT_TO_FP:
182 case ISD::TRUNCATE:
183 case ISD::UINT_TO_FP:
184 case ISD::ZERO_EXTEND:
186 R = ScalarizeVecRes_UnaryOp(N);
187 break;
189 R = ScalarizeVecRes_ADDRSPACECAST(N);
190 break;
191 case ISD::FMODF:
192 case ISD::FFREXP:
193 case ISD::FSINCOS:
194 case ISD::FSINCOSPI:
195 R = ScalarizeVecRes_UnaryOpWithTwoResults(N, ResNo);
196 break;
197 case ISD::ADD:
198 case ISD::AND:
199 case ISD::AVGCEILS:
200 case ISD::AVGCEILU:
201 case ISD::AVGFLOORS:
202 case ISD::AVGFLOORU:
203 case ISD::FADD:
204 case ISD::FCOPYSIGN:
205 case ISD::FDIV:
206 case ISD::FMUL:
207 case ISD::FMINNUM:
208 case ISD::FMAXNUM:
211 case ISD::FMINIMUM:
212 case ISD::FMAXIMUM:
213 case ISD::FMINIMUMNUM:
214 case ISD::FMAXIMUMNUM:
215 case ISD::ABDS:
216 case ISD::ABDU:
217 case ISD::SMIN:
218 case ISD::SMAX:
219 case ISD::UMIN:
220 case ISD::UMAX:
221
222 case ISD::SADDSAT:
223 case ISD::UADDSAT:
224 case ISD::SSUBSAT:
225 case ISD::USUBSAT:
226 case ISD::SSHLSAT:
227 case ISD::USHLSAT:
228
229 case ISD::FPOW:
230 case ISD::FATAN2:
231 case ISD::FREM:
232 case ISD::FSUB:
233 case ISD::MUL:
234 case ISD::MULHS:
235 case ISD::MULHU:
236 case ISD::OR:
237 case ISD::SDIV:
238 case ISD::SREM:
239 case ISD::SUB:
240 case ISD::UDIV:
241 case ISD::UREM:
242 case ISD::XOR:
243 case ISD::SHL:
244 case ISD::SRA:
245 case ISD::SRL:
246 case ISD::ROTL:
247 case ISD::ROTR:
248 case ISD::CLMUL:
249 case ISD::CLMULR:
250 case ISD::CLMULH:
251 case ISD::PEXT:
252 case ISD::PDEP:
253 R = ScalarizeVecRes_BinOp(N);
254 break;
255
256 case ISD::MASKED_UDIV:
257 case ISD::MASKED_SDIV:
258 case ISD::MASKED_UREM:
259 case ISD::MASKED_SREM:
260 R = ScalarizeVecRes_MaskedBinOp(N);
261 break;
262
263 case ISD::FLDEXP:
264 R = ScalarizeVecRes_FPOp_MultiType(N);
265 break;
266
267 case ISD::SCMP:
268 case ISD::UCMP:
269 R = ScalarizeVecRes_CMP(N);
270 break;
271
272 case ISD::FMA:
273 case ISD::FSHL:
274 case ISD::FSHR:
275 R = ScalarizeVecRes_TernaryOp(N);
276 break;
277
278#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
279 case ISD::STRICT_##DAGN:
280#include "llvm/IR/ConstrainedOps.def"
281 R = ScalarizeVecRes_StrictFPOp(N);
282 break;
283
286 R = ScalarizeVecRes_FP_TO_XINT_SAT(N);
287 break;
288
289 case ISD::UADDO:
290 case ISD::SADDO:
291 case ISD::USUBO:
292 case ISD::SSUBO:
293 case ISD::UMULO:
294 case ISD::SMULO:
295 R = ScalarizeVecRes_OverflowOp(N, ResNo);
296 break;
297 case ISD::SMULFIX:
298 case ISD::SMULFIXSAT:
299 case ISD::UMULFIX:
300 case ISD::UMULFIXSAT:
301 case ISD::SDIVFIX:
302 case ISD::SDIVFIXSAT:
303 case ISD::UDIVFIX:
304 case ISD::UDIVFIXSAT:
305 R = ScalarizeVecRes_FIX(N);
306 break;
311 R = ScalarizeVecRes_PartialReduction(N);
312 break;
313 }
314
315 // If R is null, the sub-method took care of registering the result.
316 if (R.getNode())
317 SetScalarizedVector(SDValue(N, ResNo), R);
318}
319
320SDValue DAGTypeLegalizer::ScalarizeVecRes_BinOp(SDNode *N) {
321 SDValue LHS = GetScalarizedVector(N->getOperand(0));
322 SDValue RHS = GetScalarizedVector(N->getOperand(1));
323 return DAG.getNode(N->getOpcode(), SDLoc(N),
324 LHS.getValueType(), LHS, RHS, N->getFlags());
325}
326
327SDValue DAGTypeLegalizer::ScalarizeVecRes_MaskedBinOp(SDNode *N) {
328 SDLoc DL(N);
329 SDValue LHS = GetScalarizedVector(N->getOperand(0));
330 SDValue RHS = GetScalarizedVector(N->getOperand(1));
331 SDValue Mask = N->getOperand(2);
332 EVT MaskVT = Mask.getValueType();
333 // The vselect result and input vectors need scalarizing, but it's
334 // not a given that the mask does. For instance, in AVX512 v1i1 is legal.
335 // See the similar logic in ScalarizeVecRes_SETCC.
336 if (getTypeAction(MaskVT) == TargetLowering::TypeScalarizeVector)
337 Mask = GetScalarizedVector(Mask);
338 else
339 Mask = DAG.getExtractVectorElt(DL, MaskVT.getVectorElementType(), Mask, 0);
340 // Vectors may have a different boolean contents to scalars, so truncate to i1
341 // and let type legalization promote appropriately.
342 Mask = DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, Mask);
343 // Masked binary ops don't have UB on disabled lanes but produce poison, so
344 // use 1 as the divisor to avoid division by zero and overflow.
345 SDValue Divisor = DAG.getSelect(DL, LHS.getValueType(), Mask, RHS,
346 DAG.getConstant(1, DL, LHS.getValueType()));
347 return DAG.getNode(ISD::getUnmaskedBinOpOpcode(N->getOpcode()), DL,
348 LHS.getValueType(), LHS, Divisor);
349}
350
351SDValue DAGTypeLegalizer::ScalarizeVecRes_CMP(SDNode *N) {
352 SDLoc DL(N);
353
354 SDValue LHS = N->getOperand(0);
355 SDValue RHS = N->getOperand(1);
356 if (getTypeAction(LHS.getValueType()) ==
358 LHS = GetScalarizedVector(LHS);
359 RHS = GetScalarizedVector(RHS);
360 } else {
361 EVT VT = LHS.getValueType().getVectorElementType();
362 LHS = DAG.getExtractVectorElt(DL, VT, LHS, 0);
363 RHS = DAG.getExtractVectorElt(DL, VT, RHS, 0);
364 }
365
366 return DAG.getNode(N->getOpcode(), SDLoc(N),
367 N->getValueType(0).getVectorElementType(), LHS, RHS);
368}
369
370SDValue DAGTypeLegalizer::ScalarizeVecRes_TernaryOp(SDNode *N) {
371 SDValue Op0 = GetScalarizedVector(N->getOperand(0));
372 SDValue Op1 = GetScalarizedVector(N->getOperand(1));
373 SDValue Op2 = GetScalarizedVector(N->getOperand(2));
374 return DAG.getNode(N->getOpcode(), SDLoc(N), Op0.getValueType(), Op0, Op1,
375 Op2, N->getFlags());
376}
377
378SDValue DAGTypeLegalizer::ScalarizeVecRes_FIX(SDNode *N) {
379 SDValue Op0 = GetScalarizedVector(N->getOperand(0));
380 SDValue Op1 = GetScalarizedVector(N->getOperand(1));
381 SDValue Op2 = N->getOperand(2);
382 return DAG.getNode(N->getOpcode(), SDLoc(N), Op0.getValueType(), Op0, Op1,
383 Op2, N->getFlags());
384}
385
386SDValue DAGTypeLegalizer::ScalarizeVecRes_PartialReduction(SDNode *N) {
387 SDValue Acc = GetScalarizedVector(N->getOperand(0));
388 SDValue L = N->getOperand(1);
389 SDValue R = N->getOperand(2);
390 EVT ResVT = Acc.getValueType();
391 EVT InVT = L.getValueType();
392 bool IsFP = ResVT.isFloatingPoint();
393 SDLoc DL(N);
394
395 // Make sure we're not trying an extending partial reduction in this path.
396 assert(InVT.getScalarType() == ResVT && "Extending operands unsupported");
397
398 SDValue Mul = DAG.getNode(IsFP ? ISD::FMUL : ISD::MUL, DL, InVT, L, R);
399 SDValue In = DAG.getNode(IsFP ? ISD::VECREDUCE_FADD : ISD::VECREDUCE_ADD, DL,
400 ResVT, Mul);
401
402 return DAG.getNode(IsFP ? ISD::FADD : ISD::ADD, DL, ResVT, Acc, In);
403}
404
406DAGTypeLegalizer::ScalarizeVecRes_UnaryOpWithTwoResults(SDNode *N,
407 unsigned ResNo) {
408 assert(N->getValueType(0).getVectorNumElements() == 1 &&
409 "Unexpected vector type!");
410 SDValue Elt = GetScalarizedVector(N->getOperand(0));
411
412 EVT VT0 = N->getValueType(0);
413 EVT VT1 = N->getValueType(1);
414 SDLoc dl(N);
415
416 SDNode *ScalarNode =
417 DAG.getNode(N->getOpcode(), dl,
418 {VT0.getScalarType(), VT1.getScalarType()}, Elt)
419 .getNode();
420
421 // Replace the other vector result not being explicitly scalarized here.
422 unsigned OtherNo = 1 - ResNo;
423 EVT OtherVT = N->getValueType(OtherNo);
424 if (getTypeAction(OtherVT) == TargetLowering::TypeScalarizeVector) {
425 SetScalarizedVector(SDValue(N, OtherNo), SDValue(ScalarNode, OtherNo));
426 } else {
427 SDValue OtherVal = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, OtherVT,
428 SDValue(ScalarNode, OtherNo));
429 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
430 }
431
432 return SDValue(ScalarNode, ResNo);
433}
434
435SDValue DAGTypeLegalizer::ScalarizeVecRes_StrictFPOp(SDNode *N) {
436 EVT VT = N->getValueType(0).getVectorElementType();
437 unsigned NumOpers = N->getNumOperands();
438 SDValue Chain = N->getOperand(0);
439 EVT ValueVTs[] = {VT, MVT::Other};
440 SDLoc dl(N);
441
442 SmallVector<SDValue, 4> Opers(NumOpers);
443
444 // The Chain is the first operand.
445 Opers[0] = Chain;
446
447 // Now process the remaining operands.
448 for (unsigned i = 1; i < NumOpers; ++i) {
449 SDValue Oper = N->getOperand(i);
450 EVT OperVT = Oper.getValueType();
451
452 if (OperVT.isVector()) {
453 if (getTypeAction(OperVT) == TargetLowering::TypeScalarizeVector)
454 Oper = GetScalarizedVector(Oper);
455 else
456 Oper =
457 DAG.getExtractVectorElt(dl, OperVT.getVectorElementType(), Oper, 0);
458 }
459
460 Opers[i] = Oper;
461 }
462
463 SDValue Result = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(ValueVTs),
464 Opers, N->getFlags());
465
466 // Legalize the chain result - switch anything that used the old chain to
467 // use the new one.
468 ReplaceValueWith(SDValue(N, 1), Result.getValue(1));
469 return Result;
470}
471
472SDValue DAGTypeLegalizer::ScalarizeVecRes_OverflowOp(SDNode *N,
473 unsigned ResNo) {
474 SDLoc DL(N);
475 EVT ResVT = N->getValueType(0);
476 EVT OvVT = N->getValueType(1);
477
478 SDValue ScalarLHS, ScalarRHS;
479 if (getTypeAction(ResVT) == TargetLowering::TypeScalarizeVector) {
480 ScalarLHS = GetScalarizedVector(N->getOperand(0));
481 ScalarRHS = GetScalarizedVector(N->getOperand(1));
482 } else {
483 SmallVector<SDValue, 1> ElemsLHS, ElemsRHS;
484 DAG.ExtractVectorElements(N->getOperand(0), ElemsLHS);
485 DAG.ExtractVectorElements(N->getOperand(1), ElemsRHS);
486 ScalarLHS = ElemsLHS[0];
487 ScalarRHS = ElemsRHS[0];
488 }
489
490 SDVTList ScalarVTs = DAG.getVTList(
492 SDNode *ScalarNode = DAG.getNode(N->getOpcode(), DL, ScalarVTs,
493 {ScalarLHS, ScalarRHS}, N->getFlags())
494 .getNode();
495
496 // Replace the other vector result not being explicitly scalarized here.
497 unsigned OtherNo = 1 - ResNo;
498 EVT OtherVT = N->getValueType(OtherNo);
499 if (getTypeAction(OtherVT) == TargetLowering::TypeScalarizeVector) {
500 SetScalarizedVector(SDValue(N, OtherNo), SDValue(ScalarNode, OtherNo));
501 } else {
502 SDValue OtherVal = DAG.getNode(
503 ISD::SCALAR_TO_VECTOR, DL, OtherVT, SDValue(ScalarNode, OtherNo));
504 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
505 }
506
507 return SDValue(ScalarNode, ResNo);
508}
509
510SDValue DAGTypeLegalizer::ScalarizeVecRes_MERGE_VALUES(SDNode *N,
511 unsigned ResNo) {
512 SDValue Op = DisintegrateMERGE_VALUES(N, ResNo);
513 return GetScalarizedVector(Op);
514}
515
516SDValue DAGTypeLegalizer::ScalarizeVecRes_LOOP_DEPENDENCE_MASK(SDNode *N) {
517 SDLoc DL(N);
518 // Reuse the expansion (which should scalarize).
519 SDValue Mask = TLI.expandLoopDependenceMask(N, DAG);
520 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
521 N->getValueType(0).getScalarType(), Mask,
522 DAG.getVectorIdxConstant(0, DL));
523}
524
525SDValue DAGTypeLegalizer::ScalarizeVecRes_BITCAST(SDNode *N) {
526 SDValue Op = N->getOperand(0);
527 if (getTypeAction(Op.getValueType()) == TargetLowering::TypeScalarizeVector)
528 Op = GetScalarizedVector(Op);
529 EVT NewVT = N->getValueType(0).getVectorElementType();
530 return DAG.getNode(ISD::BITCAST, SDLoc(N),
531 NewVT, Op);
532}
533
534SDValue DAGTypeLegalizer::ScalarizeVecRes_BUILD_VECTOR_OR_SPLAT(SDNode *N) {
535 EVT EltVT = N->getValueType(0).getVectorElementType();
536 SDValue InOp = N->getOperand(0);
537 // The BUILD_VECTOR / SPLAT operands may be of wider element types and
538 // we may need to truncate them back to the requested return type.
539 if (EltVT.isInteger())
540 return DAG.getNode(ISD::TRUNCATE, SDLoc(N), EltVT, InOp);
541 return InOp;
542}
543
544SDValue DAGTypeLegalizer::ScalarizeVecRes_EXTRACT_SUBVECTOR(SDNode *N) {
545 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
546 N->getValueType(0).getVectorElementType(),
547 N->getOperand(0), N->getOperand(1));
548}
549
550SDValue DAGTypeLegalizer::ScalarizeVecRes_FP_ROUND(SDNode *N) {
551 SDLoc DL(N);
552 SDValue Op = N->getOperand(0);
553 EVT OpVT = Op.getValueType();
554 // The result needs scalarizing, but it's not a given that the source does.
555 // See similar logic in ScalarizeVecRes_UnaryOp.
556 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
557 Op = GetScalarizedVector(Op);
558 } else {
559 EVT VT = OpVT.getVectorElementType();
560 Op = DAG.getExtractVectorElt(DL, VT, Op, 0);
561 }
562 return DAG.getNode(ISD::FP_ROUND, DL,
563 N->getValueType(0).getVectorElementType(), Op,
564 N->getOperand(1));
565}
566
567SDValue DAGTypeLegalizer::ScalarizeVecRes_CONVERT_FROM_ARBITRARY_FP(SDNode *N) {
568 SDLoc DL(N);
569 SDValue Op = N->getOperand(0);
570 EVT OpVT = Op.getValueType();
571 // The result needs scalarizing, but it's not a given that the source does.
572 // See similar logic in ScalarizeVecRes_UnaryOp.
573 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
574 Op = GetScalarizedVector(Op);
575 } else {
576 EVT VT = OpVT.getVectorElementType();
577 Op = DAG.getExtractVectorElt(DL, VT, Op, 0);
578 }
579 return DAG.getNode(ISD::CONVERT_FROM_ARBITRARY_FP, DL,
580 N->getValueType(0).getVectorElementType(), Op,
581 N->getOperand(1));
582}
583
584SDValue DAGTypeLegalizer::ScalarizeVecRes_CONVERT_TO_ARBITRARY_FP(SDNode *N) {
585 SDLoc DL(N);
586 SDValue Op = N->getOperand(0);
587 EVT OpVT = Op.getValueType();
588 // The result needs scalarizing, but it's not a given that the source does.
589 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
590 Op = GetScalarizedVector(Op);
591 } else {
592 EVT VT = OpVT.getVectorElementType();
593 Op = DAG.getExtractVectorElt(DL, VT, Op, 0);
594 }
595 return DAG.getNode(ISD::CONVERT_TO_ARBITRARY_FP, DL,
596 N->getValueType(0).getVectorElementType(), Op,
597 N->getOperand(1), N->getOperand(2), N->getOperand(3));
598}
599
600SDValue DAGTypeLegalizer::ScalarizeVecRes_UnaryOpWithExtraInput(SDNode *N) {
601 SDValue Op = GetScalarizedVector(N->getOperand(0));
602 return DAG.getNode(N->getOpcode(), SDLoc(N), Op.getValueType(), Op,
603 N->getOperand(1));
604}
605
606SDValue DAGTypeLegalizer::ScalarizeVecRes_FPOp_MultiType(SDNode *N) {
607 SDLoc DL(N);
608 SDValue LHS = GetScalarizedVector(N->getOperand(0));
609 SDValue RHS = N->getOperand(1);
610 EVT RHSVT = RHS.getValueType();
611 // The exponent has its own type action and may not have been scalarized:
612 // v1i1 is legal on AVX-512, v1i32 is widened on AArch64.
613 if (RHSVT.isVector()) {
614 if (getTypeAction(RHSVT) == TargetLowering::TypeScalarizeVector)
615 RHS = GetScalarizedVector(RHS);
616 else
617 RHS = DAG.getExtractVectorElt(DL, RHSVT.getVectorElementType(), RHS, 0);
618 }
619 return DAG.getNode(N->getOpcode(), DL, LHS.getValueType(), LHS, RHS,
620 N->getFlags());
621}
622
623SDValue DAGTypeLegalizer::ScalarizeVecRes_INSERT_VECTOR_ELT(SDNode *N) {
624 // The value to insert may have a wider type than the vector element type,
625 // so be sure to truncate it to the element type if necessary.
626 SDValue Op = N->getOperand(1);
627 EVT EltVT = N->getValueType(0).getVectorElementType();
628 if (Op.getValueType() != EltVT)
629 // FIXME: Can this happen for floating point types?
630 Op = DAG.getNode(ISD::TRUNCATE, SDLoc(N), EltVT, Op);
631 return Op;
632}
633
634SDValue DAGTypeLegalizer::ScalarizeVecRes_ATOMIC_LOAD(AtomicSDNode *N) {
635 SDValue Result = DAG.getAtomicLoad(
636 N->getExtensionType(), SDLoc(N), N->getMemoryVT().getVectorElementType(),
637 N->getValueType(0).getVectorElementType(), N->getChain(), N->getBasePtr(),
638 N->getMemOperand());
639
640 // Legalize the chain result - switch anything that used the old chain to
641 // use the new one.
642 ReplaceValueWith(SDValue(N, 1), Result.getValue(1));
643 return Result;
644}
645
646SDValue DAGTypeLegalizer::ScalarizeVecRes_ATOMIC_RMW(AtomicSDNode *N) {
647 SDValue Result = DAG.getAtomic(
648 N->getOpcode(), SDLoc(N), N->getMemoryVT().getVectorElementType(),
649 N->getChain(), N->getBasePtr(), GetScalarizedVector(N->getVal()),
650 N->getMemOperand());
651
652 ReplaceValueWith(SDValue(N, 1), Result.getValue(1));
653 return Result;
654}
655
656SDValue DAGTypeLegalizer::ScalarizeVecRes_LOAD(LoadSDNode *N) {
657 assert(N->isUnindexed() && "Indexed vector load?");
658
659 SDValue Result = DAG.getLoad(
660 ISD::UNINDEXED, N->getExtensionType(),
661 N->getValueType(0).getVectorElementType(), SDLoc(N), N->getChain(),
662 N->getBasePtr(), DAG.getPOISON(N->getBasePtr().getValueType()),
663 N->getPointerInfo(), N->getMemoryVT().getVectorElementType(),
664 N->getBaseAlign(), N->getMemOperand()->getFlags(),
665 N->getMMOMetadataForSubAccess());
666
667 // Legalize the chain result - switch anything that used the old chain to
668 // use the new one.
669 ReplaceValueWith(SDValue(N, 1), Result.getValue(1));
670 return Result;
671}
672
673SDValue DAGTypeLegalizer::ScalarizeVecRes_UnaryOp(SDNode *N) {
674 // Get the dest type - it doesn't always match the input type, e.g. int_to_fp.
675 EVT DestVT = N->getValueType(0).getVectorElementType();
676 SDValue Op = N->getOperand(0);
677 EVT OpVT = Op.getValueType();
678 SDLoc DL(N);
679 // The result needs scalarizing, but it's not a given that the source does.
680 // This is a workaround for targets where it's impossible to scalarize the
681 // result of a conversion, because the source type is legal.
682 // For instance, this happens on AArch64: v1i1 is illegal but v1i{8,16,32}
683 // are widened to v8i8, v4i16, and v2i32, which is legal, because v1i64 is
684 // legal and was not scalarized.
685 // See the similar logic in ScalarizeVecRes_SETCC
686 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
687 Op = GetScalarizedVector(Op);
688 } else {
689 EVT VT = OpVT.getVectorElementType();
690 Op = DAG.getExtractVectorElt(DL, VT, Op, 0);
691 }
692 return DAG.getNode(N->getOpcode(), SDLoc(N), DestVT, Op, N->getFlags());
693}
694
695SDValue DAGTypeLegalizer::ScalarizeVecRes_InregOp(SDNode *N) {
696 EVT EltVT = N->getValueType(0).getVectorElementType();
697 EVT ExtVT = cast<VTSDNode>(N->getOperand(1))->getVT().getVectorElementType();
698 SDValue LHS = GetScalarizedVector(N->getOperand(0));
699 return DAG.getNode(N->getOpcode(), SDLoc(N), EltVT,
700 LHS, DAG.getValueType(ExtVT));
701}
702
703SDValue DAGTypeLegalizer::ScalarizeVecRes_VecInregOp(SDNode *N) {
704 SDLoc DL(N);
705 SDValue Op = N->getOperand(0);
706
707 EVT OpVT = Op.getValueType();
708 EVT OpEltVT = OpVT.getVectorElementType();
709 EVT EltVT = N->getValueType(0).getVectorElementType();
710
711 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
712 Op = GetScalarizedVector(Op);
713 } else {
714 Op = DAG.getExtractVectorElt(DL, OpEltVT, Op, 0);
715 }
716
717 switch (N->getOpcode()) {
719 return DAG.getNode(ISD::ANY_EXTEND, DL, EltVT, Op);
721 return DAG.getNode(ISD::SIGN_EXTEND, DL, EltVT, Op);
723 return DAG.getNode(ISD::ZERO_EXTEND, DL, EltVT, Op);
724 }
725
726 llvm_unreachable("Illegal extend_vector_inreg opcode");
727}
728
729SDValue DAGTypeLegalizer::ScalarizeVecRes_ADDRSPACECAST(SDNode *N) {
730 EVT DestVT = N->getValueType(0).getVectorElementType();
731 SDValue Op = N->getOperand(0);
732 EVT OpVT = Op.getValueType();
733 SDLoc DL(N);
734 // The result needs scalarizing, but it's not a given that the source does.
735 // This is a workaround for targets where it's impossible to scalarize the
736 // result of a conversion, because the source type is legal.
737 // For instance, this happens on AArch64: v1i1 is illegal but v1i{8,16,32}
738 // are widened to v8i8, v4i16, and v2i32, which is legal, because v1i64 is
739 // legal and was not scalarized.
740 // See the similar logic in ScalarizeVecRes_SETCC
741 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
742 Op = GetScalarizedVector(Op);
743 } else {
744 EVT VT = OpVT.getVectorElementType();
745 Op = DAG.getExtractVectorElt(DL, VT, Op, 0);
746 }
747 auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
748 unsigned SrcAS = AddrSpaceCastN->getSrcAddressSpace();
749 unsigned DestAS = AddrSpaceCastN->getDestAddressSpace();
750 return DAG.getAddrSpaceCast(DL, DestVT, Op, SrcAS, DestAS,
751 AddrSpaceCastN->getFlags());
752}
753
754SDValue DAGTypeLegalizer::ScalarizeVecRes_SCALAR_TO_VECTOR(SDNode *N) {
755 // If the operand is wider than the vector element type then it is implicitly
756 // truncated. Make that explicit here.
757 EVT EltVT = N->getValueType(0).getVectorElementType();
758 SDValue InOp = N->getOperand(0);
759 if (InOp.getValueType() != EltVT)
760 return DAG.getNode(ISD::TRUNCATE, SDLoc(N), EltVT, InOp);
761 return InOp;
762}
763
765DAGTypeLegalizer::ScalarizeVecRes_VECTOR_INTERLEAVE_DEINTERLEAVE(SDNode *N) {
766 assert(N->getNumValues() == N->getNumOperands() &&
767 "Expected one result per operand");
768
769 // Interleaving or deinterleaving one-element vectors leaves each result
770 // equal to the corresponding operand.
771 for (unsigned I = 0; I != N->getNumValues(); ++I)
772 SetScalarizedVector(SDValue(N, I), GetScalarizedVector(N->getOperand(I)));
773 return SDValue();
774}
775
776SDValue DAGTypeLegalizer::ScalarizeVecRes_VSELECT(SDNode *N) {
777 SDValue Cond = N->getOperand(0);
778 EVT OpVT = Cond.getValueType();
779 SDLoc DL(N);
780 // The vselect result and true/value operands needs scalarizing, but it's
781 // not a given that the Cond does. For instance, in AVX512 v1i1 is legal.
782 // See the similar logic in ScalarizeVecRes_SETCC
783 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
784 Cond = GetScalarizedVector(Cond);
785 } else {
786 EVT VT = OpVT.getVectorElementType();
787 Cond = DAG.getExtractVectorElt(DL, VT, Cond, 0);
788 }
789
790 SDValue LHS = GetScalarizedVector(N->getOperand(1));
792 TLI.getBooleanContents(false, false);
793 TargetLowering::BooleanContent VecBool = TLI.getBooleanContents(true, false);
794
795 // If integer and float booleans have different contents then we can't
796 // reliably optimize in all cases. There is a full explanation for this in
797 // DAGCombiner::visitSELECT() where the same issue affects folding
798 // (select C, 0, 1) to (xor C, 1).
799 if (TLI.getBooleanContents(false, false) !=
800 TLI.getBooleanContents(false, true)) {
801 // At least try the common case where the boolean is generated by a
802 // comparison.
803 if (Cond->getOpcode() == ISD::SETCC) {
804 EVT OpVT = Cond->getOperand(0).getValueType();
805 ScalarBool = TLI.getBooleanContents(OpVT.getScalarType());
806 VecBool = TLI.getBooleanContents(OpVT);
807 } else
809 }
810
811 EVT CondVT = Cond.getValueType();
812 if (ScalarBool != VecBool) {
813 switch (ScalarBool) {
815 break;
819 // Vector read from all ones, scalar expects a single 1 so mask.
820 Cond = DAG.getNode(ISD::AND, SDLoc(N), CondVT,
821 Cond, DAG.getConstant(1, SDLoc(N), CondVT));
822 break;
826 // Vector reads from a one, scalar from all ones so sign extend.
827 Cond = DAG.getNode(ISD::SIGN_EXTEND_INREG, SDLoc(N), CondVT,
828 Cond, DAG.getValueType(MVT::i1));
829 break;
830 }
831 }
832
833 // Truncate the condition if needed
834 auto BoolVT = getSetCCResultType(CondVT);
835 if (BoolVT.bitsLT(CondVT))
836 Cond = DAG.getNode(ISD::TRUNCATE, SDLoc(N), BoolVT, Cond);
837
838 return DAG.getSelect(SDLoc(N), LHS.getValueType(), Cond, LHS,
839 GetScalarizedVector(N->getOperand(2)), N->getFlags());
840}
841
842SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT(SDNode *N) {
843 SDValue LHS = GetScalarizedVector(N->getOperand(1));
844 return DAG.getSelect(SDLoc(N),
845 LHS.getValueType(), N->getOperand(0), LHS,
846 GetScalarizedVector(N->getOperand(2)));
847}
848
849SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT_CC(SDNode *N) {
850 SDValue LHS = GetScalarizedVector(N->getOperand(2));
851 return DAG.getNode(ISD::SELECT_CC, SDLoc(N), LHS.getValueType(),
852 N->getOperand(0), N->getOperand(1),
853 LHS, GetScalarizedVector(N->getOperand(3)),
854 N->getOperand(4));
855}
856
857SDValue DAGTypeLegalizer::ScalarizeVecRes_UNDEF(SDNode *N) {
858 return DAG.getUNDEF(N->getValueType(0).getVectorElementType());
859}
860
861SDValue DAGTypeLegalizer::ScalarizeVecRes_VECTOR_SHUFFLE(SDNode *N) {
862 // Figure out if the scalar is the LHS or RHS and return it.
863 SDValue Arg = N->getOperand(2).getOperand(0);
864 if (Arg.isUndef())
865 return DAG.getUNDEF(N->getValueType(0).getVectorElementType());
866 unsigned Op = !cast<ConstantSDNode>(Arg)->isZero();
867 return GetScalarizedVector(N->getOperand(Op));
868}
869
870SDValue DAGTypeLegalizer::ScalarizeVecRes_FP_TO_XINT_SAT(SDNode *N) {
871 SDValue Src = N->getOperand(0);
872 EVT SrcVT = Src.getValueType();
873 SDLoc dl(N);
874
875 // Handle case where result is scalarized but operand is not
876 if (getTypeAction(SrcVT) == TargetLowering::TypeScalarizeVector)
877 Src = GetScalarizedVector(Src);
878 else
879 Src = DAG.getNode(
881 DAG.getConstant(0, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
882
883 EVT DstVT = N->getValueType(0).getVectorElementType();
884 return DAG.getNode(N->getOpcode(), dl, DstVT, Src, N->getOperand(1));
885}
886
887SDValue DAGTypeLegalizer::ScalarizeVecRes_SETCC(SDNode *N) {
888 assert(N->getValueType(0).isVector() &&
889 N->getOperand(0).getValueType().isVector() &&
890 "Operand types must be vectors");
891 SDValue LHS = N->getOperand(0);
892 SDValue RHS = N->getOperand(1);
893 EVT OpVT = LHS.getValueType();
894 EVT NVT = N->getValueType(0).getVectorElementType();
895 SDLoc DL(N);
896
897 // The result needs scalarizing, but it's not a given that the source does.
898 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
899 LHS = GetScalarizedVector(LHS);
900 RHS = GetScalarizedVector(RHS);
901 } else {
902 EVT VT = OpVT.getVectorElementType();
903 LHS = DAG.getExtractVectorElt(DL, VT, LHS, 0);
904 RHS = DAG.getExtractVectorElt(DL, VT, RHS, 0);
905 }
906
907 // Turn it into a scalar SETCC.
908 SDValue Res = DAG.getNode(ISD::SETCC, DL, MVT::i1, LHS, RHS,
909 N->getOperand(2));
910 // Vectors may have a different boolean contents to scalars. Promote the
911 // value appropriately.
912 ISD::NodeType ExtendCode =
913 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
914 return DAG.getNode(ExtendCode, DL, NVT, Res);
915}
916
917SDValue DAGTypeLegalizer::ScalarizeVecRes_IS_FPCLASS(SDNode *N) {
918 SDLoc DL(N);
919 SDValue Arg = N->getOperand(0);
920 SDValue Test = N->getOperand(1);
921 EVT ArgVT = Arg.getValueType();
922 EVT ResultVT = N->getValueType(0).getVectorElementType();
923
924 if (getTypeAction(ArgVT) == TargetLowering::TypeScalarizeVector) {
925 Arg = GetScalarizedVector(Arg);
926 } else {
927 EVT VT = ArgVT.getVectorElementType();
928 Arg = DAG.getExtractVectorElt(DL, VT, Arg, 0);
929 }
930
931 SDValue Res =
932 DAG.getNode(ISD::IS_FPCLASS, DL, MVT::i1, {Arg, Test}, N->getFlags());
933 // Vectors may have a different boolean contents to scalars. Promote the
934 // value appropriately.
935 ISD::NodeType ExtendCode =
936 TargetLowering::getExtendForContent(TLI.getBooleanContents(ArgVT));
937 return DAG.getNode(ExtendCode, DL, ResultVT, Res);
938}
939
940//===----------------------------------------------------------------------===//
941// Operand Vector Scalarization <1 x ty> -> ty.
942//===----------------------------------------------------------------------===//
943
944bool DAGTypeLegalizer::ScalarizeVectorOperand(SDNode *N, unsigned OpNo) {
945 LLVM_DEBUG(dbgs() << "Scalarize node operand " << OpNo << ": ";
946 N->dump(&DAG));
947 SDValue Res = SDValue();
948
949 // See if the target wants to custom scalarize this node.
950 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
951 return false;
952
953 switch (N->getOpcode()) {
954 default:
955#ifndef NDEBUG
956 dbgs() << "ScalarizeVectorOperand Op #" << OpNo << ": ";
957 N->dump(&DAG);
958 dbgs() << "\n";
959#endif
960 report_fatal_error("Do not know how to scalarize this operator's "
961 "operand!\n");
962 case ISD::BITCAST:
963 Res = ScalarizeVecOp_BITCAST(N);
964 break;
965 case ISD::FAKE_USE:
966 Res = ScalarizeVecOp_FAKE_USE(N);
967 break;
968 case ISD::ANY_EXTEND:
969 case ISD::ZERO_EXTEND:
970 case ISD::SIGN_EXTEND:
971 case ISD::TRUNCATE:
972 case ISD::FP_TO_SINT:
973 case ISD::FP_TO_UINT:
974 case ISD::SINT_TO_FP:
975 case ISD::UINT_TO_FP:
976 case ISD::LROUND:
977 case ISD::LLROUND:
978 case ISD::LRINT:
979 case ISD::LLRINT:
980 Res = ScalarizeVecOp_UnaryOp(N);
981 break;
985 Res = ScalarizeVecOp_UnaryOpWithExtraInput(N);
986 break;
988 assert(N->getValueType(0).getVectorNumElements() == 1 &&
989 "Unexpected vector type!");
990 SDValue Elt = GetScalarizedVector(N->getOperand(0));
991 SDValue Op = DAG.getNode(
992 N->getOpcode(), SDLoc(N), N->getValueType(0).getScalarType(), Elt,
993 N->getOperand(1), N->getOperand(2), N->getOperand(3));
994 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Op);
995 break;
996 }
1001 Res = ScalarizeVecOp_UnaryOp_StrictFP(N);
1002 break;
1004 Res = ScalarizeVecOp_CONCAT_VECTORS(N);
1005 break;
1007 Res = ScalarizeVecOp_INSERT_SUBVECTOR(N, OpNo);
1008 break;
1010 Res = ScalarizeVecOp_EXTRACT_VECTOR_ELT(N);
1011 break;
1012 case ISD::VSELECT:
1013 Res = ScalarizeVecOp_VSELECT(N);
1014 break;
1015 case ISD::SETCC:
1016 Res = ScalarizeVecOp_VSETCC(N);
1017 break;
1018 case ISD::STRICT_FSETCC:
1020 Res = ScalarizeVecOp_VSTRICT_FSETCC(N, OpNo);
1021 break;
1022 case ISD::STORE:
1023 Res = ScalarizeVecOp_STORE(cast<StoreSDNode>(N), OpNo);
1024 break;
1025 case ISD::ATOMIC_STORE:
1026 Res = ScalarizeVecOp_ATOMIC_STORE(cast<AtomicSDNode>(N));
1027 break;
1028 case ISD::MLOAD:
1029 Res = ScalarizeVecOp_MLOAD(cast<MaskedLoadSDNode>(N), OpNo);
1030 break;
1031 case ISD::MSTORE:
1032 Res = ScalarizeVecOp_MSTORE(cast<MaskedStoreSDNode>(N), OpNo);
1033 break;
1035 Res = ScalarizeVecOp_STRICT_FP_ROUND(N, OpNo);
1036 break;
1037 case ISD::FP_ROUND:
1038 Res = ScalarizeVecOp_FP_ROUND(N, OpNo);
1039 break;
1041 Res = ScalarizeVecOp_STRICT_FP_EXTEND(N);
1042 break;
1043 case ISD::FP_EXTEND:
1044 Res = ScalarizeVecOp_FP_EXTEND(N);
1045 break;
1048 case ISD::VECREDUCE_ADD:
1049 case ISD::VECREDUCE_MUL:
1050 case ISD::VECREDUCE_AND:
1051 case ISD::VECREDUCE_OR:
1052 case ISD::VECREDUCE_XOR:
1063 Res = ScalarizeVecOp_VECREDUCE(N);
1064 break;
1067 Res = ScalarizeVecOp_VECREDUCE_SEQ(N);
1068 break;
1069 case ISD::SCMP:
1070 case ISD::UCMP:
1071 Res = ScalarizeVecOp_CMP(N);
1072 break;
1074 Res = ScalarizeVecOp_VECTOR_FIND_LAST_ACTIVE(N);
1075 break;
1076 case ISD::CTTZ_ELTS:
1078 Res = ScalarizeVecOp_CTTZ_ELTS(N);
1079 break;
1080 case ISD::VECTOR_MATCH:
1081 Res = ScalarizeVecOp_VECTOR_MATCH(N, OpNo);
1082 break;
1083 case ISD::MASKED_UDIV:
1084 case ISD::MASKED_SDIV:
1085 case ISD::MASKED_UREM:
1086 case ISD::MASKED_SREM:
1087 Res = ScalarizeVecOp_MaskedBinOp(N, OpNo);
1088 break;
1089 }
1090
1091 // If the result is null, the sub-method took care of registering results etc.
1092 if (!Res.getNode()) return false;
1093
1094 // If the result is N, the sub-method updated N in place. Tell the legalizer
1095 // core about this.
1096 if (Res.getNode() == N)
1097 return true;
1098
1099 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
1100 "Invalid operand expansion");
1101
1102 ReplaceValueWith(SDValue(N, 0), Res);
1103 return false;
1104}
1105
1106/// If the value to convert is a vector that needs to be scalarized, it must be
1107/// <1 x ty>. Convert the element instead.
1108SDValue DAGTypeLegalizer::ScalarizeVecOp_BITCAST(SDNode *N) {
1109 SDValue Elt = GetScalarizedVector(N->getOperand(0));
1110 return DAG.getNode(ISD::BITCAST, SDLoc(N),
1111 N->getValueType(0), Elt);
1112}
1113
1114// Need to legalize vector operands of fake uses. Must be <1 x ty>.
1115SDValue DAGTypeLegalizer::ScalarizeVecOp_FAKE_USE(SDNode *N) {
1116 assert(N->getOperand(1).getValueType().getVectorNumElements() == 1 &&
1117 "Fake Use: Unexpected vector type!");
1118 SDValue Elt = GetScalarizedVector(N->getOperand(1));
1119 return DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, N->getOperand(0), Elt);
1120}
1121
1122/// If the input is a vector that needs to be scalarized, it must be <1 x ty>.
1123/// Do the operation on the element instead.
1124SDValue DAGTypeLegalizer::ScalarizeVecOp_UnaryOp(SDNode *N) {
1125 assert(N->getValueType(0).getVectorNumElements() == 1 &&
1126 "Unexpected vector type!");
1127 SDValue Elt = GetScalarizedVector(N->getOperand(0));
1128 SDValue Op = DAG.getNode(N->getOpcode(), SDLoc(N),
1129 N->getValueType(0).getScalarType(), Elt);
1130 // Revectorize the result so the types line up with what the uses of this
1131 // expression expect.
1132 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Op);
1133}
1134
1135/// Same as ScalarizeVecOp_UnaryOp with an extra operand (for example a
1136/// typesize).
1137SDValue DAGTypeLegalizer::ScalarizeVecOp_UnaryOpWithExtraInput(SDNode *N) {
1138 assert(N->getValueType(0).getVectorNumElements() == 1 &&
1139 "Unexpected vector type!");
1140 SDValue Elt = GetScalarizedVector(N->getOperand(0));
1141 SDValue Op =
1142 DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0).getScalarType(),
1143 Elt, N->getOperand(1));
1144 // Revectorize the result so the types line up with what the uses of this
1145 // expression expect.
1146 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Op);
1147}
1148
1149/// If the input is a vector that needs to be scalarized, it must be <1 x ty>.
1150/// Do the strict FP operation on the element instead.
1151SDValue DAGTypeLegalizer::ScalarizeVecOp_UnaryOp_StrictFP(SDNode *N) {
1152 assert(N->getValueType(0).getVectorNumElements() == 1 &&
1153 "Unexpected vector type!");
1154 SDValue Elt = GetScalarizedVector(N->getOperand(1));
1155 SDValue Res = DAG.getNode(N->getOpcode(), SDLoc(N),
1156 { N->getValueType(0).getScalarType(), MVT::Other },
1157 { N->getOperand(0), Elt });
1158 // Legalize the chain result - switch anything that used the old chain to
1159 // use the new one.
1160 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
1161 // Revectorize the result so the types line up with what the uses of this
1162 // expression expect.
1163 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
1164
1165 // Do our own replacement and return SDValue() to tell the caller that we
1166 // handled all replacements since caller can only handle a single result.
1167 ReplaceValueWith(SDValue(N, 0), Res);
1168 return SDValue();
1169}
1170
1171/// The vectors to concatenate have length one - use a BUILD_VECTOR instead.
1172SDValue DAGTypeLegalizer::ScalarizeVecOp_CONCAT_VECTORS(SDNode *N) {
1173 SmallVector<SDValue, 8> Ops(N->getNumOperands());
1174 for (unsigned i = 0, e = N->getNumOperands(); i < e; ++i)
1175 Ops[i] = GetScalarizedVector(N->getOperand(i));
1176 return DAG.getBuildVector(N->getValueType(0), SDLoc(N), Ops);
1177}
1178
1179/// The inserted subvector is to be scalarized - use insert vector element
1180/// instead.
1181SDValue DAGTypeLegalizer::ScalarizeVecOp_INSERT_SUBVECTOR(SDNode *N,
1182 unsigned OpNo) {
1183 // We should not be attempting to scalarize the containing vector
1184 assert(OpNo == 1);
1185 SDValue Elt = GetScalarizedVector(N->getOperand(1));
1186 SDValue ContainingVec = N->getOperand(0);
1187 return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(N),
1188 ContainingVec.getValueType(), ContainingVec, Elt,
1189 N->getOperand(2));
1190}
1191
1192/// If the input is a vector that needs to be scalarized, it must be <1 x ty>,
1193/// so just return the element, ignoring the index.
1194SDValue DAGTypeLegalizer::ScalarizeVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
1195 EVT VT = N->getValueType(0);
1196 SDValue Res = GetScalarizedVector(N->getOperand(0));
1197 if (Res.getValueType() != VT)
1198 Res = VT.isFloatingPoint()
1199 ? DAG.getNode(ISD::FP_EXTEND, SDLoc(N), VT, Res)
1200 : DAG.getNode(ISD::ANY_EXTEND, SDLoc(N), VT, Res);
1201 return Res;
1202}
1203
1204/// If the input condition is a vector that needs to be scalarized, it must be
1205/// <1 x i1>, so just convert to a normal ISD::SELECT
1206/// (still with vector output type since that was acceptable if we got here).
1207SDValue DAGTypeLegalizer::ScalarizeVecOp_VSELECT(SDNode *N) {
1208 SDValue ScalarCond = GetScalarizedVector(N->getOperand(0));
1209 EVT VT = N->getValueType(0);
1210
1211 return DAG.getNode(ISD::SELECT, SDLoc(N), VT, ScalarCond, N->getOperand(1),
1212 N->getOperand(2));
1213}
1214
1215/// If the operand is a vector that needs to be scalarized then the
1216/// result must be a single-element vector, so just convert to a scalar
1217/// SETCC and wrap with a scalar_to_vector since the res type is legal
1218/// if we got here
1219SDValue DAGTypeLegalizer::ScalarizeVecOp_VSETCC(SDNode *N) {
1220 assert(N->getValueType(0).isVector() &&
1221 N->getOperand(0).getValueType().isVector() &&
1222 "Operand types must be vectors");
1223 assert(N->getValueType(0).getVectorNumElements() == 1 &&
1224 "Expected single-element vector type");
1225
1226 EVT VT = N->getValueType(0);
1227 SDValue LHS = GetScalarizedVector(N->getOperand(0));
1228 SDValue RHS = GetScalarizedVector(N->getOperand(1));
1229
1230 EVT OpVT = N->getOperand(0).getValueType();
1231 EVT NVT = VT.getVectorElementType();
1232 SDLoc DL(N);
1233 // Turn it into a scalar SETCC.
1234 SDValue Res = DAG.getNode(ISD::SETCC, DL, MVT::i1, LHS, RHS,
1235 N->getOperand(2));
1236
1237 // Vectors may have a different boolean contents to scalars. Promote the
1238 // value appropriately.
1239 ISD::NodeType ExtendCode =
1240 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
1241
1242 Res = DAG.getNode(ExtendCode, DL, NVT, Res);
1243
1244 return DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, VT, Res);
1245}
1246
1247// Similiar to ScalarizeVecOp_VSETCC, with added logic to update chains.
1248SDValue DAGTypeLegalizer::ScalarizeVecOp_VSTRICT_FSETCC(SDNode *N,
1249 unsigned OpNo) {
1250 assert(OpNo == 1 && "Wrong operand for scalarization!");
1251 assert(N->getValueType(0).isVector() &&
1252 N->getOperand(1).getValueType().isVector() &&
1253 "Operand types must be vectors");
1254 assert(N->getValueType(0).getVectorNumElements() == 1 &&
1255 "Expected single-element vector type");
1256
1257 EVT VT = N->getValueType(0);
1258 SDValue Ch = N->getOperand(0);
1259 SDValue LHS = GetScalarizedVector(N->getOperand(1));
1260 SDValue RHS = GetScalarizedVector(N->getOperand(2));
1261 SDValue CC = N->getOperand(3);
1262
1263 EVT OpVT = N->getOperand(1).getValueType();
1264 EVT NVT = VT.getVectorElementType();
1265 SDLoc DL(N);
1266 SDValue Res = DAG.getNode(N->getOpcode(), DL, {MVT::i1, MVT::Other},
1267 {Ch, LHS, RHS, CC});
1268
1269 // Legalize the chain result - switch anything that used the old chain to
1270 // use the new one.
1271 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
1272
1273 ISD::NodeType ExtendCode =
1274 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
1275
1276 Res = DAG.getNode(ExtendCode, DL, NVT, Res);
1277 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, VT, Res);
1278
1279 // Do our own replacement and return SDValue() to tell the caller that we
1280 // handled all replacements since caller can only handle a single result.
1281 ReplaceValueWith(SDValue(N, 0), Res);
1282 return SDValue();
1283}
1284
1285/// If the value to store is a vector that needs to be scalarized, it must be
1286/// <1 x ty>. Just store the element.
1287SDValue DAGTypeLegalizer::ScalarizeVecOp_STORE(StoreSDNode *N, unsigned OpNo){
1288 assert(N->isUnindexed() && "Indexed store of one-element vector?");
1289 assert(OpNo == 1 && "Do not know how to scalarize this operand!");
1290 SDLoc dl(N);
1291
1292 if (N->isTruncatingStore())
1293 return DAG.getTruncStore(
1294 N->getChain(), dl, GetScalarizedVector(N->getOperand(1)),
1295 N->getBasePtr(), N->getPointerInfo(),
1296 N->getMemoryVT().getVectorElementType(), N->getBaseAlign(),
1297 N->getMemOperand()->getFlags(), N->getMMOMetadataForSubAccess());
1298
1299 return DAG.getStore(N->getChain(), dl, GetScalarizedVector(N->getOperand(1)),
1300 N->getBasePtr(), N->getPointerInfo(), N->getBaseAlign(),
1301 N->getMemOperand()->getFlags(),
1302 N->getMMOMetadataForSubAccess());
1303}
1304
1305/// If the value to store is a vector that needs to be scalarized, it must be
1306/// <1 x ty>. Just store the element.
1307SDValue DAGTypeLegalizer::ScalarizeVecOp_ATOMIC_STORE(AtomicSDNode *N) {
1308 SDValue ScalarVal = GetScalarizedVector(N->getVal());
1309 return DAG.getAtomic(ISD::ATOMIC_STORE, SDLoc(N),
1310 N->getMemoryVT().getVectorElementType(), N->getChain(),
1311 ScalarVal, N->getBasePtr(), N->getMemOperand());
1312}
1313
1314/// If the mask is a vector that needs to be scalarized, it must be <1 x i1>.
1315/// Promote it to a target boolean instead.
1316SDValue DAGTypeLegalizer::ScalarizeVecOp_MLOAD(MaskedLoadSDNode *N,
1317 unsigned OpNo) {
1318 assert(OpNo == 3 && "Can only scalarize the mask operand!");
1319 EVT DataVT = N->getValueType(0);
1320 SDValue Mask = PromoteTargetBoolean(N->getOperand(OpNo), DataVT);
1321 SmallVector<SDValue, 4> NewOps(N->ops());
1322 NewOps[OpNo] = Mask;
1323 SDNode *Res = DAG.UpdateNodeOperands(N, NewOps);
1324 if (Res == N)
1325 return SDValue(Res, 0);
1326
1327 // Update triggered CSE, do our own replacement since caller can't.
1328 ReplaceValueWith(SDValue(N, 0), SDValue(Res, 0));
1329 ReplaceValueWith(SDValue(N, 1), SDValue(Res, 1));
1330 return SDValue();
1331}
1332
1333/// If the mask is a vector that needs to be scalarized, it must be <1 x i1>.
1334/// Promote it to a target boolean instead.
1335SDValue DAGTypeLegalizer::ScalarizeVecOp_MSTORE(MaskedStoreSDNode *N,
1336 unsigned OpNo) {
1337 assert(!N->isCompressingStore() && "CompressingStore not expected");
1338 if (OpNo != 4)
1339 reportFatalInternalError("Scalarization of MSTORE data is not supported");
1340 EVT DataVT = N->getValue().getValueType();
1341 SmallVector<SDValue, 4> NewOps(N->ops());
1342 NewOps[OpNo] = PromoteTargetBoolean(N->getOperand(OpNo), DataVT);
1343 return SDValue(DAG.UpdateNodeOperands(N, NewOps), 0);
1344}
1345
1346/// If the value to round is a vector that needs to be scalarized, it must be
1347/// <1 x ty>. Convert the element instead.
1348SDValue DAGTypeLegalizer::ScalarizeVecOp_FP_ROUND(SDNode *N, unsigned OpNo) {
1349 assert(OpNo == 0 && "Wrong operand for scalarization!");
1350 SDValue Elt = GetScalarizedVector(N->getOperand(0));
1351 SDValue Res = DAG.getNode(ISD::FP_ROUND, SDLoc(N),
1352 N->getValueType(0).getVectorElementType(), Elt,
1353 N->getOperand(1));
1354 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
1355}
1356
1357SDValue DAGTypeLegalizer::ScalarizeVecOp_STRICT_FP_ROUND(SDNode *N,
1358 unsigned OpNo) {
1359 assert(OpNo == 1 && "Wrong operand for scalarization!");
1360 SDValue Elt = GetScalarizedVector(N->getOperand(1));
1361 SDValue Res =
1362 DAG.getNode(ISD::STRICT_FP_ROUND, SDLoc(N),
1363 {N->getValueType(0).getVectorElementType(), MVT::Other},
1364 {N->getOperand(0), Elt, N->getOperand(2)});
1365 // Legalize the chain result - switch anything that used the old chain to
1366 // use the new one.
1367 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
1368
1369 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
1370
1371 // Do our own replacement and return SDValue() to tell the caller that we
1372 // handled all replacements since caller can only handle a single result.
1373 ReplaceValueWith(SDValue(N, 0), Res);
1374 return SDValue();
1375}
1376
1377/// If the value to extend is a vector that needs to be scalarized, it must be
1378/// <1 x ty>. Convert the element instead.
1379SDValue DAGTypeLegalizer::ScalarizeVecOp_FP_EXTEND(SDNode *N) {
1380 SDValue Elt = GetScalarizedVector(N->getOperand(0));
1381 SDValue Res = DAG.getNode(ISD::FP_EXTEND, SDLoc(N),
1382 N->getValueType(0).getVectorElementType(), Elt);
1383 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
1384}
1385
1386/// If the value to extend is a vector that needs to be scalarized, it must be
1387/// <1 x ty>. Convert the element instead.
1388SDValue DAGTypeLegalizer::ScalarizeVecOp_STRICT_FP_EXTEND(SDNode *N) {
1389 SDValue Elt = GetScalarizedVector(N->getOperand(1));
1390 SDValue Res =
1391 DAG.getNode(ISD::STRICT_FP_EXTEND, SDLoc(N),
1392 {N->getValueType(0).getVectorElementType(), MVT::Other},
1393 {N->getOperand(0), Elt});
1394 // Legalize the chain result - switch anything that used the old chain to
1395 // use the new one.
1396 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
1397
1398 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
1399
1400 // Do our own replacement and return SDValue() to tell the caller that we
1401 // handled all replacements since caller can only handle a single result.
1402 ReplaceValueWith(SDValue(N, 0), Res);
1403 return SDValue();
1404}
1405
1406SDValue DAGTypeLegalizer::ScalarizeVecOp_VECREDUCE(SDNode *N) {
1407 SDValue Res = GetScalarizedVector(N->getOperand(0));
1408 // Result type may be wider than element type.
1409 if (Res.getValueType() != N->getValueType(0))
1410 Res = DAG.getNode(ISD::ANY_EXTEND, SDLoc(N), N->getValueType(0), Res);
1411 return Res;
1412}
1413
1414SDValue DAGTypeLegalizer::ScalarizeVecOp_VECREDUCE_SEQ(SDNode *N) {
1415 SDValue AccOp = N->getOperand(0);
1416 SDValue VecOp = N->getOperand(1);
1417
1418 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(N->getOpcode());
1419
1420 SDValue Op = GetScalarizedVector(VecOp);
1421 return DAG.getNode(BaseOpc, SDLoc(N), N->getValueType(0),
1422 AccOp, Op, N->getFlags());
1423}
1424
1425SDValue DAGTypeLegalizer::ScalarizeVecOp_CMP(SDNode *N) {
1426 SDValue LHS = GetScalarizedVector(N->getOperand(0));
1427 SDValue RHS = GetScalarizedVector(N->getOperand(1));
1428
1429 EVT ResVT = N->getValueType(0).getVectorElementType();
1430 SDValue Cmp = DAG.getNode(N->getOpcode(), SDLoc(N), ResVT, LHS, RHS);
1431 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Cmp);
1432}
1433
1434SDValue DAGTypeLegalizer::ScalarizeVecOp_VECTOR_FIND_LAST_ACTIVE(SDNode *N) {
1435 // Since there is no "none-active" result, the only valid return for <1 x ty>
1436 // is 0. Note: Since we check the high mask during splitting this is safe.
1437 // As e.g., a <2 x ty> operation would split to:
1438 // any_active(%hi_mask) ? (1 + last_active(%hi_mask))
1439 // : `last_active(%lo_mask)`
1440 // Which then scalarizes to:
1441 // %mask[1] ? 1 : 0
1442 EVT VT = N->getValueType(0);
1443 return DAG.getConstant(0, SDLoc(N), VT);
1444}
1445
1446SDValue DAGTypeLegalizer::ScalarizeVecOp_CTTZ_ELTS(SDNode *N) {
1447 // The number of trailing zero elements is 1 if the element is 0, and 0
1448 // otherwise.
1449 if (N->getOpcode() == ISD::CTTZ_ELTS_ZERO_POISON)
1450 return DAG.getConstant(0, SDLoc(N), N->getValueType(0));
1451 SDValue Op = GetScalarizedVector(N->getOperand(0));
1452 SDValue SetCC =
1453 DAG.getSetCC(SDLoc(N), MVT::i1, Op,
1454 DAG.getConstant(0, SDLoc(N), Op.getValueType()), ISD::SETEQ);
1455 return DAG.getZExtOrTrunc(SetCC, SDLoc(N), N->getValueType(0));
1456}
1457
1458SDValue DAGTypeLegalizer::ScalarizeVecRes_VECTOR_MATCH(SDNode *N) {
1459 SDLoc DL(N);
1460 // Reuse the expansion (which should scalarize).
1461 SDValue Mask = TLI.expandVectorMatch(N, DAG);
1462 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL,
1463 N->getValueType(0).getScalarType(), Mask,
1464 DAG.getVectorIdxConstant(0, DL));
1465}
1466
1467SDValue DAGTypeLegalizer::ScalarizeVecOp_VECTOR_MATCH(SDNode *N,
1468 unsigned OpNo) {
1469 return TLI.expandVectorMatch(N, DAG);
1470}
1471
1472SDValue DAGTypeLegalizer::ScalarizeVecOp_MaskedBinOp(SDNode *N, unsigned OpNo) {
1473 assert(OpNo == 2 && "Can only scalarize mask operand");
1474 SDLoc DL(N);
1475 EVT VT = N->getOperand(0).getValueType().getVectorElementType();
1476 SDValue LHS = DAG.getExtractVectorElt(DL, VT, N->getOperand(0), 0);
1477 SDValue RHS = DAG.getExtractVectorElt(DL, VT, N->getOperand(1), 0);
1478 SDValue Mask = GetScalarizedVector(N->getOperand(2));
1479 // Vectors may have a different boolean contents to scalars, so truncate to i1
1480 // and let type legalization promote appropriately.
1481 Mask = DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, Mask);
1482 // Masked binary ops don't have UB on disabled lanes but produce poison, so
1483 // use 1 as the divisor to avoid division by zero and overflow.
1484 SDValue BinOp =
1485 DAG.getNode(ISD::getUnmaskedBinOpOpcode(N->getOpcode()), DL, VT, LHS,
1486 DAG.getSelect(DL, VT, Mask, RHS, DAG.getConstant(1, DL, VT)));
1487 return DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, N->getValueType(0), BinOp);
1488}
1489
1490//===----------------------------------------------------------------------===//
1491// Result Vector Splitting
1492//===----------------------------------------------------------------------===//
1493
1494/// This method is called when the specified result of the specified node is
1495/// found to need vector splitting. At this point, the node may also have
1496/// invalid operands or may have other results that need legalization, we just
1497/// know that (at least) one result needs vector splitting.
1498void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
1499 LLVM_DEBUG(dbgs() << "Split node result: "; N->dump(&DAG));
1500 SDValue Lo, Hi;
1501
1502 // See if the target wants to custom expand this node.
1503 if (CustomLowerNode(N, N->getValueType(ResNo), true))
1504 return;
1505
1506 switch (N->getOpcode()) {
1507 default:
1508#ifndef NDEBUG
1509 dbgs() << "SplitVectorResult #" << ResNo << ": ";
1510 N->dump(&DAG);
1511 dbgs() << "\n";
1512#endif
1513 report_fatal_error("Do not know how to split the result of this "
1514 "operator!\n");
1515
1518 SplitVecRes_LOOP_DEPENDENCE_MASK(N, Lo, Hi);
1519 break;
1521 SplitVecRes_MASK_BEFOREFIRST(N, Lo, Hi);
1522 break;
1523 case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, ResNo, Lo, Hi); break;
1524 case ISD::AssertZext: SplitVecRes_AssertZext(N, Lo, Hi); break;
1525 case ISD::AssertSext: SplitVecRes_AssertSext(N, Lo, Hi); break;
1526 case ISD::VSELECT:
1527 case ISD::SELECT:
1528 case ISD::VP_MERGE: SplitRes_Select(N, Lo, Hi); break;
1529 case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break;
1530 case ISD::POISON:
1531 case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break;
1532 case ISD::BITCAST: SplitVecRes_BITCAST(N, Lo, Hi); break;
1533 case ISD::BUILD_VECTOR: SplitVecRes_BUILD_VECTOR(N, Lo, Hi); break;
1534 case ISD::CONCAT_VECTORS: SplitVecRes_CONCAT_VECTORS(N, Lo, Hi); break;
1535 case ISD::EXTRACT_SUBVECTOR: SplitVecRes_EXTRACT_SUBVECTOR(N, Lo, Hi); break;
1536 case ISD::INSERT_SUBVECTOR: SplitVecRes_INSERT_SUBVECTOR(N, Lo, Hi); break;
1537 case ISD::FPOWI:
1538 case ISD::FLDEXP:
1539 case ISD::FCOPYSIGN: SplitVecRes_FPOp_MultiType(N, Lo, Hi); break;
1540 case ISD::IS_FPCLASS: SplitVecRes_IS_FPCLASS(N, Lo, Hi); break;
1541 case ISD::INSERT_VECTOR_ELT: SplitVecRes_INSERT_VECTOR_ELT(N, Lo, Hi); break;
1542 case ISD::SPLAT_VECTOR:
1544 SplitVecRes_ScalarOp(N, Lo, Hi);
1545 break;
1546 case ISD::STEP_VECTOR:
1547 SplitVecRes_STEP_VECTOR(N, Lo, Hi);
1548 break;
1549 case ISD::SIGN_EXTEND_INREG: SplitVecRes_InregOp(N, Lo, Hi); break;
1550 case ISD::ATOMIC_LOAD:
1551 SplitVecRes_ATOMIC_LOAD(cast<AtomicSDNode>(N), Lo, Hi);
1552 break;
1553 case ISD::LOAD:
1554 SplitVecRes_LOAD(cast<LoadSDNode>(N), Lo, Hi);
1555 break;
1556 case ISD::VP_LOAD:
1557 SplitVecRes_VP_LOAD(cast<VPLoadSDNode>(N), Lo, Hi);
1558 break;
1559 case ISD::VP_LOAD_FF:
1560 SplitVecRes_VP_LOAD_FF(cast<VPLoadFFSDNode>(N), Lo, Hi);
1561 break;
1562 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
1563 SplitVecRes_VP_STRIDED_LOAD(cast<VPStridedLoadSDNode>(N), Lo, Hi);
1564 break;
1565 case ISD::MLOAD:
1566 SplitVecRes_MLOAD(cast<MaskedLoadSDNode>(N), Lo, Hi);
1567 break;
1568 case ISD::MGATHER:
1569 case ISD::VP_GATHER:
1570 SplitVecRes_Gather(cast<MemSDNode>(N), Lo, Hi, /*SplitSETCC*/ true);
1571 break;
1573 SplitVecRes_VECTOR_COMPRESS(N, Lo, Hi);
1574 break;
1575 case ISD::SETCC:
1576 SplitVecRes_SETCC(N, Lo, Hi);
1577 break;
1578 case ISD::VECTOR_REPEAT:
1579 SplitVecRes_VECTOR_REPEAT(N, Lo, Hi);
1580 break;
1582 SplitVecRes_VECTOR_REVERSE(N, Lo, Hi);
1583 break;
1585 SplitVecRes_VECTOR_SHUFFLE(cast<ShuffleVectorSDNode>(N), Lo, Hi);
1586 break;
1589 SplitVecRes_VECTOR_SPLICE(N, Lo, Hi);
1590 break;
1592 SplitVecRes_VECTOR_DEINTERLEAVE(N);
1593 return;
1595 SplitVecRes_VECTOR_INTERLEAVE(N);
1596 return;
1597 case ISD::VAARG:
1598 SplitVecRes_VAARG(N, Lo, Hi);
1599 break;
1600
1604 SplitVecRes_ExtVecInRegOp(N, Lo, Hi);
1605 break;
1606
1607 case ISD::ABS:
1609 case ISD::BITREVERSE:
1610 case ISD::BSWAP:
1611 case ISD::CTLZ:
1612 case ISD::CTTZ:
1615 case ISD::CTPOP:
1616 case ISD::FABS:
1617 case ISD::FACOS:
1618 case ISD::FASIN:
1619 case ISD::FATAN:
1620 case ISD::FCEIL:
1621 case ISD::FCOS:
1622 case ISD::FCOSH:
1623 case ISD::FEXP:
1624 case ISD::FEXP2:
1625 case ISD::FEXP10:
1626 case ISD::FFLOOR:
1627 case ISD::FLOG:
1628 case ISD::FLOG10:
1629 case ISD::FLOG2:
1630 case ISD::FNEARBYINT:
1631 case ISD::FNEG:
1632 case ISD::FREEZE:
1633 case ISD::ARITH_FENCE:
1634 case ISD::FP_EXTEND:
1635 case ISD::FP_ROUND:
1636 case ISD::FP_TO_SINT:
1637 case ISD::FP_TO_UINT:
1638 case ISD::FRINT:
1639 case ISD::LRINT:
1640 case ISD::LLRINT:
1641 case ISD::FROUND:
1642 case ISD::FROUNDEVEN:
1643 case ISD::LROUND:
1644 case ISD::LLROUND:
1645 case ISD::FSIN:
1646 case ISD::FSINH:
1647 case ISD::FSQRT:
1648 case ISD::FTAN:
1649 case ISD::FTANH:
1650 case ISD::FTRUNC:
1651 case ISD::SINT_TO_FP:
1652 case ISD::TRUNCATE:
1653 case ISD::UINT_TO_FP:
1654 case ISD::FCANONICALIZE:
1658 SplitVecRes_UnaryOp(N, Lo, Hi);
1659 break;
1660 case ISD::ADDRSPACECAST:
1661 SplitVecRes_ADDRSPACECAST(N, Lo, Hi);
1662 break;
1663 case ISD::FMODF:
1664 case ISD::FFREXP:
1665 case ISD::FSINCOS:
1666 case ISD::FSINCOSPI:
1667 SplitVecRes_UnaryOpWithTwoResults(N, ResNo, Lo, Hi);
1668 break;
1669
1670 case ISD::ANY_EXTEND:
1671 case ISD::SIGN_EXTEND:
1672 case ISD::ZERO_EXTEND:
1673 SplitVecRes_ExtendOp(N, Lo, Hi);
1674 break;
1675
1676 case ISD::ADD:
1677 case ISD::SUB:
1678 case ISD::MUL:
1679 case ISD::CLMUL:
1680 case ISD::CLMULR:
1681 case ISD::CLMULH:
1682 case ISD::PEXT:
1683 case ISD::PDEP:
1684 case ISD::MULHS:
1685 case ISD::MULHU:
1686 case ISD::ABDS:
1687 case ISD::ABDU:
1688 case ISD::AVGCEILS:
1689 case ISD::AVGCEILU:
1690 case ISD::AVGFLOORS:
1691 case ISD::AVGFLOORU:
1692 case ISD::FADD:
1693 case ISD::FSUB:
1694 case ISD::FMUL:
1695 case ISD::FMINNUM:
1696 case ISD::FMINNUM_IEEE:
1697 case ISD::FMAXNUM:
1698 case ISD::FMAXNUM_IEEE:
1699 case ISD::FMINIMUM:
1700 case ISD::FMAXIMUM:
1701 case ISD::FMINIMUMNUM:
1702 case ISD::FMAXIMUMNUM:
1703 case ISD::SDIV: case ISD::VP_SDIV:
1704 case ISD::UDIV: case ISD::VP_UDIV:
1705 case ISD::FDIV:
1706 case ISD::FPOW:
1707 case ISD::FATAN2:
1708 case ISD::AND:
1709 case ISD::OR:
1710 case ISD::XOR:
1711 case ISD::SHL:
1712 case ISD::SRA:
1713 case ISD::SRL:
1714 case ISD::UREM: case ISD::VP_UREM:
1715 case ISD::SREM: case ISD::VP_SREM:
1716 case ISD::FREM:
1717 case ISD::SMIN:
1718 case ISD::SMAX:
1719 case ISD::UMIN:
1720 case ISD::UMAX:
1721 case ISD::SADDSAT:
1722 case ISD::UADDSAT:
1723 case ISD::SSUBSAT:
1724 case ISD::USUBSAT:
1725 case ISD::SSHLSAT:
1726 case ISD::USHLSAT:
1727 case ISD::ROTL:
1728 case ISD::ROTR:
1729 SplitVecRes_BinOp(N, Lo, Hi);
1730 break;
1731 case ISD::MASKED_UDIV:
1732 case ISD::MASKED_SDIV:
1733 case ISD::MASKED_UREM:
1734 case ISD::MASKED_SREM:
1735 SplitVecRes_MaskedBinOp(N, Lo, Hi);
1736 break;
1737 case ISD::FMA:
1738 case ISD::FSHL:
1739 case ISD::FSHR:
1740 SplitVecRes_TernaryOp(N, Lo, Hi);
1741 break;
1742
1743 case ISD::SCMP: case ISD::UCMP:
1744 SplitVecRes_CMP(N, Lo, Hi);
1745 break;
1746
1747#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
1748 case ISD::STRICT_##DAGN:
1749#include "llvm/IR/ConstrainedOps.def"
1750 SplitVecRes_StrictFPOp(N, Lo, Hi);
1751 break;
1752
1755 SplitVecRes_FP_TO_XINT_SAT(N, Lo, Hi);
1756 break;
1757
1758 case ISD::UADDO:
1759 case ISD::SADDO:
1760 case ISD::USUBO:
1761 case ISD::SSUBO:
1762 case ISD::UMULO:
1763 case ISD::SMULO:
1764 SplitVecRes_OverflowOp(N, ResNo, Lo, Hi);
1765 break;
1766 case ISD::SMULFIX:
1767 case ISD::SMULFIXSAT:
1768 case ISD::UMULFIX:
1769 case ISD::UMULFIXSAT:
1770 case ISD::SDIVFIX:
1771 case ISD::SDIVFIXSAT:
1772 case ISD::UDIVFIX:
1773 case ISD::UDIVFIXSAT:
1774 SplitVecRes_FIX(N, Lo, Hi);
1775 break;
1776 case ISD::EXPERIMENTAL_VP_SPLICE:
1777 SplitVecRes_VP_SPLICE(N, Lo, Hi);
1778 break;
1779 case ISD::EXPERIMENTAL_VP_REVERSE:
1780 SplitVecRes_VP_REVERSE(N, Lo, Hi);
1781 break;
1786 SplitVecRes_PARTIAL_REDUCE_MLA(N, Lo, Hi);
1787 break;
1789 SplitVecRes_GET_ACTIVE_LANE_MASK(N, Lo, Hi);
1790 break;
1791 case ISD::VECTOR_MATCH:
1792 SplitVecRes_VECTOR_MATCH(N, Lo, Hi);
1793 break;
1794 }
1795
1796 // If Lo/Hi is null, the sub-method took care of registering results etc.
1797 if (Lo.getNode())
1798 SetSplitVector(SDValue(N, ResNo), Lo, Hi);
1799}
1800
1801void DAGTypeLegalizer::IncrementPointer(MemSDNode *N, EVT MemVT,
1802 MachinePointerInfo &MPI, SDValue &Ptr,
1803 uint64_t *ScaledOffset) {
1804 SDLoc DL(N);
1805 unsigned IncrementSize = MemVT.getSizeInBits().getKnownMinValue() / 8;
1806
1807 if (MemVT.isScalableVector()) {
1808 SDValue BytesIncrement = DAG.getVScale(
1809 DL, Ptr.getValueType(),
1810 APInt(Ptr.getValueSizeInBits().getFixedValue(), IncrementSize));
1811 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
1812 if (ScaledOffset)
1813 *ScaledOffset += IncrementSize;
1814 Ptr = DAG.getNode(ISD::ADD, DL, Ptr.getValueType(), Ptr, BytesIncrement,
1816 } else {
1817 MPI = N->getPointerInfo().getWithOffset(IncrementSize);
1818 // Increment the pointer to the other half.
1819 Ptr = DAG.getObjectPtrOffset(DL, Ptr, TypeSize::getFixed(IncrementSize));
1820 }
1821}
1822
1823std::pair<SDValue, SDValue> DAGTypeLegalizer::SplitMask(SDValue Mask) {
1824 return SplitMask(Mask, SDLoc(Mask));
1825}
1826
1827std::pair<SDValue, SDValue> DAGTypeLegalizer::SplitMask(SDValue Mask,
1828 const SDLoc &DL) {
1829 SDValue MaskLo, MaskHi;
1830 EVT MaskVT = Mask.getValueType();
1831 if (getTypeAction(MaskVT) == TargetLowering::TypeSplitVector)
1832 GetSplitVector(Mask, MaskLo, MaskHi);
1833 else
1834 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
1835 return std::make_pair(MaskLo, MaskHi);
1836}
1837
1838void DAGTypeLegalizer::SplitVecRes_BinOp(SDNode *N, SDValue &Lo, SDValue &Hi) {
1839 SDValue LHSLo, LHSHi;
1840 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1841 SDValue RHSLo, RHSHi;
1842 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
1843 SDLoc dl(N);
1844
1845 const SDNodeFlags Flags = N->getFlags();
1846 unsigned Opcode = N->getOpcode();
1847 if (N->getNumOperands() == 2) {
1848 Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(), LHSLo, RHSLo, Flags);
1849 Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(), LHSHi, RHSHi, Flags);
1850 return;
1851 }
1852
1853 assert(N->getNumOperands() == 4 && "Unexpected number of operands!");
1854 assert((N->getOpcode() == ISD::VP_UDIV || N->getOpcode() == ISD::VP_SDIV ||
1855 N->getOpcode() == ISD::VP_UREM || N->getOpcode() == ISD::VP_SREM) &&
1856 "Expected VP opcode");
1857
1858 SDValue MaskLo, MaskHi;
1859 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(2));
1860
1861 SDValue EVLLo, EVLHi;
1862 std::tie(EVLLo, EVLHi) =
1863 DAG.SplitEVL(N->getOperand(3), N->getValueType(0), dl);
1864
1865 Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(),
1866 {LHSLo, RHSLo, MaskLo, EVLLo}, Flags);
1867 Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(),
1868 {LHSHi, RHSHi, MaskHi, EVLHi}, Flags);
1869}
1870
1871void DAGTypeLegalizer::SplitVecRes_MaskedBinOp(SDNode *N, SDValue &Lo,
1872 SDValue &Hi) {
1873 SDValue LHSLo, LHSHi;
1874 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1875 SDValue RHSLo, RHSHi;
1876 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
1877
1878 SDValue MaskLo, MaskHi, Mask = N->getOperand(2);
1879 if (Mask.getOpcode() == ISD::SETCC)
1880 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
1881 else
1882 std::tie(MaskLo, MaskHi) = SplitMask(Mask);
1883
1884 SDLoc dl(N);
1885
1886 const SDNodeFlags Flags = N->getFlags();
1887 unsigned Opcode = N->getOpcode();
1888 Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(), LHSLo, RHSLo, MaskLo,
1889 Flags);
1890 Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(), LHSHi, RHSHi, MaskHi,
1891 Flags);
1892}
1893
1894void DAGTypeLegalizer::SplitVecRes_TernaryOp(SDNode *N, SDValue &Lo,
1895 SDValue &Hi) {
1896 SDValue Op0Lo, Op0Hi;
1897 GetSplitVector(N->getOperand(0), Op0Lo, Op0Hi);
1898 SDValue Op1Lo, Op1Hi;
1899 GetSplitVector(N->getOperand(1), Op1Lo, Op1Hi);
1900 SDValue Op2Lo, Op2Hi;
1901 GetSplitVector(N->getOperand(2), Op2Lo, Op2Hi);
1902 SDLoc dl(N);
1903
1904 const SDNodeFlags Flags = N->getFlags();
1905 unsigned Opcode = N->getOpcode();
1906 Lo =
1907 DAG.getNode(Opcode, dl, Op0Lo.getValueType(), Op0Lo, Op1Lo, Op2Lo, Flags);
1908 Hi =
1909 DAG.getNode(Opcode, dl, Op0Hi.getValueType(), Op0Hi, Op1Hi, Op2Hi, Flags);
1910}
1911
1912void DAGTypeLegalizer::SplitVecRes_CMP(SDNode *N, SDValue &Lo, SDValue &Hi) {
1913 LLVMContext &Ctxt = *DAG.getContext();
1914 SDLoc dl(N);
1915
1916 SDValue LHS = N->getOperand(0);
1917 SDValue RHS = N->getOperand(1);
1918
1919 SDValue LHSLo, LHSHi, RHSLo, RHSHi;
1920 if (getTypeAction(LHS.getValueType()) == TargetLowering::TypeSplitVector) {
1921 GetSplitVector(LHS, LHSLo, LHSHi);
1922 GetSplitVector(RHS, RHSLo, RHSHi);
1923 } else {
1924 std::tie(LHSLo, LHSHi) = DAG.SplitVector(LHS, dl);
1925 std::tie(RHSLo, RHSHi) = DAG.SplitVector(RHS, dl);
1926 }
1927
1928 EVT SplitResVT = N->getValueType(0).getHalfNumVectorElementsVT(Ctxt);
1929 Lo = DAG.getNode(N->getOpcode(), dl, SplitResVT, LHSLo, RHSLo);
1930 Hi = DAG.getNode(N->getOpcode(), dl, SplitResVT, LHSHi, RHSHi);
1931}
1932
1933void DAGTypeLegalizer::SplitVecRes_FIX(SDNode *N, SDValue &Lo, SDValue &Hi) {
1934 SDValue LHSLo, LHSHi;
1935 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1936 SDValue RHSLo, RHSHi;
1937 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
1938 SDLoc dl(N);
1939 SDValue Op2 = N->getOperand(2);
1940
1941 unsigned Opcode = N->getOpcode();
1942 Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(), LHSLo, RHSLo, Op2,
1943 N->getFlags());
1944 Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(), LHSHi, RHSHi, Op2,
1945 N->getFlags());
1946}
1947
1948void DAGTypeLegalizer::SplitVecRes_BITCAST(SDNode *N, SDValue &Lo,
1949 SDValue &Hi) {
1950 // We know the result is a vector. The input may be either a vector or a
1951 // scalar value.
1952 EVT LoVT, HiVT;
1953 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1954 SDLoc dl(N);
1955
1956 SDValue InOp = N->getOperand(0);
1957 EVT InVT = InOp.getValueType();
1958
1959 // Handle some special cases efficiently.
1960 switch (getTypeAction(InVT)) {
1967 break;
1970 // A scalar to vector conversion, where the scalar needs expansion.
1971 // If the vector is being split in two then we can just convert the
1972 // expanded pieces.
1973 if (LoVT == HiVT) {
1974 GetExpandedOp(InOp, Lo, Hi);
1975 if (DAG.getDataLayout().isBigEndian())
1976 std::swap(Lo, Hi);
1977 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
1978 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
1979 return;
1980 }
1981 break;
1983 // If the input is a vector that needs to be split, convert each split
1984 // piece of the input now.
1985 GetSplitVector(InOp, Lo, Hi);
1986 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
1987 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
1988 return;
1990 report_fatal_error("scalarization of scalable vectors is not supported");
1991 }
1992
1993 if (LoVT.isScalableVector()) {
1994 auto [InLo, InHi] = DAG.SplitVectorOperand(N, 0);
1995 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, InLo);
1996 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, InHi);
1997 return;
1998 }
1999
2000 // In the general case, convert the input to an integer and split it by hand.
2001 EVT LoIntVT = EVT::getIntegerVT(*DAG.getContext(), LoVT.getSizeInBits());
2002 EVT HiIntVT = EVT::getIntegerVT(*DAG.getContext(), HiVT.getSizeInBits());
2003 if (DAG.getDataLayout().isBigEndian())
2004 std::swap(LoIntVT, HiIntVT);
2005
2006 SplitInteger(BitConvertToInteger(InOp), LoIntVT, HiIntVT, Lo, Hi);
2007
2008 if (DAG.getDataLayout().isBigEndian())
2009 std::swap(Lo, Hi);
2010 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
2011 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
2012}
2013
2014void DAGTypeLegalizer::SplitVecRes_LOOP_DEPENDENCE_MASK(SDNode *N, SDValue &Lo,
2015 SDValue &Hi) {
2016 SDLoc DL(N);
2017 EVT LoVT, HiVT;
2018 SDValue PtrA = N->getOperand(0);
2019 SDValue PtrB = N->getOperand(1);
2020 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2021
2022 // The lane offset for the "Lo" half of the mask is unchanged.
2023 Lo = DAG.getNode(N->getOpcode(), DL, LoVT, PtrA, PtrB,
2024 /*ElementSizeInBytes=*/N->getOperand(2),
2025 /*LaneOffset=*/N->getOperand(3));
2026 // The lane offset for the "Hi" half of the mask is incremented by the number
2027 // of elements in the "Lo" half.
2028 unsigned LaneOffset =
2029 N->getConstantOperandVal(3) + LoVT.getVectorMinNumElements();
2030 // Note: The lane offset is implicitly scalable for scalable masks.
2031 Hi = DAG.getNode(N->getOpcode(), DL, HiVT, PtrA, PtrB,
2032 /*ElementSizeInBytes=*/N->getOperand(2),
2033 /*LaneOffset=*/DAG.getConstant(LaneOffset, DL, MVT::i64));
2034}
2035
2036void DAGTypeLegalizer::SplitVecRes_MASK_BEFOREFIRST(SDNode *N, SDValue &Lo,
2037 SDValue &Hi) {
2038 SDLoc DL(N);
2039 SDValue InLo, InHi;
2040 GetSplitVector(N->getOperand(0), InLo, InHi);
2041 EVT VT = InLo.getValueType();
2042 Lo = DAG.getNode(ISD::MASK_BEFOREFIRST, DL, VT, InLo);
2043
2044 // hi = AnyLoActive ? all-zeros : (mask_beforefirst hi)
2045 SDValue AnyLoActive = DAG.getNode(ISD::VECREDUCE_OR, DL, MVT::i1, InLo);
2046 SDValue Cond = DAG.getBoolExtOrTrunc(AnyLoActive, DL,
2047 getSetCCResultType(MVT::i1), MVT::i1);
2048 Hi = DAG.getNode(ISD::SELECT, DL, VT, Cond, DAG.getConstant(0, DL, VT),
2049 DAG.getNode(ISD::MASK_BEFOREFIRST, DL, VT, InHi));
2050}
2051
2052void DAGTypeLegalizer::SplitVecRes_BUILD_VECTOR(SDNode *N, SDValue &Lo,
2053 SDValue &Hi) {
2054 EVT LoVT, HiVT;
2055 SDLoc dl(N);
2056 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2057 unsigned LoNumElts = LoVT.getVectorNumElements();
2058 SmallVector<SDValue, 8> LoOps(N->op_begin(), N->op_begin()+LoNumElts);
2059 Lo = DAG.getBuildVector(LoVT, dl, LoOps);
2060
2061 SmallVector<SDValue, 8> HiOps(N->op_begin()+LoNumElts, N->op_end());
2062 Hi = DAG.getBuildVector(HiVT, dl, HiOps);
2063}
2064
2065void DAGTypeLegalizer::SplitVecRes_CONCAT_VECTORS(SDNode *N, SDValue &Lo,
2066 SDValue &Hi) {
2067 assert(!(N->getNumOperands() & 1) && "Unsupported CONCAT_VECTORS");
2068 SDLoc dl(N);
2069 unsigned NumSubvectors = N->getNumOperands() / 2;
2070 if (NumSubvectors == 1) {
2071 Lo = N->getOperand(0);
2072 Hi = N->getOperand(1);
2073 return;
2074 }
2075
2076 EVT LoVT, HiVT;
2077 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2078
2079 SmallVector<SDValue, 8> LoOps(N->op_begin(), N->op_begin()+NumSubvectors);
2080 Lo = DAG.getNode(ISD::CONCAT_VECTORS, dl, LoVT, LoOps);
2081
2082 SmallVector<SDValue, 8> HiOps(N->op_begin()+NumSubvectors, N->op_end());
2083 Hi = DAG.getNode(ISD::CONCAT_VECTORS, dl, HiVT, HiOps);
2084}
2085
2086void DAGTypeLegalizer::SplitVecRes_EXTRACT_SUBVECTOR(SDNode *N, SDValue &Lo,
2087 SDValue &Hi) {
2088 SDValue Vec = N->getOperand(0);
2089 SDValue Idx = N->getOperand(1);
2090 SDLoc dl(N);
2091
2092 EVT LoVT, HiVT;
2093 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2094
2095 Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, LoVT, Vec, Idx);
2096 uint64_t IdxVal = Idx->getAsZExtVal();
2097 Hi = DAG.getNode(
2098 ISD::EXTRACT_SUBVECTOR, dl, HiVT, Vec,
2099 DAG.getVectorIdxConstant(IdxVal + LoVT.getVectorMinNumElements(), dl));
2100}
2101
2102void DAGTypeLegalizer::SplitVecRes_INSERT_SUBVECTOR(SDNode *N, SDValue &Lo,
2103 SDValue &Hi) {
2104 SDValue Vec = N->getOperand(0);
2105 SDValue SubVec = N->getOperand(1);
2106 SDValue Idx = N->getOperand(2);
2107 SDLoc dl(N);
2108 GetSplitVector(Vec, Lo, Hi);
2109
2110 EVT VecVT = Vec.getValueType();
2111 EVT LoVT = Lo.getValueType();
2112 EVT SubVecVT = SubVec.getValueType();
2113 unsigned VecElems = VecVT.getVectorMinNumElements();
2114 unsigned SubElems = SubVecVT.getVectorMinNumElements();
2115 unsigned LoElems = LoVT.getVectorMinNumElements();
2116
2117 // If we know the index is in the first half, and we know the subvector
2118 // doesn't cross the boundary between the halves, we can avoid spilling the
2119 // vector, and insert into the lower half of the split vector directly.
2120 unsigned IdxVal = Idx->getAsZExtVal();
2121 if (IdxVal + SubElems <= LoElems) {
2122 Lo = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, LoVT, Lo, SubVec, Idx);
2123 return;
2124 }
2125 // Similarly if the subvector is fully in the high half, but mind that we
2126 // can't tell whether a fixed-length subvector is fully within the high half
2127 // of a scalable vector.
2128 if (VecVT.isScalableVector() == SubVecVT.isScalableVector() &&
2129 IdxVal >= LoElems && IdxVal + SubElems <= VecElems) {
2130 Hi = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, Hi.getValueType(), Hi, SubVec,
2131 DAG.getVectorIdxConstant(IdxVal - LoElems, dl));
2132 return;
2133 }
2134
2135 if (getTypeAction(SubVecVT) == TargetLowering::TypeWidenVector &&
2136 Vec.isUndef() && SubVecVT.getVectorElementType() == MVT::i1) {
2137 SDValue WideSubVec = GetWidenedVector(SubVec);
2138 if (WideSubVec.getValueType() == VecVT) {
2139 std::tie(Lo, Hi) = DAG.SplitVector(WideSubVec, SDLoc(WideSubVec));
2140 return;
2141 }
2142 }
2143
2144 // Spill the vector to the stack.
2145 // In cases where the vector is illegal it will be broken down into parts
2146 // and stored in parts - we should use the alignment for the smallest part.
2147 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
2149 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
2150 auto &MF = DAG.getMachineFunction();
2151 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
2152 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
2153
2154 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
2155 SmallestAlign);
2156
2157 // Store the new subvector into the specified index.
2158 SDValue SubVecPtr =
2159 TLI.getVectorSubVecPointer(DAG, StackPtr, VecVT, SubVecVT, Idx);
2160 Store = DAG.getStore(Store, dl, SubVec, SubVecPtr,
2162
2163 // Load the Lo part from the stack slot.
2164 Lo = DAG.getLoad(Lo.getValueType(), dl, Store, StackPtr, PtrInfo,
2165 SmallestAlign);
2166
2167 // Increment the pointer to the other part.
2168 auto *Load = cast<LoadSDNode>(Lo);
2169 MachinePointerInfo MPI = Load->getPointerInfo();
2170 IncrementPointer(Load, LoVT, MPI, StackPtr);
2171
2172 // Load the Hi part from the stack slot.
2173 Hi = DAG.getLoad(Hi.getValueType(), dl, Store, StackPtr, MPI, SmallestAlign);
2174}
2175
2176// Handle splitting an FP where the second operand does not match the first
2177// type. The second operand may be a scalar, or a vector that has exactly as
2178// many elements as the first
2179void DAGTypeLegalizer::SplitVecRes_FPOp_MultiType(SDNode *N, SDValue &Lo,
2180 SDValue &Hi) {
2181 SDValue LHSLo, LHSHi;
2182 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
2183 SDLoc DL(N);
2184
2185 SDValue RHSLo, RHSHi;
2186 SDValue RHS = N->getOperand(1);
2187 EVT RHSVT = RHS.getValueType();
2188 if (RHSVT.isVector()) {
2189 if (getTypeAction(RHSVT) == TargetLowering::TypeSplitVector)
2190 GetSplitVector(RHS, RHSLo, RHSHi);
2191 else
2192 std::tie(RHSLo, RHSHi) = DAG.SplitVector(RHS, SDLoc(RHS));
2193
2194 Lo = DAG.getNode(N->getOpcode(), DL, LHSLo.getValueType(), LHSLo, RHSLo);
2195 Hi = DAG.getNode(N->getOpcode(), DL, LHSHi.getValueType(), LHSHi, RHSHi);
2196 } else {
2197 Lo = DAG.getNode(N->getOpcode(), DL, LHSLo.getValueType(), LHSLo, RHS);
2198 Hi = DAG.getNode(N->getOpcode(), DL, LHSHi.getValueType(), LHSHi, RHS);
2199 }
2200}
2201
2202void DAGTypeLegalizer::SplitVecRes_IS_FPCLASS(SDNode *N, SDValue &Lo,
2203 SDValue &Hi) {
2204 SDLoc DL(N);
2205 SDValue ArgLo, ArgHi;
2206 SDValue Test = N->getOperand(1);
2207 SDValue FpValue = N->getOperand(0);
2208 if (getTypeAction(FpValue.getValueType()) == TargetLowering::TypeSplitVector)
2209 GetSplitVector(FpValue, ArgLo, ArgHi);
2210 else
2211 std::tie(ArgLo, ArgHi) = DAG.SplitVector(FpValue, SDLoc(FpValue));
2212 EVT LoVT, HiVT;
2213 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2214
2215 Lo = DAG.getNode(ISD::IS_FPCLASS, DL, LoVT, ArgLo, Test, N->getFlags());
2216 Hi = DAG.getNode(ISD::IS_FPCLASS, DL, HiVT, ArgHi, Test, N->getFlags());
2217}
2218
2219void DAGTypeLegalizer::SplitVecRes_InregOp(SDNode *N, SDValue &Lo,
2220 SDValue &Hi) {
2221 SDValue LHSLo, LHSHi;
2222 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
2223 SDLoc dl(N);
2224
2225 EVT LoVT, HiVT;
2226 std::tie(LoVT, HiVT) =
2227 DAG.GetSplitDestVTs(cast<VTSDNode>(N->getOperand(1))->getVT());
2228
2229 Lo = DAG.getNode(N->getOpcode(), dl, LHSLo.getValueType(), LHSLo,
2230 DAG.getValueType(LoVT));
2231 Hi = DAG.getNode(N->getOpcode(), dl, LHSHi.getValueType(), LHSHi,
2232 DAG.getValueType(HiVT));
2233}
2234
2235void DAGTypeLegalizer::SplitVecRes_ExtVecInRegOp(SDNode *N, SDValue &Lo,
2236 SDValue &Hi) {
2237 unsigned Opcode = N->getOpcode();
2238 SDValue N0 = N->getOperand(0);
2239
2240 SDLoc dl(N);
2241 SDValue InLo, InHi;
2242
2243 if (getTypeAction(N0.getValueType()) == TargetLowering::TypeSplitVector)
2244 GetSplitVector(N0, InLo, InHi);
2245 else
2246 std::tie(InLo, InHi) = DAG.SplitVectorOperand(N, 0);
2247
2248 EVT InLoVT = InLo.getValueType();
2249 unsigned InNumElements = InLoVT.getVectorNumElements();
2250
2251 EVT OutLoVT, OutHiVT;
2252 std::tie(OutLoVT, OutHiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2253 unsigned OutNumElements = OutLoVT.getVectorNumElements();
2254 assert((2 * OutNumElements) <= InNumElements &&
2255 "Illegal extend vector in reg split");
2256
2257 // *_EXTEND_VECTOR_INREG instructions extend the lowest elements of the
2258 // input vector (i.e. we only use InLo):
2259 // OutLo will extend the first OutNumElements from InLo.
2260 // OutHi will extend the next OutNumElements from InLo.
2261
2262 // Shuffle the elements from InLo for OutHi into the bottom elements to
2263 // create a 'fake' InHi.
2264 SmallVector<int, 8> SplitHi(InNumElements, -1);
2265 for (unsigned i = 0; i != OutNumElements; ++i)
2266 SplitHi[i] = i + OutNumElements;
2267 InHi = DAG.getVectorShuffle(InLoVT, dl, InLo, DAG.getPOISON(InLoVT), SplitHi);
2268
2269 Lo = DAG.getNode(Opcode, dl, OutLoVT, InLo);
2270 Hi = DAG.getNode(Opcode, dl, OutHiVT, InHi);
2271}
2272
2273void DAGTypeLegalizer::SplitVecRes_StrictFPOp(SDNode *N, SDValue &Lo,
2274 SDValue &Hi) {
2275 unsigned NumOps = N->getNumOperands();
2276 SDValue Chain = N->getOperand(0);
2277 EVT LoVT, HiVT;
2278 SDLoc dl(N);
2279 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2280
2283
2284 // The Chain is the first operand.
2285 OpsLo[0] = Chain;
2286 OpsHi[0] = Chain;
2287
2288 // Now process the remaining operands.
2289 for (unsigned i = 1; i < NumOps; ++i) {
2290 SDValue Op = N->getOperand(i);
2291 SDValue OpLo = Op;
2292 SDValue OpHi = Op;
2293
2294 EVT InVT = Op.getValueType();
2295 if (InVT.isVector()) {
2296 // If the input also splits, handle it directly for a
2297 // compile time speedup. Otherwise split it by hand.
2298 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
2299 GetSplitVector(Op, OpLo, OpHi);
2300 else
2301 std::tie(OpLo, OpHi) = DAG.SplitVectorOperand(N, i);
2302 }
2303
2304 OpsLo[i] = OpLo;
2305 OpsHi[i] = OpHi;
2306 }
2307
2308 EVT LoValueVTs[] = {LoVT, MVT::Other};
2309 EVT HiValueVTs[] = {HiVT, MVT::Other};
2310 Lo = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(LoValueVTs), OpsLo,
2311 N->getFlags());
2312 Hi = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(HiValueVTs), OpsHi,
2313 N->getFlags());
2314
2315 // Build a factor node to remember that this Op is independent of the
2316 // other one.
2317 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
2318 Lo.getValue(1), Hi.getValue(1));
2319
2320 // Legalize the chain result - switch anything that used the old chain to
2321 // use the new one.
2322 ReplaceValueWith(SDValue(N, 1), Chain);
2323}
2324
2325SDValue DAGTypeLegalizer::UnrollVectorOp_StrictFP(SDNode *N, unsigned ResNE) {
2326 EVT VT = N->getValueType(0);
2327 if (VT.isScalableVector())
2328 report_fatal_error("Cannot unroll scalable vector strict-fp operation!");
2329
2330 SDValue Chain = N->getOperand(0);
2331 unsigned NE = VT.getVectorNumElements();
2332 EVT EltVT = VT.getVectorElementType();
2333 SDLoc dl(N);
2334
2336 SmallVector<SDValue, 4> Operands(N->getNumOperands());
2337
2338 // If ResNE is 0, fully unroll the vector op.
2339 if (ResNE == 0)
2340 ResNE = NE;
2341 else if (NE > ResNE)
2342 NE = ResNE;
2343
2344 //The results of each unrolled operation, including the chain.
2345 SDVTList ChainVTs = DAG.getVTList(EltVT, MVT::Other);
2347
2348 unsigned i;
2349 for (i = 0; i != NE; ++i) {
2350 Operands[0] = Chain;
2351 for (unsigned j = 1, e = N->getNumOperands(); j != e; ++j) {
2352 SDValue Operand = N->getOperand(j);
2353 EVT OperandVT = Operand.getValueType();
2354 if (OperandVT.isVector()) {
2355 EVT OperandEltVT = OperandVT.getVectorElementType();
2356 Operands[j] = DAG.getExtractVectorElt(dl, OperandEltVT, Operand, i);
2357 } else {
2358 Operands[j] = Operand;
2359 }
2360 }
2361 SDValue Scalar =
2362 DAG.getNode(N->getOpcode(), dl, ChainVTs, Operands, N->getFlags());
2363
2364 //Add in the scalar as well as its chain value to the
2365 //result vectors.
2366 Scalars.push_back(Scalar);
2367 Chains.push_back(Scalar.getValue(1));
2368 }
2369
2370 for (; i < ResNE; ++i)
2371 Scalars.push_back(DAG.getPOISON(EltVT));
2372
2373 // Build a new factor node to connect the chain back together.
2374 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
2375 ReplaceValueWith(SDValue(N, 1), Chain);
2376
2377 // Create a new BUILD_VECTOR node
2378 EVT VecVT = EVT::getVectorVT(*DAG.getContext(), EltVT, ResNE);
2379 return DAG.getBuildVector(VecVT, dl, Scalars);
2380}
2381
2382void DAGTypeLegalizer::SplitVecRes_OverflowOp(SDNode *N, unsigned ResNo,
2383 SDValue &Lo, SDValue &Hi) {
2384 SDLoc dl(N);
2385 EVT ResVT = N->getValueType(0);
2386 EVT OvVT = N->getValueType(1);
2387 EVT LoResVT, HiResVT, LoOvVT, HiOvVT;
2388 std::tie(LoResVT, HiResVT) = DAG.GetSplitDestVTs(ResVT);
2389 std::tie(LoOvVT, HiOvVT) = DAG.GetSplitDestVTs(OvVT);
2390
2391 SDValue LoLHS, HiLHS, LoRHS, HiRHS;
2392 if (getTypeAction(ResVT) == TargetLowering::TypeSplitVector) {
2393 GetSplitVector(N->getOperand(0), LoLHS, HiLHS);
2394 GetSplitVector(N->getOperand(1), LoRHS, HiRHS);
2395 } else {
2396 std::tie(LoLHS, HiLHS) = DAG.SplitVectorOperand(N, 0);
2397 std::tie(LoRHS, HiRHS) = DAG.SplitVectorOperand(N, 1);
2398 }
2399
2400 unsigned Opcode = N->getOpcode();
2401 SDVTList LoVTs = DAG.getVTList(LoResVT, LoOvVT);
2402 SDVTList HiVTs = DAG.getVTList(HiResVT, HiOvVT);
2403 SDNode *LoNode =
2404 DAG.getNode(Opcode, dl, LoVTs, {LoLHS, LoRHS}, N->getFlags()).getNode();
2405 SDNode *HiNode =
2406 DAG.getNode(Opcode, dl, HiVTs, {HiLHS, HiRHS}, N->getFlags()).getNode();
2407
2408 Lo = SDValue(LoNode, ResNo);
2409 Hi = SDValue(HiNode, ResNo);
2410
2411 // Replace the other vector result not being explicitly split here.
2412 unsigned OtherNo = 1 - ResNo;
2413 EVT OtherVT = N->getValueType(OtherNo);
2414 if (getTypeAction(OtherVT) == TargetLowering::TypeSplitVector) {
2415 SetSplitVector(SDValue(N, OtherNo),
2416 SDValue(LoNode, OtherNo), SDValue(HiNode, OtherNo));
2417 } else {
2418 SDValue OtherVal = DAG.getNode(
2419 ISD::CONCAT_VECTORS, dl, OtherVT,
2420 SDValue(LoNode, OtherNo), SDValue(HiNode, OtherNo));
2421 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
2422 }
2423}
2424
2425void DAGTypeLegalizer::SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo,
2426 SDValue &Hi) {
2427 SDValue Vec = N->getOperand(0);
2428 SDValue Elt = N->getOperand(1);
2429 SDValue Idx = N->getOperand(2);
2430 SDLoc dl(N);
2431 GetSplitVector(Vec, Lo, Hi);
2432
2433 if (ConstantSDNode *CIdx = dyn_cast<ConstantSDNode>(Idx)) {
2434 unsigned IdxVal = CIdx->getZExtValue();
2435 unsigned LoNumElts = Lo.getValueType().getVectorMinNumElements();
2436 if (IdxVal < LoNumElts) {
2437 Lo = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl,
2438 Lo.getValueType(), Lo, Elt, Idx);
2439 return;
2440 } else if (!Vec.getValueType().isScalableVector()) {
2441 Hi = DAG.getInsertVectorElt(dl, Hi, Elt, IdxVal - LoNumElts);
2442 return;
2443 }
2444 }
2445
2446 // Make the vector elements byte-addressable if they aren't already.
2447 EVT VecVT = Vec.getValueType();
2448 EVT EltVT = VecVT.getVectorElementType();
2449 if (!EltVT.isByteSized()) {
2450 EltVT = EltVT.changeTypeToInteger().getRoundIntegerType(*DAG.getContext());
2451 VecVT = VecVT.changeElementType(*DAG.getContext(), EltVT);
2452 Vec = DAG.getNode(ISD::ANY_EXTEND, dl, VecVT, Vec);
2453 // Extend the element type to match if needed.
2454 if (EltVT.bitsGT(Elt.getValueType()))
2455 Elt = DAG.getNode(ISD::ANY_EXTEND, dl, EltVT, Elt);
2456 }
2457
2458 // Spill the vector to the stack.
2459 // In cases where the vector is illegal it will be broken down into parts
2460 // and stored in parts - we should use the alignment for the smallest part.
2461 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
2463 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
2464 auto &MF = DAG.getMachineFunction();
2465 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
2466 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
2467
2468 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
2469 SmallestAlign);
2470
2471 // Store the new element. This may be larger than the vector element type,
2472 // so use a truncating store.
2473 SDValue EltPtr = TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Idx);
2474 Store = DAG.getTruncStore(
2475 Store, dl, Elt, EltPtr, MachinePointerInfo::getUnknownStack(MF), EltVT,
2476 commonAlignment(SmallestAlign,
2477 EltVT.getFixedSizeInBits() / 8));
2478
2479 EVT LoVT, HiVT;
2480 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(VecVT);
2481
2482 // Load the Lo part from the stack slot.
2483 Lo = DAG.getLoad(LoVT, dl, Store, StackPtr, PtrInfo, SmallestAlign);
2484
2485 // Increment the pointer to the other part.
2486 auto Load = cast<LoadSDNode>(Lo);
2487 MachinePointerInfo MPI = Load->getPointerInfo();
2488 IncrementPointer(Load, LoVT, MPI, StackPtr);
2489
2490 Hi = DAG.getLoad(HiVT, dl, Store, StackPtr, MPI, SmallestAlign);
2491
2492 // If we adjusted the original type, we need to truncate the results.
2493 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2494 if (LoVT != Lo.getValueType())
2495 Lo = DAG.getNode(ISD::TRUNCATE, dl, LoVT, Lo);
2496 if (HiVT != Hi.getValueType())
2497 Hi = DAG.getNode(ISD::TRUNCATE, dl, HiVT, Hi);
2498}
2499
2500void DAGTypeLegalizer::SplitVecRes_STEP_VECTOR(SDNode *N, SDValue &Lo,
2501 SDValue &Hi) {
2502 EVT LoVT, HiVT;
2503 SDLoc dl(N);
2504 assert(N->getValueType(0).isScalableVector() &&
2505 "Only scalable vectors are supported for STEP_VECTOR");
2506 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2507 SDValue Step = N->getOperand(0);
2508
2509 Lo = DAG.getNode(ISD::STEP_VECTOR, dl, LoVT, Step);
2510
2511 // Hi = Lo + (EltCnt * Step)
2512 EVT EltVT = Step.getValueType();
2513 APInt StepVal = Step->getAsAPIntVal();
2514 SDValue StartOfHi =
2515 DAG.getVScale(dl, EltVT, StepVal * LoVT.getVectorMinNumElements());
2516 StartOfHi = DAG.getSExtOrTrunc(StartOfHi, dl, HiVT.getVectorElementType());
2517 StartOfHi = DAG.getNode(ISD::SPLAT_VECTOR, dl, HiVT, StartOfHi);
2518
2519 Hi = DAG.getNode(ISD::STEP_VECTOR, dl, HiVT, Step);
2520 Hi = DAG.getNode(ISD::ADD, dl, HiVT, Hi, StartOfHi);
2521}
2522
2523void DAGTypeLegalizer::SplitVecRes_ScalarOp(SDNode *N, SDValue &Lo,
2524 SDValue &Hi) {
2525 EVT LoVT, HiVT;
2526 SDLoc dl(N);
2527 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2528 Lo = DAG.getNode(N->getOpcode(), dl, LoVT, N->getOperand(0));
2529 if (N->getOpcode() == ISD::SCALAR_TO_VECTOR) {
2530 Hi = DAG.getPOISON(HiVT);
2531 } else {
2532 assert(N->getOpcode() == ISD::SPLAT_VECTOR && "Unexpected opcode");
2533 Hi = Lo;
2534 }
2535}
2536
2537void DAGTypeLegalizer::SplitVecRes_ATOMIC_LOAD(AtomicSDNode *LD, SDValue &Lo,
2538 SDValue &Hi) {
2539 assert(LD->getExtensionType() == ISD::NON_EXTLOAD &&
2540 "Extended load during type legalization!");
2541 SDLoc dl(LD);
2542 EVT VT = LD->getValueType(0);
2543 EVT LoVT, HiVT;
2544 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(VT);
2545
2546 SDValue Ch = LD->getChain();
2547 SDValue Ptr = LD->getBasePtr();
2548
2549 EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
2550 EVT MemIntVT =
2551 EVT::getIntegerVT(*DAG.getContext(), LD->getMemoryVT().getSizeInBits());
2552 SDValue ALD = DAG.getAtomicLoad(LD->getExtensionType(), dl, MemIntVT, IntVT,
2553 Ch, Ptr, LD->getMemOperand());
2554
2555 EVT LoIntVT = EVT::getIntegerVT(*DAG.getContext(), LoVT.getSizeInBits());
2556 EVT HiIntVT = EVT::getIntegerVT(*DAG.getContext(), HiVT.getSizeInBits());
2557 SDValue ExtractLo, ExtractHi;
2558 SplitInteger(ALD, LoIntVT, HiIntVT, ExtractLo, ExtractHi);
2559
2560 Lo = DAG.getBitcast(LoVT, ExtractLo);
2561 Hi = DAG.getBitcast(HiVT, ExtractHi);
2562
2563 // Legalize the chain result - switch anything that used the old chain to
2564 // use the new one.
2565 ReplaceValueWith(SDValue(LD, 1), ALD.getValue(1));
2566}
2567
2568void DAGTypeLegalizer::SplitVecRes_LOAD(LoadSDNode *LD, SDValue &Lo,
2569 SDValue &Hi) {
2570 assert(ISD::isUNINDEXEDLoad(LD) && "Indexed load during type legalization!");
2571 EVT LoVT, HiVT;
2572 SDLoc dl(LD);
2573 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(LD->getValueType(0));
2574
2575 ISD::LoadExtType ExtType = LD->getExtensionType();
2576 SDValue Ch = LD->getChain();
2577 SDValue Ptr = LD->getBasePtr();
2578 SDValue Offset = DAG.getPOISON(Ptr.getValueType());
2579 EVT MemoryVT = LD->getMemoryVT();
2580 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
2581 MMOMetadata Metadata = LD->getMMOMetadataForSubAccess();
2582
2583 EVT LoMemVT, HiMemVT;
2584 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
2585
2586 if (!LoMemVT.isByteSized() || !HiMemVT.isByteSized()) {
2587 SDValue Value, NewChain;
2588 std::tie(Value, NewChain) = TLI.scalarizeVectorLoad(LD, DAG);
2589 std::tie(Lo, Hi) = DAG.SplitVector(Value, dl);
2590 ReplaceValueWith(SDValue(LD, 1), NewChain);
2591 return;
2592 }
2593
2594 Lo = DAG.getLoad(ISD::UNINDEXED, ExtType, LoVT, dl, Ch, Ptr, Offset,
2595 LD->getPointerInfo(), LoMemVT, LD->getBaseAlign(), MMOFlags,
2596 Metadata);
2597
2598 MachinePointerInfo MPI;
2599 IncrementPointer(LD, LoMemVT, MPI, Ptr);
2600
2601 Hi = DAG.getLoad(ISD::UNINDEXED, ExtType, HiVT, dl, Ch, Ptr, Offset, MPI,
2602 HiMemVT, LD->getBaseAlign(), MMOFlags, Metadata);
2603
2604 // Build a factor node to remember that this load is independent of the
2605 // other one.
2606 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2607 Hi.getValue(1));
2608
2609 // Legalize the chain result - switch anything that used the old chain to
2610 // use the new one.
2611 ReplaceValueWith(SDValue(LD, 1), Ch);
2612}
2613
2614void DAGTypeLegalizer::SplitVecRes_VP_LOAD(VPLoadSDNode *LD, SDValue &Lo,
2615 SDValue &Hi) {
2616 assert(LD->isUnindexed() && "Indexed VP load during type legalization!");
2617 EVT LoVT, HiVT;
2618 SDLoc dl(LD);
2619 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(LD->getValueType(0));
2620
2621 ISD::LoadExtType ExtType = LD->getExtensionType();
2622 SDValue Ch = LD->getChain();
2623 SDValue Ptr = LD->getBasePtr();
2624 SDValue Offset = LD->getOffset();
2625 assert(Offset.isUndef() && "Unexpected indexed variable-length load offset");
2626 Align Alignment = LD->getBaseAlign();
2627 SDValue Mask = LD->getMask();
2628 SDValue EVL = LD->getVectorLength();
2629 EVT MemoryVT = LD->getMemoryVT();
2630
2631 EVT LoMemVT, HiMemVT;
2632 bool HiIsEmpty = false;
2633 std::tie(LoMemVT, HiMemVT) =
2634 DAG.GetDependentSplitDestVTs(MemoryVT, LoVT, &HiIsEmpty);
2635
2636 // Split Mask operand
2637 SDValue MaskLo, MaskHi;
2638 if (Mask.getOpcode() == ISD::SETCC) {
2639 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
2640 } else {
2641 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
2642 GetSplitVector(Mask, MaskLo, MaskHi);
2643 else
2644 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, dl);
2645 }
2646
2647 // Split EVL operand
2648 SDValue EVLLo, EVLHi;
2649 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(EVL, LD->getValueType(0), dl);
2650
2651 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
2652 LD->getPointerInfo(), MachineMemOperand::MOLoad,
2654 MMOMetadata(LD->getAAInfo(), LD->getRanges()));
2655
2656 Lo =
2657 DAG.getLoadVP(LD->getAddressingMode(), ExtType, LoVT, dl, Ch, Ptr, Offset,
2658 MaskLo, EVLLo, LoMemVT, MMO, LD->isExpandingLoad());
2659
2660 if (HiIsEmpty) {
2661 // The hi vp_load has zero storage size. We therefore simply set it to
2662 // the low vp_load and rely on subsequent removal from the chain.
2663 Hi = Lo;
2664 } else {
2665 // Generate hi vp_load.
2666 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, dl, LoMemVT, DAG,
2667 LD->isExpandingLoad());
2668
2669 MachinePointerInfo MPI;
2670 if (LoMemVT.isScalableVector())
2671 MPI = MachinePointerInfo(LD->getPointerInfo().getAddrSpace());
2672 else
2673 MPI = LD->getPointerInfo().getWithOffset(
2674 LoMemVT.getStoreSize().getFixedValue());
2675
2676 MMO = DAG.getMachineFunction().getMachineMemOperand(
2678 Alignment, MMOMetadata(LD->getAAInfo(), LD->getRanges()));
2679
2680 Hi = DAG.getLoadVP(LD->getAddressingMode(), ExtType, HiVT, dl, Ch, Ptr,
2681 Offset, MaskHi, EVLHi, HiMemVT, MMO,
2682 LD->isExpandingLoad());
2683 }
2684
2685 // Build a factor node to remember that this load is independent of the
2686 // other one.
2687 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2688 Hi.getValue(1));
2689
2690 // Legalize the chain result - switch anything that used the old chain to
2691 // use the new one.
2692 ReplaceValueWith(SDValue(LD, 1), Ch);
2693}
2694
2695void DAGTypeLegalizer::SplitVecRes_VP_LOAD_FF(VPLoadFFSDNode *LD, SDValue &Lo,
2696 SDValue &Hi) {
2697 SDLoc dl(LD);
2698 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(LD->getValueType(0));
2699
2700 SDValue Ch = LD->getChain();
2701 SDValue Ptr = LD->getBasePtr();
2702 Align Alignment = LD->getBaseAlign();
2703 SDValue Mask = LD->getMask();
2704 SDValue EVL = LD->getVectorLength();
2705
2706 // Split Mask operand
2707 SDValue MaskLo, MaskHi;
2708 if (Mask.getOpcode() == ISD::SETCC) {
2709 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
2710 } else {
2711 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
2712 GetSplitVector(Mask, MaskLo, MaskHi);
2713 else
2714 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, dl);
2715 }
2716
2717 // Split EVL operand
2718 auto [EVLLo, EVLHi] = DAG.SplitEVL(EVL, LD->getValueType(0), dl);
2719
2720 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
2721 LD->getPointerInfo(), MachineMemOperand::MOLoad,
2723 MMOMetadata(LD->getAAInfo(), LD->getRanges()));
2724
2725 Lo = DAG.getLoadFFVP(LoVT, dl, Ch, Ptr, MaskLo, EVLLo, MMO);
2726
2727 // Fill the upper half with poison.
2728 Hi = DAG.getPOISON(HiVT);
2729
2730 ReplaceValueWith(SDValue(LD, 1), Lo.getValue(1));
2731 ReplaceValueWith(SDValue(LD, 2), Lo.getValue(2));
2732}
2733
2734void DAGTypeLegalizer::SplitVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode *SLD,
2735 SDValue &Lo, SDValue &Hi) {
2736 assert(SLD->isUnindexed() &&
2737 "Indexed VP strided load during type legalization!");
2738 assert(SLD->getOffset().isUndef() &&
2739 "Unexpected indexed variable-length load offset");
2740
2741 SDLoc DL(SLD);
2742
2743 EVT LoVT, HiVT;
2744 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(SLD->getValueType(0));
2745
2746 EVT LoMemVT, HiMemVT;
2747 bool HiIsEmpty = false;
2748 std::tie(LoMemVT, HiMemVT) =
2749 DAG.GetDependentSplitDestVTs(SLD->getMemoryVT(), LoVT, &HiIsEmpty);
2750
2751 SDValue Mask = SLD->getMask();
2752 SDValue LoMask, HiMask;
2753 if (Mask.getOpcode() == ISD::SETCC) {
2754 SplitVecRes_SETCC(Mask.getNode(), LoMask, HiMask);
2755 } else {
2756 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
2757 GetSplitVector(Mask, LoMask, HiMask);
2758 else
2759 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
2760 }
2761
2762 SDValue LoEVL, HiEVL;
2763 std::tie(LoEVL, HiEVL) =
2764 DAG.SplitEVL(SLD->getVectorLength(), SLD->getValueType(0), DL);
2765
2766 // Generate the low vp_strided_load
2767 Lo = DAG.getStridedLoadVP(
2768 SLD->getAddressingMode(), SLD->getExtensionType(), LoVT, DL,
2769 SLD->getChain(), SLD->getBasePtr(), SLD->getOffset(), SLD->getStride(),
2770 LoMask, LoEVL, LoMemVT, SLD->getMemOperand(), SLD->isExpandingLoad());
2771
2772 if (HiIsEmpty) {
2773 // The high vp_strided_load has zero storage size. We therefore simply set
2774 // it to the low vp_strided_load and rely on subsequent removal from the
2775 // chain.
2776 Hi = Lo;
2777 } else {
2778 // Generate the high vp_strided_load.
2779 // To calculate the high base address, we need to sum to the low base
2780 // address stride number of bytes for each element already loaded by low,
2781 // that is: Ptr = Ptr + (LoEVL * Stride)
2782 EVT PtrVT = SLD->getBasePtr().getValueType();
2784 DAG.getNode(ISD::MUL, DL, PtrVT, LoEVL,
2785 DAG.getSExtOrTrunc(SLD->getStride(), DL, PtrVT));
2786 SDValue Ptr =
2787 DAG.getNode(ISD::ADD, DL, PtrVT, SLD->getBasePtr(), Increment);
2788
2789 Align Alignment = SLD->getBaseAlign();
2790 if (LoMemVT.isScalableVector())
2792 Alignment, LoMemVT.getSizeInBits().getKnownMinValue() / 8);
2793
2794 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
2795 MachinePointerInfo(SLD->getPointerInfo().getAddrSpace()),
2797 Alignment, MMOMetadata(SLD->getAAInfo(), SLD->getRanges()));
2798
2799 Hi = DAG.getStridedLoadVP(SLD->getAddressingMode(), SLD->getExtensionType(),
2800 HiVT, DL, SLD->getChain(), Ptr, SLD->getOffset(),
2801 SLD->getStride(), HiMask, HiEVL, HiMemVT, MMO,
2802 SLD->isExpandingLoad());
2803 }
2804
2805 // Build a factor node to remember that this load is independent of the
2806 // other one.
2807 SDValue Ch = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo.getValue(1),
2808 Hi.getValue(1));
2809
2810 // Legalize the chain result - switch anything that used the old chain to
2811 // use the new one.
2812 ReplaceValueWith(SDValue(SLD, 1), Ch);
2813}
2814
2815void DAGTypeLegalizer::SplitVecRes_MLOAD(MaskedLoadSDNode *MLD,
2816 SDValue &Lo, SDValue &Hi) {
2817 assert(MLD->isUnindexed() && "Indexed masked load during type legalization!");
2818 EVT LoVT, HiVT;
2819 SDLoc dl(MLD);
2820 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(MLD->getValueType(0));
2821
2822 SDValue Ch = MLD->getChain();
2823 SDValue Ptr = MLD->getBasePtr();
2824 SDValue Offset = MLD->getOffset();
2825 assert(Offset.isUndef() && "Unexpected indexed masked load offset");
2826 SDValue Mask = MLD->getMask();
2827 SDValue PassThru = MLD->getPassThru();
2828 Align Alignment = MLD->getBaseAlign();
2829 ISD::LoadExtType ExtType = MLD->getExtensionType();
2830 MachineMemOperand::Flags MMOFlags = MLD->getMemOperand()->getFlags();
2831
2832 // Split Mask operand
2833 SDValue MaskLo, MaskHi;
2834 if (Mask.getOpcode() == ISD::SETCC) {
2835 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
2836 } else {
2837 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
2838 GetSplitVector(Mask, MaskLo, MaskHi);
2839 else
2840 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, dl);
2841 }
2842
2843 EVT MemoryVT = MLD->getMemoryVT();
2844 EVT LoMemVT, HiMemVT;
2845 bool HiIsEmpty = false;
2846 std::tie(LoMemVT, HiMemVT) =
2847 DAG.GetDependentSplitDestVTs(MemoryVT, LoVT, &HiIsEmpty);
2848
2849 SDValue PassThruLo, PassThruHi;
2850 if (getTypeAction(PassThru.getValueType()) == TargetLowering::TypeSplitVector)
2851 GetSplitVector(PassThru, PassThruLo, PassThruHi);
2852 else
2853 std::tie(PassThruLo, PassThruHi) = DAG.SplitVector(PassThru, dl);
2854
2855 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
2857 Alignment,
2858 MMOMetadata(MLD->getAAInfo(), MLD->getRanges(), MLD->getMemCacheHint()));
2859
2860 Lo = DAG.getMaskedLoad(LoVT, dl, Ch, Ptr, Offset, MaskLo, PassThruLo, LoMemVT,
2861 MMO, MLD->getAddressingMode(), ExtType,
2862 MLD->isExpandingLoad());
2863
2864 if (HiIsEmpty) {
2865 // The hi masked load has zero storage size. We therefore simply set it to
2866 // the low masked load and rely on subsequent removal from the chain.
2867 Hi = Lo;
2868 } else {
2869 // Generate hi masked load.
2870 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, dl, LoMemVT, DAG,
2871 MLD->isExpandingLoad());
2872
2873 MachinePointerInfo MPI;
2874 if (LoMemVT.isScalableVector())
2875 MPI = MachinePointerInfo(MLD->getPointerInfo().getAddrSpace());
2876 else
2877 MPI = MLD->getPointerInfo().getWithOffset(
2878 LoMemVT.getStoreSize().getFixedValue());
2879
2880 MMO = DAG.getMachineFunction().getMachineMemOperand(
2881 MPI, MMOFlags, LocationSize::beforeOrAfterPointer(), Alignment,
2882 MMOMetadata(MLD->getAAInfo(), MLD->getRanges(),
2883 MLD->getMemCacheHint()));
2884
2885 Hi = DAG.getMaskedLoad(HiVT, dl, Ch, Ptr, Offset, MaskHi, PassThruHi,
2886 HiMemVT, MMO, MLD->getAddressingMode(), ExtType,
2887 MLD->isExpandingLoad());
2888 }
2889
2890 // Build a factor node to remember that this load is independent of the
2891 // other one.
2892 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2893 Hi.getValue(1));
2894
2895 // Legalize the chain result - switch anything that used the old chain to
2896 // use the new one.
2897 ReplaceValueWith(SDValue(MLD, 1), Ch);
2898
2899}
2900
2901void DAGTypeLegalizer::SplitVecRes_Gather(MemSDNode *N, SDValue &Lo,
2902 SDValue &Hi, bool SplitSETCC) {
2903 EVT LoVT, HiVT;
2904 SDLoc dl(N);
2905 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2906
2907 SDValue Ch = N->getChain();
2908 SDValue Ptr = N->getBasePtr();
2909 struct Operands {
2910 SDValue Mask;
2911 SDValue Index;
2912 SDValue Scale;
2913 } Ops = [&]() -> Operands {
2914 if (auto *MSC = dyn_cast<MaskedGatherSDNode>(N)) {
2915 return {MSC->getMask(), MSC->getIndex(), MSC->getScale()};
2916 }
2917 auto *VPSC = cast<VPGatherSDNode>(N);
2918 return {VPSC->getMask(), VPSC->getIndex(), VPSC->getScale()};
2919 }();
2920
2921 EVT MemoryVT = N->getMemoryVT();
2922 Align Alignment = N->getBaseAlign();
2923
2924 // Split Mask operand
2925 SDValue MaskLo, MaskHi;
2926 if (SplitSETCC && Ops.Mask.getOpcode() == ISD::SETCC) {
2927 SplitVecRes_SETCC(Ops.Mask.getNode(), MaskLo, MaskHi);
2928 } else {
2929 std::tie(MaskLo, MaskHi) = SplitMask(Ops.Mask, dl);
2930 }
2931
2932 EVT LoMemVT, HiMemVT;
2933 // Split MemoryVT
2934 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
2935
2936 SDValue IndexHi, IndexLo;
2937 if (getTypeAction(Ops.Index.getValueType()) ==
2939 GetSplitVector(Ops.Index, IndexLo, IndexHi);
2940 else
2941 std::tie(IndexLo, IndexHi) = DAG.SplitVector(Ops.Index, dl);
2942
2943 MachineMemOperand::Flags MMOFlags = N->getMemOperand()->getFlags();
2944 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
2945 N->getPointerInfo(), MMOFlags, LocationSize::beforeOrAfterPointer(),
2946 Alignment, MMOMetadata(N->getAAInfo(), N->getRanges()));
2947
2948 if (auto *MGT = dyn_cast<MaskedGatherSDNode>(N)) {
2949 SDValue PassThru = MGT->getPassThru();
2950 SDValue PassThruLo, PassThruHi;
2951 if (getTypeAction(PassThru.getValueType()) ==
2953 GetSplitVector(PassThru, PassThruLo, PassThruHi);
2954 else
2955 std::tie(PassThruLo, PassThruHi) = DAG.SplitVector(PassThru, dl);
2956
2957 ISD::LoadExtType ExtType = MGT->getExtensionType();
2958 ISD::MemIndexType IndexTy = MGT->getIndexType();
2959
2960 SDValue OpsLo[] = {Ch, PassThruLo, MaskLo, Ptr, IndexLo, Ops.Scale};
2961 Lo = DAG.getMaskedGather(DAG.getVTList(LoVT, MVT::Other), LoMemVT, dl,
2962 OpsLo, MMO, IndexTy, ExtType);
2963
2964 SDValue OpsHi[] = {Ch, PassThruHi, MaskHi, Ptr, IndexHi, Ops.Scale};
2965 Hi = DAG.getMaskedGather(DAG.getVTList(HiVT, MVT::Other), HiMemVT, dl,
2966 OpsHi, MMO, IndexTy, ExtType);
2967 } else {
2968 auto *VPGT = cast<VPGatherSDNode>(N);
2969 SDValue EVLLo, EVLHi;
2970 std::tie(EVLLo, EVLHi) =
2971 DAG.SplitEVL(VPGT->getVectorLength(), MemoryVT, dl);
2972
2973 SDValue OpsLo[] = {Ch, Ptr, IndexLo, Ops.Scale, MaskLo, EVLLo};
2974 Lo = DAG.getGatherVP(DAG.getVTList(LoVT, MVT::Other), LoMemVT, dl, OpsLo,
2975 MMO, VPGT->getIndexType());
2976
2977 SDValue OpsHi[] = {Ch, Ptr, IndexHi, Ops.Scale, MaskHi, EVLHi};
2978 Hi = DAG.getGatherVP(DAG.getVTList(HiVT, MVT::Other), HiMemVT, dl, OpsHi,
2979 MMO, VPGT->getIndexType());
2980 }
2981
2982 // Build a factor node to remember that this load is independent of the
2983 // other one.
2984 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2985 Hi.getValue(1));
2986
2987 // Legalize the chain result - switch anything that used the old chain to
2988 // use the new one.
2989 ReplaceValueWith(SDValue(N, 1), Ch);
2990}
2991
2992void DAGTypeLegalizer::SplitVecRes_VECTOR_COMPRESS(SDNode *N, SDValue &Lo,
2993 SDValue &Hi) {
2994 // This is not "trivial", as there is a dependency between the two subvectors.
2995 // Depending on the number of 1s in the mask, the elements from the Hi vector
2996 // need to be moved to the Lo vector. Passthru values make this even harder.
2997 // We try to use VECTOR_COMPRESS if the target has custom lowering with
2998 // smaller types and passthru is undef, as it is most likely faster than the
2999 // fully expand path. Otherwise, just do the full expansion as one "big"
3000 // operation and then extract the Lo and Hi vectors from that. This gets
3001 // rid of VECTOR_COMPRESS and all other operands can be legalized later.
3002 SDLoc DL(N);
3003 EVT VecVT = N->getValueType(0);
3004
3005 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(VecVT);
3006 bool HasCustomLowering = false;
3007 EVT CheckVT = LoVT;
3008 while (CheckVT.getVectorMinNumElements() > 1) {
3009 // TLI.isOperationLegalOrCustom requires a legal type, but we could have a
3010 // custom lowering for illegal types. So we do the checks separately.
3011 if (TLI.isOperationLegal(ISD::VECTOR_COMPRESS, CheckVT) ||
3012 TLI.isOperationCustom(ISD::VECTOR_COMPRESS, CheckVT)) {
3013 HasCustomLowering = true;
3014 break;
3015 }
3016 CheckVT = CheckVT.getHalfNumVectorElementsVT(*DAG.getContext());
3017 }
3018
3019 SDValue Passthru = N->getOperand(2);
3020 if (!HasCustomLowering) {
3021 SDValue Compressed = TLI.expandVECTOR_COMPRESS(N, DAG);
3022 std::tie(Lo, Hi) = DAG.SplitVector(Compressed, DL, LoVT, HiVT);
3023 return;
3024 }
3025
3026 // Try to VECTOR_COMPRESS smaller vectors and combine via a stack store+load.
3027 SDValue Mask = N->getOperand(1);
3028 SDValue LoMask, HiMask;
3029 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
3030 std::tie(LoMask, HiMask) = SplitMask(Mask);
3031
3032 SDValue UndefPassthru = DAG.getPOISON(LoVT);
3033 Lo = DAG.getNode(ISD::VECTOR_COMPRESS, DL, LoVT, Lo, LoMask, UndefPassthru);
3034 Hi = DAG.getNode(ISD::VECTOR_COMPRESS, DL, HiVT, Hi, HiMask, UndefPassthru);
3035
3036 SDValue StackPtr = DAG.CreateStackTemporary(
3037 VecVT.getStoreSize(), DAG.getReducedAlign(VecVT, /*UseABI=*/false));
3038 MachineFunction &MF = DAG.getMachineFunction();
3039 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(
3040 MF, cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex());
3041
3042 EVT LoMaskVT = LoMask.getValueType();
3043 assert(LoMaskVT.getScalarType() == MVT::i1 && "Expected vector of i1s");
3044
3045 // We store LoVec and then insert HiVec starting at offset=|1s| in LoMask.
3046 EVT WideLoMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i32,
3047 LoMaskVT.getVectorElementCount());
3048 SDValue WideLoMask = DAG.getNode(ISD::ZERO_EXTEND, DL, WideLoMaskVT, LoMask);
3049 SDValue Offset = DAG.getNode(ISD::VECREDUCE_ADD, DL, MVT::i32, WideLoMask);
3050 Offset = TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Offset);
3051
3052 SDValue Chain = DAG.getEntryNode();
3053 Chain = DAG.getStore(Chain, DL, Lo, StackPtr, PtrInfo);
3054 Chain = DAG.getStore(Chain, DL, Hi, Offset,
3056
3057 SDValue Compressed = DAG.getLoad(VecVT, DL, Chain, StackPtr, PtrInfo);
3058 if (!Passthru.isUndef()) {
3059 // Compress the input mask so only inactive lanes of the result are replaced
3060 // by their passthrough value.
3061 EVT MaskVT = Mask.getValueType();
3062 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i32,
3063 MaskVT.getVectorElementCount());
3064 SDValue WideMask = DAG.getNode(ISD::ZERO_EXTEND, DL, WideMaskVT, Mask);
3065 SDValue NumActiveElts =
3066 DAG.getNode(ISD::VECREDUCE_ADD, DL, MVT::i32, WideMask);
3067
3068 SDValue StepVector = DAG.getStepVector(DL, WideMaskVT);
3069 SDValue SplatNumActiveElts = DAG.getSplat(WideMaskVT, DL, NumActiveElts);
3070 SDValue CompressedMask =
3071 DAG.getSetCC(DL, MaskVT, StepVector, SplatNumActiveElts, ISD::SETULT);
3072
3073 Compressed = DAG.getNode(ISD::VSELECT, DL, VecVT, CompressedMask,
3074 Compressed, Passthru);
3075 }
3076 std::tie(Lo, Hi) = DAG.SplitVector(Compressed, DL);
3077}
3078
3079void DAGTypeLegalizer::SplitVecRes_SETCC(SDNode *N, SDValue &Lo, SDValue &Hi) {
3080 assert(N->getValueType(0).isVector() &&
3081 N->getOperand(0).getValueType().isVector() &&
3082 "Operand types must be vectors");
3083
3084 EVT LoVT, HiVT;
3085 SDLoc DL(N);
3086 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
3087
3088 // If the input also splits, handle it directly. Otherwise split it by hand.
3089 SDValue LL, LH, RL, RH;
3090 if (getTypeAction(N->getOperand(0).getValueType()) ==
3092 GetSplitVector(N->getOperand(0), LL, LH);
3093 else
3094 std::tie(LL, LH) = DAG.SplitVectorOperand(N, 0);
3095
3096 if (getTypeAction(N->getOperand(1).getValueType()) ==
3098 GetSplitVector(N->getOperand(1), RL, RH);
3099 else
3100 std::tie(RL, RH) = DAG.SplitVectorOperand(N, 1);
3101
3102 Lo = DAG.getNode(N->getOpcode(), DL, LoVT, LL, RL, N->getOperand(2));
3103 Hi = DAG.getNode(N->getOpcode(), DL, HiVT, LH, RH, N->getOperand(2));
3104}
3105
3106void DAGTypeLegalizer::SplitVecRes_UnaryOp(SDNode *N, SDValue &Lo,
3107 SDValue &Hi) {
3108 // Get the dest types - they may not match the input types, e.g. int_to_fp.
3109 EVT LoVT, HiVT;
3110 SDLoc dl(N);
3111 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
3112
3113 // If the input also splits, handle it directly for a compile time speedup.
3114 // Otherwise split it by hand.
3115 EVT InVT = N->getOperand(0).getValueType();
3116 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
3117 GetSplitVector(N->getOperand(0), Lo, Hi);
3118 else
3119 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
3120
3121 const SDNodeFlags Flags = N->getFlags();
3122 unsigned Opcode = N->getOpcode();
3123 if (Opcode == ISD::CONVERT_TO_ARBITRARY_FP) {
3124 Lo = DAG.getNode(Opcode, dl, LoVT, Lo, N->getOperand(1), N->getOperand(2),
3125 N->getOperand(3), Flags);
3126 Hi = DAG.getNode(Opcode, dl, HiVT, Hi, N->getOperand(1), N->getOperand(2),
3127 N->getOperand(3), Flags);
3128 return;
3129 }
3130
3131 if (Opcode == ISD::FP_ROUND || Opcode == ISD::AssertNoFPClass ||
3133 Lo = DAG.getNode(Opcode, dl, LoVT, Lo, N->getOperand(1), Flags);
3134 Hi = DAG.getNode(Opcode, dl, HiVT, Hi, N->getOperand(1), Flags);
3135 } else {
3136 Lo = DAG.getNode(Opcode, dl, LoVT, Lo, Flags);
3137 Hi = DAG.getNode(Opcode, dl, HiVT, Hi, Flags);
3138 }
3139}
3140
3141void DAGTypeLegalizer::SplitVecRes_ADDRSPACECAST(SDNode *N, SDValue &Lo,
3142 SDValue &Hi) {
3143 SDLoc dl(N);
3144 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(N->getValueType(0));
3145
3146 // If the input also splits, handle it directly for a compile time speedup.
3147 // Otherwise split it by hand.
3148 EVT InVT = N->getOperand(0).getValueType();
3149 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
3150 GetSplitVector(N->getOperand(0), Lo, Hi);
3151 else
3152 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
3153
3154 auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
3155 unsigned SrcAS = AddrSpaceCastN->getSrcAddressSpace();
3156 unsigned DestAS = AddrSpaceCastN->getDestAddressSpace();
3157 SDNodeFlags Flags = AddrSpaceCastN->getFlags();
3158 Lo = DAG.getAddrSpaceCast(dl, LoVT, Lo, SrcAS, DestAS, Flags);
3159 Hi = DAG.getAddrSpaceCast(dl, HiVT, Hi, SrcAS, DestAS, Flags);
3160}
3161
3162void DAGTypeLegalizer::SplitVecRes_UnaryOpWithTwoResults(SDNode *N,
3163 unsigned ResNo,
3164 SDValue &Lo,
3165 SDValue &Hi) {
3166 SDLoc dl(N);
3167 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(N->getValueType(0));
3168 auto [LoVT1, HiVT1] = DAG.GetSplitDestVTs(N->getValueType(1));
3169
3170 // If the input also splits, handle it directly for a compile time speedup.
3171 // Otherwise split it by hand.
3172 EVT InVT = N->getOperand(0).getValueType();
3173 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
3174 GetSplitVector(N->getOperand(0), Lo, Hi);
3175 else
3176 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
3177
3178 Lo = DAG.getNode(N->getOpcode(), dl, {LoVT, LoVT1}, Lo, N->getFlags());
3179 Hi = DAG.getNode(N->getOpcode(), dl, {HiVT, HiVT1}, Hi, N->getFlags());
3180
3181 SDNode *HiNode = Hi.getNode();
3182 SDNode *LoNode = Lo.getNode();
3183
3184 // Replace the other vector result not being explicitly split here.
3185 unsigned OtherNo = 1 - ResNo;
3186 EVT OtherVT = N->getValueType(OtherNo);
3187 if (getTypeAction(OtherVT) == TargetLowering::TypeSplitVector) {
3188 SetSplitVector(SDValue(N, OtherNo), SDValue(LoNode, OtherNo),
3189 SDValue(HiNode, OtherNo));
3190 } else {
3191 SDValue OtherVal =
3192 DAG.getNode(ISD::CONCAT_VECTORS, dl, OtherVT, SDValue(LoNode, OtherNo),
3193 SDValue(HiNode, OtherNo));
3194 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
3195 }
3196}
3197
3198void DAGTypeLegalizer::SplitVecRes_ExtendOp(SDNode *N, SDValue &Lo,
3199 SDValue &Hi) {
3200 SDLoc dl(N);
3201 EVT SrcVT = N->getOperand(0).getValueType();
3202 EVT DestVT = N->getValueType(0);
3203 EVT LoVT, HiVT;
3204 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(DestVT);
3205
3206 // We can do better than a generic split operation if the extend is doing
3207 // more than just doubling the width of the elements and the following are
3208 // true:
3209 // - The number of vector elements is even,
3210 // - the source type is legal,
3211 // - the type of a split source is illegal,
3212 // - the type of an extended (by doubling element size) source is legal, and
3213 // - the type of that extended source when split is legal.
3214 //
3215 // This won't necessarily completely legalize the operation, but it will
3216 // more effectively move in the right direction and prevent falling down
3217 // to scalarization in many cases due to the input vector being split too
3218 // far.
3219 if (SrcVT.getVectorElementCount().isKnownEven() &&
3220 SrcVT.getScalarSizeInBits() * 2 < DestVT.getScalarSizeInBits()) {
3221 LLVMContext &Ctx = *DAG.getContext();
3222 EVT NewSrcVT = SrcVT.widenIntegerVectorElementType(Ctx);
3223 EVT SplitSrcVT = SrcVT.getHalfNumVectorElementsVT(Ctx);
3224
3225 EVT SplitLoVT, SplitHiVT;
3226 std::tie(SplitLoVT, SplitHiVT) = DAG.GetSplitDestVTs(NewSrcVT);
3227 if (TLI.isTypeLegal(SrcVT) && !TLI.isTypeLegal(SplitSrcVT) &&
3228 TLI.isTypeLegal(NewSrcVT) && TLI.isTypeLegal(SplitLoVT)) {
3229 LLVM_DEBUG(dbgs() << "Split vector extend via incremental extend:";
3230 N->dump(&DAG); dbgs() << "\n");
3231 // Extend the source vector by one step.
3232 SDValue NewSrc =
3233 DAG.getNode(N->getOpcode(), dl, NewSrcVT, N->getOperand(0));
3234 // Get the low and high halves of the new, extended one step, vector.
3235 std::tie(Lo, Hi) = DAG.SplitVector(NewSrc, dl);
3236 // Extend those vector halves the rest of the way.
3237 Lo = DAG.getNode(N->getOpcode(), dl, LoVT, Lo);
3238 Hi = DAG.getNode(N->getOpcode(), dl, HiVT, Hi);
3239 return;
3240 }
3241 }
3242 // Fall back to the generic unary operator splitting otherwise.
3243 SplitVecRes_UnaryOp(N, Lo, Hi);
3244}
3245
3246void DAGTypeLegalizer::SplitVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N,
3247 SDValue &Lo, SDValue &Hi) {
3248 // The low and high parts of the original input give four input vectors.
3249 SDValue Inputs[4];
3250 SDLoc DL(N);
3251 GetSplitVector(N->getOperand(0), Inputs[0], Inputs[1]);
3252 GetSplitVector(N->getOperand(1), Inputs[2], Inputs[3]);
3253 EVT NewVT = Inputs[0].getValueType();
3254 unsigned NewElts = NewVT.getVectorNumElements();
3255
3256 auto &&IsConstant = [](const SDValue &N) {
3257 APInt SplatValue;
3258 return N.getResNo() == 0 &&
3259 (ISD::isConstantSplatVector(N.getNode(), SplatValue) ||
3261 };
3262 auto &&BuildVector = [NewElts, &DAG = DAG, NewVT, &DL](SDValue &Input1,
3263 SDValue &Input2,
3264 ArrayRef<int> Mask) {
3265 assert(Input1->getOpcode() == ISD::BUILD_VECTOR &&
3266 Input2->getOpcode() == ISD::BUILD_VECTOR &&
3267 "Expected build vector node.");
3268 EVT EltVT = NewVT.getVectorElementType();
3269 SmallVector<SDValue> Ops(NewElts, DAG.getPOISON(EltVT));
3270 for (unsigned I = 0; I < NewElts; ++I) {
3271 if (Mask[I] == PoisonMaskElem)
3272 continue;
3273 unsigned Idx = Mask[I];
3274 if (Idx >= NewElts)
3275 Ops[I] = Input2.getOperand(Idx - NewElts);
3276 else
3277 Ops[I] = Input1.getOperand(Idx);
3278 // Make the type of all elements the same as the element type.
3279 if (Ops[I].getValueType().bitsGT(EltVT))
3280 Ops[I] = DAG.getNode(ISD::TRUNCATE, DL, EltVT, Ops[I]);
3281 }
3282 return DAG.getBuildVector(NewVT, DL, Ops);
3283 };
3284
3285 // If Lo or Hi uses elements from at most two of the four input vectors, then
3286 // express it as a vector shuffle of those two inputs. Otherwise extract the
3287 // input elements by hand and construct the Lo/Hi output using a BUILD_VECTOR.
3288 SmallVector<int> OrigMask(N->getMask());
3289 // Try to pack incoming shuffles/inputs.
3290 auto &&TryPeekThroughShufflesInputs = [&Inputs, &NewVT, this, NewElts,
3291 &DL](SmallVectorImpl<int> &Mask) {
3292 // Check if all inputs are shuffles of the same operands or non-shuffles.
3293 MapVector<std::pair<SDValue, SDValue>, SmallVector<unsigned>> ShufflesIdxs;
3294 for (unsigned Idx = 0; Idx < std::size(Inputs); ++Idx) {
3295 SDValue Input = Inputs[Idx];
3296 auto *Shuffle = dyn_cast<ShuffleVectorSDNode>(Input.getNode());
3297 if (!Shuffle ||
3298 Input.getOperand(0).getValueType() != Input.getValueType())
3299 continue;
3300 ShufflesIdxs[std::make_pair(Input.getOperand(0), Input.getOperand(1))]
3301 .push_back(Idx);
3302 ShufflesIdxs[std::make_pair(Input.getOperand(1), Input.getOperand(0))]
3303 .push_back(Idx);
3304 }
3305 for (auto &P : ShufflesIdxs) {
3306 if (P.second.size() < 2)
3307 continue;
3308 // Use shuffles operands instead of shuffles themselves.
3309 // 1. Adjust mask.
3310 for (int &Idx : Mask) {
3311 if (Idx == PoisonMaskElem)
3312 continue;
3313 unsigned SrcRegIdx = Idx / NewElts;
3314 if (Inputs[SrcRegIdx].isUndef()) {
3316 continue;
3317 }
3318 auto *Shuffle =
3319 dyn_cast<ShuffleVectorSDNode>(Inputs[SrcRegIdx].getNode());
3320 if (!Shuffle || !is_contained(P.second, SrcRegIdx))
3321 continue;
3322 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
3323 if (MaskElt == PoisonMaskElem) {
3325 continue;
3326 }
3327 Idx = MaskElt % NewElts +
3328 P.second[Shuffle->getOperand(MaskElt / NewElts) == P.first.first
3329 ? 0
3330 : 1] *
3331 NewElts;
3332 }
3333 // 2. Update inputs.
3334 Inputs[P.second[0]] = P.first.first;
3335 Inputs[P.second[1]] = P.first.second;
3336 // Clear the pair data.
3337 P.second.clear();
3338 ShufflesIdxs[std::make_pair(P.first.second, P.first.first)].clear();
3339 }
3340 // Check if any concat_vectors can be simplified.
3341 SmallBitVector UsedSubVector(2 * std::size(Inputs));
3342 for (int &Idx : Mask) {
3343 if (Idx == PoisonMaskElem)
3344 continue;
3345 unsigned SrcRegIdx = Idx / NewElts;
3346 if (Inputs[SrcRegIdx].isUndef()) {
3348 continue;
3349 }
3351 getTypeAction(Inputs[SrcRegIdx].getValueType());
3352 if (Inputs[SrcRegIdx].getOpcode() == ISD::CONCAT_VECTORS &&
3353 Inputs[SrcRegIdx].getNumOperands() == 2 &&
3354 !Inputs[SrcRegIdx].getOperand(1).isUndef() &&
3355 (TypeAction == TargetLowering::TypeLegal ||
3356 TypeAction == TargetLowering::TypeWidenVector))
3357 UsedSubVector.set(2 * SrcRegIdx + (Idx % NewElts) / (NewElts / 2));
3358 }
3359 if (UsedSubVector.count() > 1) {
3361 for (unsigned I = 0; I < std::size(Inputs); ++I) {
3362 if (UsedSubVector.test(2 * I) == UsedSubVector.test(2 * I + 1))
3363 continue;
3364 if (Pairs.empty() || Pairs.back().size() == 2)
3365 Pairs.emplace_back();
3366 if (UsedSubVector.test(2 * I)) {
3367 Pairs.back().emplace_back(I, 0);
3368 } else {
3369 assert(UsedSubVector.test(2 * I + 1) &&
3370 "Expected to be used one of the subvectors.");
3371 Pairs.back().emplace_back(I, 1);
3372 }
3373 }
3374 if (!Pairs.empty() && Pairs.front().size() > 1) {
3375 // Adjust mask.
3376 for (int &Idx : Mask) {
3377 if (Idx == PoisonMaskElem)
3378 continue;
3379 unsigned SrcRegIdx = Idx / NewElts;
3380 auto *It = find_if(
3381 Pairs, [SrcRegIdx](ArrayRef<std::pair<unsigned, int>> Idxs) {
3382 return Idxs.front().first == SrcRegIdx ||
3383 Idxs.back().first == SrcRegIdx;
3384 });
3385 if (It == Pairs.end())
3386 continue;
3387 Idx = It->front().first * NewElts + (Idx % NewElts) % (NewElts / 2) +
3388 (SrcRegIdx == It->front().first ? 0 : (NewElts / 2));
3389 }
3390 // Adjust inputs.
3391 for (ArrayRef<std::pair<unsigned, int>> Idxs : Pairs) {
3392 Inputs[Idxs.front().first] = DAG.getNode(
3394 Inputs[Idxs.front().first].getValueType(),
3395 Inputs[Idxs.front().first].getOperand(Idxs.front().second),
3396 Inputs[Idxs.back().first].getOperand(Idxs.back().second));
3397 }
3398 }
3399 }
3400 bool Changed;
3401 do {
3402 // Try to remove extra shuffles (except broadcasts) and shuffles with the
3403 // reused operands.
3404 Changed = false;
3405 for (unsigned I = 0; I < std::size(Inputs); ++I) {
3406 auto *Shuffle = dyn_cast<ShuffleVectorSDNode>(Inputs[I].getNode());
3407 if (!Shuffle)
3408 continue;
3409 if (Shuffle->getOperand(0).getValueType() != NewVT)
3410 continue;
3411 int Op = -1;
3412 if (!Inputs[I].hasOneUse() && Shuffle->getOperand(1).isUndef() &&
3413 !Shuffle->isSplat()) {
3414 Op = 0;
3415 } else if (!Inputs[I].hasOneUse() &&
3416 !Shuffle->getOperand(1).isUndef()) {
3417 // Find the only used operand, if possible.
3418 for (int &Idx : Mask) {
3419 if (Idx == PoisonMaskElem)
3420 continue;
3421 unsigned SrcRegIdx = Idx / NewElts;
3422 if (SrcRegIdx != I)
3423 continue;
3424 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
3425 if (MaskElt == PoisonMaskElem) {
3427 continue;
3428 }
3429 int OpIdx = MaskElt / NewElts;
3430 if (Op == -1) {
3431 Op = OpIdx;
3432 continue;
3433 }
3434 if (Op != OpIdx) {
3435 Op = -1;
3436 break;
3437 }
3438 }
3439 }
3440 if (Op < 0) {
3441 // Try to check if one of the shuffle operands is used already.
3442 for (int OpIdx = 0; OpIdx < 2; ++OpIdx) {
3443 if (Shuffle->getOperand(OpIdx).isUndef())
3444 continue;
3445 auto *It = find(Inputs, Shuffle->getOperand(OpIdx));
3446 if (It == std::end(Inputs))
3447 continue;
3448 int FoundOp = std::distance(std::begin(Inputs), It);
3449 // Found that operand is used already.
3450 // 1. Fix the mask for the reused operand.
3451 for (int &Idx : Mask) {
3452 if (Idx == PoisonMaskElem)
3453 continue;
3454 unsigned SrcRegIdx = Idx / NewElts;
3455 if (SrcRegIdx != I)
3456 continue;
3457 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
3458 if (MaskElt == PoisonMaskElem) {
3460 continue;
3461 }
3462 int MaskIdx = MaskElt / NewElts;
3463 if (OpIdx == MaskIdx)
3464 Idx = MaskElt % NewElts + FoundOp * NewElts;
3465 }
3466 // 2. Set Op to the unused OpIdx.
3467 Op = (OpIdx + 1) % 2;
3468 break;
3469 }
3470 }
3471 if (Op >= 0) {
3472 Changed = true;
3473 Inputs[I] = Shuffle->getOperand(Op);
3474 // Adjust mask.
3475 for (int &Idx : Mask) {
3476 if (Idx == PoisonMaskElem)
3477 continue;
3478 unsigned SrcRegIdx = Idx / NewElts;
3479 if (SrcRegIdx != I)
3480 continue;
3481 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
3482 int OpIdx = MaskElt / NewElts;
3483 if (OpIdx != Op)
3484 continue;
3485 Idx = MaskElt % NewElts + SrcRegIdx * NewElts;
3486 }
3487 }
3488 }
3489 } while (Changed);
3490 };
3491 TryPeekThroughShufflesInputs(OrigMask);
3492 // Proces unique inputs.
3493 auto &&MakeUniqueInputs = [&Inputs, &IsConstant,
3494 NewElts](SmallVectorImpl<int> &Mask) {
3495 SetVector<SDValue> UniqueInputs;
3496 SetVector<SDValue> UniqueConstantInputs;
3497 for (const auto &I : Inputs) {
3498 if (IsConstant(I))
3499 UniqueConstantInputs.insert(I);
3500 else if (!I.isUndef())
3501 UniqueInputs.insert(I);
3502 }
3503 // Adjust mask in case of reused inputs. Also, need to insert constant
3504 // inputs at first, otherwise it affects the final outcome.
3505 if (UniqueInputs.size() != std::size(Inputs)) {
3506 auto &&UniqueVec = UniqueInputs.takeVector();
3507 auto &&UniqueConstantVec = UniqueConstantInputs.takeVector();
3508 unsigned ConstNum = UniqueConstantVec.size();
3509 for (int &Idx : Mask) {
3510 if (Idx == PoisonMaskElem)
3511 continue;
3512 unsigned SrcRegIdx = Idx / NewElts;
3513 if (Inputs[SrcRegIdx].isUndef()) {
3515 continue;
3516 }
3517 const auto It = find(UniqueConstantVec, Inputs[SrcRegIdx]);
3518 if (It != UniqueConstantVec.end()) {
3519 Idx = (Idx % NewElts) +
3520 NewElts * std::distance(UniqueConstantVec.begin(), It);
3521 assert(Idx >= 0 && "Expected defined mask idx.");
3522 continue;
3523 }
3524 const auto RegIt = find(UniqueVec, Inputs[SrcRegIdx]);
3525 assert(RegIt != UniqueVec.end() && "Cannot find non-const value.");
3526 Idx = (Idx % NewElts) +
3527 NewElts * (std::distance(UniqueVec.begin(), RegIt) + ConstNum);
3528 assert(Idx >= 0 && "Expected defined mask idx.");
3529 }
3530 copy(UniqueConstantVec, std::begin(Inputs));
3531 copy(UniqueVec, std::next(std::begin(Inputs), ConstNum));
3532 }
3533 };
3534 MakeUniqueInputs(OrigMask);
3535 SDValue OrigInputs[4];
3536 copy(Inputs, std::begin(OrigInputs));
3537 for (unsigned High = 0; High < 2; ++High) {
3538 SDValue &Output = High ? Hi : Lo;
3539
3540 // Build a shuffle mask for the output, discovering on the fly which
3541 // input vectors to use as shuffle operands.
3542 unsigned FirstMaskIdx = High * NewElts;
3543 SmallVector<int> Mask(NewElts * std::size(Inputs), PoisonMaskElem);
3544 copy(ArrayRef(OrigMask).slice(FirstMaskIdx, NewElts), Mask.begin());
3545 assert(!Output && "Expected default initialized initial value.");
3546 TryPeekThroughShufflesInputs(Mask);
3547 MakeUniqueInputs(Mask);
3548 SDValue TmpInputs[4];
3549 copy(Inputs, std::begin(TmpInputs));
3550 // Track changes in the output registers.
3551 int UsedIdx = -1;
3552 bool SecondIteration = false;
3553 auto &&AccumulateResults = [&UsedIdx, &SecondIteration](unsigned Idx) {
3554 if (UsedIdx < 0) {
3555 UsedIdx = Idx;
3556 return false;
3557 }
3558 if (UsedIdx >= 0 && static_cast<unsigned>(UsedIdx) == Idx)
3559 SecondIteration = true;
3560 return SecondIteration;
3561 };
3563 Mask, std::size(Inputs), std::size(Inputs),
3564 /*NumOfUsedRegs=*/1,
3565 [&Output, &DAG = DAG, NewVT]() { Output = DAG.getPOISON(NewVT); },
3566 [&Output, &DAG = DAG, NewVT, &DL, &Inputs,
3567 &BuildVector](ArrayRef<int> Mask, unsigned Idx, unsigned /*Unused*/) {
3568 if (Inputs[Idx]->getOpcode() == ISD::BUILD_VECTOR)
3569 Output = BuildVector(Inputs[Idx], Inputs[Idx], Mask);
3570 else
3571 Output = DAG.getVectorShuffle(NewVT, DL, Inputs[Idx],
3572 DAG.getPOISON(NewVT), Mask);
3573 Inputs[Idx] = Output;
3574 },
3575 [&AccumulateResults, &Output, &DAG = DAG, NewVT, &DL, &Inputs,
3576 &TmpInputs, &BuildVector](ArrayRef<int> Mask, unsigned Idx1,
3577 unsigned Idx2, bool /*Unused*/) {
3578 if (AccumulateResults(Idx1)) {
3579 if (Inputs[Idx1]->getOpcode() == ISD::BUILD_VECTOR &&
3580 Inputs[Idx2]->getOpcode() == ISD::BUILD_VECTOR)
3581 Output = BuildVector(Inputs[Idx1], Inputs[Idx2], Mask);
3582 else
3583 Output = DAG.getVectorShuffle(NewVT, DL, Inputs[Idx1],
3584 Inputs[Idx2], Mask);
3585 } else {
3586 if (TmpInputs[Idx1]->getOpcode() == ISD::BUILD_VECTOR &&
3587 TmpInputs[Idx2]->getOpcode() == ISD::BUILD_VECTOR)
3588 Output = BuildVector(TmpInputs[Idx1], TmpInputs[Idx2], Mask);
3589 else
3590 Output = DAG.getVectorShuffle(NewVT, DL, TmpInputs[Idx1],
3591 TmpInputs[Idx2], Mask);
3592 }
3593 Inputs[Idx1] = Output;
3594 });
3595 copy(OrigInputs, std::begin(Inputs));
3596 }
3597}
3598
3599void DAGTypeLegalizer::SplitVecRes_VAARG(SDNode *N, SDValue &Lo, SDValue &Hi) {
3600 EVT OVT = N->getValueType(0);
3601 EVT NVT = OVT.getHalfNumVectorElementsVT(*DAG.getContext());
3602 SDValue Chain = N->getOperand(0);
3603 SDValue Ptr = N->getOperand(1);
3604 SDValue SV = N->getOperand(2);
3605 SDLoc dl(N);
3606
3607 const Align Alignment =
3608 DAG.getDataLayout().getABITypeAlign(NVT.getTypeForEVT(*DAG.getContext()));
3609
3610 Lo = DAG.getVAArg(NVT, dl, Chain, Ptr, SV, Alignment.value());
3611 Hi = DAG.getVAArg(NVT, dl, Lo.getValue(1), Ptr, SV, Alignment.value());
3612 Chain = Hi.getValue(1);
3613
3614 // Modified the chain - switch anything that used the old chain to use
3615 // the new one.
3616 ReplaceValueWith(SDValue(N, 1), Chain);
3617}
3618
3619void DAGTypeLegalizer::SplitVecRes_FP_TO_XINT_SAT(SDNode *N, SDValue &Lo,
3620 SDValue &Hi) {
3621 EVT DstVTLo, DstVTHi;
3622 std::tie(DstVTLo, DstVTHi) = DAG.GetSplitDestVTs(N->getValueType(0));
3623 SDLoc dl(N);
3624
3625 SDValue SrcLo, SrcHi;
3626 EVT SrcVT = N->getOperand(0).getValueType();
3627 if (getTypeAction(SrcVT) == TargetLowering::TypeSplitVector)
3628 GetSplitVector(N->getOperand(0), SrcLo, SrcHi);
3629 else
3630 std::tie(SrcLo, SrcHi) = DAG.SplitVectorOperand(N, 0);
3631
3632 Lo = DAG.getNode(N->getOpcode(), dl, DstVTLo, SrcLo, N->getOperand(1));
3633 Hi = DAG.getNode(N->getOpcode(), dl, DstVTHi, SrcHi, N->getOperand(1));
3634}
3635
3636void DAGTypeLegalizer::SplitVecRes_VECTOR_REPEAT(SDNode *N, SDValue &Lo,
3637 SDValue &Hi) {
3638 EVT VT = N->getValueType(0);
3639 SDValue Src = N->getOperand(0);
3640 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(VT);
3641 assert(LoVT == HiVT && "Expected equal split types");
3642
3643 // Use smaller even/odd source vectors so their broadcasts can be
3644 // reinterleaved in the original lane order for every value of vscale.
3645 SDLoc DL(N);
3646 auto [SrcLo, SrcHi] = DAG.SplitVector(Src, DL);
3647 EVT SplitSrcVT = SrcLo.getValueType();
3648 SDValue Deinterleaved =
3649 DAG.getNode(ISD::VECTOR_DEINTERLEAVE, DL,
3650 DAG.getVTList(SplitSrcVT, SplitSrcVT), SrcLo, SrcHi);
3651 SDValue Even =
3652 DAG.getNode(ISD::VECTOR_REPEAT, DL, LoVT, Deinterleaved.getValue(0));
3653 SDValue Odd =
3654 DAG.getNode(ISD::VECTOR_REPEAT, DL, LoVT, Deinterleaved.getValue(1));
3655 SDValue Interleaved = DAG.getNode(ISD::VECTOR_INTERLEAVE, DL,
3656 DAG.getVTList(LoVT, LoVT), Even, Odd);
3657 Lo = Interleaved.getValue(0);
3658 Hi = Interleaved.getValue(1);
3659}
3660
3661void DAGTypeLegalizer::SplitVecRes_VECTOR_REVERSE(SDNode *N, SDValue &Lo,
3662 SDValue &Hi) {
3663 SDValue InLo, InHi;
3664 GetSplitVector(N->getOperand(0), InLo, InHi);
3665 SDLoc DL(N);
3666
3667 Lo = DAG.getNode(ISD::VECTOR_REVERSE, DL, InHi.getValueType(), InHi);
3668 Hi = DAG.getNode(ISD::VECTOR_REVERSE, DL, InLo.getValueType(), InLo);
3669}
3670
3671void DAGTypeLegalizer::SplitVecRes_VECTOR_SPLICE(SDNode *N, SDValue &Lo,
3672 SDValue &Hi) {
3673 SDLoc DL(N);
3674
3675 SDValue Expanded = TLI.expandVectorSplice(N, DAG);
3676 std::tie(Lo, Hi) = DAG.SplitVector(Expanded, DL);
3677}
3678
3679void DAGTypeLegalizer::SplitVecRes_VP_REVERSE(SDNode *N, SDValue &Lo,
3680 SDValue &Hi) {
3681 EVT VT = N->getValueType(0);
3682 SDValue Val = N->getOperand(0);
3683 SDValue Mask = N->getOperand(1);
3684 SDValue EVL = N->getOperand(2);
3685 SDLoc DL(N);
3686
3687 // The stack round-trip uses a byte stride, so a sub-byte element (e.g. i1)
3688 // would get stride 0 and alias every lane. Widen to a byte integer, reverse,
3689 // then truncate back.
3690 EVT OrigVT = VT;
3691 if (!VT.getVectorElementType().isByteSized()) {
3692 EVT WideEltVT = VT.getVectorElementType().changeTypeToInteger();
3693 WideEltVT = WideEltVT.getRoundIntegerType(*DAG.getContext());
3694 VT = VT.changeVectorElementType(*DAG.getContext(), WideEltVT);
3695 Val = DAG.getNode(ISD::ANY_EXTEND, DL, VT, Val);
3696 }
3697
3698 // Fallback to VP_STRIDED_STORE to stack followed by VP_LOAD.
3699 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
3700
3701 EVT MemVT = EVT::getVectorVT(*DAG.getContext(), VT.getVectorElementType(),
3703 SDValue StackPtr = DAG.CreateStackTemporary(MemVT.getStoreSize(), Alignment);
3704 EVT PtrVT = StackPtr.getValueType();
3705 auto &MF = DAG.getMachineFunction();
3706 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
3707 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
3708
3709 MachineMemOperand *StoreMMO = DAG.getMachineFunction().getMachineMemOperand(
3711 Alignment);
3712 MachineMemOperand *LoadMMO = DAG.getMachineFunction().getMachineMemOperand(
3714 Alignment);
3715
3716 unsigned EltWidth = VT.getScalarSizeInBits() / 8;
3717 SDValue NumElemMinus1 =
3718 DAG.getNode(ISD::SUB, DL, PtrVT, DAG.getZExtOrTrunc(EVL, DL, PtrVT),
3719 DAG.getConstant(1, DL, PtrVT));
3720 SDValue StartOffset = DAG.getNode(ISD::MUL, DL, PtrVT, NumElemMinus1,
3721 DAG.getConstant(EltWidth, DL, PtrVT));
3722 SDValue StorePtr = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, StartOffset);
3723 SDValue Stride = DAG.getConstant(-(int64_t)EltWidth, DL, PtrVT);
3724
3725 SDValue TrueMask = DAG.getBoolConstant(true, DL, Mask.getValueType(), VT);
3726 SDValue Store = DAG.getStridedStoreVP(DAG.getEntryNode(), DL, Val, StorePtr,
3727 DAG.getPOISON(PtrVT), Stride, TrueMask,
3728 EVL, MemVT, StoreMMO, ISD::UNINDEXED);
3729
3730 SDValue Load = DAG.getLoadVP(VT, DL, Store, StackPtr, Mask, EVL, LoadMMO);
3731
3732 // Truncate back if we widened above.
3733 if (OrigVT != VT)
3734 Load = DAG.getNode(ISD::TRUNCATE, DL, OrigVT, Load);
3735
3736 std::tie(Lo, Hi) = DAG.SplitVector(Load, DL);
3737}
3738
3739void DAGTypeLegalizer::SplitVecRes_VP_SPLICE(SDNode *N, SDValue &Lo,
3740 SDValue &Hi) {
3741 EVT VT = N->getValueType(0);
3742 SDValue V1 = N->getOperand(0);
3743 SDValue V2 = N->getOperand(1);
3744 int64_t Imm = cast<ConstantSDNode>(N->getOperand(2))->getSExtValue();
3745 SDValue Mask = N->getOperand(3);
3746 SDValue EVL1 = N->getOperand(4);
3747 SDValue EVL2 = N->getOperand(5);
3748 SDLoc DL(N);
3749
3750 // Since EVL2 is considered the real VL it gets promoted during
3751 // SelectionDAGBuilder. Promote EVL1 here if needed.
3752 if (getTypeAction(EVL1.getValueType()) == TargetLowering::TypePromoteInteger)
3753 EVL1 = ZExtPromotedInteger(EVL1);
3754
3755 // The stack splice addresses elements by byte offset/stride, which breaks for
3756 // a sub-byte element (e.g. i1): getVectorElementPointer asserts and the
3757 // stride is 0. Widen to a byte integer, splice, then truncate back.
3758 EVT OrigVT = VT;
3759 if (!VT.getVectorElementType().isByteSized()) {
3760 EVT WideEltVT = VT.getVectorElementType().changeTypeToInteger();
3761 WideEltVT = WideEltVT.getRoundIntegerType(*DAG.getContext());
3762 VT = VT.changeVectorElementType(*DAG.getContext(), WideEltVT);
3763 V1 = DAG.getNode(ISD::ANY_EXTEND, DL, VT, V1);
3764 V2 = DAG.getNode(ISD::ANY_EXTEND, DL, VT, V2);
3765 }
3766
3767 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
3768
3769 EVT MemVT = EVT::getVectorVT(*DAG.getContext(), VT.getVectorElementType(),
3770 VT.getVectorElementCount() * 2);
3771 SDValue StackPtr = DAG.CreateStackTemporary(MemVT.getStoreSize(), Alignment);
3772 EVT PtrVT = StackPtr.getValueType();
3773 auto &MF = DAG.getMachineFunction();
3774 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
3775 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
3776
3777 MachineMemOperand *StoreMMO = DAG.getMachineFunction().getMachineMemOperand(
3779 Alignment);
3780 MachineMemOperand *LoadMMO = DAG.getMachineFunction().getMachineMemOperand(
3782 Alignment);
3783
3784 SDValue EltByteSize =
3785 DAG.getTypeSize(DL, PtrVT, VT.getVectorElementType().getStoreSize());
3786 SDValue EVL1Ptr = DAG.getZExtOrTrunc(EVL1, DL, PtrVT);
3787 SDValue EVL1Bytes = DAG.getNode(ISD::MUL, DL, PtrVT, EVL1Ptr, EltByteSize);
3788 // Clip EVL1Bytes to make sure we stay within the stack object.
3789 SDValue VTBytes = DAG.getTypeSize(DL, PtrVT, VT.getStoreSize());
3790 EVL1Bytes = DAG.getNode(ISD::UMIN, DL, PtrVT, EVL1Bytes, VTBytes);
3791 SDValue StackPtr2 = DAG.getMemBasePlusOffset(StackPtr, EVL1Bytes, DL);
3792 SDValue PoisonPtr = DAG.getPOISON(PtrVT);
3793
3794 SDValue TrueMask = DAG.getBoolConstant(true, DL, Mask.getValueType(), VT);
3795 SDValue StoreV1 =
3796 DAG.getStoreVP(DAG.getEntryNode(), DL, V1, StackPtr, PoisonPtr, TrueMask,
3797 EVL1, V1.getValueType(), StoreMMO, ISD::UNINDEXED);
3798
3800 DAG.getStoreVP(StoreV1, DL, V2, StackPtr2, PoisonPtr, TrueMask, EVL2,
3801 V2.getValueType(), StoreMMO, ISD::UNINDEXED);
3802
3803 SDValue Load;
3804 if (Imm >= 0) {
3805 StackPtr = TLI.getVectorElementPointer(DAG, StackPtr, VT, N->getOperand(2));
3806 Load = DAG.getLoadVP(VT, DL, StoreV2, StackPtr, Mask, EVL2, LoadMMO);
3807 } else {
3808 uint64_t TrailingElts = -Imm;
3809 unsigned EltWidth = VT.getScalarSizeInBits() / 8;
3810 SDValue TrailingBytes = DAG.getConstant(TrailingElts * EltWidth, DL, PtrVT);
3811
3812 // Make sure TrailingBytes doesn't exceed the size of vec1.
3813 SDValue OffsetToV2 = DAG.getNode(ISD::SUB, DL, PtrVT, StackPtr2, StackPtr);
3814 TrailingBytes =
3815 DAG.getNode(ISD::UMIN, DL, PtrVT, TrailingBytes, OffsetToV2);
3816
3817 // Calculate the start address of the spliced result.
3818 StackPtr2 = DAG.getNode(ISD::SUB, DL, PtrVT, StackPtr2, TrailingBytes);
3819 Load = DAG.getLoadVP(VT, DL, StoreV2, StackPtr2, Mask, EVL2, LoadMMO);
3820 }
3821
3822 // Truncate back if we widened above.
3823 if (OrigVT != VT)
3824 Load = DAG.getNode(ISD::TRUNCATE, DL, OrigVT, Load);
3825
3826 EVT LoVT, HiVT;
3827 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(OrigVT);
3828 Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, LoVT, Load,
3829 DAG.getVectorIdxConstant(0, DL));
3830 Hi =
3831 DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, HiVT, Load,
3832 DAG.getVectorIdxConstant(LoVT.getVectorMinNumElements(), DL));
3833}
3834
3835void DAGTypeLegalizer::SplitVecRes_PARTIAL_REDUCE_MLA(SDNode *N, SDValue &Lo,
3836 SDValue &Hi) {
3837 SDLoc DL(N);
3838 SDValue Acc = N->getOperand(0);
3839 SDValue Input1 = N->getOperand(1);
3840 SDValue Input2 = N->getOperand(2);
3841
3842 SDValue AccLo, AccHi;
3843 GetSplitVector(Acc, AccLo, AccHi);
3844 unsigned Opcode = N->getOpcode();
3845
3846 // If the input types don't need splitting, just accumulate into the
3847 // low part of the accumulator.
3848 if (getTypeAction(Input1.getValueType()) != TargetLowering::TypeSplitVector) {
3849 Lo = DAG.getNode(Opcode, DL, AccLo.getValueType(), AccLo, Input1, Input2);
3850 Hi = AccHi;
3851 return;
3852 }
3853
3854 SDValue Input1Lo, Input1Hi;
3855 SDValue Input2Lo, Input2Hi;
3856 GetSplitVector(Input1, Input1Lo, Input1Hi);
3857 GetSplitVector(Input2, Input2Lo, Input2Hi);
3858 EVT ResultVT = AccLo.getValueType();
3859
3860 Lo = DAG.getNode(Opcode, DL, ResultVT, AccLo, Input1Lo, Input2Lo);
3861 Hi = DAG.getNode(Opcode, DL, ResultVT, AccHi, Input1Hi, Input2Hi);
3862}
3863
3864void DAGTypeLegalizer::SplitVecRes_GET_ACTIVE_LANE_MASK(SDNode *N, SDValue &Lo,
3865 SDValue &Hi) {
3866 SDLoc DL(N);
3867 SDValue Op0 = N->getOperand(0);
3868 SDValue Op1 = N->getOperand(1);
3869 EVT OpVT = Op0.getValueType();
3870
3871 EVT LoVT, HiVT;
3872 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
3873
3874 Lo = DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, DL, LoVT, Op0, Op1);
3875 SDValue LoElts = DAG.getElementCount(DL, OpVT, LoVT.getVectorElementCount());
3876 SDValue HiStartVal = DAG.getNode(ISD::UADDSAT, DL, OpVT, Op0, LoElts);
3877 Hi = DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, DL, HiVT, HiStartVal, Op1);
3878}
3879
3880void DAGTypeLegalizer::SplitVecRes_VECTOR_MATCH(SDNode *N, SDValue &Lo,
3881 SDValue &Hi) {
3882 SDValue SourceLo, SourceHi;
3883 GetSplitVector(N->getOperand(0), SourceLo, SourceHi);
3884 SDValue MaskLo, MaskHi;
3885 GetSplitVector(N->getOperand(2), MaskLo, MaskHi);
3886 SDLoc DL(N);
3887
3888 Lo = DAG.getNode(ISD::VECTOR_MATCH, DL, MaskLo.getValueType(), SourceLo,
3889 N->getOperand(1), MaskLo, N->getFlags());
3890 Hi = DAG.getNode(ISD::VECTOR_MATCH, DL, MaskHi.getValueType(), SourceHi,
3891 N->getOperand(1), MaskHi, N->getFlags());
3892}
3893
3894void DAGTypeLegalizer::SplitVecRes_VECTOR_DEINTERLEAVE(SDNode *N) {
3895 unsigned Factor = N->getNumOperands();
3896
3897 SmallVector<SDValue, 8> Ops(Factor * 2);
3898 for (unsigned i = 0; i != Factor; ++i) {
3899 SDValue OpLo, OpHi;
3900 GetSplitVector(N->getOperand(i), OpLo, OpHi);
3901 Ops[i * 2] = OpLo;
3902 Ops[i * 2 + 1] = OpHi;
3903 }
3904
3905 SmallVector<EVT, 8> VTs(Factor, Ops[0].getValueType());
3906
3907 SDLoc DL(N);
3908 SDValue ResLo = DAG.getNode(ISD::VECTOR_DEINTERLEAVE, DL, VTs,
3909 ArrayRef(Ops).slice(0, Factor));
3910 SDValue ResHi = DAG.getNode(ISD::VECTOR_DEINTERLEAVE, DL, VTs,
3911 ArrayRef(Ops).slice(Factor, Factor));
3912
3913 for (unsigned i = 0; i != Factor; ++i)
3914 SetSplitVector(SDValue(N, i), ResLo.getValue(i), ResHi.getValue(i));
3915}
3916
3917void DAGTypeLegalizer::SplitVecRes_VECTOR_INTERLEAVE(SDNode *N) {
3918 unsigned Factor = N->getNumOperands();
3919
3920 SmallVector<SDValue, 8> Ops(Factor * 2);
3921 for (unsigned i = 0; i != Factor; ++i) {
3922 SDValue OpLo, OpHi;
3923 GetSplitVector(N->getOperand(i), OpLo, OpHi);
3924 Ops[i] = OpLo;
3925 Ops[i + Factor] = OpHi;
3926 }
3927
3928 SmallVector<EVT, 8> VTs(Factor, Ops[0].getValueType());
3929
3930 SDLoc DL(N);
3931 SDValue Res[] = {DAG.getNode(ISD::VECTOR_INTERLEAVE, DL, VTs,
3932 ArrayRef(Ops).slice(0, Factor)),
3933 DAG.getNode(ISD::VECTOR_INTERLEAVE, DL, VTs,
3934 ArrayRef(Ops).slice(Factor, Factor))};
3935
3936 for (unsigned i = 0; i != Factor; ++i) {
3937 unsigned IdxLo = 2 * i;
3938 unsigned IdxHi = 2 * i + 1;
3939 SetSplitVector(SDValue(N, i), Res[IdxLo / Factor].getValue(IdxLo % Factor),
3940 Res[IdxHi / Factor].getValue(IdxHi % Factor));
3941 }
3942}
3943
3944//===----------------------------------------------------------------------===//
3945// Operand Vector Splitting
3946//===----------------------------------------------------------------------===//
3947
3948/// This method is called when the specified operand of the specified node is
3949/// found to need vector splitting. At this point, all of the result types of
3950/// the node are known to be legal, but other operands of the node may need
3951/// legalization as well as the specified one.
3952bool DAGTypeLegalizer::SplitVectorOperand(SDNode *N, unsigned OpNo) {
3953 LLVM_DEBUG(dbgs() << "Split node operand: "; N->dump(&DAG));
3954 SDValue Res = SDValue();
3955
3956 // See if the target wants to custom split this node.
3957 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
3958 return false;
3959
3960 switch (N->getOpcode()) {
3961 default:
3962#ifndef NDEBUG
3963 dbgs() << "SplitVectorOperand Op #" << OpNo << ": ";
3964 N->dump(&DAG);
3965 dbgs() << "\n";
3966#endif
3967 report_fatal_error("Do not know how to split this operator's "
3968 "operand!\n");
3969
3970 case ISD::STRICT_FSETCC:
3972 case ISD::SETCC: Res = SplitVecOp_VSETCC(N); break;
3973 case ISD::BITCAST: Res = SplitVecOp_BITCAST(N); break;
3974 case ISD::EXTRACT_SUBVECTOR: Res = SplitVecOp_EXTRACT_SUBVECTOR(N); break;
3975 case ISD::INSERT_SUBVECTOR: Res = SplitVecOp_INSERT_SUBVECTOR(N, OpNo); break;
3976 case ISD::EXTRACT_VECTOR_ELT:Res = SplitVecOp_EXTRACT_VECTOR_ELT(N); break;
3977 case ISD::CONCAT_VECTORS: Res = SplitVecOp_CONCAT_VECTORS(N); break;
3979 Res = SplitVecOp_VECTOR_FIND_LAST_ACTIVE(N);
3980 break;
3981 case ISD::TRUNCATE:
3982 Res = SplitVecOp_TruncateHelper(N);
3983 break;
3985 case ISD::FP_ROUND:
3988 Res = SplitVecOp_FP_ROUND(N);
3989 break;
3990 case ISD::FCOPYSIGN: Res = SplitVecOp_FPOpDifferentTypes(N); break;
3991 case ISD::STORE:
3992 Res = SplitVecOp_STORE(cast<StoreSDNode>(N), OpNo);
3993 break;
3994 case ISD::ATOMIC_STORE:
3995 Res = SplitVecOp_ATOMIC_STORE(cast<AtomicSDNode>(N));
3996 break;
3997 case ISD::VP_STORE:
3998 Res = SplitVecOp_VP_STORE(cast<VPStoreSDNode>(N), OpNo);
3999 break;
4000 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
4001 Res = SplitVecOp_VP_STRIDED_STORE(cast<VPStridedStoreSDNode>(N), OpNo);
4002 break;
4003 case ISD::MSTORE:
4004 Res = SplitVecOp_MSTORE(cast<MaskedStoreSDNode>(N), OpNo);
4005 break;
4006 case ISD::MSCATTER:
4007 case ISD::VP_SCATTER:
4008 Res = SplitVecOp_Scatter(cast<MemSDNode>(N), OpNo);
4009 break;
4010 case ISD::MGATHER:
4011 case ISD::VP_GATHER:
4012 Res = SplitVecOp_Gather(cast<MemSDNode>(N), OpNo);
4013 break;
4014 case ISD::VSELECT:
4015 Res = SplitVecOp_VSELECT(N, OpNo);
4016 break;
4017 case ISD::MASKED_UDIV:
4018 case ISD::MASKED_SDIV:
4019 case ISD::MASKED_UREM:
4020 case ISD::MASKED_SREM:
4021 Res = SplitVecOp_MaskedBinOp(N, OpNo);
4022 break;
4024 Res = SplitVecOp_VECTOR_COMPRESS(N, OpNo);
4025 break;
4028 case ISD::SINT_TO_FP:
4029 case ISD::UINT_TO_FP:
4030 if (N->getValueType(0).bitsLT(
4031 N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType()))
4032 Res = SplitVecOp_TruncateHelper(N);
4033 else
4034 Res = SplitVecOp_UnaryOp(N);
4035 break;
4038 Res = SplitVecOp_FP_TO_XINT_SAT(N);
4039 break;
4040 case ISD::FP_TO_SINT:
4041 case ISD::FP_TO_UINT:
4045 case ISD::FP_EXTEND:
4046 case ISD::SIGN_EXTEND:
4047 case ISD::ZERO_EXTEND:
4048 case ISD::ANY_EXTEND:
4049 case ISD::FTRUNC:
4050 case ISD::LROUND:
4051 case ISD::LLROUND:
4052 case ISD::LRINT:
4053 case ISD::LLRINT:
4054 Res = SplitVecOp_UnaryOp(N);
4055 break;
4056 case ISD::FLDEXP:
4057 Res = SplitVecOp_FPOpDifferentTypes(N);
4058 break;
4059
4060 case ISD::SCMP:
4061 case ISD::UCMP:
4062 Res = SplitVecOp_CMP(N);
4063 break;
4064
4065 case ISD::FAKE_USE:
4066 Res = SplitVecOp_FAKE_USE(N);
4067 break;
4071 Res = SplitVecOp_ExtVecInRegOp(N);
4072 break;
4073
4076 case ISD::VECREDUCE_ADD:
4077 case ISD::VECREDUCE_MUL:
4078 case ISD::VECREDUCE_AND:
4079 case ISD::VECREDUCE_OR:
4080 case ISD::VECREDUCE_XOR:
4091 Res = SplitVecOp_VECREDUCE(N, OpNo);
4092 break;
4095 Res = SplitVecOp_VECREDUCE_SEQ(N);
4096 break;
4097 case ISD::VP_REDUCE_FADD:
4098 case ISD::VP_REDUCE_SEQ_FADD:
4099 case ISD::VP_REDUCE_FMUL:
4100 case ISD::VP_REDUCE_SEQ_FMUL:
4101 case ISD::VP_REDUCE_ADD:
4102 case ISD::VP_REDUCE_MUL:
4103 case ISD::VP_REDUCE_AND:
4104 case ISD::VP_REDUCE_OR:
4105 case ISD::VP_REDUCE_XOR:
4106 case ISD::VP_REDUCE_SMAX:
4107 case ISD::VP_REDUCE_SMIN:
4108 case ISD::VP_REDUCE_UMAX:
4109 case ISD::VP_REDUCE_UMIN:
4110 case ISD::VP_REDUCE_FMAX:
4111 case ISD::VP_REDUCE_FMIN:
4112 case ISD::VP_REDUCE_FMAXIMUM:
4113 case ISD::VP_REDUCE_FMINIMUM:
4114 Res = SplitVecOp_VP_REDUCE(N, OpNo);
4115 break;
4116 case ISD::CTTZ_ELTS:
4118 Res = SplitVecOp_CttzElts(N);
4119 break;
4120 case ISD::VP_CTTZ_ELTS:
4121 case ISD::VP_CTTZ_ELTS_ZERO_POISON:
4122 Res = SplitVecOp_VP_CttzElements(N);
4123 break;
4125 Res = SplitVecOp_VECTOR_HISTOGRAM(N);
4126 break;
4131 Res = SplitVecOp_PARTIAL_REDUCE_MLA(N);
4132 break;
4133 case ISD::VECTOR_MATCH:
4134 Res = SplitVecOp_VECTOR_MATCH(N, OpNo);
4135 break;
4136 }
4137
4138 // If the result is null, the sub-method took care of registering results etc.
4139 if (!Res.getNode()) return false;
4140
4141 // If the result is N, the sub-method updated N in place. Tell the legalizer
4142 // core about this.
4143 if (Res.getNode() == N)
4144 return true;
4145
4146 if (N->isStrictFPOpcode())
4147 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
4148 "Invalid operand expansion");
4149 else
4150 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
4151 "Invalid operand expansion");
4152
4153 ReplaceValueWith(SDValue(N, 0), Res);
4154 return false;
4155}
4156
4157SDValue DAGTypeLegalizer::SplitVecOp_VECTOR_FIND_LAST_ACTIVE(SDNode *N) {
4158 SDLoc DL(N);
4159
4160 SDValue LoMask, HiMask;
4161 GetSplitVector(N->getOperand(0), LoMask, HiMask);
4162
4163 EVT VT = N->getValueType(0);
4164 EVT SplitVT = LoMask.getValueType();
4165 ElementCount SplitEC = SplitVT.getVectorElementCount();
4166
4167 // Find the last active in both the low and the high masks.
4168 SDValue LoFind = DAG.getNode(ISD::VECTOR_FIND_LAST_ACTIVE, DL, VT, LoMask);
4169 SDValue HiFind = DAG.getNode(ISD::VECTOR_FIND_LAST_ACTIVE, DL, VT, HiMask);
4170
4171 // Check if any lane is active in the high mask.
4172 // FIXME: This would not be necessary if VECTOR_FIND_LAST_ACTIVE returned a
4173 // sentinel value for "none active".
4174 SDValue AnyHiActive = DAG.getNode(ISD::VECREDUCE_OR, DL, MVT::i1, HiMask);
4175 SDValue Cond = DAG.getBoolExtOrTrunc(AnyHiActive, DL,
4176 getSetCCResultType(MVT::i1), MVT::i1);
4177
4178 // Return: AnyHiActive ? (HiFind + SplitEC) : LoFind;
4179 return DAG.getNode(ISD::SELECT, DL, VT, Cond,
4180 DAG.getNode(ISD::ADD, DL, VT, HiFind,
4181 DAG.getElementCount(DL, VT, SplitEC)),
4182 LoFind);
4183}
4184
4185SDValue DAGTypeLegalizer::SplitVecOp_VSELECT(SDNode *N, unsigned OpNo) {
4186 // The only possibility for an illegal operand is the mask, since result type
4187 // legalization would have handled this node already otherwise.
4188 assert(OpNo == 0 && "Illegal operand must be mask");
4189
4190 SDValue Mask = N->getOperand(0);
4191 SDValue Src0 = N->getOperand(1);
4192 SDValue Src1 = N->getOperand(2);
4193 EVT Src0VT = Src0.getValueType();
4194 SDLoc DL(N);
4195 assert(Mask.getValueType().isVector() && "VSELECT without a vector mask?");
4196
4197 SDValue Lo, Hi;
4198 GetSplitVector(N->getOperand(0), Lo, Hi);
4199 assert(Lo.getValueType() == Hi.getValueType() &&
4200 "Lo and Hi have differing types");
4201
4202 EVT LoOpVT, HiOpVT;
4203 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(Src0VT);
4204 assert(LoOpVT == HiOpVT && "Asymmetric vector split?");
4205
4206 SDValue LoOp0, HiOp0, LoOp1, HiOp1, LoMask, HiMask;
4207 std::tie(LoOp0, HiOp0) = DAG.SplitVector(Src0, DL);
4208 std::tie(LoOp1, HiOp1) = DAG.SplitVector(Src1, DL);
4209 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
4210
4211 SDValue LoSelect =
4212 DAG.getNode(ISD::VSELECT, DL, LoOpVT, LoMask, LoOp0, LoOp1);
4213 SDValue HiSelect =
4214 DAG.getNode(ISD::VSELECT, DL, HiOpVT, HiMask, HiOp0, HiOp1);
4215
4216 return DAG.getNode(ISD::CONCAT_VECTORS, DL, Src0VT, LoSelect, HiSelect);
4217}
4218
4219SDValue DAGTypeLegalizer::SplitVecOp_MaskedBinOp(SDNode *N, unsigned OpNo) {
4220 assert(OpNo == 2 && "Illegal operand must be mask");
4221
4222 SDLoc DL(N);
4223 auto [LHSLo, LHSHi] = DAG.SplitVector(N->getOperand(0), DL);
4224 auto [RHSLo, RHSHi] = DAG.SplitVector(N->getOperand(1), DL);
4225 SDValue MaskLo, MaskHi;
4226 GetSplitVector(N->getOperand(2), MaskLo, MaskHi);
4227
4228 SDValue Lo = DAG.getNode(N->getOpcode(), DL, LHSLo.getValueType(), LHSLo,
4229 RHSLo, MaskLo, N->getFlags());
4230 SDValue Hi = DAG.getNode(N->getOpcode(), DL, LHSHi.getValueType(), LHSHi,
4231 RHSHi, MaskHi, N->getFlags());
4232 return DAG.getNode(ISD::CONCAT_VECTORS, DL, N->getValueType(0), Lo, Hi);
4233}
4234
4235SDValue DAGTypeLegalizer::SplitVecOp_VECTOR_COMPRESS(SDNode *N, unsigned OpNo) {
4236 // The only possibility for an illegal operand is the mask, since result type
4237 // legalization would have handled this node already otherwise.
4238 assert(OpNo == 1 && "Illegal operand must be mask");
4239
4240 // To split the mask, we need to split the result type too, so we can just
4241 // reuse that logic here.
4242 SDValue Lo, Hi;
4243 SplitVecRes_VECTOR_COMPRESS(N, Lo, Hi);
4244
4245 EVT VecVT = N->getValueType(0);
4246 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), VecVT, Lo, Hi);
4247}
4248
4249SDValue DAGTypeLegalizer::SplitVecOp_VECREDUCE(SDNode *N, unsigned OpNo) {
4250 EVT ResVT = N->getValueType(0);
4251 SDValue Lo, Hi;
4252 SDLoc dl(N);
4253
4254 SDValue VecOp = N->getOperand(OpNo);
4255 EVT VecVT = VecOp.getValueType();
4256 assert(VecVT.isVector() && "Can only split reduce vector operand");
4257 GetSplitVector(VecOp, Lo, Hi);
4258 EVT LoOpVT, HiOpVT;
4259 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(VecVT);
4260
4261 // Use the appropriate scalar instruction on the split subvectors before
4262 // reducing the now partially reduced smaller vector.
4263 unsigned CombineOpc = ISD::getVecReduceBaseOpcode(N->getOpcode());
4264 SDValue Partial = DAG.getNode(CombineOpc, dl, LoOpVT, Lo, Hi, N->getFlags());
4265 return DAG.getNode(N->getOpcode(), dl, ResVT, Partial, N->getFlags());
4266}
4267
4268SDValue DAGTypeLegalizer::SplitVecOp_VECREDUCE_SEQ(SDNode *N) {
4269 EVT ResVT = N->getValueType(0);
4270 SDValue Lo, Hi;
4271 SDLoc dl(N);
4272
4273 SDValue AccOp = N->getOperand(0);
4274 SDValue VecOp = N->getOperand(1);
4275 SDNodeFlags Flags = N->getFlags();
4276
4277 EVT VecVT = VecOp.getValueType();
4278 assert(VecVT.isVector() && "Can only split reduce vector operand");
4279 GetSplitVector(VecOp, Lo, Hi);
4280 EVT LoOpVT, HiOpVT;
4281 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(VecVT);
4282
4283 // Reduce low half.
4284 SDValue Partial = DAG.getNode(N->getOpcode(), dl, ResVT, AccOp, Lo, Flags);
4285
4286 // Reduce high half, using low half result as initial value.
4287 return DAG.getNode(N->getOpcode(), dl, ResVT, Partial, Hi, Flags);
4288}
4289
4290SDValue DAGTypeLegalizer::SplitVecOp_VP_REDUCE(SDNode *N, unsigned OpNo) {
4291 assert(N->isVPOpcode() && "Expected VP opcode");
4292 assert(OpNo == 1 && "Can only split reduce vector operand");
4293
4294 unsigned Opc = N->getOpcode();
4295 EVT ResVT = N->getValueType(0);
4296 SDValue Lo, Hi;
4297 SDLoc dl(N);
4298
4299 SDValue VecOp = N->getOperand(OpNo);
4300 EVT VecVT = VecOp.getValueType();
4301 assert(VecVT.isVector() && "Can only split reduce vector operand");
4302 GetSplitVector(VecOp, Lo, Hi);
4303
4304 SDValue MaskLo, MaskHi;
4305 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(2));
4306
4307 SDValue EVLLo, EVLHi;
4308 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(N->getOperand(3), VecVT, dl);
4309
4310 const SDNodeFlags Flags = N->getFlags();
4311
4312 SDValue ResLo =
4313 DAG.getNode(Opc, dl, ResVT, {N->getOperand(0), Lo, MaskLo, EVLLo}, Flags);
4314 return DAG.getNode(Opc, dl, ResVT, {ResLo, Hi, MaskHi, EVLHi}, Flags);
4315}
4316
4317SDValue DAGTypeLegalizer::SplitVecOp_UnaryOp(SDNode *N) {
4318 // The result has a legal vector type, but the input needs splitting.
4319 EVT ResVT = N->getValueType(0);
4320 SDValue Lo, Hi;
4321 SDLoc dl(N);
4322 GetSplitVector(N->getOperand(N->isStrictFPOpcode() ? 1 : 0), Lo, Hi);
4323 EVT InVT = Lo.getValueType();
4324
4325 EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
4326 InVT.getVectorElementCount());
4327
4328 if (N->isStrictFPOpcode()) {
4329 Lo = DAG.getNode(N->getOpcode(), dl, {OutVT, MVT::Other},
4330 {N->getOperand(0), Lo});
4331 Hi = DAG.getNode(N->getOpcode(), dl, {OutVT, MVT::Other},
4332 {N->getOperand(0), Hi});
4333
4334 // Build a factor node to remember that this operation is independent
4335 // of the other one.
4336 SDValue Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
4337 Hi.getValue(1));
4338
4339 // Legalize the chain result - switch anything that used the old chain to
4340 // use the new one.
4341 ReplaceValueWith(SDValue(N, 1), Ch);
4342 } else {
4343 Lo = DAG.getNode(N->getOpcode(), dl, OutVT, Lo);
4344 Hi = DAG.getNode(N->getOpcode(), dl, OutVT, Hi);
4345 }
4346
4347 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
4348}
4349
4350// Split a FAKE_USE use of a vector into FAKE_USEs of hi and lo part.
4351SDValue DAGTypeLegalizer::SplitVecOp_FAKE_USE(SDNode *N) {
4352 SDValue Lo, Hi;
4353 GetSplitVector(N->getOperand(1), Lo, Hi);
4354 SDValue Chain =
4355 DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, N->getOperand(0), Lo);
4356 return DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, Chain, Hi);
4357}
4358
4359SDValue DAGTypeLegalizer::SplitVecOp_BITCAST(SDNode *N) {
4360 // For example, i64 = BITCAST v4i16 on alpha. Typically the vector will
4361 // end up being split all the way down to individual components. Convert the
4362 // split pieces into integers and reassemble.
4363 EVT ResVT = N->getValueType(0);
4364 SDValue Lo, Hi;
4365 GetSplitVector(N->getOperand(0), Lo, Hi);
4366 SDLoc dl(N);
4367
4368 if (ResVT.isScalableVector()) {
4369 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(ResVT);
4370 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
4371 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
4372 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
4373 }
4374
4375 Lo = BitConvertToInteger(Lo);
4376 Hi = BitConvertToInteger(Hi);
4377
4378 if (DAG.getDataLayout().isBigEndian())
4379 std::swap(Lo, Hi);
4380
4381 return DAG.getNode(ISD::BITCAST, dl, ResVT, JoinIntegers(Lo, Hi));
4382}
4383
4384SDValue DAGTypeLegalizer::SplitVecOp_INSERT_SUBVECTOR(SDNode *N,
4385 unsigned OpNo) {
4386 assert(OpNo == 1 && "Invalid OpNo; can only split SubVec.");
4387 // We know that the result type is legal.
4388 EVT ResVT = N->getValueType(0);
4389
4390 SDValue Vec = N->getOperand(0);
4391 SDValue SubVec = N->getOperand(1);
4392 SDValue Idx = N->getOperand(2);
4393 SDLoc dl(N);
4394
4395 SDValue Lo, Hi;
4396 GetSplitVector(SubVec, Lo, Hi);
4397
4398 uint64_t IdxVal = Idx->getAsZExtVal();
4400
4401 SDValue FirstInsertion =
4402 DAG.getNode(ISD::INSERT_SUBVECTOR, dl, ResVT, Vec, Lo, Idx);
4403 SDValue SecondInsertion =
4404 DAG.getNode(ISD::INSERT_SUBVECTOR, dl, ResVT, FirstInsertion, Hi,
4405 DAG.getVectorIdxConstant(IdxVal + LoElts, dl));
4406
4407 return SecondInsertion;
4408}
4409
4410SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
4411 // We know that the extracted result type is legal.
4412 EVT SubVT = N->getValueType(0);
4413 SDValue Idx = N->getOperand(1);
4414 SDLoc dl(N);
4415 SDValue Lo, Hi;
4416
4417 GetSplitVector(N->getOperand(0), Lo, Hi);
4418
4419 ElementCount LoElts = Lo.getValueType().getVectorElementCount();
4420 // Note: For scalable vectors, the index is scaled by vscale.
4421 ElementCount IdxVal =
4422 ElementCount::get(Idx->getAsZExtVal(), SubVT.isScalableVector());
4423 uint64_t IdxValMin = IdxVal.getKnownMinValue();
4424
4425 EVT SrcVT = N->getOperand(0).getValueType();
4426 ElementCount NumResultElts = SubVT.getVectorElementCount();
4427
4428 // If the extracted elements are all in the low half, do a simple extract.
4429 if (ElementCount::isKnownLE(IdxVal + NumResultElts, LoElts))
4430 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, SubVT, Lo, Idx);
4431
4432 unsigned LoEltsMin = LoElts.getKnownMinValue();
4433 if (IdxValMin < LoEltsMin && SubVT.isFixedLengthVector() &&
4434 SrcVT.isFixedLengthVector()) {
4435 // Extracted subvector crosses vector split, so we need to blend the two
4436 // halves.
4437 // TODO: May be able to emit partial extract_subvector.
4439 Elts.reserve(NumResultElts.getFixedValue());
4440
4441 // This is not valid for scalable vectors. If SubVT is scalable, this is the
4442 // same as unrolling a scalable dimension (invalid). If ScrVT is scalable,
4443 // `Lo[LoEltsMin]` may not be the last element of `Lo`.
4444 DAG.ExtractVectorElements(Lo, Elts, /*Start=*/IdxValMin,
4445 /*Count=*/LoEltsMin - IdxValMin);
4446 DAG.ExtractVectorElements(Hi, Elts, /*Start=*/0,
4447 /*Count=*/SubVT.getVectorNumElements() -
4448 Elts.size());
4449 return DAG.getBuildVector(SubVT, dl, Elts);
4450 }
4451
4452 if (SubVT.isScalableVector() == SrcVT.isScalableVector()) {
4453 ElementCount ExtractIdx = IdxVal - LoElts;
4454 if (ExtractIdx.isKnownMultipleOf(NumResultElts))
4455 return DAG.getExtractSubvector(dl, SubVT, Hi,
4456 ExtractIdx.getKnownMinValue());
4457
4458 EVT HiVT = Hi.getValueType();
4459 assert(HiVT.isFixedLengthVector() &&
4460 "Only fixed-vector extracts are supported in this case");
4461
4462 // We cannot create an extract_subvector that isn't a multiple of the
4463 // result size, which may go out of bounds for the last elements. Shuffle
4464 // the desired elements down to 0 and do a simple 0 extract.
4465 SmallVector<int, 8> Mask(HiVT.getVectorNumElements(), -1);
4466 for (int I = 0; I != int(NumResultElts.getFixedValue()); ++I)
4467 Mask[I] = int(ExtractIdx.getFixedValue()) + I;
4468
4469 SDValue Shuffle =
4470 DAG.getVectorShuffle(HiVT, dl, Hi, DAG.getPOISON(HiVT), Mask);
4471 return DAG.getExtractSubvector(dl, SubVT, Shuffle, 0);
4472 }
4473
4474 // After this point the DAG node only permits extracting fixed-width
4475 // subvectors from scalable vectors.
4476 assert(SubVT.isFixedLengthVector() &&
4477 "Extracting scalable subvector from fixed-width unsupported");
4478
4479 // If the element type is i1 and we're not promoting the result, then we may
4480 // end up loading the wrong data since the bits are packed tightly into
4481 // bytes. For example, if we extract a v4i1 (legal) from a nxv4i1 (legal)
4482 // type at index 4, then we will load a byte starting at index 0.
4483 if (SubVT.getScalarType() == MVT::i1)
4484 report_fatal_error("Don't know how to extract fixed-width predicate "
4485 "subvector from a scalable predicate vector");
4486
4487 // Spill the vector to the stack. We should use the alignment for
4488 // the smallest part.
4489 SDValue Vec = N->getOperand(0);
4490 EVT VecVT = Vec.getValueType();
4491 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
4493 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
4494 auto &MF = DAG.getMachineFunction();
4495 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
4496 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
4497
4498 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
4499 SmallestAlign);
4500
4501 // Extract the subvector by loading the correct part.
4502 StackPtr = TLI.getVectorSubVecPointer(DAG, StackPtr, VecVT, SubVT, Idx);
4503
4504 return DAG.getLoad(
4505 SubVT, dl, Store, StackPtr,
4506 MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()));
4507}
4508
4509SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
4510 SDValue Vec = N->getOperand(0);
4511 SDValue Idx = N->getOperand(1);
4512 EVT VecVT = Vec.getValueType();
4513
4514 if (const ConstantSDNode *Index = dyn_cast<ConstantSDNode>(Idx)) {
4515 uint64_t IdxVal = Index->getZExtValue();
4516
4517 SDValue Lo, Hi;
4518 GetSplitVector(Vec, Lo, Hi);
4519
4520 uint64_t LoElts = Lo.getValueType().getVectorMinNumElements();
4521
4522 if (IdxVal < LoElts)
4523 return SDValue(DAG.UpdateNodeOperands(N, Lo, Idx), 0);
4524 else if (!Vec.getValueType().isScalableVector())
4525 return SDValue(DAG.UpdateNodeOperands(N, Hi,
4526 DAG.getConstant(IdxVal - LoElts, SDLoc(N),
4527 Idx.getValueType())), 0);
4528 }
4529
4530 // See if the target wants to custom expand this node.
4531 if (CustomLowerNode(N, N->getValueType(0), true))
4532 return SDValue();
4533
4534 // Make the vector elements byte-addressable if they aren't already.
4535 SDLoc dl(N);
4536 EVT EltVT = VecVT.getVectorElementType();
4537 if (!EltVT.isByteSized()) {
4538 EltVT = EltVT.changeTypeToInteger().getRoundIntegerType(*DAG.getContext());
4539 VecVT = VecVT.changeElementType(*DAG.getContext(), EltVT);
4540 Vec = DAG.getNode(ISD::ANY_EXTEND, dl, VecVT, Vec);
4541 SDValue NewExtract =
4542 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, Vec, Idx);
4543 return DAG.getAnyExtOrTrunc(NewExtract, dl, N->getValueType(0));
4544 }
4545
4546 // Store the vector to the stack.
4547 // In cases where the vector is illegal it will be broken down into parts
4548 // and stored in parts - we should use the alignment for the smallest part.
4549 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
4551 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
4552 auto &MF = DAG.getMachineFunction();
4553 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
4554 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
4555 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
4556 SmallestAlign);
4557
4558 // Load back the required element.
4559 StackPtr = TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Idx);
4560
4561 // EXTRACT_VECTOR_ELT can extend the element type to the width of the return
4562 // type, leaving the high bits undefined. But it can't truncate.
4563 assert(N->getValueType(0).bitsGE(EltVT) && "Illegal EXTRACT_VECTOR_ELT.");
4564
4565 return DAG.getExtLoad(
4566 ISD::EXTLOAD, dl, N->getValueType(0), Store, StackPtr,
4567 MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()), EltVT,
4568 commonAlignment(SmallestAlign, EltVT.getFixedSizeInBits() / 8));
4569}
4570
4571SDValue DAGTypeLegalizer::SplitVecOp_ExtVecInRegOp(SDNode *N) {
4572 SDValue Lo, Hi;
4573
4574 // *_EXTEND_VECTOR_INREG only reference the lower half of the input, so
4575 // splitting the result has the same effect as splitting the input operand.
4576 SplitVecRes_ExtVecInRegOp(N, Lo, Hi);
4577
4578 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), N->getValueType(0), Lo, Hi);
4579}
4580
4581SDValue DAGTypeLegalizer::SplitVecOp_Gather(MemSDNode *N, unsigned OpNo) {
4582 (void)OpNo;
4583 SDValue Lo, Hi;
4584 SplitVecRes_Gather(N, Lo, Hi);
4585
4586 SDValue Res = DAG.getNode(ISD::CONCAT_VECTORS, N, N->getValueType(0), Lo, Hi);
4587 ReplaceValueWith(SDValue(N, 0), Res);
4588 return SDValue();
4589}
4590
4591SDValue DAGTypeLegalizer::SplitVecOp_VP_STORE(VPStoreSDNode *N, unsigned OpNo) {
4592 assert(N->isUnindexed() && "Indexed vp_store of vector?");
4593 SDValue Ch = N->getChain();
4594 SDValue Ptr = N->getBasePtr();
4595 SDValue Offset = N->getOffset();
4596 assert(Offset.isUndef() && "Unexpected VP store offset");
4597 SDValue Mask = N->getMask();
4598 SDValue EVL = N->getVectorLength();
4599 SDValue Data = N->getValue();
4600 Align Alignment = N->getBaseAlign();
4601 SDLoc DL(N);
4602
4603 SDValue DataLo, DataHi;
4604 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
4605 // Split Data operand
4606 GetSplitVector(Data, DataLo, DataHi);
4607 else
4608 std::tie(DataLo, DataHi) = DAG.SplitVector(Data, DL);
4609
4610 // Split Mask operand
4611 SDValue MaskLo, MaskHi;
4612 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC) {
4613 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
4614 } else {
4615 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
4616 GetSplitVector(Mask, MaskLo, MaskHi);
4617 else
4618 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
4619 }
4620
4621 EVT MemoryVT = N->getMemoryVT();
4622 EVT LoMemVT, HiMemVT;
4623 bool HiIsEmpty = false;
4624 std::tie(LoMemVT, HiMemVT) =
4625 DAG.GetDependentSplitDestVTs(MemoryVT, DataLo.getValueType(), &HiIsEmpty);
4626
4627 // Split EVL
4628 SDValue EVLLo, EVLHi;
4629 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(EVL, Data.getValueType(), DL);
4630
4631 SDValue Lo, Hi;
4632 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
4633 N->getPointerInfo(), MachineMemOperand::MOStore,
4635 MMOMetadata(N->getAAInfo(), N->getRanges()));
4636
4637 Lo = DAG.getStoreVP(Ch, DL, DataLo, Ptr, Offset, MaskLo, EVLLo, LoMemVT, MMO,
4638 N->getAddressingMode(), N->isTruncatingStore(),
4639 N->isCompressingStore());
4640
4641 // If the hi vp_store has zero storage size, only the lo vp_store is needed.
4642 if (HiIsEmpty)
4643 return Lo;
4644
4645 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, DL, LoMemVT, DAG,
4646 N->isCompressingStore());
4647
4648 MachinePointerInfo MPI;
4649 if (LoMemVT.isScalableVector()) {
4650 Alignment = commonAlignment(Alignment,
4651 LoMemVT.getSizeInBits().getKnownMinValue() / 8);
4652 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
4653 } else
4654 MPI = N->getPointerInfo().getWithOffset(
4655 LoMemVT.getStoreSize().getFixedValue());
4656
4657 MMO = DAG.getMachineFunction().getMachineMemOperand(
4659 Alignment, MMOMetadata(N->getAAInfo(), N->getRanges()));
4660
4661 Hi = DAG.getStoreVP(Ch, DL, DataHi, Ptr, Offset, MaskHi, EVLHi, HiMemVT, MMO,
4662 N->getAddressingMode(), N->isTruncatingStore(),
4663 N->isCompressingStore());
4664
4665 // Build a factor node to remember that this store is independent of the
4666 // other one.
4667 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4668}
4669
4670SDValue DAGTypeLegalizer::SplitVecOp_VP_STRIDED_STORE(VPStridedStoreSDNode *N,
4671 unsigned OpNo) {
4672 assert(N->isUnindexed() && "Indexed vp_strided_store of a vector?");
4673 assert(N->getOffset().isUndef() && "Unexpected VP strided store offset");
4674
4675 SDLoc DL(N);
4676
4677 SDValue Data = N->getValue();
4678 SDValue LoData, HiData;
4679 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
4680 GetSplitVector(Data, LoData, HiData);
4681 else
4682 std::tie(LoData, HiData) = DAG.SplitVector(Data, DL);
4683
4684 EVT LoMemVT, HiMemVT;
4685 bool HiIsEmpty = false;
4686 std::tie(LoMemVT, HiMemVT) = DAG.GetDependentSplitDestVTs(
4687 N->getMemoryVT(), LoData.getValueType(), &HiIsEmpty);
4688
4689 SDValue Mask = N->getMask();
4690 SDValue LoMask, HiMask;
4691 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC)
4692 SplitVecRes_SETCC(Mask.getNode(), LoMask, HiMask);
4693 else if (getTypeAction(Mask.getValueType()) ==
4695 GetSplitVector(Mask, LoMask, HiMask);
4696 else
4697 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
4698
4699 SDValue LoEVL, HiEVL;
4700 std::tie(LoEVL, HiEVL) =
4701 DAG.SplitEVL(N->getVectorLength(), Data.getValueType(), DL);
4702
4703 // Generate the low vp_strided_store
4704 SDValue Lo = DAG.getStridedStoreVP(
4705 N->getChain(), DL, LoData, N->getBasePtr(), N->getOffset(),
4706 N->getStride(), LoMask, LoEVL, LoMemVT, N->getMemOperand(),
4707 N->getAddressingMode(), N->isTruncatingStore(), N->isCompressingStore());
4708
4709 // If the high vp_strided_store has zero storage size, only the low
4710 // vp_strided_store is needed.
4711 if (HiIsEmpty)
4712 return Lo;
4713
4714 // Generate the high vp_strided_store.
4715 // To calculate the high base address, we need to sum to the low base
4716 // address stride number of bytes for each element already stored by low,
4717 // that is: Ptr = Ptr + (LoEVL * Stride)
4718 EVT PtrVT = N->getBasePtr().getValueType();
4720 DAG.getNode(ISD::MUL, DL, PtrVT, LoEVL,
4721 DAG.getSExtOrTrunc(N->getStride(), DL, PtrVT));
4722 SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, N->getBasePtr(), Increment);
4723
4724 Align Alignment = N->getBaseAlign();
4725 if (LoMemVT.isScalableVector())
4726 Alignment = commonAlignment(Alignment,
4727 LoMemVT.getSizeInBits().getKnownMinValue() / 8);
4728
4729 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
4730 MachinePointerInfo(N->getPointerInfo().getAddrSpace()),
4732 Alignment, MMOMetadata(N->getAAInfo(), N->getRanges()));
4733
4734 SDValue Hi = DAG.getStridedStoreVP(
4735 N->getChain(), DL, HiData, Ptr, N->getOffset(), N->getStride(), HiMask,
4736 HiEVL, HiMemVT, MMO, N->getAddressingMode(), N->isTruncatingStore(),
4737 N->isCompressingStore());
4738
4739 // Build a factor node to remember that this store is independent of the
4740 // other one.
4741 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4742}
4743
4744SDValue DAGTypeLegalizer::SplitVecOp_MSTORE(MaskedStoreSDNode *N,
4745 unsigned OpNo) {
4746 assert(N->isUnindexed() && "Indexed masked store of vector?");
4747 SDValue Ch = N->getChain();
4748 SDValue Ptr = N->getBasePtr();
4749 SDValue Offset = N->getOffset();
4750 assert(Offset.isUndef() && "Unexpected indexed masked store offset");
4751 SDValue Mask = N->getMask();
4752 SDValue Data = N->getValue();
4753 Align Alignment = N->getBaseAlign();
4754 SDLoc DL(N);
4755
4756 SDValue DataLo, DataHi;
4757 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
4758 // Split Data operand
4759 GetSplitVector(Data, DataLo, DataHi);
4760 else
4761 std::tie(DataLo, DataHi) = DAG.SplitVector(Data, DL);
4762
4763 // Split Mask operand
4764 SDValue MaskLo, MaskHi;
4765 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC) {
4766 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
4767 } else {
4768 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
4769 GetSplitVector(Mask, MaskLo, MaskHi);
4770 else
4771 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
4772 }
4773
4774 EVT MemoryVT = N->getMemoryVT();
4775 EVT LoMemVT, HiMemVT;
4776 bool HiIsEmpty = false;
4777 std::tie(LoMemVT, HiMemVT) =
4778 DAG.GetDependentSplitDestVTs(MemoryVT, DataLo.getValueType(), &HiIsEmpty);
4779
4780 SDValue Lo, Hi, Res;
4781 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
4782 N->getPointerInfo(), MachineMemOperand::MOStore,
4784 MMOMetadata(N->getAAInfo(), N->getRanges(), N->getMemCacheHint()));
4785
4786 Lo = DAG.getMaskedStore(Ch, DL, DataLo, Ptr, Offset, MaskLo, LoMemVT, MMO,
4787 N->getAddressingMode(), N->isTruncatingStore(),
4788 N->isCompressingStore());
4789
4790 if (HiIsEmpty) {
4791 // The hi masked store has zero storage size.
4792 // Only the lo masked store is needed.
4793 Res = Lo;
4794 } else {
4795
4796 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, DL, LoMemVT, DAG,
4797 N->isCompressingStore());
4798
4799 MachinePointerInfo MPI;
4800 if (LoMemVT.isScalableVector()) {
4802 Alignment, LoMemVT.getSizeInBits().getKnownMinValue() / 8);
4803 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
4804 } else
4805 MPI = N->getPointerInfo().getWithOffset(
4806 LoMemVT.getStoreSize().getFixedValue());
4807
4808 MMO = DAG.getMachineFunction().getMachineMemOperand(
4810 Alignment,
4811 MMOMetadata(N->getAAInfo(), N->getRanges(), N->getMemCacheHint()));
4812
4813 Hi = DAG.getMaskedStore(Ch, DL, DataHi, Ptr, Offset, MaskHi, HiMemVT, MMO,
4814 N->getAddressingMode(), N->isTruncatingStore(),
4815 N->isCompressingStore());
4816
4817 // Build a factor node to remember that this store is independent of the
4818 // other one.
4819 Res = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4820 }
4821
4822 return Res;
4823}
4824
4825SDValue DAGTypeLegalizer::SplitVecOp_Scatter(MemSDNode *N, unsigned OpNo) {
4826 SDValue Ch = N->getChain();
4827 SDValue Ptr = N->getBasePtr();
4828 EVT MemoryVT = N->getMemoryVT();
4829 Align Alignment = N->getBaseAlign();
4830 SDLoc DL(N);
4831 struct Operands {
4832 SDValue Mask;
4833 SDValue Index;
4834 SDValue Scale;
4835 SDValue Data;
4836 } Ops = [&]() -> Operands {
4837 if (auto *MSC = dyn_cast<MaskedScatterSDNode>(N)) {
4838 return {MSC->getMask(), MSC->getIndex(), MSC->getScale(),
4839 MSC->getValue()};
4840 }
4841 auto *VPSC = cast<VPScatterSDNode>(N);
4842 return {VPSC->getMask(), VPSC->getIndex(), VPSC->getScale(),
4843 VPSC->getValue()};
4844 }();
4845 // Split all operands
4846
4847 EVT LoMemVT, HiMemVT;
4848 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
4849
4850 SDValue DataLo, DataHi;
4851 if (getTypeAction(Ops.Data.getValueType()) == TargetLowering::TypeSplitVector)
4852 // Split Data operand
4853 GetSplitVector(Ops.Data, DataLo, DataHi);
4854 else
4855 std::tie(DataLo, DataHi) = DAG.SplitVector(Ops.Data, DL);
4856
4857 // Split Mask operand
4858 SDValue MaskLo, MaskHi;
4859 if (OpNo == 1 && Ops.Mask.getOpcode() == ISD::SETCC) {
4860 SplitVecRes_SETCC(Ops.Mask.getNode(), MaskLo, MaskHi);
4861 } else {
4862 std::tie(MaskLo, MaskHi) = SplitMask(Ops.Mask, DL);
4863 }
4864
4865 SDValue IndexHi, IndexLo;
4866 if (getTypeAction(Ops.Index.getValueType()) ==
4868 GetSplitVector(Ops.Index, IndexLo, IndexHi);
4869 else
4870 std::tie(IndexLo, IndexHi) = DAG.SplitVector(Ops.Index, DL);
4871
4872 SDValue Lo;
4873 MachineMemOperand::Flags MMOFlags = N->getMemOperand()->getFlags();
4874 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
4875 N->getPointerInfo(), MMOFlags, LocationSize::beforeOrAfterPointer(),
4876 Alignment, MMOMetadata(N->getAAInfo(), N->getRanges()));
4877
4878 if (auto *MSC = dyn_cast<MaskedScatterSDNode>(N)) {
4879 SDValue OpsLo[] = {Ch, DataLo, MaskLo, Ptr, IndexLo, Ops.Scale};
4880 Lo =
4881 DAG.getMaskedScatter(DAG.getVTList(MVT::Other), LoMemVT, DL, OpsLo, MMO,
4882 MSC->getIndexType(), MSC->isTruncatingStore());
4883
4884 // The order of the Scatter operation after split is well defined. The "Hi"
4885 // part comes after the "Lo". So these two operations should be chained one
4886 // after another.
4887 SDValue OpsHi[] = {Lo, DataHi, MaskHi, Ptr, IndexHi, Ops.Scale};
4888 return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), HiMemVT, DL, OpsHi,
4889 MMO, MSC->getIndexType(),
4890 MSC->isTruncatingStore());
4891 }
4892 auto *VPSC = cast<VPScatterSDNode>(N);
4893 SDValue EVLLo, EVLHi;
4894 std::tie(EVLLo, EVLHi) =
4895 DAG.SplitEVL(VPSC->getVectorLength(), Ops.Data.getValueType(), DL);
4896
4897 SDValue OpsLo[] = {Ch, DataLo, Ptr, IndexLo, Ops.Scale, MaskLo, EVLLo};
4898 Lo = DAG.getScatterVP(DAG.getVTList(MVT::Other), LoMemVT, DL, OpsLo, MMO,
4899 VPSC->getIndexType());
4900
4901 // The order of the Scatter operation after split is well defined. The "Hi"
4902 // part comes after the "Lo". So these two operations should be chained one
4903 // after another.
4904 SDValue OpsHi[] = {Lo, DataHi, Ptr, IndexHi, Ops.Scale, MaskHi, EVLHi};
4905 return DAG.getScatterVP(DAG.getVTList(MVT::Other), HiMemVT, DL, OpsHi, MMO,
4906 VPSC->getIndexType());
4907}
4908
4909SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) {
4910 assert(N->isUnindexed() && "Indexed store of vector?");
4911 assert(OpNo == 1 && "Can only split the stored value");
4912 SDLoc DL(N);
4913
4914 bool isTruncating = N->isTruncatingStore();
4915 SDValue Ch = N->getChain();
4916 SDValue Ptr = N->getBasePtr();
4917 EVT MemoryVT = N->getMemoryVT();
4918 Align Alignment = N->getBaseAlign();
4919 MachineMemOperand::Flags MMOFlags = N->getMemOperand()->getFlags();
4920 MMOMetadata Metadata = N->getMMOMetadataForSubAccess();
4921 SDValue Lo, Hi;
4922 GetSplitVector(N->getOperand(1), Lo, Hi);
4923
4924 EVT LoMemVT, HiMemVT;
4925 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
4926
4927 // Scalarize if the split halves are not byte-sized.
4928 if (!LoMemVT.isByteSized() || !HiMemVT.isByteSized())
4929 return TLI.scalarizeVectorStore(N, DAG);
4930
4931 if (isTruncating)
4932 Lo = DAG.getTruncStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), LoMemVT,
4933 Alignment, MMOFlags, Metadata);
4934 else
4935 Lo = DAG.getStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), Alignment, MMOFlags,
4936 Metadata);
4937
4938 MachinePointerInfo MPI;
4939 IncrementPointer(N, LoMemVT, MPI, Ptr);
4940
4941 if (isTruncating)
4942 Hi = DAG.getTruncStore(Ch, DL, Hi, Ptr, MPI, HiMemVT, Alignment, MMOFlags,
4943 Metadata);
4944 else
4945 Hi = DAG.getStore(Ch, DL, Hi, Ptr, MPI, Alignment, MMOFlags, Metadata);
4946
4947 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4948}
4949
4950SDValue DAGTypeLegalizer::SplitVecOp_ATOMIC_STORE(AtomicSDNode *N) {
4951 SDLoc DL(N);
4952 LLVMContext &Ctx = *DAG.getContext();
4953 SDValue StVal = N->getVal();
4954 EVT VT = StVal.getValueType();
4955 EVT MemIntVT = EVT::getIntegerVT(Ctx, N->getMemoryVT().getSizeInBits());
4956
4957 // The store needs a single value spanning the full memory width. If the
4958 // value can be held in a legal vector register, keep it there and extract
4959 // the low integer element of the memory width. This lets the store be issued
4960 // directly from a vector register (e.g. a single MOVQ/MOVD) instead of
4961 // bitcasting the split vector straight to a scalar integer, which would
4962 // reassemble the value element by element in GPRs.
4963 //
4964 // Reinterpret the value as a same-shaped integer vector first: an FP element
4965 // type may not have a legal vector form (e.g. bfloat on SSE2) while the
4966 // integer-of-element-size form does. Ask the target which legal vector type
4967 // it widens to.
4968 EVT IntVecVT = VT.changeVectorElementTypeToInteger();
4969 EVT IntEltVT = IntVecVT.getVectorElementType();
4970 EVT WideVT = TLI.getLegalTypeToTransformTo(Ctx, IntVecVT);
4971 if (DAG.getDataLayout().isLittleEndian() && TLI.isTypeLegal(MemIntVT) &&
4972 WideVT.isVector() && WideVT.getVectorElementType() == IntEltVT &&
4973 IntEltVT.getSizeInBits() <= MemIntVT.getSizeInBits() &&
4974 WideVT.getSizeInBits() % MemIntVT.getSizeInBits() == 0) {
4975 SDValue Wide = ModifyToType(DAG.getBitcast(IntVecVT, StVal), WideVT);
4976 unsigned NumMemElts = WideVT.getSizeInBits() / MemIntVT.getSizeInBits();
4977 EVT MemVecVT = EVT::getVectorVT(Ctx, MemIntVT, NumMemElts);
4978 SDValue Elt = DAG.getExtractVectorElt(DL, MemIntVT,
4979 DAG.getBitcast(MemVecVT, Wide), 0);
4980 return DAG.getAtomic(ISD::ATOMIC_STORE, DL, MemIntVT, N->getChain(), Elt,
4981 N->getBasePtr(), N->getMemOperand());
4982 }
4983
4984 // Otherwise issue a single atomic store of an integer that spans the full
4985 // memory width. Bitcasting the (illegal) vector value to that integer lets
4986 // the type legalizer further legalize the BITCAST input as needed, while the
4987 // ATOMIC_STORE itself uses only the legal integer type.
4988 EVT IntVT = EVT::getIntegerVT(Ctx, VT.getSizeInBits());
4989 SDValue AsInt = DAG.getBitcast(IntVT, StVal);
4990 return DAG.getAtomic(ISD::ATOMIC_STORE, DL, MemIntVT, N->getChain(), AsInt,
4991 N->getBasePtr(), N->getMemOperand());
4992}
4993
4994SDValue DAGTypeLegalizer::SplitVecOp_CONCAT_VECTORS(SDNode *N) {
4995 SDLoc DL(N);
4996
4997 // The input operands all must have the same type, and we know the result
4998 // type is valid. Convert this to a buildvector which extracts all the
4999 // input elements.
5000 // TODO: If the input elements are power-two vectors, we could convert this to
5001 // a new CONCAT_VECTORS node with elements that are half-wide.
5003 EVT EltVT = N->getValueType(0).getVectorElementType();
5004 for (const SDValue &Op : N->op_values()) {
5005 for (unsigned i = 0, e = Op.getValueType().getVectorNumElements();
5006 i != e; ++i) {
5007 Elts.push_back(DAG.getExtractVectorElt(DL, EltVT, Op, i));
5008 }
5009 }
5010
5011 return DAG.getBuildVector(N->getValueType(0), DL, Elts);
5012}
5013
5014SDValue DAGTypeLegalizer::SplitVecOp_TruncateHelper(SDNode *N) {
5015 // The result type is legal, but the input type is illegal. If splitting
5016 // ends up with the result type of each half still being legal, just
5017 // do that. If, however, that would result in an illegal result type,
5018 // we can try to get more clever with power-two vectors. Specifically,
5019 // split the input type, but also widen the result element size, then
5020 // concatenate the halves and truncate again. For example, consider a target
5021 // where v8i8 is legal and v8i32 is not (ARM, which doesn't have 256-bit
5022 // vectors). To perform a "%res = v8i8 trunc v8i32 %in" we do:
5023 // %inlo = v4i32 extract_subvector %in, 0
5024 // %inhi = v4i32 extract_subvector %in, 4
5025 // %lo16 = v4i16 trunc v4i32 %inlo
5026 // %hi16 = v4i16 trunc v4i32 %inhi
5027 // %in16 = v8i16 concat_vectors v4i16 %lo16, v4i16 %hi16
5028 // %res = v8i8 trunc v8i16 %in16
5029 //
5030 // Without this transform, the original truncate would end up being
5031 // scalarized, which is pretty much always a last resort.
5032 unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
5033 SDValue InVec = N->getOperand(OpNo);
5034 EVT InVT = InVec->getValueType(0);
5035 EVT OutVT = N->getValueType(0);
5036 ElementCount NumElements = OutVT.getVectorElementCount();
5037 bool IsFloat = OutVT.isFloatingPoint();
5038
5039 unsigned InElementSize = InVT.getScalarSizeInBits();
5040 unsigned OutElementSize = OutVT.getScalarSizeInBits();
5041
5042 // Determine the split output VT. If its legal we can just split dirctly.
5043 EVT LoOutVT, HiOutVT;
5044 std::tie(LoOutVT, HiOutVT) = DAG.GetSplitDestVTs(OutVT);
5045 assert(LoOutVT == HiOutVT && "Unequal split?");
5046
5047 // If the input elements are only 1/2 the width of the result elements,
5048 // just use the normal splitting. Our trick only work if there's room
5049 // to split more than once.
5050 if (isTypeLegal(LoOutVT) || InElementSize <= OutElementSize * 2 ||
5051 (IsFloat && !isPowerOf2_32(InElementSize)))
5052 return SplitVecOp_UnaryOp(N);
5053 SDLoc DL(N);
5054
5055 // Don't touch if this will be scalarized.
5056 EVT FinalVT = InVT;
5057 while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
5058 FinalVT = FinalVT.getHalfNumVectorElementsVT(*DAG.getContext());
5059
5060 if (getTypeAction(FinalVT) == TargetLowering::TypeScalarizeVector)
5061 return SplitVecOp_UnaryOp(N);
5062
5063 // Get the split input vector.
5064 SDValue InLoVec, InHiVec;
5065 GetSplitVector(InVec, InLoVec, InHiVec);
5066
5067 // Truncate them to 1/2 the element size.
5068 //
5069 // This assumes the number of elements is a power of two; any vector that
5070 // isn't should be widened, not split.
5071 EVT HalfElementVT = IsFloat ?
5072 EVT::getFloatingPointVT(InElementSize/2) :
5073 EVT::getIntegerVT(*DAG.getContext(), InElementSize/2);
5074 EVT HalfVT = EVT::getVectorVT(*DAG.getContext(), HalfElementVT,
5075 NumElements.divideCoefficientBy(2));
5076
5077 SDValue HalfLo;
5078 SDValue HalfHi;
5079 SDValue Chain;
5080 if (N->isStrictFPOpcode()) {
5081 HalfLo = DAG.getNode(N->getOpcode(), DL, {HalfVT, MVT::Other},
5082 {N->getOperand(0), InLoVec});
5083 HalfHi = DAG.getNode(N->getOpcode(), DL, {HalfVT, MVT::Other},
5084 {N->getOperand(0), InHiVec});
5085 // Legalize the chain result - switch anything that used the old chain to
5086 // use the new one.
5087 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, HalfLo.getValue(1),
5088 HalfHi.getValue(1));
5089 } else {
5090 HalfLo = DAG.getNode(N->getOpcode(), DL, HalfVT, InLoVec);
5091 HalfHi = DAG.getNode(N->getOpcode(), DL, HalfVT, InHiVec);
5092 }
5093
5094 // Concatenate them to get the full intermediate truncation result.
5095 EVT InterVT = EVT::getVectorVT(*DAG.getContext(), HalfElementVT, NumElements);
5096 SDValue InterVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InterVT, HalfLo,
5097 HalfHi);
5098 // Now finish up by truncating all the way down to the original result
5099 // type. This should normally be something that ends up being legal directly,
5100 // but in theory if a target has very wide vectors and an annoyingly
5101 // restricted set of legal types, this split can chain to build things up.
5102
5103 if (N->isStrictFPOpcode()) {
5104 SDValue Res = DAG.getNode(
5105 ISD::STRICT_FP_ROUND, DL, {OutVT, MVT::Other},
5106 {Chain, InterVec,
5107 DAG.getTargetConstant(0, DL, TLI.getPointerTy(DAG.getDataLayout()))});
5108 // Relink the chain
5109 ReplaceValueWith(SDValue(N, 1), SDValue(Res.getNode(), 1));
5110 return Res;
5111 }
5112
5113 return IsFloat
5114 ? DAG.getNode(ISD::FP_ROUND, DL, OutVT, InterVec,
5115 DAG.getTargetConstant(
5116 0, DL, TLI.getPointerTy(DAG.getDataLayout())))
5117 : DAG.getNode(ISD::TRUNCATE, DL, OutVT, InterVec);
5118}
5119
5120SDValue DAGTypeLegalizer::SplitVecOp_VSETCC(SDNode *N) {
5121 unsigned Opc = N->getOpcode();
5122 bool isStrict = Opc == ISD::STRICT_FSETCC || Opc == ISD::STRICT_FSETCCS;
5123 assert(N->getValueType(0).isVector() &&
5124 N->getOperand(isStrict ? 1 : 0).getValueType().isVector() &&
5125 "Operand types must be vectors");
5126 // The result has a legal vector type, but the input needs splitting.
5127 SDValue Lo0, Hi0, Lo1, Hi1, LoRes, HiRes;
5128 SDLoc DL(N);
5129 GetSplitVector(N->getOperand(isStrict ? 1 : 0), Lo0, Hi0);
5130 GetSplitVector(N->getOperand(isStrict ? 2 : 1), Lo1, Hi1);
5131
5132 EVT VT = N->getValueType(0);
5133 EVT PartResVT = getSetCCResultType(Lo0.getValueType());
5134
5135 if (Opc == ISD::SETCC) {
5136 LoRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Lo0, Lo1, N->getOperand(2));
5137 HiRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Hi0, Hi1, N->getOperand(2));
5138 } else {
5139 assert(isStrict && "unexpected node");
5140 LoRes = DAG.getNode(Opc, DL, DAG.getVTList(PartResVT, N->getValueType(1)),
5141 N->getOperand(0), Lo0, Lo1, N->getOperand(3));
5142 HiRes = DAG.getNode(Opc, DL, DAG.getVTList(PartResVT, N->getValueType(1)),
5143 N->getOperand(0), Hi0, Hi1, N->getOperand(3));
5144 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
5145 LoRes.getValue(1), HiRes.getValue(1));
5146 ReplaceValueWith(SDValue(N, 1), NewChain);
5147 }
5148
5149 EVT ConcatVT = PartResVT.getDoubleNumVectorElementsVT(*DAG.getContext());
5150 SDValue Con = DAG.getNode(ISD::CONCAT_VECTORS, DL, ConcatVT, LoRes, HiRes);
5151 if (VT == ConcatVT)
5152 return Con;
5153
5154 EVT OpVT = N->getOperand(0).getValueType();
5155 ISD::NodeType ExtendCode =
5156 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
5157 return DAG.getExtOrTrunc(Con, DL, VT, ExtendCode);
5158}
5159
5160
5161SDValue DAGTypeLegalizer::SplitVecOp_FP_ROUND(SDNode *N) {
5162 // The result has a legal vector type, but the input needs splitting.
5163 EVT ResVT = N->getValueType(0);
5164 SDValue Lo, Hi;
5165 SDLoc DL(N);
5166 GetSplitVector(N->getOperand(N->isStrictFPOpcode() ? 1 : 0), Lo, Hi);
5167 EVT InVT = Lo.getValueType();
5168
5169 EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
5170 InVT.getVectorElementCount());
5171
5172 if (N->isStrictFPOpcode()) {
5173 Lo = DAG.getNode(N->getOpcode(), DL, {OutVT, MVT::Other},
5174 {N->getOperand(0), Lo, N->getOperand(2)});
5175 Hi = DAG.getNode(N->getOpcode(), DL, {OutVT, MVT::Other},
5176 {N->getOperand(0), Hi, N->getOperand(2)});
5177 // Legalize the chain result - switch anything that used the old chain to
5178 // use the new one.
5179 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
5180 Lo.getValue(1), Hi.getValue(1));
5181 ReplaceValueWith(SDValue(N, 1), NewChain);
5182 } else if (N->getOpcode() == ISD::CONVERT_TO_ARBITRARY_FP) {
5183 Lo = DAG.getNode(N->getOpcode(), DL, OutVT, Lo, N->getOperand(1),
5184 N->getOperand(2), N->getOperand(3));
5185 Hi = DAG.getNode(N->getOpcode(), DL, OutVT, Hi, N->getOperand(1),
5186 N->getOperand(2), N->getOperand(3));
5187 } else {
5188 Lo = DAG.getNode(N->getOpcode(), DL, OutVT, Lo, N->getOperand(1));
5189 Hi = DAG.getNode(N->getOpcode(), DL, OutVT, Hi, N->getOperand(1));
5190 }
5191
5192 return DAG.getNode(ISD::CONCAT_VECTORS, DL, ResVT, Lo, Hi);
5193}
5194
5195// Split a vector type in an FP binary operation where the second operand has a
5196// different type from the first.
5197//
5198// The result (and the first input) has a legal vector type, but the second
5199// input needs splitting.
5200SDValue DAGTypeLegalizer::SplitVecOp_FPOpDifferentTypes(SDNode *N) {
5201 SDLoc DL(N);
5202
5203 EVT LHSLoVT, LHSHiVT;
5204 std::tie(LHSLoVT, LHSHiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
5205
5206 if (!isTypeLegal(LHSLoVT) || !isTypeLegal(LHSHiVT))
5207 return DAG.UnrollVectorOp(N, N->getValueType(0).getVectorNumElements());
5208
5209 SDValue LHSLo, LHSHi;
5210 std::tie(LHSLo, LHSHi) =
5211 DAG.SplitVector(N->getOperand(0), DL, LHSLoVT, LHSHiVT);
5212
5213 SDValue RHSLo, RHSHi;
5214 std::tie(RHSLo, RHSHi) = DAG.SplitVector(N->getOperand(1), DL);
5215
5216 SDValue Lo = DAG.getNode(N->getOpcode(), DL, LHSLoVT, LHSLo, RHSLo);
5217 SDValue Hi = DAG.getNode(N->getOpcode(), DL, LHSHiVT, LHSHi, RHSHi);
5218
5219 return DAG.getNode(ISD::CONCAT_VECTORS, DL, N->getValueType(0), Lo, Hi);
5220}
5221
5222SDValue DAGTypeLegalizer::SplitVecOp_CMP(SDNode *N) {
5223 LLVMContext &Ctxt = *DAG.getContext();
5224 SDLoc dl(N);
5225
5226 SDValue LHSLo, LHSHi, RHSLo, RHSHi;
5227 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
5228 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
5229
5230 EVT ResVT = N->getValueType(0);
5231 ElementCount SplitOpEC = LHSLo.getValueType().getVectorElementCount();
5232 EVT NewResVT =
5233 EVT::getVectorVT(Ctxt, ResVT.getVectorElementType(), SplitOpEC);
5234
5235 SDValue Lo = DAG.getNode(N->getOpcode(), dl, NewResVT, LHSLo, RHSLo);
5236 SDValue Hi = DAG.getNode(N->getOpcode(), dl, NewResVT, LHSHi, RHSHi);
5237
5238 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
5239}
5240
5241SDValue DAGTypeLegalizer::SplitVecOp_FP_TO_XINT_SAT(SDNode *N) {
5242 EVT ResVT = N->getValueType(0);
5243 SDValue Lo, Hi;
5244 SDLoc dl(N);
5245 GetSplitVector(N->getOperand(0), Lo, Hi);
5246 EVT InVT = Lo.getValueType();
5247
5248 EVT NewResVT =
5249 EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
5250 InVT.getVectorElementCount());
5251
5252 Lo = DAG.getNode(N->getOpcode(), dl, NewResVT, Lo, N->getOperand(1));
5253 Hi = DAG.getNode(N->getOpcode(), dl, NewResVT, Hi, N->getOperand(1));
5254
5255 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
5256}
5257
5258SDValue DAGTypeLegalizer::SplitVecOp_CttzElts(SDNode *N) {
5259 SDLoc DL(N);
5260 EVT ResVT = N->getValueType(0);
5261
5262 SDValue Lo, Hi;
5263 SDValue VecOp = N->getOperand(0);
5264 GetSplitVector(VecOp, Lo, Hi);
5265
5266 // if CTTZ_ELTS(Lo) != VL => CTTZ_ELTS(Lo).
5267 // else => VL + (CTTZ_ELTS(Hi) or CTTZ_ELTS_ZERO_POISON(Hi)).
5268 SDValue ResLo = DAG.getNode(ISD::CTTZ_ELTS, DL, ResVT, Lo);
5269 SDValue VL =
5270 DAG.getElementCount(DL, ResVT, Lo.getValueType().getVectorElementCount());
5271 SDValue ResLoNotVL =
5272 DAG.getSetCC(DL, getSetCCResultType(ResVT), ResLo, VL, ISD::SETNE);
5273 SDValue ResHi = DAG.getNode(N->getOpcode(), DL, ResVT, Hi);
5274 return DAG.getSelect(DL, ResVT, ResLoNotVL, ResLo,
5275 DAG.getNode(ISD::ADD, DL, ResVT, VL, ResHi));
5276}
5277
5278SDValue DAGTypeLegalizer::SplitVecOp_VP_CttzElements(SDNode *N) {
5279 SDLoc DL(N);
5280 EVT ResVT = N->getValueType(0);
5281
5282 SDValue Lo, Hi;
5283 SDValue VecOp = N->getOperand(0);
5284 GetSplitVector(VecOp, Lo, Hi);
5285
5286 auto [MaskLo, MaskHi] = SplitMask(N->getOperand(1));
5287 auto [EVLLo, EVLHi] =
5288 DAG.SplitEVL(N->getOperand(2), VecOp.getValueType(), DL);
5289 SDValue VLo = DAG.getZExtOrTrunc(EVLLo, DL, ResVT);
5290
5291 // if VP_CTTZ_ELTS(Lo) != EVLLo => VP_CTTZ_ELTS(Lo).
5292 // else => EVLLo + (VP_CTTZ_ELTS(Hi) or VP_CTTZ_ELTS_ZERO_POISON(Hi)).
5293 SDValue ResLo = DAG.getNode(ISD::VP_CTTZ_ELTS, DL, ResVT, Lo, MaskLo, EVLLo);
5294 SDValue ResLoNotEVL =
5295 DAG.getSetCC(DL, getSetCCResultType(ResVT), ResLo, VLo, ISD::SETNE);
5296 SDValue ResHi = DAG.getNode(N->getOpcode(), DL, ResVT, Hi, MaskHi, EVLHi);
5297 return DAG.getSelect(DL, ResVT, ResLoNotEVL, ResLo,
5298 DAG.getNode(ISD::ADD, DL, ResVT, VLo, ResHi));
5299}
5300
5301SDValue DAGTypeLegalizer::SplitVecOp_VECTOR_HISTOGRAM(SDNode *N) {
5302 MaskedHistogramSDNode *HG = cast<MaskedHistogramSDNode>(N);
5303 SDLoc DL(HG);
5304 SDValue Inc = HG->getInc();
5305 SDValue Ptr = HG->getBasePtr();
5306 SDValue Scale = HG->getScale();
5307 SDValue IntID = HG->getIntID();
5308 EVT MemVT = HG->getMemoryVT();
5309 MachineMemOperand *MMO = HG->getMemOperand();
5310 ISD::MemIndexType IndexType = HG->getIndexType();
5311
5312 SDValue IndexLo, IndexHi, MaskLo, MaskHi;
5313 std::tie(IndexLo, IndexHi) = DAG.SplitVector(HG->getIndex(), DL);
5314 std::tie(MaskLo, MaskHi) = DAG.SplitVector(HG->getMask(), DL);
5315 SDValue OpsLo[] = {HG->getChain(), Inc, MaskLo, Ptr, IndexLo, Scale, IntID};
5316 SDValue Lo = DAG.getMaskedHistogram(DAG.getVTList(MVT::Other), MemVT, DL,
5317 OpsLo, MMO, IndexType);
5318 SDValue OpsHi[] = {Lo, Inc, MaskHi, Ptr, IndexHi, Scale, IntID};
5319 return DAG.getMaskedHistogram(DAG.getVTList(MVT::Other), MemVT, DL, OpsHi,
5320 MMO, IndexType);
5321}
5322
5323SDValue DAGTypeLegalizer::SplitVecOp_VECTOR_MATCH(SDNode *N, unsigned OpNo) {
5324 SDLoc DL(N);
5325
5326 if (OpNo == 0) {
5327 EVT LoResVT, HiResVT;
5328 std::tie(LoResVT, HiResVT) = DAG.GetSplitDestVTs(N->getValueType(0));
5329 SDValue SourceLo, SourceHi;
5330 std::tie(SourceLo, SourceHi) = DAG.SplitVectorOperand(N, 0);
5331 SDValue MaskLo, MaskHi;
5332 std::tie(MaskLo, MaskHi) = DAG.SplitVectorOperand(N, 2);
5333
5334 SDValue MatchLo = DAG.getNode(ISD::VECTOR_MATCH, DL, LoResVT, SourceLo,
5335 N->getOperand(1), MaskLo, N->getFlags());
5336 SDValue MatchHi = DAG.getNode(ISD::VECTOR_MATCH, DL, HiResVT, SourceHi,
5337 N->getOperand(1), MaskHi, N->getFlags());
5338 return DAG.getNode(ISD::CONCAT_VECTORS, DL, N->getValueType(0), MatchLo,
5339 MatchHi);
5340 }
5341
5342 // Note: The Mask (OpNo == 2) should be widened with the result.
5343 assert(OpNo == 1 && "Unexpected VECTOR_MATCH operand");
5344
5345 SDValue NeedleLo, NeedleHi;
5346 GetSplitVector(N->getOperand(1), NeedleLo, NeedleHi);
5347
5348 SDValue MatchLo =
5349 DAG.getNode(ISD::VECTOR_MATCH, DL, N->getValueType(0), N->getOperand(0),
5350 NeedleLo, N->getOperand(2), N->getFlags());
5351 SDValue MatchHi =
5352 DAG.getNode(ISD::VECTOR_MATCH, DL, N->getValueType(0), N->getOperand(0),
5353 NeedleHi, N->getOperand(2), N->getFlags());
5354 return DAG.getNode(ISD::OR, DL, N->getValueType(0), MatchLo, MatchHi);
5355}
5356
5357SDValue DAGTypeLegalizer::SplitVecOp_PARTIAL_REDUCE_MLA(SDNode *N) {
5358 SDValue Acc = N->getOperand(0);
5359 assert(getTypeAction(Acc.getValueType()) != TargetLowering::TypeSplitVector &&
5360 "Accumulator should already be a legal type, and shouldn't need "
5361 "further splitting");
5362
5363 SDLoc DL(N);
5364 SDValue Input1Lo, Input1Hi, Input2Lo, Input2Hi;
5365 GetSplitVector(N->getOperand(1), Input1Lo, Input1Hi);
5366 GetSplitVector(N->getOperand(2), Input2Lo, Input2Hi);
5367 unsigned Opcode = N->getOpcode();
5368 EVT ResultVT = Acc.getValueType();
5369
5370 SDValue Lo = DAG.getNode(Opcode, DL, ResultVT, Acc, Input1Lo, Input2Lo);
5371 return DAG.getNode(Opcode, DL, ResultVT, Lo, Input1Hi, Input2Hi);
5372}
5373
5374//===----------------------------------------------------------------------===//
5375// Result Vector Widening
5376//===----------------------------------------------------------------------===//
5377
5378void DAGTypeLegalizer::ReplaceOtherWidenResults(SDNode *N, SDNode *WidenNode,
5379 unsigned WidenResNo) {
5380 unsigned NumResults = N->getNumValues();
5381 for (unsigned ResNo = 0; ResNo < NumResults; ResNo++) {
5382 if (ResNo == WidenResNo)
5383 continue;
5384 EVT ResVT = N->getValueType(ResNo);
5385 if (getTypeAction(ResVT) == TargetLowering::TypeWidenVector) {
5386 SetWidenedVector(SDValue(N, ResNo), SDValue(WidenNode, ResNo));
5387 } else {
5388 SDLoc DL(N);
5389 SDValue ResVal =
5390 DAG.getExtractSubvector(DL, ResVT, SDValue(WidenNode, ResNo), 0);
5391 ReplaceValueWith(SDValue(N, ResNo), ResVal);
5392 }
5393 }
5394}
5395
5396void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
5397 LLVM_DEBUG(dbgs() << "Widen node result " << ResNo << ": "; N->dump(&DAG));
5398
5399 // See if the target wants to custom widen this node.
5400 if (CustomWidenLowerNode(N, N->getValueType(ResNo)))
5401 return;
5402
5403 SDValue Res = SDValue();
5404
5405 auto unrollExpandedOp = [&]() {
5406 // We're going to widen this vector op to a legal type by padding with undef
5407 // elements. If the wide vector op is eventually going to be expanded to
5408 // scalar libcalls, then unroll into scalar ops now to avoid unnecessary
5409 // libcalls on the undef elements.
5410 EVT ResVT = N->getValueType(ResNo);
5411 EVT WideVecVT = TLI.getTypeToTransformTo(*DAG.getContext(), ResVT);
5412 if (WideVecVT.isScalableVector())
5413 return false;
5414 EVT VT0 = N->getValueType(0);
5415 if (!TLI.isOperationLegalOrCustomOrPromote(N->getOpcode(), WideVecVT) &&
5416 TLI.isOperationExpandOrLibCall(N->getOpcode(), VT0.getScalarType())) {
5417 SDValue Unrolled =
5418 DAG.UnrollVectorOp(N, WideVecVT.getVectorNumElements());
5419 Res = Unrolled.getValue(ResNo);
5420 if (N->getNumValues() > 1)
5421 ReplaceOtherWidenResults(N, Unrolled.getNode(), ResNo);
5422 return true;
5423 }
5424 return false;
5425 };
5426
5427 switch (N->getOpcode()) {
5428 default:
5429#ifndef NDEBUG
5430 dbgs() << "WidenVectorResult #" << ResNo << ": ";
5431 N->dump(&DAG);
5432 dbgs() << "\n";
5433#endif
5434 report_fatal_error("do not know how to widen the result of this operator!");
5435
5438 Res = WidenVecRes_LOOP_DEPENDENCE_MASK(N);
5439 break;
5440 case ISD::MERGE_VALUES: Res = WidenVecRes_MERGE_VALUES(N, ResNo); break;
5441 case ISD::ADDRSPACECAST:
5442 Res = WidenVecRes_ADDRSPACECAST(N);
5443 break;
5444 case ISD::AssertZext: Res = WidenVecRes_AssertZext(N); break;
5445 case ISD::BITCAST: Res = WidenVecRes_BITCAST(N); break;
5446 case ISD::BUILD_VECTOR: Res = WidenVecRes_BUILD_VECTOR(N); break;
5447 case ISD::CONCAT_VECTORS: Res = WidenVecRes_CONCAT_VECTORS(N); break;
5449 Res = WidenVecRes_INSERT_SUBVECTOR(N);
5450 break;
5451 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecRes_EXTRACT_SUBVECTOR(N); break;
5452 case ISD::INSERT_VECTOR_ELT: Res = WidenVecRes_INSERT_VECTOR_ELT(N); break;
5453 case ISD::ATOMIC_LOAD:
5454 Res = WidenVecRes_ATOMIC_LOAD(cast<AtomicSDNode>(N));
5455 break;
5456 case ISD::LOAD: Res = WidenVecRes_LOAD(N); break;
5457 case ISD::STEP_VECTOR:
5458 case ISD::SPLAT_VECTOR:
5460 Res = WidenVecRes_ScalarOp(N);
5461 break;
5462 case ISD::SIGN_EXTEND_INREG: Res = WidenVecRes_InregOp(N); break;
5463 case ISD::VSELECT:
5464 case ISD::SELECT:
5465 case ISD::VP_MERGE:
5466 Res = WidenVecRes_Select(N);
5467 break;
5468 case ISD::SELECT_CC: Res = WidenVecRes_SELECT_CC(N); break;
5469 case ISD::SETCC: Res = WidenVecRes_SETCC(N); break;
5470 case ISD::POISON:
5471 case ISD::UNDEF: Res = WidenVecRes_UNDEF(N); break;
5473 Res = WidenVecRes_VECTOR_SHUFFLE(cast<ShuffleVectorSDNode>(N));
5474 break;
5475 case ISD::VP_LOAD:
5476 Res = WidenVecRes_VP_LOAD(cast<VPLoadSDNode>(N));
5477 break;
5478 case ISD::VP_LOAD_FF:
5479 Res = WidenVecRes_VP_LOAD_FF(cast<VPLoadFFSDNode>(N));
5480 break;
5481 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
5482 Res = WidenVecRes_VP_STRIDED_LOAD(cast<VPStridedLoadSDNode>(N));
5483 break;
5485 Res = WidenVecRes_VECTOR_COMPRESS(N);
5486 break;
5487 case ISD::MLOAD:
5488 Res = WidenVecRes_MLOAD(cast<MaskedLoadSDNode>(N));
5489 break;
5490 case ISD::MGATHER:
5491 Res = WidenVecRes_MGATHER(cast<MaskedGatherSDNode>(N));
5492 break;
5493 case ISD::VP_GATHER:
5494 Res = WidenVecRes_VP_GATHER(cast<VPGatherSDNode>(N));
5495 break;
5497 Res = WidenVecRes_VECTOR_REVERSE(N);
5498 break;
5500 Res = WidenVecRes_GET_ACTIVE_LANE_MASK(N);
5501 break;
5503 WidenVecRes_VECTOR_INTERLEAVE(N);
5504 break;
5505 case ISD::VECTOR_MATCH:
5506 Res = WidenVecRes_VECTOR_MATCH(N);
5507 break;
5509 WidenVecRes_VECTOR_DEINTERLEAVE(N);
5510 break;
5511
5512 case ISD::ADD:
5513 case ISD::AND:
5514 case ISD::MUL:
5515 case ISD::MULHS:
5516 case ISD::MULHU:
5517 case ISD::ABDS:
5518 case ISD::ABDU:
5519 case ISD::OR:
5520 case ISD::SUB:
5521 case ISD::XOR:
5522 case ISD::SHL:
5523 case ISD::SRA:
5524 case ISD::SRL:
5525 case ISD::CLMUL:
5526 case ISD::CLMULR:
5527 case ISD::CLMULH:
5528 case ISD::PEXT:
5529 case ISD::PDEP:
5530 case ISD::FMINNUM:
5531 case ISD::FMINNUM_IEEE:
5532 case ISD::FMAXNUM:
5533 case ISD::FMAXNUM_IEEE:
5534 case ISD::FMINIMUM:
5535 case ISD::FMAXIMUM:
5536 case ISD::FMINIMUMNUM:
5537 case ISD::FMAXIMUMNUM:
5538 case ISD::SMIN:
5539 case ISD::SMAX:
5540 case ISD::UMIN:
5541 case ISD::UMAX:
5542 case ISD::UADDSAT:
5543 case ISD::SADDSAT:
5544 case ISD::USUBSAT:
5545 case ISD::SSUBSAT:
5546 case ISD::SSHLSAT:
5547 case ISD::USHLSAT:
5548 case ISD::ROTL:
5549 case ISD::ROTR:
5550 case ISD::AVGFLOORS:
5551 case ISD::AVGFLOORU:
5552 case ISD::AVGCEILS:
5553 case ISD::AVGCEILU:
5554 case ISD::AVGSUBFLOORS:
5555 case ISD::AVGSUBFLOORU:
5556 // Vector-predicated binary op widening. Note that -- unlike the
5557 // unpredicated versions -- we don't have to worry about trapping on
5558 // operations like UDIV, FADD, etc., as we pass on the original vector
5559 // length parameter. This means the widened elements containing garbage
5560 // aren't active.
5561 case ISD::VP_SDIV:
5562 case ISD::VP_UDIV:
5563 case ISD::VP_SREM:
5564 case ISD::VP_UREM:
5565 Res = WidenVecRes_Binary(N);
5566 break;
5567
5568 case ISD::MASKED_UDIV:
5569 case ISD::MASKED_SDIV:
5570 case ISD::MASKED_UREM:
5571 case ISD::MASKED_SREM:
5572 Res = WidenVecRes_MaskedBinary(N);
5573 break;
5574
5575 case ISD::SCMP:
5576 case ISD::UCMP:
5577 Res = WidenVecRes_CMP(N);
5578 break;
5579
5580 case ISD::FPOW:
5581 case ISD::FATAN2:
5582 case ISD::FREM:
5583 if (unrollExpandedOp())
5584 break;
5585 // If the target has custom/legal support for the scalar FP intrinsic ops
5586 // (they are probably not destined to become libcalls), then widen those
5587 // like any other binary ops.
5588 [[fallthrough]];
5589
5590 case ISD::FADD:
5591 case ISD::FMUL:
5592 case ISD::FSUB:
5593 case ISD::FDIV:
5594 case ISD::SDIV:
5595 case ISD::UDIV:
5596 case ISD::SREM:
5597 case ISD::UREM:
5598 Res = WidenVecRes_BinaryCanTrap(N);
5599 break;
5600
5601 case ISD::SMULFIX:
5602 case ISD::SMULFIXSAT:
5603 case ISD::UMULFIX:
5604 case ISD::UMULFIXSAT:
5605 // These are binary operations, but with an extra operand that shouldn't
5606 // be widened (the scale).
5607 Res = WidenVecRes_BinaryWithExtraScalarOp(N);
5608 break;
5609
5610#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
5611 case ISD::STRICT_##DAGN:
5612#include "llvm/IR/ConstrainedOps.def"
5613 Res = WidenVecRes_StrictFP(N);
5614 break;
5615
5616 case ISD::UADDO:
5617 case ISD::SADDO:
5618 case ISD::USUBO:
5619 case ISD::SSUBO:
5620 case ISD::UMULO:
5621 case ISD::SMULO:
5622 Res = WidenVecRes_OverflowOp(N, ResNo);
5623 break;
5624
5625 case ISD::FCOPYSIGN:
5626 Res = WidenVecRes_FCOPYSIGN(N);
5627 break;
5628
5629 case ISD::IS_FPCLASS:
5630 case ISD::FPTRUNC_ROUND:
5631 Res = WidenVecRes_UnarySameEltsWithScalarArg(N);
5632 break;
5633
5634 case ISD::FLDEXP:
5635 case ISD::FPOWI:
5636 if (!unrollExpandedOp())
5637 Res = WidenVecRes_ExpOp(N);
5638 break;
5639
5643 Res = WidenVecRes_EXTEND_VECTOR_INREG(N);
5644 break;
5645
5646 case ISD::ANY_EXTEND:
5647 case ISD::FP_EXTEND:
5648 case ISD::FP_ROUND:
5649 case ISD::FP_TO_SINT:
5650 case ISD::FP_TO_UINT:
5651 case ISD::SIGN_EXTEND:
5652 case ISD::SINT_TO_FP:
5653 case ISD::TRUNCATE:
5654 case ISD::UINT_TO_FP:
5655 case ISD::ZERO_EXTEND:
5658 Res = WidenVecRes_Convert(N);
5659 break;
5660
5663 Res = WidenVecRes_FP_TO_XINT_SAT(N);
5664 break;
5665
5666 case ISD::LRINT:
5667 case ISD::LLRINT:
5668 case ISD::LROUND:
5669 case ISD::LLROUND:
5670 Res = WidenVecRes_XROUND(N);
5671 break;
5672
5673 case ISD::FACOS:
5674 case ISD::FASIN:
5675 case ISD::FATAN:
5676 case ISD::FCEIL:
5677 case ISD::FCOS:
5678 case ISD::FCOSH:
5679 case ISD::FEXP:
5680 case ISD::FEXP2:
5681 case ISD::FEXP10:
5682 case ISD::FFLOOR:
5683 case ISD::FLOG:
5684 case ISD::FLOG10:
5685 case ISD::FLOG2:
5686 case ISD::FNEARBYINT:
5687 case ISD::FRINT:
5688 case ISD::FROUND:
5689 case ISD::FROUNDEVEN:
5690 case ISD::FSIN:
5691 case ISD::FSINH:
5692 case ISD::FSQRT:
5693 case ISD::FTAN:
5694 case ISD::FTANH:
5695 case ISD::FTRUNC:
5696 if (unrollExpandedOp())
5697 break;
5698 // If the target has custom/legal support for the scalar FP intrinsic ops
5699 // (they are probably not destined to become libcalls), then widen those
5700 // like any other unary ops.
5701 [[fallthrough]];
5702
5703 case ISD::ABS:
5705 case ISD::BITREVERSE:
5706 case ISD::BSWAP:
5707 case ISD::CTLZ:
5709 case ISD::CTPOP:
5710 case ISD::CTTZ:
5712 case ISD::FNEG:
5713 case ISD::FABS:
5714 case ISD::FREEZE:
5715 case ISD::ARITH_FENCE:
5716 case ISD::FCANONICALIZE:
5719 Res = WidenVecRes_Unary(N);
5720 break;
5721 case ISD::FMA:
5722 case ISD::FSHL:
5723 case ISD::FSHR:
5724 Res = WidenVecRes_Ternary(N);
5725 break;
5726 case ISD::FMODF:
5727 case ISD::FFREXP:
5728 case ISD::FSINCOS:
5729 case ISD::FSINCOSPI: {
5730 if (!unrollExpandedOp())
5731 Res = WidenVecRes_UnaryOpWithTwoResults(N, ResNo);
5732 break;
5733 }
5738 Res = WidenVecRes_PARTIAL_REDUCE_MLA(N);
5739 break;
5740 }
5741
5742 // If Res is null, the sub-method took care of registering the result.
5743 if (Res.getNode())
5744 SetWidenedVector(SDValue(N, ResNo), Res);
5745}
5746
5747SDValue DAGTypeLegalizer::WidenVecRes_Ternary(SDNode *N) {
5748 // Ternary op widening.
5749 SDLoc dl(N);
5750 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5751 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5752 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5753 SDValue InOp3 = GetWidenedVector(N->getOperand(2));
5754 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3);
5755}
5756
5757SDValue DAGTypeLegalizer::WidenVecRes_Binary(SDNode *N) {
5758 // Binary op widening.
5759 SDLoc dl(N);
5760 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5761 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5762 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5763 if (N->getNumOperands() == 2)
5764 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2,
5765 N->getFlags());
5766
5767 assert(N->getNumOperands() == 4 && "Unexpected number of operands!");
5768 assert((N->getOpcode() == ISD::VP_UDIV || N->getOpcode() == ISD::VP_SDIV ||
5769 N->getOpcode() == ISD::VP_UREM || N->getOpcode() == ISD::VP_SREM) &&
5770 "Expected VP opcode");
5771
5772 SDValue Mask =
5773 GetWidenedMask(N->getOperand(2), WidenVT.getVectorElementCount());
5774 return DAG.getNode(N->getOpcode(), dl, WidenVT,
5775 {InOp1, InOp2, Mask, N->getOperand(3)}, N->getFlags());
5776}
5777
5778SDValue DAGTypeLegalizer::WidenVecRes_MaskedBinary(SDNode *N) {
5779 SDLoc dl(N);
5780 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5781 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5782 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5783 SDValue Mask = N->getOperand(2);
5784 EVT WideMaskVT = WidenVT.changeVectorElementType(
5785 *DAG.getContext(), Mask.getValueType().getVectorElementType());
5786 Mask = ModifyToType(Mask, WideMaskVT, /*FillWithZeros=*/true);
5787 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, Mask,
5788 N->getFlags());
5789}
5790
5791SDValue DAGTypeLegalizer::WidenVecRes_CMP(SDNode *N) {
5792 LLVMContext &Ctxt = *DAG.getContext();
5793 SDLoc dl(N);
5794
5795 SDValue LHS = N->getOperand(0);
5796 SDValue RHS = N->getOperand(1);
5797 EVT OpVT = LHS.getValueType();
5798 if (getTypeAction(OpVT) == TargetLowering::TypeWidenVector) {
5799 LHS = GetWidenedVector(LHS);
5800 RHS = GetWidenedVector(RHS);
5801 OpVT = LHS.getValueType();
5802 }
5803
5804 EVT WidenResVT = TLI.getTypeToTransformTo(Ctxt, N->getValueType(0));
5805 ElementCount WidenResEC = WidenResVT.getVectorElementCount();
5806 if (WidenResEC == OpVT.getVectorElementCount()) {
5807 return DAG.getNode(N->getOpcode(), dl, WidenResVT, LHS, RHS);
5808 }
5809
5810 return DAG.UnrollVectorOp(N, WidenResVT.getVectorNumElements());
5811}
5812
5813SDValue DAGTypeLegalizer::WidenVecRes_BinaryWithExtraScalarOp(SDNode *N) {
5814 // Binary op widening, but with an extra operand that shouldn't be widened.
5815 SDLoc dl(N);
5816 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5817 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5818 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5819 SDValue InOp3 = N->getOperand(2);
5820 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3,
5821 N->getFlags());
5822}
5823
5824// Given a vector of operations that have been broken up to widen, see
5825// if we can collect them together into the next widest legal VT. This
5826// implementation is trap-safe.
5828 SmallVectorImpl<SDValue> &ConcatOps,
5829 unsigned ConcatEnd, EVT VT, EVT MaxVT,
5830 EVT WidenVT) {
5831 // Check to see if we have a single operation with the widen type.
5832 if (ConcatEnd == 1) {
5833 VT = ConcatOps[0].getValueType();
5834 if (VT == WidenVT)
5835 return ConcatOps[0];
5836 }
5837
5838 SDLoc dl(ConcatOps[0]);
5839 EVT WidenEltVT = WidenVT.getVectorElementType();
5840
5841 // while (Some element of ConcatOps is not of type MaxVT) {
5842 // From the end of ConcatOps, collect elements of the same type and put
5843 // them into an op of the next larger supported type
5844 // }
5845 while (ConcatOps[ConcatEnd-1].getValueType() != MaxVT) {
5846 int Idx = ConcatEnd - 1;
5847 VT = ConcatOps[Idx--].getValueType();
5848 while (Idx >= 0 && ConcatOps[Idx].getValueType() == VT)
5849 Idx--;
5850
5851 int NextSize = VT.isVector() ? VT.getVectorNumElements() : 1;
5852 EVT NextVT;
5853 do {
5854 NextSize *= 2;
5855 NextVT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NextSize);
5856 } while (!TLI.isTypeLegal(NextVT));
5857
5858 if (!VT.isVector()) {
5859 // Scalar type, create an INSERT_VECTOR_ELEMENT of type NextVT
5860 SDValue VecOp = DAG.getPOISON(NextVT);
5861 unsigned NumToInsert = ConcatEnd - Idx - 1;
5862 for (unsigned i = 0, OpIdx = Idx + 1; i < NumToInsert; i++, OpIdx++)
5863 VecOp = DAG.getInsertVectorElt(dl, VecOp, ConcatOps[OpIdx], i);
5864 ConcatOps[Idx+1] = VecOp;
5865 ConcatEnd = Idx + 2;
5866 } else {
5867 // Vector type, create a CONCAT_VECTORS of type NextVT
5868 SDValue undefVec = DAG.getPOISON(VT);
5869 unsigned OpsToConcat = NextSize/VT.getVectorNumElements();
5870 SmallVector<SDValue, 16> SubConcatOps(OpsToConcat);
5871 unsigned RealVals = ConcatEnd - Idx - 1;
5872 unsigned SubConcatEnd = 0;
5873 unsigned SubConcatIdx = Idx + 1;
5874 while (SubConcatEnd < RealVals)
5875 SubConcatOps[SubConcatEnd++] = ConcatOps[++Idx];
5876 while (SubConcatEnd < OpsToConcat)
5877 SubConcatOps[SubConcatEnd++] = undefVec;
5878 ConcatOps[SubConcatIdx] = DAG.getNode(ISD::CONCAT_VECTORS, dl,
5879 NextVT, SubConcatOps);
5880 ConcatEnd = SubConcatIdx + 1;
5881 }
5882 }
5883
5884 // Check to see if we have a single operation with the widen type.
5885 if (ConcatEnd == 1) {
5886 VT = ConcatOps[0].getValueType();
5887 if (VT == WidenVT)
5888 return ConcatOps[0];
5889 }
5890
5891 // add undefs of size MaxVT until ConcatOps grows to length of WidenVT
5893 MaxVT.getVectorElementCount());
5894 if (NumOps != ConcatEnd ) {
5895 SDValue UndefVal = DAG.getPOISON(MaxVT);
5896 for (unsigned j = ConcatEnd; j < NumOps; ++j)
5897 ConcatOps[j] = UndefVal;
5898 }
5899 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
5900 ArrayRef(ConcatOps.data(), NumOps));
5901}
5902
5903SDValue DAGTypeLegalizer::WidenVecRes_BinaryCanTrap(SDNode *N) {
5904 // Binary op widening for operations that can trap.
5905 unsigned Opcode = N->getOpcode();
5906 SDLoc dl(N);
5907 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5908 EVT VT = WidenVT;
5909 ElementCount NumElts = VT.getVectorElementCount();
5910 const SDNodeFlags Flags = N->getFlags();
5911 while (!TLI.isTypeLegal(VT) && NumElts.getKnownMinValue() != 1) {
5912 NumElts = NumElts.divideCoefficientBy(2);
5913 VT = VT.changeVectorElementCount(*DAG.getContext(), NumElts);
5914 }
5915
5916 bool FoundLegalVectorType = TLI.isTypeLegal(VT) && !NumElts.isScalar();
5917 if (FoundLegalVectorType && DAG.isSafeToSpeculativelyExecute(Opcode)) {
5918 // Operation can be speculatively executed so just widen as normal.
5919 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5920 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5921 return DAG.getNode(Opcode, dl, WidenVT, InOp1, InOp2, Flags);
5922 }
5923
5924 // Generate a vp.op if it is custom/legal for the target. This avoids need
5925 // to split and tile the subvectors (below), because the inactive lanes can
5926 // simply be disabled. To avoid possible recursion, only do this if the
5927 // widened mask type is legal.
5928 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opcode);
5929 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WidenVT)) {
5930 if (EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
5931 WidenVT.getVectorElementCount());
5932 TLI.isTypeLegal(WideMaskVT)) {
5933 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5934 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5935 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
5936 SDValue EVL =
5937 DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
5938 N->getValueType(0).getVectorElementCount());
5939 return DAG.getNode(*VPOpcode, dl, WidenVT, InOp1, InOp2, Mask, EVL,
5940 Flags);
5941 }
5942 }
5943
5944 // No legal vector version so unroll the vector operation and then widen.
5945 if (NumElts.isScalar())
5946 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
5947
5948 if (!TLI.isTypeLegal(VT))
5949 report_fatal_error("Cannot widen scalable vector trapping binop!");
5950
5951 // Since the operation can trap, apply operation on the original vector.
5952 EVT MaxVT = VT;
5953 EVT EltVT = VT.getVectorElementType();
5954 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5955 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5956 ElementCount CurNumElts = N->getValueType(0).getVectorElementCount();
5957
5958 SmallVector<SDValue, 16> ConcatOps(CurNumElts.getKnownMinValue());
5959 unsigned ConcatEnd = 0; // Current ConcatOps index.
5960 int Idx = 0; // Current Idx into input vectors.
5961
5962 // NumElts := greatest legal vector size (at most WidenVT)
5963 // while (orig. vector has unhandled elements) {
5964 // take munches of size NumElts from the beginning and add to ConcatOps
5965 // NumElts := next smaller supported vector size or 1
5966 // }
5967 for (;;) {
5968 while (ElementCount::isKnownGE(CurNumElts, NumElts)) {
5969 SDValue EOp1 = DAG.getExtractSubvector(dl, VT, InOp1, Idx);
5970 SDValue EOp2 = DAG.getExtractSubvector(dl, VT, InOp2, Idx);
5971 ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, VT, EOp1, EOp2, Flags);
5972 // Subvector indices are implicitly scaled by vscale.
5973 Idx += NumElts.getKnownMinValue();
5974 CurNumElts -= NumElts;
5975 }
5976
5977 if (CurNumElts.isZero())
5978 break;
5979
5980 // Find the next smaller legal vector type.
5981 do {
5982 NumElts = NumElts.divideCoefficientBy(2);
5983 VT = VT.changeVectorElementCount(*DAG.getContext(), NumElts);
5984 } while (!TLI.isTypeLegal(VT) && NumElts.getKnownMinValue() != 1);
5985
5986 if (NumElts.isScalar()) {
5987 // Scalarize the non-type-legal remainder.
5988 for (unsigned i = 0; i != CurNumElts.getFixedValue(); ++i, ++Idx) {
5989 SDValue EOp1 = DAG.getExtractVectorElt(dl, EltVT, InOp1, Idx);
5990 SDValue EOp2 = DAG.getExtractVectorElt(dl, EltVT, InOp2, Idx);
5991 ConcatOps[ConcatEnd++] =
5992 DAG.getNode(Opcode, dl, EltVT, EOp1, EOp2, Flags);
5993 }
5994
5995 break;
5996 }
5997
5998 if (!TLI.isTypeLegal(VT))
5999 report_fatal_error("scalarization of scalable vectors is not supported");
6000 }
6001
6002 return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
6003}
6004
6005SDValue DAGTypeLegalizer::WidenVecRes_StrictFP(SDNode *N) {
6006 switch (N->getOpcode()) {
6007 case ISD::STRICT_FSETCC:
6009 return WidenVecRes_STRICT_FSETCC(N);
6016 return WidenVecRes_Convert_StrictFP(N);
6017 default:
6018 break;
6019 }
6020
6021 // StrictFP op widening for operations that can trap.
6022 unsigned NumOpers = N->getNumOperands();
6023 unsigned Opcode = N->getOpcode();
6024 SDLoc dl(N);
6025 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6026 EVT WidenEltVT = WidenVT.getVectorElementType();
6027 EVT VT = WidenVT;
6028 unsigned NumElts = VT.getVectorNumElements();
6029 while (!TLI.isTypeLegal(VT) && NumElts != 1) {
6030 NumElts = NumElts / 2;
6031 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
6032 }
6033
6034 // No legal vector version so unroll the vector operation and then widen.
6035 if (NumElts == 1)
6036 return UnrollVectorOp_StrictFP(N, WidenVT.getVectorNumElements());
6037
6038 // Since the operation can trap, apply operation on the original vector.
6039 EVT MaxVT = VT;
6041 unsigned CurNumElts = N->getValueType(0).getVectorNumElements();
6042
6043 SmallVector<SDValue, 16> ConcatOps(CurNumElts);
6045 unsigned ConcatEnd = 0; // Current ConcatOps index.
6046 int Idx = 0; // Current Idx into input vectors.
6047
6048 // The Chain is the first operand.
6049 InOps.push_back(N->getOperand(0));
6050
6051 // Now process the remaining operands.
6052 for (unsigned i = 1; i < NumOpers; ++i) {
6053 SDValue Oper = N->getOperand(i);
6054
6055 EVT OpVT = Oper.getValueType();
6056 if (OpVT.isVector()) {
6057 if (getTypeAction(OpVT) == TargetLowering::TypeWidenVector)
6058 Oper = GetWidenedVector(Oper);
6059 else {
6060 EVT WideOpVT =
6061 EVT::getVectorVT(*DAG.getContext(), OpVT.getVectorElementType(),
6062 WidenVT.getVectorElementCount());
6063 Oper = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WideOpVT,
6064 DAG.getPOISON(WideOpVT), Oper,
6065 DAG.getVectorIdxConstant(0, dl));
6066 }
6067 }
6068
6069 InOps.push_back(Oper);
6070 }
6071
6072 // NumElts := greatest legal vector size (at most WidenVT)
6073 // while (orig. vector has unhandled elements) {
6074 // take munches of size NumElts from the beginning and add to ConcatOps
6075 // NumElts := next smaller supported vector size or 1
6076 // }
6077 while (CurNumElts != 0) {
6078 while (CurNumElts >= NumElts) {
6080
6081 for (unsigned i = 0; i < NumOpers; ++i) {
6082 SDValue Op = InOps[i];
6083
6084 EVT OpVT = Op.getValueType();
6085 if (OpVT.isVector()) {
6086 EVT OpExtractVT =
6087 EVT::getVectorVT(*DAG.getContext(), OpVT.getVectorElementType(),
6089 Op = DAG.getExtractSubvector(dl, OpExtractVT, Op, Idx);
6090 }
6091
6092 EOps.push_back(Op);
6093 }
6094
6095 EVT OperVT[] = {VT, MVT::Other};
6096 SDValue Oper = DAG.getNode(Opcode, dl, OperVT, EOps);
6097 ConcatOps[ConcatEnd++] = Oper;
6098 Chains.push_back(Oper.getValue(1));
6099 Idx += NumElts;
6100 CurNumElts -= NumElts;
6101 }
6102 do {
6103 NumElts = NumElts / 2;
6104 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
6105 } while (!TLI.isTypeLegal(VT) && NumElts != 1);
6106
6107 if (NumElts == 1) {
6108 for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
6110
6111 for (unsigned i = 0; i < NumOpers; ++i) {
6112 SDValue Op = InOps[i];
6113
6114 EVT OpVT = Op.getValueType();
6115 if (OpVT.isVector())
6116 Op = DAG.getExtractVectorElt(dl, OpVT.getVectorElementType(), Op,
6117 Idx);
6118
6119 EOps.push_back(Op);
6120 }
6121
6122 EVT WidenVT[] = {WidenEltVT, MVT::Other};
6123 SDValue Oper = DAG.getNode(Opcode, dl, WidenVT, EOps);
6124 ConcatOps[ConcatEnd++] = Oper;
6125 Chains.push_back(Oper.getValue(1));
6126 }
6127 CurNumElts = 0;
6128 }
6129 }
6130
6131 // Build a factor node to remember all the Ops that have been created.
6132 SDValue NewChain;
6133 if (Chains.size() == 1)
6134 NewChain = Chains[0];
6135 else
6136 NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
6137 ReplaceValueWith(SDValue(N, 1), NewChain);
6138
6139 return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
6140}
6141
6142SDValue DAGTypeLegalizer::WidenVecRes_OverflowOp(SDNode *N, unsigned ResNo) {
6143 SDLoc DL(N);
6144 EVT ResVT = N->getValueType(0);
6145 EVT OvVT = N->getValueType(1);
6146 EVT WideResVT, WideOvVT;
6147 SDValue WideLHS, WideRHS;
6148
6149 // TODO: This might result in a widen/split loop.
6150 if (ResNo == 0) {
6151 WideResVT = TLI.getTypeToTransformTo(*DAG.getContext(), ResVT);
6152 WideOvVT = EVT::getVectorVT(
6153 *DAG.getContext(), OvVT.getVectorElementType(),
6154 WideResVT.getVectorNumElements());
6155
6156 WideLHS = GetWidenedVector(N->getOperand(0));
6157 WideRHS = GetWidenedVector(N->getOperand(1));
6158 } else {
6159 WideOvVT = TLI.getTypeToTransformTo(*DAG.getContext(), OvVT);
6160 WideResVT = EVT::getVectorVT(
6161 *DAG.getContext(), ResVT.getVectorElementType(),
6162 WideOvVT.getVectorNumElements());
6163
6164 SDValue Zero = DAG.getVectorIdxConstant(0, DL);
6165 SDValue Poison = DAG.getPOISON(WideResVT);
6166
6167 WideLHS = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideResVT, Poison,
6168 N->getOperand(0), Zero);
6169 WideRHS = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideResVT, Poison,
6170 N->getOperand(1), Zero);
6171 }
6172
6173 SDVTList WideVTs = DAG.getVTList(WideResVT, WideOvVT);
6174 SDNode *WideNode = DAG.getNode(
6175 N->getOpcode(), DL, WideVTs, WideLHS, WideRHS).getNode();
6176
6177 // Replace the other vector result not being explicitly widened here.
6178 unsigned OtherNo = 1 - ResNo;
6179 EVT OtherVT = N->getValueType(OtherNo);
6180 if (getTypeAction(OtherVT) == TargetLowering::TypeWidenVector) {
6181 SetWidenedVector(SDValue(N, OtherNo), SDValue(WideNode, OtherNo));
6182 } else {
6183 SDValue Zero = DAG.getVectorIdxConstant(0, DL);
6184 SDValue OtherVal = DAG.getNode(
6185 ISD::EXTRACT_SUBVECTOR, DL, OtherVT, SDValue(WideNode, OtherNo), Zero);
6186 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
6187 }
6188
6189 return SDValue(WideNode, ResNo);
6190}
6191
6192SDValue DAGTypeLegalizer::WidenVecRes_Convert(SDNode *N) {
6193 LLVMContext &Ctx = *DAG.getContext();
6194 SDValue InOp = N->getOperand(0);
6195 SDLoc DL(N);
6196
6197 EVT WidenVT = TLI.getTypeToTransformTo(Ctx, N->getValueType(0));
6198 ElementCount WidenEC = WidenVT.getVectorElementCount();
6199
6200 EVT InVT = InOp.getValueType();
6201
6202 unsigned Opcode = N->getOpcode();
6203 const SDNodeFlags Flags = N->getFlags();
6204
6205 // Handle the case of ZERO_EXTEND where the promoted InVT element size does
6206 // not equal that of WidenVT.
6207 if (N->getOpcode() == ISD::ZERO_EXTEND &&
6208 getTypeAction(InVT) == TargetLowering::TypePromoteInteger &&
6209 TLI.getTypeToTransformTo(Ctx, InVT).getScalarSizeInBits() !=
6210 WidenVT.getScalarSizeInBits()) {
6211 InOp = ZExtPromotedInteger(InOp);
6212 InVT = InOp.getValueType();
6213 if (WidenVT.getScalarSizeInBits() < InVT.getScalarSizeInBits())
6214 Opcode = ISD::TRUNCATE;
6215 }
6216
6217 EVT InEltVT = InVT.getVectorElementType();
6218 EVT InWidenVT = EVT::getVectorVT(Ctx, InEltVT, WidenEC);
6219 ElementCount InVTEC = InVT.getVectorElementCount();
6220
6221 // Helper to build node with all scalar trailing operands.
6222 auto MakeConvertNode = [&](EVT VT, SDValue Op) -> SDValue {
6223 if (N->getNumOperands() == 1)
6224 return DAG.getNode(Opcode, DL, VT, Op, Flags);
6225 if (Opcode == ISD::CONVERT_TO_ARBITRARY_FP)
6226 return DAG.getNode(Opcode, DL, VT, Op, N->getOperand(1), N->getOperand(2),
6227 N->getOperand(3), Flags);
6228 return DAG.getNode(Opcode, DL, VT, Op, N->getOperand(1), Flags);
6229 };
6230
6231 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
6232 InOp = GetWidenedVector(N->getOperand(0));
6233 InVT = InOp.getValueType();
6234 InVTEC = InVT.getVectorElementCount();
6235 if (InVTEC == WidenEC)
6236 return MakeConvertNode(WidenVT, InOp);
6237 if (WidenVT.getSizeInBits() == InVT.getSizeInBits()) {
6238 // If both input and result vector types are of same width, extend
6239 // operations should be done with SIGN/ZERO_EXTEND_VECTOR_INREG, which
6240 // accepts fewer elements in the result than in the input.
6241 if (Opcode == ISD::ANY_EXTEND)
6242 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
6243 if (Opcode == ISD::SIGN_EXTEND)
6244 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
6245 if (Opcode == ISD::ZERO_EXTEND)
6246 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
6247 }
6248
6249 // For TRUNCATE, try to widen using the legal EC of the input type instead
6250 // if the legalisation action for that intermediate type is not widening.
6251 // E.g. for trunc nxv1i64 -> nxv1i8 where
6252 // - nxv1i64 input gets widened to nxv2i64
6253 // - nxv1i8 output gets widened to nxv16i8
6254 // Then one can try widening the result to nxv2i8 (instead of going all the
6255 // way to nxv16i8) if this later allows type promotion.
6256 EVT MidResVT =
6257 EVT::getVectorVT(Ctx, WidenVT.getVectorElementType(), InVTEC);
6258 if (N->getOpcode() == ISD::TRUNCATE &&
6259 getTypeAction(MidResVT) == TargetLowering::TypePromoteInteger) {
6260 SDValue MidRes = DAG.getNode(ISD::TRUNCATE, DL, MidResVT, InOp, Flags);
6261 return DAG.getInsertSubvector(DL, DAG.getPOISON(WidenVT), MidRes, 0);
6262 }
6263 }
6264
6265 if (TLI.isTypeLegal(InWidenVT)) {
6266 // Because the result and the input are different vector types, widening
6267 // the result could create a legal type but widening the input might make
6268 // it an illegal type that might lead to repeatedly splitting the input
6269 // and then widening it. To avoid this, we widen the input only if
6270 // it results in a legal type.
6271 if (WidenEC.isKnownMultipleOf(InVTEC.getKnownMinValue())) {
6272 // Widen the input and call convert on the widened input vector.
6273 unsigned NumConcat =
6274 WidenEC.getKnownMinValue() / InVTEC.getKnownMinValue();
6275 SmallVector<SDValue, 16> Ops(NumConcat, DAG.getPOISON(InVT));
6276 Ops[0] = InOp;
6277 SDValue InVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InWidenVT, Ops);
6278 return MakeConvertNode(WidenVT, InVec);
6279 }
6280
6281 if (InVTEC.isKnownMultipleOf(WidenEC.getKnownMinValue())) {
6282 SDValue InVal = DAG.getExtractSubvector(DL, InWidenVT, InOp, 0);
6283 // Extract the input and convert the shorten input vector.
6284 return MakeConvertNode(WidenVT, InVal);
6285 }
6286 }
6287
6288 // Otherwise unroll into some nasty scalar code and rebuild the vector.
6289 EVT EltVT = WidenVT.getVectorElementType();
6290 SmallVector<SDValue, 16> Ops(WidenEC.getFixedValue(), DAG.getPOISON(EltVT));
6291 // Use the original element count so we don't do more scalar opts than
6292 // necessary.
6293 unsigned MinElts = N->getValueType(0).getVectorNumElements();
6294 for (unsigned i=0; i < MinElts; ++i) {
6295 SDValue Val = DAG.getExtractVectorElt(DL, InEltVT, InOp, i);
6296 Ops[i] = MakeConvertNode(EltVT, Val);
6297 }
6298
6299 return DAG.getBuildVector(WidenVT, DL, Ops);
6300}
6301
6302SDValue DAGTypeLegalizer::WidenVecRes_FP_TO_XINT_SAT(SDNode *N) {
6303 SDLoc dl(N);
6304 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6305 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
6306
6307 SDValue Src = N->getOperand(0);
6308 EVT SrcVT = Src.getValueType();
6309
6310 // Also widen the input.
6311 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
6312 Src = GetWidenedVector(Src);
6313 SrcVT = Src.getValueType();
6314 }
6315
6316 // Input and output not widened to the same size, give up.
6317 if (WidenNumElts != SrcVT.getVectorElementCount())
6318 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
6319
6320 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src, N->getOperand(1));
6321}
6322
6323SDValue DAGTypeLegalizer::WidenVecRes_XROUND(SDNode *N) {
6324 SDLoc dl(N);
6325 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6326 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
6327
6328 SDValue Src = N->getOperand(0);
6329 EVT SrcVT = Src.getValueType();
6330
6331 // Also widen the input.
6332 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
6333 Src = GetWidenedVector(Src);
6334 SrcVT = Src.getValueType();
6335 }
6336
6337 // Input and output not widened to the same size, give up.
6338 if (WidenNumElts != SrcVT.getVectorElementCount())
6339 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
6340
6341 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src);
6342}
6343
6344SDValue DAGTypeLegalizer::WidenVecRes_Convert_StrictFP(SDNode *N) {
6345 SDValue InOp = N->getOperand(1);
6346 SDLoc DL(N);
6347 SmallVector<SDValue, 4> NewOps(N->ops());
6348
6349 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6350 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6351
6352 EVT InVT = InOp.getValueType();
6353 EVT InEltVT = InVT.getVectorElementType();
6354
6355 unsigned Opcode = N->getOpcode();
6356
6357 // FIXME: Optimizations need to be implemented here.
6358
6359 // Otherwise unroll into some nasty scalar code and rebuild the vector.
6360 EVT EltVT = WidenVT.getVectorElementType();
6361 std::array<EVT, 2> EltVTs = {{EltVT, MVT::Other}};
6362 SmallVector<SDValue, 16> Ops(WidenNumElts, DAG.getPOISON(EltVT));
6363 SmallVector<SDValue, 32> OpChains;
6364 // Use the original element count so we don't do more scalar opts than
6365 // necessary.
6366 unsigned MinElts = N->getValueType(0).getVectorNumElements();
6367 for (unsigned i=0; i < MinElts; ++i) {
6368 NewOps[1] = DAG.getExtractVectorElt(DL, InEltVT, InOp, i);
6369 Ops[i] = DAG.getNode(Opcode, DL, EltVTs, NewOps);
6370 OpChains.push_back(Ops[i].getValue(1));
6371 }
6372 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OpChains);
6373 ReplaceValueWith(SDValue(N, 1), NewChain);
6374
6375 return DAG.getBuildVector(WidenVT, DL, Ops);
6376}
6377
6378SDValue DAGTypeLegalizer::WidenVecRes_EXTEND_VECTOR_INREG(SDNode *N) {
6379 unsigned Opcode = N->getOpcode();
6380 SDValue InOp = N->getOperand(0);
6381 SDLoc DL(N);
6382
6383 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6384 EVT WidenSVT = WidenVT.getVectorElementType();
6385 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6386
6387 EVT InVT = InOp.getValueType();
6388 EVT InSVT = InVT.getVectorElementType();
6389 unsigned InVTNumElts = InVT.getVectorNumElements();
6390
6391 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
6392 InOp = GetWidenedVector(InOp);
6393 InVT = InOp.getValueType();
6394 if (InVT.getSizeInBits() == WidenVT.getSizeInBits()) {
6395 switch (Opcode) {
6399 return DAG.getNode(Opcode, DL, WidenVT, InOp);
6400 }
6401 }
6402 }
6403
6404 // Unroll, extend the scalars and rebuild the vector.
6406 for (unsigned i = 0, e = std::min(InVTNumElts, WidenNumElts); i != e; ++i) {
6407 SDValue Val = DAG.getExtractVectorElt(DL, InSVT, InOp, i);
6408 switch (Opcode) {
6410 Val = DAG.getNode(ISD::ANY_EXTEND, DL, WidenSVT, Val);
6411 break;
6413 Val = DAG.getNode(ISD::SIGN_EXTEND, DL, WidenSVT, Val);
6414 break;
6416 Val = DAG.getNode(ISD::ZERO_EXTEND, DL, WidenSVT, Val);
6417 break;
6418 default:
6419 llvm_unreachable("A *_EXTEND_VECTOR_INREG node was expected");
6420 }
6421 Ops.push_back(Val);
6422 }
6423
6424 while (Ops.size() != WidenNumElts)
6425 Ops.push_back(DAG.getPOISON(WidenSVT));
6426
6427 return DAG.getBuildVector(WidenVT, DL, Ops);
6428}
6429
6430SDValue DAGTypeLegalizer::WidenVecRes_FCOPYSIGN(SDNode *N) {
6431 // If this is an FCOPYSIGN with same input types, we can treat it as a
6432 // normal (can trap) binary op.
6433 if (N->getOperand(0).getValueType() == N->getOperand(1).getValueType())
6434 return WidenVecRes_BinaryCanTrap(N);
6435
6436 // If the types are different, fall back to unrolling.
6437 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6438 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
6439}
6440
6441/// Result and first source operand are different scalar types, but must have
6442/// the same number of elements. There is an additional control argument which
6443/// should be passed through unchanged.
6444SDValue DAGTypeLegalizer::WidenVecRes_UnarySameEltsWithScalarArg(SDNode *N) {
6445 SDValue FpValue = N->getOperand(0);
6446 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6447 if (getTypeAction(FpValue.getValueType()) != TargetLowering::TypeWidenVector)
6448 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
6449 SDValue Arg = GetWidenedVector(FpValue);
6450 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, {Arg, N->getOperand(1)},
6451 N->getFlags());
6452}
6453
6454SDValue DAGTypeLegalizer::WidenVecRes_ExpOp(SDNode *N) {
6455 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6456 SDValue InOp = GetWidenedVector(N->getOperand(0));
6457 SDValue RHS = N->getOperand(1);
6458 EVT ExpVT = RHS.getValueType();
6459 SDValue ExpOp = RHS;
6460 if (ExpVT.isVector()) {
6461 EVT WideExpVT = WidenVT.changeVectorElementType(
6462 *DAG.getContext(), ExpVT.getVectorElementType());
6463 ExpOp = ModifyToType(RHS, WideExpVT);
6464 }
6465
6466 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, ExpOp);
6467}
6468
6469SDValue DAGTypeLegalizer::WidenVecRes_Unary(SDNode *N) {
6470 // Unary op widening.
6471 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6472 SDValue InOp = GetWidenedVector(N->getOperand(0));
6473 if (N->getNumOperands() == 1)
6474 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, N->getFlags());
6475 assert(N->getOpcode() == ISD::AssertNoFPClass && "unexpected opcode");
6476 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, N->getOperand(1),
6477 N->getFlags());
6478}
6479
6480SDValue DAGTypeLegalizer::WidenVecRes_InregOp(SDNode *N) {
6481 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6482 EVT ExtVT = EVT::getVectorVT(
6483 *DAG.getContext(),
6484 cast<VTSDNode>(N->getOperand(1))->getVT().getVectorElementType(),
6485 WidenVT.getVectorElementCount());
6486 SDValue WidenLHS = GetWidenedVector(N->getOperand(0));
6487 return DAG.getNode(N->getOpcode(), SDLoc(N),
6488 WidenVT, WidenLHS, DAG.getValueType(ExtVT));
6489}
6490
6491SDValue DAGTypeLegalizer::WidenVecRes_UnaryOpWithTwoResults(SDNode *N,
6492 unsigned ResNo) {
6493 EVT VT0 = N->getValueType(0);
6494 EVT VT1 = N->getValueType(1);
6495
6496 assert(VT0.isVector() && VT1.isVector() &&
6498 "expected both results to be vectors of matching element count");
6499
6500 LLVMContext &Ctx = *DAG.getContext();
6501 SDValue InOp = GetWidenedVector(N->getOperand(0));
6502
6503 EVT WidenVT = TLI.getTypeToTransformTo(Ctx, N->getValueType(ResNo));
6504 ElementCount WidenEC = WidenVT.getVectorElementCount();
6505
6506 EVT WidenVT0 = EVT::getVectorVT(Ctx, VT0.getVectorElementType(), WidenEC);
6507 EVT WidenVT1 = EVT::getVectorVT(Ctx, VT1.getVectorElementType(), WidenEC);
6508
6509 SDNode *WidenNode =
6510 DAG.getNode(N->getOpcode(), SDLoc(N), {WidenVT0, WidenVT1}, InOp)
6511 .getNode();
6512
6513 ReplaceOtherWidenResults(N, WidenNode, ResNo);
6514 return SDValue(WidenNode, ResNo);
6515}
6516
6517SDValue DAGTypeLegalizer::WidenVecRes_MERGE_VALUES(SDNode *N, unsigned ResNo) {
6518 SDValue WidenVec = DisintegrateMERGE_VALUES(N, ResNo);
6519 return GetWidenedVector(WidenVec);
6520}
6521
6522SDValue DAGTypeLegalizer::WidenVecRes_ADDRSPACECAST(SDNode *N) {
6523 SDLoc DL(N);
6524 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6525 ElementCount WidenEC = WidenVT.getVectorElementCount();
6526 auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
6527
6528 // The source has the same number of elements as the result, so widen it to
6529 // match WidenVT. It only lives in the widened-vector map if it is itself
6530 // widened; otherwise pad it up to the widened element count
6531 // when it is illegal.
6532 SDValue InOp = N->getOperand(0);
6533 EVT InVT = InOp.getValueType();
6534 TargetLowering::LegalizeTypeAction InAction = getTypeAction(InVT);
6535 if (InAction == TargetLowering::TypeWidenVector) {
6536 InOp = GetWidenedVector(InOp);
6537 } else if (InAction != TargetLowering::TypeLegal) {
6538 EVT InWidenVT = EVT::getVectorVT(*DAG.getContext(),
6539 InVT.getVectorElementType(), WidenEC);
6540 InOp = DAG.getInsertSubvector(DL, DAG.getPOISON(InWidenVT), InOp, 0);
6541 }
6542
6543 return DAG.getAddrSpaceCast(
6544 DL, WidenVT, InOp, AddrSpaceCastN->getSrcAddressSpace(),
6545 AddrSpaceCastN->getDestAddressSpace(), AddrSpaceCastN->getFlags());
6546}
6547
6548SDValue DAGTypeLegalizer::WidenVecRes_BITCAST(SDNode *N) {
6549 SDValue InOp = N->getOperand(0);
6550 EVT InVT = InOp.getValueType();
6551 EVT VT = N->getValueType(0);
6552 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6553 SDLoc dl(N);
6554
6555 switch (getTypeAction(InVT)) {
6557 break;
6559 report_fatal_error("scalarization of scalable vectors is not supported");
6561 // If the incoming type is a vector that is being promoted, then
6562 // we know that the elements are arranged differently and that we
6563 // must perform the conversion using a stack slot.
6564 if (InVT.isVector())
6565 break;
6566
6567 // If the InOp is promoted to the same size, convert it. Otherwise,
6568 // fall out of the switch and widen the promoted input.
6569 SDValue NInOp = GetPromotedInteger(InOp);
6570 EVT NInVT = NInOp.getValueType();
6571 if (WidenVT.bitsEq(NInVT)) {
6572 // For big endian targets we need to shift the input integer or the
6573 // interesting bits will end up at the wrong place.
6574 if (DAG.getDataLayout().isBigEndian()) {
6575 unsigned ShiftAmt = NInVT.getSizeInBits() - InVT.getSizeInBits();
6576 NInOp = DAG.getNode(ISD::SHL, dl, NInVT, NInOp,
6577 DAG.getShiftAmountConstant(ShiftAmt, NInVT, dl));
6578 }
6579 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NInOp);
6580 }
6581 InOp = NInOp;
6582 InVT = NInVT;
6583 break;
6584 }
6591 break;
6593 // If the InOp is widened to the same size, convert it. Otherwise, fall
6594 // out of the switch and widen the widened input.
6595 InOp = GetWidenedVector(InOp);
6596 InVT = InOp.getValueType();
6597 if (WidenVT.bitsEq(InVT))
6598 // The input widens to the same size. Convert to the widen value.
6599 return DAG.getNode(ISD::BITCAST, dl, WidenVT, InOp);
6600 break;
6601 }
6602
6603 unsigned WidenSize = WidenVT.getSizeInBits();
6604 unsigned InSize = InVT.getSizeInBits();
6605 unsigned InScalarSize = InVT.getScalarSizeInBits();
6606 // x86mmx is not an acceptable vector element type, so don't try.
6607 if (WidenSize % InScalarSize == 0 && InVT != MVT::x86mmx) {
6608 // Determine new input vector type. The new input vector type will use
6609 // the same element type (if its a vector) or use the input type as a
6610 // vector. It is the same size as the type to widen to.
6611 EVT NewInVT;
6612 unsigned NewNumParts = WidenSize / InSize;
6613 if (InVT.isVector()) {
6614 EVT InEltVT = InVT.getVectorElementType();
6615 NewInVT = EVT::getVectorVT(*DAG.getContext(), InEltVT,
6616 WidenSize / InEltVT.getSizeInBits());
6617 } else {
6618 // For big endian systems, using the promoted input scalar type
6619 // to produce the scalar_to_vector would put the desired bits into
6620 // the least significant byte(s) of the wider element zero. This
6621 // will mean that the users of the result vector are using incorrect
6622 // bits. Use the original input type instead. Although either input
6623 // type can be used on little endian systems, for consistency we
6624 // use the original type there as well.
6625 EVT OrigInVT = N->getOperand(0).getValueType();
6626 NewNumParts = WidenSize / OrigInVT.getSizeInBits();
6627 NewInVT = EVT::getVectorVT(*DAG.getContext(), OrigInVT, NewNumParts);
6628 }
6629
6630 if (TLI.isTypeLegal(NewInVT)) {
6631 SDValue NewVec;
6632 if (InVT.isVector()) {
6633 // Because the result and the input are different vector types, widening
6634 // the result could create a legal type but widening the input might
6635 // make it an illegal type that might lead to repeatedly splitting the
6636 // input and then widening it. To avoid this, we widen the input only if
6637 // it results in a legal type.
6638 if (WidenSize % InSize == 0) {
6639 SmallVector<SDValue, 16> Ops(NewNumParts, DAG.getPOISON(InVT));
6640 Ops[0] = InOp;
6641
6642 NewVec = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewInVT, Ops);
6643 } else {
6645 DAG.ExtractVectorElements(InOp, Ops);
6646 Ops.append(WidenSize / InScalarSize - Ops.size(),
6647 DAG.getPOISON(InVT.getVectorElementType()));
6648
6649 NewVec = DAG.getNode(ISD::BUILD_VECTOR, dl, NewInVT, Ops);
6650 }
6651 } else {
6652 NewVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewInVT, InOp);
6653 }
6654 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NewVec);
6655 }
6656 }
6657
6658 return CreateStackStoreLoad(InOp, WidenVT);
6659}
6660
6661SDValue DAGTypeLegalizer::WidenVecRes_LOOP_DEPENDENCE_MASK(SDNode *N) {
6662 return DAG.getNode(
6663 N->getOpcode(), SDLoc(N),
6664 TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)),
6665 N->getOperand(0), N->getOperand(1), N->getOperand(2), N->getOperand(3));
6666}
6667
6668SDValue DAGTypeLegalizer::WidenVecRes_BUILD_VECTOR(SDNode *N) {
6669 SDLoc dl(N);
6670 // Build a vector with poison for the new nodes.
6671 EVT VT = N->getValueType(0);
6672
6673 // Integer BUILD_VECTOR operands may be larger than the node's vector element
6674 // type. The POISONs need to have the same type as the existing operands.
6675 EVT EltVT = N->getOperand(0).getValueType();
6676 unsigned NumElts = VT.getVectorNumElements();
6677
6678 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6679 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6680
6681 SmallVector<SDValue, 16> NewOps(N->ops());
6682 assert(WidenNumElts >= NumElts && "Shrinking vector instead of widening!");
6683 NewOps.append(WidenNumElts - NumElts, DAG.getPOISON(EltVT));
6684
6685 return DAG.getBuildVector(WidenVT, dl, NewOps);
6686}
6687
6688SDValue DAGTypeLegalizer::WidenVecRes_CONCAT_VECTORS(SDNode *N) {
6689 EVT InVT = N->getOperand(0).getValueType();
6690 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6691 SDLoc dl(N);
6692 unsigned NumOperands = N->getNumOperands();
6693
6694 bool InputWidened = false; // Indicates we need to widen the input.
6695 if (getTypeAction(InVT) != TargetLowering::TypeWidenVector) {
6696 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6697 unsigned NumInElts = InVT.getVectorMinNumElements();
6698 if (WidenNumElts % NumInElts == 0) {
6699 // Add undef vectors to widen to correct length.
6700 unsigned NumConcat = WidenNumElts / NumInElts;
6701 SDValue UndefVal = DAG.getPOISON(InVT);
6702 SmallVector<SDValue, 16> Ops(NumConcat);
6703 for (unsigned i=0; i < NumOperands; ++i)
6704 Ops[i] = N->getOperand(i);
6705 for (unsigned i = NumOperands; i != NumConcat; ++i)
6706 Ops[i] = UndefVal;
6707 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Ops);
6708 }
6709 } else {
6710 InputWidened = true;
6711 if (WidenVT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
6712 // The inputs and the result are widen to the same value.
6713 unsigned i;
6714 for (i=1; i < NumOperands; ++i)
6715 if (!N->getOperand(i).isUndef())
6716 break;
6717
6718 if (i == NumOperands)
6719 // Everything but the first operand is an UNDEF so just return the
6720 // widened first operand.
6721 return GetWidenedVector(N->getOperand(0));
6722
6723 if (NumOperands == 2) {
6724 assert(!WidenVT.isScalableVector() &&
6725 "Cannot use vector shuffles to widen CONCAT_VECTOR result");
6726 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6727 unsigned NumInElts = InVT.getVectorNumElements();
6728
6729 // Replace concat of two operands with a shuffle.
6730 SmallVector<int, 16> MaskOps(WidenNumElts, -1);
6731 for (unsigned i = 0; i < NumInElts; ++i) {
6732 MaskOps[i] = i;
6733 MaskOps[i + NumInElts] = i + WidenNumElts;
6734 }
6735 return DAG.getVectorShuffle(WidenVT, dl,
6736 GetWidenedVector(N->getOperand(0)),
6737 GetWidenedVector(N->getOperand(1)),
6738 MaskOps);
6739 }
6740 }
6741 }
6742
6743 if (WidenVT.isScalableVector()) {
6744 SDValue WideVec = DAG.getPOISON(WidenVT);
6745 unsigned NumInElts = InVT.getVectorMinNumElements();
6746 for (unsigned I = 0; I < NumOperands; ++I)
6747 WideVec =
6748 DAG.getInsertSubvector(dl, WideVec, N->getOperand(I), I * NumInElts);
6749 return WideVec;
6750 }
6751
6752 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6753 unsigned NumInElts = InVT.getVectorNumElements();
6754
6755 // Fall back to use extracts and build vector.
6756 EVT EltVT = WidenVT.getVectorElementType();
6757 SmallVector<SDValue, 16> Ops(WidenNumElts);
6758 unsigned Idx = 0;
6759 for (unsigned i=0; i < NumOperands; ++i) {
6760 SDValue InOp = N->getOperand(i);
6761 if (InputWidened)
6762 InOp = GetWidenedVector(InOp);
6763 for (unsigned j = 0; j < NumInElts; ++j)
6764 Ops[Idx++] = DAG.getExtractVectorElt(dl, EltVT, InOp, j);
6765 }
6766 SDValue UndefVal = DAG.getPOISON(EltVT);
6767 for (; Idx < WidenNumElts; ++Idx)
6768 Ops[Idx] = UndefVal;
6769 return DAG.getBuildVector(WidenVT, dl, Ops);
6770}
6771
6772SDValue DAGTypeLegalizer::WidenVecRes_INSERT_SUBVECTOR(SDNode *N) {
6773 EVT VT = N->getValueType(0);
6774 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6775 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
6776 SDValue InOp2 = N->getOperand(1);
6777 SDValue Idx = N->getOperand(2);
6778 SDLoc dl(N);
6779 return DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WidenVT, InOp1, InOp2, Idx);
6780}
6781
6782SDValue DAGTypeLegalizer::WidenVecRes_EXTRACT_SUBVECTOR(SDNode *N) {
6783 EVT VT = N->getValueType(0);
6784 EVT EltVT = VT.getVectorElementType();
6785 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6786 SDValue InOp = N->getOperand(0);
6787 SDValue Idx = N->getOperand(1);
6788 SDLoc dl(N);
6789
6790 auto InOpTypeAction = getTypeAction(InOp.getValueType());
6791 if (InOpTypeAction == TargetLowering::TypeWidenVector)
6792 InOp = GetWidenedVector(InOp);
6793
6794 EVT InVT = InOp.getValueType();
6795
6796 // Check if we can just return the input vector after widening.
6797 uint64_t IdxVal = Idx->getAsZExtVal();
6798 if (IdxVal == 0 && InVT == WidenVT)
6799 return InOp;
6800
6801 // Check if we can extract from the vector.
6802 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6803 unsigned InNumElts = InVT.getVectorMinNumElements();
6804 unsigned VTNumElts = VT.getVectorMinNumElements();
6805 assert(IdxVal % VTNumElts == 0 &&
6806 "Expected Idx to be a multiple of subvector minimum vector length");
6807 if (IdxVal % WidenNumElts == 0 && IdxVal + WidenNumElts < InNumElts)
6808 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, WidenVT, InOp, Idx);
6809
6810 if (VT.isScalableVector()) {
6811 // Try to split the operation up into smaller extracts and concat the
6812 // results together, e.g.
6813 // nxv6i64 extract_subvector(nxv12i64, 6)
6814 // <->
6815 // nxv8i64 concat(
6816 // nxv2i64 extract_subvector(nxv16i64, 6)
6817 // nxv2i64 extract_subvector(nxv16i64, 8)
6818 // nxv2i64 extract_subvector(nxv16i64, 10)
6819 // undef)
6820 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
6821 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
6822 "down type's element count");
6823 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
6825 // Avoid recursion around e.g. nxv1i8.
6826 if (getTypeAction(PartVT) != TargetLowering::TypeWidenVector) {
6828 unsigned I = 0;
6829 for (; I < VTNumElts / GCD; ++I)
6830 Parts.push_back(
6831 DAG.getExtractSubvector(dl, PartVT, InOp, IdxVal + I * GCD));
6832 for (; I < WidenNumElts / GCD; ++I)
6833 Parts.push_back(DAG.getPOISON(PartVT));
6834
6835 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
6836 }
6837
6838 // Fallback to extracting through memory.
6839
6840 Align Alignment = DAG.getReducedAlign(InVT, /*UseABI=*/false);
6841 SDValue StackPtr = DAG.CreateStackTemporary(InVT.getStoreSize(), Alignment);
6842 MachineFunction &MF = DAG.getMachineFunction();
6843 int FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
6844 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
6845
6846 MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
6849 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
6852
6853 // Write out the input vector.
6854 SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, InOp, StackPtr, StoreMMO);
6855
6856 // Build a mask to match the length of the non-widened result.
6857 SDValue Mask =
6858 DAG.getMaskFromElementCount(dl, WidenVT, VT.getVectorElementCount());
6859
6860 // Read back the sub-vector setting the remaining lanes to poison.
6861 StackPtr = TLI.getVectorSubVecPointer(DAG, StackPtr, InVT, VT, Idx);
6862 return DAG.getMaskedLoad(
6863 WidenVT, dl, Ch, StackPtr, DAG.getPOISON(StackPtr.getValueType()), Mask,
6864 DAG.getPOISON(WidenVT), VT, LoadMMO, ISD::UNINDEXED, ISD::NON_EXTLOAD);
6865 }
6866
6867 // We could try widening the input to the right length but for now, extract
6868 // the original elements, fill the rest with undefs and build a vector.
6869 SmallVector<SDValue, 16> Ops(WidenNumElts);
6870 unsigned i;
6871 for (i = 0; i < VTNumElts; ++i)
6872 Ops[i] = DAG.getExtractVectorElt(dl, EltVT, InOp, IdxVal + i);
6873
6874 SDValue UndefVal = DAG.getPOISON(EltVT);
6875 for (; i < WidenNumElts; ++i)
6876 Ops[i] = UndefVal;
6877 return DAG.getBuildVector(WidenVT, dl, Ops);
6878}
6879
6880SDValue DAGTypeLegalizer::WidenVecRes_AssertZext(SDNode *N) {
6881 SDValue InOp = ModifyToType(
6882 N->getOperand(0),
6883 TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)), true);
6884 return DAG.getNode(ISD::AssertZext, SDLoc(N), InOp.getValueType(), InOp,
6885 N->getOperand(1));
6886}
6887
6888SDValue DAGTypeLegalizer::WidenVecRes_INSERT_VECTOR_ELT(SDNode *N) {
6889 SDValue InOp = GetWidenedVector(N->getOperand(0));
6890 return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(N),
6891 InOp.getValueType(), InOp,
6892 N->getOperand(1), N->getOperand(2));
6893}
6894
6895/// Either return the same load or provide appropriate casts
6896/// from the load and return that.
6897static SDValue coerceLoadedValue(SDValue LdOp, EVT FirstVT, EVT WidenVT,
6898 TypeSize LdWidth, TypeSize FirstVTWidth,
6899 SDLoc dl, SelectionDAG &DAG) {
6900 assert(TypeSize::isKnownLE(LdWidth, FirstVTWidth) &&
6901 "Load width must be less than or equal to first value type width");
6902 TypeSize WidenWidth = WidenVT.getSizeInBits();
6903 if (!FirstVT.isVector()) {
6904 unsigned NumElts =
6905 WidenWidth.getFixedValue() / FirstVTWidth.getFixedValue();
6906 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), FirstVT, NumElts);
6907 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT, LdOp);
6908 return DAG.getNode(ISD::BITCAST, dl, WidenVT, VecOp);
6909 }
6910 assert(FirstVT == WidenVT && "First value type must equal widen value type");
6911 return LdOp;
6912}
6913
6914/// Inverse of coerceLoadedValue: pull a FirstVT-sized scalar/vector out of the
6915/// widened value so it can be issued in a single atomic store.
6916static SDValue coerceStoredValue(SDValue StVal, EVT FirstVT, EVT WidenVT,
6917 TypeSize FirstVTWidth, const SDLoc &dl,
6918 SelectionDAG &DAG) {
6919 TypeSize WidenWidth = WidenVT.getSizeInBits();
6920 if (!FirstVT.isVector()) {
6921 unsigned NumElts =
6922 WidenWidth.getFixedValue() / FirstVTWidth.getFixedValue();
6923 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), FirstVT, NumElts);
6924 SDValue VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, StVal);
6925 return DAG.getExtractVectorElt(dl, FirstVT, VecOp, 0);
6926 }
6927 assert(FirstVT == WidenVT && "First value type must equal widen value type");
6928 return StVal;
6929}
6930
6931static std::optional<EVT> findMemType(SelectionDAG &DAG,
6932 const TargetLowering &TLI, unsigned Width,
6933 EVT WidenVT, unsigned Align,
6934 unsigned WidenEx);
6935
6936SDValue DAGTypeLegalizer::WidenVecRes_ATOMIC_LOAD(AtomicSDNode *LD) {
6937 EVT WidenVT =
6938 TLI.getTypeToTransformTo(*DAG.getContext(), LD->getValueType(0));
6939 EVT LdVT = LD->getMemoryVT();
6940 SDLoc dl(LD);
6941
6942 // Load information
6943 SDValue Chain = LD->getChain();
6944 SDValue BasePtr = LD->getBasePtr();
6945
6946 TypeSize LdWidth = LdVT.getSizeInBits();
6947 TypeSize WidenWidth = WidenVT.getSizeInBits();
6948 TypeSize WidthDiff = WidenWidth - LdWidth;
6949
6950 // Find the vector type that can load from.
6951 std::optional<EVT> FirstVT =
6952 findMemType(DAG, TLI, LdWidth.getKnownMinValue(), WidenVT, /*LdAlign=*/0,
6953 WidthDiff.getKnownMinValue());
6954
6955 if (!FirstVT)
6956 return SDValue();
6957
6958 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
6959
6960 SDValue LdOp = DAG.getAtomicLoad(ISD::NON_EXTLOAD, dl, *FirstVT, *FirstVT,
6961 Chain, BasePtr, LD->getMemOperand());
6962
6963 // Load the element with one instruction.
6964 SDValue Result = coerceLoadedValue(LdOp, *FirstVT, WidenVT, LdWidth,
6965 FirstVTWidth, dl, DAG);
6966
6967 // Modified the chain - switch anything that used the old chain to use
6968 // the new one.
6969 ReplaceValueWith(SDValue(LD, 1), LdOp.getValue(1));
6970 return Result;
6971}
6972
6973SDValue DAGTypeLegalizer::WidenVecRes_LOAD(SDNode *N) {
6974 LoadSDNode *LD = cast<LoadSDNode>(N);
6975 ISD::LoadExtType ExtType = LD->getExtensionType();
6976
6977 // A vector must always be stored in memory as-is, i.e. without any padding
6978 // between the elements, since various code depend on it, e.g. in the
6979 // handling of a bitcast of a vector type to int, which may be done with a
6980 // vector store followed by an integer load. A vector that does not have
6981 // elements that are byte-sized must therefore be stored as an integer
6982 // built out of the extracted vector elements.
6983 if (!LD->getMemoryVT().isByteSized()) {
6984 SDValue Value, NewChain;
6985 std::tie(Value, NewChain) = TLI.scalarizeVectorLoad(LD, DAG);
6986 ReplaceValueWith(SDValue(LD, 0), Value);
6987 ReplaceValueWith(SDValue(LD, 1), NewChain);
6988 return SDValue();
6989 }
6990
6991 // Generate a vector-predicated load if it is custom/legal on the target. To
6992 // avoid possible recursion, only do this if the widened mask type is legal.
6993 // FIXME: Not all targets may support EVL in VP_LOAD. These will have been
6994 // removed from the IR by the ExpandVectorPredication pass but we're
6995 // reintroducing them here.
6996 EVT VT = LD->getValueType(0);
6997 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6998 EVT WideMaskVT = getSetCCResultType(WideVT);
6999
7000 if (ExtType == ISD::NON_EXTLOAD &&
7001 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WideVT) &&
7002 TLI.isTypeLegal(WideMaskVT)) {
7003 SDLoc DL(N);
7004 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
7005 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
7007 SDValue NewLoad =
7008 DAG.getLoadVP(LD->getAddressingMode(), ISD::NON_EXTLOAD, WideVT, DL,
7009 LD->getChain(), LD->getBasePtr(), LD->getOffset(), Mask,
7010 EVL, LD->getMemoryVT(), LD->getMemOperand());
7011
7012 // Modified the chain - switch anything that used the old chain to use
7013 // the new one.
7014 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
7015
7016 return NewLoad;
7017 }
7018
7020 SmallVector<SDValue, 16> LdChain; // Chain for the series of load
7021 if (ExtType != ISD::NON_EXTLOAD)
7022 Result = GenWidenVectorExtLoads(LdChain, LD, ExtType);
7023 else
7024 Result = GenWidenVectorLoads(LdChain, LD);
7025
7026 if (Result) {
7027 // If we generate a single load, we can use that for the chain. Otherwise,
7028 // build a factor node to remember the multiple loads are independent and
7029 // chain to that.
7030 SDValue NewChain;
7031 if (LdChain.size() == 1)
7032 NewChain = LdChain[0];
7033 else
7034 NewChain = DAG.getNode(ISD::TokenFactor, SDLoc(LD), MVT::Other, LdChain);
7035
7036 // Modified the chain - switch anything that used the old chain to use
7037 // the new one.
7038 ReplaceValueWith(SDValue(N, 1), NewChain);
7039
7040 return Result;
7041 }
7042
7043 if (VT.isVector()) {
7044 // If all else fails replace the load with a wide masked load.
7045 SDLoc DL(N);
7046 SDValue Mask =
7047 DAG.getMaskFromElementCount(DL, WideVT, VT.getVectorElementCount());
7048
7049 SDValue NewLoad = DAG.getMaskedLoad(
7050 WideVT, DL, LD->getChain(), LD->getBasePtr(), LD->getOffset(), Mask,
7051 DAG.getPOISON(WideVT), LD->getMemoryVT(), LD->getMemOperand(),
7052 LD->getAddressingMode(), LD->getExtensionType());
7053
7054 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
7055 return NewLoad;
7056 }
7057
7058 report_fatal_error("Unable to widen vector load");
7059}
7060
7061SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD(VPLoadSDNode *N) {
7062 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7063 SDValue Mask = N->getMask();
7064 SDValue EVL = N->getVectorLength();
7065 ISD::LoadExtType ExtType = N->getExtensionType();
7066 SDLoc dl(N);
7067
7068 // The mask should be widened as well
7069 assert(getTypeAction(Mask.getValueType()) ==
7071 "Unable to widen binary VP op");
7072 Mask = GetWidenedVector(Mask);
7073 assert(Mask.getValueType().getVectorElementCount() ==
7074 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
7075 .getVectorElementCount() &&
7076 "Unable to widen vector load");
7077
7078 SDValue Res =
7079 DAG.getLoadVP(N->getAddressingMode(), ExtType, WidenVT, dl, N->getChain(),
7080 N->getBasePtr(), N->getOffset(), Mask, EVL,
7081 N->getMemoryVT(), N->getMemOperand(), N->isExpandingLoad());
7082 // Legalize the chain result - switch anything that used the old chain to
7083 // use the new one.
7084 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7085 return Res;
7086}
7087
7088SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD_FF(VPLoadFFSDNode *N) {
7089 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7090 SDValue Mask = N->getMask();
7091 SDValue EVL = N->getVectorLength();
7092 SDLoc dl(N);
7093
7094 // The mask should be widened as well
7095 assert(getTypeAction(Mask.getValueType()) ==
7097 "Unable to widen binary VP op");
7098 Mask = GetWidenedVector(Mask);
7099 assert(Mask.getValueType().getVectorElementCount() ==
7100 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
7101 .getVectorElementCount() &&
7102 "Unable to widen vector load");
7103
7104 SDValue Res = DAG.getLoadFFVP(WidenVT, dl, N->getChain(), N->getBasePtr(),
7105 Mask, EVL, N->getMemOperand());
7106 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7107 ReplaceValueWith(SDValue(N, 2), Res.getValue(2));
7108 return Res;
7109}
7110
7111SDValue DAGTypeLegalizer::WidenVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode *N) {
7112 SDLoc DL(N);
7113
7114 // The mask should be widened as well
7115 SDValue Mask = N->getMask();
7116 assert(getTypeAction(Mask.getValueType()) ==
7118 "Unable to widen VP strided load");
7119 Mask = GetWidenedVector(Mask);
7120
7121 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7122 assert(Mask.getValueType().getVectorElementCount() ==
7123 WidenVT.getVectorElementCount() &&
7124 "Data and mask vectors should have the same number of elements");
7125
7126 SDValue Res = DAG.getStridedLoadVP(
7127 N->getAddressingMode(), N->getExtensionType(), WidenVT, DL, N->getChain(),
7128 N->getBasePtr(), N->getOffset(), N->getStride(), Mask,
7129 N->getVectorLength(), N->getMemoryVT(), N->getMemOperand(),
7130 N->isExpandingLoad());
7131
7132 // Legalize the chain result - switch anything that used the old chain to
7133 // use the new one.
7134 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7135 return Res;
7136}
7137
7138SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_COMPRESS(SDNode *N) {
7139 SDValue Vec = N->getOperand(0);
7140 SDValue Mask = N->getOperand(1);
7141 SDValue Passthru = N->getOperand(2);
7142 EVT WideVecVT =
7143 TLI.getTypeToTransformTo(*DAG.getContext(), Vec.getValueType());
7144 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
7145 Mask.getValueType().getVectorElementType(),
7146 WideVecVT.getVectorElementCount());
7147
7148 SDValue WideVec = ModifyToType(Vec, WideVecVT);
7149 SDValue WideMask = ModifyToType(Mask, WideMaskVT, /*FillWithZeroes=*/true);
7150 SDValue WidePassthru = ModifyToType(Passthru, WideVecVT);
7151 return DAG.getNode(ISD::VECTOR_COMPRESS, SDLoc(N), WideVecVT, WideVec,
7152 WideMask, WidePassthru);
7153}
7154
7155SDValue DAGTypeLegalizer::WidenVecRes_MLOAD(MaskedLoadSDNode *N) {
7156 EVT VT = N->getValueType(0);
7157 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7158 SDValue Mask = N->getMask();
7159 EVT MaskVT = Mask.getValueType();
7160 SDValue PassThru = GetWidenedVector(N->getPassThru());
7161 ISD::LoadExtType ExtType = N->getExtensionType();
7162 SDLoc dl(N);
7163
7164 EVT WideMaskVT =
7165 EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(),
7166 WidenVT.getVectorElementCount());
7167
7168 if (ExtType == ISD::NON_EXTLOAD && !N->isExpandingLoad() &&
7169 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WidenVT) &&
7170 TLI.isTypeLegal(WideMaskVT) &&
7171 // If there is a passthru, we shouldn't use vp.load. However,
7172 // type legalizer will struggle on masked.load with
7173 // scalable vectors, so for scalable vectors, we still use vp.load
7174 // but manually merge the load result with the passthru using vp.select.
7175 (N->getPassThru()->isUndef() || VT.isScalableVector())) {
7176 Mask = DAG.getInsertSubvector(dl, DAG.getPOISON(WideMaskVT), Mask, 0);
7177 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
7179 SDValue NewLoad =
7180 DAG.getLoadVP(N->getAddressingMode(), ISD::NON_EXTLOAD, WidenVT, dl,
7181 N->getChain(), N->getBasePtr(), N->getOffset(), Mask, EVL,
7182 N->getMemoryVT(), N->getMemOperand());
7183 SDValue NewVal = NewLoad;
7184
7185 // Manually merge with vselect
7186 if (!N->getPassThru()->isUndef()) {
7187 assert(WidenVT.isScalableVector());
7188 NewVal = DAG.getNode(ISD::VSELECT, dl, WidenVT, Mask, NewVal, PassThru);
7189 // The lanes past EVL are poison.
7190 NewVal = DAG.getNode(ISD::VP_MERGE, dl, WidenVT,
7191 DAG.getAllOnesConstant(dl, WideMaskVT), NewVal,
7192 DAG.getPOISON(WidenVT), EVL);
7193 }
7194
7195 // Modified the chain - switch anything that used the old chain to use
7196 // the new one.
7197 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
7198
7199 return NewVal;
7200 }
7201
7202 // The mask should be widened as well
7203 Mask = ModifyToType(Mask, WideMaskVT, true);
7204
7205 SDValue Res = DAG.getMaskedLoad(
7206 WidenVT, dl, N->getChain(), N->getBasePtr(), N->getOffset(), Mask,
7207 PassThru, N->getMemoryVT(), N->getMemOperand(), N->getAddressingMode(),
7208 ExtType, N->isExpandingLoad());
7209 // Legalize the chain result - switch anything that used the old chain to
7210 // use the new one.
7211 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7212 return Res;
7213}
7214
7215SDValue DAGTypeLegalizer::WidenVecRes_MGATHER(MaskedGatherSDNode *N) {
7216
7217 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7218 SDValue Mask = N->getMask();
7219 EVT MaskVT = Mask.getValueType();
7220 SDValue PassThru = GetWidenedVector(N->getPassThru());
7221 SDValue Scale = N->getScale();
7222 ElementCount WideEC = WideVT.getVectorElementCount();
7223 SDLoc dl(N);
7224
7225 // The mask should be widened as well
7226 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
7227 MaskVT.getVectorElementType(), WideEC);
7228 Mask = ModifyToType(Mask, WideMaskVT, true);
7229
7230 // Widen the Index operand
7231 SDValue Index = N->getIndex();
7232 EVT WideIndexVT = EVT::getVectorVT(
7233 *DAG.getContext(), Index.getValueType().getScalarType(), WideEC);
7234 Index = ModifyToType(Index, WideIndexVT);
7235 SDValue Ops[] = { N->getChain(), PassThru, Mask, N->getBasePtr(), Index,
7236 Scale };
7237
7238 // Widen the MemoryType
7239 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
7240 N->getMemoryVT().getScalarType(), WideEC);
7241 SDValue Res = DAG.getMaskedGather(DAG.getVTList(WideVT, MVT::Other),
7242 WideMemVT, dl, Ops, N->getMemOperand(),
7243 N->getIndexType(), N->getExtensionType());
7244
7245 // Legalize the chain result - switch anything that used the old chain to
7246 // use the new one.
7247 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7248 return Res;
7249}
7250
7251SDValue DAGTypeLegalizer::WidenVecRes_VP_GATHER(VPGatherSDNode *N) {
7252 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7253 SDValue Mask = N->getMask();
7254 SDValue Scale = N->getScale();
7255 ElementCount WideEC = WideVT.getVectorElementCount();
7256 SDLoc dl(N);
7257
7258 SDValue Index = GetWidenedVector(N->getIndex());
7259 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
7260 N->getMemoryVT().getScalarType(), WideEC);
7261 Mask = GetWidenedMask(Mask, WideEC);
7262
7263 SDValue Ops[] = {N->getChain(), N->getBasePtr(), Index, Scale,
7264 Mask, N->getVectorLength()};
7265 SDValue Res = DAG.getGatherVP(DAG.getVTList(WideVT, MVT::Other), WideMemVT,
7266 dl, Ops, N->getMemOperand(), N->getIndexType());
7267
7268 // Legalize the chain result - switch anything that used the old chain to
7269 // use the new one.
7270 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7271 return Res;
7272}
7273
7274SDValue DAGTypeLegalizer::WidenVecRes_ScalarOp(SDNode *N) {
7275 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7276 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, N->getOperand(0));
7277}
7278
7279// Return true is this is a SETCC node or a strict version of it.
7280static inline bool isSETCCOp(unsigned Opcode) {
7281 switch (Opcode) {
7282 case ISD::SETCC:
7283 case ISD::STRICT_FSETCC:
7285 return true;
7286 }
7287 return false;
7288}
7289
7290// Return true if this is a node that could have two SETCCs as operands.
7291static inline bool isLogicalMaskOp(unsigned Opcode) {
7292 switch (Opcode) {
7293 case ISD::AND:
7294 case ISD::OR:
7295 case ISD::XOR:
7296 return true;
7297 }
7298 return false;
7299}
7300
7301// If N is a SETCC or a strict variant of it, return the type
7302// of the compare operands.
7304 unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
7305 return N->getOperand(OpNo).getValueType();
7306}
7307
7308// This is used just for the assert in convertMask(). Check that this either
7309// a SETCC or a previously handled SETCC by convertMask().
7310#ifndef NDEBUG
7311static inline bool isSETCCorConvertedSETCC(SDValue N) {
7312 if (N.getOpcode() == ISD::EXTRACT_SUBVECTOR)
7313 N = N.getOperand(0);
7314 else if (N.getOpcode() == ISD::CONCAT_VECTORS) {
7315 for (unsigned i = 1; i < N->getNumOperands(); ++i)
7316 if (!N->getOperand(i)->isUndef())
7317 return false;
7318 N = N.getOperand(0);
7319 }
7320
7321 if (N.getOpcode() == ISD::TRUNCATE)
7322 N = N.getOperand(0);
7323 else if (N.getOpcode() == ISD::SIGN_EXTEND)
7324 N = N.getOperand(0);
7325
7326 if (isLogicalMaskOp(N.getOpcode()))
7327 return isSETCCorConvertedSETCC(N.getOperand(0)) &&
7328 isSETCCorConvertedSETCC(N.getOperand(1));
7329
7330 return (isSETCCOp(N.getOpcode()) ||
7332}
7333#endif
7334
7335// Return a mask of vector type MaskVT to replace InMask. Also adjust MaskVT
7336// to ToMaskVT if needed with vector extension or truncation.
7337SDValue DAGTypeLegalizer::convertMask(SDValue InMask, EVT MaskVT,
7338 EVT ToMaskVT) {
7339 // Called from convertMaskTree for SETCC leaf nodes. Re-creates the SETCC with
7340 // result type MaskVT, then sign-extends/truncates and pads to ToMaskVT.
7341 assert(isSETCCorConvertedSETCC(InMask) && "Unexpected mask argument.");
7342
7343 // Make a new Mask node, with a legal result VT.
7344 SDValue Mask;
7346 for (unsigned i = 0, e = InMask->getNumOperands(); i < e; ++i)
7347 Ops.push_back(InMask->getOperand(i));
7348 if (InMask->isStrictFPOpcode()) {
7349 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask),
7350 { MaskVT, MVT::Other }, Ops);
7351 ReplaceValueWith(InMask.getValue(1), Mask.getValue(1));
7352 }
7353 else
7354 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask), MaskVT, Ops,
7355 InMask->getFlags());
7356
7357 return adjustMaskToType(Mask, ToMaskVT);
7358}
7359
7360// Adjust element width (sign-extend/truncate) and element count
7361// (extract/concat) of Mask to match ToMaskVT.
7362SDValue DAGTypeLegalizer::adjustMaskToType(SDValue Mask, EVT ToMaskVT) {
7363 LLVMContext &Ctx = *DAG.getContext();
7364 EVT MaskVT = Mask.getValueType();
7365 unsigned MaskScalarBits = MaskVT.getScalarSizeInBits();
7366 unsigned ToMaskScalBits = ToMaskVT.getScalarSizeInBits();
7367 if (MaskScalarBits < ToMaskScalBits) {
7368 EVT ExtVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
7369 MaskVT.getVectorNumElements());
7370 Mask = DAG.getNode(ISD::SIGN_EXTEND, SDLoc(Mask), ExtVT, Mask);
7371 } else if (MaskScalarBits > ToMaskScalBits) {
7372 EVT TruncVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
7373 MaskVT.getVectorNumElements());
7374 Mask = DAG.getNode(ISD::TRUNCATE, SDLoc(Mask), TruncVT, Mask);
7375 }
7376
7377 assert(Mask->getValueType(0).getScalarSizeInBits() ==
7378 ToMaskVT.getScalarSizeInBits() &&
7379 "Mask should have the right element size by now.");
7380
7381 // Adjust Mask to the right number of elements.
7382 unsigned CurrMaskNumEls = Mask->getValueType(0).getVectorNumElements();
7383 if (CurrMaskNumEls > ToMaskVT.getVectorNumElements()) {
7384 Mask = DAG.getExtractSubvector(SDLoc(Mask), ToMaskVT, Mask, 0);
7385 } else if (CurrMaskNumEls < ToMaskVT.getVectorNumElements()) {
7386 unsigned NumSubVecs = (ToMaskVT.getVectorNumElements() / CurrMaskNumEls);
7387 EVT SubVT = Mask->getValueType(0);
7388 SmallVector<SDValue, 16> SubOps(NumSubVecs, DAG.getPOISON(SubVT));
7389 SubOps[0] = Mask;
7390 Mask = DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Mask), ToMaskVT, SubOps);
7391 }
7392
7393 assert((Mask->getValueType(0) == ToMaskVT) &&
7394 "A mask of ToMaskVT should have been produced by now.");
7395
7396 return Mask;
7397}
7398
7399// Adjust both operands to a common intermediate mask type, picking a scalar
7400// width that minimizes extend/truncate overhead given the final target ToVT.
7401EVT DAGTypeLegalizer::unifyMaskTypes(SDValue &Op0, bool IsOpLenient0,
7402 SDValue &Op1, bool IsOpLenient1,
7403 EVT ToVT) {
7406 "unifyMaskTypes only handles scalar width differences");
7407
7408 // If only one of the operands lenient type-wise, we can simply
7409 // adjust its type to the other operand's type assuming that this
7410 // adjustment can be folded away.
7411 //
7412 // NOTE: We essentially rely on the fact that further optimizations
7413 // do spot redundant casts in "lenient" cases. If at some
7414 // point we decide that we want to do better here, we can
7415 // postpone converting lenient sub-trees right away and postpone
7416 // it to the moment when we know the best fitting integer type
7417 // to materialize them, and do it there.
7418 if (IsOpLenient0 != IsOpLenient1) {
7419 SDValue *LenientOp, *NonLenientOp;
7420 if (IsOpLenient0) {
7421 LenientOp = &Op0;
7422 NonLenientOp = &Op1;
7423 } else {
7424 LenientOp = &Op1;
7425 NonLenientOp = &Op0;
7426 }
7427 EVT OpVT = NonLenientOp->getValueType();
7428 *LenientOp = adjustMaskToType(*LenientOp, OpVT);
7429 return OpVT;
7430 }
7431
7432 unsigned Bits0 = Op0.getScalarValueSizeInBits();
7433 unsigned Bits1 = Op1.getScalarValueSizeInBits();
7434 unsigned NarrowBits = std::min(Bits0, Bits1);
7435 unsigned WideBits = std::max(Bits0, Bits1);
7436 unsigned ToBits = ToVT.getScalarSizeInBits();
7437 unsigned IntBits = NarrowBits == WideBits ? NarrowBits
7438 : ToBits >= WideBits ? WideBits
7439 : ToBits <= NarrowBits ? NarrowBits
7440 : ToBits;
7441 EVT OpVT = Op0.getValueType().changeVectorElementType(
7442 *DAG.getContext(), EVT::getIntegerVT(*DAG.getContext(), IntBits));
7443 Op0 = adjustMaskToType(Op0, OpVT);
7444 Op1 = adjustMaskToType(Op1, OpVT);
7445 return OpVT;
7446}
7447
7448std::pair<SDValue, bool>
7449DAGTypeLegalizer::convertMaskTreeImpl(SDValue V, EVT ToVT, unsigned Depth) {
7450 // The main idea is to recursively traverse VSELECT's mask that needs
7451 // widening to see if we can avoid unnecessary casts. The problem usually
7452 // stems from a simple fact that SETCC might naturally produce results
7453 // not in i1 (as we model it in LLVM IR) and we can continue using that
7454 // type until we have to switch it up. Another important aspect is that
7455 // "all ones" and "all zeros" constants can be materialized at any type,
7456 // so we can try to utilize that to keep SETCC results at their natural
7457 // types as much as possible.
7458 //
7459 // The algorithm traverses the mask-producing tree of operations that
7460 // retain "mask-vector"-ness of the input (i.e. it remains a vector of
7461 // -1s and 0s).
7462 //
7463 // SETCC1 SETCC2 CONST1 SETCC3 CONST2 CONST3
7464 // | / | / | /
7465 // | / | / | /
7466 // |_____/ |______/ |______/
7467 // | * choose the | * choose SETCC3 | * keep it as final type
7468 // | most fitting | type | but consider it subject to
7469 // | type | / change
7470 // | | /
7471 // | |______________/
7472 // | | * choose SETCC3 type
7473 // | /
7474 // | /
7475 // |_____________/
7476 // | * choose the most fitting type
7477 // | and then cast to the final desired type
7478 // |
7479 // VSELECT
7480 //
7481 if (Depth >= DAG.MaxRecursionDepth)
7482 return {};
7483
7484 // Bail out when encounter the vector element count mismatch.
7485 // It potentially can be just an assertion, but we deliberately try to
7486 // be overly conservative here.
7487 if (V.getValueType().getVectorNumElements() != ToVT.getVectorNumElements())
7488 return {};
7489
7490 unsigned Opcode = V.getOpcode();
7491
7492 // Base case: SETCC produces the mask at its natural type.
7493 if (isSETCCOp(Opcode)) {
7494 EVT MaskVT = getSetCCResultType(getSETCCOperandType(V));
7495 return {convertMask(V, MaskVT, MaskVT), /*IsTypeLenient=*/false};
7496 }
7497
7498 SDLoc DL(V);
7499
7500 // Base case: all-zeros or all-ones BUILD_VECTOR. Type-lenient since these are
7501 // invariant under sign-extend/truncate.
7502 if (ISD::isBuildVectorAllZeros(V.getNode()))
7503 return {DAG.getConstant(0, DL, ToVT), /*IsTypeLenient=*/true};
7504 if (ISD::isBuildVectorAllOnes(V.getNode()))
7505 return {DAG.getAllOnesConstant(DL, ToVT), /*IsTypeLenient=*/true};
7506
7507 // Logical operations (AND/OR/XOR): try picking the best fitting width out
7508 // of children's element widths.
7509 if (isLogicalMaskOp(Opcode)) {
7510 auto [Op0, IsLenientOp0] =
7511 convertMaskTreeImpl(V.getOperand(0), ToVT, Depth + 1);
7512 if (!Op0)
7513 return {};
7514 auto [Op1, IsLenientOp1] =
7515 convertMaskTreeImpl(V.getOperand(1), ToVT, Depth + 1);
7516 if (!Op1)
7517 return {};
7518 EVT OpVT = unifyMaskTypes(Op0, IsLenientOp0, Op1, IsLenientOp1, ToVT);
7519 return {DAG.getNode(Opcode, DL, OpVT, Op0, Op1),
7520 IsLenientOp0 && IsLenientOp1};
7521 }
7522
7523 // FREEZE: widen the operand and re-wrap.
7524 if (Opcode == ISD::FREEZE) {
7525 auto [Inner, IsTypeLenient] =
7526 convertMaskTreeImpl(V.getOperand(0), ToVT, Depth + 1);
7527 if (!Inner)
7528 return {};
7529 return {DAG.getNode(ISD::FREEZE, DL, Inner.getValueType(), Inner),
7530 IsTypeLenient};
7531 }
7532
7533 // Vector shuffle: try inferring the best fitting width from operands.
7534 if (Opcode == ISD::VECTOR_SHUFFLE) {
7535 auto *Shuf = cast<ShuffleVectorSDNode>(V);
7536 auto [Op0, IsLenientOp0] =
7537 convertMaskTreeImpl(V.getOperand(0), ToVT, Depth + 1);
7538 if (!Op0)
7539 return {};
7540 if (V.getOperand(1).isUndef()) {
7541 EVT OpVT = Op0.getValueType();
7542 return {DAG.getVectorShuffle(OpVT, DL, Op0, DAG.getUNDEF(OpVT),
7543 Shuf->getMask()),
7544 IsLenientOp0};
7545 }
7546 auto [Op1, IsLenientOp1] =
7547 convertMaskTreeImpl(V.getOperand(1), ToVT, Depth + 1);
7548 if (!Op1)
7549 return {};
7550 EVT OpVT = unifyMaskTypes(Op0, IsLenientOp0, Op1, IsLenientOp1, ToVT);
7551 return {DAG.getVectorShuffle(OpVT, DL, Op0, Op1, Shuf->getMask()),
7552 IsLenientOp0 && IsLenientOp1};
7553 }
7554
7555 // SELECT/VSELECT: try inferring the best fitting width from operands.
7556 if (Opcode == ISD::SELECT || Opcode == ISD::VSELECT) {
7557 auto [Op1, IsLenientOp1] =
7558 convertMaskTreeImpl(V.getOperand(1), ToVT, Depth + 1);
7559 if (!Op1)
7560 return {};
7561 auto [Op2, IsLenientOp2] =
7562 convertMaskTreeImpl(V.getOperand(2), ToVT, Depth + 1);
7563 if (!Op2)
7564 return {};
7565 EVT OpVT = unifyMaskTypes(Op1, IsLenientOp1, Op2, IsLenientOp2, ToVT);
7566
7567 // We deliberately skip traversing/modifying VSELECT's mask because
7568 //
7569 // a. We only change bitwidth of the operands and it shouldn't affect
7570 // condition on its own.
7571 //
7572 // b. This VSELECT's mask can be widened in an independent traversal
7573 // if needed.
7574 SDValue Cond = V.getOperand(0);
7575 return {DAG.getNode(Opcode, DL, OpVT, Cond, Op1, Op2),
7576 IsLenientOp1 && IsLenientOp2};
7577 }
7578
7579 return {};
7580}
7581
7582SDValue DAGTypeLegalizer::convertMaskTree(SDValue V, EVT ToVT) {
7583 // In general, we are converting from <N x i1> into <M x iW>.
7584 // This would mean that during the tree traversal we need to pay
7585 // attention to both bitwidth and element count, which can be error-prone.
7586 //
7587 // Instead, we split the task in two, we first widen the type of the tree
7588 // and then change the element count.
7589 EVT MaskTreeVT = ToVT.changeVectorElementCount(
7590 *DAG.getContext(), V.getValueType().getVectorElementCount());
7591 auto [Result, _] = convertMaskTreeImpl(V, MaskTreeVT);
7592 if (!Result)
7593 return Result;
7594 return adjustMaskToType(Result, ToVT);
7595}
7596
7597// This method tries to handle some special cases for the vselect mask
7598// and if needed adjusting the mask vector type to match that of the VSELECT.
7599// Without it, many cases end up with scalarization of the SETCC, with many
7600// unnecessary instructions.
7601SDValue DAGTypeLegalizer::WidenVSELECTMask(SDNode *N) {
7602 LLVMContext &Ctx = *DAG.getContext();
7603 SDValue Cond = N->getOperand(0);
7604
7605 if (N->getOpcode() != ISD::VSELECT)
7606 return SDValue();
7607
7608 // If this is a splitted VSELECT that was previously already handled, do
7609 // nothing.
7610 EVT CondVT = Cond->getValueType(0);
7611 if (CondVT.getScalarSizeInBits() != 1)
7612 return SDValue();
7613
7614 EVT VSelVT = N->getValueType(0);
7615
7616 // This method can't handle scalable vector types.
7617 // FIXME: This support could be added in the future.
7618 if (VSelVT.isScalableVector())
7619 return SDValue();
7620
7621 // Only handle vector types which are a power of 2.
7622 if (!isPowerOf2_64(VSelVT.getSizeInBits()))
7623 return SDValue();
7624
7625 // Don't touch if this will be scalarized.
7626 EVT FinalVT = VSelVT;
7627 while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
7628 FinalVT = FinalVT.getHalfNumVectorElementsVT(Ctx);
7629
7630 if (FinalVT.getVectorNumElements() == 1)
7631 return SDValue();
7632
7633 // If there is support for an i1 vector mask, don't touch.
7634 if (isSETCCOp(Cond.getOpcode())) {
7635 EVT SetCCOpVT = getSETCCOperandType(Cond);
7636 while (TLI.getTypeAction(Ctx, SetCCOpVT) != TargetLowering::TypeLegal)
7637 SetCCOpVT = TLI.getTypeToTransformTo(Ctx, SetCCOpVT);
7638 EVT SetCCResVT = getSetCCResultType(SetCCOpVT);
7639 if (SetCCResVT.getScalarSizeInBits() == 1)
7640 return SDValue();
7641 } else if (CondVT.getScalarType() == MVT::i1) {
7642 // If there is support for an i1 vector mask (or only scalar i1 conditions),
7643 // don't touch.
7644 while (TLI.getTypeAction(Ctx, CondVT) != TargetLowering::TypeLegal)
7645 CondVT = TLI.getTypeToTransformTo(Ctx, CondVT);
7646
7647 if (CondVT.getScalarType() == MVT::i1)
7648 return SDValue();
7649 }
7650
7651 // Widen the vselect result type if needed.
7652 if (getTypeAction(VSelVT) == TargetLowering::TypeWidenVector)
7653 VSelVT = TLI.getTypeToTransformTo(Ctx, VSelVT);
7654
7655 // The mask of the VSELECT should have integer elements.
7656 EVT ToMaskVT = VSelVT;
7657 if (!ToMaskVT.getScalarType().isInteger())
7658 ToMaskVT = ToMaskVT.changeVectorElementTypeToInteger();
7659
7660 // Try to recursively widen the mask expression tree to the target type.
7661 return convertMaskTree(Cond, ToMaskVT);
7662}
7663
7664SDValue DAGTypeLegalizer::WidenVecRes_Select(SDNode *N) {
7665 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7666 ElementCount WidenEC = WidenVT.getVectorElementCount();
7667
7668 SDValue Cond1 = N->getOperand(0);
7669 EVT CondVT = Cond1.getValueType();
7670 unsigned Opcode = N->getOpcode();
7671 if (CondVT.isVector()) {
7672 if (SDValue WideCond = WidenVSELECTMask(N)) {
7673 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
7674 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
7675 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
7676 return DAG.getNode(Opcode, SDLoc(N), WidenVT, WideCond, InOp1, InOp2);
7677 }
7678
7679 EVT CondEltVT = CondVT.getVectorElementType();
7680 EVT CondWidenVT = EVT::getVectorVT(*DAG.getContext(), CondEltVT, WidenEC);
7681 if (getTypeAction(CondVT) == TargetLowering::TypeWidenVector)
7682 Cond1 = GetWidenedVector(Cond1);
7683
7684 // If we have to split the condition there is no point in widening the
7685 // select. This would result in an cycle of widening the select ->
7686 // widening the condition operand -> splitting the condition operand ->
7687 // splitting the select -> widening the select. Instead split this select
7688 // further and widen the resulting type.
7689 if (getTypeAction(CondVT) == TargetLowering::TypeSplitVector) {
7690 SDValue SplitSelect = SplitVecOp_VSELECT(N, 0);
7691 SDValue Res = ModifyToType(SplitSelect, WidenVT);
7692 return Res;
7693 }
7694
7695 if (Cond1.getValueType() != CondWidenVT)
7696 Cond1 = ModifyToType(Cond1, CondWidenVT);
7697 }
7698
7699 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
7700 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
7701 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
7702 if (Opcode == ISD::VP_MERGE)
7703 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2,
7704 N->getOperand(3));
7705 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2);
7706}
7707
7708SDValue DAGTypeLegalizer::WidenVecRes_SELECT_CC(SDNode *N) {
7709 SDValue InOp1 = GetWidenedVector(N->getOperand(2));
7710 SDValue InOp2 = GetWidenedVector(N->getOperand(3));
7711 return DAG.getNode(ISD::SELECT_CC, SDLoc(N),
7712 InOp1.getValueType(), N->getOperand(0),
7713 N->getOperand(1), InOp1, InOp2, N->getOperand(4));
7714}
7715
7716SDValue DAGTypeLegalizer::WidenVecRes_UNDEF(SDNode *N) {
7717 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7718 return DAG.getUNDEF(WidenVT);
7719}
7720
7721SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N) {
7722 EVT VT = N->getValueType(0);
7723 SDLoc dl(N);
7724
7725 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7726 unsigned NumElts = VT.getVectorNumElements();
7727 unsigned WidenNumElts = WidenVT.getVectorNumElements();
7728
7729 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
7730 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
7731
7732 // Adjust mask based on new input vector length.
7733 SmallVector<int, 16> NewMask(WidenNumElts, -1);
7734 for (unsigned i = 0; i != NumElts; ++i) {
7735 int Idx = N->getMaskElt(i);
7736 if (Idx < (int)NumElts)
7737 NewMask[i] = Idx;
7738 else
7739 NewMask[i] = Idx - NumElts + WidenNumElts;
7740 }
7741 return DAG.getVectorShuffle(WidenVT, dl, InOp1, InOp2, NewMask);
7742}
7743
7744SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_REVERSE(SDNode *N) {
7745 EVT VT = N->getValueType(0);
7746 EVT EltVT = VT.getVectorElementType();
7747 SDLoc dl(N);
7748
7749 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7750 SDValue OpValue = GetWidenedVector(N->getOperand(0));
7751 assert(WidenVT == OpValue.getValueType() && "Unexpected widened vector type");
7752
7753 SDValue ReverseVal = DAG.getNode(ISD::VECTOR_REVERSE, dl, WidenVT, OpValue);
7754 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
7755 unsigned VTNumElts = VT.getVectorMinNumElements();
7756 unsigned IdxVal = WidenNumElts - VTNumElts;
7757
7758 if (VT.isScalableVector()) {
7759 // Try to split the 'Widen ReverseVal' into smaller extracts and concat the
7760 // results together, e.g.(nxv6i64 -> nxv8i64)
7761 // nxv8i64 vector_reverse
7762 // <->
7763 // nxv8i64 concat(
7764 // nxv2i64 extract_subvector(nxv8i64, 2)
7765 // nxv2i64 extract_subvector(nxv8i64, 4)
7766 // nxv2i64 extract_subvector(nxv8i64, 6)
7767 // nxv2i64 undef)
7768
7769 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
7770 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
7772 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
7773 "down type's element count");
7775 unsigned i = 0;
7776 for (; i < VTNumElts / GCD; ++i)
7777 Parts.push_back(
7778 DAG.getExtractSubvector(dl, PartVT, ReverseVal, IdxVal + i * GCD));
7779 for (; i < WidenNumElts / GCD; ++i)
7780 Parts.push_back(DAG.getPOISON(PartVT));
7781
7782 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
7783 }
7784
7785 // Use VECTOR_SHUFFLE to combine new vector from 'ReverseVal' for
7786 // fixed-vectors.
7787 SmallVector<int, 16> Mask(WidenNumElts, -1);
7788 std::iota(Mask.begin(), Mask.begin() + VTNumElts, IdxVal);
7789
7790 return DAG.getVectorShuffle(WidenVT, dl, ReverseVal, DAG.getPOISON(WidenVT),
7791 Mask);
7792}
7793
7794SDValue DAGTypeLegalizer::WidenVecRes_GET_ACTIVE_LANE_MASK(SDNode *N) {
7795 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7796 return DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, SDLoc(N), NVT, N->ops());
7797}
7798
7799void DAGTypeLegalizer::WidenVecRes_VECTOR_INTERLEAVE(SDNode *N) {
7800 EVT VT = N->getValueType(0);
7801 EVT EltVT = VT.getVectorElementType();
7802 ElementCount OrigEC = VT.getVectorElementCount();
7803 unsigned Factor = N->getNumOperands();
7804 SDLoc DL(N);
7805
7806 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7807 ElementCount WidenEC = WidenVT.getVectorElementCount();
7808
7809 SmallVector<SDValue, 8> WidenOps(Factor);
7810 for (unsigned Idx = 0U; Idx < Factor; ++Idx)
7811 WidenOps[Idx] = GetWidenedVector(N->getOperand(Idx));
7812
7813 SmallVector<EVT, 8> WidenVTs(Factor, WidenVT);
7814 SDValue Interleaved =
7815 DAG.getNode(ISD::VECTOR_INTERLEAVE, DL, WidenVTs, WidenOps);
7816
7817 EVT PackedWidenVT =
7818 EVT::getVectorVT(*DAG.getContext(), EltVT, WidenEC * Factor);
7819 SmallVector<SDValue, 8> Slices(Factor);
7820 for (unsigned Idx = 0; Idx != Factor; ++Idx)
7821 Slices[Idx] = Interleaved.getValue(Idx);
7822
7823 SDValue Packed = DAG.getNode(ISD::CONCAT_VECTORS, DL, PackedWidenVT, Slices);
7824
7825 for (unsigned Idx = 0U; Idx < Factor; ++Idx) {
7826 SDValue Narrow = DAG.getExtractSubvector(DL, VT, Packed,
7827 OrigEC.getKnownMinValue() * Idx);
7828 SDValue Wide =
7829 DAG.getInsertSubvector(DL, DAG.getPOISON(WidenVT), Narrow, /*Idx=*/0U);
7830 SetWidenedVector(SDValue(N, Idx), Wide);
7831 }
7832}
7833
7834SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_MATCH(SDNode *N) {
7835 SDLoc DL(N);
7836 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7837 EVT SourceVT = N->getOperand(0).getValueType();
7838 EVT WideSourceVT =
7839 EVT::getVectorVT(*DAG.getContext(), SourceVT.getVectorElementType(),
7840 WidenVT.getVectorElementCount());
7841
7842 SDValue WideSource = DAG.getInsertSubvector(DL, DAG.getUNDEF(WideSourceVT),
7843 N->getOperand(0), 0);
7844 SDValue WideMask = DAG.getInsertSubvector(DL, DAG.getConstant(0, DL, WidenVT),
7845 N->getOperand(2), 0);
7846 return DAG.getNode(ISD::VECTOR_MATCH, DL, WidenVT, WideSource,
7847 N->getOperand(1), WideMask, N->getFlags());
7848}
7849
7850void DAGTypeLegalizer::WidenVecRes_VECTOR_DEINTERLEAVE(SDNode *N) {
7851 EVT VT = N->getValueType(0);
7852 EVT EltVT = VT.getVectorElementType();
7853 ElementCount OrigEC = VT.getVectorElementCount();
7854 unsigned Factor = N->getNumOperands();
7855 SDLoc DL(N);
7856
7857 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7858 ElementCount WidenEC = WidenVT.getVectorElementCount();
7859 // We cannot just use the widened operands directly: since they might be
7860 // individually widened, using them directly will result in de-interleaving
7861 // the "padded" lanes that sit in the middle of the vector. Instead, we should
7862 // not concat the widened operands but the original ones to effectively
7863 // generate a "packed" concated and widened vector, before extracting new
7864 // operand vectors with the widened type.
7865 EVT PackedWidenVT =
7866 EVT::getVectorVT(*DAG.getContext(), EltVT, WidenEC * Factor);
7867 EVT ConcatVT = EVT::getVectorVT(*DAG.getContext(), EltVT, OrigEC * Factor);
7868 SDValue ConcatOp = DAG.getNode(ISD::CONCAT_VECTORS, DL, ConcatVT, N->ops());
7869 SDValue PackedWidenVec = DAG.getInsertSubvector(
7870 DL, DAG.getUNDEF(PackedWidenVT), ConcatOp, /*Idx=*/0U);
7871
7872 // Extract the new widened operand vectors.
7873 SmallVector<SDValue, 8> NewOps(Factor, SDValue());
7874 for (unsigned Idx = 0U; Idx < Factor; ++Idx) {
7875 NewOps[Idx] = DAG.getExtractSubvector(DL, WidenVT, PackedWidenVec,
7876 WidenEC.getKnownMinValue() * Idx);
7877 }
7878
7879 SmallVector<EVT, 8> NewVTs(Factor, WidenVT);
7880 SDValue NewRes = DAG.getNode(ISD::VECTOR_DEINTERLEAVE, DL, NewVTs, NewOps);
7881 // Set the widened results manually.
7882 for (unsigned Idx = 0U; Idx < Factor; ++Idx)
7883 SetWidenedVector(SDValue(N, Idx), NewRes.getValue(Idx));
7884}
7885
7886SDValue DAGTypeLegalizer::WidenVecRes_SETCC(SDNode *N) {
7887 assert(N->getValueType(0).isVector() &&
7888 N->getOperand(0).getValueType().isVector() &&
7889 "Operands must be vectors");
7890 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7891 ElementCount WidenEC = WidenVT.getVectorElementCount();
7892
7893 SDValue InOp1 = N->getOperand(0);
7894 EVT InVT = InOp1.getValueType();
7895 assert(InVT.isVector() && "can not widen non-vector type");
7896 EVT WidenInVT =
7897 EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), WidenEC);
7898
7899 // The input and output types often differ here, and it could be that while
7900 // we'd prefer to widen the result type, the input operands have been split.
7901 // In this case, we also need to split the result of this node as well.
7902 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector) {
7903 SDValue SplitVSetCC = SplitVecOp_VSETCC(N);
7904 SDValue Res = ModifyToType(SplitVSetCC, WidenVT);
7905 return Res;
7906 }
7907
7908 // If the inputs also widen, handle them directly. Otherwise widen by hand.
7909 SDValue InOp2 = N->getOperand(1);
7910 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
7911 InOp1 = GetWidenedVector(InOp1);
7912 InOp2 = GetWidenedVector(InOp2);
7913 } else {
7914 SDValue Poison = DAG.getPOISON(WidenInVT);
7915 SDValue ZeroIdx = DAG.getVectorIdxConstant(0, SDLoc(N));
7916 InOp1 = DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), WidenInVT, Poison,
7917 InOp1, ZeroIdx);
7918 InOp2 = DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), WidenInVT, Poison,
7919 InOp2, ZeroIdx);
7920 }
7921
7922 // Assume that the input and output will be widen appropriately. If not,
7923 // we will have to unroll it at some point.
7924 assert(InOp1.getValueType() == WidenInVT &&
7925 InOp2.getValueType() == WidenInVT &&
7926 "Input not widened to expected type!");
7927 (void)WidenInVT;
7928 return DAG.getNode(ISD::SETCC, SDLoc(N), WidenVT, InOp1, InOp2,
7929 N->getOperand(2));
7930}
7931
7932SDValue DAGTypeLegalizer::WidenVecRes_STRICT_FSETCC(SDNode *N) {
7933 assert(N->getValueType(0).isVector() &&
7934 N->getOperand(1).getValueType().isVector() &&
7935 "Operands must be vectors");
7936 EVT VT = N->getValueType(0);
7937 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7938 unsigned WidenNumElts = WidenVT.getVectorNumElements();
7939 unsigned NumElts = VT.getVectorNumElements();
7940 EVT EltVT = VT.getVectorElementType();
7941
7942 SDLoc dl(N);
7943 SDValue Chain = N->getOperand(0);
7944 SDValue LHS = N->getOperand(1);
7945 SDValue RHS = N->getOperand(2);
7946 SDValue CC = N->getOperand(3);
7947 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
7948
7949 // Fully unroll and reassemble.
7950 SmallVector<SDValue, 8> Scalars(WidenNumElts, DAG.getPOISON(EltVT));
7951 SmallVector<SDValue, 8> Chains(NumElts);
7952 for (unsigned i = 0; i != NumElts; ++i) {
7953 SDValue LHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, LHS, i);
7954 SDValue RHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, RHS, i);
7955
7956 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
7957 {Chain, LHSElem, RHSElem, CC});
7958 Chains[i] = Scalars[i].getValue(1);
7959 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
7960 DAG.getBoolConstant(true, dl, EltVT, VT),
7961 DAG.getBoolConstant(false, dl, EltVT, VT));
7962 }
7963
7964 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
7965 ReplaceValueWith(SDValue(N, 1), NewChain);
7966
7967 return DAG.getBuildVector(WidenVT, dl, Scalars);
7968}
7969
7970SDValue DAGTypeLegalizer::WidenVecRes_PARTIAL_REDUCE_MLA(SDNode *N) {
7971 SDLoc DL(N);
7972 EVT VT = N->getValueType(0);
7973
7974 // Expand, then widen the result.
7975 SDValue Expanded = TLI.expandPartialReduceMLA(N, DAG);
7976 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7977 return DAG.getInsertSubvector(DL, DAG.getPOISON(WideVT), Expanded, 0);
7978}
7979
7980//===----------------------------------------------------------------------===//
7981// Widen Vector Operand
7982//===----------------------------------------------------------------------===//
7983bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned OpNo) {
7984 LLVM_DEBUG(dbgs() << "Widen node operand " << OpNo << ": "; N->dump(&DAG));
7985 SDValue Res = SDValue();
7986
7987 // See if the target wants to custom widen this node.
7988 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
7989 return false;
7990
7991 switch (N->getOpcode()) {
7992 default:
7993#ifndef NDEBUG
7994 dbgs() << "WidenVectorOperand op #" << OpNo << ": ";
7995 N->dump(&DAG);
7996 dbgs() << "\n";
7997#endif
7998 report_fatal_error("do not know how to widen this operator's operand!");
7999
8000 case ISD::BITCAST: Res = WidenVecOp_BITCAST(N); break;
8001 case ISD::FAKE_USE:
8002 Res = WidenVecOp_FAKE_USE(N);
8003 break;
8004 case ISD::CONCAT_VECTORS: Res = WidenVecOp_CONCAT_VECTORS(N); break;
8005 case ISD::VECTOR_REPEAT:
8006 Res = WidenVecOp_VECTOR_REPEAT(N);
8007 break;
8008 case ISD::INSERT_SUBVECTOR: Res = WidenVecOp_INSERT_SUBVECTOR(N); break;
8009 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecOp_EXTRACT_SUBVECTOR(N); break;
8010 case ISD::EXTRACT_VECTOR_ELT: Res = WidenVecOp_EXTRACT_VECTOR_ELT(N); break;
8011 case ISD::STORE: Res = WidenVecOp_STORE(N); break;
8012 case ISD::ATOMIC_STORE:
8013 Res = WidenVecOp_ATOMIC_STORE(cast<AtomicSDNode>(N));
8014 break;
8015 case ISD::VP_STORE: Res = WidenVecOp_VP_STORE(N, OpNo); break;
8016 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
8017 Res = WidenVecOp_VP_STRIDED_STORE(N, OpNo);
8018 break;
8022 Res = WidenVecOp_EXTEND_VECTOR_INREG(N);
8023 break;
8024 case ISD::MSTORE: Res = WidenVecOp_MSTORE(N, OpNo); break;
8025 case ISD::MGATHER: Res = WidenVecOp_MGATHER(N, OpNo); break;
8026 case ISD::MSCATTER: Res = WidenVecOp_MSCATTER(N, OpNo); break;
8027 case ISD::VP_SCATTER: Res = WidenVecOp_VP_SCATTER(N, OpNo); break;
8028 case ISD::SETCC: Res = WidenVecOp_SETCC(N); break;
8029 case ISD::STRICT_FSETCC:
8030 case ISD::STRICT_FSETCCS: Res = WidenVecOp_STRICT_FSETCC(N); break;
8031 case ISD::VSELECT: Res = WidenVecOp_VSELECT(N); break;
8032 case ISD::FLDEXP:
8033 case ISD::FCOPYSIGN:
8034 case ISD::LROUND:
8035 case ISD::LLROUND:
8036 case ISD::LRINT:
8037 case ISD::LLRINT:
8038 Res = WidenVecOp_UnrollVectorOp(N);
8039 break;
8040 case ISD::IS_FPCLASS: Res = WidenVecOp_IS_FPCLASS(N); break;
8041
8042 case ISD::ANY_EXTEND:
8043 case ISD::SIGN_EXTEND:
8044 case ISD::ZERO_EXTEND:
8045 Res = WidenVecOp_EXTEND(N);
8046 break;
8047
8048 case ISD::SCMP:
8049 case ISD::UCMP:
8050 Res = WidenVecOp_CMP(N);
8051 break;
8052
8053 case ISD::FP_EXTEND:
8055 case ISD::FP_ROUND:
8057 case ISD::FP_TO_SINT:
8059 case ISD::FP_TO_UINT:
8061 case ISD::SINT_TO_FP:
8063 case ISD::UINT_TO_FP:
8065 case ISD::TRUNCATE:
8068 Res = WidenVecOp_Convert(N);
8069 break;
8070
8073 Res = WidenVecOp_FP_TO_XINT_SAT(N);
8074 break;
8075
8078 case ISD::VECREDUCE_ADD:
8079 case ISD::VECREDUCE_MUL:
8080 case ISD::VECREDUCE_AND:
8081 case ISD::VECREDUCE_OR:
8082 case ISD::VECREDUCE_XOR:
8093 Res = WidenVecOp_VECREDUCE(N);
8094 break;
8097 Res = WidenVecOp_VECREDUCE_SEQ(N);
8098 break;
8099 case ISD::VP_REDUCE_FADD:
8100 case ISD::VP_REDUCE_SEQ_FADD:
8101 case ISD::VP_REDUCE_FMUL:
8102 case ISD::VP_REDUCE_SEQ_FMUL:
8103 case ISD::VP_REDUCE_ADD:
8104 case ISD::VP_REDUCE_MUL:
8105 case ISD::VP_REDUCE_AND:
8106 case ISD::VP_REDUCE_OR:
8107 case ISD::VP_REDUCE_XOR:
8108 case ISD::VP_REDUCE_SMAX:
8109 case ISD::VP_REDUCE_SMIN:
8110 case ISD::VP_REDUCE_UMAX:
8111 case ISD::VP_REDUCE_UMIN:
8112 case ISD::VP_REDUCE_FMAX:
8113 case ISD::VP_REDUCE_FMIN:
8114 case ISD::VP_REDUCE_FMAXIMUM:
8115 case ISD::VP_REDUCE_FMINIMUM:
8116 Res = WidenVecOp_VP_REDUCE(N);
8117 break;
8118 case ISD::CTTZ_ELTS:
8120 Res = WidenVecOp_CttzElements(N);
8121 break;
8122 case ISD::VP_CTTZ_ELTS:
8123 case ISD::VP_CTTZ_ELTS_ZERO_POISON:
8124 Res = WidenVecOp_VP_CttzElements(N);
8125 break;
8127 Res = WidenVecOp_VECTOR_FIND_LAST_ACTIVE(N);
8128 break;
8129 case ISD::VECTOR_MATCH:
8130 Res = WidenVecOp_VECTOR_MATCH(N, OpNo);
8131 break;
8132 }
8133
8134 // If Res is null, the sub-method took care of registering the result.
8135 if (!Res.getNode()) return false;
8136
8137 // If the result is N, the sub-method updated N in place. Tell the legalizer
8138 // core about this.
8139 if (Res.getNode() == N)
8140 return true;
8141
8142
8143 if (N->isStrictFPOpcode())
8144 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
8145 "Invalid operand expansion");
8146 else
8147 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
8148 "Invalid operand expansion");
8149
8150 ReplaceValueWith(SDValue(N, 0), Res);
8151 return false;
8152}
8153
8154SDValue DAGTypeLegalizer::WidenVecOp_EXTEND(SDNode *N) {
8155 SDLoc DL(N);
8156 EVT VT = N->getValueType(0);
8157
8158 SDValue InOp = N->getOperand(0);
8159 assert(getTypeAction(InOp.getValueType()) ==
8161 "Unexpected type action");
8162 InOp = GetWidenedVector(InOp);
8165 "Input wasn't widened!");
8166
8167 // We may need to further widen the operand until it has the same total
8168 // vector size as the result.
8169 EVT InVT = InOp.getValueType();
8170 if (InVT.getSizeInBits() != VT.getSizeInBits()) {
8171 EVT InEltVT = InVT.getVectorElementType();
8172 for (EVT FixedVT : MVT::vector_valuetypes()) {
8173 EVT FixedEltVT = FixedVT.getVectorElementType();
8174 if (TLI.isTypeLegal(FixedVT) &&
8175 FixedVT.getSizeInBits() == VT.getSizeInBits() &&
8176 FixedEltVT == InEltVT) {
8177 assert(FixedVT.getVectorNumElements() >= VT.getVectorNumElements() &&
8178 "Not enough elements in the fixed type for the operand!");
8179 assert(FixedVT.getVectorNumElements() != InVT.getVectorNumElements() &&
8180 "We can't have the same type as we started with!");
8181 if (FixedVT.getVectorNumElements() > InVT.getVectorNumElements())
8182 InOp = DAG.getInsertSubvector(DL, DAG.getPOISON(FixedVT), InOp, 0);
8183 else
8184 InOp = DAG.getExtractSubvector(DL, FixedVT, InOp, 0);
8185 break;
8186 }
8187 }
8188 InVT = InOp.getValueType();
8189 if (InVT.getSizeInBits() != VT.getSizeInBits())
8190 // We couldn't find a legal vector type that was a widening of the input
8191 // and could be extended in-register to the result type, so we have to
8192 // scalarize.
8193 return WidenVecOp_Convert(N);
8194 }
8195
8196 // Use special DAG nodes to represent the operation of extending the
8197 // low lanes.
8198 switch (N->getOpcode()) {
8199 default:
8200 llvm_unreachable("Extend legalization on extend operation!");
8201 case ISD::ANY_EXTEND:
8202 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, VT, InOp);
8203 case ISD::SIGN_EXTEND:
8204 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, VT, InOp);
8205 case ISD::ZERO_EXTEND:
8206 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, VT, InOp);
8207 }
8208}
8209
8210SDValue DAGTypeLegalizer::WidenVecOp_CMP(SDNode *N) {
8211 SDLoc dl(N);
8212
8213 EVT OpVT = N->getOperand(0).getValueType();
8214 EVT ResVT = N->getValueType(0);
8215 SDValue LHS = GetWidenedVector(N->getOperand(0));
8216 SDValue RHS = GetWidenedVector(N->getOperand(1));
8217
8218 // 1. EXTRACT_SUBVECTOR
8219 // 2. SIGN_EXTEND/ZERO_EXTEND
8220 // 3. CMP
8221 LHS = DAG.getExtractSubvector(dl, OpVT, LHS, 0);
8222 RHS = DAG.getExtractSubvector(dl, OpVT, RHS, 0);
8223
8224 // At this point the result type is guaranteed to be valid, so we can use it
8225 // as the operand type by extending it appropriately
8226 ISD::NodeType ExtendOpcode =
8227 N->getOpcode() == ISD::SCMP ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
8228 LHS = DAG.getNode(ExtendOpcode, dl, ResVT, LHS);
8229 RHS = DAG.getNode(ExtendOpcode, dl, ResVT, RHS);
8230
8231 return DAG.getNode(N->getOpcode(), dl, ResVT, LHS, RHS);
8232}
8233
8234SDValue DAGTypeLegalizer::WidenVecOp_UnrollVectorOp(SDNode *N) {
8235 // The result (and first input) is legal, but the second input is illegal.
8236 // We can't do much to fix that, so just unroll and let the extracts off of
8237 // the second input be widened as needed later.
8238 return DAG.UnrollVectorOp(N);
8239}
8240
8241SDValue DAGTypeLegalizer::WidenVecOp_IS_FPCLASS(SDNode *N) {
8242 SDLoc DL(N);
8243 EVT ResultVT = N->getValueType(0);
8244 SDValue Test = N->getOperand(1);
8245 SDValue WideArg = GetWidenedVector(N->getOperand(0));
8246
8247 // Process this node similarly to SETCC.
8248 EVT WideResultVT = getSetCCResultType(WideArg.getValueType());
8249 if (ResultVT.getScalarType() == MVT::i1)
8250 WideResultVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8251 WideResultVT.getVectorNumElements());
8252
8253 SDValue WideNode = DAG.getNode(ISD::IS_FPCLASS, DL, WideResultVT,
8254 {WideArg, Test}, N->getFlags());
8255
8256 // Extract the needed results from the result vector.
8257 EVT ResVT =
8258 EVT::getVectorVT(*DAG.getContext(), WideResultVT.getVectorElementType(),
8259 ResultVT.getVectorNumElements());
8260 SDValue CC = DAG.getExtractSubvector(DL, ResVT, WideNode, 0);
8261
8262 EVT OpVT = N->getOperand(0).getValueType();
8263 ISD::NodeType ExtendCode =
8264 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
8265 return DAG.getNode(ExtendCode, DL, ResultVT, CC);
8266}
8267
8268SDValue DAGTypeLegalizer::WidenVecOp_Convert(SDNode *N) {
8269 // Since the result is legal and the input is illegal.
8270 EVT VT = N->getValueType(0);
8271 EVT EltVT = VT.getVectorElementType();
8272 SDLoc dl(N);
8273 SDValue InOp = N->getOperand(N->isStrictFPOpcode() ? 1 : 0);
8274 assert(getTypeAction(InOp.getValueType()) ==
8276 "Unexpected type action");
8277 InOp = GetWidenedVector(InOp);
8278 EVT InVT = InOp.getValueType();
8279 unsigned Opcode = N->getOpcode();
8280
8281 // Helper to build a convert node with all scalar trailing operands.
8282 auto MakeConvertNode = [&](EVT VT, SDValue Op) -> SDValue {
8283 if (Opcode == ISD::CONVERT_TO_ARBITRARY_FP)
8284 return DAG.getNode(Opcode, dl, VT, Op, N->getOperand(1), N->getOperand(2),
8285 N->getOperand(3));
8286 if (Opcode == ISD::FP_ROUND || Opcode == ISD::CONVERT_FROM_ARBITRARY_FP)
8287 return DAG.getNode(Opcode, dl, VT, Op, N->getOperand(1));
8288 return DAG.getNode(Opcode, dl, VT, Op);
8289 };
8290
8291 // See if a widened result type would be legal, if so widen the node.
8292 // FIXME: This isn't safe for StrictFP. Other optimization here is needed.
8293 EVT WideVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
8294 InVT.getVectorElementCount());
8295 if (TLI.isTypeLegal(WideVT) && !N->isStrictFPOpcode()) {
8296 SDValue Res;
8297 if (N->isStrictFPOpcode()) {
8298 if (Opcode == ISD::STRICT_FP_ROUND)
8299 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
8300 { N->getOperand(0), InOp, N->getOperand(2) });
8301 else
8302 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
8303 { N->getOperand(0), InOp });
8304 // Legalize the chain result - switch anything that used the old chain to
8305 // use the new one.
8306 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
8307 } else {
8308 Res = MakeConvertNode(WideVT, InOp);
8309 }
8310 return DAG.getExtractSubvector(dl, VT, Res, 0);
8311 }
8312
8313 EVT InEltVT = InVT.getVectorElementType();
8314
8315 // Unroll the convert into some scalar code and create a nasty build vector.
8316 unsigned NumElts = VT.getVectorNumElements();
8318 if (N->isStrictFPOpcode()) {
8319 SmallVector<SDValue, 4> NewOps(N->ops());
8320 SmallVector<SDValue, 32> OpChains;
8321 for (unsigned i=0; i < NumElts; ++i) {
8322 NewOps[1] = DAG.getExtractVectorElt(dl, InEltVT, InOp, i);
8323 Ops[i] = DAG.getNode(Opcode, dl, { EltVT, MVT::Other }, NewOps);
8324 OpChains.push_back(Ops[i].getValue(1));
8325 }
8326 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OpChains);
8327 ReplaceValueWith(SDValue(N, 1), NewChain);
8328 } else {
8329 for (unsigned i = 0; i < NumElts; ++i) {
8330 SDValue Elt = DAG.getExtractVectorElt(dl, InEltVT, InOp, i);
8331 Ops[i] = MakeConvertNode(EltVT, Elt);
8332 }
8333 }
8334
8335 return DAG.getBuildVector(VT, dl, Ops);
8336}
8337
8338SDValue DAGTypeLegalizer::WidenVecOp_FP_TO_XINT_SAT(SDNode *N) {
8339 EVT DstVT = N->getValueType(0);
8340 SDValue Src = GetWidenedVector(N->getOperand(0));
8341 EVT SrcVT = Src.getValueType();
8342 ElementCount WideNumElts = SrcVT.getVectorElementCount();
8343 SDLoc dl(N);
8344
8345 // See if a widened result type would be legal, if so widen the node.
8346 EVT WideDstVT = EVT::getVectorVT(*DAG.getContext(),
8347 DstVT.getVectorElementType(), WideNumElts);
8348 if (TLI.isTypeLegal(WideDstVT)) {
8349 SDValue Res =
8350 DAG.getNode(N->getOpcode(), dl, WideDstVT, Src, N->getOperand(1));
8351 return DAG.getNode(
8352 ISD::EXTRACT_SUBVECTOR, dl, DstVT, Res,
8353 DAG.getConstant(0, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
8354 }
8355
8356 // Give up and unroll.
8357 return DAG.UnrollVectorOp(N);
8358}
8359
8360SDValue DAGTypeLegalizer::WidenVecOp_BITCAST(SDNode *N) {
8361 EVT VT = N->getValueType(0);
8362 SDValue InOp = GetWidenedVector(N->getOperand(0));
8363 EVT InWidenVT = InOp.getValueType();
8364 SDLoc dl(N);
8365
8366 // Check if we can convert between two legal vector types and extract.
8367 TypeSize InWidenSize = InWidenVT.getSizeInBits();
8368 TypeSize Size = VT.getSizeInBits();
8369 // x86mmx is not an acceptable vector element type, so don't try.
8370 if (!VT.isVector() && VT != MVT::x86mmx &&
8371 InWidenSize.hasKnownScalarFactor(Size)) {
8372 unsigned NewNumElts = InWidenSize.getKnownScalarFactor(Size);
8373 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), VT, NewNumElts);
8374 if (TLI.isTypeLegal(NewVT)) {
8375 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
8376 return DAG.getExtractVectorElt(dl, VT, BitOp, 0);
8377 }
8378 }
8379
8380 // Handle a case like bitcast v12i8 -> v3i32. Normally that would get widened
8381 // to v16i8 -> v4i32, but for a target where v3i32 is legal but v12i8 is not,
8382 // we end up here. Handling the case here with EXTRACT_SUBVECTOR avoids
8383 // having to copy via memory.
8384 if (VT.isVector()) {
8385 EVT EltVT = VT.getVectorElementType();
8386 unsigned EltSize = EltVT.getFixedSizeInBits();
8387 if (InWidenSize.isKnownMultipleOf(EltSize)) {
8388 ElementCount NewNumElts =
8389 (InWidenVT.getVectorElementCount() * InWidenVT.getScalarSizeInBits())
8390 .divideCoefficientBy(EltSize);
8391 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NewNumElts);
8392 if (TLI.isTypeLegal(NewVT)) {
8393 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
8394 return DAG.getExtractSubvector(dl, VT, BitOp, 0);
8395 }
8396 }
8397 }
8398
8399 return CreateStackStoreLoad(InOp, VT);
8400}
8401
8402// Vectors with sizes that are not powers of 2 need to be widened to the
8403// next largest power of 2. For example, we may get a vector of 3 32-bit
8404// integers or of 6 16-bit integers, both of which have to be widened to a
8405// 128-bit vector.
8406SDValue DAGTypeLegalizer::WidenVecOp_FAKE_USE(SDNode *N) {
8407 SDValue WidenedOp = GetWidenedVector(N->getOperand(1));
8408 return DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, N->getOperand(0),
8409 WidenedOp);
8410}
8411
8412SDValue DAGTypeLegalizer::WidenVecOp_CONCAT_VECTORS(SDNode *N) {
8413 EVT VT = N->getValueType(0);
8414 EVT EltVT = VT.getVectorElementType();
8415 EVT InVT = N->getOperand(0).getValueType();
8416 SDLoc dl(N);
8417
8418 // If the widen width for this operand is the same as the width of the concat
8419 // and all but the first operand is undef, just use the widened operand.
8420 unsigned NumOperands = N->getNumOperands();
8421 if (VT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
8422 unsigned i;
8423 for (i = 1; i < NumOperands; ++i)
8424 if (!N->getOperand(i).isUndef())
8425 break;
8426
8427 if (i == NumOperands)
8428 return GetWidenedVector(N->getOperand(0));
8429 }
8430
8431 if (VT.isScalableVector()) {
8432 SDValue Result = DAG.getPOISON(VT);
8433 unsigned NumInElts = InVT.getVectorMinNumElements();
8434 for (unsigned i = 0; i < NumOperands; ++i) {
8435 SDValue InOp = GetWidenedVector(N->getOperand(i));
8436 if (InOp.getValueType() != InVT)
8437 InOp = DAG.getExtractSubvector(dl, InVT, InOp, 0);
8438 Result = DAG.getInsertSubvector(dl, Result, InOp, i * NumInElts);
8439 }
8440 return Result;
8441 }
8442
8443 // Otherwise, fall back to a nasty build vector.
8444 unsigned NumElts = VT.getVectorNumElements();
8446
8447 unsigned NumInElts = InVT.getVectorNumElements();
8448
8449 unsigned Idx = 0;
8450 for (unsigned i=0; i < NumOperands; ++i) {
8451 SDValue InOp = N->getOperand(i);
8452 assert(getTypeAction(InOp.getValueType()) ==
8454 "Unexpected type action");
8455 InOp = GetWidenedVector(InOp);
8456 for (unsigned j = 0; j < NumInElts; ++j)
8457 Ops[Idx++] = DAG.getExtractVectorElt(dl, EltVT, InOp, j);
8458 }
8459 return DAG.getBuildVector(VT, dl, Ops);
8460}
8461
8462SDValue DAGTypeLegalizer::WidenVecOp_VECTOR_REPEAT(SDNode *N) {
8463 SDLoc DL(N);
8464 EVT VT = N->getValueType(0);
8465 SDValue Src = N->getOperand(0);
8466 EVT SrcVT = Src.getValueType();
8467 EVT WidenedSrcVT = TLI.getTypeToTransformTo(*DAG.getContext(), SrcVT);
8468
8469 if (!WidenedSrcVT.getVectorElementCount().hasKnownScalarFactor(
8470 SrcVT.getVectorElementCount()))
8472 "Cannot widen VECTOR_REPEAT operand to an ElementCount that's not "
8473 "a known scalar multiple of the input ElementCount.");
8474
8475 // Repeat the original source because the extra lanes of its widened value
8476 // are unspecified.
8477 unsigned NumConcat =
8478 WidenedSrcVT.getVectorNumElements() / SrcVT.getVectorNumElements();
8479 SmallVector<SDValue, 8> Ops(NumConcat, Src);
8480 SDValue WidenedSrc = DAG.getNode(ISD::CONCAT_VECTORS, DL, WidenedSrcVT, Ops);
8481 EVT WidenedVT = VT.changeVectorElementCount(
8482 *DAG.getContext(),
8484 SDValue Widened = DAG.getNode(ISD::VECTOR_REPEAT, DL, WidenedVT, WidenedSrc);
8485 return DAG.getExtractSubvector(DL, VT, Widened, 0);
8486}
8487
8488SDValue DAGTypeLegalizer::WidenVecOp_INSERT_SUBVECTOR(SDNode *N) {
8489 EVT VT = N->getValueType(0);
8490 SDValue SubVec = N->getOperand(1);
8491 SDValue InVec = N->getOperand(0);
8492
8493 EVT OrigVT = SubVec.getValueType();
8494 SubVec = GetWidenedVector(SubVec);
8495 EVT SubVT = SubVec.getValueType();
8496
8497 // Whether or not all the elements of the widened SubVec will be inserted into
8498 // valid indices of VT.
8499 bool IndicesValid = false;
8500 // If we statically know that VT can fit SubVT, the indices are valid.
8501 if (VT.knownBitsGE(SubVT))
8502 IndicesValid = true;
8503 else if (VT.isScalableVector() && SubVT.isFixedLengthVector()) {
8504 // Otherwise, if we're inserting a fixed vector into a scalable vector and
8505 // we know the minimum vscale we can work out if it's valid ourselves.
8506 Attribute Attr = DAG.getMachineFunction().getFunction().getFnAttribute(
8507 Attribute::VScaleRange);
8508 if (Attr.isValid()) {
8509 unsigned VScaleMin = Attr.getVScaleRangeMin();
8510 if (VT.getSizeInBits().getKnownMinValue() * VScaleMin >=
8511 SubVT.getFixedSizeInBits())
8512 IndicesValid = true;
8513 }
8514 }
8515
8516 if (!IndicesValid)
8518 "Don't know how to widen the operands for INSERT_SUBVECTOR");
8519
8520 SDLoc DL(N);
8521
8522 // We need to make sure that the indices are still valid, otherwise we might
8523 // widen what was previously well-defined to something undefined.
8524 if (InVec.isUndef() && N->getConstantOperandVal(2) == 0)
8525 return DAG.getNode(ISD::INSERT_SUBVECTOR, DL, VT, InVec, SubVec,
8526 N->getOperand(2));
8527
8528 if (OrigVT.isScalableVector()) {
8529 // When the widened types match, overwriting the start of a vector is
8530 // effectively a merge operation that can be implement as a vselect.
8531 if (SubVT == VT && N->getConstantOperandVal(2) == 0) {
8532 SDValue Mask =
8533 DAG.getMaskFromElementCount(DL, VT, OrigVT.getVectorElementCount());
8534 return DAG.getNode(ISD::VSELECT, DL, VT, Mask, SubVec, InVec);
8535 }
8536
8537 // Fallback to inserting through memory.
8538 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
8539 SDValue StackPtr = DAG.CreateStackTemporary(VT.getStoreSize(), Alignment);
8540 MachineFunction &MF = DAG.getMachineFunction();
8541 int FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
8542 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
8543
8544 MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
8547 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
8550
8551 // Write out the vector being inserting into.
8552 SDValue Ch =
8553 DAG.getStore(DAG.getEntryNode(), DL, InVec, StackPtr, StoreMMO);
8554
8555 // Build a mask to match the length of the sub-vector.
8556 SDValue Mask =
8557 DAG.getMaskFromElementCount(DL, SubVT, OrigVT.getVectorElementCount());
8558
8559 // Overwrite the sub-vector at the required offset.
8560 SDValue SubVecPtr =
8561 TLI.getVectorSubVecPointer(DAG, StackPtr, VT, OrigVT, N->getOperand(2));
8562 Ch = DAG.getMaskedStore(Ch, DL, SubVec, SubVecPtr,
8563 DAG.getPOISON(SubVecPtr.getValueType()), Mask, VT,
8564 StoreMMO, ISD::UNINDEXED, ISD::NON_EXTLOAD);
8565
8566 // Read back the result.
8567 return DAG.getLoad(VT, DL, Ch, StackPtr, LoadMMO);
8568 }
8569
8570 // If the operands can't be widened legally, just replace the INSERT_SUBVECTOR
8571 // with a series of INSERT_VECTOR_ELT
8572 unsigned Idx = N->getConstantOperandVal(2);
8573
8574 SDValue InsertElt = InVec;
8575 for (unsigned I = 0, E = OrigVT.getVectorNumElements(); I != E; ++I) {
8576 SDValue ExtractElt =
8577 DAG.getExtractVectorElt(DL, VT.getVectorElementType(), SubVec, I);
8578 InsertElt = DAG.getInsertVectorElt(DL, InsertElt, ExtractElt, I + Idx);
8579 }
8580
8581 return InsertElt;
8582}
8583
8584SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
8585 SDValue InOp = GetWidenedVector(N->getOperand(0));
8586 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SDLoc(N),
8587 N->getValueType(0), InOp, N->getOperand(1));
8588}
8589
8590SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
8591 SDValue InOp = GetWidenedVector(N->getOperand(0));
8592 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
8593 N->getValueType(0), InOp, N->getOperand(1));
8594}
8595
8596SDValue DAGTypeLegalizer::WidenVecOp_EXTEND_VECTOR_INREG(SDNode *N) {
8597 SDLoc DL(N);
8598 EVT ResVT = N->getValueType(0);
8599
8600 // Widen the input as requested by the legalizer.
8601 SDValue WideInOp = GetWidenedVector(N->getOperand(0));
8602 EVT WideInVT = WideInOp.getValueType();
8603
8604 // Simple case: if widened input is still smaller than or equal to result,
8605 // just use it directly.
8606 if (WideInVT.getSizeInBits() <= ResVT.getSizeInBits())
8607 return DAG.getNode(N->getOpcode(), DL, ResVT, WideInOp);
8608
8609 // EXTEND_VECTOR_INREG requires input bits <= result bits.
8610 // If widening makes the input larger than the original result, widen the
8611 // result to match, then extract back down.
8612 EVT ResEltVT = ResVT.getVectorElementType();
8613 unsigned EltBits = ResEltVT.getSizeInBits();
8614 assert((WideInVT.getSizeInBits() % EltBits) == 0 &&
8615 "Widened input size must be a multiple of result element size");
8616
8617 unsigned WideNumElts = WideInVT.getSizeInBits() / EltBits;
8618 EVT WideResVT = EVT::getVectorVT(*DAG.getContext(), ResEltVT, WideNumElts);
8619
8620 SDValue WideRes = DAG.getNode(N->getOpcode(), DL, WideResVT, WideInOp);
8621 return DAG.getExtractSubvector(DL, ResVT, WideRes, 0);
8622}
8623
8624SDValue DAGTypeLegalizer::WidenVecOp_STORE(SDNode *N) {
8625 // We have to widen the value, but we want only to store the original
8626 // vector type.
8627 StoreSDNode *ST = cast<StoreSDNode>(N);
8628
8629 if (!ST->getMemoryVT().getScalarType().isByteSized())
8630 return TLI.scalarizeVectorStore(ST, DAG);
8631
8632 if (ST->isTruncatingStore())
8633 return TLI.scalarizeVectorStore(ST, DAG);
8634
8635 // Generate a vector-predicated store if it is custom/legal on the target.
8636 // To avoid possible recursion, only do this if the widened mask type is
8637 // legal.
8638 // FIXME: Not all targets may support EVL in VP_STORE. These will have been
8639 // removed from the IR by the ExpandVectorPredication pass but we're
8640 // reintroducing them here.
8641 SDValue StVal = ST->getValue();
8642 EVT StVT = StVal.getValueType();
8643 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), StVT);
8644 EVT WideMaskVT = getSetCCResultType(WideVT);
8645
8646 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
8647 TLI.isTypeLegal(WideMaskVT)) {
8648 // Widen the value.
8649 SDLoc DL(N);
8650 StVal = GetWidenedVector(StVal);
8651 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
8652 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
8653 StVT.getVectorElementCount());
8654 return DAG.getStoreVP(ST->getChain(), DL, StVal, ST->getBasePtr(),
8655 ST->getOffset(), Mask, EVL, StVT, ST->getMemOperand(),
8656 ST->getAddressingMode());
8657 }
8658
8660 if (GenWidenVectorStores(StChain, ST)) {
8661 if (StChain.size() == 1)
8662 return StChain[0];
8663
8664 return DAG.getNode(ISD::TokenFactor, SDLoc(ST), MVT::Other, StChain);
8665 }
8666
8667 if (StVT.isVector()) {
8668 // If all else fails replace the store with a wide masked store.
8669 SDLoc DL(N);
8670 SDValue WideStVal = GetWidenedVector(StVal);
8671 SDValue Mask =
8672 DAG.getMaskFromElementCount(DL, WideVT, StVT.getVectorElementCount());
8673
8674 return DAG.getMaskedStore(ST->getChain(), DL, WideStVal, ST->getBasePtr(),
8675 ST->getOffset(), Mask, ST->getMemoryVT(),
8676 ST->getMemOperand(), ST->getAddressingMode(),
8677 ST->isTruncatingStore());
8678 }
8679
8680 report_fatal_error("Unable to widen vector store");
8681}
8682
8683SDValue DAGTypeLegalizer::WidenVecOp_ATOMIC_STORE(AtomicSDNode *ST) {
8684 EVT StVT = ST->getMemoryVT();
8685 SDLoc dl(ST);
8686
8687 SDValue StVal = GetWidenedVector(ST->getVal());
8688 EVT WidenVT = StVal.getValueType();
8689
8690 TypeSize StWidth = StVT.getSizeInBits();
8691 TypeSize WidenWidth = WidenVT.getSizeInBits();
8692 TypeSize WidthDiff = WidenWidth - StWidth;
8693
8694 // Find the vector type that can store the original memory width in one
8695 // atomic operation. Pass StAlign=0 (like atomic loads); a real align would
8696 // let findMemType widen the access past the value (e.g. <2 x i8> at align 4
8697 // implies a 4-byte movl, writing undef bytes past its object).
8698 std::optional<EVT> FirstVT =
8699 findMemType(DAG, TLI, StWidth.getKnownMinValue(), WidenVT, /*StAlign=*/0,
8700 WidthDiff.getKnownMinValue());
8701 if (!FirstVT)
8702 return SDValue();
8703
8704 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
8705
8706 SDValue StOp =
8707 coerceStoredValue(StVal, *FirstVT, WidenVT, FirstVTWidth, dl, DAG);
8708
8709 return DAG.getAtomic(ISD::ATOMIC_STORE, dl, *FirstVT, ST->getChain(), StOp,
8710 ST->getBasePtr(), ST->getMemOperand());
8711}
8712
8713SDValue DAGTypeLegalizer::WidenVecOp_VP_STORE(SDNode *N, unsigned OpNo) {
8714 assert((OpNo == 1 || OpNo == 3) &&
8715 "Can widen only data or mask operand of vp_store");
8716 VPStoreSDNode *ST = cast<VPStoreSDNode>(N);
8717 SDValue Mask = ST->getMask();
8718 SDValue StVal = ST->getValue();
8719 SDLoc dl(N);
8720
8721 if (OpNo == 1) {
8722 // Widen the value.
8723 StVal = GetWidenedVector(StVal);
8724
8725 // We only handle the case where the mask needs widening to an
8726 // identically-sized type as the vector inputs.
8727 assert(getTypeAction(Mask.getValueType()) ==
8729 "Unable to widen VP store");
8730 Mask = GetWidenedVector(Mask);
8731 } else {
8732 Mask = GetWidenedVector(Mask);
8733
8734 // We only handle the case where the stored value needs widening to an
8735 // identically-sized type as the mask.
8736 assert(getTypeAction(StVal.getValueType()) ==
8738 "Unable to widen VP store");
8739 StVal = GetWidenedVector(StVal);
8740 }
8741
8742 assert(Mask.getValueType().getVectorElementCount() ==
8744 "Mask and data vectors should have the same number of elements");
8745 return DAG.getStoreVP(ST->getChain(), dl, StVal, ST->getBasePtr(),
8746 ST->getOffset(), Mask, ST->getVectorLength(),
8747 ST->getMemoryVT(), ST->getMemOperand(),
8748 ST->getAddressingMode(), ST->isTruncatingStore(),
8749 ST->isCompressingStore());
8750}
8751
8752SDValue DAGTypeLegalizer::WidenVecOp_VP_STRIDED_STORE(SDNode *N,
8753 unsigned OpNo) {
8754 assert((OpNo == 1 || OpNo == 4) &&
8755 "Can widen only data or mask operand of vp_strided_store");
8756 VPStridedStoreSDNode *SST = cast<VPStridedStoreSDNode>(N);
8757 SDValue Mask = SST->getMask();
8758 SDValue StVal = SST->getValue();
8759 SDLoc DL(N);
8760
8761 if (OpNo == 1)
8762 assert(getTypeAction(Mask.getValueType()) ==
8764 "Unable to widen VP strided store");
8765 else
8766 assert(getTypeAction(StVal.getValueType()) ==
8768 "Unable to widen VP strided store");
8769
8770 StVal = GetWidenedVector(StVal);
8771 Mask = GetWidenedVector(Mask);
8772
8774 Mask.getValueType().getVectorElementCount() &&
8775 "Data and mask vectors should have the same number of elements");
8776
8777 return DAG.getStridedStoreVP(
8778 SST->getChain(), DL, StVal, SST->getBasePtr(), SST->getOffset(),
8779 SST->getStride(), Mask, SST->getVectorLength(), SST->getMemoryVT(),
8780 SST->getMemOperand(), SST->getAddressingMode(), SST->isTruncatingStore(),
8781 SST->isCompressingStore());
8782}
8783
8784SDValue DAGTypeLegalizer::WidenVecOp_MSTORE(SDNode *N, unsigned OpNo) {
8785 assert((OpNo == 1 || OpNo == 4) &&
8786 "Can widen only data or mask operand of mstore");
8787 MaskedStoreSDNode *MST = cast<MaskedStoreSDNode>(N);
8788 SDValue Mask = MST->getMask();
8789 EVT MaskVT = Mask.getValueType();
8790 SDValue StVal = MST->getValue();
8791 EVT VT = StVal.getValueType();
8792 SDLoc dl(N);
8793
8794 EVT WideVT, WideMaskVT;
8795 if (OpNo == 1) {
8796 // Widen the value.
8797 StVal = GetWidenedVector(StVal);
8798
8799 WideVT = StVal.getValueType();
8800 WideMaskVT =
8801 EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(),
8802 WideVT.getVectorElementCount());
8803 } else {
8804 WideMaskVT = TLI.getTypeToTransformTo(*DAG.getContext(), MaskVT);
8805
8806 EVT ValueVT = StVal.getValueType();
8807 WideVT = EVT::getVectorVT(*DAG.getContext(), ValueVT.getVectorElementType(),
8808 WideMaskVT.getVectorElementCount());
8809 }
8810
8811 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
8812 TLI.isTypeLegal(WideMaskVT) && !MST->isCompressingStore()) {
8813 Mask = DAG.getInsertSubvector(dl, DAG.getPOISON(WideMaskVT), Mask, 0);
8814 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8816 return DAG.getStoreVP(MST->getChain(), dl, StVal, MST->getBasePtr(),
8817 MST->getOffset(), Mask, EVL, MST->getMemoryVT(),
8818 MST->getMemOperand(), MST->getAddressingMode());
8819 }
8820
8821 if (OpNo == 1) {
8822 // The mask should be widened as well.
8823 Mask = ModifyToType(Mask, WideMaskVT, true);
8824 } else {
8825 // Widen the mask.
8826 Mask = ModifyToType(Mask, WideMaskVT, true);
8827
8828 StVal = ModifyToType(StVal, WideVT);
8829 }
8830
8831 assert(Mask.getValueType().getVectorElementCount() ==
8833 "Mask and data vectors should have the same number of elements");
8834 return DAG.getMaskedStore(MST->getChain(), dl, StVal, MST->getBasePtr(),
8835 MST->getOffset(), Mask, MST->getMemoryVT(),
8836 MST->getMemOperand(), MST->getAddressingMode(),
8837 false, MST->isCompressingStore());
8838}
8839
8840SDValue DAGTypeLegalizer::WidenVecOp_MGATHER(SDNode *N, unsigned OpNo) {
8841 assert(OpNo == 4 && "Can widen only the index of mgather");
8842 auto *MG = cast<MaskedGatherSDNode>(N);
8843 SDValue DataOp = MG->getPassThru();
8844 SDValue Mask = MG->getMask();
8845 SDValue Scale = MG->getScale();
8846
8847 // Just widen the index. It's allowed to have extra elements.
8848 SDValue Index = GetWidenedVector(MG->getIndex());
8849
8850 SDLoc dl(N);
8851 SDValue Ops[] = {MG->getChain(), DataOp, Mask, MG->getBasePtr(), Index,
8852 Scale};
8853 SDValue Res = DAG.getMaskedGather(MG->getVTList(), MG->getMemoryVT(), dl, Ops,
8854 MG->getMemOperand(), MG->getIndexType(),
8855 MG->getExtensionType());
8856 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
8857 ReplaceValueWith(SDValue(N, 0), Res.getValue(0));
8858 return SDValue();
8859}
8860
8861SDValue DAGTypeLegalizer::WidenVecOp_MSCATTER(SDNode *N, unsigned OpNo) {
8862 MaskedScatterSDNode *MSC = cast<MaskedScatterSDNode>(N);
8863 SDValue DataOp = MSC->getValue();
8864 SDValue Mask = MSC->getMask();
8865 SDValue Index = MSC->getIndex();
8866 SDValue Scale = MSC->getScale();
8867 EVT WideMemVT = MSC->getMemoryVT();
8868
8869 if (OpNo == 1) {
8870 DataOp = GetWidenedVector(DataOp);
8871 ElementCount WideEC = DataOp.getValueType().getVectorElementCount();
8872
8873 // Widen index.
8874 EVT IndexVT = Index.getValueType();
8875 EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
8876 IndexVT.getVectorElementType(), WideEC);
8877 Index = ModifyToType(Index, WideIndexVT);
8878
8879 // The mask should be widened as well.
8880 EVT MaskVT = Mask.getValueType();
8881 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
8882 MaskVT.getVectorElementType(), WideEC);
8883 Mask = ModifyToType(Mask, WideMaskVT, true);
8884
8885 // Widen the MemoryType
8886 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
8887 MSC->getMemoryVT().getScalarType(), WideEC);
8888 } else if (OpNo == 4) {
8889 // Just widen the index. It's allowed to have extra elements.
8890 Index = GetWidenedVector(Index);
8891 } else
8892 llvm_unreachable("Can't widen this operand of mscatter");
8893
8894 SDValue Ops[] = {MSC->getChain(), DataOp, Mask, MSC->getBasePtr(), Index,
8895 Scale};
8896 return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N),
8897 Ops, MSC->getMemOperand(), MSC->getIndexType(),
8898 MSC->isTruncatingStore());
8899}
8900
8901SDValue DAGTypeLegalizer::WidenVecOp_VP_SCATTER(SDNode *N, unsigned OpNo) {
8902 VPScatterSDNode *VPSC = cast<VPScatterSDNode>(N);
8903 SDValue DataOp = VPSC->getValue();
8904 SDValue Mask = VPSC->getMask();
8905 SDValue Index = VPSC->getIndex();
8906 SDValue Scale = VPSC->getScale();
8907 EVT WideMemVT = VPSC->getMemoryVT();
8908
8909 if (OpNo == 1) {
8910 DataOp = GetWidenedVector(DataOp);
8911 Index = GetWidenedVector(Index);
8912 const auto WideEC = DataOp.getValueType().getVectorElementCount();
8913 Mask = GetWidenedMask(Mask, WideEC);
8914 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
8915 VPSC->getMemoryVT().getScalarType(), WideEC);
8916 } else if (OpNo == 3) {
8917 // Just widen the index. It's allowed to have extra elements.
8918 Index = GetWidenedVector(Index);
8919 } else
8920 llvm_unreachable("Can't widen this operand of VP_SCATTER");
8921
8922 SDValue Ops[] = {
8923 VPSC->getChain(), DataOp, VPSC->getBasePtr(), Index, Scale, Mask,
8924 VPSC->getVectorLength()};
8925 return DAG.getScatterVP(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N), Ops,
8926 VPSC->getMemOperand(), VPSC->getIndexType());
8927}
8928
8929SDValue DAGTypeLegalizer::WidenVecOp_SETCC(SDNode *N) {
8930 SDValue InOp0 = GetWidenedVector(N->getOperand(0));
8931 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
8932 SDLoc dl(N);
8933 EVT VT = N->getValueType(0);
8934
8935 // WARNING: In this code we widen the compare instruction with garbage.
8936 // This garbage may contain denormal floats which may be slow. Is this a real
8937 // concern ? Should we zero the unused lanes if this is a float compare ?
8938
8939 // Get a new SETCC node to compare the newly widened operands.
8940 // Only some of the compared elements are legal.
8941 EVT SVT = getSetCCResultType(InOp0.getValueType());
8942 // The result type is legal, if its vXi1, keep vXi1 for the new SETCC.
8943 if (VT.getScalarType() == MVT::i1)
8944 SVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8945 SVT.getVectorElementCount());
8946
8947 SDValue WideSETCC = DAG.getNode(ISD::SETCC, SDLoc(N),
8948 SVT, InOp0, InOp1, N->getOperand(2));
8949
8950 // Extract the needed results from the result vector.
8951 EVT ResVT = EVT::getVectorVT(*DAG.getContext(),
8954 SDValue CC = DAG.getExtractSubvector(dl, ResVT, WideSETCC, 0);
8955
8956 EVT OpVT = N->getOperand(0).getValueType();
8957 ISD::NodeType ExtendCode =
8958 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
8959 return DAG.getNode(ExtendCode, dl, VT, CC);
8960}
8961
8962SDValue DAGTypeLegalizer::WidenVecOp_STRICT_FSETCC(SDNode *N) {
8963 SDValue Chain = N->getOperand(0);
8964 SDValue LHS = GetWidenedVector(N->getOperand(1));
8965 SDValue RHS = GetWidenedVector(N->getOperand(2));
8966 SDValue CC = N->getOperand(3);
8967 SDLoc dl(N);
8968
8969 EVT VT = N->getValueType(0);
8970 EVT EltVT = VT.getVectorElementType();
8971 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
8972 unsigned NumElts = VT.getVectorNumElements();
8973
8974 // Unroll into a build vector.
8975 SmallVector<SDValue, 8> Scalars(NumElts);
8976 SmallVector<SDValue, 8> Chains(NumElts);
8977
8978 for (unsigned i = 0; i != NumElts; ++i) {
8979 SDValue LHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, LHS, i);
8980 SDValue RHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, RHS, i);
8981
8982 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
8983 {Chain, LHSElem, RHSElem, CC});
8984 Chains[i] = Scalars[i].getValue(1);
8985 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
8986 DAG.getBoolConstant(true, dl, EltVT, VT),
8987 DAG.getBoolConstant(false, dl, EltVT, VT));
8988 }
8989
8990 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
8991 ReplaceValueWith(SDValue(N, 1), NewChain);
8992
8993 return DAG.getBuildVector(VT, dl, Scalars);
8994}
8995
8996static unsigned getExtendForIntVecReduction(unsigned Opc) {
8997 switch (Opc) {
8998 default:
8999 llvm_unreachable("Expected integer vector reduction");
9000 case ISD::VECREDUCE_ADD:
9001 case ISD::VECREDUCE_MUL:
9002 case ISD::VECREDUCE_AND:
9003 case ISD::VECREDUCE_OR:
9004 case ISD::VECREDUCE_XOR:
9005 return ISD::ANY_EXTEND;
9008 return ISD::SIGN_EXTEND;
9011 return ISD::ZERO_EXTEND;
9012 }
9013}
9014
9015SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE(SDNode *N) {
9016 SDLoc dl(N);
9017 SDValue Op = GetWidenedVector(N->getOperand(0));
9018 EVT VT = N->getValueType(0);
9019 EVT OrigVT = N->getOperand(0).getValueType();
9020 EVT WideVT = Op.getValueType();
9021 EVT ElemVT = OrigVT.getVectorElementType();
9022 SDNodeFlags Flags = N->getFlags();
9023
9024 unsigned Opc = N->getOpcode();
9025 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
9026 SDValue NeutralElem = DAG.getIdentityElement(BaseOpc, dl, ElemVT, Flags);
9027 assert(NeutralElem && "Neutral element must exist");
9028
9029 // Pad the vector with the neutral element.
9030 unsigned OrigElts = OrigVT.getVectorMinNumElements();
9031 unsigned WideElts = WideVT.getVectorMinNumElements();
9032
9033 // Generate a vp.reduce_op if it is custom/legal for the target. This avoids
9034 // needing to pad the source vector, because the inactive lanes can simply be
9035 // disabled and not contribute to the result.
9036 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opc);
9037 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WideVT)) {
9038 SDValue Start = NeutralElem;
9039 if (VT.isInteger())
9040 Start = DAG.getNode(getExtendForIntVecReduction(Opc), dl, VT, Start);
9041 assert(Start.getValueType() == VT);
9042 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
9043 WideVT.getVectorElementCount());
9044 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
9045 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
9046 OrigVT.getVectorElementCount());
9047 return DAG.getNode(*VPOpcode, dl, VT, {Start, Op, Mask, EVL}, Flags);
9048 }
9049
9050 if (WideVT.isScalableVector()) {
9051 unsigned GCD = std::gcd(OrigElts, WideElts);
9052 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
9054 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
9055 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
9056 Op = DAG.getInsertSubvector(dl, Op, SplatNeutral, Idx);
9057 return DAG.getNode(Opc, dl, VT, Op, Flags);
9058 }
9059
9060 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
9061 Op = DAG.getInsertVectorElt(dl, Op, NeutralElem, Idx);
9062
9063 return DAG.getNode(Opc, dl, VT, Op, Flags);
9064}
9065
9066SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE_SEQ(SDNode *N) {
9067 SDLoc dl(N);
9068 SDValue AccOp = N->getOperand(0);
9069 SDValue VecOp = N->getOperand(1);
9070 SDValue Op = GetWidenedVector(VecOp);
9071
9072 EVT VT = N->getValueType(0);
9073 EVT OrigVT = VecOp.getValueType();
9074 EVT WideVT = Op.getValueType();
9075 EVT ElemVT = OrigVT.getVectorElementType();
9076 SDNodeFlags Flags = N->getFlags();
9077
9078 unsigned Opc = N->getOpcode();
9079 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
9080 SDValue NeutralElem = DAG.getIdentityElement(BaseOpc, dl, ElemVT, Flags);
9081
9082 // Pad the vector with the neutral element.
9083 unsigned OrigElts = OrigVT.getVectorMinNumElements();
9084 unsigned WideElts = WideVT.getVectorMinNumElements();
9085
9086 // Generate a vp.reduce_op if it is custom/legal for the target. This avoids
9087 // needing to pad the source vector, because the inactive lanes can simply be
9088 // disabled and not contribute to the result.
9089 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opc);
9090 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WideVT)) {
9091 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
9092 WideVT.getVectorElementCount());
9093 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
9094 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
9095 OrigVT.getVectorElementCount());
9096 return DAG.getNode(*VPOpcode, dl, VT, {AccOp, Op, Mask, EVL}, Flags);
9097 }
9098
9099 if (WideVT.isScalableVector()) {
9100 unsigned GCD = std::gcd(OrigElts, WideElts);
9101 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
9103 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
9104 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
9105 Op = DAG.getInsertSubvector(dl, Op, SplatNeutral, Idx);
9106 return DAG.getNode(Opc, dl, VT, AccOp, Op, Flags);
9107 }
9108
9109 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
9110 Op = DAG.getInsertVectorElt(dl, Op, NeutralElem, Idx);
9111
9112 return DAG.getNode(Opc, dl, VT, AccOp, Op, Flags);
9113}
9114
9115SDValue DAGTypeLegalizer::WidenVecOp_VP_REDUCE(SDNode *N) {
9116 assert(N->isVPOpcode() && "Expected VP opcode");
9117
9118 SDLoc dl(N);
9119 SDValue Op = GetWidenedVector(N->getOperand(1));
9120 SDValue Mask = GetWidenedMask(N->getOperand(2),
9121 Op.getValueType().getVectorElementCount());
9122
9123 return DAG.getNode(N->getOpcode(), dl, N->getValueType(0),
9124 {N->getOperand(0), Op, Mask, N->getOperand(3)},
9125 N->getFlags());
9126}
9127
9128SDValue DAGTypeLegalizer::WidenVecOp_VSELECT(SDNode *N) {
9129 // This only gets called in the case that the left and right inputs and
9130 // result are of a legal odd vector type, and the condition is illegal i1 of
9131 // the same odd width that needs widening.
9132 EVT VT = N->getValueType(0);
9133 assert(VT.isVector() && !VT.isPow2VectorType() && isTypeLegal(VT));
9134
9135 SDValue Cond = GetWidenedVector(N->getOperand(0));
9136 SDValue LeftIn = DAG.WidenVector(N->getOperand(1), SDLoc(N));
9137 SDValue RightIn = DAG.WidenVector(N->getOperand(2), SDLoc(N));
9138 SDLoc DL(N);
9139
9140 SDValue Select = DAG.getNode(N->getOpcode(), DL, LeftIn.getValueType(), Cond,
9141 LeftIn, RightIn);
9142 return DAG.getExtractSubvector(DL, VT, Select, 0);
9143}
9144
9145SDValue DAGTypeLegalizer::WidenVecOp_CttzElements(SDNode *N) {
9146 SDLoc DL(N);
9147 SDValue Source = N->getOperand(0);
9148 EVT SourceVT = Source.getValueType();
9149 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), SourceVT);
9150
9151 SDValue WideSource;
9152 if (N->getOpcode() == ISD::CTTZ_ELTS_ZERO_POISON) {
9153 WideSource = GetWidenedVector(Source);
9154 } else {
9155 // Pad the widened portion with all-ones so the extra lanes appear as
9156 // active (non-zero) elements and do not contribute trailing zeros.
9157 SDValue AllOnes = DAG.getAllOnesConstant(DL, WideVT);
9158 if (WideVT.isFixedLengthVector() &&
9159 getTypeAction(WideVT) == TargetLowering::TypeSplitVector) {
9160 WideSource = GetWidenedVector(Source);
9161 unsigned WideElts = WideVT.getVectorNumElements();
9162 SmallVector<int> Mask(WideElts);
9163 std::iota(Mask.begin(), Mask.end(), 0);
9164 for (unsigned I = SourceVT.getVectorNumElements(); I != WideElts; ++I)
9165 Mask[I] += WideElts;
9166 WideSource = DAG.getVectorShuffle(WideVT, DL, WideSource, AllOnes, Mask);
9167 } else {
9168 WideSource = DAG.getInsertSubvector(DL, AllOnes, Source, 0);
9169 }
9170 }
9171
9172 return DAG.getNode(N->getOpcode(), DL, N->getValueType(0), WideSource,
9173 N->getFlags());
9174}
9175
9176SDValue DAGTypeLegalizer::WidenVecOp_VP_CttzElements(SDNode *N) {
9177 SDLoc DL(N);
9178 SDValue Source = GetWidenedVector(N->getOperand(0));
9179 EVT SrcVT = Source.getValueType();
9180 SDValue Mask =
9181 GetWidenedMask(N->getOperand(1), SrcVT.getVectorElementCount());
9182
9183 return DAG.getNode(N->getOpcode(), DL, N->getValueType(0),
9184 {Source, Mask, N->getOperand(2)}, N->getFlags());
9185}
9186
9187SDValue DAGTypeLegalizer::WidenVecOp_VECTOR_FIND_LAST_ACTIVE(SDNode *N) {
9188 SDLoc DL(N);
9189 SDValue Mask = N->getOperand(0);
9190 EVT OrigMaskVT = Mask.getValueType();
9191 SDValue WideMask = GetWidenedVector(Mask);
9192 EVT WideMaskVT = WideMask.getValueType();
9193
9194 // Pad the mask with zeros to ensure inactive lanes don't affect the result.
9195 unsigned OrigElts = OrigMaskVT.getVectorNumElements();
9196 unsigned WideElts = WideMaskVT.getVectorNumElements();
9197 if (OrigElts != WideElts) {
9198 SDValue ZeroMask = DAG.getConstant(0, DL, WideMaskVT);
9199 WideMask = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideMaskVT, ZeroMask,
9200 Mask, DAG.getVectorIdxConstant(0, DL));
9201 }
9202
9203 return DAG.getNode(ISD::VECTOR_FIND_LAST_ACTIVE, DL, N->getValueType(0),
9204 WideMask);
9205}
9206
9207SDValue DAGTypeLegalizer::WidenVecOp_VECTOR_MATCH(SDNode *N, unsigned OpNo) {
9208 if (OpNo == 0) {
9209 SDLoc DL(N);
9210 EVT ResVT = N->getValueType(0);
9211 EVT SourceVT = N->getOperand(0).getValueType();
9212 EVT WideSourceVT = TLI.getTypeToTransformTo(*DAG.getContext(), SourceVT);
9213 EVT WidenVT =
9214 EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
9215 WideSourceVT.getVectorElementCount());
9216
9217 SDValue WideSource = DAG.getInsertSubvector(DL, DAG.getUNDEF(WideSourceVT),
9218 N->getOperand(0), 0);
9219 SDValue WideMask = DAG.getInsertSubvector(
9220 DL, DAG.getConstant(0, DL, WidenVT), N->getOperand(2), 0);
9221 SDValue WideMatch = DAG.getNode(ISD::VECTOR_MATCH, DL, WidenVT, WideSource,
9222 N->getOperand(1), WideMask, N->getFlags());
9223 return DAG.getExtractSubvector(DL, ResVT, WideMatch, 0);
9224 }
9225
9226 // Note: The Mask (OpNo == 2) should be widened with the result.
9227 assert(OpNo == 1 && "Unexpected VECTOR_MATCH operand");
9228
9229 SDLoc DL(N);
9230 SDValue Needle = N->getOperand(1);
9231 EVT NeedleVT = Needle.getValueType();
9232 if (NeedleVT.getVectorNumElements() == 1)
9233 return TLI.expandVectorMatch(N, DAG);
9234
9235 EVT WidenNeedleVT = TLI.getTypeToTransformTo(*DAG.getContext(), NeedleVT);
9236
9237 SDValue Fill =
9238 DAG.getExtractVectorElt(DL, NeedleVT.getVectorElementType(), Needle, 0);
9239 SDValue WideNeedle = DAG.getSplatVector(WidenNeedleVT, DL, Fill);
9240 WideNeedle = DAG.getInsertSubvector(DL, WideNeedle, Needle, 0);
9241
9242 return DAG.getNode(ISD::VECTOR_MATCH, DL, N->getValueType(0),
9243 N->getOperand(0), WideNeedle, N->getOperand(2),
9244 N->getFlags());
9245}
9246
9247//===----------------------------------------------------------------------===//
9248// Vector Widening Utilities
9249//===----------------------------------------------------------------------===//
9250
9251// Utility function to find the type to chop up a widen vector for load/store
9252// TLI: Target lowering used to determine legal types.
9253// Width: Width left need to load/store.
9254// WidenVT: The widen vector type to load to/store from
9255// Align: If 0, don't allow use of a wider type
9256// WidenEx: If Align is not 0, the amount additional we can load/store from.
9257
9258static std::optional<EVT> findMemType(SelectionDAG &DAG,
9259 const TargetLowering &TLI, unsigned Width,
9260 EVT WidenVT, unsigned Align = 0,
9261 unsigned WidenEx = 0) {
9262 EVT WidenEltVT = WidenVT.getVectorElementType();
9263 const bool Scalable = WidenVT.isScalableVector();
9264 unsigned WidenWidth = WidenVT.getSizeInBits().getKnownMinValue();
9265 unsigned WidenEltWidth = WidenEltVT.getSizeInBits();
9266 unsigned AlignInBits = Align*8;
9267
9268 EVT RetVT = WidenEltVT;
9269 // Don't bother looking for an integer type if the vector is scalable, skip
9270 // to vector types.
9271 if (!Scalable) {
9272 // If we have one element to load/store, return it.
9273 if (Width == WidenEltWidth)
9274 return RetVT;
9275
9276 // See if there is larger legal integer than the element type to load/store.
9277 for (EVT MemVT : reverse(MVT::integer_valuetypes())) {
9278 unsigned MemVTWidth = MemVT.getSizeInBits();
9279 if (MemVT.getSizeInBits() <= WidenEltWidth)
9280 break;
9281 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
9282 if ((Action == TargetLowering::TypeLegal ||
9284 (WidenWidth % MemVTWidth) == 0 &&
9285 isPowerOf2_32(WidenWidth / MemVTWidth) &&
9286 (MemVTWidth <= Width ||
9287 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
9288 if (MemVTWidth == WidenWidth)
9289 return MemVT;
9290 RetVT = MemVT;
9291 break;
9292 }
9293 }
9294 }
9295
9296 // See if there is a larger vector type to load/store that has the same vector
9297 // element type and is evenly divisible with the WidenVT.
9298 for (EVT MemVT : reverse(MVT::vector_valuetypes())) {
9299 // Skip vector MVTs which don't match the scalable property of WidenVT.
9300 if (Scalable != MemVT.isScalableVector())
9301 continue;
9302 unsigned MemVTWidth = MemVT.getSizeInBits().getKnownMinValue();
9303 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
9304 if ((Action == TargetLowering::TypeLegal ||
9306 WidenEltVT == MemVT.getVectorElementType() &&
9307 (WidenWidth % MemVTWidth) == 0 &&
9308 isPowerOf2_32(WidenWidth / MemVTWidth) &&
9309 (MemVTWidth <= Width ||
9310 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
9311 if (RetVT.getFixedSizeInBits() < MemVTWidth || MemVT == WidenVT)
9312 return MemVT;
9313 }
9314 }
9315
9316 // Using element-wise loads and stores for widening operations is not
9317 // supported for scalable vectors
9318 if (Scalable)
9319 return std::nullopt;
9320
9321 return RetVT;
9322}
9323
9324// Builds a vector type from scalar loads
9325// VecTy: Resulting Vector type
9326// LDOps: Load operators to build a vector type
9327// [Start,End) the list of loads to use.
9330 unsigned Start, unsigned End) {
9331 SDLoc dl(LdOps[Start]);
9332 EVT LdTy = LdOps[Start].getValueType();
9333 unsigned Width = VecTy.getSizeInBits();
9334 unsigned NumElts = Width / LdTy.getSizeInBits();
9335 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), LdTy, NumElts);
9336
9337 unsigned Idx = 1;
9338 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT,LdOps[Start]);
9339
9340 for (unsigned i = Start + 1; i != End; ++i) {
9341 EVT NewLdTy = LdOps[i].getValueType();
9342 if (NewLdTy != LdTy) {
9343 NumElts = Width / NewLdTy.getSizeInBits();
9344 NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewLdTy, NumElts);
9345 VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, VecOp);
9346 // Readjust position and vector position based on new load type.
9347 Idx = Idx * LdTy.getSizeInBits() / NewLdTy.getSizeInBits();
9348 LdTy = NewLdTy;
9349 }
9350 VecOp = DAG.getInsertVectorElt(dl, VecOp, LdOps[i], Idx++);
9351 }
9352 return DAG.getNode(ISD::BITCAST, dl, VecTy, VecOp);
9353}
9354
9355SDValue DAGTypeLegalizer::GenWidenVectorLoads(SmallVectorImpl<SDValue> &LdChain,
9356 LoadSDNode *LD) {
9357 // The strategy assumes that we can efficiently load power-of-two widths.
9358 // The routine chops the vector into the largest vector loads with the same
9359 // element type or scalar loads and then recombines it to the widen vector
9360 // type.
9361 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
9362 EVT LdVT = LD->getMemoryVT();
9363 SDLoc dl(LD);
9364 assert(LdVT.isVector() && WidenVT.isVector());
9365 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
9367
9368 // Load information
9369 SDValue Chain = LD->getChain();
9370 SDValue BasePtr = LD->getBasePtr();
9371 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
9372 MMOMetadata Metadata = LD->getMMOMetadataForSubAccess();
9373
9374 TypeSize LdWidth = LdVT.getSizeInBits();
9375 TypeSize WidenWidth = WidenVT.getSizeInBits();
9376 TypeSize WidthDiff = WidenWidth - LdWidth;
9377 // Allow wider loads if they are sufficiently aligned to avoid memory faults
9378 // and if the original load is simple.
9379 unsigned LdAlign =
9380 (!LD->isSimple() || LdVT.isScalableVector()) ? 0 : LD->getAlign().value();
9381
9382 // Find the vector type that can load from.
9383 std::optional<EVT> FirstVT =
9384 findMemType(DAG, TLI, LdWidth.getKnownMinValue(), WidenVT, LdAlign,
9385 WidthDiff.getKnownMinValue());
9386
9387 if (!FirstVT)
9388 return SDValue();
9389
9390 SmallVector<EVT, 8> MemVTs;
9391 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
9392
9393 // Unless we're able to load in one instruction we must work out how to load
9394 // the remainder.
9395 if (!TypeSize::isKnownLE(LdWidth, FirstVTWidth)) {
9396 std::optional<EVT> NewVT = FirstVT;
9397 TypeSize RemainingWidth = LdWidth;
9398 TypeSize NewVTWidth = FirstVTWidth;
9399 do {
9400 RemainingWidth -= NewVTWidth;
9401 if (TypeSize::isKnownLT(RemainingWidth, NewVTWidth)) {
9402 // The current type we are using is too large. Find a better size.
9403 NewVT = findMemType(DAG, TLI, RemainingWidth.getKnownMinValue(),
9404 WidenVT, LdAlign, WidthDiff.getKnownMinValue());
9405 if (!NewVT)
9406 return SDValue();
9407 NewVTWidth = NewVT->getSizeInBits();
9408 }
9409 MemVTs.push_back(*NewVT);
9410 } while (TypeSize::isKnownGT(RemainingWidth, NewVTWidth));
9411 }
9412
9413 SDValue LdOp = DAG.getLoad(*FirstVT, dl, Chain, BasePtr, LD->getPointerInfo(),
9414 LD->getBaseAlign(), MMOFlags, Metadata);
9415 LdChain.push_back(LdOp.getValue(1));
9416
9417 // Check if we can load the element with one instruction.
9418 if (MemVTs.empty())
9419 return coerceLoadedValue(LdOp, *FirstVT, WidenVT, LdWidth, FirstVTWidth, dl,
9420 DAG);
9421
9422 // Load vector by using multiple loads from largest vector to scalar.
9424 LdOps.push_back(LdOp);
9425
9426 uint64_t ScaledOffset = 0;
9427 MachinePointerInfo MPI = LD->getPointerInfo();
9428
9429 // First incremement past the first load.
9430 IncrementPointer(cast<LoadSDNode>(LdOp), *FirstVT, MPI, BasePtr,
9431 &ScaledOffset);
9432
9433 for (EVT MemVT : MemVTs) {
9434 Align NewAlign = ScaledOffset == 0
9435 ? LD->getBaseAlign()
9436 : commonAlignment(LD->getAlign(), ScaledOffset);
9437 SDValue L = DAG.getLoad(MemVT, dl, Chain, BasePtr, MPI, NewAlign, MMOFlags,
9438 Metadata);
9439
9440 LdOps.push_back(L);
9441 LdChain.push_back(L.getValue(1));
9442 IncrementPointer(cast<LoadSDNode>(L), MemVT, MPI, BasePtr, &ScaledOffset);
9443 }
9444
9445 // Build the vector from the load operations.
9446 unsigned End = LdOps.size();
9447 if (!LdOps[0].getValueType().isVector())
9448 // All the loads are scalar loads.
9449 return BuildVectorFromScalar(DAG, WidenVT, LdOps, 0, End);
9450
9451 // If the load contains vectors, build the vector using concat vector.
9452 // All of the vectors used to load are power-of-2, and the scalar loads can be
9453 // combined to make a power-of-2 vector.
9454 SmallVector<SDValue, 16> ConcatOps(End);
9455 int i = End - 1;
9456 int Idx = End;
9457 EVT LdTy = LdOps[i].getValueType();
9458 // First, combine the scalar loads to a vector.
9459 if (!LdTy.isVector()) {
9460 for (--i; i >= 0; --i) {
9461 LdTy = LdOps[i].getValueType();
9462 if (LdTy.isVector())
9463 break;
9464 }
9465 ConcatOps[--Idx] = BuildVectorFromScalar(DAG, LdTy, LdOps, i + 1, End);
9466 }
9467
9468 ConcatOps[--Idx] = LdOps[i];
9469 for (--i; i >= 0; --i) {
9470 EVT NewLdTy = LdOps[i].getValueType();
9471 if (NewLdTy != LdTy) {
9472 // Create a larger vector.
9473 TypeSize LdTySize = LdTy.getSizeInBits();
9474 TypeSize NewLdTySize = NewLdTy.getSizeInBits();
9475 assert(NewLdTySize.isScalable() == LdTySize.isScalable() &&
9476 NewLdTySize.isKnownMultipleOf(LdTySize.getKnownMinValue()));
9477 unsigned NumOps =
9478 NewLdTySize.getKnownMinValue() / LdTySize.getKnownMinValue();
9480 unsigned j = 0;
9481 for (; j != End-Idx; ++j)
9482 WidenOps[j] = ConcatOps[Idx+j];
9483 for (; j != NumOps; ++j)
9484 WidenOps[j] = DAG.getPOISON(LdTy);
9485
9486 ConcatOps[End-1] = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewLdTy,
9487 WidenOps);
9488 Idx = End - 1;
9489 LdTy = NewLdTy;
9490 }
9491 ConcatOps[--Idx] = LdOps[i];
9492 }
9493
9494 if (WidenWidth == LdTy.getSizeInBits() * (End - Idx))
9495 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
9496 ArrayRef(&ConcatOps[Idx], End - Idx));
9497
9498 // We need to fill the rest with undefs to build the vector.
9499 unsigned NumOps =
9500 WidenWidth.getKnownMinValue() / LdTy.getSizeInBits().getKnownMinValue();
9502 SDValue UndefVal = DAG.getPOISON(LdTy);
9503 {
9504 unsigned i = 0;
9505 for (; i != End-Idx; ++i)
9506 WidenOps[i] = ConcatOps[Idx+i];
9507 for (; i != NumOps; ++i)
9508 WidenOps[i] = UndefVal;
9509 }
9510 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, WidenOps);
9511}
9512
9513SDValue
9514DAGTypeLegalizer::GenWidenVectorExtLoads(SmallVectorImpl<SDValue> &LdChain,
9515 LoadSDNode *LD,
9516 ISD::LoadExtType ExtType) {
9517 // For extension loads, it may not be more efficient to chop up the vector
9518 // and then extend it. Instead, we unroll the load and build a new vector.
9519 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
9520 EVT LdVT = LD->getMemoryVT();
9521 SDLoc dl(LD);
9522 assert(LdVT.isVector() && WidenVT.isVector());
9523 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
9524
9525 // Load information
9526 SDValue Chain = LD->getChain();
9527 SDValue BasePtr = LD->getBasePtr();
9528 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
9529 MMOMetadata Metadata = LD->getMMOMetadataForSubAccess();
9530
9531 if (LdVT.isScalableVector())
9532 return SDValue();
9533
9534 EVT EltVT = WidenVT.getVectorElementType();
9535 EVT LdEltVT = LdVT.getVectorElementType();
9536 unsigned NumElts = LdVT.getVectorNumElements();
9537
9538 // Load each element and widen.
9539 unsigned WidenNumElts = WidenVT.getVectorNumElements();
9540 SmallVector<SDValue, 16> Ops(WidenNumElts);
9541 unsigned Increment = LdEltVT.getSizeInBits() / 8;
9542 Ops[0] =
9543 DAG.getExtLoad(ExtType, dl, EltVT, Chain, BasePtr, LD->getPointerInfo(),
9544 LdEltVT, LD->getBaseAlign(), MMOFlags, Metadata);
9545 LdChain.push_back(Ops[0].getValue(1));
9546 unsigned i = 0, Offset = Increment;
9547 for (i=1; i < NumElts; ++i, Offset += Increment) {
9548 SDValue NewBasePtr =
9549 DAG.getObjectPtrOffset(dl, BasePtr, TypeSize::getFixed(Offset));
9550 Ops[i] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, NewBasePtr,
9551 LD->getPointerInfo().getWithOffset(Offset), LdEltVT,
9552 LD->getBaseAlign(), MMOFlags, Metadata);
9553 LdChain.push_back(Ops[i].getValue(1));
9554 }
9555
9556 // Fill the rest with undefs.
9557 SDValue UndefVal = DAG.getPOISON(EltVT);
9558 for (; i != WidenNumElts; ++i)
9559 Ops[i] = UndefVal;
9560
9561 return DAG.getBuildVector(WidenVT, dl, Ops);
9562}
9563
9564bool DAGTypeLegalizer::GenWidenVectorStores(SmallVectorImpl<SDValue> &StChain,
9565 StoreSDNode *ST) {
9566 // The strategy assumes that we can efficiently store power-of-two widths.
9567 // The routine chops the vector into the largest vector stores with the same
9568 // element type or scalar stores.
9569 SDValue Chain = ST->getChain();
9570 SDValue BasePtr = ST->getBasePtr();
9571 MachineMemOperand::Flags MMOFlags = ST->getMemOperand()->getFlags();
9572 MMOMetadata Metadata = ST->getMMOMetadataForSubAccess();
9573 SDValue ValOp = GetWidenedVector(ST->getValue());
9574 SDLoc dl(ST);
9575
9576 EVT StVT = ST->getMemoryVT();
9577 TypeSize StWidth = StVT.getSizeInBits();
9578 EVT ValVT = ValOp.getValueType();
9579 TypeSize ValWidth = ValVT.getSizeInBits();
9580 EVT ValEltVT = ValVT.getVectorElementType();
9581 unsigned ValEltWidth = ValEltVT.getFixedSizeInBits();
9582 assert(StVT.getVectorElementType() == ValEltVT);
9583 assert(StVT.isScalableVector() == ValVT.isScalableVector() &&
9584 "Mismatch between store and value types");
9585
9586 int Idx = 0; // current index to store
9587
9588 MachinePointerInfo MPI = ST->getPointerInfo();
9589 uint64_t ScaledOffset = 0;
9590
9591 // A breakdown of how to widen this vector store. Each element of the vector
9592 // is a memory VT combined with the number of times it is to be stored to,
9593 // e,g., v5i32 -> {{v2i32,2},{i32,1}}
9595
9596 while (StWidth.isNonZero()) {
9597 // Find the largest vector type we can store with.
9598 std::optional<EVT> NewVT =
9599 findMemType(DAG, TLI, StWidth.getKnownMinValue(), ValVT);
9600 if (!NewVT)
9601 return false;
9602 MemVTs.push_back({*NewVT, 0});
9603 TypeSize NewVTWidth = NewVT->getSizeInBits();
9604
9605 do {
9606 StWidth -= NewVTWidth;
9607 MemVTs.back().second++;
9608 } while (StWidth.isNonZero() && TypeSize::isKnownGE(StWidth, NewVTWidth));
9609 }
9610
9611 for (const auto &Pair : MemVTs) {
9612 EVT NewVT = Pair.first;
9613 unsigned Count = Pair.second;
9614 TypeSize NewVTWidth = NewVT.getSizeInBits();
9615
9616 if (NewVT.isVector()) {
9617 unsigned NumVTElts = NewVT.getVectorMinNumElements();
9618 do {
9619 Align NewAlign = ScaledOffset == 0
9620 ? ST->getBaseAlign()
9621 : commonAlignment(ST->getAlign(), ScaledOffset);
9622 SDValue EOp = DAG.getExtractSubvector(dl, NewVT, ValOp, Idx);
9623 SDValue PartStore = DAG.getStore(Chain, dl, EOp, BasePtr, MPI, NewAlign,
9624 MMOFlags, Metadata);
9625 StChain.push_back(PartStore);
9626
9627 Idx += NumVTElts;
9628 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr,
9629 &ScaledOffset);
9630 } while (--Count);
9631 } else {
9632 // Cast the vector to the scalar type we can store.
9633 unsigned NumElts = ValWidth.getFixedValue() / NewVTWidth.getFixedValue();
9634 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewVT, NumElts);
9635 SDValue VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, ValOp);
9636 // Readjust index position based on new vector type.
9637 Idx = Idx * ValEltWidth / NewVTWidth.getFixedValue();
9638 do {
9639 SDValue EOp = DAG.getExtractVectorElt(dl, NewVT, VecOp, Idx++);
9640 SDValue PartStore =
9641 DAG.getStore(Chain, dl, EOp, BasePtr, MPI, ST->getBaseAlign(),
9642 MMOFlags, Metadata);
9643 StChain.push_back(PartStore);
9644
9645 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr);
9646 } while (--Count);
9647 // Restore index back to be relative to the original widen element type.
9648 Idx = Idx * NewVTWidth.getFixedValue() / ValEltWidth;
9649 }
9650 }
9651
9652 return true;
9653}
9654
9655/// Modifies a vector input (widen or narrows) to a vector of NVT. The
9656/// input vector must have the same element type as NVT.
9657/// FillWithZeroes specifies that the vector should be widened with zeroes.
9658SDValue DAGTypeLegalizer::ModifyToType(SDValue InOp, EVT NVT,
9659 bool FillWithZeroes) {
9660 // Note that InOp might have been widened so it might already have
9661 // the right width or it might need be narrowed.
9662 EVT InVT = InOp.getValueType();
9664 "input and widen element type must match");
9665 assert(InVT.isScalableVector() == NVT.isScalableVector() &&
9666 "cannot modify scalable vectors in this way");
9667 SDLoc dl(InOp);
9668
9669 // Check if InOp already has the right width.
9670 if (InVT == NVT)
9671 return InOp;
9672
9673 ElementCount InEC = InVT.getVectorElementCount();
9674 ElementCount WidenEC = NVT.getVectorElementCount();
9675 if (WidenEC.hasKnownScalarFactor(InEC)) {
9676 unsigned NumConcat = WidenEC.getKnownScalarFactor(InEC);
9677 SmallVector<SDValue, 16> Ops(NumConcat);
9678 SDValue FillVal =
9679 FillWithZeroes ? DAG.getConstant(0, dl, InVT) : DAG.getPOISON(InVT);
9680 Ops[0] = InOp;
9681 for (unsigned i = 1; i != NumConcat; ++i)
9682 Ops[i] = FillVal;
9683
9684 return DAG.getNode(ISD::CONCAT_VECTORS, dl, NVT, Ops);
9685 }
9686
9687 if (InEC.hasKnownScalarFactor(WidenEC))
9688 return DAG.getExtractSubvector(dl, NVT, InOp, 0);
9689
9690 if (NVT.isScalableVector() && InVT.isScalableVector()) {
9691 // Split the input into the largest equal-sized scalable subvectors.
9692 unsigned InNumElts = InVT.getVectorMinNumElements();
9693 unsigned NewNumElts = NVT.getVectorMinNumElements();
9694 unsigned CommonFactor = std::gcd(InNumElts, NewNumElts);
9695 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), NVT.getVectorElementType(),
9696 ElementCount::getScalable(CommonFactor));
9697
9699 unsigned NumCopiedParts = std::min(InNumElts, NewNumElts) / CommonFactor;
9700 for (unsigned I = 0; I != NumCopiedParts; ++I)
9701 Ops.push_back(
9702 DAG.getExtractSubvector(dl, PartVT, InOp, I * CommonFactor));
9703
9704 unsigned NumResultParts = NewNumElts / CommonFactor;
9705 if (NumResultParts > NumCopiedParts) {
9706 SDValue FillVal = FillWithZeroes ? DAG.getConstant(0, dl, PartVT)
9707 : DAG.getPOISON(PartVT);
9708 Ops.append(NumResultParts - NumCopiedParts, FillVal);
9709 }
9710
9711 return DAG.getNode(ISD::CONCAT_VECTORS, dl, NVT, Ops);
9712 }
9713
9714 assert(!InVT.isScalableVector() && !NVT.isScalableVector() &&
9715 "Scalable vectors should have been handled already.");
9716
9717 unsigned InNumElts = InEC.getFixedValue();
9718 unsigned WidenNumElts = WidenEC.getFixedValue();
9719
9720 // Fall back to extract and build (+ mask, if padding with zeros).
9721 SmallVector<SDValue, 16> Ops(WidenNumElts);
9722 EVT EltVT = NVT.getVectorElementType();
9723 unsigned MinNumElts = std::min(WidenNumElts, InNumElts);
9724 unsigned Idx;
9725 for (Idx = 0; Idx < MinNumElts; ++Idx)
9726 Ops[Idx] = DAG.getExtractVectorElt(dl, EltVT, InOp, Idx);
9727
9728 SDValue UndefVal = DAG.getPOISON(EltVT);
9729 for (; Idx < WidenNumElts; ++Idx)
9730 Ops[Idx] = UndefVal;
9731
9732 SDValue Widened = DAG.getBuildVector(NVT, dl, Ops);
9733 if (!FillWithZeroes)
9734 return Widened;
9735
9736 assert(NVT.isInteger() &&
9737 "We expect to never want to FillWithZeroes for non-integral types.");
9738
9740 MaskOps.append(MinNumElts, DAG.getAllOnesConstant(dl, EltVT));
9741 MaskOps.append(WidenNumElts - MinNumElts, DAG.getConstant(0, dl, EltVT));
9742
9743 return DAG.getNode(ISD::AND, dl, NVT, Widened,
9744 DAG.getBuildVector(NVT, dl, MaskOps));
9745}
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:845
@ 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:733
@ 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:805
@ 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:879
@ 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:906
@ 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....
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
Definition ISDOpcodes.h:765
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
Definition ISDOpcodes.h:936
@ 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:796
@ 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:814
@ PARTIAL_REDUCE_UMLA
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:870
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
Definition ISDOpcodes.h:725
@ 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:675
@ 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:701
@ 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:822
@ 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:682
@ 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:714
@ ATOMIC_LOAD_FMAXIMUM
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:787
@ 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:876
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:837
@ 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:663
@ ANY_EXTEND_VECTOR_INREG
ANY_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register any-extension of the low la...
Definition ISDOpcodes.h:925
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition ISDOpcodes.h:914
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:745
@ 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:831
@ 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:801
@ 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:952
@ 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:757
@ SCMP
[US]CMP - 3-way comparison of signed or unsigned integers.
Definition ISDOpcodes.h:753
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
Definition ISDOpcodes.h:720
@ 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:667
@ 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:813
@ 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:985
@ VECTOR_COMPRESS
VECTOR_COMPRESS(Vec, Mask, Passthru) consecutively place vector elements based on mask e....
Definition ISDOpcodes.h:709
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
Definition ISDOpcodes.h:947
@ 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:971
@ VECREDUCE_FMINIMUM
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:882
@ 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:740
@ ABS_MIN_POISON
ABS with a poison result for INT_MIN.
Definition ISDOpcodes.h:769
@ 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:880
#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.