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