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);
2148 SDValue StackPtr =
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);
2462 SDValue StackPtr =
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();
2783 SDValue Increment =
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
3799 SDValue StoreV2 =
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);
4492 SDValue StackPtr =
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);
4550 SDValue StackPtr =
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();
4719 SDValue Increment =
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 EVT VT0 = N->getValueType(0);
5413 if (!TLI.isOperationLegalOrCustomOrPromote(N->getOpcode(), WideVecVT) &&
5414 TLI.isOperationExpandOrLibCall(N->getOpcode(), VT0.getScalarType())) {
5415 SDValue Unrolled =
5416 DAG.UnrollVectorOp(N, WideVecVT.getVectorNumElements());
5417 Res = Unrolled.getValue(ResNo);
5418 if (N->getNumValues() > 1)
5419 ReplaceOtherWidenResults(N, Unrolled.getNode(), ResNo);
5420 return true;
5421 }
5422 return false;
5423 };
5424
5425 switch (N->getOpcode()) {
5426 default:
5427#ifndef NDEBUG
5428 dbgs() << "WidenVectorResult #" << ResNo << ": ";
5429 N->dump(&DAG);
5430 dbgs() << "\n";
5431#endif
5432 report_fatal_error("do not know how to widen the result of this operator!");
5433
5436 Res = WidenVecRes_LOOP_DEPENDENCE_MASK(N);
5437 break;
5438 case ISD::MERGE_VALUES: Res = WidenVecRes_MERGE_VALUES(N, ResNo); break;
5439 case ISD::ADDRSPACECAST:
5440 Res = WidenVecRes_ADDRSPACECAST(N);
5441 break;
5442 case ISD::AssertZext: Res = WidenVecRes_AssertZext(N); break;
5443 case ISD::BITCAST: Res = WidenVecRes_BITCAST(N); break;
5444 case ISD::BUILD_VECTOR: Res = WidenVecRes_BUILD_VECTOR(N); break;
5445 case ISD::CONCAT_VECTORS: Res = WidenVecRes_CONCAT_VECTORS(N); break;
5447 Res = WidenVecRes_INSERT_SUBVECTOR(N);
5448 break;
5449 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecRes_EXTRACT_SUBVECTOR(N); break;
5450 case ISD::INSERT_VECTOR_ELT: Res = WidenVecRes_INSERT_VECTOR_ELT(N); break;
5451 case ISD::ATOMIC_LOAD:
5452 Res = WidenVecRes_ATOMIC_LOAD(cast<AtomicSDNode>(N));
5453 break;
5454 case ISD::LOAD: Res = WidenVecRes_LOAD(N); break;
5455 case ISD::STEP_VECTOR:
5456 case ISD::SPLAT_VECTOR:
5458 Res = WidenVecRes_ScalarOp(N);
5459 break;
5460 case ISD::SIGN_EXTEND_INREG: Res = WidenVecRes_InregOp(N); break;
5461 case ISD::VSELECT:
5462 case ISD::SELECT:
5463 case ISD::VP_MERGE:
5464 Res = WidenVecRes_Select(N);
5465 break;
5466 case ISD::SELECT_CC: Res = WidenVecRes_SELECT_CC(N); break;
5467 case ISD::SETCC: Res = WidenVecRes_SETCC(N); break;
5468 case ISD::POISON:
5469 case ISD::UNDEF: Res = WidenVecRes_UNDEF(N); break;
5471 Res = WidenVecRes_VECTOR_SHUFFLE(cast<ShuffleVectorSDNode>(N));
5472 break;
5473 case ISD::VP_LOAD:
5474 Res = WidenVecRes_VP_LOAD(cast<VPLoadSDNode>(N));
5475 break;
5476 case ISD::VP_LOAD_FF:
5477 Res = WidenVecRes_VP_LOAD_FF(cast<VPLoadFFSDNode>(N));
5478 break;
5479 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
5480 Res = WidenVecRes_VP_STRIDED_LOAD(cast<VPStridedLoadSDNode>(N));
5481 break;
5483 Res = WidenVecRes_VECTOR_COMPRESS(N);
5484 break;
5485 case ISD::MLOAD:
5486 Res = WidenVecRes_MLOAD(cast<MaskedLoadSDNode>(N));
5487 break;
5488 case ISD::MGATHER:
5489 Res = WidenVecRes_MGATHER(cast<MaskedGatherSDNode>(N));
5490 break;
5491 case ISD::VP_GATHER:
5492 Res = WidenVecRes_VP_GATHER(cast<VPGatherSDNode>(N));
5493 break;
5495 Res = WidenVecRes_VECTOR_REVERSE(N);
5496 break;
5498 Res = WidenVecRes_GET_ACTIVE_LANE_MASK(N);
5499 break;
5501 WidenVecRes_VECTOR_INTERLEAVE(N);
5502 break;
5503 case ISD::VECTOR_MATCH:
5504 Res = WidenVecRes_VECTOR_MATCH(N);
5505 break;
5507 WidenVecRes_VECTOR_DEINTERLEAVE(N);
5508 break;
5509
5510 case ISD::ADD:
5511 case ISD::AND:
5512 case ISD::MUL:
5513 case ISD::MULHS:
5514 case ISD::MULHU:
5515 case ISD::ABDS:
5516 case ISD::ABDU:
5517 case ISD::OR:
5518 case ISD::SUB:
5519 case ISD::XOR:
5520 case ISD::SHL:
5521 case ISD::SRA:
5522 case ISD::SRL:
5523 case ISD::CLMUL:
5524 case ISD::CLMULR:
5525 case ISD::CLMULH:
5526 case ISD::PEXT:
5527 case ISD::PDEP:
5528 case ISD::FMINNUM:
5529 case ISD::FMINNUM_IEEE:
5530 case ISD::FMAXNUM:
5531 case ISD::FMAXNUM_IEEE:
5532 case ISD::FMINIMUM:
5533 case ISD::FMAXIMUM:
5534 case ISD::FMINIMUMNUM:
5535 case ISD::FMAXIMUMNUM:
5536 case ISD::SMIN:
5537 case ISD::SMAX:
5538 case ISD::UMIN:
5539 case ISD::UMAX:
5540 case ISD::UADDSAT:
5541 case ISD::SADDSAT:
5542 case ISD::USUBSAT:
5543 case ISD::SSUBSAT:
5544 case ISD::SSHLSAT:
5545 case ISD::USHLSAT:
5546 case ISD::ROTL:
5547 case ISD::ROTR:
5548 case ISD::AVGFLOORS:
5549 case ISD::AVGFLOORU:
5550 case ISD::AVGCEILS:
5551 case ISD::AVGCEILU:
5552 case ISD::AVGSUBFLOORS:
5553 case ISD::AVGSUBFLOORU:
5554 // Vector-predicated binary op widening. Note that -- unlike the
5555 // unpredicated versions -- we don't have to worry about trapping on
5556 // operations like UDIV, FADD, etc., as we pass on the original vector
5557 // length parameter. This means the widened elements containing garbage
5558 // aren't active.
5559 case ISD::VP_SDIV:
5560 case ISD::VP_UDIV:
5561 case ISD::VP_SREM:
5562 case ISD::VP_UREM:
5563 Res = WidenVecRes_Binary(N);
5564 break;
5565
5566 case ISD::MASKED_UDIV:
5567 case ISD::MASKED_SDIV:
5568 case ISD::MASKED_UREM:
5569 case ISD::MASKED_SREM:
5570 Res = WidenVecRes_MaskedBinary(N);
5571 break;
5572
5573 case ISD::SCMP:
5574 case ISD::UCMP:
5575 Res = WidenVecRes_CMP(N);
5576 break;
5577
5578 case ISD::FPOW:
5579 case ISD::FATAN2:
5580 case ISD::FREM:
5581 if (unrollExpandedOp())
5582 break;
5583 // If the target has custom/legal support for the scalar FP intrinsic ops
5584 // (they are probably not destined to become libcalls), then widen those
5585 // like any other binary ops.
5586 [[fallthrough]];
5587
5588 case ISD::FADD:
5589 case ISD::FMUL:
5590 case ISD::FSUB:
5591 case ISD::FDIV:
5592 case ISD::SDIV:
5593 case ISD::UDIV:
5594 case ISD::SREM:
5595 case ISD::UREM:
5596 Res = WidenVecRes_BinaryCanTrap(N);
5597 break;
5598
5599 case ISD::SMULFIX:
5600 case ISD::SMULFIXSAT:
5601 case ISD::UMULFIX:
5602 case ISD::UMULFIXSAT:
5603 // These are binary operations, but with an extra operand that shouldn't
5604 // be widened (the scale).
5605 Res = WidenVecRes_BinaryWithExtraScalarOp(N);
5606 break;
5607
5608#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
5609 case ISD::STRICT_##DAGN:
5610#include "llvm/IR/ConstrainedOps.def"
5611 Res = WidenVecRes_StrictFP(N);
5612 break;
5613
5614 case ISD::UADDO:
5615 case ISD::SADDO:
5616 case ISD::USUBO:
5617 case ISD::SSUBO:
5618 case ISD::UMULO:
5619 case ISD::SMULO:
5620 Res = WidenVecRes_OverflowOp(N, ResNo);
5621 break;
5622
5623 case ISD::FCOPYSIGN:
5624 Res = WidenVecRes_FCOPYSIGN(N);
5625 break;
5626
5627 case ISD::IS_FPCLASS:
5628 case ISD::FPTRUNC_ROUND:
5629 Res = WidenVecRes_UnarySameEltsWithScalarArg(N);
5630 break;
5631
5632 case ISD::FLDEXP:
5633 case ISD::FPOWI:
5634 if (!unrollExpandedOp())
5635 Res = WidenVecRes_ExpOp(N);
5636 break;
5637
5641 Res = WidenVecRes_EXTEND_VECTOR_INREG(N);
5642 break;
5643
5644 case ISD::ANY_EXTEND:
5645 case ISD::FP_EXTEND:
5646 case ISD::FP_ROUND:
5647 case ISD::FP_TO_SINT:
5648 case ISD::FP_TO_UINT:
5649 case ISD::SIGN_EXTEND:
5650 case ISD::SINT_TO_FP:
5651 case ISD::TRUNCATE:
5652 case ISD::UINT_TO_FP:
5653 case ISD::ZERO_EXTEND:
5656 Res = WidenVecRes_Convert(N);
5657 break;
5658
5661 Res = WidenVecRes_FP_TO_XINT_SAT(N);
5662 break;
5663
5664 case ISD::LRINT:
5665 case ISD::LLRINT:
5666 case ISD::LROUND:
5667 case ISD::LLROUND:
5668 Res = WidenVecRes_XROUND(N);
5669 break;
5670
5671 case ISD::FACOS:
5672 case ISD::FASIN:
5673 case ISD::FATAN:
5674 case ISD::FCEIL:
5675 case ISD::FCOS:
5676 case ISD::FCOSH:
5677 case ISD::FEXP:
5678 case ISD::FEXP2:
5679 case ISD::FEXP10:
5680 case ISD::FFLOOR:
5681 case ISD::FLOG:
5682 case ISD::FLOG10:
5683 case ISD::FLOG2:
5684 case ISD::FNEARBYINT:
5685 case ISD::FRINT:
5686 case ISD::FROUND:
5687 case ISD::FROUNDEVEN:
5688 case ISD::FSIN:
5689 case ISD::FSINH:
5690 case ISD::FSQRT:
5691 case ISD::FTAN:
5692 case ISD::FTANH:
5693 case ISD::FTRUNC:
5694 if (unrollExpandedOp())
5695 break;
5696 // If the target has custom/legal support for the scalar FP intrinsic ops
5697 // (they are probably not destined to become libcalls), then widen those
5698 // like any other unary ops.
5699 [[fallthrough]];
5700
5701 case ISD::ABS:
5703 case ISD::BITREVERSE:
5704 case ISD::BSWAP:
5705 case ISD::CTLZ:
5707 case ISD::CTPOP:
5708 case ISD::CTTZ:
5710 case ISD::FNEG:
5711 case ISD::FABS:
5712 case ISD::FREEZE:
5713 case ISD::ARITH_FENCE:
5714 case ISD::FCANONICALIZE:
5717 Res = WidenVecRes_Unary(N);
5718 break;
5719 case ISD::FMA:
5720 case ISD::FSHL:
5721 case ISD::FSHR:
5722 Res = WidenVecRes_Ternary(N);
5723 break;
5724 case ISD::FMODF:
5725 case ISD::FFREXP:
5726 case ISD::FSINCOS:
5727 case ISD::FSINCOSPI: {
5728 if (!unrollExpandedOp())
5729 Res = WidenVecRes_UnaryOpWithTwoResults(N, ResNo);
5730 break;
5731 }
5736 Res = WidenVecRes_PARTIAL_REDUCE_MLA(N);
5737 break;
5738 }
5739
5740 // If Res is null, the sub-method took care of registering the result.
5741 if (Res.getNode())
5742 SetWidenedVector(SDValue(N, ResNo), Res);
5743}
5744
5745SDValue DAGTypeLegalizer::WidenVecRes_Ternary(SDNode *N) {
5746 // Ternary op widening.
5747 SDLoc dl(N);
5748 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5749 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5750 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5751 SDValue InOp3 = GetWidenedVector(N->getOperand(2));
5752 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3);
5753}
5754
5755SDValue DAGTypeLegalizer::WidenVecRes_Binary(SDNode *N) {
5756 // Binary op widening.
5757 SDLoc dl(N);
5758 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5759 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5760 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5761 if (N->getNumOperands() == 2)
5762 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2,
5763 N->getFlags());
5764
5765 assert(N->getNumOperands() == 4 && "Unexpected number of operands!");
5766 assert((N->getOpcode() == ISD::VP_UDIV || N->getOpcode() == ISD::VP_SDIV ||
5767 N->getOpcode() == ISD::VP_UREM || N->getOpcode() == ISD::VP_SREM) &&
5768 "Expected VP opcode");
5769
5770 SDValue Mask =
5771 GetWidenedMask(N->getOperand(2), WidenVT.getVectorElementCount());
5772 return DAG.getNode(N->getOpcode(), dl, WidenVT,
5773 {InOp1, InOp2, Mask, N->getOperand(3)}, N->getFlags());
5774}
5775
5776SDValue DAGTypeLegalizer::WidenVecRes_MaskedBinary(SDNode *N) {
5777 SDLoc dl(N);
5778 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5779 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5780 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5781 SDValue Mask = N->getOperand(2);
5782 EVT WideMaskVT = WidenVT.changeVectorElementType(
5783 *DAG.getContext(), Mask.getValueType().getVectorElementType());
5784 Mask = ModifyToType(Mask, WideMaskVT, /*FillWithZeros=*/true);
5785 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, Mask,
5786 N->getFlags());
5787}
5788
5789SDValue DAGTypeLegalizer::WidenVecRes_CMP(SDNode *N) {
5790 LLVMContext &Ctxt = *DAG.getContext();
5791 SDLoc dl(N);
5792
5793 SDValue LHS = N->getOperand(0);
5794 SDValue RHS = N->getOperand(1);
5795 EVT OpVT = LHS.getValueType();
5796 if (getTypeAction(OpVT) == TargetLowering::TypeWidenVector) {
5797 LHS = GetWidenedVector(LHS);
5798 RHS = GetWidenedVector(RHS);
5799 OpVT = LHS.getValueType();
5800 }
5801
5802 EVT WidenResVT = TLI.getTypeToTransformTo(Ctxt, N->getValueType(0));
5803 ElementCount WidenResEC = WidenResVT.getVectorElementCount();
5804 if (WidenResEC == OpVT.getVectorElementCount()) {
5805 return DAG.getNode(N->getOpcode(), dl, WidenResVT, LHS, RHS);
5806 }
5807
5808 return DAG.UnrollVectorOp(N, WidenResVT.getVectorNumElements());
5809}
5810
5811SDValue DAGTypeLegalizer::WidenVecRes_BinaryWithExtraScalarOp(SDNode *N) {
5812 // Binary op widening, but with an extra operand that shouldn't be widened.
5813 SDLoc dl(N);
5814 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5815 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5816 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5817 SDValue InOp3 = N->getOperand(2);
5818 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3,
5819 N->getFlags());
5820}
5821
5822// Given a vector of operations that have been broken up to widen, see
5823// if we can collect them together into the next widest legal VT. This
5824// implementation is trap-safe.
5826 SmallVectorImpl<SDValue> &ConcatOps,
5827 unsigned ConcatEnd, EVT VT, EVT MaxVT,
5828 EVT WidenVT) {
5829 // Check to see if we have a single operation with the widen type.
5830 if (ConcatEnd == 1) {
5831 VT = ConcatOps[0].getValueType();
5832 if (VT == WidenVT)
5833 return ConcatOps[0];
5834 }
5835
5836 SDLoc dl(ConcatOps[0]);
5837 EVT WidenEltVT = WidenVT.getVectorElementType();
5838
5839 // while (Some element of ConcatOps is not of type MaxVT) {
5840 // From the end of ConcatOps, collect elements of the same type and put
5841 // them into an op of the next larger supported type
5842 // }
5843 while (ConcatOps[ConcatEnd-1].getValueType() != MaxVT) {
5844 int Idx = ConcatEnd - 1;
5845 VT = ConcatOps[Idx--].getValueType();
5846 while (Idx >= 0 && ConcatOps[Idx].getValueType() == VT)
5847 Idx--;
5848
5849 int NextSize = VT.isVector() ? VT.getVectorNumElements() : 1;
5850 EVT NextVT;
5851 do {
5852 NextSize *= 2;
5853 NextVT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NextSize);
5854 } while (!TLI.isTypeLegal(NextVT));
5855
5856 if (!VT.isVector()) {
5857 // Scalar type, create an INSERT_VECTOR_ELEMENT of type NextVT
5858 SDValue VecOp = DAG.getPOISON(NextVT);
5859 unsigned NumToInsert = ConcatEnd - Idx - 1;
5860 for (unsigned i = 0, OpIdx = Idx + 1; i < NumToInsert; i++, OpIdx++)
5861 VecOp = DAG.getInsertVectorElt(dl, VecOp, ConcatOps[OpIdx], i);
5862 ConcatOps[Idx+1] = VecOp;
5863 ConcatEnd = Idx + 2;
5864 } else {
5865 // Vector type, create a CONCAT_VECTORS of type NextVT
5866 SDValue undefVec = DAG.getPOISON(VT);
5867 unsigned OpsToConcat = NextSize/VT.getVectorNumElements();
5868 SmallVector<SDValue, 16> SubConcatOps(OpsToConcat);
5869 unsigned RealVals = ConcatEnd - Idx - 1;
5870 unsigned SubConcatEnd = 0;
5871 unsigned SubConcatIdx = Idx + 1;
5872 while (SubConcatEnd < RealVals)
5873 SubConcatOps[SubConcatEnd++] = ConcatOps[++Idx];
5874 while (SubConcatEnd < OpsToConcat)
5875 SubConcatOps[SubConcatEnd++] = undefVec;
5876 ConcatOps[SubConcatIdx] = DAG.getNode(ISD::CONCAT_VECTORS, dl,
5877 NextVT, SubConcatOps);
5878 ConcatEnd = SubConcatIdx + 1;
5879 }
5880 }
5881
5882 // Check to see if we have a single operation with the widen type.
5883 if (ConcatEnd == 1) {
5884 VT = ConcatOps[0].getValueType();
5885 if (VT == WidenVT)
5886 return ConcatOps[0];
5887 }
5888
5889 // add undefs of size MaxVT until ConcatOps grows to length of WidenVT
5890 unsigned NumOps = WidenVT.getVectorNumElements()/MaxVT.getVectorNumElements();
5891 if (NumOps != ConcatEnd ) {
5892 SDValue UndefVal = DAG.getPOISON(MaxVT);
5893 for (unsigned j = ConcatEnd; j < NumOps; ++j)
5894 ConcatOps[j] = UndefVal;
5895 }
5896 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
5897 ArrayRef(ConcatOps.data(), NumOps));
5898}
5899
5900SDValue DAGTypeLegalizer::WidenVecRes_BinaryCanTrap(SDNode *N) {
5901 // Binary op widening for operations that can trap.
5902 unsigned Opcode = N->getOpcode();
5903 SDLoc dl(N);
5904 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5905 EVT WidenEltVT = WidenVT.getVectorElementType();
5906 EVT VT = WidenVT;
5907 unsigned NumElts = VT.getVectorMinNumElements();
5908 const SDNodeFlags Flags = N->getFlags();
5909 while (!TLI.isTypeLegal(VT) && NumElts != 1) {
5910 NumElts = NumElts / 2;
5911 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5912 }
5913
5914 if (NumElts != 1 && !TLI.canOpTrap(N->getOpcode(), VT)) {
5915 // Operation doesn't trap so just widen as normal.
5916 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5917 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5918 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, Flags);
5919 }
5920
5921 // Generate a vp.op if it is custom/legal for the target. This avoids need
5922 // to split and tile the subvectors (below), because the inactive lanes can
5923 // simply be disabled. To avoid possible recursion, only do this if the
5924 // widened mask type is legal.
5925 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opcode);
5926 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WidenVT)) {
5927 if (EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
5928 WidenVT.getVectorElementCount());
5929 TLI.isTypeLegal(WideMaskVT)) {
5930 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5931 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5932 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
5933 SDValue EVL =
5934 DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
5935 N->getValueType(0).getVectorElementCount());
5936 return DAG.getNode(*VPOpcode, dl, WidenVT, InOp1, InOp2, Mask, EVL,
5937 Flags);
5938 }
5939 }
5940
5941 // FIXME: Improve support for scalable vectors.
5942 assert(!VT.isScalableVector() && "Scalable vectors not handled yet.");
5943
5944 // No legal vector version so unroll the vector operation and then widen.
5945 if (NumElts == 1)
5946 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
5947
5948 // Since the operation can trap, apply operation on the original vector.
5949 EVT MaxVT = VT;
5950 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5951 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5952 unsigned CurNumElts = N->getValueType(0).getVectorNumElements();
5953
5954 SmallVector<SDValue, 16> ConcatOps(CurNumElts);
5955 unsigned ConcatEnd = 0; // Current ConcatOps index.
5956 int Idx = 0; // Current Idx into input vectors.
5957
5958 // NumElts := greatest legal vector size (at most WidenVT)
5959 // while (orig. vector has unhandled elements) {
5960 // take munches of size NumElts from the beginning and add to ConcatOps
5961 // NumElts := next smaller supported vector size or 1
5962 // }
5963 while (CurNumElts != 0) {
5964 while (CurNumElts >= NumElts) {
5965 SDValue EOp1 = DAG.getExtractSubvector(dl, VT, InOp1, Idx);
5966 SDValue EOp2 = DAG.getExtractSubvector(dl, VT, InOp2, Idx);
5967 ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, VT, EOp1, EOp2, Flags);
5968 Idx += NumElts;
5969 CurNumElts -= NumElts;
5970 }
5971 do {
5972 NumElts = NumElts / 2;
5973 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5974 } while (!TLI.isTypeLegal(VT) && NumElts != 1);
5975
5976 if (NumElts == 1) {
5977 for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
5978 SDValue EOp1 = DAG.getExtractVectorElt(dl, WidenEltVT, InOp1, Idx);
5979 SDValue EOp2 = DAG.getExtractVectorElt(dl, WidenEltVT, InOp2, Idx);
5980 ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, WidenEltVT,
5981 EOp1, EOp2, Flags);
5982 }
5983 CurNumElts = 0;
5984 }
5985 }
5986
5987 return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
5988}
5989
5990SDValue DAGTypeLegalizer::WidenVecRes_StrictFP(SDNode *N) {
5991 switch (N->getOpcode()) {
5992 case ISD::STRICT_FSETCC:
5994 return WidenVecRes_STRICT_FSETCC(N);
6001 return WidenVecRes_Convert_StrictFP(N);
6002 default:
6003 break;
6004 }
6005
6006 // StrictFP op widening for operations that can trap.
6007 unsigned NumOpers = N->getNumOperands();
6008 unsigned Opcode = N->getOpcode();
6009 SDLoc dl(N);
6010 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6011 EVT WidenEltVT = WidenVT.getVectorElementType();
6012 EVT VT = WidenVT;
6013 unsigned NumElts = VT.getVectorNumElements();
6014 while (!TLI.isTypeLegal(VT) && NumElts != 1) {
6015 NumElts = NumElts / 2;
6016 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
6017 }
6018
6019 // No legal vector version so unroll the vector operation and then widen.
6020 if (NumElts == 1)
6021 return UnrollVectorOp_StrictFP(N, WidenVT.getVectorNumElements());
6022
6023 // Since the operation can trap, apply operation on the original vector.
6024 EVT MaxVT = VT;
6026 unsigned CurNumElts = N->getValueType(0).getVectorNumElements();
6027
6028 SmallVector<SDValue, 16> ConcatOps(CurNumElts);
6030 unsigned ConcatEnd = 0; // Current ConcatOps index.
6031 int Idx = 0; // Current Idx into input vectors.
6032
6033 // The Chain is the first operand.
6034 InOps.push_back(N->getOperand(0));
6035
6036 // Now process the remaining operands.
6037 for (unsigned i = 1; i < NumOpers; ++i) {
6038 SDValue Oper = N->getOperand(i);
6039
6040 EVT OpVT = Oper.getValueType();
6041 if (OpVT.isVector()) {
6042 if (getTypeAction(OpVT) == TargetLowering::TypeWidenVector)
6043 Oper = GetWidenedVector(Oper);
6044 else {
6045 EVT WideOpVT =
6046 EVT::getVectorVT(*DAG.getContext(), OpVT.getVectorElementType(),
6047 WidenVT.getVectorElementCount());
6048 Oper = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WideOpVT,
6049 DAG.getPOISON(WideOpVT), Oper,
6050 DAG.getVectorIdxConstant(0, dl));
6051 }
6052 }
6053
6054 InOps.push_back(Oper);
6055 }
6056
6057 // NumElts := greatest legal vector size (at most WidenVT)
6058 // while (orig. vector has unhandled elements) {
6059 // take munches of size NumElts from the beginning and add to ConcatOps
6060 // NumElts := next smaller supported vector size or 1
6061 // }
6062 while (CurNumElts != 0) {
6063 while (CurNumElts >= NumElts) {
6065
6066 for (unsigned i = 0; i < NumOpers; ++i) {
6067 SDValue Op = InOps[i];
6068
6069 EVT OpVT = Op.getValueType();
6070 if (OpVT.isVector()) {
6071 EVT OpExtractVT =
6072 EVT::getVectorVT(*DAG.getContext(), OpVT.getVectorElementType(),
6074 Op = DAG.getExtractSubvector(dl, OpExtractVT, Op, Idx);
6075 }
6076
6077 EOps.push_back(Op);
6078 }
6079
6080 EVT OperVT[] = {VT, MVT::Other};
6081 SDValue Oper = DAG.getNode(Opcode, dl, OperVT, EOps);
6082 ConcatOps[ConcatEnd++] = Oper;
6083 Chains.push_back(Oper.getValue(1));
6084 Idx += NumElts;
6085 CurNumElts -= NumElts;
6086 }
6087 do {
6088 NumElts = NumElts / 2;
6089 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
6090 } while (!TLI.isTypeLegal(VT) && NumElts != 1);
6091
6092 if (NumElts == 1) {
6093 for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
6095
6096 for (unsigned i = 0; i < NumOpers; ++i) {
6097 SDValue Op = InOps[i];
6098
6099 EVT OpVT = Op.getValueType();
6100 if (OpVT.isVector())
6101 Op = DAG.getExtractVectorElt(dl, OpVT.getVectorElementType(), Op,
6102 Idx);
6103
6104 EOps.push_back(Op);
6105 }
6106
6107 EVT WidenVT[] = {WidenEltVT, MVT::Other};
6108 SDValue Oper = DAG.getNode(Opcode, dl, WidenVT, EOps);
6109 ConcatOps[ConcatEnd++] = Oper;
6110 Chains.push_back(Oper.getValue(1));
6111 }
6112 CurNumElts = 0;
6113 }
6114 }
6115
6116 // Build a factor node to remember all the Ops that have been created.
6117 SDValue NewChain;
6118 if (Chains.size() == 1)
6119 NewChain = Chains[0];
6120 else
6121 NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
6122 ReplaceValueWith(SDValue(N, 1), NewChain);
6123
6124 return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
6125}
6126
6127SDValue DAGTypeLegalizer::WidenVecRes_OverflowOp(SDNode *N, unsigned ResNo) {
6128 SDLoc DL(N);
6129 EVT ResVT = N->getValueType(0);
6130 EVT OvVT = N->getValueType(1);
6131 EVT WideResVT, WideOvVT;
6132 SDValue WideLHS, WideRHS;
6133
6134 // TODO: This might result in a widen/split loop.
6135 if (ResNo == 0) {
6136 WideResVT = TLI.getTypeToTransformTo(*DAG.getContext(), ResVT);
6137 WideOvVT = EVT::getVectorVT(
6138 *DAG.getContext(), OvVT.getVectorElementType(),
6139 WideResVT.getVectorNumElements());
6140
6141 WideLHS = GetWidenedVector(N->getOperand(0));
6142 WideRHS = GetWidenedVector(N->getOperand(1));
6143 } else {
6144 WideOvVT = TLI.getTypeToTransformTo(*DAG.getContext(), OvVT);
6145 WideResVT = EVT::getVectorVT(
6146 *DAG.getContext(), ResVT.getVectorElementType(),
6147 WideOvVT.getVectorNumElements());
6148
6149 SDValue Zero = DAG.getVectorIdxConstant(0, DL);
6150 SDValue Poison = DAG.getPOISON(WideResVT);
6151
6152 WideLHS = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideResVT, Poison,
6153 N->getOperand(0), Zero);
6154 WideRHS = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideResVT, Poison,
6155 N->getOperand(1), Zero);
6156 }
6157
6158 SDVTList WideVTs = DAG.getVTList(WideResVT, WideOvVT);
6159 SDNode *WideNode = DAG.getNode(
6160 N->getOpcode(), DL, WideVTs, WideLHS, WideRHS).getNode();
6161
6162 // Replace the other vector result not being explicitly widened here.
6163 unsigned OtherNo = 1 - ResNo;
6164 EVT OtherVT = N->getValueType(OtherNo);
6165 if (getTypeAction(OtherVT) == TargetLowering::TypeWidenVector) {
6166 SetWidenedVector(SDValue(N, OtherNo), SDValue(WideNode, OtherNo));
6167 } else {
6168 SDValue Zero = DAG.getVectorIdxConstant(0, DL);
6169 SDValue OtherVal = DAG.getNode(
6170 ISD::EXTRACT_SUBVECTOR, DL, OtherVT, SDValue(WideNode, OtherNo), Zero);
6171 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
6172 }
6173
6174 return SDValue(WideNode, ResNo);
6175}
6176
6177SDValue DAGTypeLegalizer::WidenVecRes_Convert(SDNode *N) {
6178 LLVMContext &Ctx = *DAG.getContext();
6179 SDValue InOp = N->getOperand(0);
6180 SDLoc DL(N);
6181
6182 EVT WidenVT = TLI.getTypeToTransformTo(Ctx, N->getValueType(0));
6183 ElementCount WidenEC = WidenVT.getVectorElementCount();
6184
6185 EVT InVT = InOp.getValueType();
6186
6187 unsigned Opcode = N->getOpcode();
6188 const SDNodeFlags Flags = N->getFlags();
6189
6190 // Handle the case of ZERO_EXTEND where the promoted InVT element size does
6191 // not equal that of WidenVT.
6192 if (N->getOpcode() == ISD::ZERO_EXTEND &&
6193 getTypeAction(InVT) == TargetLowering::TypePromoteInteger &&
6194 TLI.getTypeToTransformTo(Ctx, InVT).getScalarSizeInBits() !=
6195 WidenVT.getScalarSizeInBits()) {
6196 InOp = ZExtPromotedInteger(InOp);
6197 InVT = InOp.getValueType();
6198 if (WidenVT.getScalarSizeInBits() < InVT.getScalarSizeInBits())
6199 Opcode = ISD::TRUNCATE;
6200 }
6201
6202 EVT InEltVT = InVT.getVectorElementType();
6203 EVT InWidenVT = EVT::getVectorVT(Ctx, InEltVT, WidenEC);
6204 ElementCount InVTEC = InVT.getVectorElementCount();
6205
6206 // Helper to build node with all scalar trailing operands.
6207 auto MakeConvertNode = [&](EVT VT, SDValue Op) -> SDValue {
6208 if (N->getNumOperands() == 1)
6209 return DAG.getNode(Opcode, DL, VT, Op, Flags);
6210 if (Opcode == ISD::CONVERT_TO_ARBITRARY_FP)
6211 return DAG.getNode(Opcode, DL, VT, Op, N->getOperand(1), N->getOperand(2),
6212 N->getOperand(3), Flags);
6213 return DAG.getNode(Opcode, DL, VT, Op, N->getOperand(1), Flags);
6214 };
6215
6216 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
6217 InOp = GetWidenedVector(N->getOperand(0));
6218 InVT = InOp.getValueType();
6219 InVTEC = InVT.getVectorElementCount();
6220 if (InVTEC == WidenEC)
6221 return MakeConvertNode(WidenVT, InOp);
6222 if (WidenVT.getSizeInBits() == InVT.getSizeInBits()) {
6223 // If both input and result vector types are of same width, extend
6224 // operations should be done with SIGN/ZERO_EXTEND_VECTOR_INREG, which
6225 // accepts fewer elements in the result than in the input.
6226 if (Opcode == ISD::ANY_EXTEND)
6227 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
6228 if (Opcode == ISD::SIGN_EXTEND)
6229 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
6230 if (Opcode == ISD::ZERO_EXTEND)
6231 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
6232 }
6233
6234 // For TRUNCATE, try to widen using the legal EC of the input type instead
6235 // if the legalisation action for that intermediate type is not widening.
6236 // E.g. for trunc nxv1i64 -> nxv1i8 where
6237 // - nxv1i64 input gets widened to nxv2i64
6238 // - nxv1i8 output gets widened to nxv16i8
6239 // Then one can try widening the result to nxv2i8 (instead of going all the
6240 // way to nxv16i8) if this later allows type promotion.
6241 EVT MidResVT =
6242 EVT::getVectorVT(Ctx, WidenVT.getVectorElementType(), InVTEC);
6243 if (N->getOpcode() == ISD::TRUNCATE &&
6244 getTypeAction(MidResVT) == TargetLowering::TypePromoteInteger) {
6245 SDValue MidRes = DAG.getNode(ISD::TRUNCATE, DL, MidResVT, InOp, Flags);
6246 return DAG.getInsertSubvector(DL, DAG.getPOISON(WidenVT), MidRes, 0);
6247 }
6248 }
6249
6250 if (TLI.isTypeLegal(InWidenVT)) {
6251 // Because the result and the input are different vector types, widening
6252 // the result could create a legal type but widening the input might make
6253 // it an illegal type that might lead to repeatedly splitting the input
6254 // and then widening it. To avoid this, we widen the input only if
6255 // it results in a legal type.
6256 if (WidenEC.isKnownMultipleOf(InVTEC.getKnownMinValue())) {
6257 // Widen the input and call convert on the widened input vector.
6258 unsigned NumConcat =
6259 WidenEC.getKnownMinValue() / InVTEC.getKnownMinValue();
6260 SmallVector<SDValue, 16> Ops(NumConcat, DAG.getPOISON(InVT));
6261 Ops[0] = InOp;
6262 SDValue InVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InWidenVT, Ops);
6263 return MakeConvertNode(WidenVT, InVec);
6264 }
6265
6266 if (InVTEC.isKnownMultipleOf(WidenEC.getKnownMinValue())) {
6267 SDValue InVal = DAG.getExtractSubvector(DL, InWidenVT, InOp, 0);
6268 // Extract the input and convert the shorten input vector.
6269 return MakeConvertNode(WidenVT, InVal);
6270 }
6271 }
6272
6273 // Otherwise unroll into some nasty scalar code and rebuild the vector.
6274 EVT EltVT = WidenVT.getVectorElementType();
6275 SmallVector<SDValue, 16> Ops(WidenEC.getFixedValue(), DAG.getPOISON(EltVT));
6276 // Use the original element count so we don't do more scalar opts than
6277 // necessary.
6278 unsigned MinElts = N->getValueType(0).getVectorNumElements();
6279 for (unsigned i=0; i < MinElts; ++i) {
6280 SDValue Val = DAG.getExtractVectorElt(DL, InEltVT, InOp, i);
6281 Ops[i] = MakeConvertNode(EltVT, Val);
6282 }
6283
6284 return DAG.getBuildVector(WidenVT, DL, Ops);
6285}
6286
6287SDValue DAGTypeLegalizer::WidenVecRes_FP_TO_XINT_SAT(SDNode *N) {
6288 SDLoc dl(N);
6289 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6290 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
6291
6292 SDValue Src = N->getOperand(0);
6293 EVT SrcVT = Src.getValueType();
6294
6295 // Also widen the input.
6296 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
6297 Src = GetWidenedVector(Src);
6298 SrcVT = Src.getValueType();
6299 }
6300
6301 // Input and output not widened to the same size, give up.
6302 if (WidenNumElts != SrcVT.getVectorElementCount())
6303 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
6304
6305 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src, N->getOperand(1));
6306}
6307
6308SDValue DAGTypeLegalizer::WidenVecRes_XROUND(SDNode *N) {
6309 SDLoc dl(N);
6310 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6311 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
6312
6313 SDValue Src = N->getOperand(0);
6314 EVT SrcVT = Src.getValueType();
6315
6316 // Also widen the input.
6317 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
6318 Src = GetWidenedVector(Src);
6319 SrcVT = Src.getValueType();
6320 }
6321
6322 // Input and output not widened to the same size, give up.
6323 if (WidenNumElts != SrcVT.getVectorElementCount())
6324 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
6325
6326 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src);
6327}
6328
6329SDValue DAGTypeLegalizer::WidenVecRes_Convert_StrictFP(SDNode *N) {
6330 SDValue InOp = N->getOperand(1);
6331 SDLoc DL(N);
6332 SmallVector<SDValue, 4> NewOps(N->ops());
6333
6334 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6335 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6336
6337 EVT InVT = InOp.getValueType();
6338 EVT InEltVT = InVT.getVectorElementType();
6339
6340 unsigned Opcode = N->getOpcode();
6341
6342 // FIXME: Optimizations need to be implemented here.
6343
6344 // Otherwise unroll into some nasty scalar code and rebuild the vector.
6345 EVT EltVT = WidenVT.getVectorElementType();
6346 std::array<EVT, 2> EltVTs = {{EltVT, MVT::Other}};
6347 SmallVector<SDValue, 16> Ops(WidenNumElts, DAG.getPOISON(EltVT));
6348 SmallVector<SDValue, 32> OpChains;
6349 // Use the original element count so we don't do more scalar opts than
6350 // necessary.
6351 unsigned MinElts = N->getValueType(0).getVectorNumElements();
6352 for (unsigned i=0; i < MinElts; ++i) {
6353 NewOps[1] = DAG.getExtractVectorElt(DL, InEltVT, InOp, i);
6354 Ops[i] = DAG.getNode(Opcode, DL, EltVTs, NewOps);
6355 OpChains.push_back(Ops[i].getValue(1));
6356 }
6357 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OpChains);
6358 ReplaceValueWith(SDValue(N, 1), NewChain);
6359
6360 return DAG.getBuildVector(WidenVT, DL, Ops);
6361}
6362
6363SDValue DAGTypeLegalizer::WidenVecRes_EXTEND_VECTOR_INREG(SDNode *N) {
6364 unsigned Opcode = N->getOpcode();
6365 SDValue InOp = N->getOperand(0);
6366 SDLoc DL(N);
6367
6368 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6369 EVT WidenSVT = WidenVT.getVectorElementType();
6370 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6371
6372 EVT InVT = InOp.getValueType();
6373 EVT InSVT = InVT.getVectorElementType();
6374 unsigned InVTNumElts = InVT.getVectorNumElements();
6375
6376 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
6377 InOp = GetWidenedVector(InOp);
6378 InVT = InOp.getValueType();
6379 if (InVT.getSizeInBits() == WidenVT.getSizeInBits()) {
6380 switch (Opcode) {
6384 return DAG.getNode(Opcode, DL, WidenVT, InOp);
6385 }
6386 }
6387 }
6388
6389 // Unroll, extend the scalars and rebuild the vector.
6391 for (unsigned i = 0, e = std::min(InVTNumElts, WidenNumElts); i != e; ++i) {
6392 SDValue Val = DAG.getExtractVectorElt(DL, InSVT, InOp, i);
6393 switch (Opcode) {
6395 Val = DAG.getNode(ISD::ANY_EXTEND, DL, WidenSVT, Val);
6396 break;
6398 Val = DAG.getNode(ISD::SIGN_EXTEND, DL, WidenSVT, Val);
6399 break;
6401 Val = DAG.getNode(ISD::ZERO_EXTEND, DL, WidenSVT, Val);
6402 break;
6403 default:
6404 llvm_unreachable("A *_EXTEND_VECTOR_INREG node was expected");
6405 }
6406 Ops.push_back(Val);
6407 }
6408
6409 while (Ops.size() != WidenNumElts)
6410 Ops.push_back(DAG.getPOISON(WidenSVT));
6411
6412 return DAG.getBuildVector(WidenVT, DL, Ops);
6413}
6414
6415SDValue DAGTypeLegalizer::WidenVecRes_FCOPYSIGN(SDNode *N) {
6416 // If this is an FCOPYSIGN with same input types, we can treat it as a
6417 // normal (can trap) binary op.
6418 if (N->getOperand(0).getValueType() == N->getOperand(1).getValueType())
6419 return WidenVecRes_BinaryCanTrap(N);
6420
6421 // If the types are different, fall back to unrolling.
6422 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6423 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
6424}
6425
6426/// Result and first source operand are different scalar types, but must have
6427/// the same number of elements. There is an additional control argument which
6428/// should be passed through unchanged.
6429SDValue DAGTypeLegalizer::WidenVecRes_UnarySameEltsWithScalarArg(SDNode *N) {
6430 SDValue FpValue = N->getOperand(0);
6431 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6432 if (getTypeAction(FpValue.getValueType()) != TargetLowering::TypeWidenVector)
6433 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
6434 SDValue Arg = GetWidenedVector(FpValue);
6435 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, {Arg, N->getOperand(1)},
6436 N->getFlags());
6437}
6438
6439SDValue DAGTypeLegalizer::WidenVecRes_ExpOp(SDNode *N) {
6440 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6441 SDValue InOp = GetWidenedVector(N->getOperand(0));
6442 SDValue RHS = N->getOperand(1);
6443 EVT ExpVT = RHS.getValueType();
6444 SDValue ExpOp = RHS;
6445 if (ExpVT.isVector()) {
6446 EVT WideExpVT = WidenVT.changeVectorElementType(
6447 *DAG.getContext(), ExpVT.getVectorElementType());
6448 ExpOp = ModifyToType(RHS, WideExpVT);
6449 }
6450
6451 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, ExpOp);
6452}
6453
6454SDValue DAGTypeLegalizer::WidenVecRes_Unary(SDNode *N) {
6455 // Unary op widening.
6456 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6457 SDValue InOp = GetWidenedVector(N->getOperand(0));
6458 if (N->getNumOperands() == 1)
6459 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, N->getFlags());
6460 assert(N->getOpcode() == ISD::AssertNoFPClass && "unexpected opcode");
6461 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, N->getOperand(1),
6462 N->getFlags());
6463}
6464
6465SDValue DAGTypeLegalizer::WidenVecRes_InregOp(SDNode *N) {
6466 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6467 EVT ExtVT = EVT::getVectorVT(
6468 *DAG.getContext(),
6469 cast<VTSDNode>(N->getOperand(1))->getVT().getVectorElementType(),
6470 WidenVT.getVectorElementCount());
6471 SDValue WidenLHS = GetWidenedVector(N->getOperand(0));
6472 return DAG.getNode(N->getOpcode(), SDLoc(N),
6473 WidenVT, WidenLHS, DAG.getValueType(ExtVT));
6474}
6475
6476SDValue DAGTypeLegalizer::WidenVecRes_UnaryOpWithTwoResults(SDNode *N,
6477 unsigned ResNo) {
6478 EVT VT0 = N->getValueType(0);
6479 EVT VT1 = N->getValueType(1);
6480
6481 assert(VT0.isVector() && VT1.isVector() &&
6483 "expected both results to be vectors of matching element count");
6484
6485 LLVMContext &Ctx = *DAG.getContext();
6486 SDValue InOp = GetWidenedVector(N->getOperand(0));
6487
6488 EVT WidenVT = TLI.getTypeToTransformTo(Ctx, N->getValueType(ResNo));
6489 ElementCount WidenEC = WidenVT.getVectorElementCount();
6490
6491 EVT WidenVT0 = EVT::getVectorVT(Ctx, VT0.getVectorElementType(), WidenEC);
6492 EVT WidenVT1 = EVT::getVectorVT(Ctx, VT1.getVectorElementType(), WidenEC);
6493
6494 SDNode *WidenNode =
6495 DAG.getNode(N->getOpcode(), SDLoc(N), {WidenVT0, WidenVT1}, InOp)
6496 .getNode();
6497
6498 ReplaceOtherWidenResults(N, WidenNode, ResNo);
6499 return SDValue(WidenNode, ResNo);
6500}
6501
6502SDValue DAGTypeLegalizer::WidenVecRes_MERGE_VALUES(SDNode *N, unsigned ResNo) {
6503 SDValue WidenVec = DisintegrateMERGE_VALUES(N, ResNo);
6504 return GetWidenedVector(WidenVec);
6505}
6506
6507SDValue DAGTypeLegalizer::WidenVecRes_ADDRSPACECAST(SDNode *N) {
6508 SDLoc DL(N);
6509 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6510 ElementCount WidenEC = WidenVT.getVectorElementCount();
6511 auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
6512
6513 // The source has the same number of elements as the result, so widen it to
6514 // match WidenVT. It only lives in the widened-vector map if it is itself
6515 // widened; otherwise pad it up to the widened element count
6516 // when it is illegal.
6517 SDValue InOp = N->getOperand(0);
6518 EVT InVT = InOp.getValueType();
6519 TargetLowering::LegalizeTypeAction InAction = getTypeAction(InVT);
6520 if (InAction == TargetLowering::TypeWidenVector) {
6521 InOp = GetWidenedVector(InOp);
6522 } else if (InAction != TargetLowering::TypeLegal) {
6523 EVT InWidenVT = EVT::getVectorVT(*DAG.getContext(),
6524 InVT.getVectorElementType(), WidenEC);
6525 InOp = DAG.getInsertSubvector(DL, DAG.getPOISON(InWidenVT), InOp, 0);
6526 }
6527
6528 return DAG.getAddrSpaceCast(
6529 DL, WidenVT, InOp, AddrSpaceCastN->getSrcAddressSpace(),
6530 AddrSpaceCastN->getDestAddressSpace(), AddrSpaceCastN->getFlags());
6531}
6532
6533SDValue DAGTypeLegalizer::WidenVecRes_BITCAST(SDNode *N) {
6534 SDValue InOp = N->getOperand(0);
6535 EVT InVT = InOp.getValueType();
6536 EVT VT = N->getValueType(0);
6537 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6538 SDLoc dl(N);
6539
6540 switch (getTypeAction(InVT)) {
6542 break;
6544 report_fatal_error("scalarization of scalable vectors is not supported");
6546 // If the incoming type is a vector that is being promoted, then
6547 // we know that the elements are arranged differently and that we
6548 // must perform the conversion using a stack slot.
6549 if (InVT.isVector())
6550 break;
6551
6552 // If the InOp is promoted to the same size, convert it. Otherwise,
6553 // fall out of the switch and widen the promoted input.
6554 SDValue NInOp = GetPromotedInteger(InOp);
6555 EVT NInVT = NInOp.getValueType();
6556 if (WidenVT.bitsEq(NInVT)) {
6557 // For big endian targets we need to shift the input integer or the
6558 // interesting bits will end up at the wrong place.
6559 if (DAG.getDataLayout().isBigEndian()) {
6560 unsigned ShiftAmt = NInVT.getSizeInBits() - InVT.getSizeInBits();
6561 NInOp = DAG.getNode(ISD::SHL, dl, NInVT, NInOp,
6562 DAG.getShiftAmountConstant(ShiftAmt, NInVT, dl));
6563 }
6564 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NInOp);
6565 }
6566 InOp = NInOp;
6567 InVT = NInVT;
6568 break;
6569 }
6576 break;
6578 // If the InOp is widened to the same size, convert it. Otherwise, fall
6579 // out of the switch and widen the widened input.
6580 InOp = GetWidenedVector(InOp);
6581 InVT = InOp.getValueType();
6582 if (WidenVT.bitsEq(InVT))
6583 // The input widens to the same size. Convert to the widen value.
6584 return DAG.getNode(ISD::BITCAST, dl, WidenVT, InOp);
6585 break;
6586 }
6587
6588 unsigned WidenSize = WidenVT.getSizeInBits();
6589 unsigned InSize = InVT.getSizeInBits();
6590 unsigned InScalarSize = InVT.getScalarSizeInBits();
6591 // x86mmx is not an acceptable vector element type, so don't try.
6592 if (WidenSize % InScalarSize == 0 && InVT != MVT::x86mmx) {
6593 // Determine new input vector type. The new input vector type will use
6594 // the same element type (if its a vector) or use the input type as a
6595 // vector. It is the same size as the type to widen to.
6596 EVT NewInVT;
6597 unsigned NewNumParts = WidenSize / InSize;
6598 if (InVT.isVector()) {
6599 EVT InEltVT = InVT.getVectorElementType();
6600 NewInVT = EVT::getVectorVT(*DAG.getContext(), InEltVT,
6601 WidenSize / InEltVT.getSizeInBits());
6602 } else {
6603 // For big endian systems, using the promoted input scalar type
6604 // to produce the scalar_to_vector would put the desired bits into
6605 // the least significant byte(s) of the wider element zero. This
6606 // will mean that the users of the result vector are using incorrect
6607 // bits. Use the original input type instead. Although either input
6608 // type can be used on little endian systems, for consistency we
6609 // use the original type there as well.
6610 EVT OrigInVT = N->getOperand(0).getValueType();
6611 NewNumParts = WidenSize / OrigInVT.getSizeInBits();
6612 NewInVT = EVT::getVectorVT(*DAG.getContext(), OrigInVT, NewNumParts);
6613 }
6614
6615 if (TLI.isTypeLegal(NewInVT)) {
6616 SDValue NewVec;
6617 if (InVT.isVector()) {
6618 // Because the result and the input are different vector types, widening
6619 // the result could create a legal type but widening the input might
6620 // make it an illegal type that might lead to repeatedly splitting the
6621 // input and then widening it. To avoid this, we widen the input only if
6622 // it results in a legal type.
6623 if (WidenSize % InSize == 0) {
6624 SmallVector<SDValue, 16> Ops(NewNumParts, DAG.getPOISON(InVT));
6625 Ops[0] = InOp;
6626
6627 NewVec = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewInVT, Ops);
6628 } else {
6630 DAG.ExtractVectorElements(InOp, Ops);
6631 Ops.append(WidenSize / InScalarSize - Ops.size(),
6632 DAG.getPOISON(InVT.getVectorElementType()));
6633
6634 NewVec = DAG.getNode(ISD::BUILD_VECTOR, dl, NewInVT, Ops);
6635 }
6636 } else {
6637 NewVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewInVT, InOp);
6638 }
6639 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NewVec);
6640 }
6641 }
6642
6643 return CreateStackStoreLoad(InOp, WidenVT);
6644}
6645
6646SDValue DAGTypeLegalizer::WidenVecRes_LOOP_DEPENDENCE_MASK(SDNode *N) {
6647 return DAG.getNode(
6648 N->getOpcode(), SDLoc(N),
6649 TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)),
6650 N->getOperand(0), N->getOperand(1), N->getOperand(2), N->getOperand(3));
6651}
6652
6653SDValue DAGTypeLegalizer::WidenVecRes_BUILD_VECTOR(SDNode *N) {
6654 SDLoc dl(N);
6655 // Build a vector with poison for the new nodes.
6656 EVT VT = N->getValueType(0);
6657
6658 // Integer BUILD_VECTOR operands may be larger than the node's vector element
6659 // type. The POISONs need to have the same type as the existing operands.
6660 EVT EltVT = N->getOperand(0).getValueType();
6661 unsigned NumElts = VT.getVectorNumElements();
6662
6663 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6664 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6665
6666 SmallVector<SDValue, 16> NewOps(N->ops());
6667 assert(WidenNumElts >= NumElts && "Shrinking vector instead of widening!");
6668 NewOps.append(WidenNumElts - NumElts, DAG.getPOISON(EltVT));
6669
6670 return DAG.getBuildVector(WidenVT, dl, NewOps);
6671}
6672
6673SDValue DAGTypeLegalizer::WidenVecRes_CONCAT_VECTORS(SDNode *N) {
6674 EVT InVT = N->getOperand(0).getValueType();
6675 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6676 SDLoc dl(N);
6677 unsigned NumOperands = N->getNumOperands();
6678
6679 bool InputWidened = false; // Indicates we need to widen the input.
6680 if (getTypeAction(InVT) != TargetLowering::TypeWidenVector) {
6681 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6682 unsigned NumInElts = InVT.getVectorMinNumElements();
6683 if (WidenNumElts % NumInElts == 0) {
6684 // Add undef vectors to widen to correct length.
6685 unsigned NumConcat = WidenNumElts / NumInElts;
6686 SDValue UndefVal = DAG.getPOISON(InVT);
6687 SmallVector<SDValue, 16> Ops(NumConcat);
6688 for (unsigned i=0; i < NumOperands; ++i)
6689 Ops[i] = N->getOperand(i);
6690 for (unsigned i = NumOperands; i != NumConcat; ++i)
6691 Ops[i] = UndefVal;
6692 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Ops);
6693 }
6694 } else {
6695 InputWidened = true;
6696 if (WidenVT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
6697 // The inputs and the result are widen to the same value.
6698 unsigned i;
6699 for (i=1; i < NumOperands; ++i)
6700 if (!N->getOperand(i).isUndef())
6701 break;
6702
6703 if (i == NumOperands)
6704 // Everything but the first operand is an UNDEF so just return the
6705 // widened first operand.
6706 return GetWidenedVector(N->getOperand(0));
6707
6708 if (NumOperands == 2) {
6709 assert(!WidenVT.isScalableVector() &&
6710 "Cannot use vector shuffles to widen CONCAT_VECTOR result");
6711 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6712 unsigned NumInElts = InVT.getVectorNumElements();
6713
6714 // Replace concat of two operands with a shuffle.
6715 SmallVector<int, 16> MaskOps(WidenNumElts, -1);
6716 for (unsigned i = 0; i < NumInElts; ++i) {
6717 MaskOps[i] = i;
6718 MaskOps[i + NumInElts] = i + WidenNumElts;
6719 }
6720 return DAG.getVectorShuffle(WidenVT, dl,
6721 GetWidenedVector(N->getOperand(0)),
6722 GetWidenedVector(N->getOperand(1)),
6723 MaskOps);
6724 }
6725 }
6726 }
6727
6728 if (WidenVT.isScalableVector()) {
6729 SDValue WideVec = DAG.getPOISON(WidenVT);
6730 unsigned NumInElts = InVT.getVectorMinNumElements();
6731 for (unsigned I = 0; I < NumOperands; ++I)
6732 WideVec =
6733 DAG.getInsertSubvector(dl, WideVec, N->getOperand(I), I * NumInElts);
6734 return WideVec;
6735 }
6736
6737 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6738 unsigned NumInElts = InVT.getVectorNumElements();
6739
6740 // Fall back to use extracts and build vector.
6741 EVT EltVT = WidenVT.getVectorElementType();
6742 SmallVector<SDValue, 16> Ops(WidenNumElts);
6743 unsigned Idx = 0;
6744 for (unsigned i=0; i < NumOperands; ++i) {
6745 SDValue InOp = N->getOperand(i);
6746 if (InputWidened)
6747 InOp = GetWidenedVector(InOp);
6748 for (unsigned j = 0; j < NumInElts; ++j)
6749 Ops[Idx++] = DAG.getExtractVectorElt(dl, EltVT, InOp, j);
6750 }
6751 SDValue UndefVal = DAG.getPOISON(EltVT);
6752 for (; Idx < WidenNumElts; ++Idx)
6753 Ops[Idx] = UndefVal;
6754 return DAG.getBuildVector(WidenVT, dl, Ops);
6755}
6756
6757SDValue DAGTypeLegalizer::WidenVecRes_INSERT_SUBVECTOR(SDNode *N) {
6758 EVT VT = N->getValueType(0);
6759 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6760 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
6761 SDValue InOp2 = N->getOperand(1);
6762 SDValue Idx = N->getOperand(2);
6763 SDLoc dl(N);
6764 return DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WidenVT, InOp1, InOp2, Idx);
6765}
6766
6767SDValue DAGTypeLegalizer::WidenVecRes_EXTRACT_SUBVECTOR(SDNode *N) {
6768 EVT VT = N->getValueType(0);
6769 EVT EltVT = VT.getVectorElementType();
6770 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6771 SDValue InOp = N->getOperand(0);
6772 SDValue Idx = N->getOperand(1);
6773 SDLoc dl(N);
6774
6775 auto InOpTypeAction = getTypeAction(InOp.getValueType());
6776 if (InOpTypeAction == TargetLowering::TypeWidenVector)
6777 InOp = GetWidenedVector(InOp);
6778
6779 EVT InVT = InOp.getValueType();
6780
6781 // Check if we can just return the input vector after widening.
6782 uint64_t IdxVal = Idx->getAsZExtVal();
6783 if (IdxVal == 0 && InVT == WidenVT)
6784 return InOp;
6785
6786 // Check if we can extract from the vector.
6787 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6788 unsigned InNumElts = InVT.getVectorMinNumElements();
6789 unsigned VTNumElts = VT.getVectorMinNumElements();
6790 assert(IdxVal % VTNumElts == 0 &&
6791 "Expected Idx to be a multiple of subvector minimum vector length");
6792 if (IdxVal % WidenNumElts == 0 && IdxVal + WidenNumElts < InNumElts)
6793 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, WidenVT, InOp, Idx);
6794
6795 if (VT.isScalableVector()) {
6796 // Try to split the operation up into smaller extracts and concat the
6797 // results together, e.g.
6798 // nxv6i64 extract_subvector(nxv12i64, 6)
6799 // <->
6800 // nxv8i64 concat(
6801 // nxv2i64 extract_subvector(nxv16i64, 6)
6802 // nxv2i64 extract_subvector(nxv16i64, 8)
6803 // nxv2i64 extract_subvector(nxv16i64, 10)
6804 // undef)
6805 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
6806 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
6807 "down type's element count");
6808 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
6810 // Avoid recursion around e.g. nxv1i8.
6811 if (getTypeAction(PartVT) != TargetLowering::TypeWidenVector) {
6813 unsigned I = 0;
6814 for (; I < VTNumElts / GCD; ++I)
6815 Parts.push_back(
6816 DAG.getExtractSubvector(dl, PartVT, InOp, IdxVal + I * GCD));
6817 for (; I < WidenNumElts / GCD; ++I)
6818 Parts.push_back(DAG.getPOISON(PartVT));
6819
6820 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
6821 }
6822
6823 // Fallback to extracting through memory.
6824
6825 Align Alignment = DAG.getReducedAlign(InVT, /*UseABI=*/false);
6826 SDValue StackPtr = DAG.CreateStackTemporary(InVT.getStoreSize(), Alignment);
6827 MachineFunction &MF = DAG.getMachineFunction();
6828 int FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
6829 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
6830
6831 MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
6834 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
6837
6838 // Write out the input vector.
6839 SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, InOp, StackPtr, StoreMMO);
6840
6841 // Build a mask to match the length of the non-widened result.
6842 SDValue Mask =
6843 DAG.getMaskFromElementCount(dl, WidenVT, VT.getVectorElementCount());
6844
6845 // Read back the sub-vector setting the remaining lanes to poison.
6846 StackPtr = TLI.getVectorSubVecPointer(DAG, StackPtr, InVT, VT, Idx);
6847 return DAG.getMaskedLoad(
6848 WidenVT, dl, Ch, StackPtr, DAG.getPOISON(StackPtr.getValueType()), Mask,
6849 DAG.getPOISON(WidenVT), VT, LoadMMO, ISD::UNINDEXED, ISD::NON_EXTLOAD);
6850 }
6851
6852 // We could try widening the input to the right length but for now, extract
6853 // the original elements, fill the rest with undefs and build a vector.
6854 SmallVector<SDValue, 16> Ops(WidenNumElts);
6855 unsigned i;
6856 for (i = 0; i < VTNumElts; ++i)
6857 Ops[i] = DAG.getExtractVectorElt(dl, EltVT, InOp, IdxVal + i);
6858
6859 SDValue UndefVal = DAG.getPOISON(EltVT);
6860 for (; i < WidenNumElts; ++i)
6861 Ops[i] = UndefVal;
6862 return DAG.getBuildVector(WidenVT, dl, Ops);
6863}
6864
6865SDValue DAGTypeLegalizer::WidenVecRes_AssertZext(SDNode *N) {
6866 SDValue InOp = ModifyToType(
6867 N->getOperand(0),
6868 TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)), true);
6869 return DAG.getNode(ISD::AssertZext, SDLoc(N), InOp.getValueType(), InOp,
6870 N->getOperand(1));
6871}
6872
6873SDValue DAGTypeLegalizer::WidenVecRes_INSERT_VECTOR_ELT(SDNode *N) {
6874 SDValue InOp = GetWidenedVector(N->getOperand(0));
6875 return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(N),
6876 InOp.getValueType(), InOp,
6877 N->getOperand(1), N->getOperand(2));
6878}
6879
6880/// Either return the same load or provide appropriate casts
6881/// from the load and return that.
6882static SDValue coerceLoadedValue(SDValue LdOp, EVT FirstVT, EVT WidenVT,
6883 TypeSize LdWidth, TypeSize FirstVTWidth,
6884 SDLoc dl, SelectionDAG &DAG) {
6885 assert(TypeSize::isKnownLE(LdWidth, FirstVTWidth) &&
6886 "Load width must be less than or equal to first value type width");
6887 TypeSize WidenWidth = WidenVT.getSizeInBits();
6888 if (!FirstVT.isVector()) {
6889 unsigned NumElts =
6890 WidenWidth.getFixedValue() / FirstVTWidth.getFixedValue();
6891 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), FirstVT, NumElts);
6892 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT, LdOp);
6893 return DAG.getNode(ISD::BITCAST, dl, WidenVT, VecOp);
6894 }
6895 assert(FirstVT == WidenVT && "First value type must equal widen value type");
6896 return LdOp;
6897}
6898
6899/// Inverse of coerceLoadedValue: pull a FirstVT-sized scalar/vector out of the
6900/// widened value so it can be issued in a single atomic store.
6901static SDValue coerceStoredValue(SDValue StVal, EVT FirstVT, EVT WidenVT,
6902 TypeSize FirstVTWidth, const SDLoc &dl,
6903 SelectionDAG &DAG) {
6904 TypeSize WidenWidth = WidenVT.getSizeInBits();
6905 if (!FirstVT.isVector()) {
6906 unsigned NumElts =
6907 WidenWidth.getFixedValue() / FirstVTWidth.getFixedValue();
6908 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), FirstVT, NumElts);
6909 SDValue VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, StVal);
6910 return DAG.getExtractVectorElt(dl, FirstVT, VecOp, 0);
6911 }
6912 assert(FirstVT == WidenVT && "First value type must equal widen value type");
6913 return StVal;
6914}
6915
6916static std::optional<EVT> findMemType(SelectionDAG &DAG,
6917 const TargetLowering &TLI, unsigned Width,
6918 EVT WidenVT, unsigned Align,
6919 unsigned WidenEx);
6920
6921SDValue DAGTypeLegalizer::WidenVecRes_ATOMIC_LOAD(AtomicSDNode *LD) {
6922 EVT WidenVT =
6923 TLI.getTypeToTransformTo(*DAG.getContext(), LD->getValueType(0));
6924 EVT LdVT = LD->getMemoryVT();
6925 SDLoc dl(LD);
6926
6927 // Load information
6928 SDValue Chain = LD->getChain();
6929 SDValue BasePtr = LD->getBasePtr();
6930
6931 TypeSize LdWidth = LdVT.getSizeInBits();
6932 TypeSize WidenWidth = WidenVT.getSizeInBits();
6933 TypeSize WidthDiff = WidenWidth - LdWidth;
6934
6935 // Find the vector type that can load from.
6936 std::optional<EVT> FirstVT =
6937 findMemType(DAG, TLI, LdWidth.getKnownMinValue(), WidenVT, /*LdAlign=*/0,
6938 WidthDiff.getKnownMinValue());
6939
6940 if (!FirstVT)
6941 return SDValue();
6942
6943 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
6944
6945 SDValue LdOp = DAG.getAtomicLoad(ISD::NON_EXTLOAD, dl, *FirstVT, *FirstVT,
6946 Chain, BasePtr, LD->getMemOperand());
6947
6948 // Load the element with one instruction.
6949 SDValue Result = coerceLoadedValue(LdOp, *FirstVT, WidenVT, LdWidth,
6950 FirstVTWidth, dl, DAG);
6951
6952 // Modified the chain - switch anything that used the old chain to use
6953 // the new one.
6954 ReplaceValueWith(SDValue(LD, 1), LdOp.getValue(1));
6955 return Result;
6956}
6957
6958SDValue DAGTypeLegalizer::WidenVecRes_LOAD(SDNode *N) {
6959 LoadSDNode *LD = cast<LoadSDNode>(N);
6960 ISD::LoadExtType ExtType = LD->getExtensionType();
6961
6962 // A vector must always be stored in memory as-is, i.e. without any padding
6963 // between the elements, since various code depend on it, e.g. in the
6964 // handling of a bitcast of a vector type to int, which may be done with a
6965 // vector store followed by an integer load. A vector that does not have
6966 // elements that are byte-sized must therefore be stored as an integer
6967 // built out of the extracted vector elements.
6968 if (!LD->getMemoryVT().isByteSized()) {
6969 SDValue Value, NewChain;
6970 std::tie(Value, NewChain) = TLI.scalarizeVectorLoad(LD, DAG);
6971 ReplaceValueWith(SDValue(LD, 0), Value);
6972 ReplaceValueWith(SDValue(LD, 1), NewChain);
6973 return SDValue();
6974 }
6975
6976 // Generate a vector-predicated load if it is custom/legal on the target. To
6977 // avoid possible recursion, only do this if the widened mask type is legal.
6978 // FIXME: Not all targets may support EVL in VP_LOAD. These will have been
6979 // removed from the IR by the ExpandVectorPredication pass but we're
6980 // reintroducing them here.
6981 EVT VT = LD->getValueType(0);
6982 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6983 EVT WideMaskVT = getSetCCResultType(WideVT);
6984
6985 if (ExtType == ISD::NON_EXTLOAD &&
6986 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WideVT) &&
6987 TLI.isTypeLegal(WideMaskVT)) {
6988 SDLoc DL(N);
6989 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
6990 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
6992 SDValue NewLoad =
6993 DAG.getLoadVP(LD->getAddressingMode(), ISD::NON_EXTLOAD, WideVT, DL,
6994 LD->getChain(), LD->getBasePtr(), LD->getOffset(), Mask,
6995 EVL, LD->getMemoryVT(), LD->getMemOperand());
6996
6997 // Modified the chain - switch anything that used the old chain to use
6998 // the new one.
6999 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
7000
7001 return NewLoad;
7002 }
7003
7004 SDValue Result;
7005 SmallVector<SDValue, 16> LdChain; // Chain for the series of load
7006 if (ExtType != ISD::NON_EXTLOAD)
7007 Result = GenWidenVectorExtLoads(LdChain, LD, ExtType);
7008 else
7009 Result = GenWidenVectorLoads(LdChain, LD);
7010
7011 if (Result) {
7012 // If we generate a single load, we can use that for the chain. Otherwise,
7013 // build a factor node to remember the multiple loads are independent and
7014 // chain to that.
7015 SDValue NewChain;
7016 if (LdChain.size() == 1)
7017 NewChain = LdChain[0];
7018 else
7019 NewChain = DAG.getNode(ISD::TokenFactor, SDLoc(LD), MVT::Other, LdChain);
7020
7021 // Modified the chain - switch anything that used the old chain to use
7022 // the new one.
7023 ReplaceValueWith(SDValue(N, 1), NewChain);
7024
7025 return Result;
7026 }
7027
7028 if (VT.isVector()) {
7029 // If all else fails replace the load with a wide masked load.
7030 SDLoc DL(N);
7031 SDValue Mask =
7032 DAG.getMaskFromElementCount(DL, WideVT, VT.getVectorElementCount());
7033
7034 SDValue NewLoad = DAG.getMaskedLoad(
7035 WideVT, DL, LD->getChain(), LD->getBasePtr(), LD->getOffset(), Mask,
7036 DAG.getPOISON(WideVT), LD->getMemoryVT(), LD->getMemOperand(),
7037 LD->getAddressingMode(), LD->getExtensionType());
7038
7039 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
7040 return NewLoad;
7041 }
7042
7043 report_fatal_error("Unable to widen vector load");
7044}
7045
7046SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD(VPLoadSDNode *N) {
7047 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7048 SDValue Mask = N->getMask();
7049 SDValue EVL = N->getVectorLength();
7050 ISD::LoadExtType ExtType = N->getExtensionType();
7051 SDLoc dl(N);
7052
7053 // The mask should be widened as well
7054 assert(getTypeAction(Mask.getValueType()) ==
7056 "Unable to widen binary VP op");
7057 Mask = GetWidenedVector(Mask);
7058 assert(Mask.getValueType().getVectorElementCount() ==
7059 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
7060 .getVectorElementCount() &&
7061 "Unable to widen vector load");
7062
7063 SDValue Res =
7064 DAG.getLoadVP(N->getAddressingMode(), ExtType, WidenVT, dl, N->getChain(),
7065 N->getBasePtr(), N->getOffset(), Mask, EVL,
7066 N->getMemoryVT(), N->getMemOperand(), N->isExpandingLoad());
7067 // Legalize the chain result - switch anything that used the old chain to
7068 // use the new one.
7069 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7070 return Res;
7071}
7072
7073SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD_FF(VPLoadFFSDNode *N) {
7074 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7075 SDValue Mask = N->getMask();
7076 SDValue EVL = N->getVectorLength();
7077 SDLoc dl(N);
7078
7079 // The mask should be widened as well
7080 assert(getTypeAction(Mask.getValueType()) ==
7082 "Unable to widen binary VP op");
7083 Mask = GetWidenedVector(Mask);
7084 assert(Mask.getValueType().getVectorElementCount() ==
7085 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
7086 .getVectorElementCount() &&
7087 "Unable to widen vector load");
7088
7089 SDValue Res = DAG.getLoadFFVP(WidenVT, dl, N->getChain(), N->getBasePtr(),
7090 Mask, EVL, N->getMemOperand());
7091 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7092 ReplaceValueWith(SDValue(N, 2), Res.getValue(2));
7093 return Res;
7094}
7095
7096SDValue DAGTypeLegalizer::WidenVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode *N) {
7097 SDLoc DL(N);
7098
7099 // The mask should be widened as well
7100 SDValue Mask = N->getMask();
7101 assert(getTypeAction(Mask.getValueType()) ==
7103 "Unable to widen VP strided load");
7104 Mask = GetWidenedVector(Mask);
7105
7106 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7107 assert(Mask.getValueType().getVectorElementCount() ==
7108 WidenVT.getVectorElementCount() &&
7109 "Data and mask vectors should have the same number of elements");
7110
7111 SDValue Res = DAG.getStridedLoadVP(
7112 N->getAddressingMode(), N->getExtensionType(), WidenVT, DL, N->getChain(),
7113 N->getBasePtr(), N->getOffset(), N->getStride(), Mask,
7114 N->getVectorLength(), N->getMemoryVT(), N->getMemOperand(),
7115 N->isExpandingLoad());
7116
7117 // Legalize the chain result - switch anything that used the old chain to
7118 // use the new one.
7119 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7120 return Res;
7121}
7122
7123SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_COMPRESS(SDNode *N) {
7124 SDValue Vec = N->getOperand(0);
7125 SDValue Mask = N->getOperand(1);
7126 SDValue Passthru = N->getOperand(2);
7127 EVT WideVecVT =
7128 TLI.getTypeToTransformTo(*DAG.getContext(), Vec.getValueType());
7129 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
7130 Mask.getValueType().getVectorElementType(),
7131 WideVecVT.getVectorElementCount());
7132
7133 SDValue WideVec = ModifyToType(Vec, WideVecVT);
7134 SDValue WideMask = ModifyToType(Mask, WideMaskVT, /*FillWithZeroes=*/true);
7135 SDValue WidePassthru = ModifyToType(Passthru, WideVecVT);
7136 return DAG.getNode(ISD::VECTOR_COMPRESS, SDLoc(N), WideVecVT, WideVec,
7137 WideMask, WidePassthru);
7138}
7139
7140SDValue DAGTypeLegalizer::WidenVecRes_MLOAD(MaskedLoadSDNode *N) {
7141 EVT VT = N->getValueType(0);
7142 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7143 SDValue Mask = N->getMask();
7144 EVT MaskVT = Mask.getValueType();
7145 SDValue PassThru = GetWidenedVector(N->getPassThru());
7146 ISD::LoadExtType ExtType = N->getExtensionType();
7147 SDLoc dl(N);
7148
7149 EVT WideMaskVT =
7150 EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(),
7151 WidenVT.getVectorElementCount());
7152
7153 if (ExtType == ISD::NON_EXTLOAD && !N->isExpandingLoad() &&
7154 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WidenVT) &&
7155 TLI.isTypeLegal(WideMaskVT) &&
7156 // If there is a passthru, we shouldn't use vp.load. However,
7157 // type legalizer will struggle on masked.load with
7158 // scalable vectors, so for scalable vectors, we still use vp.load
7159 // but manually merge the load result with the passthru using vp.select.
7160 (N->getPassThru()->isUndef() || VT.isScalableVector())) {
7161 Mask = DAG.getInsertSubvector(dl, DAG.getPOISON(WideMaskVT), Mask, 0);
7162 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
7164 SDValue NewLoad =
7165 DAG.getLoadVP(N->getAddressingMode(), ISD::NON_EXTLOAD, WidenVT, dl,
7166 N->getChain(), N->getBasePtr(), N->getOffset(), Mask, EVL,
7167 N->getMemoryVT(), N->getMemOperand());
7168 SDValue NewVal = NewLoad;
7169
7170 // Manually merge with vselect
7171 if (!N->getPassThru()->isUndef()) {
7172 assert(WidenVT.isScalableVector());
7173 NewVal = DAG.getNode(ISD::VSELECT, dl, WidenVT, Mask, NewVal, PassThru);
7174 // The lanes past EVL are poison.
7175 NewVal = DAG.getNode(ISD::VP_MERGE, dl, WidenVT,
7176 DAG.getAllOnesConstant(dl, WideMaskVT), NewVal,
7177 DAG.getPOISON(WidenVT), EVL);
7178 }
7179
7180 // Modified the chain - switch anything that used the old chain to use
7181 // the new one.
7182 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
7183
7184 return NewVal;
7185 }
7186
7187 // The mask should be widened as well
7188 Mask = ModifyToType(Mask, WideMaskVT, true);
7189
7190 SDValue Res = DAG.getMaskedLoad(
7191 WidenVT, dl, N->getChain(), N->getBasePtr(), N->getOffset(), Mask,
7192 PassThru, N->getMemoryVT(), N->getMemOperand(), N->getAddressingMode(),
7193 ExtType, N->isExpandingLoad());
7194 // Legalize the chain result - switch anything that used the old chain to
7195 // use the new one.
7196 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7197 return Res;
7198}
7199
7200SDValue DAGTypeLegalizer::WidenVecRes_MGATHER(MaskedGatherSDNode *N) {
7201
7202 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7203 SDValue Mask = N->getMask();
7204 EVT MaskVT = Mask.getValueType();
7205 SDValue PassThru = GetWidenedVector(N->getPassThru());
7206 SDValue Scale = N->getScale();
7207 ElementCount WideEC = WideVT.getVectorElementCount();
7208 SDLoc dl(N);
7209
7210 // The mask should be widened as well
7211 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
7212 MaskVT.getVectorElementType(), WideEC);
7213 Mask = ModifyToType(Mask, WideMaskVT, true);
7214
7215 // Widen the Index operand
7216 SDValue Index = N->getIndex();
7217 EVT WideIndexVT = EVT::getVectorVT(
7218 *DAG.getContext(), Index.getValueType().getScalarType(), WideEC);
7219 Index = ModifyToType(Index, WideIndexVT);
7220 SDValue Ops[] = { N->getChain(), PassThru, Mask, N->getBasePtr(), Index,
7221 Scale };
7222
7223 // Widen the MemoryType
7224 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
7225 N->getMemoryVT().getScalarType(), WideEC);
7226 SDValue Res = DAG.getMaskedGather(DAG.getVTList(WideVT, MVT::Other),
7227 WideMemVT, dl, Ops, N->getMemOperand(),
7228 N->getIndexType(), N->getExtensionType());
7229
7230 // Legalize the chain result - switch anything that used the old chain to
7231 // use the new one.
7232 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7233 return Res;
7234}
7235
7236SDValue DAGTypeLegalizer::WidenVecRes_VP_GATHER(VPGatherSDNode *N) {
7237 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7238 SDValue Mask = N->getMask();
7239 SDValue Scale = N->getScale();
7240 ElementCount WideEC = WideVT.getVectorElementCount();
7241 SDLoc dl(N);
7242
7243 SDValue Index = GetWidenedVector(N->getIndex());
7244 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
7245 N->getMemoryVT().getScalarType(), WideEC);
7246 Mask = GetWidenedMask(Mask, WideEC);
7247
7248 SDValue Ops[] = {N->getChain(), N->getBasePtr(), Index, Scale,
7249 Mask, N->getVectorLength()};
7250 SDValue Res = DAG.getGatherVP(DAG.getVTList(WideVT, MVT::Other), WideMemVT,
7251 dl, Ops, N->getMemOperand(), N->getIndexType());
7252
7253 // Legalize the chain result - switch anything that used the old chain to
7254 // use the new one.
7255 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7256 return Res;
7257}
7258
7259SDValue DAGTypeLegalizer::WidenVecRes_ScalarOp(SDNode *N) {
7260 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7261 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, N->getOperand(0));
7262}
7263
7264// Return true is this is a SETCC node or a strict version of it.
7265static inline bool isSETCCOp(unsigned Opcode) {
7266 switch (Opcode) {
7267 case ISD::SETCC:
7268 case ISD::STRICT_FSETCC:
7270 return true;
7271 }
7272 return false;
7273}
7274
7275// Return true if this is a node that could have two SETCCs as operands.
7276static inline bool isLogicalMaskOp(unsigned Opcode) {
7277 switch (Opcode) {
7278 case ISD::AND:
7279 case ISD::OR:
7280 case ISD::XOR:
7281 return true;
7282 }
7283 return false;
7284}
7285
7286// If N is a SETCC or a strict variant of it, return the type
7287// of the compare operands.
7289 unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
7290 return N->getOperand(OpNo).getValueType();
7291}
7292
7293// This is used just for the assert in convertMask(). Check that this either
7294// a SETCC or a previously handled SETCC by convertMask().
7295#ifndef NDEBUG
7296static inline bool isSETCCorConvertedSETCC(SDValue N) {
7297 if (N.getOpcode() == ISD::EXTRACT_SUBVECTOR)
7298 N = N.getOperand(0);
7299 else if (N.getOpcode() == ISD::CONCAT_VECTORS) {
7300 for (unsigned i = 1; i < N->getNumOperands(); ++i)
7301 if (!N->getOperand(i)->isUndef())
7302 return false;
7303 N = N.getOperand(0);
7304 }
7305
7306 if (N.getOpcode() == ISD::TRUNCATE)
7307 N = N.getOperand(0);
7308 else if (N.getOpcode() == ISD::SIGN_EXTEND)
7309 N = N.getOperand(0);
7310
7311 if (isLogicalMaskOp(N.getOpcode()))
7312 return isSETCCorConvertedSETCC(N.getOperand(0)) &&
7313 isSETCCorConvertedSETCC(N.getOperand(1));
7314
7315 return (isSETCCOp(N.getOpcode()) ||
7317}
7318#endif
7319
7320// Return a mask of vector type MaskVT to replace InMask. Also adjust MaskVT
7321// to ToMaskVT if needed with vector extension or truncation.
7322SDValue DAGTypeLegalizer::convertMask(SDValue InMask, EVT MaskVT,
7323 EVT ToMaskVT) {
7324 // Called from convertMaskTree for SETCC leaf nodes. Re-creates the SETCC with
7325 // result type MaskVT, then sign-extends/truncates and pads to ToMaskVT.
7326 assert(isSETCCorConvertedSETCC(InMask) && "Unexpected mask argument.");
7327
7328 // Make a new Mask node, with a legal result VT.
7329 SDValue Mask;
7331 for (unsigned i = 0, e = InMask->getNumOperands(); i < e; ++i)
7332 Ops.push_back(InMask->getOperand(i));
7333 if (InMask->isStrictFPOpcode()) {
7334 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask),
7335 { MaskVT, MVT::Other }, Ops);
7336 ReplaceValueWith(InMask.getValue(1), Mask.getValue(1));
7337 }
7338 else
7339 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask), MaskVT, Ops,
7340 InMask->getFlags());
7341
7342 return adjustMaskToType(Mask, ToMaskVT);
7343}
7344
7345// Adjust element width (sign-extend/truncate) and element count
7346// (extract/concat) of Mask to match ToMaskVT.
7347SDValue DAGTypeLegalizer::adjustMaskToType(SDValue Mask, EVT ToMaskVT) {
7348 LLVMContext &Ctx = *DAG.getContext();
7349 EVT MaskVT = Mask.getValueType();
7350 unsigned MaskScalarBits = MaskVT.getScalarSizeInBits();
7351 unsigned ToMaskScalBits = ToMaskVT.getScalarSizeInBits();
7352 if (MaskScalarBits < ToMaskScalBits) {
7353 EVT ExtVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
7354 MaskVT.getVectorNumElements());
7355 Mask = DAG.getNode(ISD::SIGN_EXTEND, SDLoc(Mask), ExtVT, Mask);
7356 } else if (MaskScalarBits > ToMaskScalBits) {
7357 EVT TruncVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
7358 MaskVT.getVectorNumElements());
7359 Mask = DAG.getNode(ISD::TRUNCATE, SDLoc(Mask), TruncVT, Mask);
7360 }
7361
7362 assert(Mask->getValueType(0).getScalarSizeInBits() ==
7363 ToMaskVT.getScalarSizeInBits() &&
7364 "Mask should have the right element size by now.");
7365
7366 // Adjust Mask to the right number of elements.
7367 unsigned CurrMaskNumEls = Mask->getValueType(0).getVectorNumElements();
7368 if (CurrMaskNumEls > ToMaskVT.getVectorNumElements()) {
7369 Mask = DAG.getExtractSubvector(SDLoc(Mask), ToMaskVT, Mask, 0);
7370 } else if (CurrMaskNumEls < ToMaskVT.getVectorNumElements()) {
7371 unsigned NumSubVecs = (ToMaskVT.getVectorNumElements() / CurrMaskNumEls);
7372 EVT SubVT = Mask->getValueType(0);
7373 SmallVector<SDValue, 16> SubOps(NumSubVecs, DAG.getPOISON(SubVT));
7374 SubOps[0] = Mask;
7375 Mask = DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Mask), ToMaskVT, SubOps);
7376 }
7377
7378 assert((Mask->getValueType(0) == ToMaskVT) &&
7379 "A mask of ToMaskVT should have been produced by now.");
7380
7381 return Mask;
7382}
7383
7384// Adjust both operands to a common intermediate mask type, picking a scalar
7385// width that minimizes extend/truncate overhead given the final target ToVT.
7386EVT DAGTypeLegalizer::unifyMaskTypes(SDValue &Op0, bool IsOpLenient0,
7387 SDValue &Op1, bool IsOpLenient1,
7388 EVT ToVT) {
7391 "unifyMaskTypes only handles scalar width differences");
7392
7393 // If only one of the operands lenient type-wise, we can simply
7394 // adjust its type to the other operand's type assuming that this
7395 // adjustment can be folded away.
7396 //
7397 // NOTE: We essentially rely on the fact that further optimizations
7398 // do spot redundant casts in "lenient" cases. If at some
7399 // point we decide that we want to do better here, we can
7400 // postpone converting lenient sub-trees right away and postpone
7401 // it to the moment when we know the best fitting integer type
7402 // to materialize them, and do it there.
7403 if (IsOpLenient0 != IsOpLenient1) {
7404 SDValue *LenientOp, *NonLenientOp;
7405 if (IsOpLenient0) {
7406 LenientOp = &Op0;
7407 NonLenientOp = &Op1;
7408 } else {
7409 LenientOp = &Op1;
7410 NonLenientOp = &Op0;
7411 }
7412 EVT OpVT = NonLenientOp->getValueType();
7413 *LenientOp = adjustMaskToType(*LenientOp, OpVT);
7414 return OpVT;
7415 }
7416
7417 unsigned Bits0 = Op0.getScalarValueSizeInBits();
7418 unsigned Bits1 = Op1.getScalarValueSizeInBits();
7419 unsigned NarrowBits = std::min(Bits0, Bits1);
7420 unsigned WideBits = std::max(Bits0, Bits1);
7421 unsigned ToBits = ToVT.getScalarSizeInBits();
7422 unsigned IntBits = NarrowBits == WideBits ? NarrowBits
7423 : ToBits >= WideBits ? WideBits
7424 : ToBits <= NarrowBits ? NarrowBits
7425 : ToBits;
7426 EVT OpVT = Op0.getValueType().changeVectorElementType(
7427 *DAG.getContext(), EVT::getIntegerVT(*DAG.getContext(), IntBits));
7428 Op0 = adjustMaskToType(Op0, OpVT);
7429 Op1 = adjustMaskToType(Op1, OpVT);
7430 return OpVT;
7431}
7432
7433std::pair<SDValue, bool>
7434DAGTypeLegalizer::convertMaskTreeImpl(SDValue V, EVT ToVT, unsigned Depth) {
7435 // The main idea is to recursively traverse VSELECT's mask that needs
7436 // widening to see if we can avoid unnecessary casts. The problem usually
7437 // stems from a simple fact that SETCC might naturally produce results
7438 // not in i1 (as we model it in LLVM IR) and we can continue using that
7439 // type until we have to switch it up. Another important aspect is that
7440 // "all ones" and "all zeros" constants can be materialized at any type,
7441 // so we can try to utilize that to keep SETCC results at their natural
7442 // types as much as possible.
7443 //
7444 // The algorithm traverses the mask-producing tree of operations that
7445 // retain "mask-vector"-ness of the input (i.e. it remains a vector of
7446 // -1s and 0s).
7447 //
7448 // SETCC1 SETCC2 CONST1 SETCC3 CONST2 CONST3
7449 // | / | / | /
7450 // | / | / | /
7451 // |_____/ |______/ |______/
7452 // | * choose the | * choose SETCC3 | * keep it as final type
7453 // | most fitting | type | but consider it subject to
7454 // | type | / change
7455 // | | /
7456 // | |______________/
7457 // | | * choose SETCC3 type
7458 // | /
7459 // | /
7460 // |_____________/
7461 // | * choose the most fitting type
7462 // | and then cast to the final desired type
7463 // |
7464 // VSELECT
7465 //
7466 if (Depth >= DAG.MaxRecursionDepth)
7467 return {};
7468
7469 // Bail out when encounter the vector element count mismatch.
7470 // It potentially can be just an assertion, but we deliberately try to
7471 // be overly conservative here.
7472 if (V.getValueType().getVectorNumElements() != ToVT.getVectorNumElements())
7473 return {};
7474
7475 unsigned Opcode = V.getOpcode();
7476
7477 // Base case: SETCC produces the mask at its natural type.
7478 if (isSETCCOp(Opcode)) {
7479 EVT MaskVT = getSetCCResultType(getSETCCOperandType(V));
7480 return {convertMask(V, MaskVT, MaskVT), /*IsTypeLenient=*/false};
7481 }
7482
7483 SDLoc DL(V);
7484
7485 // Base case: all-zeros or all-ones BUILD_VECTOR. Type-lenient since these are
7486 // invariant under sign-extend/truncate.
7487 if (ISD::isBuildVectorAllZeros(V.getNode()))
7488 return {DAG.getConstant(0, DL, ToVT), /*IsTypeLenient=*/true};
7489 if (ISD::isBuildVectorAllOnes(V.getNode()))
7490 return {DAG.getAllOnesConstant(DL, ToVT), /*IsTypeLenient=*/true};
7491
7492 // Logical operations (AND/OR/XOR): try picking the best fitting width out
7493 // of children's element widths.
7494 if (isLogicalMaskOp(Opcode)) {
7495 auto [Op0, IsLenientOp0] =
7496 convertMaskTreeImpl(V.getOperand(0), ToVT, Depth + 1);
7497 if (!Op0)
7498 return {};
7499 auto [Op1, IsLenientOp1] =
7500 convertMaskTreeImpl(V.getOperand(1), ToVT, Depth + 1);
7501 if (!Op1)
7502 return {};
7503 EVT OpVT = unifyMaskTypes(Op0, IsLenientOp0, Op1, IsLenientOp1, ToVT);
7504 return {DAG.getNode(Opcode, DL, OpVT, Op0, Op1),
7505 IsLenientOp0 && IsLenientOp1};
7506 }
7507
7508 // FREEZE: widen the operand and re-wrap.
7509 if (Opcode == ISD::FREEZE) {
7510 auto [Inner, IsTypeLenient] =
7511 convertMaskTreeImpl(V.getOperand(0), ToVT, Depth + 1);
7512 if (!Inner)
7513 return {};
7514 return {DAG.getNode(ISD::FREEZE, DL, Inner.getValueType(), Inner),
7515 IsTypeLenient};
7516 }
7517
7518 // Vector shuffle: try inferring the best fitting width from operands.
7519 if (Opcode == ISD::VECTOR_SHUFFLE) {
7520 auto *Shuf = cast<ShuffleVectorSDNode>(V);
7521 auto [Op0, IsLenientOp0] =
7522 convertMaskTreeImpl(V.getOperand(0), ToVT, Depth + 1);
7523 if (!Op0)
7524 return {};
7525 if (V.getOperand(1).isUndef()) {
7526 EVT OpVT = Op0.getValueType();
7527 return {DAG.getVectorShuffle(OpVT, DL, Op0, DAG.getUNDEF(OpVT),
7528 Shuf->getMask()),
7529 IsLenientOp0};
7530 }
7531 auto [Op1, IsLenientOp1] =
7532 convertMaskTreeImpl(V.getOperand(1), ToVT, Depth + 1);
7533 if (!Op1)
7534 return {};
7535 EVT OpVT = unifyMaskTypes(Op0, IsLenientOp0, Op1, IsLenientOp1, ToVT);
7536 return {DAG.getVectorShuffle(OpVT, DL, Op0, Op1, Shuf->getMask()),
7537 IsLenientOp0 && IsLenientOp1};
7538 }
7539
7540 // SELECT/VSELECT: try inferring the best fitting width from operands.
7541 if (Opcode == ISD::SELECT || Opcode == ISD::VSELECT) {
7542 auto [Op1, IsLenientOp1] =
7543 convertMaskTreeImpl(V.getOperand(1), ToVT, Depth + 1);
7544 if (!Op1)
7545 return {};
7546 auto [Op2, IsLenientOp2] =
7547 convertMaskTreeImpl(V.getOperand(2), ToVT, Depth + 1);
7548 if (!Op2)
7549 return {};
7550 EVT OpVT = unifyMaskTypes(Op1, IsLenientOp1, Op2, IsLenientOp2, ToVT);
7551
7552 // We deliberately skip traversing/modifying VSELECT's mask because
7553 //
7554 // a. We only change bitwidth of the operands and it shouldn't affect
7555 // condition on its own.
7556 //
7557 // b. This VSELECT's mask can be widened in an independent traversal
7558 // if needed.
7559 SDValue Cond = V.getOperand(0);
7560 return {DAG.getNode(Opcode, DL, OpVT, Cond, Op1, Op2),
7561 IsLenientOp1 && IsLenientOp2};
7562 }
7563
7564 return {};
7565}
7566
7567SDValue DAGTypeLegalizer::convertMaskTree(SDValue V, EVT ToVT) {
7568 // In general, we are converting from <N x i1> into <M x iW>.
7569 // This would mean that during the tree traversal we need to pay
7570 // attention to both bitwidth and element count, which can be error-prone.
7571 //
7572 // Instead, we split the task in two, we first widen the type of the tree
7573 // and then change the element count.
7574 EVT MaskTreeVT = ToVT.changeVectorElementCount(
7575 *DAG.getContext(), V.getValueType().getVectorElementCount());
7576 auto [Result, _] = convertMaskTreeImpl(V, MaskTreeVT);
7577 if (!Result)
7578 return Result;
7579 return adjustMaskToType(Result, ToVT);
7580}
7581
7582// This method tries to handle some special cases for the vselect mask
7583// and if needed adjusting the mask vector type to match that of the VSELECT.
7584// Without it, many cases end up with scalarization of the SETCC, with many
7585// unnecessary instructions.
7586SDValue DAGTypeLegalizer::WidenVSELECTMask(SDNode *N) {
7587 LLVMContext &Ctx = *DAG.getContext();
7588 SDValue Cond = N->getOperand(0);
7589
7590 if (N->getOpcode() != ISD::VSELECT)
7591 return SDValue();
7592
7593 // If this is a splitted VSELECT that was previously already handled, do
7594 // nothing.
7595 EVT CondVT = Cond->getValueType(0);
7596 if (CondVT.getScalarSizeInBits() != 1)
7597 return SDValue();
7598
7599 EVT VSelVT = N->getValueType(0);
7600
7601 // This method can't handle scalable vector types.
7602 // FIXME: This support could be added in the future.
7603 if (VSelVT.isScalableVector())
7604 return SDValue();
7605
7606 // Only handle vector types which are a power of 2.
7607 if (!isPowerOf2_64(VSelVT.getSizeInBits()))
7608 return SDValue();
7609
7610 // Don't touch if this will be scalarized.
7611 EVT FinalVT = VSelVT;
7612 while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
7613 FinalVT = FinalVT.getHalfNumVectorElementsVT(Ctx);
7614
7615 if (FinalVT.getVectorNumElements() == 1)
7616 return SDValue();
7617
7618 // If there is support for an i1 vector mask, don't touch.
7619 if (isSETCCOp(Cond.getOpcode())) {
7620 EVT SetCCOpVT = getSETCCOperandType(Cond);
7621 while (TLI.getTypeAction(Ctx, SetCCOpVT) != TargetLowering::TypeLegal)
7622 SetCCOpVT = TLI.getTypeToTransformTo(Ctx, SetCCOpVT);
7623 EVT SetCCResVT = getSetCCResultType(SetCCOpVT);
7624 if (SetCCResVT.getScalarSizeInBits() == 1)
7625 return SDValue();
7626 } else if (CondVT.getScalarType() == MVT::i1) {
7627 // If there is support for an i1 vector mask (or only scalar i1 conditions),
7628 // don't touch.
7629 while (TLI.getTypeAction(Ctx, CondVT) != TargetLowering::TypeLegal)
7630 CondVT = TLI.getTypeToTransformTo(Ctx, CondVT);
7631
7632 if (CondVT.getScalarType() == MVT::i1)
7633 return SDValue();
7634 }
7635
7636 // Widen the vselect result type if needed.
7637 if (getTypeAction(VSelVT) == TargetLowering::TypeWidenVector)
7638 VSelVT = TLI.getTypeToTransformTo(Ctx, VSelVT);
7639
7640 // The mask of the VSELECT should have integer elements.
7641 EVT ToMaskVT = VSelVT;
7642 if (!ToMaskVT.getScalarType().isInteger())
7643 ToMaskVT = ToMaskVT.changeVectorElementTypeToInteger();
7644
7645 // Try to recursively widen the mask expression tree to the target type.
7646 return convertMaskTree(Cond, ToMaskVT);
7647}
7648
7649SDValue DAGTypeLegalizer::WidenVecRes_Select(SDNode *N) {
7650 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7651 ElementCount WidenEC = WidenVT.getVectorElementCount();
7652
7653 SDValue Cond1 = N->getOperand(0);
7654 EVT CondVT = Cond1.getValueType();
7655 unsigned Opcode = N->getOpcode();
7656 if (CondVT.isVector()) {
7657 if (SDValue WideCond = WidenVSELECTMask(N)) {
7658 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
7659 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
7660 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
7661 return DAG.getNode(Opcode, SDLoc(N), WidenVT, WideCond, InOp1, InOp2);
7662 }
7663
7664 EVT CondEltVT = CondVT.getVectorElementType();
7665 EVT CondWidenVT = EVT::getVectorVT(*DAG.getContext(), CondEltVT, WidenEC);
7666 if (getTypeAction(CondVT) == TargetLowering::TypeWidenVector)
7667 Cond1 = GetWidenedVector(Cond1);
7668
7669 // If we have to split the condition there is no point in widening the
7670 // select. This would result in an cycle of widening the select ->
7671 // widening the condition operand -> splitting the condition operand ->
7672 // splitting the select -> widening the select. Instead split this select
7673 // further and widen the resulting type.
7674 if (getTypeAction(CondVT) == TargetLowering::TypeSplitVector) {
7675 SDValue SplitSelect = SplitVecOp_VSELECT(N, 0);
7676 SDValue Res = ModifyToType(SplitSelect, WidenVT);
7677 return Res;
7678 }
7679
7680 if (Cond1.getValueType() != CondWidenVT)
7681 Cond1 = ModifyToType(Cond1, CondWidenVT);
7682 }
7683
7684 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
7685 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
7686 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
7687 if (Opcode == ISD::VP_MERGE)
7688 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2,
7689 N->getOperand(3));
7690 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2);
7691}
7692
7693SDValue DAGTypeLegalizer::WidenVecRes_SELECT_CC(SDNode *N) {
7694 SDValue InOp1 = GetWidenedVector(N->getOperand(2));
7695 SDValue InOp2 = GetWidenedVector(N->getOperand(3));
7696 return DAG.getNode(ISD::SELECT_CC, SDLoc(N),
7697 InOp1.getValueType(), N->getOperand(0),
7698 N->getOperand(1), InOp1, InOp2, N->getOperand(4));
7699}
7700
7701SDValue DAGTypeLegalizer::WidenVecRes_UNDEF(SDNode *N) {
7702 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7703 return DAG.getUNDEF(WidenVT);
7704}
7705
7706SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N) {
7707 EVT VT = N->getValueType(0);
7708 SDLoc dl(N);
7709
7710 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7711 unsigned NumElts = VT.getVectorNumElements();
7712 unsigned WidenNumElts = WidenVT.getVectorNumElements();
7713
7714 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
7715 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
7716
7717 // Adjust mask based on new input vector length.
7718 SmallVector<int, 16> NewMask(WidenNumElts, -1);
7719 for (unsigned i = 0; i != NumElts; ++i) {
7720 int Idx = N->getMaskElt(i);
7721 if (Idx < (int)NumElts)
7722 NewMask[i] = Idx;
7723 else
7724 NewMask[i] = Idx - NumElts + WidenNumElts;
7725 }
7726 return DAG.getVectorShuffle(WidenVT, dl, InOp1, InOp2, NewMask);
7727}
7728
7729SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_REVERSE(SDNode *N) {
7730 EVT VT = N->getValueType(0);
7731 EVT EltVT = VT.getVectorElementType();
7732 SDLoc dl(N);
7733
7734 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7735 SDValue OpValue = GetWidenedVector(N->getOperand(0));
7736 assert(WidenVT == OpValue.getValueType() && "Unexpected widened vector type");
7737
7738 SDValue ReverseVal = DAG.getNode(ISD::VECTOR_REVERSE, dl, WidenVT, OpValue);
7739 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
7740 unsigned VTNumElts = VT.getVectorMinNumElements();
7741 unsigned IdxVal = WidenNumElts - VTNumElts;
7742
7743 if (VT.isScalableVector()) {
7744 // Try to split the 'Widen ReverseVal' into smaller extracts and concat the
7745 // results together, e.g.(nxv6i64 -> nxv8i64)
7746 // nxv8i64 vector_reverse
7747 // <->
7748 // nxv8i64 concat(
7749 // nxv2i64 extract_subvector(nxv8i64, 2)
7750 // nxv2i64 extract_subvector(nxv8i64, 4)
7751 // nxv2i64 extract_subvector(nxv8i64, 6)
7752 // nxv2i64 undef)
7753
7754 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
7755 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
7757 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
7758 "down type's element count");
7760 unsigned i = 0;
7761 for (; i < VTNumElts / GCD; ++i)
7762 Parts.push_back(
7763 DAG.getExtractSubvector(dl, PartVT, ReverseVal, IdxVal + i * GCD));
7764 for (; i < WidenNumElts / GCD; ++i)
7765 Parts.push_back(DAG.getPOISON(PartVT));
7766
7767 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
7768 }
7769
7770 // Use VECTOR_SHUFFLE to combine new vector from 'ReverseVal' for
7771 // fixed-vectors.
7772 SmallVector<int, 16> Mask(WidenNumElts, -1);
7773 std::iota(Mask.begin(), Mask.begin() + VTNumElts, IdxVal);
7774
7775 return DAG.getVectorShuffle(WidenVT, dl, ReverseVal, DAG.getPOISON(WidenVT),
7776 Mask);
7777}
7778
7779SDValue DAGTypeLegalizer::WidenVecRes_GET_ACTIVE_LANE_MASK(SDNode *N) {
7780 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7781 return DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, SDLoc(N), NVT, N->ops());
7782}
7783
7784void DAGTypeLegalizer::WidenVecRes_VECTOR_INTERLEAVE(SDNode *N) {
7785 EVT VT = N->getValueType(0);
7786 EVT EltVT = VT.getVectorElementType();
7787 ElementCount OrigEC = VT.getVectorElementCount();
7788 unsigned Factor = N->getNumOperands();
7789 SDLoc DL(N);
7790
7791 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7792 ElementCount WidenEC = WidenVT.getVectorElementCount();
7793
7794 SmallVector<SDValue, 8> WidenOps(Factor);
7795 for (unsigned Idx = 0U; Idx < Factor; ++Idx)
7796 WidenOps[Idx] = GetWidenedVector(N->getOperand(Idx));
7797
7798 SmallVector<EVT, 8> WidenVTs(Factor, WidenVT);
7799 SDValue Interleaved =
7800 DAG.getNode(ISD::VECTOR_INTERLEAVE, DL, WidenVTs, WidenOps);
7801
7802 EVT PackedWidenVT =
7803 EVT::getVectorVT(*DAG.getContext(), EltVT, WidenEC * Factor);
7804 SmallVector<SDValue, 8> Slices(Factor);
7805 for (unsigned Idx = 0; Idx != Factor; ++Idx)
7806 Slices[Idx] = Interleaved.getValue(Idx);
7807
7808 SDValue Packed = DAG.getNode(ISD::CONCAT_VECTORS, DL, PackedWidenVT, Slices);
7809
7810 for (unsigned Idx = 0U; Idx < Factor; ++Idx) {
7811 SDValue Narrow = DAG.getExtractSubvector(DL, VT, Packed,
7812 OrigEC.getKnownMinValue() * Idx);
7813 SDValue Wide =
7814 DAG.getInsertSubvector(DL, DAG.getPOISON(WidenVT), Narrow, /*Idx=*/0U);
7815 SetWidenedVector(SDValue(N, Idx), Wide);
7816 }
7817}
7818
7819SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_MATCH(SDNode *N) {
7820 SDLoc DL(N);
7821 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7822 EVT SourceVT = N->getOperand(0).getValueType();
7823 EVT WideSourceVT =
7824 EVT::getVectorVT(*DAG.getContext(), SourceVT.getVectorElementType(),
7825 WidenVT.getVectorElementCount());
7826
7827 SDValue WideSource = DAG.getInsertSubvector(DL, DAG.getUNDEF(WideSourceVT),
7828 N->getOperand(0), 0);
7829 SDValue WideMask = DAG.getInsertSubvector(DL, DAG.getConstant(0, DL, WidenVT),
7830 N->getOperand(2), 0);
7831 return DAG.getNode(ISD::VECTOR_MATCH, DL, WidenVT, WideSource,
7832 N->getOperand(1), WideMask, N->getFlags());
7833}
7834
7835void DAGTypeLegalizer::WidenVecRes_VECTOR_DEINTERLEAVE(SDNode *N) {
7836 EVT VT = N->getValueType(0);
7837 EVT EltVT = VT.getVectorElementType();
7838 ElementCount OrigEC = VT.getVectorElementCount();
7839 unsigned Factor = N->getNumOperands();
7840 SDLoc DL(N);
7841
7842 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7843 ElementCount WidenEC = WidenVT.getVectorElementCount();
7844 // We cannot just use the widened operands directly: since they might be
7845 // individually widened, using them directly will result in de-interleaving
7846 // the "padded" lanes that sit in the middle of the vector. Instead, we should
7847 // not concat the widened operands but the original ones to effectively
7848 // generate a "packed" concated and widened vector, before extracting new
7849 // operand vectors with the widened type.
7850 EVT PackedWidenVT =
7851 EVT::getVectorVT(*DAG.getContext(), EltVT, WidenEC * Factor);
7852 EVT ConcatVT = EVT::getVectorVT(*DAG.getContext(), EltVT, OrigEC * Factor);
7853 SDValue ConcatOp = DAG.getNode(ISD::CONCAT_VECTORS, DL, ConcatVT, N->ops());
7854 SDValue PackedWidenVec = DAG.getInsertSubvector(
7855 DL, DAG.getUNDEF(PackedWidenVT), ConcatOp, /*Idx=*/0U);
7856
7857 // Extract the new widened operand vectors.
7858 SmallVector<SDValue, 8> NewOps(Factor, SDValue());
7859 for (unsigned Idx = 0U; Idx < Factor; ++Idx) {
7860 NewOps[Idx] = DAG.getExtractSubvector(DL, WidenVT, PackedWidenVec,
7861 WidenEC.getKnownMinValue() * Idx);
7862 }
7863
7864 SmallVector<EVT, 8> NewVTs(Factor, WidenVT);
7865 SDValue NewRes = DAG.getNode(ISD::VECTOR_DEINTERLEAVE, DL, NewVTs, NewOps);
7866 // Set the widened results manually.
7867 for (unsigned Idx = 0U; Idx < Factor; ++Idx)
7868 SetWidenedVector(SDValue(N, Idx), NewRes.getValue(Idx));
7869}
7870
7871SDValue DAGTypeLegalizer::WidenVecRes_SETCC(SDNode *N) {
7872 assert(N->getValueType(0).isVector() &&
7873 N->getOperand(0).getValueType().isVector() &&
7874 "Operands must be vectors");
7875 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7876 ElementCount WidenEC = WidenVT.getVectorElementCount();
7877
7878 SDValue InOp1 = N->getOperand(0);
7879 EVT InVT = InOp1.getValueType();
7880 assert(InVT.isVector() && "can not widen non-vector type");
7881 EVT WidenInVT =
7882 EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), WidenEC);
7883
7884 // The input and output types often differ here, and it could be that while
7885 // we'd prefer to widen the result type, the input operands have been split.
7886 // In this case, we also need to split the result of this node as well.
7887 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector) {
7888 SDValue SplitVSetCC = SplitVecOp_VSETCC(N);
7889 SDValue Res = ModifyToType(SplitVSetCC, WidenVT);
7890 return Res;
7891 }
7892
7893 // If the inputs also widen, handle them directly. Otherwise widen by hand.
7894 SDValue InOp2 = N->getOperand(1);
7895 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
7896 InOp1 = GetWidenedVector(InOp1);
7897 InOp2 = GetWidenedVector(InOp2);
7898 } else {
7899 SDValue Poison = DAG.getPOISON(WidenInVT);
7900 SDValue ZeroIdx = DAG.getVectorIdxConstant(0, SDLoc(N));
7901 InOp1 = DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), WidenInVT, Poison,
7902 InOp1, ZeroIdx);
7903 InOp2 = DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), WidenInVT, Poison,
7904 InOp2, ZeroIdx);
7905 }
7906
7907 // Assume that the input and output will be widen appropriately. If not,
7908 // we will have to unroll it at some point.
7909 assert(InOp1.getValueType() == WidenInVT &&
7910 InOp2.getValueType() == WidenInVT &&
7911 "Input not widened to expected type!");
7912 (void)WidenInVT;
7913 return DAG.getNode(ISD::SETCC, SDLoc(N), WidenVT, InOp1, InOp2,
7914 N->getOperand(2));
7915}
7916
7917SDValue DAGTypeLegalizer::WidenVecRes_STRICT_FSETCC(SDNode *N) {
7918 assert(N->getValueType(0).isVector() &&
7919 N->getOperand(1).getValueType().isVector() &&
7920 "Operands must be vectors");
7921 EVT VT = N->getValueType(0);
7922 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7923 unsigned WidenNumElts = WidenVT.getVectorNumElements();
7924 unsigned NumElts = VT.getVectorNumElements();
7925 EVT EltVT = VT.getVectorElementType();
7926
7927 SDLoc dl(N);
7928 SDValue Chain = N->getOperand(0);
7929 SDValue LHS = N->getOperand(1);
7930 SDValue RHS = N->getOperand(2);
7931 SDValue CC = N->getOperand(3);
7932 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
7933
7934 // Fully unroll and reassemble.
7935 SmallVector<SDValue, 8> Scalars(WidenNumElts, DAG.getPOISON(EltVT));
7936 SmallVector<SDValue, 8> Chains(NumElts);
7937 for (unsigned i = 0; i != NumElts; ++i) {
7938 SDValue LHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, LHS, i);
7939 SDValue RHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, RHS, i);
7940
7941 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
7942 {Chain, LHSElem, RHSElem, CC});
7943 Chains[i] = Scalars[i].getValue(1);
7944 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
7945 DAG.getBoolConstant(true, dl, EltVT, VT),
7946 DAG.getBoolConstant(false, dl, EltVT, VT));
7947 }
7948
7949 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
7950 ReplaceValueWith(SDValue(N, 1), NewChain);
7951
7952 return DAG.getBuildVector(WidenVT, dl, Scalars);
7953}
7954
7955SDValue DAGTypeLegalizer::WidenVecRes_PARTIAL_REDUCE_MLA(SDNode *N) {
7956 SDLoc DL(N);
7957 EVT VT = N->getValueType(0);
7958
7959 // Expand, then widen the result.
7960 SDValue Expanded = TLI.expandPartialReduceMLA(N, DAG);
7961 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7962 return DAG.getInsertSubvector(DL, DAG.getPOISON(WideVT), Expanded, 0);
7963}
7964
7965//===----------------------------------------------------------------------===//
7966// Widen Vector Operand
7967//===----------------------------------------------------------------------===//
7968bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned OpNo) {
7969 LLVM_DEBUG(dbgs() << "Widen node operand " << OpNo << ": "; N->dump(&DAG));
7970 SDValue Res = SDValue();
7971
7972 // See if the target wants to custom widen this node.
7973 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
7974 return false;
7975
7976 switch (N->getOpcode()) {
7977 default:
7978#ifndef NDEBUG
7979 dbgs() << "WidenVectorOperand op #" << OpNo << ": ";
7980 N->dump(&DAG);
7981 dbgs() << "\n";
7982#endif
7983 report_fatal_error("do not know how to widen this operator's operand!");
7984
7985 case ISD::BITCAST: Res = WidenVecOp_BITCAST(N); break;
7986 case ISD::FAKE_USE:
7987 Res = WidenVecOp_FAKE_USE(N);
7988 break;
7989 case ISD::CONCAT_VECTORS: Res = WidenVecOp_CONCAT_VECTORS(N); break;
7990 case ISD::VECTOR_REPEAT:
7991 Res = WidenVecOp_VECTOR_REPEAT(N);
7992 break;
7993 case ISD::INSERT_SUBVECTOR: Res = WidenVecOp_INSERT_SUBVECTOR(N); break;
7994 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecOp_EXTRACT_SUBVECTOR(N); break;
7995 case ISD::EXTRACT_VECTOR_ELT: Res = WidenVecOp_EXTRACT_VECTOR_ELT(N); break;
7996 case ISD::STORE: Res = WidenVecOp_STORE(N); break;
7997 case ISD::ATOMIC_STORE:
7998 Res = WidenVecOp_ATOMIC_STORE(cast<AtomicSDNode>(N));
7999 break;
8000 case ISD::VP_STORE: Res = WidenVecOp_VP_STORE(N, OpNo); break;
8001 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
8002 Res = WidenVecOp_VP_STRIDED_STORE(N, OpNo);
8003 break;
8007 Res = WidenVecOp_EXTEND_VECTOR_INREG(N);
8008 break;
8009 case ISD::MSTORE: Res = WidenVecOp_MSTORE(N, OpNo); break;
8010 case ISD::MGATHER: Res = WidenVecOp_MGATHER(N, OpNo); break;
8011 case ISD::MSCATTER: Res = WidenVecOp_MSCATTER(N, OpNo); break;
8012 case ISD::VP_SCATTER: Res = WidenVecOp_VP_SCATTER(N, OpNo); break;
8013 case ISD::SETCC: Res = WidenVecOp_SETCC(N); break;
8014 case ISD::STRICT_FSETCC:
8015 case ISD::STRICT_FSETCCS: Res = WidenVecOp_STRICT_FSETCC(N); break;
8016 case ISD::VSELECT: Res = WidenVecOp_VSELECT(N); break;
8017 case ISD::FLDEXP:
8018 case ISD::FCOPYSIGN:
8019 case ISD::LROUND:
8020 case ISD::LLROUND:
8021 case ISD::LRINT:
8022 case ISD::LLRINT:
8023 Res = WidenVecOp_UnrollVectorOp(N);
8024 break;
8025 case ISD::IS_FPCLASS: Res = WidenVecOp_IS_FPCLASS(N); break;
8026
8027 case ISD::ANY_EXTEND:
8028 case ISD::SIGN_EXTEND:
8029 case ISD::ZERO_EXTEND:
8030 Res = WidenVecOp_EXTEND(N);
8031 break;
8032
8033 case ISD::SCMP:
8034 case ISD::UCMP:
8035 Res = WidenVecOp_CMP(N);
8036 break;
8037
8038 case ISD::FP_EXTEND:
8040 case ISD::FP_ROUND:
8042 case ISD::FP_TO_SINT:
8044 case ISD::FP_TO_UINT:
8046 case ISD::SINT_TO_FP:
8048 case ISD::UINT_TO_FP:
8050 case ISD::TRUNCATE:
8053 Res = WidenVecOp_Convert(N);
8054 break;
8055
8058 Res = WidenVecOp_FP_TO_XINT_SAT(N);
8059 break;
8060
8063 case ISD::VECREDUCE_ADD:
8064 case ISD::VECREDUCE_MUL:
8065 case ISD::VECREDUCE_AND:
8066 case ISD::VECREDUCE_OR:
8067 case ISD::VECREDUCE_XOR:
8078 Res = WidenVecOp_VECREDUCE(N);
8079 break;
8082 Res = WidenVecOp_VECREDUCE_SEQ(N);
8083 break;
8084 case ISD::VP_REDUCE_FADD:
8085 case ISD::VP_REDUCE_SEQ_FADD:
8086 case ISD::VP_REDUCE_FMUL:
8087 case ISD::VP_REDUCE_SEQ_FMUL:
8088 case ISD::VP_REDUCE_ADD:
8089 case ISD::VP_REDUCE_MUL:
8090 case ISD::VP_REDUCE_AND:
8091 case ISD::VP_REDUCE_OR:
8092 case ISD::VP_REDUCE_XOR:
8093 case ISD::VP_REDUCE_SMAX:
8094 case ISD::VP_REDUCE_SMIN:
8095 case ISD::VP_REDUCE_UMAX:
8096 case ISD::VP_REDUCE_UMIN:
8097 case ISD::VP_REDUCE_FMAX:
8098 case ISD::VP_REDUCE_FMIN:
8099 case ISD::VP_REDUCE_FMAXIMUM:
8100 case ISD::VP_REDUCE_FMINIMUM:
8101 Res = WidenVecOp_VP_REDUCE(N);
8102 break;
8103 case ISD::CTTZ_ELTS:
8105 Res = WidenVecOp_CttzElements(N);
8106 break;
8107 case ISD::VP_CTTZ_ELTS:
8108 case ISD::VP_CTTZ_ELTS_ZERO_POISON:
8109 Res = WidenVecOp_VP_CttzElements(N);
8110 break;
8112 Res = WidenVecOp_VECTOR_FIND_LAST_ACTIVE(N);
8113 break;
8114 case ISD::VECTOR_MATCH:
8115 Res = WidenVecOp_VECTOR_MATCH(N, OpNo);
8116 break;
8117 }
8118
8119 // If Res is null, the sub-method took care of registering the result.
8120 if (!Res.getNode()) return false;
8121
8122 // If the result is N, the sub-method updated N in place. Tell the legalizer
8123 // core about this.
8124 if (Res.getNode() == N)
8125 return true;
8126
8127
8128 if (N->isStrictFPOpcode())
8129 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
8130 "Invalid operand expansion");
8131 else
8132 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
8133 "Invalid operand expansion");
8134
8135 ReplaceValueWith(SDValue(N, 0), Res);
8136 return false;
8137}
8138
8139SDValue DAGTypeLegalizer::WidenVecOp_EXTEND(SDNode *N) {
8140 SDLoc DL(N);
8141 EVT VT = N->getValueType(0);
8142
8143 SDValue InOp = N->getOperand(0);
8144 assert(getTypeAction(InOp.getValueType()) ==
8146 "Unexpected type action");
8147 InOp = GetWidenedVector(InOp);
8150 "Input wasn't widened!");
8151
8152 // We may need to further widen the operand until it has the same total
8153 // vector size as the result.
8154 EVT InVT = InOp.getValueType();
8155 if (InVT.getSizeInBits() != VT.getSizeInBits()) {
8156 EVT InEltVT = InVT.getVectorElementType();
8157 for (EVT FixedVT : MVT::vector_valuetypes()) {
8158 EVT FixedEltVT = FixedVT.getVectorElementType();
8159 if (TLI.isTypeLegal(FixedVT) &&
8160 FixedVT.getSizeInBits() == VT.getSizeInBits() &&
8161 FixedEltVT == InEltVT) {
8162 assert(FixedVT.getVectorNumElements() >= VT.getVectorNumElements() &&
8163 "Not enough elements in the fixed type for the operand!");
8164 assert(FixedVT.getVectorNumElements() != InVT.getVectorNumElements() &&
8165 "We can't have the same type as we started with!");
8166 if (FixedVT.getVectorNumElements() > InVT.getVectorNumElements())
8167 InOp = DAG.getInsertSubvector(DL, DAG.getPOISON(FixedVT), InOp, 0);
8168 else
8169 InOp = DAG.getExtractSubvector(DL, FixedVT, InOp, 0);
8170 break;
8171 }
8172 }
8173 InVT = InOp.getValueType();
8174 if (InVT.getSizeInBits() != VT.getSizeInBits())
8175 // We couldn't find a legal vector type that was a widening of the input
8176 // and could be extended in-register to the result type, so we have to
8177 // scalarize.
8178 return WidenVecOp_Convert(N);
8179 }
8180
8181 // Use special DAG nodes to represent the operation of extending the
8182 // low lanes.
8183 switch (N->getOpcode()) {
8184 default:
8185 llvm_unreachable("Extend legalization on extend operation!");
8186 case ISD::ANY_EXTEND:
8187 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, VT, InOp);
8188 case ISD::SIGN_EXTEND:
8189 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, VT, InOp);
8190 case ISD::ZERO_EXTEND:
8191 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, VT, InOp);
8192 }
8193}
8194
8195SDValue DAGTypeLegalizer::WidenVecOp_CMP(SDNode *N) {
8196 SDLoc dl(N);
8197
8198 EVT OpVT = N->getOperand(0).getValueType();
8199 EVT ResVT = N->getValueType(0);
8200 SDValue LHS = GetWidenedVector(N->getOperand(0));
8201 SDValue RHS = GetWidenedVector(N->getOperand(1));
8202
8203 // 1. EXTRACT_SUBVECTOR
8204 // 2. SIGN_EXTEND/ZERO_EXTEND
8205 // 3. CMP
8206 LHS = DAG.getExtractSubvector(dl, OpVT, LHS, 0);
8207 RHS = DAG.getExtractSubvector(dl, OpVT, RHS, 0);
8208
8209 // At this point the result type is guaranteed to be valid, so we can use it
8210 // as the operand type by extending it appropriately
8211 ISD::NodeType ExtendOpcode =
8212 N->getOpcode() == ISD::SCMP ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
8213 LHS = DAG.getNode(ExtendOpcode, dl, ResVT, LHS);
8214 RHS = DAG.getNode(ExtendOpcode, dl, ResVT, RHS);
8215
8216 return DAG.getNode(N->getOpcode(), dl, ResVT, LHS, RHS);
8217}
8218
8219SDValue DAGTypeLegalizer::WidenVecOp_UnrollVectorOp(SDNode *N) {
8220 // The result (and first input) is legal, but the second input is illegal.
8221 // We can't do much to fix that, so just unroll and let the extracts off of
8222 // the second input be widened as needed later.
8223 return DAG.UnrollVectorOp(N);
8224}
8225
8226SDValue DAGTypeLegalizer::WidenVecOp_IS_FPCLASS(SDNode *N) {
8227 SDLoc DL(N);
8228 EVT ResultVT = N->getValueType(0);
8229 SDValue Test = N->getOperand(1);
8230 SDValue WideArg = GetWidenedVector(N->getOperand(0));
8231
8232 // Process this node similarly to SETCC.
8233 EVT WideResultVT = getSetCCResultType(WideArg.getValueType());
8234 if (ResultVT.getScalarType() == MVT::i1)
8235 WideResultVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8236 WideResultVT.getVectorNumElements());
8237
8238 SDValue WideNode = DAG.getNode(ISD::IS_FPCLASS, DL, WideResultVT,
8239 {WideArg, Test}, N->getFlags());
8240
8241 // Extract the needed results from the result vector.
8242 EVT ResVT =
8243 EVT::getVectorVT(*DAG.getContext(), WideResultVT.getVectorElementType(),
8244 ResultVT.getVectorNumElements());
8245 SDValue CC = DAG.getExtractSubvector(DL, ResVT, WideNode, 0);
8246
8247 EVT OpVT = N->getOperand(0).getValueType();
8248 ISD::NodeType ExtendCode =
8249 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
8250 return DAG.getNode(ExtendCode, DL, ResultVT, CC);
8251}
8252
8253SDValue DAGTypeLegalizer::WidenVecOp_Convert(SDNode *N) {
8254 // Since the result is legal and the input is illegal.
8255 EVT VT = N->getValueType(0);
8256 EVT EltVT = VT.getVectorElementType();
8257 SDLoc dl(N);
8258 SDValue InOp = N->getOperand(N->isStrictFPOpcode() ? 1 : 0);
8259 assert(getTypeAction(InOp.getValueType()) ==
8261 "Unexpected type action");
8262 InOp = GetWidenedVector(InOp);
8263 EVT InVT = InOp.getValueType();
8264 unsigned Opcode = N->getOpcode();
8265
8266 // Helper to build a convert node with all scalar trailing operands.
8267 auto MakeConvertNode = [&](EVT VT, SDValue Op) -> SDValue {
8268 if (Opcode == ISD::CONVERT_TO_ARBITRARY_FP)
8269 return DAG.getNode(Opcode, dl, VT, Op, N->getOperand(1), N->getOperand(2),
8270 N->getOperand(3));
8271 if (Opcode == ISD::FP_ROUND || Opcode == ISD::CONVERT_FROM_ARBITRARY_FP)
8272 return DAG.getNode(Opcode, dl, VT, Op, N->getOperand(1));
8273 return DAG.getNode(Opcode, dl, VT, Op);
8274 };
8275
8276 // See if a widened result type would be legal, if so widen the node.
8277 // FIXME: This isn't safe for StrictFP. Other optimization here is needed.
8278 EVT WideVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
8279 InVT.getVectorElementCount());
8280 if (TLI.isTypeLegal(WideVT) && !N->isStrictFPOpcode()) {
8281 SDValue Res;
8282 if (N->isStrictFPOpcode()) {
8283 if (Opcode == ISD::STRICT_FP_ROUND)
8284 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
8285 { N->getOperand(0), InOp, N->getOperand(2) });
8286 else
8287 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
8288 { N->getOperand(0), InOp });
8289 // Legalize the chain result - switch anything that used the old chain to
8290 // use the new one.
8291 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
8292 } else {
8293 Res = MakeConvertNode(WideVT, InOp);
8294 }
8295 return DAG.getExtractSubvector(dl, VT, Res, 0);
8296 }
8297
8298 EVT InEltVT = InVT.getVectorElementType();
8299
8300 // Unroll the convert into some scalar code and create a nasty build vector.
8301 unsigned NumElts = VT.getVectorNumElements();
8303 if (N->isStrictFPOpcode()) {
8304 SmallVector<SDValue, 4> NewOps(N->ops());
8305 SmallVector<SDValue, 32> OpChains;
8306 for (unsigned i=0; i < NumElts; ++i) {
8307 NewOps[1] = DAG.getExtractVectorElt(dl, InEltVT, InOp, i);
8308 Ops[i] = DAG.getNode(Opcode, dl, { EltVT, MVT::Other }, NewOps);
8309 OpChains.push_back(Ops[i].getValue(1));
8310 }
8311 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OpChains);
8312 ReplaceValueWith(SDValue(N, 1), NewChain);
8313 } else {
8314 for (unsigned i = 0; i < NumElts; ++i) {
8315 SDValue Elt = DAG.getExtractVectorElt(dl, InEltVT, InOp, i);
8316 Ops[i] = MakeConvertNode(EltVT, Elt);
8317 }
8318 }
8319
8320 return DAG.getBuildVector(VT, dl, Ops);
8321}
8322
8323SDValue DAGTypeLegalizer::WidenVecOp_FP_TO_XINT_SAT(SDNode *N) {
8324 EVT DstVT = N->getValueType(0);
8325 SDValue Src = GetWidenedVector(N->getOperand(0));
8326 EVT SrcVT = Src.getValueType();
8327 ElementCount WideNumElts = SrcVT.getVectorElementCount();
8328 SDLoc dl(N);
8329
8330 // See if a widened result type would be legal, if so widen the node.
8331 EVT WideDstVT = EVT::getVectorVT(*DAG.getContext(),
8332 DstVT.getVectorElementType(), WideNumElts);
8333 if (TLI.isTypeLegal(WideDstVT)) {
8334 SDValue Res =
8335 DAG.getNode(N->getOpcode(), dl, WideDstVT, Src, N->getOperand(1));
8336 return DAG.getNode(
8337 ISD::EXTRACT_SUBVECTOR, dl, DstVT, Res,
8338 DAG.getConstant(0, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
8339 }
8340
8341 // Give up and unroll.
8342 return DAG.UnrollVectorOp(N);
8343}
8344
8345SDValue DAGTypeLegalizer::WidenVecOp_BITCAST(SDNode *N) {
8346 EVT VT = N->getValueType(0);
8347 SDValue InOp = GetWidenedVector(N->getOperand(0));
8348 EVT InWidenVT = InOp.getValueType();
8349 SDLoc dl(N);
8350
8351 // Check if we can convert between two legal vector types and extract.
8352 TypeSize InWidenSize = InWidenVT.getSizeInBits();
8353 TypeSize Size = VT.getSizeInBits();
8354 // x86mmx is not an acceptable vector element type, so don't try.
8355 if (!VT.isVector() && VT != MVT::x86mmx &&
8356 InWidenSize.hasKnownScalarFactor(Size)) {
8357 unsigned NewNumElts = InWidenSize.getKnownScalarFactor(Size);
8358 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), VT, NewNumElts);
8359 if (TLI.isTypeLegal(NewVT)) {
8360 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
8361 return DAG.getExtractVectorElt(dl, VT, BitOp, 0);
8362 }
8363 }
8364
8365 // Handle a case like bitcast v12i8 -> v3i32. Normally that would get widened
8366 // to v16i8 -> v4i32, but for a target where v3i32 is legal but v12i8 is not,
8367 // we end up here. Handling the case here with EXTRACT_SUBVECTOR avoids
8368 // having to copy via memory.
8369 if (VT.isVector()) {
8370 EVT EltVT = VT.getVectorElementType();
8371 unsigned EltSize = EltVT.getFixedSizeInBits();
8372 if (InWidenSize.isKnownMultipleOf(EltSize)) {
8373 ElementCount NewNumElts =
8374 (InWidenVT.getVectorElementCount() * InWidenVT.getScalarSizeInBits())
8375 .divideCoefficientBy(EltSize);
8376 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NewNumElts);
8377 if (TLI.isTypeLegal(NewVT)) {
8378 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
8379 return DAG.getExtractSubvector(dl, VT, BitOp, 0);
8380 }
8381 }
8382 }
8383
8384 return CreateStackStoreLoad(InOp, VT);
8385}
8386
8387// Vectors with sizes that are not powers of 2 need to be widened to the
8388// next largest power of 2. For example, we may get a vector of 3 32-bit
8389// integers or of 6 16-bit integers, both of which have to be widened to a
8390// 128-bit vector.
8391SDValue DAGTypeLegalizer::WidenVecOp_FAKE_USE(SDNode *N) {
8392 SDValue WidenedOp = GetWidenedVector(N->getOperand(1));
8393 return DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, N->getOperand(0),
8394 WidenedOp);
8395}
8396
8397SDValue DAGTypeLegalizer::WidenVecOp_CONCAT_VECTORS(SDNode *N) {
8398 EVT VT = N->getValueType(0);
8399 EVT EltVT = VT.getVectorElementType();
8400 EVT InVT = N->getOperand(0).getValueType();
8401 SDLoc dl(N);
8402
8403 // If the widen width for this operand is the same as the width of the concat
8404 // and all but the first operand is undef, just use the widened operand.
8405 unsigned NumOperands = N->getNumOperands();
8406 if (VT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
8407 unsigned i;
8408 for (i = 1; i < NumOperands; ++i)
8409 if (!N->getOperand(i).isUndef())
8410 break;
8411
8412 if (i == NumOperands)
8413 return GetWidenedVector(N->getOperand(0));
8414 }
8415
8416 if (VT.isScalableVector()) {
8417 SDValue Result = DAG.getPOISON(VT);
8418 unsigned NumInElts = InVT.getVectorMinNumElements();
8419 for (unsigned i = 0; i < NumOperands; ++i) {
8420 SDValue InOp = GetWidenedVector(N->getOperand(i));
8421 if (InOp.getValueType() != InVT)
8422 InOp = DAG.getExtractSubvector(dl, InVT, InOp, 0);
8423 Result = DAG.getInsertSubvector(dl, Result, InOp, i * NumInElts);
8424 }
8425 return Result;
8426 }
8427
8428 // Otherwise, fall back to a nasty build vector.
8429 unsigned NumElts = VT.getVectorNumElements();
8431
8432 unsigned NumInElts = InVT.getVectorNumElements();
8433
8434 unsigned Idx = 0;
8435 for (unsigned i=0; i < NumOperands; ++i) {
8436 SDValue InOp = N->getOperand(i);
8437 assert(getTypeAction(InOp.getValueType()) ==
8439 "Unexpected type action");
8440 InOp = GetWidenedVector(InOp);
8441 for (unsigned j = 0; j < NumInElts; ++j)
8442 Ops[Idx++] = DAG.getExtractVectorElt(dl, EltVT, InOp, j);
8443 }
8444 return DAG.getBuildVector(VT, dl, Ops);
8445}
8446
8447SDValue DAGTypeLegalizer::WidenVecOp_VECTOR_REPEAT(SDNode *N) {
8448 SDLoc DL(N);
8449 EVT VT = N->getValueType(0);
8450 SDValue Src = N->getOperand(0);
8451 EVT SrcVT = Src.getValueType();
8452 EVT WidenedSrcVT = TLI.getTypeToTransformTo(*DAG.getContext(), SrcVT);
8453
8454 if (!WidenedSrcVT.getVectorElementCount().hasKnownScalarFactor(
8455 SrcVT.getVectorElementCount()))
8457 "Cannot widen VECTOR_REPEAT operand to an ElementCount that's not "
8458 "a known scalar multiple of the input ElementCount.");
8459
8460 // Repeat the original source because the extra lanes of its widened value
8461 // are unspecified.
8462 unsigned NumConcat =
8463 WidenedSrcVT.getVectorNumElements() / SrcVT.getVectorNumElements();
8464 SmallVector<SDValue, 8> Ops(NumConcat, Src);
8465 SDValue WidenedSrc = DAG.getNode(ISD::CONCAT_VECTORS, DL, WidenedSrcVT, Ops);
8466 EVT WidenedVT = VT.changeVectorElementCount(
8467 *DAG.getContext(),
8469 SDValue Widened = DAG.getNode(ISD::VECTOR_REPEAT, DL, WidenedVT, WidenedSrc);
8470 return DAG.getExtractSubvector(DL, VT, Widened, 0);
8471}
8472
8473SDValue DAGTypeLegalizer::WidenVecOp_INSERT_SUBVECTOR(SDNode *N) {
8474 EVT VT = N->getValueType(0);
8475 SDValue SubVec = N->getOperand(1);
8476 SDValue InVec = N->getOperand(0);
8477
8478 EVT OrigVT = SubVec.getValueType();
8479 SubVec = GetWidenedVector(SubVec);
8480 EVT SubVT = SubVec.getValueType();
8481
8482 // Whether or not all the elements of the widened SubVec will be inserted into
8483 // valid indices of VT.
8484 bool IndicesValid = false;
8485 // If we statically know that VT can fit SubVT, the indices are valid.
8486 if (VT.knownBitsGE(SubVT))
8487 IndicesValid = true;
8488 else if (VT.isScalableVector() && SubVT.isFixedLengthVector()) {
8489 // Otherwise, if we're inserting a fixed vector into a scalable vector and
8490 // we know the minimum vscale we can work out if it's valid ourselves.
8491 Attribute Attr = DAG.getMachineFunction().getFunction().getFnAttribute(
8492 Attribute::VScaleRange);
8493 if (Attr.isValid()) {
8494 unsigned VScaleMin = Attr.getVScaleRangeMin();
8495 if (VT.getSizeInBits().getKnownMinValue() * VScaleMin >=
8496 SubVT.getFixedSizeInBits())
8497 IndicesValid = true;
8498 }
8499 }
8500
8501 if (!IndicesValid)
8503 "Don't know how to widen the operands for INSERT_SUBVECTOR");
8504
8505 SDLoc DL(N);
8506
8507 // We need to make sure that the indices are still valid, otherwise we might
8508 // widen what was previously well-defined to something undefined.
8509 if (InVec.isUndef() && N->getConstantOperandVal(2) == 0)
8510 return DAG.getNode(ISD::INSERT_SUBVECTOR, DL, VT, InVec, SubVec,
8511 N->getOperand(2));
8512
8513 if (OrigVT.isScalableVector()) {
8514 // When the widened types match, overwriting the start of a vector is
8515 // effectively a merge operation that can be implement as a vselect.
8516 if (SubVT == VT && N->getConstantOperandVal(2) == 0) {
8517 SDValue Mask =
8518 DAG.getMaskFromElementCount(DL, VT, OrigVT.getVectorElementCount());
8519 return DAG.getNode(ISD::VSELECT, DL, VT, Mask, SubVec, InVec);
8520 }
8521
8522 // Fallback to inserting through memory.
8523 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
8524 SDValue StackPtr = DAG.CreateStackTemporary(VT.getStoreSize(), Alignment);
8525 MachineFunction &MF = DAG.getMachineFunction();
8526 int FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
8527 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
8528
8529 MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
8532 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
8535
8536 // Write out the vector being inserting into.
8537 SDValue Ch =
8538 DAG.getStore(DAG.getEntryNode(), DL, InVec, StackPtr, StoreMMO);
8539
8540 // Build a mask to match the length of the sub-vector.
8541 SDValue Mask =
8542 DAG.getMaskFromElementCount(DL, SubVT, OrigVT.getVectorElementCount());
8543
8544 // Overwrite the sub-vector at the required offset.
8545 SDValue SubVecPtr =
8546 TLI.getVectorSubVecPointer(DAG, StackPtr, VT, OrigVT, N->getOperand(2));
8547 Ch = DAG.getMaskedStore(Ch, DL, SubVec, SubVecPtr,
8548 DAG.getPOISON(SubVecPtr.getValueType()), Mask, VT,
8549 StoreMMO, ISD::UNINDEXED, ISD::NON_EXTLOAD);
8550
8551 // Read back the result.
8552 return DAG.getLoad(VT, DL, Ch, StackPtr, LoadMMO);
8553 }
8554
8555 // If the operands can't be widened legally, just replace the INSERT_SUBVECTOR
8556 // with a series of INSERT_VECTOR_ELT
8557 unsigned Idx = N->getConstantOperandVal(2);
8558
8559 SDValue InsertElt = InVec;
8560 for (unsigned I = 0, E = OrigVT.getVectorNumElements(); I != E; ++I) {
8561 SDValue ExtractElt =
8562 DAG.getExtractVectorElt(DL, VT.getVectorElementType(), SubVec, I);
8563 InsertElt = DAG.getInsertVectorElt(DL, InsertElt, ExtractElt, I + Idx);
8564 }
8565
8566 return InsertElt;
8567}
8568
8569SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
8570 SDValue InOp = GetWidenedVector(N->getOperand(0));
8571 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SDLoc(N),
8572 N->getValueType(0), InOp, N->getOperand(1));
8573}
8574
8575SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
8576 SDValue InOp = GetWidenedVector(N->getOperand(0));
8577 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
8578 N->getValueType(0), InOp, N->getOperand(1));
8579}
8580
8581SDValue DAGTypeLegalizer::WidenVecOp_EXTEND_VECTOR_INREG(SDNode *N) {
8582 SDLoc DL(N);
8583 EVT ResVT = N->getValueType(0);
8584
8585 // Widen the input as requested by the legalizer.
8586 SDValue WideInOp = GetWidenedVector(N->getOperand(0));
8587 EVT WideInVT = WideInOp.getValueType();
8588
8589 // Simple case: if widened input is still smaller than or equal to result,
8590 // just use it directly.
8591 if (WideInVT.getSizeInBits() <= ResVT.getSizeInBits())
8592 return DAG.getNode(N->getOpcode(), DL, ResVT, WideInOp);
8593
8594 // EXTEND_VECTOR_INREG requires input bits <= result bits.
8595 // If widening makes the input larger than the original result, widen the
8596 // result to match, then extract back down.
8597 EVT ResEltVT = ResVT.getVectorElementType();
8598 unsigned EltBits = ResEltVT.getSizeInBits();
8599 assert((WideInVT.getSizeInBits() % EltBits) == 0 &&
8600 "Widened input size must be a multiple of result element size");
8601
8602 unsigned WideNumElts = WideInVT.getSizeInBits() / EltBits;
8603 EVT WideResVT = EVT::getVectorVT(*DAG.getContext(), ResEltVT, WideNumElts);
8604
8605 SDValue WideRes = DAG.getNode(N->getOpcode(), DL, WideResVT, WideInOp);
8606 return DAG.getExtractSubvector(DL, ResVT, WideRes, 0);
8607}
8608
8609SDValue DAGTypeLegalizer::WidenVecOp_STORE(SDNode *N) {
8610 // We have to widen the value, but we want only to store the original
8611 // vector type.
8612 StoreSDNode *ST = cast<StoreSDNode>(N);
8613
8614 if (!ST->getMemoryVT().getScalarType().isByteSized())
8615 return TLI.scalarizeVectorStore(ST, DAG);
8616
8617 if (ST->isTruncatingStore())
8618 return TLI.scalarizeVectorStore(ST, DAG);
8619
8620 // Generate a vector-predicated store if it is custom/legal on the target.
8621 // To avoid possible recursion, only do this if the widened mask type is
8622 // legal.
8623 // FIXME: Not all targets may support EVL in VP_STORE. These will have been
8624 // removed from the IR by the ExpandVectorPredication pass but we're
8625 // reintroducing them here.
8626 SDValue StVal = ST->getValue();
8627 EVT StVT = StVal.getValueType();
8628 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), StVT);
8629 EVT WideMaskVT = getSetCCResultType(WideVT);
8630
8631 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
8632 TLI.isTypeLegal(WideMaskVT)) {
8633 // Widen the value.
8634 SDLoc DL(N);
8635 StVal = GetWidenedVector(StVal);
8636 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
8637 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
8638 StVT.getVectorElementCount());
8639 return DAG.getStoreVP(ST->getChain(), DL, StVal, ST->getBasePtr(),
8640 ST->getOffset(), Mask, EVL, StVT, ST->getMemOperand(),
8641 ST->getAddressingMode());
8642 }
8643
8645 if (GenWidenVectorStores(StChain, ST)) {
8646 if (StChain.size() == 1)
8647 return StChain[0];
8648
8649 return DAG.getNode(ISD::TokenFactor, SDLoc(ST), MVT::Other, StChain);
8650 }
8651
8652 if (StVT.isVector()) {
8653 // If all else fails replace the store with a wide masked store.
8654 SDLoc DL(N);
8655 SDValue WideStVal = GetWidenedVector(StVal);
8656 SDValue Mask =
8657 DAG.getMaskFromElementCount(DL, WideVT, StVT.getVectorElementCount());
8658
8659 return DAG.getMaskedStore(ST->getChain(), DL, WideStVal, ST->getBasePtr(),
8660 ST->getOffset(), Mask, ST->getMemoryVT(),
8661 ST->getMemOperand(), ST->getAddressingMode(),
8662 ST->isTruncatingStore());
8663 }
8664
8665 report_fatal_error("Unable to widen vector store");
8666}
8667
8668SDValue DAGTypeLegalizer::WidenVecOp_ATOMIC_STORE(AtomicSDNode *ST) {
8669 EVT StVT = ST->getMemoryVT();
8670 SDLoc dl(ST);
8671
8672 SDValue StVal = GetWidenedVector(ST->getVal());
8673 EVT WidenVT = StVal.getValueType();
8674
8675 TypeSize StWidth = StVT.getSizeInBits();
8676 TypeSize WidenWidth = WidenVT.getSizeInBits();
8677 TypeSize WidthDiff = WidenWidth - StWidth;
8678
8679 // Find the vector type that can store the original memory width in one
8680 // atomic operation. Pass StAlign=0 (like atomic loads); a real align would
8681 // let findMemType widen the access past the value (e.g. <2 x i8> at align 4
8682 // implies a 4-byte movl, writing undef bytes past its object).
8683 std::optional<EVT> FirstVT =
8684 findMemType(DAG, TLI, StWidth.getKnownMinValue(), WidenVT, /*StAlign=*/0,
8685 WidthDiff.getKnownMinValue());
8686 if (!FirstVT)
8687 return SDValue();
8688
8689 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
8690
8691 SDValue StOp =
8692 coerceStoredValue(StVal, *FirstVT, WidenVT, FirstVTWidth, dl, DAG);
8693
8694 return DAG.getAtomic(ISD::ATOMIC_STORE, dl, *FirstVT, ST->getChain(), StOp,
8695 ST->getBasePtr(), ST->getMemOperand());
8696}
8697
8698SDValue DAGTypeLegalizer::WidenVecOp_VP_STORE(SDNode *N, unsigned OpNo) {
8699 assert((OpNo == 1 || OpNo == 3) &&
8700 "Can widen only data or mask operand of vp_store");
8701 VPStoreSDNode *ST = cast<VPStoreSDNode>(N);
8702 SDValue Mask = ST->getMask();
8703 SDValue StVal = ST->getValue();
8704 SDLoc dl(N);
8705
8706 if (OpNo == 1) {
8707 // Widen the value.
8708 StVal = GetWidenedVector(StVal);
8709
8710 // We only handle the case where the mask needs widening to an
8711 // identically-sized type as the vector inputs.
8712 assert(getTypeAction(Mask.getValueType()) ==
8714 "Unable to widen VP store");
8715 Mask = GetWidenedVector(Mask);
8716 } else {
8717 Mask = GetWidenedVector(Mask);
8718
8719 // We only handle the case where the stored value needs widening to an
8720 // identically-sized type as the mask.
8721 assert(getTypeAction(StVal.getValueType()) ==
8723 "Unable to widen VP store");
8724 StVal = GetWidenedVector(StVal);
8725 }
8726
8727 assert(Mask.getValueType().getVectorElementCount() ==
8729 "Mask and data vectors should have the same number of elements");
8730 return DAG.getStoreVP(ST->getChain(), dl, StVal, ST->getBasePtr(),
8731 ST->getOffset(), Mask, ST->getVectorLength(),
8732 ST->getMemoryVT(), ST->getMemOperand(),
8733 ST->getAddressingMode(), ST->isTruncatingStore(),
8734 ST->isCompressingStore());
8735}
8736
8737SDValue DAGTypeLegalizer::WidenVecOp_VP_STRIDED_STORE(SDNode *N,
8738 unsigned OpNo) {
8739 assert((OpNo == 1 || OpNo == 4) &&
8740 "Can widen only data or mask operand of vp_strided_store");
8741 VPStridedStoreSDNode *SST = cast<VPStridedStoreSDNode>(N);
8742 SDValue Mask = SST->getMask();
8743 SDValue StVal = SST->getValue();
8744 SDLoc DL(N);
8745
8746 if (OpNo == 1)
8747 assert(getTypeAction(Mask.getValueType()) ==
8749 "Unable to widen VP strided store");
8750 else
8751 assert(getTypeAction(StVal.getValueType()) ==
8753 "Unable to widen VP strided store");
8754
8755 StVal = GetWidenedVector(StVal);
8756 Mask = GetWidenedVector(Mask);
8757
8759 Mask.getValueType().getVectorElementCount() &&
8760 "Data and mask vectors should have the same number of elements");
8761
8762 return DAG.getStridedStoreVP(
8763 SST->getChain(), DL, StVal, SST->getBasePtr(), SST->getOffset(),
8764 SST->getStride(), Mask, SST->getVectorLength(), SST->getMemoryVT(),
8765 SST->getMemOperand(), SST->getAddressingMode(), SST->isTruncatingStore(),
8766 SST->isCompressingStore());
8767}
8768
8769SDValue DAGTypeLegalizer::WidenVecOp_MSTORE(SDNode *N, unsigned OpNo) {
8770 assert((OpNo == 1 || OpNo == 4) &&
8771 "Can widen only data or mask operand of mstore");
8772 MaskedStoreSDNode *MST = cast<MaskedStoreSDNode>(N);
8773 SDValue Mask = MST->getMask();
8774 EVT MaskVT = Mask.getValueType();
8775 SDValue StVal = MST->getValue();
8776 EVT VT = StVal.getValueType();
8777 SDLoc dl(N);
8778
8779 EVT WideVT, WideMaskVT;
8780 if (OpNo == 1) {
8781 // Widen the value.
8782 StVal = GetWidenedVector(StVal);
8783
8784 WideVT = StVal.getValueType();
8785 WideMaskVT =
8786 EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(),
8787 WideVT.getVectorElementCount());
8788 } else {
8789 WideMaskVT = TLI.getTypeToTransformTo(*DAG.getContext(), MaskVT);
8790
8791 EVT ValueVT = StVal.getValueType();
8792 WideVT = EVT::getVectorVT(*DAG.getContext(), ValueVT.getVectorElementType(),
8793 WideMaskVT.getVectorElementCount());
8794 }
8795
8796 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
8797 TLI.isTypeLegal(WideMaskVT) && !MST->isCompressingStore()) {
8798 Mask = DAG.getInsertSubvector(dl, DAG.getPOISON(WideMaskVT), Mask, 0);
8799 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8801 return DAG.getStoreVP(MST->getChain(), dl, StVal, MST->getBasePtr(),
8802 MST->getOffset(), Mask, EVL, MST->getMemoryVT(),
8803 MST->getMemOperand(), MST->getAddressingMode());
8804 }
8805
8806 if (OpNo == 1) {
8807 // The mask should be widened as well.
8808 Mask = ModifyToType(Mask, WideMaskVT, true);
8809 } else {
8810 // Widen the mask.
8811 Mask = ModifyToType(Mask, WideMaskVT, true);
8812
8813 StVal = ModifyToType(StVal, WideVT);
8814 }
8815
8816 assert(Mask.getValueType().getVectorElementCount() ==
8818 "Mask and data vectors should have the same number of elements");
8819 return DAG.getMaskedStore(MST->getChain(), dl, StVal, MST->getBasePtr(),
8820 MST->getOffset(), Mask, MST->getMemoryVT(),
8821 MST->getMemOperand(), MST->getAddressingMode(),
8822 false, MST->isCompressingStore());
8823}
8824
8825SDValue DAGTypeLegalizer::WidenVecOp_MGATHER(SDNode *N, unsigned OpNo) {
8826 assert(OpNo == 4 && "Can widen only the index of mgather");
8827 auto *MG = cast<MaskedGatherSDNode>(N);
8828 SDValue DataOp = MG->getPassThru();
8829 SDValue Mask = MG->getMask();
8830 SDValue Scale = MG->getScale();
8831
8832 // Just widen the index. It's allowed to have extra elements.
8833 SDValue Index = GetWidenedVector(MG->getIndex());
8834
8835 SDLoc dl(N);
8836 SDValue Ops[] = {MG->getChain(), DataOp, Mask, MG->getBasePtr(), Index,
8837 Scale};
8838 SDValue Res = DAG.getMaskedGather(MG->getVTList(), MG->getMemoryVT(), dl, Ops,
8839 MG->getMemOperand(), MG->getIndexType(),
8840 MG->getExtensionType());
8841 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
8842 ReplaceValueWith(SDValue(N, 0), Res.getValue(0));
8843 return SDValue();
8844}
8845
8846SDValue DAGTypeLegalizer::WidenVecOp_MSCATTER(SDNode *N, unsigned OpNo) {
8847 MaskedScatterSDNode *MSC = cast<MaskedScatterSDNode>(N);
8848 SDValue DataOp = MSC->getValue();
8849 SDValue Mask = MSC->getMask();
8850 SDValue Index = MSC->getIndex();
8851 SDValue Scale = MSC->getScale();
8852 EVT WideMemVT = MSC->getMemoryVT();
8853
8854 if (OpNo == 1) {
8855 DataOp = GetWidenedVector(DataOp);
8856 ElementCount WideEC = DataOp.getValueType().getVectorElementCount();
8857
8858 // Widen index.
8859 EVT IndexVT = Index.getValueType();
8860 EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
8861 IndexVT.getVectorElementType(), WideEC);
8862 Index = ModifyToType(Index, WideIndexVT);
8863
8864 // The mask should be widened as well.
8865 EVT MaskVT = Mask.getValueType();
8866 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
8867 MaskVT.getVectorElementType(), WideEC);
8868 Mask = ModifyToType(Mask, WideMaskVT, true);
8869
8870 // Widen the MemoryType
8871 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
8872 MSC->getMemoryVT().getScalarType(), WideEC);
8873 } else if (OpNo == 4) {
8874 // Just widen the index. It's allowed to have extra elements.
8875 Index = GetWidenedVector(Index);
8876 } else
8877 llvm_unreachable("Can't widen this operand of mscatter");
8878
8879 SDValue Ops[] = {MSC->getChain(), DataOp, Mask, MSC->getBasePtr(), Index,
8880 Scale};
8881 return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N),
8882 Ops, MSC->getMemOperand(), MSC->getIndexType(),
8883 MSC->isTruncatingStore());
8884}
8885
8886SDValue DAGTypeLegalizer::WidenVecOp_VP_SCATTER(SDNode *N, unsigned OpNo) {
8887 VPScatterSDNode *VPSC = cast<VPScatterSDNode>(N);
8888 SDValue DataOp = VPSC->getValue();
8889 SDValue Mask = VPSC->getMask();
8890 SDValue Index = VPSC->getIndex();
8891 SDValue Scale = VPSC->getScale();
8892 EVT WideMemVT = VPSC->getMemoryVT();
8893
8894 if (OpNo == 1) {
8895 DataOp = GetWidenedVector(DataOp);
8896 Index = GetWidenedVector(Index);
8897 const auto WideEC = DataOp.getValueType().getVectorElementCount();
8898 Mask = GetWidenedMask(Mask, WideEC);
8899 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
8900 VPSC->getMemoryVT().getScalarType(), WideEC);
8901 } else if (OpNo == 3) {
8902 // Just widen the index. It's allowed to have extra elements.
8903 Index = GetWidenedVector(Index);
8904 } else
8905 llvm_unreachable("Can't widen this operand of VP_SCATTER");
8906
8907 SDValue Ops[] = {
8908 VPSC->getChain(), DataOp, VPSC->getBasePtr(), Index, Scale, Mask,
8909 VPSC->getVectorLength()};
8910 return DAG.getScatterVP(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N), Ops,
8911 VPSC->getMemOperand(), VPSC->getIndexType());
8912}
8913
8914SDValue DAGTypeLegalizer::WidenVecOp_SETCC(SDNode *N) {
8915 SDValue InOp0 = GetWidenedVector(N->getOperand(0));
8916 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
8917 SDLoc dl(N);
8918 EVT VT = N->getValueType(0);
8919
8920 // WARNING: In this code we widen the compare instruction with garbage.
8921 // This garbage may contain denormal floats which may be slow. Is this a real
8922 // concern ? Should we zero the unused lanes if this is a float compare ?
8923
8924 // Get a new SETCC node to compare the newly widened operands.
8925 // Only some of the compared elements are legal.
8926 EVT SVT = getSetCCResultType(InOp0.getValueType());
8927 // The result type is legal, if its vXi1, keep vXi1 for the new SETCC.
8928 if (VT.getScalarType() == MVT::i1)
8929 SVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8930 SVT.getVectorElementCount());
8931
8932 SDValue WideSETCC = DAG.getNode(ISD::SETCC, SDLoc(N),
8933 SVT, InOp0, InOp1, N->getOperand(2));
8934
8935 // Extract the needed results from the result vector.
8936 EVT ResVT = EVT::getVectorVT(*DAG.getContext(),
8939 SDValue CC = DAG.getExtractSubvector(dl, ResVT, WideSETCC, 0);
8940
8941 EVT OpVT = N->getOperand(0).getValueType();
8942 ISD::NodeType ExtendCode =
8943 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
8944 return DAG.getNode(ExtendCode, dl, VT, CC);
8945}
8946
8947SDValue DAGTypeLegalizer::WidenVecOp_STRICT_FSETCC(SDNode *N) {
8948 SDValue Chain = N->getOperand(0);
8949 SDValue LHS = GetWidenedVector(N->getOperand(1));
8950 SDValue RHS = GetWidenedVector(N->getOperand(2));
8951 SDValue CC = N->getOperand(3);
8952 SDLoc dl(N);
8953
8954 EVT VT = N->getValueType(0);
8955 EVT EltVT = VT.getVectorElementType();
8956 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
8957 unsigned NumElts = VT.getVectorNumElements();
8958
8959 // Unroll into a build vector.
8960 SmallVector<SDValue, 8> Scalars(NumElts);
8961 SmallVector<SDValue, 8> Chains(NumElts);
8962
8963 for (unsigned i = 0; i != NumElts; ++i) {
8964 SDValue LHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, LHS, i);
8965 SDValue RHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, RHS, i);
8966
8967 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
8968 {Chain, LHSElem, RHSElem, CC});
8969 Chains[i] = Scalars[i].getValue(1);
8970 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
8971 DAG.getBoolConstant(true, dl, EltVT, VT),
8972 DAG.getBoolConstant(false, dl, EltVT, VT));
8973 }
8974
8975 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
8976 ReplaceValueWith(SDValue(N, 1), NewChain);
8977
8978 return DAG.getBuildVector(VT, dl, Scalars);
8979}
8980
8981static unsigned getExtendForIntVecReduction(unsigned Opc) {
8982 switch (Opc) {
8983 default:
8984 llvm_unreachable("Expected integer vector reduction");
8985 case ISD::VECREDUCE_ADD:
8986 case ISD::VECREDUCE_MUL:
8987 case ISD::VECREDUCE_AND:
8988 case ISD::VECREDUCE_OR:
8989 case ISD::VECREDUCE_XOR:
8990 return ISD::ANY_EXTEND;
8993 return ISD::SIGN_EXTEND;
8996 return ISD::ZERO_EXTEND;
8997 }
8998}
8999
9000SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE(SDNode *N) {
9001 SDLoc dl(N);
9002 SDValue Op = GetWidenedVector(N->getOperand(0));
9003 EVT VT = N->getValueType(0);
9004 EVT OrigVT = N->getOperand(0).getValueType();
9005 EVT WideVT = Op.getValueType();
9006 EVT ElemVT = OrigVT.getVectorElementType();
9007 SDNodeFlags Flags = N->getFlags();
9008
9009 unsigned Opc = N->getOpcode();
9010 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
9011 SDValue NeutralElem = DAG.getIdentityElement(BaseOpc, dl, ElemVT, Flags);
9012 assert(NeutralElem && "Neutral element must exist");
9013
9014 // Pad the vector with the neutral element.
9015 unsigned OrigElts = OrigVT.getVectorMinNumElements();
9016 unsigned WideElts = WideVT.getVectorMinNumElements();
9017
9018 // Generate a vp.reduce_op if it is custom/legal for the target. This avoids
9019 // needing to pad the source vector, because the inactive lanes can simply be
9020 // disabled and not contribute to the result.
9021 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opc);
9022 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WideVT)) {
9023 SDValue Start = NeutralElem;
9024 if (VT.isInteger())
9025 Start = DAG.getNode(getExtendForIntVecReduction(Opc), dl, VT, Start);
9026 assert(Start.getValueType() == VT);
9027 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
9028 WideVT.getVectorElementCount());
9029 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
9030 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
9031 OrigVT.getVectorElementCount());
9032 return DAG.getNode(*VPOpcode, dl, VT, {Start, Op, Mask, EVL}, Flags);
9033 }
9034
9035 if (WideVT.isScalableVector()) {
9036 unsigned GCD = std::gcd(OrigElts, WideElts);
9037 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
9039 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
9040 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
9041 Op = DAG.getInsertSubvector(dl, Op, SplatNeutral, Idx);
9042 return DAG.getNode(Opc, dl, VT, Op, Flags);
9043 }
9044
9045 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
9046 Op = DAG.getInsertVectorElt(dl, Op, NeutralElem, Idx);
9047
9048 return DAG.getNode(Opc, dl, VT, Op, Flags);
9049}
9050
9051SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE_SEQ(SDNode *N) {
9052 SDLoc dl(N);
9053 SDValue AccOp = N->getOperand(0);
9054 SDValue VecOp = N->getOperand(1);
9055 SDValue Op = GetWidenedVector(VecOp);
9056
9057 EVT VT = N->getValueType(0);
9058 EVT OrigVT = VecOp.getValueType();
9059 EVT WideVT = Op.getValueType();
9060 EVT ElemVT = OrigVT.getVectorElementType();
9061 SDNodeFlags Flags = N->getFlags();
9062
9063 unsigned Opc = N->getOpcode();
9064 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
9065 SDValue NeutralElem = DAG.getIdentityElement(BaseOpc, dl, ElemVT, Flags);
9066
9067 // Pad the vector with the neutral element.
9068 unsigned OrigElts = OrigVT.getVectorMinNumElements();
9069 unsigned WideElts = WideVT.getVectorMinNumElements();
9070
9071 // Generate a vp.reduce_op if it is custom/legal for the target. This avoids
9072 // needing to pad the source vector, because the inactive lanes can simply be
9073 // disabled and not contribute to the result.
9074 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opc);
9075 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WideVT)) {
9076 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
9077 WideVT.getVectorElementCount());
9078 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
9079 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
9080 OrigVT.getVectorElementCount());
9081 return DAG.getNode(*VPOpcode, dl, VT, {AccOp, Op, Mask, EVL}, Flags);
9082 }
9083
9084 if (WideVT.isScalableVector()) {
9085 unsigned GCD = std::gcd(OrigElts, WideElts);
9086 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
9088 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
9089 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
9090 Op = DAG.getInsertSubvector(dl, Op, SplatNeutral, Idx);
9091 return DAG.getNode(Opc, dl, VT, AccOp, Op, Flags);
9092 }
9093
9094 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
9095 Op = DAG.getInsertVectorElt(dl, Op, NeutralElem, Idx);
9096
9097 return DAG.getNode(Opc, dl, VT, AccOp, Op, Flags);
9098}
9099
9100SDValue DAGTypeLegalizer::WidenVecOp_VP_REDUCE(SDNode *N) {
9101 assert(N->isVPOpcode() && "Expected VP opcode");
9102
9103 SDLoc dl(N);
9104 SDValue Op = GetWidenedVector(N->getOperand(1));
9105 SDValue Mask = GetWidenedMask(N->getOperand(2),
9106 Op.getValueType().getVectorElementCount());
9107
9108 return DAG.getNode(N->getOpcode(), dl, N->getValueType(0),
9109 {N->getOperand(0), Op, Mask, N->getOperand(3)},
9110 N->getFlags());
9111}
9112
9113SDValue DAGTypeLegalizer::WidenVecOp_VSELECT(SDNode *N) {
9114 // This only gets called in the case that the left and right inputs and
9115 // result are of a legal odd vector type, and the condition is illegal i1 of
9116 // the same odd width that needs widening.
9117 EVT VT = N->getValueType(0);
9118 assert(VT.isVector() && !VT.isPow2VectorType() && isTypeLegal(VT));
9119
9120 SDValue Cond = GetWidenedVector(N->getOperand(0));
9121 SDValue LeftIn = DAG.WidenVector(N->getOperand(1), SDLoc(N));
9122 SDValue RightIn = DAG.WidenVector(N->getOperand(2), SDLoc(N));
9123 SDLoc DL(N);
9124
9125 SDValue Select = DAG.getNode(N->getOpcode(), DL, LeftIn.getValueType(), Cond,
9126 LeftIn, RightIn);
9127 return DAG.getExtractSubvector(DL, VT, Select, 0);
9128}
9129
9130SDValue DAGTypeLegalizer::WidenVecOp_CttzElements(SDNode *N) {
9131 SDLoc DL(N);
9132 SDValue Source = N->getOperand(0);
9133 EVT SourceVT = Source.getValueType();
9134 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), SourceVT);
9135
9136 SDValue WideSource;
9137 if (N->getOpcode() == ISD::CTTZ_ELTS_ZERO_POISON) {
9138 WideSource = GetWidenedVector(Source);
9139 } else {
9140 // Pad the widened portion with all-ones so the extra lanes appear as
9141 // active (non-zero) elements and do not contribute trailing zeros.
9142 SDValue AllOnes = DAG.getAllOnesConstant(DL, WideVT);
9143 if (WideVT.isFixedLengthVector() &&
9144 getTypeAction(WideVT) == TargetLowering::TypeSplitVector) {
9145 WideSource = GetWidenedVector(Source);
9146 unsigned WideElts = WideVT.getVectorNumElements();
9147 SmallVector<int> Mask(WideElts);
9148 std::iota(Mask.begin(), Mask.end(), 0);
9149 for (unsigned I = SourceVT.getVectorNumElements(); I != WideElts; ++I)
9150 Mask[I] += WideElts;
9151 WideSource = DAG.getVectorShuffle(WideVT, DL, WideSource, AllOnes, Mask);
9152 } else {
9153 WideSource = DAG.getInsertSubvector(DL, AllOnes, Source, 0);
9154 }
9155 }
9156
9157 return DAG.getNode(N->getOpcode(), DL, N->getValueType(0), WideSource,
9158 N->getFlags());
9159}
9160
9161SDValue DAGTypeLegalizer::WidenVecOp_VP_CttzElements(SDNode *N) {
9162 SDLoc DL(N);
9163 SDValue Source = GetWidenedVector(N->getOperand(0));
9164 EVT SrcVT = Source.getValueType();
9165 SDValue Mask =
9166 GetWidenedMask(N->getOperand(1), SrcVT.getVectorElementCount());
9167
9168 return DAG.getNode(N->getOpcode(), DL, N->getValueType(0),
9169 {Source, Mask, N->getOperand(2)}, N->getFlags());
9170}
9171
9172SDValue DAGTypeLegalizer::WidenVecOp_VECTOR_FIND_LAST_ACTIVE(SDNode *N) {
9173 SDLoc DL(N);
9174 SDValue Mask = N->getOperand(0);
9175 EVT OrigMaskVT = Mask.getValueType();
9176 SDValue WideMask = GetWidenedVector(Mask);
9177 EVT WideMaskVT = WideMask.getValueType();
9178
9179 // Pad the mask with zeros to ensure inactive lanes don't affect the result.
9180 unsigned OrigElts = OrigMaskVT.getVectorNumElements();
9181 unsigned WideElts = WideMaskVT.getVectorNumElements();
9182 if (OrigElts != WideElts) {
9183 SDValue ZeroMask = DAG.getConstant(0, DL, WideMaskVT);
9184 WideMask = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideMaskVT, ZeroMask,
9185 Mask, DAG.getVectorIdxConstant(0, DL));
9186 }
9187
9188 return DAG.getNode(ISD::VECTOR_FIND_LAST_ACTIVE, DL, N->getValueType(0),
9189 WideMask);
9190}
9191
9192SDValue DAGTypeLegalizer::WidenVecOp_VECTOR_MATCH(SDNode *N, unsigned OpNo) {
9193 if (OpNo == 0) {
9194 SDLoc DL(N);
9195 EVT ResVT = N->getValueType(0);
9196 EVT SourceVT = N->getOperand(0).getValueType();
9197 EVT WideSourceVT = TLI.getTypeToTransformTo(*DAG.getContext(), SourceVT);
9198 EVT WidenVT =
9199 EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
9200 WideSourceVT.getVectorElementCount());
9201
9202 SDValue WideSource = DAG.getInsertSubvector(DL, DAG.getUNDEF(WideSourceVT),
9203 N->getOperand(0), 0);
9204 SDValue WideMask = DAG.getInsertSubvector(
9205 DL, DAG.getConstant(0, DL, WidenVT), N->getOperand(2), 0);
9206 SDValue WideMatch = DAG.getNode(ISD::VECTOR_MATCH, DL, WidenVT, WideSource,
9207 N->getOperand(1), WideMask, N->getFlags());
9208 return DAG.getExtractSubvector(DL, ResVT, WideMatch, 0);
9209 }
9210
9211 // Note: The Mask (OpNo == 2) should be widened with the result.
9212 assert(OpNo == 1 && "Unexpected VECTOR_MATCH operand");
9213
9214 SDLoc DL(N);
9215 SDValue Needle = N->getOperand(1);
9216 EVT NeedleVT = Needle.getValueType();
9217 if (NeedleVT.getVectorNumElements() == 1)
9218 return TLI.expandVectorMatch(N, DAG);
9219
9220 EVT WidenNeedleVT = TLI.getTypeToTransformTo(*DAG.getContext(), NeedleVT);
9221
9222 SDValue Fill =
9223 DAG.getExtractVectorElt(DL, NeedleVT.getVectorElementType(), Needle, 0);
9224 SDValue WideNeedle = DAG.getSplatVector(WidenNeedleVT, DL, Fill);
9225 WideNeedle = DAG.getInsertSubvector(DL, WideNeedle, Needle, 0);
9226
9227 return DAG.getNode(ISD::VECTOR_MATCH, DL, N->getValueType(0),
9228 N->getOperand(0), WideNeedle, N->getOperand(2),
9229 N->getFlags());
9230}
9231
9232//===----------------------------------------------------------------------===//
9233// Vector Widening Utilities
9234//===----------------------------------------------------------------------===//
9235
9236// Utility function to find the type to chop up a widen vector for load/store
9237// TLI: Target lowering used to determine legal types.
9238// Width: Width left need to load/store.
9239// WidenVT: The widen vector type to load to/store from
9240// Align: If 0, don't allow use of a wider type
9241// WidenEx: If Align is not 0, the amount additional we can load/store from.
9242
9243static std::optional<EVT> findMemType(SelectionDAG &DAG,
9244 const TargetLowering &TLI, unsigned Width,
9245 EVT WidenVT, unsigned Align = 0,
9246 unsigned WidenEx = 0) {
9247 EVT WidenEltVT = WidenVT.getVectorElementType();
9248 const bool Scalable = WidenVT.isScalableVector();
9249 unsigned WidenWidth = WidenVT.getSizeInBits().getKnownMinValue();
9250 unsigned WidenEltWidth = WidenEltVT.getSizeInBits();
9251 unsigned AlignInBits = Align*8;
9252
9253 EVT RetVT = WidenEltVT;
9254 // Don't bother looking for an integer type if the vector is scalable, skip
9255 // to vector types.
9256 if (!Scalable) {
9257 // If we have one element to load/store, return it.
9258 if (Width == WidenEltWidth)
9259 return RetVT;
9260
9261 // See if there is larger legal integer than the element type to load/store.
9262 for (EVT MemVT : reverse(MVT::integer_valuetypes())) {
9263 unsigned MemVTWidth = MemVT.getSizeInBits();
9264 if (MemVT.getSizeInBits() <= WidenEltWidth)
9265 break;
9266 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
9267 if ((Action == TargetLowering::TypeLegal ||
9269 (WidenWidth % MemVTWidth) == 0 &&
9270 isPowerOf2_32(WidenWidth / MemVTWidth) &&
9271 (MemVTWidth <= Width ||
9272 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
9273 if (MemVTWidth == WidenWidth)
9274 return MemVT;
9275 RetVT = MemVT;
9276 break;
9277 }
9278 }
9279 }
9280
9281 // See if there is a larger vector type to load/store that has the same vector
9282 // element type and is evenly divisible with the WidenVT.
9283 for (EVT MemVT : reverse(MVT::vector_valuetypes())) {
9284 // Skip vector MVTs which don't match the scalable property of WidenVT.
9285 if (Scalable != MemVT.isScalableVector())
9286 continue;
9287 unsigned MemVTWidth = MemVT.getSizeInBits().getKnownMinValue();
9288 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
9289 if ((Action == TargetLowering::TypeLegal ||
9291 WidenEltVT == MemVT.getVectorElementType() &&
9292 (WidenWidth % MemVTWidth) == 0 &&
9293 isPowerOf2_32(WidenWidth / MemVTWidth) &&
9294 (MemVTWidth <= Width ||
9295 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
9296 if (RetVT.getFixedSizeInBits() < MemVTWidth || MemVT == WidenVT)
9297 return MemVT;
9298 }
9299 }
9300
9301 // Using element-wise loads and stores for widening operations is not
9302 // supported for scalable vectors
9303 if (Scalable)
9304 return std::nullopt;
9305
9306 return RetVT;
9307}
9308
9309// Builds a vector type from scalar loads
9310// VecTy: Resulting Vector type
9311// LDOps: Load operators to build a vector type
9312// [Start,End) the list of loads to use.
9315 unsigned Start, unsigned End) {
9316 SDLoc dl(LdOps[Start]);
9317 EVT LdTy = LdOps[Start].getValueType();
9318 unsigned Width = VecTy.getSizeInBits();
9319 unsigned NumElts = Width / LdTy.getSizeInBits();
9320 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), LdTy, NumElts);
9321
9322 unsigned Idx = 1;
9323 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT,LdOps[Start]);
9324
9325 for (unsigned i = Start + 1; i != End; ++i) {
9326 EVT NewLdTy = LdOps[i].getValueType();
9327 if (NewLdTy != LdTy) {
9328 NumElts = Width / NewLdTy.getSizeInBits();
9329 NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewLdTy, NumElts);
9330 VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, VecOp);
9331 // Readjust position and vector position based on new load type.
9332 Idx = Idx * LdTy.getSizeInBits() / NewLdTy.getSizeInBits();
9333 LdTy = NewLdTy;
9334 }
9335 VecOp = DAG.getInsertVectorElt(dl, VecOp, LdOps[i], Idx++);
9336 }
9337 return DAG.getNode(ISD::BITCAST, dl, VecTy, VecOp);
9338}
9339
9340SDValue DAGTypeLegalizer::GenWidenVectorLoads(SmallVectorImpl<SDValue> &LdChain,
9341 LoadSDNode *LD) {
9342 // The strategy assumes that we can efficiently load power-of-two widths.
9343 // The routine chops the vector into the largest vector loads with the same
9344 // element type or scalar loads and then recombines it to the widen vector
9345 // type.
9346 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
9347 EVT LdVT = LD->getMemoryVT();
9348 SDLoc dl(LD);
9349 assert(LdVT.isVector() && WidenVT.isVector());
9350 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
9352
9353 // Load information
9354 SDValue Chain = LD->getChain();
9355 SDValue BasePtr = LD->getBasePtr();
9356 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
9357 MMOMetadata Metadata = LD->getMMOMetadataForSubAccess();
9358
9359 TypeSize LdWidth = LdVT.getSizeInBits();
9360 TypeSize WidenWidth = WidenVT.getSizeInBits();
9361 TypeSize WidthDiff = WidenWidth - LdWidth;
9362 // Allow wider loads if they are sufficiently aligned to avoid memory faults
9363 // and if the original load is simple.
9364 unsigned LdAlign =
9365 (!LD->isSimple() || LdVT.isScalableVector()) ? 0 : LD->getAlign().value();
9366
9367 // Find the vector type that can load from.
9368 std::optional<EVT> FirstVT =
9369 findMemType(DAG, TLI, LdWidth.getKnownMinValue(), WidenVT, LdAlign,
9370 WidthDiff.getKnownMinValue());
9371
9372 if (!FirstVT)
9373 return SDValue();
9374
9375 SmallVector<EVT, 8> MemVTs;
9376 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
9377
9378 // Unless we're able to load in one instruction we must work out how to load
9379 // the remainder.
9380 if (!TypeSize::isKnownLE(LdWidth, FirstVTWidth)) {
9381 std::optional<EVT> NewVT = FirstVT;
9382 TypeSize RemainingWidth = LdWidth;
9383 TypeSize NewVTWidth = FirstVTWidth;
9384 do {
9385 RemainingWidth -= NewVTWidth;
9386 if (TypeSize::isKnownLT(RemainingWidth, NewVTWidth)) {
9387 // The current type we are using is too large. Find a better size.
9388 NewVT = findMemType(DAG, TLI, RemainingWidth.getKnownMinValue(),
9389 WidenVT, LdAlign, WidthDiff.getKnownMinValue());
9390 if (!NewVT)
9391 return SDValue();
9392 NewVTWidth = NewVT->getSizeInBits();
9393 }
9394 MemVTs.push_back(*NewVT);
9395 } while (TypeSize::isKnownGT(RemainingWidth, NewVTWidth));
9396 }
9397
9398 SDValue LdOp = DAG.getLoad(*FirstVT, dl, Chain, BasePtr, LD->getPointerInfo(),
9399 LD->getBaseAlign(), MMOFlags, Metadata);
9400 LdChain.push_back(LdOp.getValue(1));
9401
9402 // Check if we can load the element with one instruction.
9403 if (MemVTs.empty())
9404 return coerceLoadedValue(LdOp, *FirstVT, WidenVT, LdWidth, FirstVTWidth, dl,
9405 DAG);
9406
9407 // Load vector by using multiple loads from largest vector to scalar.
9409 LdOps.push_back(LdOp);
9410
9411 uint64_t ScaledOffset = 0;
9412 MachinePointerInfo MPI = LD->getPointerInfo();
9413
9414 // First incremement past the first load.
9415 IncrementPointer(cast<LoadSDNode>(LdOp), *FirstVT, MPI, BasePtr,
9416 &ScaledOffset);
9417
9418 for (EVT MemVT : MemVTs) {
9419 Align NewAlign = ScaledOffset == 0
9420 ? LD->getBaseAlign()
9421 : commonAlignment(LD->getAlign(), ScaledOffset);
9422 SDValue L = DAG.getLoad(MemVT, dl, Chain, BasePtr, MPI, NewAlign, MMOFlags,
9423 Metadata);
9424
9425 LdOps.push_back(L);
9426 LdChain.push_back(L.getValue(1));
9427 IncrementPointer(cast<LoadSDNode>(L), MemVT, MPI, BasePtr, &ScaledOffset);
9428 }
9429
9430 // Build the vector from the load operations.
9431 unsigned End = LdOps.size();
9432 if (!LdOps[0].getValueType().isVector())
9433 // All the loads are scalar loads.
9434 return BuildVectorFromScalar(DAG, WidenVT, LdOps, 0, End);
9435
9436 // If the load contains vectors, build the vector using concat vector.
9437 // All of the vectors used to load are power-of-2, and the scalar loads can be
9438 // combined to make a power-of-2 vector.
9439 SmallVector<SDValue, 16> ConcatOps(End);
9440 int i = End - 1;
9441 int Idx = End;
9442 EVT LdTy = LdOps[i].getValueType();
9443 // First, combine the scalar loads to a vector.
9444 if (!LdTy.isVector()) {
9445 for (--i; i >= 0; --i) {
9446 LdTy = LdOps[i].getValueType();
9447 if (LdTy.isVector())
9448 break;
9449 }
9450 ConcatOps[--Idx] = BuildVectorFromScalar(DAG, LdTy, LdOps, i + 1, End);
9451 }
9452
9453 ConcatOps[--Idx] = LdOps[i];
9454 for (--i; i >= 0; --i) {
9455 EVT NewLdTy = LdOps[i].getValueType();
9456 if (NewLdTy != LdTy) {
9457 // Create a larger vector.
9458 TypeSize LdTySize = LdTy.getSizeInBits();
9459 TypeSize NewLdTySize = NewLdTy.getSizeInBits();
9460 assert(NewLdTySize.isScalable() == LdTySize.isScalable() &&
9461 NewLdTySize.isKnownMultipleOf(LdTySize.getKnownMinValue()));
9462 unsigned NumOps =
9463 NewLdTySize.getKnownMinValue() / LdTySize.getKnownMinValue();
9465 unsigned j = 0;
9466 for (; j != End-Idx; ++j)
9467 WidenOps[j] = ConcatOps[Idx+j];
9468 for (; j != NumOps; ++j)
9469 WidenOps[j] = DAG.getPOISON(LdTy);
9470
9471 ConcatOps[End-1] = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewLdTy,
9472 WidenOps);
9473 Idx = End - 1;
9474 LdTy = NewLdTy;
9475 }
9476 ConcatOps[--Idx] = LdOps[i];
9477 }
9478
9479 if (WidenWidth == LdTy.getSizeInBits() * (End - Idx))
9480 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
9481 ArrayRef(&ConcatOps[Idx], End - Idx));
9482
9483 // We need to fill the rest with undefs to build the vector.
9484 unsigned NumOps =
9485 WidenWidth.getKnownMinValue() / LdTy.getSizeInBits().getKnownMinValue();
9487 SDValue UndefVal = DAG.getPOISON(LdTy);
9488 {
9489 unsigned i = 0;
9490 for (; i != End-Idx; ++i)
9491 WidenOps[i] = ConcatOps[Idx+i];
9492 for (; i != NumOps; ++i)
9493 WidenOps[i] = UndefVal;
9494 }
9495 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, WidenOps);
9496}
9497
9498SDValue
9499DAGTypeLegalizer::GenWidenVectorExtLoads(SmallVectorImpl<SDValue> &LdChain,
9500 LoadSDNode *LD,
9501 ISD::LoadExtType ExtType) {
9502 // For extension loads, it may not be more efficient to chop up the vector
9503 // and then extend it. Instead, we unroll the load and build a new vector.
9504 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
9505 EVT LdVT = LD->getMemoryVT();
9506 SDLoc dl(LD);
9507 assert(LdVT.isVector() && WidenVT.isVector());
9508 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
9509
9510 // Load information
9511 SDValue Chain = LD->getChain();
9512 SDValue BasePtr = LD->getBasePtr();
9513 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
9514 MMOMetadata Metadata = LD->getMMOMetadataForSubAccess();
9515
9516 if (LdVT.isScalableVector())
9517 return SDValue();
9518
9519 EVT EltVT = WidenVT.getVectorElementType();
9520 EVT LdEltVT = LdVT.getVectorElementType();
9521 unsigned NumElts = LdVT.getVectorNumElements();
9522
9523 // Load each element and widen.
9524 unsigned WidenNumElts = WidenVT.getVectorNumElements();
9525 SmallVector<SDValue, 16> Ops(WidenNumElts);
9526 unsigned Increment = LdEltVT.getSizeInBits() / 8;
9527 Ops[0] =
9528 DAG.getExtLoad(ExtType, dl, EltVT, Chain, BasePtr, LD->getPointerInfo(),
9529 LdEltVT, LD->getBaseAlign(), MMOFlags, Metadata);
9530 LdChain.push_back(Ops[0].getValue(1));
9531 unsigned i = 0, Offset = Increment;
9532 for (i=1; i < NumElts; ++i, Offset += Increment) {
9533 SDValue NewBasePtr =
9534 DAG.getObjectPtrOffset(dl, BasePtr, TypeSize::getFixed(Offset));
9535 Ops[i] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, NewBasePtr,
9536 LD->getPointerInfo().getWithOffset(Offset), LdEltVT,
9537 LD->getBaseAlign(), MMOFlags, Metadata);
9538 LdChain.push_back(Ops[i].getValue(1));
9539 }
9540
9541 // Fill the rest with undefs.
9542 SDValue UndefVal = DAG.getPOISON(EltVT);
9543 for (; i != WidenNumElts; ++i)
9544 Ops[i] = UndefVal;
9545
9546 return DAG.getBuildVector(WidenVT, dl, Ops);
9547}
9548
9549bool DAGTypeLegalizer::GenWidenVectorStores(SmallVectorImpl<SDValue> &StChain,
9550 StoreSDNode *ST) {
9551 // The strategy assumes that we can efficiently store power-of-two widths.
9552 // The routine chops the vector into the largest vector stores with the same
9553 // element type or scalar stores.
9554 SDValue Chain = ST->getChain();
9555 SDValue BasePtr = ST->getBasePtr();
9556 MachineMemOperand::Flags MMOFlags = ST->getMemOperand()->getFlags();
9557 MMOMetadata Metadata = ST->getMMOMetadataForSubAccess();
9558 SDValue ValOp = GetWidenedVector(ST->getValue());
9559 SDLoc dl(ST);
9560
9561 EVT StVT = ST->getMemoryVT();
9562 TypeSize StWidth = StVT.getSizeInBits();
9563 EVT ValVT = ValOp.getValueType();
9564 TypeSize ValWidth = ValVT.getSizeInBits();
9565 EVT ValEltVT = ValVT.getVectorElementType();
9566 unsigned ValEltWidth = ValEltVT.getFixedSizeInBits();
9567 assert(StVT.getVectorElementType() == ValEltVT);
9568 assert(StVT.isScalableVector() == ValVT.isScalableVector() &&
9569 "Mismatch between store and value types");
9570
9571 int Idx = 0; // current index to store
9572
9573 MachinePointerInfo MPI = ST->getPointerInfo();
9574 uint64_t ScaledOffset = 0;
9575
9576 // A breakdown of how to widen this vector store. Each element of the vector
9577 // is a memory VT combined with the number of times it is to be stored to,
9578 // e,g., v5i32 -> {{v2i32,2},{i32,1}}
9580
9581 while (StWidth.isNonZero()) {
9582 // Find the largest vector type we can store with.
9583 std::optional<EVT> NewVT =
9584 findMemType(DAG, TLI, StWidth.getKnownMinValue(), ValVT);
9585 if (!NewVT)
9586 return false;
9587 MemVTs.push_back({*NewVT, 0});
9588 TypeSize NewVTWidth = NewVT->getSizeInBits();
9589
9590 do {
9591 StWidth -= NewVTWidth;
9592 MemVTs.back().second++;
9593 } while (StWidth.isNonZero() && TypeSize::isKnownGE(StWidth, NewVTWidth));
9594 }
9595
9596 for (const auto &Pair : MemVTs) {
9597 EVT NewVT = Pair.first;
9598 unsigned Count = Pair.second;
9599 TypeSize NewVTWidth = NewVT.getSizeInBits();
9600
9601 if (NewVT.isVector()) {
9602 unsigned NumVTElts = NewVT.getVectorMinNumElements();
9603 do {
9604 Align NewAlign = ScaledOffset == 0
9605 ? ST->getBaseAlign()
9606 : commonAlignment(ST->getAlign(), ScaledOffset);
9607 SDValue EOp = DAG.getExtractSubvector(dl, NewVT, ValOp, Idx);
9608 SDValue PartStore = DAG.getStore(Chain, dl, EOp, BasePtr, MPI, NewAlign,
9609 MMOFlags, Metadata);
9610 StChain.push_back(PartStore);
9611
9612 Idx += NumVTElts;
9613 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr,
9614 &ScaledOffset);
9615 } while (--Count);
9616 } else {
9617 // Cast the vector to the scalar type we can store.
9618 unsigned NumElts = ValWidth.getFixedValue() / NewVTWidth.getFixedValue();
9619 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewVT, NumElts);
9620 SDValue VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, ValOp);
9621 // Readjust index position based on new vector type.
9622 Idx = Idx * ValEltWidth / NewVTWidth.getFixedValue();
9623 do {
9624 SDValue EOp = DAG.getExtractVectorElt(dl, NewVT, VecOp, Idx++);
9625 SDValue PartStore =
9626 DAG.getStore(Chain, dl, EOp, BasePtr, MPI, ST->getBaseAlign(),
9627 MMOFlags, Metadata);
9628 StChain.push_back(PartStore);
9629
9630 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr);
9631 } while (--Count);
9632 // Restore index back to be relative to the original widen element type.
9633 Idx = Idx * NewVTWidth.getFixedValue() / ValEltWidth;
9634 }
9635 }
9636
9637 return true;
9638}
9639
9640/// Modifies a vector input (widen or narrows) to a vector of NVT. The
9641/// input vector must have the same element type as NVT.
9642/// FillWithZeroes specifies that the vector should be widened with zeroes.
9643SDValue DAGTypeLegalizer::ModifyToType(SDValue InOp, EVT NVT,
9644 bool FillWithZeroes) {
9645 // Note that InOp might have been widened so it might already have
9646 // the right width or it might need be narrowed.
9647 EVT InVT = InOp.getValueType();
9649 "input and widen element type must match");
9650 assert(InVT.isScalableVector() == NVT.isScalableVector() &&
9651 "cannot modify scalable vectors in this way");
9652 SDLoc dl(InOp);
9653
9654 // Check if InOp already has the right width.
9655 if (InVT == NVT)
9656 return InOp;
9657
9658 ElementCount InEC = InVT.getVectorElementCount();
9659 ElementCount WidenEC = NVT.getVectorElementCount();
9660 if (WidenEC.hasKnownScalarFactor(InEC)) {
9661 unsigned NumConcat = WidenEC.getKnownScalarFactor(InEC);
9662 SmallVector<SDValue, 16> Ops(NumConcat);
9663 SDValue FillVal =
9664 FillWithZeroes ? DAG.getConstant(0, dl, InVT) : DAG.getPOISON(InVT);
9665 Ops[0] = InOp;
9666 for (unsigned i = 1; i != NumConcat; ++i)
9667 Ops[i] = FillVal;
9668
9669 return DAG.getNode(ISD::CONCAT_VECTORS, dl, NVT, Ops);
9670 }
9671
9672 if (InEC.hasKnownScalarFactor(WidenEC))
9673 return DAG.getExtractSubvector(dl, NVT, InOp, 0);
9674
9675 if (NVT.isScalableVector() && InVT.isScalableVector()) {
9676 // Split the input into the largest equal-sized scalable subvectors.
9677 unsigned InNumElts = InVT.getVectorMinNumElements();
9678 unsigned NewNumElts = NVT.getVectorMinNumElements();
9679 unsigned CommonFactor = std::gcd(InNumElts, NewNumElts);
9680 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), NVT.getVectorElementType(),
9681 ElementCount::getScalable(CommonFactor));
9682
9684 unsigned NumCopiedParts = std::min(InNumElts, NewNumElts) / CommonFactor;
9685 for (unsigned I = 0; I != NumCopiedParts; ++I)
9686 Ops.push_back(
9687 DAG.getExtractSubvector(dl, PartVT, InOp, I * CommonFactor));
9688
9689 unsigned NumResultParts = NewNumElts / CommonFactor;
9690 if (NumResultParts > NumCopiedParts) {
9691 SDValue FillVal = FillWithZeroes ? DAG.getConstant(0, dl, PartVT)
9692 : DAG.getPOISON(PartVT);
9693 Ops.append(NumResultParts - NumCopiedParts, FillVal);
9694 }
9695
9696 return DAG.getNode(ISD::CONCAT_VECTORS, dl, NVT, Ops);
9697 }
9698
9699 assert(!InVT.isScalableVector() && !NVT.isScalableVector() &&
9700 "Scalable vectors should have been handled already.");
9701
9702 unsigned InNumElts = InEC.getFixedValue();
9703 unsigned WidenNumElts = WidenEC.getFixedValue();
9704
9705 // Fall back to extract and build (+ mask, if padding with zeros).
9706 SmallVector<SDValue, 16> Ops(WidenNumElts);
9707 EVT EltVT = NVT.getVectorElementType();
9708 unsigned MinNumElts = std::min(WidenNumElts, InNumElts);
9709 unsigned Idx;
9710 for (Idx = 0; Idx < MinNumElts; ++Idx)
9711 Ops[Idx] = DAG.getExtractVectorElt(dl, EltVT, InOp, Idx);
9712
9713 SDValue UndefVal = DAG.getPOISON(EltVT);
9714 for (; Idx < WidenNumElts; ++Idx)
9715 Ops[Idx] = UndefVal;
9716
9717 SDValue Widened = DAG.getBuildVector(NVT, dl, Ops);
9718 if (!FillWithZeroes)
9719 return Widened;
9720
9721 assert(NVT.isInteger() &&
9722 "We expect to never want to FillWithZeroes for non-integral types.");
9723
9725 MaskOps.append(MinNumElts, DAG.getAllOnesConstant(dl, EltVT));
9726 MaskOps.append(WidenNumElts - MinNumElts, DAG.getConstant(0, dl, EltVT));
9727
9728 return DAG.getNode(ISD::AND, dl, NVT, Widened,
9729 DAG.getBuildVector(NVT, dl, MaskOps));
9730}
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
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...
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
BooleanContent
Enum that describes how the target represents true/false values.
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
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
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:418
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:129
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
Definition ValueTypes.h:307
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
Definition ValueTypes.h:155
ElementCount getVectorElementCount() const
Definition ValueTypes.h:373
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
Definition ValueTypes.h:494
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:396
bool isByteSized() const
Return true if the bit size is a multiple of 8.
Definition ValueTypes.h:266
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
Definition ValueTypes.h:382
uint64_t getScalarSizeInBits() const
Definition ValueTypes.h:408
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
Definition ValueTypes.h:501
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:404
EVT widenIntegerVectorElementType(LLVMContext &Context) const
Return a VT for an integer vector type with the size of the elements doubled.
Definition ValueTypes.h:475
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:199
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:442
bool isVector() const
Return true if this is a vector value type.
Definition ValueTypes.h:176
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
Definition ValueTypes.h:346
bool bitsEq(EVT VT) const
Return true if this has the same number of bits as VT.
Definition ValueTypes.h:279
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:187
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:291
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition ValueTypes.h:351
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:121
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Definition ValueTypes.h:359
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
Definition ValueTypes.h:484
bool isInteger() const
Return true if this is an integer or a vector integer type.
Definition ValueTypes.h:160
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.