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;
3861 case ISD::MASKED_UDIV:
3862 case ISD::MASKED_SDIV:
3863 case ISD::MASKED_UREM:
3864 case ISD::MASKED_SREM:
3865 Res = SplitVecOp_MaskedBinOp(N, OpNo);
3866 break;
3868 Res = SplitVecOp_VECTOR_COMPRESS(N, OpNo);
3869 break;
3872 case ISD::SINT_TO_FP:
3873 case ISD::UINT_TO_FP:
3874 case ISD::VP_SINT_TO_FP:
3875 case ISD::VP_UINT_TO_FP:
3876 if (N->getValueType(0).bitsLT(
3877 N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType()))
3878 Res = SplitVecOp_TruncateHelper(N);
3879 else
3880 Res = SplitVecOp_UnaryOp(N);
3881 break;
3884 Res = SplitVecOp_FP_TO_XINT_SAT(N);
3885 break;
3886 case ISD::FP_TO_SINT:
3887 case ISD::FP_TO_UINT:
3888 case ISD::VP_FP_TO_SINT:
3889 case ISD::VP_FP_TO_UINT:
3893 case ISD::FP_EXTEND:
3894 case ISD::SIGN_EXTEND:
3895 case ISD::ZERO_EXTEND:
3896 case ISD::ANY_EXTEND:
3897 case ISD::FTRUNC:
3898 case ISD::LROUND:
3899 case ISD::LLROUND:
3900 case ISD::LRINT:
3901 case ISD::LLRINT:
3902 Res = SplitVecOp_UnaryOp(N);
3903 break;
3904 case ISD::FLDEXP:
3905 Res = SplitVecOp_FPOpDifferentTypes(N);
3906 break;
3907
3908 case ISD::SCMP:
3909 case ISD::UCMP:
3910 Res = SplitVecOp_CMP(N);
3911 break;
3912
3913 case ISD::FAKE_USE:
3914 Res = SplitVecOp_FAKE_USE(N);
3915 break;
3919 Res = SplitVecOp_ExtVecInRegOp(N);
3920 break;
3921
3924 case ISD::VECREDUCE_ADD:
3925 case ISD::VECREDUCE_MUL:
3926 case ISD::VECREDUCE_AND:
3927 case ISD::VECREDUCE_OR:
3928 case ISD::VECREDUCE_XOR:
3937 Res = SplitVecOp_VECREDUCE(N, OpNo);
3938 break;
3941 Res = SplitVecOp_VECREDUCE_SEQ(N);
3942 break;
3943 case ISD::VP_REDUCE_FADD:
3944 case ISD::VP_REDUCE_SEQ_FADD:
3945 case ISD::VP_REDUCE_FMUL:
3946 case ISD::VP_REDUCE_SEQ_FMUL:
3947 case ISD::VP_REDUCE_ADD:
3948 case ISD::VP_REDUCE_MUL:
3949 case ISD::VP_REDUCE_AND:
3950 case ISD::VP_REDUCE_OR:
3951 case ISD::VP_REDUCE_XOR:
3952 case ISD::VP_REDUCE_SMAX:
3953 case ISD::VP_REDUCE_SMIN:
3954 case ISD::VP_REDUCE_UMAX:
3955 case ISD::VP_REDUCE_UMIN:
3956 case ISD::VP_REDUCE_FMAX:
3957 case ISD::VP_REDUCE_FMIN:
3958 case ISD::VP_REDUCE_FMAXIMUM:
3959 case ISD::VP_REDUCE_FMINIMUM:
3960 Res = SplitVecOp_VP_REDUCE(N, OpNo);
3961 break;
3962 case ISD::CTTZ_ELTS:
3964 Res = SplitVecOp_CttzElts(N);
3965 break;
3966 case ISD::VP_CTTZ_ELTS:
3967 case ISD::VP_CTTZ_ELTS_ZERO_POISON:
3968 Res = SplitVecOp_VP_CttzElements(N);
3969 break;
3971 Res = SplitVecOp_VECTOR_HISTOGRAM(N);
3972 break;
3977 Res = SplitVecOp_PARTIAL_REDUCE_MLA(N);
3978 break;
3979 }
3980
3981 // If the result is null, the sub-method took care of registering results etc.
3982 if (!Res.getNode()) return false;
3983
3984 // If the result is N, the sub-method updated N in place. Tell the legalizer
3985 // core about this.
3986 if (Res.getNode() == N)
3987 return true;
3988
3989 if (N->isStrictFPOpcode())
3990 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
3991 "Invalid operand expansion");
3992 else
3993 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
3994 "Invalid operand expansion");
3995
3996 ReplaceValueWith(SDValue(N, 0), Res);
3997 return false;
3998}
3999
4000SDValue DAGTypeLegalizer::SplitVecOp_VECTOR_FIND_LAST_ACTIVE(SDNode *N) {
4001 SDLoc DL(N);
4002
4003 SDValue LoMask, HiMask;
4004 GetSplitVector(N->getOperand(0), LoMask, HiMask);
4005
4006 EVT VT = N->getValueType(0);
4007 EVT SplitVT = LoMask.getValueType();
4008 ElementCount SplitEC = SplitVT.getVectorElementCount();
4009
4010 // Find the last active in both the low and the high masks.
4011 SDValue LoFind = DAG.getNode(ISD::VECTOR_FIND_LAST_ACTIVE, DL, VT, LoMask);
4012 SDValue HiFind = DAG.getNode(ISD::VECTOR_FIND_LAST_ACTIVE, DL, VT, HiMask);
4013
4014 // Check if any lane is active in the high mask.
4015 // FIXME: This would not be necessary if VECTOR_FIND_LAST_ACTIVE returned a
4016 // sentinel value for "none active".
4017 SDValue AnyHiActive = DAG.getNode(ISD::VECREDUCE_OR, DL, MVT::i1, HiMask);
4018 SDValue Cond = DAG.getBoolExtOrTrunc(AnyHiActive, DL,
4019 getSetCCResultType(MVT::i1), MVT::i1);
4020
4021 // Return: AnyHiActive ? (HiFind + SplitEC) : LoFind;
4022 return DAG.getNode(ISD::SELECT, DL, VT, Cond,
4023 DAG.getNode(ISD::ADD, DL, VT, HiFind,
4024 DAG.getElementCount(DL, VT, SplitEC)),
4025 LoFind);
4026}
4027
4028SDValue DAGTypeLegalizer::SplitVecOp_VSELECT(SDNode *N, unsigned OpNo) {
4029 // The only possibility for an illegal operand is the mask, since result type
4030 // legalization would have handled this node already otherwise.
4031 assert(OpNo == 0 && "Illegal operand must be mask");
4032
4033 SDValue Mask = N->getOperand(0);
4034 SDValue Src0 = N->getOperand(1);
4035 SDValue Src1 = N->getOperand(2);
4036 EVT Src0VT = Src0.getValueType();
4037 SDLoc DL(N);
4038 assert(Mask.getValueType().isVector() && "VSELECT without a vector mask?");
4039
4040 SDValue Lo, Hi;
4041 GetSplitVector(N->getOperand(0), Lo, Hi);
4042 assert(Lo.getValueType() == Hi.getValueType() &&
4043 "Lo and Hi have differing types");
4044
4045 EVT LoOpVT, HiOpVT;
4046 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(Src0VT);
4047 assert(LoOpVT == HiOpVT && "Asymmetric vector split?");
4048
4049 SDValue LoOp0, HiOp0, LoOp1, HiOp1, LoMask, HiMask;
4050 std::tie(LoOp0, HiOp0) = DAG.SplitVector(Src0, DL);
4051 std::tie(LoOp1, HiOp1) = DAG.SplitVector(Src1, DL);
4052 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
4053
4054 SDValue LoSelect =
4055 DAG.getNode(ISD::VSELECT, DL, LoOpVT, LoMask, LoOp0, LoOp1);
4056 SDValue HiSelect =
4057 DAG.getNode(ISD::VSELECT, DL, HiOpVT, HiMask, HiOp0, HiOp1);
4058
4059 return DAG.getNode(ISD::CONCAT_VECTORS, DL, Src0VT, LoSelect, HiSelect);
4060}
4061
4062SDValue DAGTypeLegalizer::SplitVecOp_MaskedBinOp(SDNode *N, unsigned OpNo) {
4063 assert(OpNo == 2 && "Illegal operand must be mask");
4064
4065 SDLoc DL(N);
4066 auto [LHSLo, LHSHi] = DAG.SplitVector(N->getOperand(0), DL);
4067 auto [RHSLo, RHSHi] = DAG.SplitVector(N->getOperand(1), DL);
4068 SDValue MaskLo, MaskHi;
4069 GetSplitVector(N->getOperand(2), MaskLo, MaskHi);
4070
4071 SDValue Lo = DAG.getNode(N->getOpcode(), DL, LHSLo.getValueType(), LHSLo,
4072 RHSLo, MaskLo, N->getFlags());
4073 SDValue Hi = DAG.getNode(N->getOpcode(), DL, LHSHi.getValueType(), LHSHi,
4074 RHSHi, MaskHi, N->getFlags());
4075 return DAG.getNode(ISD::CONCAT_VECTORS, DL, N->getValueType(0), Lo, Hi);
4076}
4077
4078SDValue DAGTypeLegalizer::SplitVecOp_VECTOR_COMPRESS(SDNode *N, unsigned OpNo) {
4079 // The only possibility for an illegal operand is the mask, since result type
4080 // legalization would have handled this node already otherwise.
4081 assert(OpNo == 1 && "Illegal operand must be mask");
4082
4083 // To split the mask, we need to split the result type too, so we can just
4084 // reuse that logic here.
4085 SDValue Lo, Hi;
4086 SplitVecRes_VECTOR_COMPRESS(N, Lo, Hi);
4087
4088 EVT VecVT = N->getValueType(0);
4089 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), VecVT, Lo, Hi);
4090}
4091
4092SDValue DAGTypeLegalizer::SplitVecOp_VECREDUCE(SDNode *N, unsigned OpNo) {
4093 EVT ResVT = N->getValueType(0);
4094 SDValue Lo, Hi;
4095 SDLoc dl(N);
4096
4097 SDValue VecOp = N->getOperand(OpNo);
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 // Use the appropriate scalar instruction on the split subvectors before
4105 // reducing the now partially reduced smaller vector.
4106 unsigned CombineOpc = ISD::getVecReduceBaseOpcode(N->getOpcode());
4107 SDValue Partial = DAG.getNode(CombineOpc, dl, LoOpVT, Lo, Hi, N->getFlags());
4108 return DAG.getNode(N->getOpcode(), dl, ResVT, Partial, N->getFlags());
4109}
4110
4111SDValue DAGTypeLegalizer::SplitVecOp_VECREDUCE_SEQ(SDNode *N) {
4112 EVT ResVT = N->getValueType(0);
4113 SDValue Lo, Hi;
4114 SDLoc dl(N);
4115
4116 SDValue AccOp = N->getOperand(0);
4117 SDValue VecOp = N->getOperand(1);
4118 SDNodeFlags Flags = N->getFlags();
4119
4120 EVT VecVT = VecOp.getValueType();
4121 assert(VecVT.isVector() && "Can only split reduce vector operand");
4122 GetSplitVector(VecOp, Lo, Hi);
4123 EVT LoOpVT, HiOpVT;
4124 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(VecVT);
4125
4126 // Reduce low half.
4127 SDValue Partial = DAG.getNode(N->getOpcode(), dl, ResVT, AccOp, Lo, Flags);
4128
4129 // Reduce high half, using low half result as initial value.
4130 return DAG.getNode(N->getOpcode(), dl, ResVT, Partial, Hi, Flags);
4131}
4132
4133SDValue DAGTypeLegalizer::SplitVecOp_VP_REDUCE(SDNode *N, unsigned OpNo) {
4134 assert(N->isVPOpcode() && "Expected VP opcode");
4135 assert(OpNo == 1 && "Can only split reduce vector operand");
4136
4137 unsigned Opc = N->getOpcode();
4138 EVT ResVT = N->getValueType(0);
4139 SDValue Lo, Hi;
4140 SDLoc dl(N);
4141
4142 SDValue VecOp = N->getOperand(OpNo);
4143 EVT VecVT = VecOp.getValueType();
4144 assert(VecVT.isVector() && "Can only split reduce vector operand");
4145 GetSplitVector(VecOp, Lo, Hi);
4146
4147 SDValue MaskLo, MaskHi;
4148 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(2));
4149
4150 SDValue EVLLo, EVLHi;
4151 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(N->getOperand(3), VecVT, dl);
4152
4153 const SDNodeFlags Flags = N->getFlags();
4154
4155 SDValue ResLo =
4156 DAG.getNode(Opc, dl, ResVT, {N->getOperand(0), Lo, MaskLo, EVLLo}, Flags);
4157 return DAG.getNode(Opc, dl, ResVT, {ResLo, Hi, MaskHi, EVLHi}, Flags);
4158}
4159
4160SDValue DAGTypeLegalizer::SplitVecOp_UnaryOp(SDNode *N) {
4161 // The result has a legal vector type, but the input needs splitting.
4162 EVT ResVT = N->getValueType(0);
4163 SDValue Lo, Hi;
4164 SDLoc dl(N);
4165 GetSplitVector(N->getOperand(N->isStrictFPOpcode() ? 1 : 0), Lo, Hi);
4166 EVT InVT = Lo.getValueType();
4167
4168 EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
4169 InVT.getVectorElementCount());
4170
4171 if (N->isStrictFPOpcode()) {
4172 Lo = DAG.getNode(N->getOpcode(), dl, {OutVT, MVT::Other},
4173 {N->getOperand(0), Lo});
4174 Hi = DAG.getNode(N->getOpcode(), dl, {OutVT, MVT::Other},
4175 {N->getOperand(0), Hi});
4176
4177 // Build a factor node to remember that this operation is independent
4178 // of the other one.
4179 SDValue Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
4180 Hi.getValue(1));
4181
4182 // Legalize the chain result - switch anything that used the old chain to
4183 // use the new one.
4184 ReplaceValueWith(SDValue(N, 1), Ch);
4185 } else if (N->getNumOperands() == 3) {
4186 assert(N->isVPOpcode() && "Expected VP opcode");
4187 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
4188 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
4189 std::tie(EVLLo, EVLHi) =
4190 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), dl);
4191 Lo = DAG.getNode(N->getOpcode(), dl, OutVT, Lo, MaskLo, EVLLo);
4192 Hi = DAG.getNode(N->getOpcode(), dl, OutVT, Hi, MaskHi, EVLHi);
4193 } else {
4194 Lo = DAG.getNode(N->getOpcode(), dl, OutVT, Lo);
4195 Hi = DAG.getNode(N->getOpcode(), dl, OutVT, Hi);
4196 }
4197
4198 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
4199}
4200
4201// Split a FAKE_USE use of a vector into FAKE_USEs of hi and lo part.
4202SDValue DAGTypeLegalizer::SplitVecOp_FAKE_USE(SDNode *N) {
4203 SDValue Lo, Hi;
4204 GetSplitVector(N->getOperand(1), Lo, Hi);
4205 SDValue Chain =
4206 DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, N->getOperand(0), Lo);
4207 return DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, Chain, Hi);
4208}
4209
4210SDValue DAGTypeLegalizer::SplitVecOp_BITCAST(SDNode *N) {
4211 // For example, i64 = BITCAST v4i16 on alpha. Typically the vector will
4212 // end up being split all the way down to individual components. Convert the
4213 // split pieces into integers and reassemble.
4214 EVT ResVT = N->getValueType(0);
4215 SDValue Lo, Hi;
4216 GetSplitVector(N->getOperand(0), Lo, Hi);
4217 SDLoc dl(N);
4218
4219 if (ResVT.isScalableVector()) {
4220 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(ResVT);
4221 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
4222 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
4223 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
4224 }
4225
4226 Lo = BitConvertToInteger(Lo);
4227 Hi = BitConvertToInteger(Hi);
4228
4229 if (DAG.getDataLayout().isBigEndian())
4230 std::swap(Lo, Hi);
4231
4232 return DAG.getNode(ISD::BITCAST, dl, ResVT, JoinIntegers(Lo, Hi));
4233}
4234
4235SDValue DAGTypeLegalizer::SplitVecOp_INSERT_SUBVECTOR(SDNode *N,
4236 unsigned OpNo) {
4237 assert(OpNo == 1 && "Invalid OpNo; can only split SubVec.");
4238 // We know that the result type is legal.
4239 EVT ResVT = N->getValueType(0);
4240
4241 SDValue Vec = N->getOperand(0);
4242 SDValue SubVec = N->getOperand(1);
4243 SDValue Idx = N->getOperand(2);
4244 SDLoc dl(N);
4245
4246 SDValue Lo, Hi;
4247 GetSplitVector(SubVec, Lo, Hi);
4248
4249 uint64_t IdxVal = Idx->getAsZExtVal();
4250 uint64_t LoElts = Lo.getValueType().getVectorMinNumElements();
4251
4252 SDValue FirstInsertion =
4253 DAG.getNode(ISD::INSERT_SUBVECTOR, dl, ResVT, Vec, Lo, Idx);
4254 SDValue SecondInsertion =
4255 DAG.getNode(ISD::INSERT_SUBVECTOR, dl, ResVT, FirstInsertion, Hi,
4256 DAG.getVectorIdxConstant(IdxVal + LoElts, dl));
4257
4258 return SecondInsertion;
4259}
4260
4261SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
4262 // We know that the extracted result type is legal.
4263 EVT SubVT = N->getValueType(0);
4264 SDValue Idx = N->getOperand(1);
4265 SDLoc dl(N);
4266 SDValue Lo, Hi;
4267
4268 GetSplitVector(N->getOperand(0), Lo, Hi);
4269
4270 ElementCount LoElts = Lo.getValueType().getVectorElementCount();
4271 // Note: For scalable vectors, the index is scaled by vscale.
4272 ElementCount IdxVal =
4274 uint64_t IdxValMin = IdxVal.getKnownMinValue();
4275
4276 EVT SrcVT = N->getOperand(0).getValueType();
4277 ElementCount NumResultElts = SubVT.getVectorElementCount();
4278
4279 // If the extracted elements are all in the low half, do a simple extract.
4280 if (ElementCount::isKnownLE(IdxVal + NumResultElts, LoElts))
4281 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, SubVT, Lo, Idx);
4282
4283 unsigned LoEltsMin = LoElts.getKnownMinValue();
4284 if (IdxValMin < LoEltsMin && SubVT.isFixedLengthVector() &&
4285 SrcVT.isFixedLengthVector()) {
4286 // Extracted subvector crosses vector split, so we need to blend the two
4287 // halves.
4288 // TODO: May be able to emit partial extract_subvector.
4290 Elts.reserve(NumResultElts.getFixedValue());
4291
4292 // This is not valid for scalable vectors. If SubVT is scalable, this is the
4293 // same as unrolling a scalable dimension (invalid). If ScrVT is scalable,
4294 // `Lo[LoEltsMin]` may not be the last element of `Lo`.
4295 DAG.ExtractVectorElements(Lo, Elts, /*Start=*/IdxValMin,
4296 /*Count=*/LoEltsMin - IdxValMin);
4297 DAG.ExtractVectorElements(Hi, Elts, /*Start=*/0,
4298 /*Count=*/SubVT.getVectorNumElements() -
4299 Elts.size());
4300 return DAG.getBuildVector(SubVT, dl, Elts);
4301 }
4302
4303 if (SubVT.isScalableVector() == SrcVT.isScalableVector()) {
4304 ElementCount ExtractIdx = IdxVal - LoElts;
4305 if (ExtractIdx.isKnownMultipleOf(NumResultElts))
4306 return DAG.getExtractSubvector(dl, SubVT, Hi,
4307 ExtractIdx.getKnownMinValue());
4308
4309 EVT HiVT = Hi.getValueType();
4310 assert(HiVT.isFixedLengthVector() &&
4311 "Only fixed-vector extracts are supported in this case");
4312
4313 // We cannot create an extract_subvector that isn't a multiple of the
4314 // result size, which may go out of bounds for the last elements. Shuffle
4315 // the desired elements down to 0 and do a simple 0 extract.
4316 SmallVector<int, 8> Mask(HiVT.getVectorNumElements(), -1);
4317 for (int I = 0; I != int(NumResultElts.getFixedValue()); ++I)
4318 Mask[I] = int(ExtractIdx.getFixedValue()) + I;
4319
4320 SDValue Shuffle =
4321 DAG.getVectorShuffle(HiVT, dl, Hi, DAG.getPOISON(HiVT), Mask);
4322 return DAG.getExtractSubvector(dl, SubVT, Shuffle, 0);
4323 }
4324
4325 // After this point the DAG node only permits extracting fixed-width
4326 // subvectors from scalable vectors.
4327 assert(SubVT.isFixedLengthVector() &&
4328 "Extracting scalable subvector from fixed-width unsupported");
4329
4330 // If the element type is i1 and we're not promoting the result, then we may
4331 // end up loading the wrong data since the bits are packed tightly into
4332 // bytes. For example, if we extract a v4i1 (legal) from a nxv4i1 (legal)
4333 // type at index 4, then we will load a byte starting at index 0.
4334 if (SubVT.getScalarType() == MVT::i1)
4335 report_fatal_error("Don't know how to extract fixed-width predicate "
4336 "subvector from a scalable predicate vector");
4337
4338 // Spill the vector to the stack. We should use the alignment for
4339 // the smallest part.
4340 SDValue Vec = N->getOperand(0);
4341 EVT VecVT = Vec.getValueType();
4342 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
4344 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
4345 auto &MF = DAG.getMachineFunction();
4346 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
4347 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
4348
4349 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
4350 SmallestAlign);
4351
4352 // Extract the subvector by loading the correct part.
4353 StackPtr = TLI.getVectorSubVecPointer(DAG, StackPtr, VecVT, SubVT, Idx);
4354
4355 return DAG.getLoad(
4356 SubVT, dl, Store, StackPtr,
4357 MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()));
4358}
4359
4360SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
4361 SDValue Vec = N->getOperand(0);
4362 SDValue Idx = N->getOperand(1);
4363 EVT VecVT = Vec.getValueType();
4364
4365 if (const ConstantSDNode *Index = dyn_cast<ConstantSDNode>(Idx)) {
4366 uint64_t IdxVal = Index->getZExtValue();
4367
4368 SDValue Lo, Hi;
4369 GetSplitVector(Vec, Lo, Hi);
4370
4371 uint64_t LoElts = Lo.getValueType().getVectorMinNumElements();
4372
4373 if (IdxVal < LoElts)
4374 return SDValue(DAG.UpdateNodeOperands(N, Lo, Idx), 0);
4375 else if (!Vec.getValueType().isScalableVector())
4376 return SDValue(DAG.UpdateNodeOperands(N, Hi,
4377 DAG.getConstant(IdxVal - LoElts, SDLoc(N),
4378 Idx.getValueType())), 0);
4379 }
4380
4381 // See if the target wants to custom expand this node.
4382 if (CustomLowerNode(N, N->getValueType(0), true))
4383 return SDValue();
4384
4385 // Make the vector elements byte-addressable if they aren't already.
4386 SDLoc dl(N);
4387 EVT EltVT = VecVT.getVectorElementType();
4388 if (!EltVT.isByteSized()) {
4389 EltVT = EltVT.changeTypeToInteger().getRoundIntegerType(*DAG.getContext());
4390 VecVT = VecVT.changeElementType(*DAG.getContext(), EltVT);
4391 Vec = DAG.getNode(ISD::ANY_EXTEND, dl, VecVT, Vec);
4392 SDValue NewExtract =
4393 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, Vec, Idx);
4394 return DAG.getAnyExtOrTrunc(NewExtract, dl, N->getValueType(0));
4395 }
4396
4397 // Store the vector to the stack.
4398 // In cases where the vector is illegal it will be broken down into parts
4399 // and stored in parts - we should use the alignment for the smallest part.
4400 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
4402 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
4403 auto &MF = DAG.getMachineFunction();
4404 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
4405 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
4406 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
4407 SmallestAlign);
4408
4409 // Load back the required element.
4410 StackPtr = TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Idx);
4411
4412 // EXTRACT_VECTOR_ELT can extend the element type to the width of the return
4413 // type, leaving the high bits undefined. But it can't truncate.
4414 assert(N->getValueType(0).bitsGE(EltVT) && "Illegal EXTRACT_VECTOR_ELT.");
4415
4416 return DAG.getExtLoad(
4417 ISD::EXTLOAD, dl, N->getValueType(0), Store, StackPtr,
4418 MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()), EltVT,
4419 commonAlignment(SmallestAlign, EltVT.getFixedSizeInBits() / 8));
4420}
4421
4422SDValue DAGTypeLegalizer::SplitVecOp_ExtVecInRegOp(SDNode *N) {
4423 SDValue Lo, Hi;
4424
4425 // *_EXTEND_VECTOR_INREG only reference the lower half of the input, so
4426 // splitting the result has the same effect as splitting the input operand.
4427 SplitVecRes_ExtVecInRegOp(N, Lo, Hi);
4428
4429 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), N->getValueType(0), Lo, Hi);
4430}
4431
4432SDValue DAGTypeLegalizer::SplitVecOp_Gather(MemSDNode *N, unsigned OpNo) {
4433 (void)OpNo;
4434 SDValue Lo, Hi;
4435 SplitVecRes_Gather(N, Lo, Hi);
4436
4437 SDValue Res = DAG.getNode(ISD::CONCAT_VECTORS, N, N->getValueType(0), Lo, Hi);
4438 ReplaceValueWith(SDValue(N, 0), Res);
4439 return SDValue();
4440}
4441
4442SDValue DAGTypeLegalizer::SplitVecOp_VP_STORE(VPStoreSDNode *N, unsigned OpNo) {
4443 assert(N->isUnindexed() && "Indexed vp_store of vector?");
4444 SDValue Ch = N->getChain();
4445 SDValue Ptr = N->getBasePtr();
4446 SDValue Offset = N->getOffset();
4447 assert(Offset.isUndef() && "Unexpected VP store offset");
4448 SDValue Mask = N->getMask();
4449 SDValue EVL = N->getVectorLength();
4450 SDValue Data = N->getValue();
4451 Align Alignment = N->getBaseAlign();
4452 SDLoc DL(N);
4453
4454 SDValue DataLo, DataHi;
4455 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
4456 // Split Data operand
4457 GetSplitVector(Data, DataLo, DataHi);
4458 else
4459 std::tie(DataLo, DataHi) = DAG.SplitVector(Data, DL);
4460
4461 // Split Mask operand
4462 SDValue MaskLo, MaskHi;
4463 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC) {
4464 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
4465 } else {
4466 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
4467 GetSplitVector(Mask, MaskLo, MaskHi);
4468 else
4469 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
4470 }
4471
4472 EVT MemoryVT = N->getMemoryVT();
4473 EVT LoMemVT, HiMemVT;
4474 bool HiIsEmpty = false;
4475 std::tie(LoMemVT, HiMemVT) =
4476 DAG.GetDependentSplitDestVTs(MemoryVT, DataLo.getValueType(), &HiIsEmpty);
4477
4478 // Split EVL
4479 SDValue EVLLo, EVLHi;
4480 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(EVL, Data.getValueType(), DL);
4481
4482 SDValue Lo, Hi;
4483 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
4484 N->getPointerInfo(), MachineMemOperand::MOStore,
4485 LocationSize::beforeOrAfterPointer(), Alignment, N->getAAInfo(),
4486 N->getRanges());
4487
4488 Lo = DAG.getStoreVP(Ch, DL, DataLo, Ptr, Offset, MaskLo, EVLLo, LoMemVT, MMO,
4489 N->getAddressingMode(), N->isTruncatingStore(),
4490 N->isCompressingStore());
4491
4492 // If the hi vp_store has zero storage size, only the lo vp_store is needed.
4493 if (HiIsEmpty)
4494 return Lo;
4495
4496 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, DL, LoMemVT, DAG,
4497 N->isCompressingStore());
4498
4499 MachinePointerInfo MPI;
4500 if (LoMemVT.isScalableVector()) {
4501 Alignment = commonAlignment(Alignment,
4502 LoMemVT.getSizeInBits().getKnownMinValue() / 8);
4503 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
4504 } else
4505 MPI = N->getPointerInfo().getWithOffset(
4506 LoMemVT.getStoreSize().getFixedValue());
4507
4508 MMO = DAG.getMachineFunction().getMachineMemOperand(
4510 Alignment, N->getAAInfo(), N->getRanges());
4511
4512 Hi = DAG.getStoreVP(Ch, DL, DataHi, Ptr, Offset, MaskHi, EVLHi, HiMemVT, MMO,
4513 N->getAddressingMode(), N->isTruncatingStore(),
4514 N->isCompressingStore());
4515
4516 // Build a factor node to remember that this store is independent of the
4517 // other one.
4518 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4519}
4520
4521SDValue DAGTypeLegalizer::SplitVecOp_VP_STRIDED_STORE(VPStridedStoreSDNode *N,
4522 unsigned OpNo) {
4523 assert(N->isUnindexed() && "Indexed vp_strided_store of a vector?");
4524 assert(N->getOffset().isUndef() && "Unexpected VP strided store offset");
4525
4526 SDLoc DL(N);
4527
4528 SDValue Data = N->getValue();
4529 SDValue LoData, HiData;
4530 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
4531 GetSplitVector(Data, LoData, HiData);
4532 else
4533 std::tie(LoData, HiData) = DAG.SplitVector(Data, DL);
4534
4535 EVT LoMemVT, HiMemVT;
4536 bool HiIsEmpty = false;
4537 std::tie(LoMemVT, HiMemVT) = DAG.GetDependentSplitDestVTs(
4538 N->getMemoryVT(), LoData.getValueType(), &HiIsEmpty);
4539
4540 SDValue Mask = N->getMask();
4541 SDValue LoMask, HiMask;
4542 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC)
4543 SplitVecRes_SETCC(Mask.getNode(), LoMask, HiMask);
4544 else if (getTypeAction(Mask.getValueType()) ==
4546 GetSplitVector(Mask, LoMask, HiMask);
4547 else
4548 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
4549
4550 SDValue LoEVL, HiEVL;
4551 std::tie(LoEVL, HiEVL) =
4552 DAG.SplitEVL(N->getVectorLength(), Data.getValueType(), DL);
4553
4554 // Generate the low vp_strided_store
4555 SDValue Lo = DAG.getStridedStoreVP(
4556 N->getChain(), DL, LoData, N->getBasePtr(), N->getOffset(),
4557 N->getStride(), LoMask, LoEVL, LoMemVT, N->getMemOperand(),
4558 N->getAddressingMode(), N->isTruncatingStore(), N->isCompressingStore());
4559
4560 // If the high vp_strided_store has zero storage size, only the low
4561 // vp_strided_store is needed.
4562 if (HiIsEmpty)
4563 return Lo;
4564
4565 // Generate the high vp_strided_store.
4566 // To calculate the high base address, we need to sum to the low base
4567 // address stride number of bytes for each element already stored by low,
4568 // that is: Ptr = Ptr + (LoEVL * Stride)
4569 EVT PtrVT = N->getBasePtr().getValueType();
4571 DAG.getNode(ISD::MUL, DL, PtrVT, LoEVL,
4572 DAG.getSExtOrTrunc(N->getStride(), DL, PtrVT));
4573 SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, N->getBasePtr(), Increment);
4574
4575 Align Alignment = N->getBaseAlign();
4576 if (LoMemVT.isScalableVector())
4577 Alignment = commonAlignment(Alignment,
4578 LoMemVT.getSizeInBits().getKnownMinValue() / 8);
4579
4580 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
4581 MachinePointerInfo(N->getPointerInfo().getAddrSpace()),
4583 Alignment, N->getAAInfo(), N->getRanges());
4584
4585 SDValue Hi = DAG.getStridedStoreVP(
4586 N->getChain(), DL, HiData, Ptr, N->getOffset(), N->getStride(), HiMask,
4587 HiEVL, HiMemVT, MMO, N->getAddressingMode(), N->isTruncatingStore(),
4588 N->isCompressingStore());
4589
4590 // Build a factor node to remember that this store is independent of the
4591 // other one.
4592 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4593}
4594
4595SDValue DAGTypeLegalizer::SplitVecOp_MSTORE(MaskedStoreSDNode *N,
4596 unsigned OpNo) {
4597 assert(N->isUnindexed() && "Indexed masked store of vector?");
4598 SDValue Ch = N->getChain();
4599 SDValue Ptr = N->getBasePtr();
4600 SDValue Offset = N->getOffset();
4601 assert(Offset.isUndef() && "Unexpected indexed masked store offset");
4602 SDValue Mask = N->getMask();
4603 SDValue Data = N->getValue();
4604 Align Alignment = N->getBaseAlign();
4605 SDLoc DL(N);
4606
4607 SDValue DataLo, DataHi;
4608 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
4609 // Split Data operand
4610 GetSplitVector(Data, DataLo, DataHi);
4611 else
4612 std::tie(DataLo, DataHi) = DAG.SplitVector(Data, DL);
4613
4614 // Split Mask operand
4615 SDValue MaskLo, MaskHi;
4616 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC) {
4617 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
4618 } else {
4619 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
4620 GetSplitVector(Mask, MaskLo, MaskHi);
4621 else
4622 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
4623 }
4624
4625 EVT MemoryVT = N->getMemoryVT();
4626 EVT LoMemVT, HiMemVT;
4627 bool HiIsEmpty = false;
4628 std::tie(LoMemVT, HiMemVT) =
4629 DAG.GetDependentSplitDestVTs(MemoryVT, DataLo.getValueType(), &HiIsEmpty);
4630
4631 SDValue Lo, Hi, Res;
4632 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
4633 N->getPointerInfo(), MachineMemOperand::MOStore,
4634 LocationSize::beforeOrAfterPointer(), Alignment, N->getAAInfo(),
4635 N->getRanges());
4636
4637 Lo = DAG.getMaskedStore(Ch, DL, DataLo, Ptr, Offset, MaskLo, LoMemVT, MMO,
4638 N->getAddressingMode(), N->isTruncatingStore(),
4639 N->isCompressingStore());
4640
4641 if (HiIsEmpty) {
4642 // The hi masked store has zero storage size.
4643 // Only the lo masked store is needed.
4644 Res = Lo;
4645 } else {
4646
4647 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, DL, LoMemVT, DAG,
4648 N->isCompressingStore());
4649
4650 MachinePointerInfo MPI;
4651 if (LoMemVT.isScalableVector()) {
4652 Alignment = commonAlignment(
4653 Alignment, LoMemVT.getSizeInBits().getKnownMinValue() / 8);
4654 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
4655 } else
4656 MPI = N->getPointerInfo().getWithOffset(
4657 LoMemVT.getStoreSize().getFixedValue());
4658
4659 MMO = DAG.getMachineFunction().getMachineMemOperand(
4661 Alignment, N->getAAInfo(), N->getRanges());
4662
4663 Hi = DAG.getMaskedStore(Ch, DL, DataHi, Ptr, Offset, MaskHi, HiMemVT, MMO,
4664 N->getAddressingMode(), N->isTruncatingStore(),
4665 N->isCompressingStore());
4666
4667 // Build a factor node to remember that this store is independent of the
4668 // other one.
4669 Res = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4670 }
4671
4672 return Res;
4673}
4674
4675SDValue DAGTypeLegalizer::SplitVecOp_Scatter(MemSDNode *N, unsigned OpNo) {
4676 SDValue Ch = N->getChain();
4677 SDValue Ptr = N->getBasePtr();
4678 EVT MemoryVT = N->getMemoryVT();
4679 Align Alignment = N->getBaseAlign();
4680 SDLoc DL(N);
4681 struct Operands {
4682 SDValue Mask;
4683 SDValue Index;
4684 SDValue Scale;
4685 SDValue Data;
4686 } Ops = [&]() -> Operands {
4687 if (auto *MSC = dyn_cast<MaskedScatterSDNode>(N)) {
4688 return {MSC->getMask(), MSC->getIndex(), MSC->getScale(),
4689 MSC->getValue()};
4690 }
4691 auto *VPSC = cast<VPScatterSDNode>(N);
4692 return {VPSC->getMask(), VPSC->getIndex(), VPSC->getScale(),
4693 VPSC->getValue()};
4694 }();
4695 // Split all operands
4696
4697 EVT LoMemVT, HiMemVT;
4698 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
4699
4700 SDValue DataLo, DataHi;
4701 if (getTypeAction(Ops.Data.getValueType()) == TargetLowering::TypeSplitVector)
4702 // Split Data operand
4703 GetSplitVector(Ops.Data, DataLo, DataHi);
4704 else
4705 std::tie(DataLo, DataHi) = DAG.SplitVector(Ops.Data, DL);
4706
4707 // Split Mask operand
4708 SDValue MaskLo, MaskHi;
4709 if (OpNo == 1 && Ops.Mask.getOpcode() == ISD::SETCC) {
4710 SplitVecRes_SETCC(Ops.Mask.getNode(), MaskLo, MaskHi);
4711 } else {
4712 std::tie(MaskLo, MaskHi) = SplitMask(Ops.Mask, DL);
4713 }
4714
4715 SDValue IndexHi, IndexLo;
4716 if (getTypeAction(Ops.Index.getValueType()) ==
4718 GetSplitVector(Ops.Index, IndexLo, IndexHi);
4719 else
4720 std::tie(IndexLo, IndexHi) = DAG.SplitVector(Ops.Index, DL);
4721
4722 SDValue Lo;
4723 MachineMemOperand::Flags MMOFlags = N->getMemOperand()->getFlags();
4724 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
4725 N->getPointerInfo(), MMOFlags, LocationSize::beforeOrAfterPointer(),
4726 Alignment, N->getAAInfo(), N->getRanges());
4727
4728 if (auto *MSC = dyn_cast<MaskedScatterSDNode>(N)) {
4729 SDValue OpsLo[] = {Ch, DataLo, MaskLo, Ptr, IndexLo, Ops.Scale};
4730 Lo =
4731 DAG.getMaskedScatter(DAG.getVTList(MVT::Other), LoMemVT, DL, OpsLo, MMO,
4732 MSC->getIndexType(), MSC->isTruncatingStore());
4733
4734 // The order of the Scatter operation after split is well defined. The "Hi"
4735 // part comes after the "Lo". So these two operations should be chained one
4736 // after another.
4737 SDValue OpsHi[] = {Lo, DataHi, MaskHi, Ptr, IndexHi, Ops.Scale};
4738 return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), HiMemVT, DL, OpsHi,
4739 MMO, MSC->getIndexType(),
4740 MSC->isTruncatingStore());
4741 }
4742 auto *VPSC = cast<VPScatterSDNode>(N);
4743 SDValue EVLLo, EVLHi;
4744 std::tie(EVLLo, EVLHi) =
4745 DAG.SplitEVL(VPSC->getVectorLength(), Ops.Data.getValueType(), DL);
4746
4747 SDValue OpsLo[] = {Ch, DataLo, Ptr, IndexLo, Ops.Scale, MaskLo, EVLLo};
4748 Lo = DAG.getScatterVP(DAG.getVTList(MVT::Other), LoMemVT, DL, OpsLo, MMO,
4749 VPSC->getIndexType());
4750
4751 // The order of the Scatter operation after split is well defined. The "Hi"
4752 // part comes after the "Lo". So these two operations should be chained one
4753 // after another.
4754 SDValue OpsHi[] = {Lo, DataHi, Ptr, IndexHi, Ops.Scale, MaskHi, EVLHi};
4755 return DAG.getScatterVP(DAG.getVTList(MVT::Other), HiMemVT, DL, OpsHi, MMO,
4756 VPSC->getIndexType());
4757}
4758
4759SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) {
4760 assert(N->isUnindexed() && "Indexed store of vector?");
4761 assert(OpNo == 1 && "Can only split the stored value");
4762 SDLoc DL(N);
4763
4764 bool isTruncating = N->isTruncatingStore();
4765 SDValue Ch = N->getChain();
4766 SDValue Ptr = N->getBasePtr();
4767 EVT MemoryVT = N->getMemoryVT();
4768 Align Alignment = N->getBaseAlign();
4769 MachineMemOperand::Flags MMOFlags = N->getMemOperand()->getFlags();
4770 AAMDNodes AAInfo = N->getAAInfo();
4771 SDValue Lo, Hi;
4772 GetSplitVector(N->getOperand(1), Lo, Hi);
4773
4774 EVT LoMemVT, HiMemVT;
4775 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
4776
4777 // Scalarize if the split halves are not byte-sized.
4778 if (!LoMemVT.isByteSized() || !HiMemVT.isByteSized())
4779 return TLI.scalarizeVectorStore(N, DAG);
4780
4781 if (isTruncating)
4782 Lo = DAG.getTruncStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), LoMemVT,
4783 Alignment, MMOFlags, AAInfo);
4784 else
4785 Lo = DAG.getStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), Alignment, MMOFlags,
4786 AAInfo);
4787
4788 MachinePointerInfo MPI;
4789 IncrementPointer(N, LoMemVT, MPI, Ptr);
4790
4791 if (isTruncating)
4792 Hi = DAG.getTruncStore(Ch, DL, Hi, Ptr, MPI,
4793 HiMemVT, Alignment, MMOFlags, AAInfo);
4794 else
4795 Hi = DAG.getStore(Ch, DL, Hi, Ptr, MPI, Alignment, MMOFlags, AAInfo);
4796
4797 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4798}
4799
4800SDValue DAGTypeLegalizer::SplitVecOp_ATOMIC_STORE(AtomicSDNode *N) {
4801 SDLoc DL(N);
4802 LLVMContext &Ctx = *DAG.getContext();
4803 SDValue StVal = N->getVal();
4804 EVT VT = StVal.getValueType();
4805 EVT MemIntVT = EVT::getIntegerVT(Ctx, N->getMemoryVT().getSizeInBits());
4806
4807 // The store needs a single value spanning the full memory width. If the
4808 // value can be held in a legal vector register, keep it there and extract
4809 // the low integer element of the memory width. This lets the store be issued
4810 // directly from a vector register (e.g. a single MOVQ/MOVD) instead of
4811 // bitcasting the split vector straight to a scalar integer, which would
4812 // reassemble the value element by element in GPRs.
4813 //
4814 // Reinterpret the value as a same-shaped integer vector first: an FP element
4815 // type may not have a legal vector form (e.g. bfloat on SSE2) while the
4816 // integer-of-element-size form does. Ask the target which legal vector type
4817 // it widens to.
4818 EVT IntVecVT = VT.changeVectorElementTypeToInteger();
4819 EVT IntEltVT = IntVecVT.getVectorElementType();
4820 EVT WideVT = TLI.getLegalTypeToTransformTo(Ctx, IntVecVT);
4821 if (DAG.getDataLayout().isLittleEndian() && TLI.isTypeLegal(MemIntVT) &&
4822 WideVT.isVector() && WideVT.getVectorElementType() == IntEltVT &&
4823 IntEltVT.getSizeInBits() <= MemIntVT.getSizeInBits() &&
4824 WideVT.getSizeInBits() % MemIntVT.getSizeInBits() == 0) {
4825 SDValue Wide = ModifyToType(DAG.getBitcast(IntVecVT, StVal), WideVT);
4826 unsigned NumMemElts = WideVT.getSizeInBits() / MemIntVT.getSizeInBits();
4827 EVT MemVecVT = EVT::getVectorVT(Ctx, MemIntVT, NumMemElts);
4828 SDValue Elt = DAG.getExtractVectorElt(DL, MemIntVT,
4829 DAG.getBitcast(MemVecVT, Wide), 0);
4830 return DAG.getAtomic(ISD::ATOMIC_STORE, DL, MemIntVT, N->getChain(), Elt,
4831 N->getBasePtr(), N->getMemOperand());
4832 }
4833
4834 // Otherwise issue a single atomic store of an integer that spans the full
4835 // memory width. Bitcasting the (illegal) vector value to that integer lets
4836 // the type legalizer further legalize the BITCAST input as needed, while the
4837 // ATOMIC_STORE itself uses only the legal integer type.
4838 EVT IntVT = EVT::getIntegerVT(Ctx, VT.getSizeInBits());
4839 SDValue AsInt = DAG.getBitcast(IntVT, StVal);
4840 return DAG.getAtomic(ISD::ATOMIC_STORE, DL, MemIntVT, N->getChain(), AsInt,
4841 N->getBasePtr(), N->getMemOperand());
4842}
4843
4844SDValue DAGTypeLegalizer::SplitVecOp_CONCAT_VECTORS(SDNode *N) {
4845 SDLoc DL(N);
4846
4847 // The input operands all must have the same type, and we know the result
4848 // type is valid. Convert this to a buildvector which extracts all the
4849 // input elements.
4850 // TODO: If the input elements are power-two vectors, we could convert this to
4851 // a new CONCAT_VECTORS node with elements that are half-wide.
4853 EVT EltVT = N->getValueType(0).getVectorElementType();
4854 for (const SDValue &Op : N->op_values()) {
4855 for (unsigned i = 0, e = Op.getValueType().getVectorNumElements();
4856 i != e; ++i) {
4857 Elts.push_back(DAG.getExtractVectorElt(DL, EltVT, Op, i));
4858 }
4859 }
4860
4861 return DAG.getBuildVector(N->getValueType(0), DL, Elts);
4862}
4863
4864SDValue DAGTypeLegalizer::SplitVecOp_TruncateHelper(SDNode *N) {
4865 // The result type is legal, but the input type is illegal. If splitting
4866 // ends up with the result type of each half still being legal, just
4867 // do that. If, however, that would result in an illegal result type,
4868 // we can try to get more clever with power-two vectors. Specifically,
4869 // split the input type, but also widen the result element size, then
4870 // concatenate the halves and truncate again. For example, consider a target
4871 // where v8i8 is legal and v8i32 is not (ARM, which doesn't have 256-bit
4872 // vectors). To perform a "%res = v8i8 trunc v8i32 %in" we do:
4873 // %inlo = v4i32 extract_subvector %in, 0
4874 // %inhi = v4i32 extract_subvector %in, 4
4875 // %lo16 = v4i16 trunc v4i32 %inlo
4876 // %hi16 = v4i16 trunc v4i32 %inhi
4877 // %in16 = v8i16 concat_vectors v4i16 %lo16, v4i16 %hi16
4878 // %res = v8i8 trunc v8i16 %in16
4879 //
4880 // Without this transform, the original truncate would end up being
4881 // scalarized, which is pretty much always a last resort.
4882 unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
4883 SDValue InVec = N->getOperand(OpNo);
4884 EVT InVT = InVec->getValueType(0);
4885 EVT OutVT = N->getValueType(0);
4886 ElementCount NumElements = OutVT.getVectorElementCount();
4887 bool IsFloat = OutVT.isFloatingPoint();
4888
4889 unsigned InElementSize = InVT.getScalarSizeInBits();
4890 unsigned OutElementSize = OutVT.getScalarSizeInBits();
4891
4892 // Determine the split output VT. If its legal we can just split dirctly.
4893 EVT LoOutVT, HiOutVT;
4894 std::tie(LoOutVT, HiOutVT) = DAG.GetSplitDestVTs(OutVT);
4895 assert(LoOutVT == HiOutVT && "Unequal split?");
4896
4897 // If the input elements are only 1/2 the width of the result elements,
4898 // just use the normal splitting. Our trick only work if there's room
4899 // to split more than once.
4900 if (isTypeLegal(LoOutVT) || InElementSize <= OutElementSize * 2 ||
4901 (IsFloat && !isPowerOf2_32(InElementSize)))
4902 return SplitVecOp_UnaryOp(N);
4903 SDLoc DL(N);
4904
4905 // Don't touch if this will be scalarized.
4906 EVT FinalVT = InVT;
4907 while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
4908 FinalVT = FinalVT.getHalfNumVectorElementsVT(*DAG.getContext());
4909
4910 if (getTypeAction(FinalVT) == TargetLowering::TypeScalarizeVector)
4911 return SplitVecOp_UnaryOp(N);
4912
4913 // Get the split input vector.
4914 SDValue InLoVec, InHiVec;
4915 GetSplitVector(InVec, InLoVec, InHiVec);
4916
4917 // Truncate them to 1/2 the element size.
4918 //
4919 // This assumes the number of elements is a power of two; any vector that
4920 // isn't should be widened, not split.
4921 EVT HalfElementVT = IsFloat ?
4922 EVT::getFloatingPointVT(InElementSize/2) :
4923 EVT::getIntegerVT(*DAG.getContext(), InElementSize/2);
4924 EVT HalfVT = EVT::getVectorVT(*DAG.getContext(), HalfElementVT,
4925 NumElements.divideCoefficientBy(2));
4926
4927 SDValue HalfLo;
4928 SDValue HalfHi;
4929 SDValue Chain;
4930 if (N->isStrictFPOpcode()) {
4931 HalfLo = DAG.getNode(N->getOpcode(), DL, {HalfVT, MVT::Other},
4932 {N->getOperand(0), InLoVec});
4933 HalfHi = DAG.getNode(N->getOpcode(), DL, {HalfVT, MVT::Other},
4934 {N->getOperand(0), InHiVec});
4935 // Legalize the chain result - switch anything that used the old chain to
4936 // use the new one.
4937 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, HalfLo.getValue(1),
4938 HalfHi.getValue(1));
4939 } else {
4940 HalfLo = DAG.getNode(N->getOpcode(), DL, HalfVT, InLoVec);
4941 HalfHi = DAG.getNode(N->getOpcode(), DL, HalfVT, InHiVec);
4942 }
4943
4944 // Concatenate them to get the full intermediate truncation result.
4945 EVT InterVT = EVT::getVectorVT(*DAG.getContext(), HalfElementVT, NumElements);
4946 SDValue InterVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InterVT, HalfLo,
4947 HalfHi);
4948 // Now finish up by truncating all the way down to the original result
4949 // type. This should normally be something that ends up being legal directly,
4950 // but in theory if a target has very wide vectors and an annoyingly
4951 // restricted set of legal types, this split can chain to build things up.
4952
4953 if (N->isStrictFPOpcode()) {
4954 SDValue Res = DAG.getNode(
4955 ISD::STRICT_FP_ROUND, DL, {OutVT, MVT::Other},
4956 {Chain, InterVec,
4957 DAG.getTargetConstant(0, DL, TLI.getPointerTy(DAG.getDataLayout()))});
4958 // Relink the chain
4959 ReplaceValueWith(SDValue(N, 1), SDValue(Res.getNode(), 1));
4960 return Res;
4961 }
4962
4963 return IsFloat
4964 ? DAG.getNode(ISD::FP_ROUND, DL, OutVT, InterVec,
4965 DAG.getTargetConstant(
4966 0, DL, TLI.getPointerTy(DAG.getDataLayout())))
4967 : DAG.getNode(ISD::TRUNCATE, DL, OutVT, InterVec);
4968}
4969
4970SDValue DAGTypeLegalizer::SplitVecOp_VSETCC(SDNode *N) {
4971 unsigned Opc = N->getOpcode();
4972 bool isStrict = Opc == ISD::STRICT_FSETCC || Opc == ISD::STRICT_FSETCCS;
4973 assert(N->getValueType(0).isVector() &&
4974 N->getOperand(isStrict ? 1 : 0).getValueType().isVector() &&
4975 "Operand types must be vectors");
4976 // The result has a legal vector type, but the input needs splitting.
4977 SDValue Lo0, Hi0, Lo1, Hi1, LoRes, HiRes;
4978 SDLoc DL(N);
4979 GetSplitVector(N->getOperand(isStrict ? 1 : 0), Lo0, Hi0);
4980 GetSplitVector(N->getOperand(isStrict ? 2 : 1), Lo1, Hi1);
4981
4982 EVT VT = N->getValueType(0);
4983 EVT PartResVT = getSetCCResultType(Lo0.getValueType());
4984
4985 if (Opc == ISD::SETCC) {
4986 LoRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Lo0, Lo1, N->getOperand(2));
4987 HiRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Hi0, Hi1, N->getOperand(2));
4988 } else if (isStrict) {
4989 LoRes = DAG.getNode(Opc, DL, DAG.getVTList(PartResVT, N->getValueType(1)),
4990 N->getOperand(0), Lo0, Lo1, N->getOperand(3));
4991 HiRes = DAG.getNode(Opc, DL, DAG.getVTList(PartResVT, N->getValueType(1)),
4992 N->getOperand(0), Hi0, Hi1, N->getOperand(3));
4993 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
4994 LoRes.getValue(1), HiRes.getValue(1));
4995 ReplaceValueWith(SDValue(N, 1), NewChain);
4996 } else {
4997 assert(Opc == ISD::VP_SETCC && "Expected VP_SETCC opcode");
4998 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
4999 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(3));
5000 std::tie(EVLLo, EVLHi) =
5001 DAG.SplitEVL(N->getOperand(4), N->getValueType(0), DL);
5002 LoRes = DAG.getNode(ISD::VP_SETCC, DL, PartResVT, Lo0, Lo1,
5003 N->getOperand(2), MaskLo, EVLLo);
5004 HiRes = DAG.getNode(ISD::VP_SETCC, DL, PartResVT, Hi0, Hi1,
5005 N->getOperand(2), MaskHi, EVLHi);
5006 }
5007
5008 EVT ConcatVT = PartResVT.getDoubleNumVectorElementsVT(*DAG.getContext());
5009 SDValue Con = DAG.getNode(ISD::CONCAT_VECTORS, DL, ConcatVT, LoRes, HiRes);
5010 if (VT == ConcatVT)
5011 return Con;
5012
5013 EVT OpVT = N->getOperand(0).getValueType();
5014 ISD::NodeType ExtendCode =
5015 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
5016 return DAG.getExtOrTrunc(Con, DL, VT, ExtendCode);
5017}
5018
5019
5020SDValue DAGTypeLegalizer::SplitVecOp_FP_ROUND(SDNode *N) {
5021 // The result has a legal vector type, but the input needs splitting.
5022 EVT ResVT = N->getValueType(0);
5023 SDValue Lo, Hi;
5024 SDLoc DL(N);
5025 GetSplitVector(N->getOperand(N->isStrictFPOpcode() ? 1 : 0), Lo, Hi);
5026 EVT InVT = Lo.getValueType();
5027
5028 EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
5029 InVT.getVectorElementCount());
5030
5031 if (N->isStrictFPOpcode()) {
5032 Lo = DAG.getNode(N->getOpcode(), DL, {OutVT, MVT::Other},
5033 {N->getOperand(0), Lo, N->getOperand(2)});
5034 Hi = DAG.getNode(N->getOpcode(), DL, {OutVT, MVT::Other},
5035 {N->getOperand(0), Hi, N->getOperand(2)});
5036 // Legalize the chain result - switch anything that used the old chain to
5037 // use the new one.
5038 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
5039 Lo.getValue(1), Hi.getValue(1));
5040 ReplaceValueWith(SDValue(N, 1), NewChain);
5041 } else if (N->getOpcode() == ISD::VP_FP_ROUND) {
5042 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
5043 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
5044 std::tie(EVLLo, EVLHi) =
5045 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), DL);
5046 Lo = DAG.getNode(ISD::VP_FP_ROUND, DL, OutVT, Lo, MaskLo, EVLLo);
5047 Hi = DAG.getNode(ISD::VP_FP_ROUND, DL, OutVT, Hi, MaskHi, EVLHi);
5048 } else if (N->getOpcode() == ISD::CONVERT_TO_ARBITRARY_FP) {
5049 Lo = DAG.getNode(N->getOpcode(), DL, OutVT, Lo, N->getOperand(1),
5050 N->getOperand(2), N->getOperand(3));
5051 Hi = DAG.getNode(N->getOpcode(), DL, OutVT, Hi, N->getOperand(1),
5052 N->getOperand(2), N->getOperand(3));
5053 } else {
5054 Lo = DAG.getNode(N->getOpcode(), DL, OutVT, Lo, N->getOperand(1));
5055 Hi = DAG.getNode(N->getOpcode(), DL, OutVT, Hi, N->getOperand(1));
5056 }
5057
5058 return DAG.getNode(ISD::CONCAT_VECTORS, DL, ResVT, Lo, Hi);
5059}
5060
5061// Split a vector type in an FP binary operation where the second operand has a
5062// different type from the first.
5063//
5064// The result (and the first input) has a legal vector type, but the second
5065// input needs splitting.
5066SDValue DAGTypeLegalizer::SplitVecOp_FPOpDifferentTypes(SDNode *N) {
5067 SDLoc DL(N);
5068
5069 EVT LHSLoVT, LHSHiVT;
5070 std::tie(LHSLoVT, LHSHiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
5071
5072 if (!isTypeLegal(LHSLoVT) || !isTypeLegal(LHSHiVT))
5073 return DAG.UnrollVectorOp(N, N->getValueType(0).getVectorNumElements());
5074
5075 SDValue LHSLo, LHSHi;
5076 std::tie(LHSLo, LHSHi) =
5077 DAG.SplitVector(N->getOperand(0), DL, LHSLoVT, LHSHiVT);
5078
5079 SDValue RHSLo, RHSHi;
5080 std::tie(RHSLo, RHSHi) = DAG.SplitVector(N->getOperand(1), DL);
5081
5082 SDValue Lo = DAG.getNode(N->getOpcode(), DL, LHSLoVT, LHSLo, RHSLo);
5083 SDValue Hi = DAG.getNode(N->getOpcode(), DL, LHSHiVT, LHSHi, RHSHi);
5084
5085 return DAG.getNode(ISD::CONCAT_VECTORS, DL, N->getValueType(0), Lo, Hi);
5086}
5087
5088SDValue DAGTypeLegalizer::SplitVecOp_CMP(SDNode *N) {
5089 LLVMContext &Ctxt = *DAG.getContext();
5090 SDLoc dl(N);
5091
5092 SDValue LHSLo, LHSHi, RHSLo, RHSHi;
5093 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
5094 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
5095
5096 EVT ResVT = N->getValueType(0);
5097 ElementCount SplitOpEC = LHSLo.getValueType().getVectorElementCount();
5098 EVT NewResVT =
5099 EVT::getVectorVT(Ctxt, ResVT.getVectorElementType(), SplitOpEC);
5100
5101 SDValue Lo = DAG.getNode(N->getOpcode(), dl, NewResVT, LHSLo, RHSLo);
5102 SDValue Hi = DAG.getNode(N->getOpcode(), dl, NewResVT, LHSHi, RHSHi);
5103
5104 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
5105}
5106
5107SDValue DAGTypeLegalizer::SplitVecOp_FP_TO_XINT_SAT(SDNode *N) {
5108 EVT ResVT = N->getValueType(0);
5109 SDValue Lo, Hi;
5110 SDLoc dl(N);
5111 GetSplitVector(N->getOperand(0), Lo, Hi);
5112 EVT InVT = Lo.getValueType();
5113
5114 EVT NewResVT =
5115 EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
5116 InVT.getVectorElementCount());
5117
5118 Lo = DAG.getNode(N->getOpcode(), dl, NewResVT, Lo, N->getOperand(1));
5119 Hi = DAG.getNode(N->getOpcode(), dl, NewResVT, Hi, N->getOperand(1));
5120
5121 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
5122}
5123
5124SDValue DAGTypeLegalizer::SplitVecOp_CttzElts(SDNode *N) {
5125 SDLoc DL(N);
5126 EVT ResVT = N->getValueType(0);
5127
5128 SDValue Lo, Hi;
5129 SDValue VecOp = N->getOperand(0);
5130 GetSplitVector(VecOp, Lo, Hi);
5131
5132 // if CTTZ_ELTS(Lo) != VL => CTTZ_ELTS(Lo).
5133 // else => VL + (CTTZ_ELTS(Hi) or CTTZ_ELTS_ZERO_POISON(Hi)).
5134 SDValue ResLo = DAG.getNode(ISD::CTTZ_ELTS, DL, ResVT, Lo);
5135 SDValue VL =
5136 DAG.getElementCount(DL, ResVT, Lo.getValueType().getVectorElementCount());
5137 SDValue ResLoNotVL =
5138 DAG.getSetCC(DL, getSetCCResultType(ResVT), ResLo, VL, ISD::SETNE);
5139 SDValue ResHi = DAG.getNode(N->getOpcode(), DL, ResVT, Hi);
5140 return DAG.getSelect(DL, ResVT, ResLoNotVL, ResLo,
5141 DAG.getNode(ISD::ADD, DL, ResVT, VL, ResHi));
5142}
5143
5144SDValue DAGTypeLegalizer::SplitVecOp_VP_CttzElements(SDNode *N) {
5145 SDLoc DL(N);
5146 EVT ResVT = N->getValueType(0);
5147
5148 SDValue Lo, Hi;
5149 SDValue VecOp = N->getOperand(0);
5150 GetSplitVector(VecOp, Lo, Hi);
5151
5152 auto [MaskLo, MaskHi] = SplitMask(N->getOperand(1));
5153 auto [EVLLo, EVLHi] =
5154 DAG.SplitEVL(N->getOperand(2), VecOp.getValueType(), DL);
5155 SDValue VLo = DAG.getZExtOrTrunc(EVLLo, DL, ResVT);
5156
5157 // if VP_CTTZ_ELTS(Lo) != EVLLo => VP_CTTZ_ELTS(Lo).
5158 // else => EVLLo + (VP_CTTZ_ELTS(Hi) or VP_CTTZ_ELTS_ZERO_POISON(Hi)).
5159 SDValue ResLo = DAG.getNode(ISD::VP_CTTZ_ELTS, DL, ResVT, Lo, MaskLo, EVLLo);
5160 SDValue ResLoNotEVL =
5161 DAG.getSetCC(DL, getSetCCResultType(ResVT), ResLo, VLo, ISD::SETNE);
5162 SDValue ResHi = DAG.getNode(N->getOpcode(), DL, ResVT, Hi, MaskHi, EVLHi);
5163 return DAG.getSelect(DL, ResVT, ResLoNotEVL, ResLo,
5164 DAG.getNode(ISD::ADD, DL, ResVT, VLo, ResHi));
5165}
5166
5167SDValue DAGTypeLegalizer::SplitVecOp_VECTOR_HISTOGRAM(SDNode *N) {
5168 MaskedHistogramSDNode *HG = cast<MaskedHistogramSDNode>(N);
5169 SDLoc DL(HG);
5170 SDValue Inc = HG->getInc();
5171 SDValue Ptr = HG->getBasePtr();
5172 SDValue Scale = HG->getScale();
5173 SDValue IntID = HG->getIntID();
5174 EVT MemVT = HG->getMemoryVT();
5175 MachineMemOperand *MMO = HG->getMemOperand();
5176 ISD::MemIndexType IndexType = HG->getIndexType();
5177
5178 SDValue IndexLo, IndexHi, MaskLo, MaskHi;
5179 std::tie(IndexLo, IndexHi) = DAG.SplitVector(HG->getIndex(), DL);
5180 std::tie(MaskLo, MaskHi) = DAG.SplitVector(HG->getMask(), DL);
5181 SDValue OpsLo[] = {HG->getChain(), Inc, MaskLo, Ptr, IndexLo, Scale, IntID};
5182 SDValue Lo = DAG.getMaskedHistogram(DAG.getVTList(MVT::Other), MemVT, DL,
5183 OpsLo, MMO, IndexType);
5184 SDValue OpsHi[] = {Lo, Inc, MaskHi, Ptr, IndexHi, Scale, IntID};
5185 return DAG.getMaskedHistogram(DAG.getVTList(MVT::Other), MemVT, DL, OpsHi,
5186 MMO, IndexType);
5187}
5188
5189SDValue DAGTypeLegalizer::SplitVecOp_PARTIAL_REDUCE_MLA(SDNode *N) {
5190 SDValue Acc = N->getOperand(0);
5191 assert(getTypeAction(Acc.getValueType()) != TargetLowering::TypeSplitVector &&
5192 "Accumulator should already be a legal type, and shouldn't need "
5193 "further splitting");
5194
5195 SDLoc DL(N);
5196 SDValue Input1Lo, Input1Hi, Input2Lo, Input2Hi;
5197 GetSplitVector(N->getOperand(1), Input1Lo, Input1Hi);
5198 GetSplitVector(N->getOperand(2), Input2Lo, Input2Hi);
5199 unsigned Opcode = N->getOpcode();
5200 EVT ResultVT = Acc.getValueType();
5201
5202 SDValue Lo = DAG.getNode(Opcode, DL, ResultVT, Acc, Input1Lo, Input2Lo);
5203 return DAG.getNode(Opcode, DL, ResultVT, Lo, Input1Hi, Input2Hi);
5204}
5205
5206//===----------------------------------------------------------------------===//
5207// Result Vector Widening
5208//===----------------------------------------------------------------------===//
5209
5210void DAGTypeLegalizer::ReplaceOtherWidenResults(SDNode *N, SDNode *WidenNode,
5211 unsigned WidenResNo) {
5212 unsigned NumResults = N->getNumValues();
5213 for (unsigned ResNo = 0; ResNo < NumResults; ResNo++) {
5214 if (ResNo == WidenResNo)
5215 continue;
5216 EVT ResVT = N->getValueType(ResNo);
5217 if (getTypeAction(ResVT) == TargetLowering::TypeWidenVector) {
5218 SetWidenedVector(SDValue(N, ResNo), SDValue(WidenNode, ResNo));
5219 } else {
5220 SDLoc DL(N);
5221 SDValue ResVal =
5222 DAG.getExtractSubvector(DL, ResVT, SDValue(WidenNode, ResNo), 0);
5223 ReplaceValueWith(SDValue(N, ResNo), ResVal);
5224 }
5225 }
5226}
5227
5228void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
5229 LLVM_DEBUG(dbgs() << "Widen node result " << ResNo << ": "; N->dump(&DAG));
5230
5231 // See if the target wants to custom widen this node.
5232 if (CustomWidenLowerNode(N, N->getValueType(ResNo)))
5233 return;
5234
5235 SDValue Res = SDValue();
5236
5237 auto unrollExpandedOp = [&]() {
5238 // We're going to widen this vector op to a legal type by padding with undef
5239 // elements. If the wide vector op is eventually going to be expanded to
5240 // scalar libcalls, then unroll into scalar ops now to avoid unnecessary
5241 // libcalls on the undef elements.
5242 EVT VT = N->getValueType(0);
5243 EVT WideVecVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
5244 if (!TLI.isOperationLegalOrCustomOrPromote(N->getOpcode(), WideVecVT) &&
5245 TLI.isOperationExpandOrLibCall(N->getOpcode(), VT.getScalarType())) {
5246 Res = DAG.UnrollVectorOp(N, WideVecVT.getVectorNumElements());
5247 if (N->getNumValues() > 1)
5248 ReplaceOtherWidenResults(N, Res.getNode(), ResNo);
5249 return true;
5250 }
5251 return false;
5252 };
5253
5254 switch (N->getOpcode()) {
5255 default:
5256#ifndef NDEBUG
5257 dbgs() << "WidenVectorResult #" << ResNo << ": ";
5258 N->dump(&DAG);
5259 dbgs() << "\n";
5260#endif
5261 report_fatal_error("Do not know how to widen the result of this operator!");
5262
5265 Res = WidenVecRes_LOOP_DEPENDENCE_MASK(N);
5266 break;
5267 case ISD::MERGE_VALUES: Res = WidenVecRes_MERGE_VALUES(N, ResNo); break;
5268 case ISD::ADDRSPACECAST:
5269 Res = WidenVecRes_ADDRSPACECAST(N);
5270 break;
5271 case ISD::AssertZext: Res = WidenVecRes_AssertZext(N); break;
5272 case ISD::BITCAST: Res = WidenVecRes_BITCAST(N); break;
5273 case ISD::BUILD_VECTOR: Res = WidenVecRes_BUILD_VECTOR(N); break;
5274 case ISD::CONCAT_VECTORS: Res = WidenVecRes_CONCAT_VECTORS(N); break;
5276 Res = WidenVecRes_INSERT_SUBVECTOR(N);
5277 break;
5278 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecRes_EXTRACT_SUBVECTOR(N); break;
5279 case ISD::INSERT_VECTOR_ELT: Res = WidenVecRes_INSERT_VECTOR_ELT(N); break;
5280 case ISD::ATOMIC_LOAD:
5281 Res = WidenVecRes_ATOMIC_LOAD(cast<AtomicSDNode>(N));
5282 break;
5283 case ISD::LOAD: Res = WidenVecRes_LOAD(N); break;
5284 case ISD::STEP_VECTOR:
5285 case ISD::SPLAT_VECTOR:
5287 Res = WidenVecRes_ScalarOp(N);
5288 break;
5289 case ISD::SIGN_EXTEND_INREG: Res = WidenVecRes_InregOp(N); break;
5290 case ISD::VSELECT:
5291 case ISD::SELECT:
5292 case ISD::VP_SELECT:
5293 case ISD::VP_MERGE:
5294 Res = WidenVecRes_Select(N);
5295 break;
5296 case ISD::SELECT_CC: Res = WidenVecRes_SELECT_CC(N); break;
5297 case ISD::VP_SETCC:
5298 case ISD::SETCC: Res = WidenVecRes_SETCC(N); break;
5299 case ISD::POISON:
5300 case ISD::UNDEF: Res = WidenVecRes_UNDEF(N); break;
5302 Res = WidenVecRes_VECTOR_SHUFFLE(cast<ShuffleVectorSDNode>(N));
5303 break;
5304 case ISD::VP_LOAD:
5305 Res = WidenVecRes_VP_LOAD(cast<VPLoadSDNode>(N));
5306 break;
5307 case ISD::VP_LOAD_FF:
5308 Res = WidenVecRes_VP_LOAD_FF(cast<VPLoadFFSDNode>(N));
5309 break;
5310 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
5311 Res = WidenVecRes_VP_STRIDED_LOAD(cast<VPStridedLoadSDNode>(N));
5312 break;
5314 Res = WidenVecRes_VECTOR_COMPRESS(N);
5315 break;
5316 case ISD::MLOAD:
5317 Res = WidenVecRes_MLOAD(cast<MaskedLoadSDNode>(N));
5318 break;
5319 case ISD::MGATHER:
5320 Res = WidenVecRes_MGATHER(cast<MaskedGatherSDNode>(N));
5321 break;
5322 case ISD::VP_GATHER:
5323 Res = WidenVecRes_VP_GATHER(cast<VPGatherSDNode>(N));
5324 break;
5326 Res = WidenVecRes_VECTOR_REVERSE(N);
5327 break;
5329 Res = WidenVecRes_GET_ACTIVE_LANE_MASK(N);
5330 break;
5332 WidenVecRes_VECTOR_DEINTERLEAVE(N);
5333 break;
5334
5335 case ISD::ADD: case ISD::VP_ADD:
5336 case ISD::AND: case ISD::VP_AND:
5337 case ISD::MUL: case ISD::VP_MUL:
5338 case ISD::MULHS:
5339 case ISD::MULHU:
5340 case ISD::ABDS:
5341 case ISD::ABDU:
5342 case ISD::OR: case ISD::VP_OR:
5343 case ISD::SUB: case ISD::VP_SUB:
5344 case ISD::XOR: case ISD::VP_XOR:
5345 case ISD::SHL: case ISD::VP_SHL:
5346 case ISD::SRA: case ISD::VP_SRA:
5347 case ISD::SRL: case ISD::VP_SRL:
5348 case ISD::CLMUL:
5349 case ISD::CLMULR:
5350 case ISD::CLMULH:
5351 case ISD::PEXT:
5352 case ISD::PDEP:
5353 case ISD::FMINNUM:
5354 case ISD::FMINNUM_IEEE:
5355 case ISD::VP_FMINNUM:
5356 case ISD::FMAXNUM:
5357 case ISD::FMAXNUM_IEEE:
5358 case ISD::VP_FMAXNUM:
5359 case ISD::FMINIMUM:
5360 case ISD::VP_FMINIMUM:
5361 case ISD::FMAXIMUM:
5362 case ISD::VP_FMAXIMUM:
5363 case ISD::FMINIMUMNUM:
5364 case ISD::FMAXIMUMNUM:
5365 case ISD::SMIN: case ISD::VP_SMIN:
5366 case ISD::SMAX: case ISD::VP_SMAX:
5367 case ISD::UMIN: case ISD::VP_UMIN:
5368 case ISD::UMAX: case ISD::VP_UMAX:
5369 case ISD::UADDSAT: case ISD::VP_UADDSAT:
5370 case ISD::SADDSAT: case ISD::VP_SADDSAT:
5371 case ISD::USUBSAT: case ISD::VP_USUBSAT:
5372 case ISD::SSUBSAT: case ISD::VP_SSUBSAT:
5373 case ISD::SSHLSAT:
5374 case ISD::USHLSAT:
5375 case ISD::ROTL:
5376 case ISD::ROTR:
5377 case ISD::AVGFLOORS:
5378 case ISD::AVGFLOORU:
5379 case ISD::AVGCEILS:
5380 case ISD::AVGCEILU:
5381 // Vector-predicated binary op widening. Note that -- unlike the
5382 // unpredicated versions -- we don't have to worry about trapping on
5383 // operations like UDIV, FADD, etc., as we pass on the original vector
5384 // length parameter. This means the widened elements containing garbage
5385 // aren't active.
5386 case ISD::VP_SDIV:
5387 case ISD::VP_UDIV:
5388 case ISD::VP_SREM:
5389 case ISD::VP_UREM:
5390 case ISD::VP_FADD:
5391 case ISD::VP_FSUB:
5392 case ISD::VP_FMUL:
5393 case ISD::VP_FDIV:
5394 case ISD::VP_FREM:
5395 case ISD::VP_FCOPYSIGN:
5396 Res = WidenVecRes_Binary(N);
5397 break;
5398
5399 case ISD::MASKED_UDIV:
5400 case ISD::MASKED_SDIV:
5401 case ISD::MASKED_UREM:
5402 case ISD::MASKED_SREM:
5403 Res = WidenVecRes_MaskedBinary(N);
5404 break;
5405
5406 case ISD::SCMP:
5407 case ISD::UCMP:
5408 Res = WidenVecRes_CMP(N);
5409 break;
5410
5411 case ISD::FPOW:
5412 case ISD::FATAN2:
5413 case ISD::FREM:
5414 if (unrollExpandedOp())
5415 break;
5416 // If the target has custom/legal support for the scalar FP intrinsic ops
5417 // (they are probably not destined to become libcalls), then widen those
5418 // like any other binary ops.
5419 [[fallthrough]];
5420
5421 case ISD::FADD:
5422 case ISD::FMUL:
5423 case ISD::FSUB:
5424 case ISD::FDIV:
5425 case ISD::SDIV:
5426 case ISD::UDIV:
5427 case ISD::SREM:
5428 case ISD::UREM:
5429 Res = WidenVecRes_BinaryCanTrap(N);
5430 break;
5431
5432 case ISD::SMULFIX:
5433 case ISD::SMULFIXSAT:
5434 case ISD::UMULFIX:
5435 case ISD::UMULFIXSAT:
5436 // These are binary operations, but with an extra operand that shouldn't
5437 // be widened (the scale).
5438 Res = WidenVecRes_BinaryWithExtraScalarOp(N);
5439 break;
5440
5441#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
5442 case ISD::STRICT_##DAGN:
5443#include "llvm/IR/ConstrainedOps.def"
5444 Res = WidenVecRes_StrictFP(N);
5445 break;
5446
5447 case ISD::UADDO:
5448 case ISD::SADDO:
5449 case ISD::USUBO:
5450 case ISD::SSUBO:
5451 case ISD::UMULO:
5452 case ISD::SMULO:
5453 Res = WidenVecRes_OverflowOp(N, ResNo);
5454 break;
5455
5456 case ISD::FCOPYSIGN:
5457 Res = WidenVecRes_FCOPYSIGN(N);
5458 break;
5459
5460 case ISD::IS_FPCLASS:
5461 case ISD::FPTRUNC_ROUND:
5462 Res = WidenVecRes_UnarySameEltsWithScalarArg(N);
5463 break;
5464
5465 case ISD::FLDEXP:
5466 case ISD::FPOWI:
5467 if (!unrollExpandedOp())
5468 Res = WidenVecRes_ExpOp(N);
5469 break;
5470
5474 Res = WidenVecRes_EXTEND_VECTOR_INREG(N);
5475 break;
5476
5477 case ISD::ANY_EXTEND:
5478 case ISD::FP_EXTEND:
5479 case ISD::VP_FP_EXTEND:
5480 case ISD::FP_ROUND:
5481 case ISD::VP_FP_ROUND:
5482 case ISD::FP_TO_SINT:
5483 case ISD::VP_FP_TO_SINT:
5484 case ISD::FP_TO_UINT:
5485 case ISD::VP_FP_TO_UINT:
5486 case ISD::SIGN_EXTEND:
5487 case ISD::VP_SIGN_EXTEND:
5488 case ISD::SINT_TO_FP:
5489 case ISD::VP_SINT_TO_FP:
5490 case ISD::VP_TRUNCATE:
5491 case ISD::TRUNCATE:
5492 case ISD::UINT_TO_FP:
5493 case ISD::VP_UINT_TO_FP:
5494 case ISD::ZERO_EXTEND:
5495 case ISD::VP_ZERO_EXTEND:
5498 Res = WidenVecRes_Convert(N);
5499 break;
5500
5503 Res = WidenVecRes_FP_TO_XINT_SAT(N);
5504 break;
5505
5506 case ISD::LRINT:
5507 case ISD::LLRINT:
5508 case ISD::VP_LRINT:
5509 case ISD::VP_LLRINT:
5510 case ISD::LROUND:
5511 case ISD::LLROUND:
5512 Res = WidenVecRes_XROUND(N);
5513 break;
5514
5515 case ISD::FACOS:
5516 case ISD::FASIN:
5517 case ISD::FATAN:
5518 case ISD::FCEIL:
5519 case ISD::FCOS:
5520 case ISD::FCOSH:
5521 case ISD::FEXP:
5522 case ISD::FEXP2:
5523 case ISD::FEXP10:
5524 case ISD::FFLOOR:
5525 case ISD::FLOG:
5526 case ISD::FLOG10:
5527 case ISD::FLOG2:
5528 case ISD::FNEARBYINT:
5529 case ISD::FRINT:
5530 case ISD::FROUND:
5531 case ISD::FROUNDEVEN:
5532 case ISD::FSIN:
5533 case ISD::FSINH:
5534 case ISD::FSQRT:
5535 case ISD::FTAN:
5536 case ISD::FTANH:
5537 case ISD::FTRUNC:
5538 if (unrollExpandedOp())
5539 break;
5540 // If the target has custom/legal support for the scalar FP intrinsic ops
5541 // (they are probably not destined to become libcalls), then widen those
5542 // like any other unary ops.
5543 [[fallthrough]];
5544
5545 case ISD::ABS:
5547 case ISD::VP_ABS:
5548 case ISD::BITREVERSE:
5549 case ISD::VP_BITREVERSE:
5550 case ISD::BSWAP:
5551 case ISD::VP_BSWAP:
5552 case ISD::CTLZ:
5553 case ISD::VP_CTLZ:
5555 case ISD::VP_CTLZ_ZERO_POISON:
5556 case ISD::CTPOP:
5557 case ISD::VP_CTPOP:
5558 case ISD::CTTZ:
5559 case ISD::VP_CTTZ:
5561 case ISD::VP_CTTZ_ZERO_POISON:
5562 case ISD::FNEG: case ISD::VP_FNEG:
5563 case ISD::FABS: case ISD::VP_FABS:
5564 case ISD::VP_SQRT:
5565 case ISD::VP_FCEIL:
5566 case ISD::VP_FFLOOR:
5567 case ISD::VP_FRINT:
5568 case ISD::VP_FNEARBYINT:
5569 case ISD::VP_FROUND:
5570 case ISD::VP_FROUNDEVEN:
5571 case ISD::VP_FROUNDTOZERO:
5572 case ISD::FREEZE:
5573 case ISD::ARITH_FENCE:
5574 case ISD::FCANONICALIZE:
5576 Res = WidenVecRes_Unary(N);
5577 break;
5578 case ISD::FMA: case ISD::VP_FMA:
5579 case ISD::FSHL:
5580 case ISD::VP_FSHL:
5581 case ISD::FSHR:
5582 case ISD::VP_FSHR:
5583 Res = WidenVecRes_Ternary(N);
5584 break;
5585 case ISD::FMODF:
5586 case ISD::FFREXP:
5587 case ISD::FSINCOS:
5588 case ISD::FSINCOSPI: {
5589 if (!unrollExpandedOp())
5590 Res = WidenVecRes_UnaryOpWithTwoResults(N, ResNo);
5591 break;
5592 }
5593 }
5594
5595 // If Res is null, the sub-method took care of registering the result.
5596 if (Res.getNode())
5597 SetWidenedVector(SDValue(N, ResNo), Res);
5598}
5599
5600SDValue DAGTypeLegalizer::WidenVecRes_Ternary(SDNode *N) {
5601 // Ternary op widening.
5602 SDLoc dl(N);
5603 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5604 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5605 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5606 SDValue InOp3 = GetWidenedVector(N->getOperand(2));
5607 if (N->getNumOperands() == 3)
5608 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3);
5609
5610 assert(N->getNumOperands() == 5 && "Unexpected number of operands!");
5611 assert(N->isVPOpcode() && "Expected VP opcode");
5612
5613 SDValue Mask =
5614 GetWidenedMask(N->getOperand(3), WidenVT.getVectorElementCount());
5615 return DAG.getNode(N->getOpcode(), dl, WidenVT,
5616 {InOp1, InOp2, InOp3, Mask, N->getOperand(4)});
5617}
5618
5619SDValue DAGTypeLegalizer::WidenVecRes_Binary(SDNode *N) {
5620 // Binary op widening.
5621 SDLoc dl(N);
5622 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5623 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5624 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5625 if (N->getNumOperands() == 2)
5626 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2,
5627 N->getFlags());
5628
5629 assert(N->getNumOperands() == 4 && "Unexpected number of operands!");
5630 assert(N->isVPOpcode() && "Expected VP opcode");
5631
5632 SDValue Mask =
5633 GetWidenedMask(N->getOperand(2), WidenVT.getVectorElementCount());
5634 return DAG.getNode(N->getOpcode(), dl, WidenVT,
5635 {InOp1, InOp2, Mask, N->getOperand(3)}, N->getFlags());
5636}
5637
5638SDValue DAGTypeLegalizer::WidenVecRes_MaskedBinary(SDNode *N) {
5639 SDLoc dl(N);
5640 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5641 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5642 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5643 SDValue Mask = N->getOperand(2);
5644 EVT WideMaskVT = WidenVT.changeVectorElementType(
5645 *DAG.getContext(), Mask.getValueType().getVectorElementType());
5646 Mask = ModifyToType(Mask, WideMaskVT, /*FillWithZeros=*/true);
5647 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, Mask,
5648 N->getFlags());
5649}
5650
5651SDValue DAGTypeLegalizer::WidenVecRes_CMP(SDNode *N) {
5652 LLVMContext &Ctxt = *DAG.getContext();
5653 SDLoc dl(N);
5654
5655 SDValue LHS = N->getOperand(0);
5656 SDValue RHS = N->getOperand(1);
5657 EVT OpVT = LHS.getValueType();
5658 if (getTypeAction(OpVT) == TargetLowering::TypeWidenVector) {
5659 LHS = GetWidenedVector(LHS);
5660 RHS = GetWidenedVector(RHS);
5661 OpVT = LHS.getValueType();
5662 }
5663
5664 EVT WidenResVT = TLI.getTypeToTransformTo(Ctxt, N->getValueType(0));
5665 ElementCount WidenResEC = WidenResVT.getVectorElementCount();
5666 if (WidenResEC == OpVT.getVectorElementCount()) {
5667 return DAG.getNode(N->getOpcode(), dl, WidenResVT, LHS, RHS);
5668 }
5669
5670 return DAG.UnrollVectorOp(N, WidenResVT.getVectorNumElements());
5671}
5672
5673SDValue DAGTypeLegalizer::WidenVecRes_BinaryWithExtraScalarOp(SDNode *N) {
5674 // Binary op widening, but with an extra operand that shouldn't be widened.
5675 SDLoc dl(N);
5676 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5677 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5678 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5679 SDValue InOp3 = N->getOperand(2);
5680 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3,
5681 N->getFlags());
5682}
5683
5684// Given a vector of operations that have been broken up to widen, see
5685// if we can collect them together into the next widest legal VT. This
5686// implementation is trap-safe.
5688 SmallVectorImpl<SDValue> &ConcatOps,
5689 unsigned ConcatEnd, EVT VT, EVT MaxVT,
5690 EVT WidenVT) {
5691 // Check to see if we have a single operation with the widen type.
5692 if (ConcatEnd == 1) {
5693 VT = ConcatOps[0].getValueType();
5694 if (VT == WidenVT)
5695 return ConcatOps[0];
5696 }
5697
5698 SDLoc dl(ConcatOps[0]);
5699 EVT WidenEltVT = WidenVT.getVectorElementType();
5700
5701 // while (Some element of ConcatOps is not of type MaxVT) {
5702 // From the end of ConcatOps, collect elements of the same type and put
5703 // them into an op of the next larger supported type
5704 // }
5705 while (ConcatOps[ConcatEnd-1].getValueType() != MaxVT) {
5706 int Idx = ConcatEnd - 1;
5707 VT = ConcatOps[Idx--].getValueType();
5708 while (Idx >= 0 && ConcatOps[Idx].getValueType() == VT)
5709 Idx--;
5710
5711 int NextSize = VT.isVector() ? VT.getVectorNumElements() : 1;
5712 EVT NextVT;
5713 do {
5714 NextSize *= 2;
5715 NextVT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NextSize);
5716 } while (!TLI.isTypeLegal(NextVT));
5717
5718 if (!VT.isVector()) {
5719 // Scalar type, create an INSERT_VECTOR_ELEMENT of type NextVT
5720 SDValue VecOp = DAG.getPOISON(NextVT);
5721 unsigned NumToInsert = ConcatEnd - Idx - 1;
5722 for (unsigned i = 0, OpIdx = Idx + 1; i < NumToInsert; i++, OpIdx++)
5723 VecOp = DAG.getInsertVectorElt(dl, VecOp, ConcatOps[OpIdx], i);
5724 ConcatOps[Idx+1] = VecOp;
5725 ConcatEnd = Idx + 2;
5726 } else {
5727 // Vector type, create a CONCAT_VECTORS of type NextVT
5728 SDValue undefVec = DAG.getPOISON(VT);
5729 unsigned OpsToConcat = NextSize/VT.getVectorNumElements();
5730 SmallVector<SDValue, 16> SubConcatOps(OpsToConcat);
5731 unsigned RealVals = ConcatEnd - Idx - 1;
5732 unsigned SubConcatEnd = 0;
5733 unsigned SubConcatIdx = Idx + 1;
5734 while (SubConcatEnd < RealVals)
5735 SubConcatOps[SubConcatEnd++] = ConcatOps[++Idx];
5736 while (SubConcatEnd < OpsToConcat)
5737 SubConcatOps[SubConcatEnd++] = undefVec;
5738 ConcatOps[SubConcatIdx] = DAG.getNode(ISD::CONCAT_VECTORS, dl,
5739 NextVT, SubConcatOps);
5740 ConcatEnd = SubConcatIdx + 1;
5741 }
5742 }
5743
5744 // Check to see if we have a single operation with the widen type.
5745 if (ConcatEnd == 1) {
5746 VT = ConcatOps[0].getValueType();
5747 if (VT == WidenVT)
5748 return ConcatOps[0];
5749 }
5750
5751 // add undefs of size MaxVT until ConcatOps grows to length of WidenVT
5752 unsigned NumOps = WidenVT.getVectorNumElements()/MaxVT.getVectorNumElements();
5753 if (NumOps != ConcatEnd ) {
5754 SDValue UndefVal = DAG.getPOISON(MaxVT);
5755 for (unsigned j = ConcatEnd; j < NumOps; ++j)
5756 ConcatOps[j] = UndefVal;
5757 }
5758 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
5759 ArrayRef(ConcatOps.data(), NumOps));
5760}
5761
5762SDValue DAGTypeLegalizer::WidenVecRes_BinaryCanTrap(SDNode *N) {
5763 // Binary op widening for operations that can trap.
5764 unsigned Opcode = N->getOpcode();
5765 SDLoc dl(N);
5766 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5767 EVT WidenEltVT = WidenVT.getVectorElementType();
5768 EVT VT = WidenVT;
5769 unsigned NumElts = VT.getVectorMinNumElements();
5770 const SDNodeFlags Flags = N->getFlags();
5771 while (!TLI.isTypeLegal(VT) && NumElts != 1) {
5772 NumElts = NumElts / 2;
5773 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5774 }
5775
5776 if (NumElts != 1 && !TLI.canOpTrap(N->getOpcode(), VT)) {
5777 // Operation doesn't trap so just widen as normal.
5778 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5779 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5780 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, Flags);
5781 }
5782
5783 // Generate a vp.op if it is custom/legal for the target. This avoids need
5784 // to split and tile the subvectors (below), because the inactive lanes can
5785 // simply be disabled. To avoid possible recursion, only do this if the
5786 // widened mask type is legal.
5787 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opcode);
5788 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WidenVT)) {
5789 if (EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
5790 WidenVT.getVectorElementCount());
5791 TLI.isTypeLegal(WideMaskVT)) {
5792 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5793 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5794 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
5795 SDValue EVL =
5796 DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
5797 N->getValueType(0).getVectorElementCount());
5798 return DAG.getNode(*VPOpcode, dl, WidenVT, InOp1, InOp2, Mask, EVL,
5799 Flags);
5800 }
5801 }
5802
5803 // FIXME: Improve support for scalable vectors.
5804 assert(!VT.isScalableVector() && "Scalable vectors not handled yet.");
5805
5806 // No legal vector version so unroll the vector operation and then widen.
5807 if (NumElts == 1)
5808 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
5809
5810 // Since the operation can trap, apply operation on the original vector.
5811 EVT MaxVT = VT;
5812 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5813 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5814 unsigned CurNumElts = N->getValueType(0).getVectorNumElements();
5815
5816 SmallVector<SDValue, 16> ConcatOps(CurNumElts);
5817 unsigned ConcatEnd = 0; // Current ConcatOps index.
5818 int Idx = 0; // Current Idx into input vectors.
5819
5820 // NumElts := greatest legal vector size (at most WidenVT)
5821 // while (orig. vector has unhandled elements) {
5822 // take munches of size NumElts from the beginning and add to ConcatOps
5823 // NumElts := next smaller supported vector size or 1
5824 // }
5825 while (CurNumElts != 0) {
5826 while (CurNumElts >= NumElts) {
5827 SDValue EOp1 = DAG.getExtractSubvector(dl, VT, InOp1, Idx);
5828 SDValue EOp2 = DAG.getExtractSubvector(dl, VT, InOp2, Idx);
5829 ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, VT, EOp1, EOp2, Flags);
5830 Idx += NumElts;
5831 CurNumElts -= NumElts;
5832 }
5833 do {
5834 NumElts = NumElts / 2;
5835 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5836 } while (!TLI.isTypeLegal(VT) && NumElts != 1);
5837
5838 if (NumElts == 1) {
5839 for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
5840 SDValue EOp1 = DAG.getExtractVectorElt(dl, WidenEltVT, InOp1, Idx);
5841 SDValue EOp2 = DAG.getExtractVectorElt(dl, WidenEltVT, InOp2, Idx);
5842 ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, WidenEltVT,
5843 EOp1, EOp2, Flags);
5844 }
5845 CurNumElts = 0;
5846 }
5847 }
5848
5849 return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
5850}
5851
5852SDValue DAGTypeLegalizer::WidenVecRes_StrictFP(SDNode *N) {
5853 switch (N->getOpcode()) {
5854 case ISD::STRICT_FSETCC:
5856 return WidenVecRes_STRICT_FSETCC(N);
5863 return WidenVecRes_Convert_StrictFP(N);
5864 default:
5865 break;
5866 }
5867
5868 // StrictFP op widening for operations that can trap.
5869 unsigned NumOpers = N->getNumOperands();
5870 unsigned Opcode = N->getOpcode();
5871 SDLoc dl(N);
5872 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5873 EVT WidenEltVT = WidenVT.getVectorElementType();
5874 EVT VT = WidenVT;
5875 unsigned NumElts = VT.getVectorNumElements();
5876 while (!TLI.isTypeLegal(VT) && NumElts != 1) {
5877 NumElts = NumElts / 2;
5878 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5879 }
5880
5881 // No legal vector version so unroll the vector operation and then widen.
5882 if (NumElts == 1)
5883 return UnrollVectorOp_StrictFP(N, WidenVT.getVectorNumElements());
5884
5885 // Since the operation can trap, apply operation on the original vector.
5886 EVT MaxVT = VT;
5888 unsigned CurNumElts = N->getValueType(0).getVectorNumElements();
5889
5890 SmallVector<SDValue, 16> ConcatOps(CurNumElts);
5892 unsigned ConcatEnd = 0; // Current ConcatOps index.
5893 int Idx = 0; // Current Idx into input vectors.
5894
5895 // The Chain is the first operand.
5896 InOps.push_back(N->getOperand(0));
5897
5898 // Now process the remaining operands.
5899 for (unsigned i = 1; i < NumOpers; ++i) {
5900 SDValue Oper = N->getOperand(i);
5901
5902 EVT OpVT = Oper.getValueType();
5903 if (OpVT.isVector()) {
5904 if (getTypeAction(OpVT) == TargetLowering::TypeWidenVector)
5905 Oper = GetWidenedVector(Oper);
5906 else {
5907 EVT WideOpVT =
5908 EVT::getVectorVT(*DAG.getContext(), OpVT.getVectorElementType(),
5909 WidenVT.getVectorElementCount());
5910 Oper = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WideOpVT,
5911 DAG.getPOISON(WideOpVT), Oper,
5912 DAG.getVectorIdxConstant(0, dl));
5913 }
5914 }
5915
5916 InOps.push_back(Oper);
5917 }
5918
5919 // NumElts := greatest legal vector size (at most WidenVT)
5920 // while (orig. vector has unhandled elements) {
5921 // take munches of size NumElts from the beginning and add to ConcatOps
5922 // NumElts := next smaller supported vector size or 1
5923 // }
5924 while (CurNumElts != 0) {
5925 while (CurNumElts >= NumElts) {
5927
5928 for (unsigned i = 0; i < NumOpers; ++i) {
5929 SDValue Op = InOps[i];
5930
5931 EVT OpVT = Op.getValueType();
5932 if (OpVT.isVector()) {
5933 EVT OpExtractVT =
5934 EVT::getVectorVT(*DAG.getContext(), OpVT.getVectorElementType(),
5936 Op = DAG.getExtractSubvector(dl, OpExtractVT, Op, Idx);
5937 }
5938
5939 EOps.push_back(Op);
5940 }
5941
5942 EVT OperVT[] = {VT, MVT::Other};
5943 SDValue Oper = DAG.getNode(Opcode, dl, OperVT, EOps);
5944 ConcatOps[ConcatEnd++] = Oper;
5945 Chains.push_back(Oper.getValue(1));
5946 Idx += NumElts;
5947 CurNumElts -= NumElts;
5948 }
5949 do {
5950 NumElts = NumElts / 2;
5951 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5952 } while (!TLI.isTypeLegal(VT) && NumElts != 1);
5953
5954 if (NumElts == 1) {
5955 for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
5957
5958 for (unsigned i = 0; i < NumOpers; ++i) {
5959 SDValue Op = InOps[i];
5960
5961 EVT OpVT = Op.getValueType();
5962 if (OpVT.isVector())
5963 Op = DAG.getExtractVectorElt(dl, OpVT.getVectorElementType(), Op,
5964 Idx);
5965
5966 EOps.push_back(Op);
5967 }
5968
5969 EVT WidenVT[] = {WidenEltVT, MVT::Other};
5970 SDValue Oper = DAG.getNode(Opcode, dl, WidenVT, EOps);
5971 ConcatOps[ConcatEnd++] = Oper;
5972 Chains.push_back(Oper.getValue(1));
5973 }
5974 CurNumElts = 0;
5975 }
5976 }
5977
5978 // Build a factor node to remember all the Ops that have been created.
5979 SDValue NewChain;
5980 if (Chains.size() == 1)
5981 NewChain = Chains[0];
5982 else
5983 NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
5984 ReplaceValueWith(SDValue(N, 1), NewChain);
5985
5986 return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
5987}
5988
5989SDValue DAGTypeLegalizer::WidenVecRes_OverflowOp(SDNode *N, unsigned ResNo) {
5990 SDLoc DL(N);
5991 EVT ResVT = N->getValueType(0);
5992 EVT OvVT = N->getValueType(1);
5993 EVT WideResVT, WideOvVT;
5994 SDValue WideLHS, WideRHS;
5995
5996 // TODO: This might result in a widen/split loop.
5997 if (ResNo == 0) {
5998 WideResVT = TLI.getTypeToTransformTo(*DAG.getContext(), ResVT);
5999 WideOvVT = EVT::getVectorVT(
6000 *DAG.getContext(), OvVT.getVectorElementType(),
6001 WideResVT.getVectorNumElements());
6002
6003 WideLHS = GetWidenedVector(N->getOperand(0));
6004 WideRHS = GetWidenedVector(N->getOperand(1));
6005 } else {
6006 WideOvVT = TLI.getTypeToTransformTo(*DAG.getContext(), OvVT);
6007 WideResVT = EVT::getVectorVT(
6008 *DAG.getContext(), ResVT.getVectorElementType(),
6009 WideOvVT.getVectorNumElements());
6010
6011 SDValue Zero = DAG.getVectorIdxConstant(0, DL);
6012 SDValue Poison = DAG.getPOISON(WideResVT);
6013
6014 WideLHS = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideResVT, Poison,
6015 N->getOperand(0), Zero);
6016 WideRHS = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideResVT, Poison,
6017 N->getOperand(1), Zero);
6018 }
6019
6020 SDVTList WideVTs = DAG.getVTList(WideResVT, WideOvVT);
6021 SDNode *WideNode = DAG.getNode(
6022 N->getOpcode(), DL, WideVTs, WideLHS, WideRHS).getNode();
6023
6024 // Replace the other vector result not being explicitly widened here.
6025 unsigned OtherNo = 1 - ResNo;
6026 EVT OtherVT = N->getValueType(OtherNo);
6027 if (getTypeAction(OtherVT) == TargetLowering::TypeWidenVector) {
6028 SetWidenedVector(SDValue(N, OtherNo), SDValue(WideNode, OtherNo));
6029 } else {
6030 SDValue Zero = DAG.getVectorIdxConstant(0, DL);
6031 SDValue OtherVal = DAG.getNode(
6032 ISD::EXTRACT_SUBVECTOR, DL, OtherVT, SDValue(WideNode, OtherNo), Zero);
6033 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
6034 }
6035
6036 return SDValue(WideNode, ResNo);
6037}
6038
6039SDValue DAGTypeLegalizer::WidenVecRes_Convert(SDNode *N) {
6040 LLVMContext &Ctx = *DAG.getContext();
6041 SDValue InOp = N->getOperand(0);
6042 SDLoc DL(N);
6043
6044 EVT WidenVT = TLI.getTypeToTransformTo(Ctx, N->getValueType(0));
6045 ElementCount WidenEC = WidenVT.getVectorElementCount();
6046
6047 EVT InVT = InOp.getValueType();
6048
6049 unsigned Opcode = N->getOpcode();
6050 const SDNodeFlags Flags = N->getFlags();
6051
6052 // Handle the case of ZERO_EXTEND where the promoted InVT element size does
6053 // not equal that of WidenVT.
6054 if (N->getOpcode() == ISD::ZERO_EXTEND &&
6055 getTypeAction(InVT) == TargetLowering::TypePromoteInteger &&
6056 TLI.getTypeToTransformTo(Ctx, InVT).getScalarSizeInBits() !=
6057 WidenVT.getScalarSizeInBits()) {
6058 InOp = ZExtPromotedInteger(InOp);
6059 InVT = InOp.getValueType();
6060 if (WidenVT.getScalarSizeInBits() < InVT.getScalarSizeInBits())
6061 Opcode = ISD::TRUNCATE;
6062 }
6063
6064 EVT InEltVT = InVT.getVectorElementType();
6065 EVT InWidenVT = EVT::getVectorVT(Ctx, InEltVT, WidenEC);
6066 ElementCount InVTEC = InVT.getVectorElementCount();
6067
6068 // Helper to build node with all scalar trailing operands.
6069 auto MakeConvertNode = [&](EVT VT, SDValue Op) -> SDValue {
6070 if (N->getNumOperands() == 1)
6071 return DAG.getNode(Opcode, DL, VT, Op, Flags);
6072 if (Opcode == ISD::CONVERT_TO_ARBITRARY_FP)
6073 return DAG.getNode(Opcode, DL, VT, Op, N->getOperand(1), N->getOperand(2),
6074 N->getOperand(3), Flags);
6075 return DAG.getNode(Opcode, DL, VT, Op, N->getOperand(1), Flags);
6076 };
6077
6078 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
6079 InOp = GetWidenedVector(N->getOperand(0));
6080 InVT = InOp.getValueType();
6081 InVTEC = InVT.getVectorElementCount();
6082 if (InVTEC == WidenEC) {
6083 if (N->getNumOperands() == 3 && N->isVPOpcode()) {
6084 SDValue Mask =
6085 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
6086 return DAG.getNode(Opcode, DL, WidenVT, InOp, Mask, N->getOperand(2));
6087 }
6088 return MakeConvertNode(WidenVT, InOp);
6089 }
6090 if (WidenVT.getSizeInBits() == InVT.getSizeInBits()) {
6091 // If both input and result vector types are of same width, extend
6092 // operations should be done with SIGN/ZERO_EXTEND_VECTOR_INREG, which
6093 // accepts fewer elements in the result than in the input.
6094 if (Opcode == ISD::ANY_EXTEND)
6095 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
6096 if (Opcode == ISD::SIGN_EXTEND)
6097 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
6098 if (Opcode == ISD::ZERO_EXTEND)
6099 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
6100 }
6101
6102 // For TRUNCATE, try to widen using the legal EC of the input type instead
6103 // if the legalisation action for that intermediate type is not widening.
6104 // E.g. for trunc nxv1i64 -> nxv1i8 where
6105 // - nxv1i64 input gets widened to nxv2i64
6106 // - nxv1i8 output gets widened to nxv16i8
6107 // Then one can try widening the result to nxv2i8 (instead of going all the
6108 // way to nxv16i8) if this later allows type promotion.
6109 EVT MidResVT =
6110 EVT::getVectorVT(Ctx, WidenVT.getVectorElementType(), InVTEC);
6111 if (N->getOpcode() == ISD::TRUNCATE &&
6112 getTypeAction(MidResVT) == TargetLowering::TypePromoteInteger) {
6113 SDValue MidRes = DAG.getNode(ISD::TRUNCATE, DL, MidResVT, InOp, Flags);
6114 return DAG.getInsertSubvector(DL, DAG.getPOISON(WidenVT), MidRes, 0);
6115 }
6116 }
6117
6118 if (TLI.isTypeLegal(InWidenVT)) {
6119 // Because the result and the input are different vector types, widening
6120 // the result could create a legal type but widening the input might make
6121 // it an illegal type that might lead to repeatedly splitting the input
6122 // and then widening it. To avoid this, we widen the input only if
6123 // it results in a legal type.
6124 if (WidenEC.isKnownMultipleOf(InVTEC.getKnownMinValue())) {
6125 // Widen the input and call convert on the widened input vector.
6126 unsigned NumConcat =
6127 WidenEC.getKnownMinValue() / InVTEC.getKnownMinValue();
6128 SmallVector<SDValue, 16> Ops(NumConcat, DAG.getPOISON(InVT));
6129 Ops[0] = InOp;
6130 SDValue InVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InWidenVT, Ops);
6131 return MakeConvertNode(WidenVT, InVec);
6132 }
6133
6134 if (InVTEC.isKnownMultipleOf(WidenEC.getKnownMinValue())) {
6135 SDValue InVal = DAG.getExtractSubvector(DL, InWidenVT, InOp, 0);
6136 // Extract the input and convert the shorten input vector.
6137 return MakeConvertNode(WidenVT, InVal);
6138 }
6139 }
6140
6141 // Otherwise unroll into some nasty scalar code and rebuild the vector.
6142 EVT EltVT = WidenVT.getVectorElementType();
6143 SmallVector<SDValue, 16> Ops(WidenEC.getFixedValue(), DAG.getPOISON(EltVT));
6144 // Use the original element count so we don't do more scalar opts than
6145 // necessary.
6146 unsigned MinElts = N->getValueType(0).getVectorNumElements();
6147 for (unsigned i=0; i < MinElts; ++i) {
6148 SDValue Val = DAG.getExtractVectorElt(DL, InEltVT, InOp, i);
6149 Ops[i] = MakeConvertNode(EltVT, Val);
6150 }
6151
6152 return DAG.getBuildVector(WidenVT, DL, Ops);
6153}
6154
6155SDValue DAGTypeLegalizer::WidenVecRes_FP_TO_XINT_SAT(SDNode *N) {
6156 SDLoc dl(N);
6157 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6158 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
6159
6160 SDValue Src = N->getOperand(0);
6161 EVT SrcVT = Src.getValueType();
6162
6163 // Also widen the input.
6164 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
6165 Src = GetWidenedVector(Src);
6166 SrcVT = Src.getValueType();
6167 }
6168
6169 // Input and output not widened to the same size, give up.
6170 if (WidenNumElts != SrcVT.getVectorElementCount())
6171 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
6172
6173 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src, N->getOperand(1));
6174}
6175
6176SDValue DAGTypeLegalizer::WidenVecRes_XROUND(SDNode *N) {
6177 SDLoc dl(N);
6178 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6179 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
6180
6181 SDValue Src = N->getOperand(0);
6182 EVT SrcVT = Src.getValueType();
6183
6184 // Also widen the input.
6185 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
6186 Src = GetWidenedVector(Src);
6187 SrcVT = Src.getValueType();
6188 }
6189
6190 // Input and output not widened to the same size, give up.
6191 if (WidenNumElts != SrcVT.getVectorElementCount())
6192 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
6193
6194 if (N->getNumOperands() == 1)
6195 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src);
6196
6197 assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
6198 assert(N->isVPOpcode() && "Expected VP opcode");
6199
6200 SDValue Mask =
6201 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
6202 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src, Mask, N->getOperand(2));
6203}
6204
6205SDValue DAGTypeLegalizer::WidenVecRes_Convert_StrictFP(SDNode *N) {
6206 SDValue InOp = N->getOperand(1);
6207 SDLoc DL(N);
6208 SmallVector<SDValue, 4> NewOps(N->ops());
6209
6210 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6211 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6212
6213 EVT InVT = InOp.getValueType();
6214 EVT InEltVT = InVT.getVectorElementType();
6215
6216 unsigned Opcode = N->getOpcode();
6217
6218 // FIXME: Optimizations need to be implemented here.
6219
6220 // Otherwise unroll into some nasty scalar code and rebuild the vector.
6221 EVT EltVT = WidenVT.getVectorElementType();
6222 std::array<EVT, 2> EltVTs = {{EltVT, MVT::Other}};
6223 SmallVector<SDValue, 16> Ops(WidenNumElts, DAG.getPOISON(EltVT));
6224 SmallVector<SDValue, 32> OpChains;
6225 // Use the original element count so we don't do more scalar opts than
6226 // necessary.
6227 unsigned MinElts = N->getValueType(0).getVectorNumElements();
6228 for (unsigned i=0; i < MinElts; ++i) {
6229 NewOps[1] = DAG.getExtractVectorElt(DL, InEltVT, InOp, i);
6230 Ops[i] = DAG.getNode(Opcode, DL, EltVTs, NewOps);
6231 OpChains.push_back(Ops[i].getValue(1));
6232 }
6233 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OpChains);
6234 ReplaceValueWith(SDValue(N, 1), NewChain);
6235
6236 return DAG.getBuildVector(WidenVT, DL, Ops);
6237}
6238
6239SDValue DAGTypeLegalizer::WidenVecRes_EXTEND_VECTOR_INREG(SDNode *N) {
6240 unsigned Opcode = N->getOpcode();
6241 SDValue InOp = N->getOperand(0);
6242 SDLoc DL(N);
6243
6244 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6245 EVT WidenSVT = WidenVT.getVectorElementType();
6246 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6247
6248 EVT InVT = InOp.getValueType();
6249 EVT InSVT = InVT.getVectorElementType();
6250 unsigned InVTNumElts = InVT.getVectorNumElements();
6251
6252 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
6253 InOp = GetWidenedVector(InOp);
6254 InVT = InOp.getValueType();
6255 if (InVT.getSizeInBits() == WidenVT.getSizeInBits()) {
6256 switch (Opcode) {
6260 return DAG.getNode(Opcode, DL, WidenVT, InOp);
6261 }
6262 }
6263 }
6264
6265 // Unroll, extend the scalars and rebuild the vector.
6267 for (unsigned i = 0, e = std::min(InVTNumElts, WidenNumElts); i != e; ++i) {
6268 SDValue Val = DAG.getExtractVectorElt(DL, InSVT, InOp, i);
6269 switch (Opcode) {
6271 Val = DAG.getNode(ISD::ANY_EXTEND, DL, WidenSVT, Val);
6272 break;
6274 Val = DAG.getNode(ISD::SIGN_EXTEND, DL, WidenSVT, Val);
6275 break;
6277 Val = DAG.getNode(ISD::ZERO_EXTEND, DL, WidenSVT, Val);
6278 break;
6279 default:
6280 llvm_unreachable("A *_EXTEND_VECTOR_INREG node was expected");
6281 }
6282 Ops.push_back(Val);
6283 }
6284
6285 while (Ops.size() != WidenNumElts)
6286 Ops.push_back(DAG.getPOISON(WidenSVT));
6287
6288 return DAG.getBuildVector(WidenVT, DL, Ops);
6289}
6290
6291SDValue DAGTypeLegalizer::WidenVecRes_FCOPYSIGN(SDNode *N) {
6292 // If this is an FCOPYSIGN with same input types, we can treat it as a
6293 // normal (can trap) binary op.
6294 if (N->getOperand(0).getValueType() == N->getOperand(1).getValueType())
6295 return WidenVecRes_BinaryCanTrap(N);
6296
6297 // If the types are different, fall back to unrolling.
6298 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6299 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
6300}
6301
6302/// Result and first source operand are different scalar types, but must have
6303/// the same number of elements. There is an additional control argument which
6304/// should be passed through unchanged.
6305SDValue DAGTypeLegalizer::WidenVecRes_UnarySameEltsWithScalarArg(SDNode *N) {
6306 SDValue FpValue = N->getOperand(0);
6307 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6308 if (getTypeAction(FpValue.getValueType()) != TargetLowering::TypeWidenVector)
6309 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
6310 SDValue Arg = GetWidenedVector(FpValue);
6311 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, {Arg, N->getOperand(1)},
6312 N->getFlags());
6313}
6314
6315SDValue DAGTypeLegalizer::WidenVecRes_ExpOp(SDNode *N) {
6316 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6317 SDValue InOp = GetWidenedVector(N->getOperand(0));
6318 SDValue RHS = N->getOperand(1);
6319 EVT ExpVT = RHS.getValueType();
6320 SDValue ExpOp = RHS;
6321 if (ExpVT.isVector()) {
6322 EVT WideExpVT = WidenVT.changeVectorElementType(
6323 *DAG.getContext(), ExpVT.getVectorElementType());
6324 ExpOp = ModifyToType(RHS, WideExpVT);
6325 }
6326
6327 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, ExpOp);
6328}
6329
6330SDValue DAGTypeLegalizer::WidenVecRes_Unary(SDNode *N) {
6331 // Unary op widening.
6332 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6333 SDValue InOp = GetWidenedVector(N->getOperand(0));
6334 if (N->getNumOperands() == 1)
6335 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, N->getFlags());
6336 if (N->getOpcode() == ISD::AssertNoFPClass)
6337 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp,
6338 N->getOperand(1), N->getFlags());
6339
6340 assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
6341 assert(N->isVPOpcode() && "Expected VP opcode");
6342
6343 SDValue Mask =
6344 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
6345 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT,
6346 {InOp, Mask, N->getOperand(2)});
6347}
6348
6349SDValue DAGTypeLegalizer::WidenVecRes_InregOp(SDNode *N) {
6350 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6351 EVT ExtVT = EVT::getVectorVT(
6352 *DAG.getContext(),
6353 cast<VTSDNode>(N->getOperand(1))->getVT().getVectorElementType(),
6354 WidenVT.getVectorElementCount());
6355 SDValue WidenLHS = GetWidenedVector(N->getOperand(0));
6356 return DAG.getNode(N->getOpcode(), SDLoc(N),
6357 WidenVT, WidenLHS, DAG.getValueType(ExtVT));
6358}
6359
6360SDValue DAGTypeLegalizer::WidenVecRes_UnaryOpWithTwoResults(SDNode *N,
6361 unsigned ResNo) {
6362 EVT VT0 = N->getValueType(0);
6363 EVT VT1 = N->getValueType(1);
6364
6365 assert(VT0.isVector() && VT1.isVector() &&
6367 "expected both results to be vectors of matching element count");
6368
6369 LLVMContext &Ctx = *DAG.getContext();
6370 SDValue InOp = GetWidenedVector(N->getOperand(0));
6371
6372 EVT WidenVT = TLI.getTypeToTransformTo(Ctx, N->getValueType(ResNo));
6373 ElementCount WidenEC = WidenVT.getVectorElementCount();
6374
6375 EVT WidenVT0 = EVT::getVectorVT(Ctx, VT0.getVectorElementType(), WidenEC);
6376 EVT WidenVT1 = EVT::getVectorVT(Ctx, VT1.getVectorElementType(), WidenEC);
6377
6378 SDNode *WidenNode =
6379 DAG.getNode(N->getOpcode(), SDLoc(N), {WidenVT0, WidenVT1}, InOp)
6380 .getNode();
6381
6382 ReplaceOtherWidenResults(N, WidenNode, ResNo);
6383 return SDValue(WidenNode, ResNo);
6384}
6385
6386SDValue DAGTypeLegalizer::WidenVecRes_MERGE_VALUES(SDNode *N, unsigned ResNo) {
6387 SDValue WidenVec = DisintegrateMERGE_VALUES(N, ResNo);
6388 return GetWidenedVector(WidenVec);
6389}
6390
6391SDValue DAGTypeLegalizer::WidenVecRes_ADDRSPACECAST(SDNode *N) {
6392 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6393 SDValue InOp = GetWidenedVector(N->getOperand(0));
6394 auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
6395
6396 return DAG.getAddrSpaceCast(SDLoc(N), WidenVT, InOp,
6397 AddrSpaceCastN->getSrcAddressSpace(),
6398 AddrSpaceCastN->getDestAddressSpace());
6399}
6400
6401SDValue DAGTypeLegalizer::WidenVecRes_BITCAST(SDNode *N) {
6402 SDValue InOp = N->getOperand(0);
6403 EVT InVT = InOp.getValueType();
6404 EVT VT = N->getValueType(0);
6405 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6406 SDLoc dl(N);
6407
6408 switch (getTypeAction(InVT)) {
6410 break;
6412 report_fatal_error("Scalarization of scalable vectors is not supported.");
6414 // If the incoming type is a vector that is being promoted, then
6415 // we know that the elements are arranged differently and that we
6416 // must perform the conversion using a stack slot.
6417 if (InVT.isVector())
6418 break;
6419
6420 // If the InOp is promoted to the same size, convert it. Otherwise,
6421 // fall out of the switch and widen the promoted input.
6422 SDValue NInOp = GetPromotedInteger(InOp);
6423 EVT NInVT = NInOp.getValueType();
6424 if (WidenVT.bitsEq(NInVT)) {
6425 // For big endian targets we need to shift the input integer or the
6426 // interesting bits will end up at the wrong place.
6427 if (DAG.getDataLayout().isBigEndian()) {
6428 unsigned ShiftAmt = NInVT.getSizeInBits() - InVT.getSizeInBits();
6429 NInOp = DAG.getNode(ISD::SHL, dl, NInVT, NInOp,
6430 DAG.getShiftAmountConstant(ShiftAmt, NInVT, dl));
6431 }
6432 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NInOp);
6433 }
6434 InOp = NInOp;
6435 InVT = NInVT;
6436 break;
6437 }
6444 break;
6446 // If the InOp is widened to the same size, convert it. Otherwise, fall
6447 // out of the switch and widen the widened input.
6448 InOp = GetWidenedVector(InOp);
6449 InVT = InOp.getValueType();
6450 if (WidenVT.bitsEq(InVT))
6451 // The input widens to the same size. Convert to the widen value.
6452 return DAG.getNode(ISD::BITCAST, dl, WidenVT, InOp);
6453 break;
6454 }
6455
6456 unsigned WidenSize = WidenVT.getSizeInBits();
6457 unsigned InSize = InVT.getSizeInBits();
6458 unsigned InScalarSize = InVT.getScalarSizeInBits();
6459 // x86mmx is not an acceptable vector element type, so don't try.
6460 if (WidenSize % InScalarSize == 0 && InVT != MVT::x86mmx) {
6461 // Determine new input vector type. The new input vector type will use
6462 // the same element type (if its a vector) or use the input type as a
6463 // vector. It is the same size as the type to widen to.
6464 EVT NewInVT;
6465 unsigned NewNumParts = WidenSize / InSize;
6466 if (InVT.isVector()) {
6467 EVT InEltVT = InVT.getVectorElementType();
6468 NewInVT = EVT::getVectorVT(*DAG.getContext(), InEltVT,
6469 WidenSize / InEltVT.getSizeInBits());
6470 } else {
6471 // For big endian systems, using the promoted input scalar type
6472 // to produce the scalar_to_vector would put the desired bits into
6473 // the least significant byte(s) of the wider element zero. This
6474 // will mean that the users of the result vector are using incorrect
6475 // bits. Use the original input type instead. Although either input
6476 // type can be used on little endian systems, for consistency we
6477 // use the original type there as well.
6478 EVT OrigInVT = N->getOperand(0).getValueType();
6479 NewNumParts = WidenSize / OrigInVT.getSizeInBits();
6480 NewInVT = EVT::getVectorVT(*DAG.getContext(), OrigInVT, NewNumParts);
6481 }
6482
6483 if (TLI.isTypeLegal(NewInVT)) {
6484 SDValue NewVec;
6485 if (InVT.isVector()) {
6486 // Because the result and the input are different vector types, widening
6487 // the result could create a legal type but widening the input might
6488 // make it an illegal type that might lead to repeatedly splitting the
6489 // input and then widening it. To avoid this, we widen the input only if
6490 // it results in a legal type.
6491 if (WidenSize % InSize == 0) {
6492 SmallVector<SDValue, 16> Ops(NewNumParts, DAG.getPOISON(InVT));
6493 Ops[0] = InOp;
6494
6495 NewVec = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewInVT, Ops);
6496 } else {
6498 DAG.ExtractVectorElements(InOp, Ops);
6499 Ops.append(WidenSize / InScalarSize - Ops.size(),
6500 DAG.getPOISON(InVT.getVectorElementType()));
6501
6502 NewVec = DAG.getNode(ISD::BUILD_VECTOR, dl, NewInVT, Ops);
6503 }
6504 } else {
6505 NewVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewInVT, InOp);
6506 }
6507 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NewVec);
6508 }
6509 }
6510
6511 return CreateStackStoreLoad(InOp, WidenVT);
6512}
6513
6514SDValue DAGTypeLegalizer::WidenVecRes_LOOP_DEPENDENCE_MASK(SDNode *N) {
6515 return DAG.getNode(
6516 N->getOpcode(), SDLoc(N),
6517 TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)),
6518 N->getOperand(0), N->getOperand(1), N->getOperand(2), N->getOperand(3));
6519}
6520
6521SDValue DAGTypeLegalizer::WidenVecRes_BUILD_VECTOR(SDNode *N) {
6522 SDLoc dl(N);
6523 // Build a vector with poison for the new nodes.
6524 EVT VT = N->getValueType(0);
6525
6526 // Integer BUILD_VECTOR operands may be larger than the node's vector element
6527 // type. The POISONs need to have the same type as the existing operands.
6528 EVT EltVT = N->getOperand(0).getValueType();
6529 unsigned NumElts = VT.getVectorNumElements();
6530
6531 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6532 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6533
6534 SmallVector<SDValue, 16> NewOps(N->ops());
6535 assert(WidenNumElts >= NumElts && "Shrinking vector instead of widening!");
6536 NewOps.append(WidenNumElts - NumElts, DAG.getPOISON(EltVT));
6537
6538 return DAG.getBuildVector(WidenVT, dl, NewOps);
6539}
6540
6541SDValue DAGTypeLegalizer::WidenVecRes_CONCAT_VECTORS(SDNode *N) {
6542 EVT InVT = N->getOperand(0).getValueType();
6543 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6544 SDLoc dl(N);
6545 unsigned NumOperands = N->getNumOperands();
6546
6547 bool InputWidened = false; // Indicates we need to widen the input.
6548 if (getTypeAction(InVT) != TargetLowering::TypeWidenVector) {
6549 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6550 unsigned NumInElts = InVT.getVectorMinNumElements();
6551 if (WidenNumElts % NumInElts == 0) {
6552 // Add undef vectors to widen to correct length.
6553 unsigned NumConcat = WidenNumElts / NumInElts;
6554 SDValue UndefVal = DAG.getPOISON(InVT);
6555 SmallVector<SDValue, 16> Ops(NumConcat);
6556 for (unsigned i=0; i < NumOperands; ++i)
6557 Ops[i] = N->getOperand(i);
6558 for (unsigned i = NumOperands; i != NumConcat; ++i)
6559 Ops[i] = UndefVal;
6560 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Ops);
6561 }
6562 } else {
6563 InputWidened = true;
6564 if (WidenVT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
6565 // The inputs and the result are widen to the same value.
6566 unsigned i;
6567 for (i=1; i < NumOperands; ++i)
6568 if (!N->getOperand(i).isUndef())
6569 break;
6570
6571 if (i == NumOperands)
6572 // Everything but the first operand is an UNDEF so just return the
6573 // widened first operand.
6574 return GetWidenedVector(N->getOperand(0));
6575
6576 if (NumOperands == 2) {
6577 assert(!WidenVT.isScalableVector() &&
6578 "Cannot use vector shuffles to widen CONCAT_VECTOR result");
6579 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6580 unsigned NumInElts = InVT.getVectorNumElements();
6581
6582 // Replace concat of two operands with a shuffle.
6583 SmallVector<int, 16> MaskOps(WidenNumElts, -1);
6584 for (unsigned i = 0; i < NumInElts; ++i) {
6585 MaskOps[i] = i;
6586 MaskOps[i + NumInElts] = i + WidenNumElts;
6587 }
6588 return DAG.getVectorShuffle(WidenVT, dl,
6589 GetWidenedVector(N->getOperand(0)),
6590 GetWidenedVector(N->getOperand(1)),
6591 MaskOps);
6592 }
6593 }
6594 }
6595
6596 assert(!WidenVT.isScalableVector() &&
6597 "Cannot use build vectors to widen CONCAT_VECTOR result");
6598 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6599 unsigned NumInElts = InVT.getVectorNumElements();
6600
6601 // Fall back to use extracts and build vector.
6602 EVT EltVT = WidenVT.getVectorElementType();
6603 SmallVector<SDValue, 16> Ops(WidenNumElts);
6604 unsigned Idx = 0;
6605 for (unsigned i=0; i < NumOperands; ++i) {
6606 SDValue InOp = N->getOperand(i);
6607 if (InputWidened)
6608 InOp = GetWidenedVector(InOp);
6609 for (unsigned j = 0; j < NumInElts; ++j)
6610 Ops[Idx++] = DAG.getExtractVectorElt(dl, EltVT, InOp, j);
6611 }
6612 SDValue UndefVal = DAG.getPOISON(EltVT);
6613 for (; Idx < WidenNumElts; ++Idx)
6614 Ops[Idx] = UndefVal;
6615 return DAG.getBuildVector(WidenVT, dl, Ops);
6616}
6617
6618SDValue DAGTypeLegalizer::WidenVecRes_INSERT_SUBVECTOR(SDNode *N) {
6619 EVT VT = N->getValueType(0);
6620 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6621 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
6622 SDValue InOp2 = N->getOperand(1);
6623 SDValue Idx = N->getOperand(2);
6624 SDLoc dl(N);
6625 return DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WidenVT, InOp1, InOp2, Idx);
6626}
6627
6628SDValue DAGTypeLegalizer::WidenVecRes_EXTRACT_SUBVECTOR(SDNode *N) {
6629 EVT VT = N->getValueType(0);
6630 EVT EltVT = VT.getVectorElementType();
6631 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6632 SDValue InOp = N->getOperand(0);
6633 SDValue Idx = N->getOperand(1);
6634 SDLoc dl(N);
6635
6636 auto InOpTypeAction = getTypeAction(InOp.getValueType());
6637 if (InOpTypeAction == TargetLowering::TypeWidenVector)
6638 InOp = GetWidenedVector(InOp);
6639
6640 EVT InVT = InOp.getValueType();
6641
6642 // Check if we can just return the input vector after widening.
6643 uint64_t IdxVal = Idx->getAsZExtVal();
6644 if (IdxVal == 0 && InVT == WidenVT)
6645 return InOp;
6646
6647 // Check if we can extract from the vector.
6648 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6649 unsigned InNumElts = InVT.getVectorMinNumElements();
6650 unsigned VTNumElts = VT.getVectorMinNumElements();
6651 assert(IdxVal % VTNumElts == 0 &&
6652 "Expected Idx to be a multiple of subvector minimum vector length");
6653 if (IdxVal % WidenNumElts == 0 && IdxVal + WidenNumElts < InNumElts)
6654 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, WidenVT, InOp, Idx);
6655
6656 if (VT.isScalableVector()) {
6657 // Try to split the operation up into smaller extracts and concat the
6658 // results together, e.g.
6659 // nxv6i64 extract_subvector(nxv12i64, 6)
6660 // <->
6661 // nxv8i64 concat(
6662 // nxv2i64 extract_subvector(nxv16i64, 6)
6663 // nxv2i64 extract_subvector(nxv16i64, 8)
6664 // nxv2i64 extract_subvector(nxv16i64, 10)
6665 // undef)
6666 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
6667 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
6668 "down type's element count");
6669 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
6671 // Avoid recursion around e.g. nxv1i8.
6672 if (getTypeAction(PartVT) != TargetLowering::TypeWidenVector) {
6674 unsigned I = 0;
6675 for (; I < VTNumElts / GCD; ++I)
6676 Parts.push_back(
6677 DAG.getExtractSubvector(dl, PartVT, InOp, IdxVal + I * GCD));
6678 for (; I < WidenNumElts / GCD; ++I)
6679 Parts.push_back(DAG.getPOISON(PartVT));
6680
6681 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
6682 }
6683
6684 // Fallback to extracting through memory.
6685
6686 Align Alignment = DAG.getReducedAlign(InVT, /*UseABI=*/false);
6687 SDValue StackPtr = DAG.CreateStackTemporary(InVT.getStoreSize(), Alignment);
6688 MachineFunction &MF = DAG.getMachineFunction();
6689 int FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
6690 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
6691
6692 MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
6695 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
6698
6699 // Write out the input vector.
6700 SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, InOp, StackPtr, StoreMMO);
6701
6702 // Build a mask to match the length of the non-widened result.
6703 SDValue Mask =
6704 DAG.getMaskFromElementCount(dl, WidenVT, VT.getVectorElementCount());
6705
6706 // Read back the sub-vector setting the remaining lanes to poison.
6707 StackPtr = TLI.getVectorSubVecPointer(DAG, StackPtr, InVT, VT, Idx);
6708 return DAG.getMaskedLoad(
6709 WidenVT, dl, Ch, StackPtr, DAG.getPOISON(StackPtr.getValueType()), Mask,
6710 DAG.getPOISON(WidenVT), VT, LoadMMO, ISD::UNINDEXED, ISD::NON_EXTLOAD);
6711 }
6712
6713 // We could try widening the input to the right length but for now, extract
6714 // the original elements, fill the rest with undefs and build a vector.
6715 SmallVector<SDValue, 16> Ops(WidenNumElts);
6716 unsigned i;
6717 for (i = 0; i < VTNumElts; ++i)
6718 Ops[i] = DAG.getExtractVectorElt(dl, EltVT, InOp, IdxVal + i);
6719
6720 SDValue UndefVal = DAG.getPOISON(EltVT);
6721 for (; i < WidenNumElts; ++i)
6722 Ops[i] = UndefVal;
6723 return DAG.getBuildVector(WidenVT, dl, Ops);
6724}
6725
6726SDValue DAGTypeLegalizer::WidenVecRes_AssertZext(SDNode *N) {
6727 SDValue InOp = ModifyToType(
6728 N->getOperand(0),
6729 TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)), true);
6730 return DAG.getNode(ISD::AssertZext, SDLoc(N), InOp.getValueType(), InOp,
6731 N->getOperand(1));
6732}
6733
6734SDValue DAGTypeLegalizer::WidenVecRes_INSERT_VECTOR_ELT(SDNode *N) {
6735 SDValue InOp = GetWidenedVector(N->getOperand(0));
6736 return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(N),
6737 InOp.getValueType(), InOp,
6738 N->getOperand(1), N->getOperand(2));
6739}
6740
6741/// Either return the same load or provide appropriate casts
6742/// from the load and return that.
6743static SDValue coerceLoadedValue(SDValue LdOp, EVT FirstVT, EVT WidenVT,
6744 TypeSize LdWidth, TypeSize FirstVTWidth,
6745 SDLoc dl, SelectionDAG &DAG) {
6746 assert(TypeSize::isKnownLE(LdWidth, FirstVTWidth) &&
6747 "Load width must be less than or equal to first value type width");
6748 TypeSize WidenWidth = WidenVT.getSizeInBits();
6749 if (!FirstVT.isVector()) {
6750 unsigned NumElts =
6751 WidenWidth.getFixedValue() / FirstVTWidth.getFixedValue();
6752 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), FirstVT, NumElts);
6753 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT, LdOp);
6754 return DAG.getNode(ISD::BITCAST, dl, WidenVT, VecOp);
6755 }
6756 assert(FirstVT == WidenVT && "First value type must equal widen value type");
6757 return LdOp;
6758}
6759
6760/// Inverse of coerceLoadedValue: pull a FirstVT-sized scalar/vector out of the
6761/// widened value so it can be issued in a single atomic store.
6762static SDValue coerceStoredValue(SDValue StVal, EVT FirstVT, EVT WidenVT,
6763 TypeSize FirstVTWidth, const SDLoc &dl,
6764 SelectionDAG &DAG) {
6765 TypeSize WidenWidth = WidenVT.getSizeInBits();
6766 if (!FirstVT.isVector()) {
6767 unsigned NumElts =
6768 WidenWidth.getFixedValue() / FirstVTWidth.getFixedValue();
6769 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), FirstVT, NumElts);
6770 SDValue VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, StVal);
6771 return DAG.getExtractVectorElt(dl, FirstVT, VecOp, 0);
6772 }
6773 assert(FirstVT == WidenVT && "First value type must equal widen value type");
6774 return StVal;
6775}
6776
6777static std::optional<EVT> findMemType(SelectionDAG &DAG,
6778 const TargetLowering &TLI, unsigned Width,
6779 EVT WidenVT, unsigned Align,
6780 unsigned WidenEx);
6781
6782SDValue DAGTypeLegalizer::WidenVecRes_ATOMIC_LOAD(AtomicSDNode *LD) {
6783 EVT WidenVT =
6784 TLI.getTypeToTransformTo(*DAG.getContext(), LD->getValueType(0));
6785 EVT LdVT = LD->getMemoryVT();
6786 SDLoc dl(LD);
6787
6788 // Load information
6789 SDValue Chain = LD->getChain();
6790 SDValue BasePtr = LD->getBasePtr();
6791
6792 TypeSize LdWidth = LdVT.getSizeInBits();
6793 TypeSize WidenWidth = WidenVT.getSizeInBits();
6794 TypeSize WidthDiff = WidenWidth - LdWidth;
6795
6796 // Find the vector type that can load from.
6797 std::optional<EVT> FirstVT =
6798 findMemType(DAG, TLI, LdWidth.getKnownMinValue(), WidenVT, /*LdAlign=*/0,
6799 WidthDiff.getKnownMinValue());
6800
6801 if (!FirstVT)
6802 return SDValue();
6803
6804 SmallVector<EVT, 8> MemVTs;
6805 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
6806
6807 SDValue LdOp = DAG.getAtomicLoad(ISD::NON_EXTLOAD, dl, *FirstVT, *FirstVT,
6808 Chain, BasePtr, LD->getMemOperand());
6809
6810 // Load the element with one instruction.
6811 SDValue Result = coerceLoadedValue(LdOp, *FirstVT, WidenVT, LdWidth,
6812 FirstVTWidth, dl, DAG);
6813
6814 // Modified the chain - switch anything that used the old chain to use
6815 // the new one.
6816 ReplaceValueWith(SDValue(LD, 1), LdOp.getValue(1));
6817 return Result;
6818}
6819
6820SDValue DAGTypeLegalizer::WidenVecRes_LOAD(SDNode *N) {
6821 LoadSDNode *LD = cast<LoadSDNode>(N);
6822 ISD::LoadExtType ExtType = LD->getExtensionType();
6823
6824 // A vector must always be stored in memory as-is, i.e. without any padding
6825 // between the elements, since various code depend on it, e.g. in the
6826 // handling of a bitcast of a vector type to int, which may be done with a
6827 // vector store followed by an integer load. A vector that does not have
6828 // elements that are byte-sized must therefore be stored as an integer
6829 // built out of the extracted vector elements.
6830 if (!LD->getMemoryVT().isByteSized()) {
6831 SDValue Value, NewChain;
6832 std::tie(Value, NewChain) = TLI.scalarizeVectorLoad(LD, DAG);
6833 ReplaceValueWith(SDValue(LD, 0), Value);
6834 ReplaceValueWith(SDValue(LD, 1), NewChain);
6835 return SDValue();
6836 }
6837
6838 // Generate a vector-predicated load if it is custom/legal on the target. To
6839 // avoid possible recursion, only do this if the widened mask type is legal.
6840 // FIXME: Not all targets may support EVL in VP_LOAD. These will have been
6841 // removed from the IR by the ExpandVectorPredication pass but we're
6842 // reintroducing them here.
6843 EVT VT = LD->getValueType(0);
6844 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6845 EVT WideMaskVT = getSetCCResultType(WideVT);
6846
6847 if (ExtType == ISD::NON_EXTLOAD &&
6848 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WideVT) &&
6849 TLI.isTypeLegal(WideMaskVT)) {
6850 SDLoc DL(N);
6851 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
6852 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
6854 SDValue NewLoad =
6855 DAG.getLoadVP(LD->getAddressingMode(), ISD::NON_EXTLOAD, WideVT, DL,
6856 LD->getChain(), LD->getBasePtr(), LD->getOffset(), Mask,
6857 EVL, LD->getMemoryVT(), LD->getMemOperand());
6858
6859 // Modified the chain - switch anything that used the old chain to use
6860 // the new one.
6861 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6862
6863 return NewLoad;
6864 }
6865
6867 SmallVector<SDValue, 16> LdChain; // Chain for the series of load
6868 if (ExtType != ISD::NON_EXTLOAD)
6869 Result = GenWidenVectorExtLoads(LdChain, LD, ExtType);
6870 else
6871 Result = GenWidenVectorLoads(LdChain, LD);
6872
6873 if (Result) {
6874 // If we generate a single load, we can use that for the chain. Otherwise,
6875 // build a factor node to remember the multiple loads are independent and
6876 // chain to that.
6877 SDValue NewChain;
6878 if (LdChain.size() == 1)
6879 NewChain = LdChain[0];
6880 else
6881 NewChain = DAG.getNode(ISD::TokenFactor, SDLoc(LD), MVT::Other, LdChain);
6882
6883 // Modified the chain - switch anything that used the old chain to use
6884 // the new one.
6885 ReplaceValueWith(SDValue(N, 1), NewChain);
6886
6887 return Result;
6888 }
6889
6890 if (VT.isVector()) {
6891 // If all else fails replace the load with a wide masked load.
6892 SDLoc DL(N);
6893 SDValue Mask =
6894 DAG.getMaskFromElementCount(DL, WideVT, VT.getVectorElementCount());
6895
6896 SDValue NewLoad = DAG.getMaskedLoad(
6897 WideVT, DL, LD->getChain(), LD->getBasePtr(), LD->getOffset(), Mask,
6898 DAG.getPOISON(WideVT), LD->getMemoryVT(), LD->getMemOperand(),
6899 LD->getAddressingMode(), LD->getExtensionType());
6900
6901 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6902 return NewLoad;
6903 }
6904
6905 report_fatal_error("Unable to widen vector load");
6906}
6907
6908SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD(VPLoadSDNode *N) {
6909 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6910 SDValue Mask = N->getMask();
6911 SDValue EVL = N->getVectorLength();
6912 ISD::LoadExtType ExtType = N->getExtensionType();
6913 SDLoc dl(N);
6914
6915 // The mask should be widened as well
6916 assert(getTypeAction(Mask.getValueType()) ==
6918 "Unable to widen binary VP op");
6919 Mask = GetWidenedVector(Mask);
6920 assert(Mask.getValueType().getVectorElementCount() ==
6921 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
6922 .getVectorElementCount() &&
6923 "Unable to widen vector load");
6924
6925 SDValue Res =
6926 DAG.getLoadVP(N->getAddressingMode(), ExtType, WidenVT, dl, N->getChain(),
6927 N->getBasePtr(), N->getOffset(), Mask, EVL,
6928 N->getMemoryVT(), N->getMemOperand(), N->isExpandingLoad());
6929 // Legalize the chain result - switch anything that used the old chain to
6930 // use the new one.
6931 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6932 return Res;
6933}
6934
6935SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD_FF(VPLoadFFSDNode *N) {
6936 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6937 SDValue Mask = N->getMask();
6938 SDValue EVL = N->getVectorLength();
6939 SDLoc dl(N);
6940
6941 // The mask should be widened as well
6942 assert(getTypeAction(Mask.getValueType()) ==
6944 "Unable to widen binary VP op");
6945 Mask = GetWidenedVector(Mask);
6946 assert(Mask.getValueType().getVectorElementCount() ==
6947 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
6948 .getVectorElementCount() &&
6949 "Unable to widen vector load");
6950
6951 SDValue Res = DAG.getLoadFFVP(WidenVT, dl, N->getChain(), N->getBasePtr(),
6952 Mask, EVL, N->getMemOperand());
6953 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6954 ReplaceValueWith(SDValue(N, 2), Res.getValue(2));
6955 return Res;
6956}
6957
6958SDValue DAGTypeLegalizer::WidenVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode *N) {
6959 SDLoc DL(N);
6960
6961 // The mask should be widened as well
6962 SDValue Mask = N->getMask();
6963 assert(getTypeAction(Mask.getValueType()) ==
6965 "Unable to widen VP strided load");
6966 Mask = GetWidenedVector(Mask);
6967
6968 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6969 assert(Mask.getValueType().getVectorElementCount() ==
6970 WidenVT.getVectorElementCount() &&
6971 "Data and mask vectors should have the same number of elements");
6972
6973 SDValue Res = DAG.getStridedLoadVP(
6974 N->getAddressingMode(), N->getExtensionType(), WidenVT, DL, N->getChain(),
6975 N->getBasePtr(), N->getOffset(), N->getStride(), Mask,
6976 N->getVectorLength(), N->getMemoryVT(), N->getMemOperand(),
6977 N->isExpandingLoad());
6978
6979 // Legalize the chain result - switch anything that used the old chain to
6980 // use the new one.
6981 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6982 return Res;
6983}
6984
6985SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_COMPRESS(SDNode *N) {
6986 SDValue Vec = N->getOperand(0);
6987 SDValue Mask = N->getOperand(1);
6988 SDValue Passthru = N->getOperand(2);
6989 EVT WideVecVT =
6990 TLI.getTypeToTransformTo(*DAG.getContext(), Vec.getValueType());
6991 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
6992 Mask.getValueType().getVectorElementType(),
6993 WideVecVT.getVectorElementCount());
6994
6995 SDValue WideVec = ModifyToType(Vec, WideVecVT);
6996 SDValue WideMask = ModifyToType(Mask, WideMaskVT, /*FillWithZeroes=*/true);
6997 SDValue WidePassthru = ModifyToType(Passthru, WideVecVT);
6998 return DAG.getNode(ISD::VECTOR_COMPRESS, SDLoc(N), WideVecVT, WideVec,
6999 WideMask, WidePassthru);
7000}
7001
7002SDValue DAGTypeLegalizer::WidenVecRes_MLOAD(MaskedLoadSDNode *N) {
7003 EVT VT = N->getValueType(0);
7004 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7005 SDValue Mask = N->getMask();
7006 EVT MaskVT = Mask.getValueType();
7007 SDValue PassThru = GetWidenedVector(N->getPassThru());
7008 ISD::LoadExtType ExtType = N->getExtensionType();
7009 SDLoc dl(N);
7010
7011 EVT WideMaskVT =
7012 EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(),
7013 WidenVT.getVectorElementCount());
7014
7015 if (ExtType == ISD::NON_EXTLOAD && !N->isExpandingLoad() &&
7016 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WidenVT) &&
7017 TLI.isTypeLegal(WideMaskVT) &&
7018 // If there is a passthru, we shouldn't use vp.load. However,
7019 // type legalizer will struggle on masked.load with
7020 // scalable vectors, so for scalable vectors, we still use vp.load
7021 // but manually merge the load result with the passthru using vp.select.
7022 (N->getPassThru()->isUndef() || VT.isScalableVector())) {
7023 Mask = DAG.getInsertSubvector(dl, DAG.getPOISON(WideMaskVT), Mask, 0);
7024 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
7026 SDValue NewLoad =
7027 DAG.getLoadVP(N->getAddressingMode(), ISD::NON_EXTLOAD, WidenVT, dl,
7028 N->getChain(), N->getBasePtr(), N->getOffset(), Mask, EVL,
7029 N->getMemoryVT(), N->getMemOperand());
7030 SDValue NewVal = NewLoad;
7031
7032 // Manually merge with vselect
7033 if (!N->getPassThru()->isUndef()) {
7034 assert(WidenVT.isScalableVector());
7035 NewVal = DAG.getNode(ISD::VSELECT, dl, WidenVT, Mask, NewVal, PassThru);
7036 // The lanes past EVL are poison.
7037 NewVal = DAG.getNode(ISD::VP_MERGE, dl, WidenVT,
7038 DAG.getAllOnesConstant(dl, WideMaskVT), NewVal,
7039 DAG.getPOISON(WidenVT), EVL);
7040 }
7041
7042 // Modified the chain - switch anything that used the old chain to use
7043 // the new one.
7044 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
7045
7046 return NewVal;
7047 }
7048
7049 // The mask should be widened as well
7050 Mask = ModifyToType(Mask, WideMaskVT, true);
7051
7052 SDValue Res = DAG.getMaskedLoad(
7053 WidenVT, dl, N->getChain(), N->getBasePtr(), N->getOffset(), Mask,
7054 PassThru, N->getMemoryVT(), N->getMemOperand(), N->getAddressingMode(),
7055 ExtType, N->isExpandingLoad());
7056 // Legalize the chain result - switch anything that used the old chain to
7057 // use the new one.
7058 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7059 return Res;
7060}
7061
7062SDValue DAGTypeLegalizer::WidenVecRes_MGATHER(MaskedGatherSDNode *N) {
7063
7064 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7065 SDValue Mask = N->getMask();
7066 EVT MaskVT = Mask.getValueType();
7067 SDValue PassThru = GetWidenedVector(N->getPassThru());
7068 SDValue Scale = N->getScale();
7069 ElementCount WideEC = WideVT.getVectorElementCount();
7070 SDLoc dl(N);
7071
7072 // The mask should be widened as well
7073 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
7074 MaskVT.getVectorElementType(), WideEC);
7075 Mask = ModifyToType(Mask, WideMaskVT, true);
7076
7077 // Widen the Index operand
7078 SDValue Index = N->getIndex();
7079 EVT WideIndexVT = EVT::getVectorVT(
7080 *DAG.getContext(), Index.getValueType().getScalarType(), WideEC);
7081 Index = ModifyToType(Index, WideIndexVT);
7082 SDValue Ops[] = { N->getChain(), PassThru, Mask, N->getBasePtr(), Index,
7083 Scale };
7084
7085 // Widen the MemoryType
7086 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
7087 N->getMemoryVT().getScalarType(), WideEC);
7088 SDValue Res = DAG.getMaskedGather(DAG.getVTList(WideVT, MVT::Other),
7089 WideMemVT, dl, Ops, N->getMemOperand(),
7090 N->getIndexType(), N->getExtensionType());
7091
7092 // Legalize the chain result - switch anything that used the old chain to
7093 // use the new one.
7094 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7095 return Res;
7096}
7097
7098SDValue DAGTypeLegalizer::WidenVecRes_VP_GATHER(VPGatherSDNode *N) {
7099 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7100 SDValue Mask = N->getMask();
7101 SDValue Scale = N->getScale();
7102 ElementCount WideEC = WideVT.getVectorElementCount();
7103 SDLoc dl(N);
7104
7105 SDValue Index = GetWidenedVector(N->getIndex());
7106 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
7107 N->getMemoryVT().getScalarType(), WideEC);
7108 Mask = GetWidenedMask(Mask, WideEC);
7109
7110 SDValue Ops[] = {N->getChain(), N->getBasePtr(), Index, Scale,
7111 Mask, N->getVectorLength()};
7112 SDValue Res = DAG.getGatherVP(DAG.getVTList(WideVT, MVT::Other), WideMemVT,
7113 dl, Ops, N->getMemOperand(), N->getIndexType());
7114
7115 // Legalize the chain result - switch anything that used the old chain to
7116 // use the new one.
7117 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7118 return Res;
7119}
7120
7121SDValue DAGTypeLegalizer::WidenVecRes_ScalarOp(SDNode *N) {
7122 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7123 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, N->getOperand(0));
7124}
7125
7126// Return true is this is a SETCC node or a strict version of it.
7127static inline bool isSETCCOp(unsigned Opcode) {
7128 switch (Opcode) {
7129 case ISD::SETCC:
7130 case ISD::STRICT_FSETCC:
7132 return true;
7133 }
7134 return false;
7135}
7136
7137// Return true if this is a node that could have two SETCCs as operands.
7138static inline bool isLogicalMaskOp(unsigned Opcode) {
7139 switch (Opcode) {
7140 case ISD::AND:
7141 case ISD::OR:
7142 case ISD::XOR:
7143 return true;
7144 }
7145 return false;
7146}
7147
7148// If N is a SETCC or a strict variant of it, return the type
7149// of the compare operands.
7151 unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
7152 return N->getOperand(OpNo).getValueType();
7153}
7154
7155// This is used just for the assert in convertMask(). Check that this either
7156// a SETCC or a previously handled SETCC by convertMask().
7157#ifndef NDEBUG
7158static inline bool isSETCCorConvertedSETCC(SDValue N) {
7159 if (N.getOpcode() == ISD::EXTRACT_SUBVECTOR)
7160 N = N.getOperand(0);
7161 else if (N.getOpcode() == ISD::CONCAT_VECTORS) {
7162 for (unsigned i = 1; i < N->getNumOperands(); ++i)
7163 if (!N->getOperand(i)->isUndef())
7164 return false;
7165 N = N.getOperand(0);
7166 }
7167
7168 if (N.getOpcode() == ISD::TRUNCATE)
7169 N = N.getOperand(0);
7170 else if (N.getOpcode() == ISD::SIGN_EXTEND)
7171 N = N.getOperand(0);
7172
7173 if (isLogicalMaskOp(N.getOpcode()))
7174 return isSETCCorConvertedSETCC(N.getOperand(0)) &&
7175 isSETCCorConvertedSETCC(N.getOperand(1));
7176
7177 return (isSETCCOp(N.getOpcode()) ||
7179}
7180#endif
7181
7182// Return a mask of vector type MaskVT to replace InMask. Also adjust MaskVT
7183// to ToMaskVT if needed with vector extension or truncation.
7184SDValue DAGTypeLegalizer::convertMask(SDValue InMask, EVT MaskVT,
7185 EVT ToMaskVT) {
7186 // Currently a SETCC or a AND/OR/XOR with two SETCCs are handled.
7187 // FIXME: This code seems to be too restrictive, we might consider
7188 // generalizing it or dropping it.
7189 assert(isSETCCorConvertedSETCC(InMask) && "Unexpected mask argument.");
7190
7191 // Make a new Mask node, with a legal result VT.
7192 SDValue Mask;
7194 for (unsigned i = 0, e = InMask->getNumOperands(); i < e; ++i)
7195 Ops.push_back(InMask->getOperand(i));
7196 if (InMask->isStrictFPOpcode()) {
7197 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask),
7198 { MaskVT, MVT::Other }, Ops);
7199 ReplaceValueWith(InMask.getValue(1), Mask.getValue(1));
7200 }
7201 else
7202 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask), MaskVT, Ops,
7203 InMask->getFlags());
7204
7205 // If MaskVT has smaller or bigger elements than ToMaskVT, a vector sign
7206 // extend or truncate is needed.
7207 LLVMContext &Ctx = *DAG.getContext();
7208 unsigned MaskScalarBits = MaskVT.getScalarSizeInBits();
7209 unsigned ToMaskScalBits = ToMaskVT.getScalarSizeInBits();
7210 if (MaskScalarBits < ToMaskScalBits) {
7211 EVT ExtVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
7212 MaskVT.getVectorNumElements());
7213 Mask = DAG.getNode(ISD::SIGN_EXTEND, SDLoc(Mask), ExtVT, Mask);
7214 } else if (MaskScalarBits > ToMaskScalBits) {
7215 EVT TruncVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
7216 MaskVT.getVectorNumElements());
7217 Mask = DAG.getNode(ISD::TRUNCATE, SDLoc(Mask), TruncVT, Mask);
7218 }
7219
7220 assert(Mask->getValueType(0).getScalarSizeInBits() ==
7221 ToMaskVT.getScalarSizeInBits() &&
7222 "Mask should have the right element size by now.");
7223
7224 // Adjust Mask to the right number of elements.
7225 unsigned CurrMaskNumEls = Mask->getValueType(0).getVectorNumElements();
7226 if (CurrMaskNumEls > ToMaskVT.getVectorNumElements()) {
7227 Mask = DAG.getExtractSubvector(SDLoc(Mask), ToMaskVT, Mask, 0);
7228 } else if (CurrMaskNumEls < ToMaskVT.getVectorNumElements()) {
7229 unsigned NumSubVecs = (ToMaskVT.getVectorNumElements() / CurrMaskNumEls);
7230 EVT SubVT = Mask->getValueType(0);
7231 SmallVector<SDValue, 16> SubOps(NumSubVecs, DAG.getPOISON(SubVT));
7232 SubOps[0] = Mask;
7233 Mask = DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Mask), ToMaskVT, SubOps);
7234 }
7235
7236 assert((Mask->getValueType(0) == ToMaskVT) &&
7237 "A mask of ToMaskVT should have been produced by now.");
7238
7239 return Mask;
7240}
7241
7242// This method tries to handle some special cases for the vselect mask
7243// and if needed adjusting the mask vector type to match that of the VSELECT.
7244// Without it, many cases end up with scalarization of the SETCC, with many
7245// unnecessary instructions.
7246SDValue DAGTypeLegalizer::WidenVSELECTMask(SDNode *N) {
7247 LLVMContext &Ctx = *DAG.getContext();
7248 SDValue Cond = N->getOperand(0);
7249
7250 if (N->getOpcode() != ISD::VSELECT)
7251 return SDValue();
7252
7253 if (!isSETCCOp(Cond->getOpcode()) && !isLogicalMaskOp(Cond->getOpcode()))
7254 return SDValue();
7255
7256 // If this is a splitted VSELECT that was previously already handled, do
7257 // nothing.
7258 EVT CondVT = Cond->getValueType(0);
7259 if (CondVT.getScalarSizeInBits() != 1)
7260 return SDValue();
7261
7262 EVT VSelVT = N->getValueType(0);
7263
7264 // This method can't handle scalable vector types.
7265 // FIXME: This support could be added in the future.
7266 if (VSelVT.isScalableVector())
7267 return SDValue();
7268
7269 // Only handle vector types which are a power of 2.
7270 if (!isPowerOf2_64(VSelVT.getSizeInBits()))
7271 return SDValue();
7272
7273 // Don't touch if this will be scalarized.
7274 EVT FinalVT = VSelVT;
7275 while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
7276 FinalVT = FinalVT.getHalfNumVectorElementsVT(Ctx);
7277
7278 if (FinalVT.getVectorNumElements() == 1)
7279 return SDValue();
7280
7281 // If there is support for an i1 vector mask, don't touch.
7282 if (isSETCCOp(Cond.getOpcode())) {
7283 EVT SetCCOpVT = getSETCCOperandType(Cond);
7284 while (TLI.getTypeAction(Ctx, SetCCOpVT) != TargetLowering::TypeLegal)
7285 SetCCOpVT = TLI.getTypeToTransformTo(Ctx, SetCCOpVT);
7286 EVT SetCCResVT = getSetCCResultType(SetCCOpVT);
7287 if (SetCCResVT.getScalarSizeInBits() == 1)
7288 return SDValue();
7289 } else if (CondVT.getScalarType() == MVT::i1) {
7290 // If there is support for an i1 vector mask (or only scalar i1 conditions),
7291 // don't touch.
7292 while (TLI.getTypeAction(Ctx, CondVT) != TargetLowering::TypeLegal)
7293 CondVT = TLI.getTypeToTransformTo(Ctx, CondVT);
7294
7295 if (CondVT.getScalarType() == MVT::i1)
7296 return SDValue();
7297 }
7298
7299 // Widen the vselect result type if needed.
7300 if (getTypeAction(VSelVT) == TargetLowering::TypeWidenVector)
7301 VSelVT = TLI.getTypeToTransformTo(Ctx, VSelVT);
7302
7303 // The mask of the VSELECT should have integer elements.
7304 EVT ToMaskVT = VSelVT;
7305 if (!ToMaskVT.getScalarType().isInteger())
7306 ToMaskVT = ToMaskVT.changeVectorElementTypeToInteger();
7307
7308 SDValue Mask;
7309 if (isSETCCOp(Cond->getOpcode())) {
7310 EVT MaskVT = getSetCCResultType(getSETCCOperandType(Cond));
7311 Mask = convertMask(Cond, MaskVT, ToMaskVT);
7312 } else if (isLogicalMaskOp(Cond->getOpcode()) &&
7313 isSETCCOp(Cond->getOperand(0).getOpcode()) &&
7314 isSETCCOp(Cond->getOperand(1).getOpcode())) {
7315 // Cond is (AND/OR/XOR (SETCC, SETCC))
7316 SDValue SETCC0 = Cond->getOperand(0);
7317 SDValue SETCC1 = Cond->getOperand(1);
7318 EVT VT0 = getSetCCResultType(getSETCCOperandType(SETCC0));
7319 EVT VT1 = getSetCCResultType(getSETCCOperandType(SETCC1));
7320 unsigned ScalarBits0 = VT0.getScalarSizeInBits();
7321 unsigned ScalarBits1 = VT1.getScalarSizeInBits();
7322 unsigned ScalarBits_ToMask = ToMaskVT.getScalarSizeInBits();
7323 EVT MaskVT;
7324 // If the two SETCCs have different VTs, either extend/truncate one of
7325 // them to the other "towards" ToMaskVT, or truncate one and extend the
7326 // other to ToMaskVT.
7327 if (ScalarBits0 != ScalarBits1) {
7328 EVT NarrowVT = ((ScalarBits0 < ScalarBits1) ? VT0 : VT1);
7329 EVT WideVT = ((NarrowVT == VT0) ? VT1 : VT0);
7330 if (ScalarBits_ToMask >= WideVT.getScalarSizeInBits())
7331 MaskVT = WideVT;
7332 else if (ScalarBits_ToMask <= NarrowVT.getScalarSizeInBits())
7333 MaskVT = NarrowVT;
7334 else
7335 MaskVT = ToMaskVT;
7336 } else
7337 // If the two SETCCs have the same VT, don't change it.
7338 MaskVT = VT0;
7339
7340 // Make new SETCCs and logical nodes.
7341 SETCC0 = convertMask(SETCC0, VT0, MaskVT);
7342 SETCC1 = convertMask(SETCC1, VT1, MaskVT);
7343 Cond = DAG.getNode(Cond->getOpcode(), SDLoc(Cond), MaskVT, SETCC0, SETCC1);
7344
7345 // Convert the logical op for VSELECT if needed.
7346 Mask = convertMask(Cond, MaskVT, ToMaskVT);
7347 } else
7348 return SDValue();
7349
7350 return Mask;
7351}
7352
7353SDValue DAGTypeLegalizer::WidenVecRes_Select(SDNode *N) {
7354 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7355 ElementCount WidenEC = WidenVT.getVectorElementCount();
7356
7357 SDValue Cond1 = N->getOperand(0);
7358 EVT CondVT = Cond1.getValueType();
7359 unsigned Opcode = N->getOpcode();
7360 if (CondVT.isVector()) {
7361 if (SDValue WideCond = WidenVSELECTMask(N)) {
7362 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
7363 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
7364 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
7365 return DAG.getNode(Opcode, SDLoc(N), WidenVT, WideCond, InOp1, InOp2);
7366 }
7367
7368 EVT CondEltVT = CondVT.getVectorElementType();
7369 EVT CondWidenVT = EVT::getVectorVT(*DAG.getContext(), CondEltVT, WidenEC);
7370 if (getTypeAction(CondVT) == TargetLowering::TypeWidenVector)
7371 Cond1 = GetWidenedVector(Cond1);
7372
7373 // If we have to split the condition there is no point in widening the
7374 // select. This would result in an cycle of widening the select ->
7375 // widening the condition operand -> splitting the condition operand ->
7376 // splitting the select -> widening the select. Instead split this select
7377 // further and widen the resulting type.
7378 if (getTypeAction(CondVT) == TargetLowering::TypeSplitVector) {
7379 SDValue SplitSelect = SplitVecOp_VSELECT(N, 0);
7380 SDValue Res = ModifyToType(SplitSelect, WidenVT);
7381 return Res;
7382 }
7383
7384 if (Cond1.getValueType() != CondWidenVT)
7385 Cond1 = ModifyToType(Cond1, CondWidenVT);
7386 }
7387
7388 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
7389 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
7390 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
7391 if (Opcode == ISD::VP_SELECT || Opcode == ISD::VP_MERGE)
7392 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2,
7393 N->getOperand(3));
7394 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2);
7395}
7396
7397SDValue DAGTypeLegalizer::WidenVecRes_SELECT_CC(SDNode *N) {
7398 SDValue InOp1 = GetWidenedVector(N->getOperand(2));
7399 SDValue InOp2 = GetWidenedVector(N->getOperand(3));
7400 return DAG.getNode(ISD::SELECT_CC, SDLoc(N),
7401 InOp1.getValueType(), N->getOperand(0),
7402 N->getOperand(1), InOp1, InOp2, N->getOperand(4));
7403}
7404
7405SDValue DAGTypeLegalizer::WidenVecRes_UNDEF(SDNode *N) {
7406 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7407 return DAG.getUNDEF(WidenVT);
7408}
7409
7410SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N) {
7411 EVT VT = N->getValueType(0);
7412 SDLoc dl(N);
7413
7414 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7415 unsigned NumElts = VT.getVectorNumElements();
7416 unsigned WidenNumElts = WidenVT.getVectorNumElements();
7417
7418 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
7419 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
7420
7421 // Adjust mask based on new input vector length.
7422 SmallVector<int, 16> NewMask(WidenNumElts, -1);
7423 for (unsigned i = 0; i != NumElts; ++i) {
7424 int Idx = N->getMaskElt(i);
7425 if (Idx < (int)NumElts)
7426 NewMask[i] = Idx;
7427 else
7428 NewMask[i] = Idx - NumElts + WidenNumElts;
7429 }
7430 return DAG.getVectorShuffle(WidenVT, dl, InOp1, InOp2, NewMask);
7431}
7432
7433SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_REVERSE(SDNode *N) {
7434 EVT VT = N->getValueType(0);
7435 EVT EltVT = VT.getVectorElementType();
7436 SDLoc dl(N);
7437
7438 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7439 SDValue OpValue = GetWidenedVector(N->getOperand(0));
7440 assert(WidenVT == OpValue.getValueType() && "Unexpected widened vector type");
7441
7442 SDValue ReverseVal = DAG.getNode(ISD::VECTOR_REVERSE, dl, WidenVT, OpValue);
7443 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
7444 unsigned VTNumElts = VT.getVectorMinNumElements();
7445 unsigned IdxVal = WidenNumElts - VTNumElts;
7446
7447 if (VT.isScalableVector()) {
7448 // Try to split the 'Widen ReverseVal' into smaller extracts and concat the
7449 // results together, e.g.(nxv6i64 -> nxv8i64)
7450 // nxv8i64 vector_reverse
7451 // <->
7452 // nxv8i64 concat(
7453 // nxv2i64 extract_subvector(nxv8i64, 2)
7454 // nxv2i64 extract_subvector(nxv8i64, 4)
7455 // nxv2i64 extract_subvector(nxv8i64, 6)
7456 // nxv2i64 undef)
7457
7458 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
7459 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
7461 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
7462 "down type's element count");
7464 unsigned i = 0;
7465 for (; i < VTNumElts / GCD; ++i)
7466 Parts.push_back(
7467 DAG.getExtractSubvector(dl, PartVT, ReverseVal, IdxVal + i * GCD));
7468 for (; i < WidenNumElts / GCD; ++i)
7469 Parts.push_back(DAG.getPOISON(PartVT));
7470
7471 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
7472 }
7473
7474 // Use VECTOR_SHUFFLE to combine new vector from 'ReverseVal' for
7475 // fixed-vectors.
7476 SmallVector<int, 16> Mask(WidenNumElts, -1);
7477 std::iota(Mask.begin(), Mask.begin() + VTNumElts, IdxVal);
7478
7479 return DAG.getVectorShuffle(WidenVT, dl, ReverseVal, DAG.getPOISON(WidenVT),
7480 Mask);
7481}
7482
7483SDValue DAGTypeLegalizer::WidenVecRes_GET_ACTIVE_LANE_MASK(SDNode *N) {
7484 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7485 return DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, SDLoc(N), NVT, N->ops());
7486}
7487
7488void DAGTypeLegalizer::WidenVecRes_VECTOR_DEINTERLEAVE(SDNode *N) {
7489 EVT VT = N->getValueType(0);
7490 EVT EltVT = VT.getVectorElementType();
7491 ElementCount OrigEC = VT.getVectorElementCount();
7492 unsigned Factor = N->getNumOperands();
7493 SDLoc DL(N);
7494
7495 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7496 ElementCount WidenEC = WidenVT.getVectorElementCount();
7497 // We cannot just use the widened operands directly: since they might be
7498 // individually widened, using them directly will result in de-interleaving
7499 // the "padded" lanes that sit in the middle of the vector. Instead, we should
7500 // not concat the widened operands but the original ones to effectively
7501 // generate a "packed" concated and widened vector, before extracting new
7502 // operand vectors with the widened type.
7503 EVT PackedWidenVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
7504 WidenEC.multiplyCoefficientBy(Factor));
7505 EVT ConcatVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
7506 OrigEC.multiplyCoefficientBy(Factor));
7507 SDValue ConcatOp = DAG.getNode(ISD::CONCAT_VECTORS, DL, ConcatVT, N->ops());
7508 SDValue PackedWidenVec = DAG.getInsertSubvector(
7509 DL, DAG.getUNDEF(PackedWidenVT), ConcatOp, /*Idx=*/0U);
7510
7511 // Extract the new widened operand vectors.
7512 SmallVector<SDValue, 8> NewOps(Factor, SDValue());
7513 for (unsigned Idx = 0U; Idx < Factor; ++Idx) {
7514 NewOps[Idx] = DAG.getExtractSubvector(
7515 DL, WidenVT, PackedWidenVec,
7517 }
7518
7519 SmallVector<EVT, 8> NewVTs(Factor, WidenVT);
7520 SDValue NewRes = DAG.getNode(ISD::VECTOR_DEINTERLEAVE, DL, NewVTs, NewOps);
7521 // Set the widened results manually.
7522 for (unsigned Idx = 0U; Idx < Factor; ++Idx)
7523 SetWidenedVector(SDValue(N, Idx), NewRes.getValue(Idx));
7524}
7525
7526SDValue DAGTypeLegalizer::WidenVecRes_SETCC(SDNode *N) {
7527 assert(N->getValueType(0).isVector() &&
7528 N->getOperand(0).getValueType().isVector() &&
7529 "Operands must be vectors");
7530 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7531 ElementCount WidenEC = WidenVT.getVectorElementCount();
7532
7533 SDValue InOp1 = N->getOperand(0);
7534 EVT InVT = InOp1.getValueType();
7535 assert(InVT.isVector() && "can not widen non-vector type");
7536 EVT WidenInVT =
7537 EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), WidenEC);
7538
7539 // The input and output types often differ here, and it could be that while
7540 // we'd prefer to widen the result type, the input operands have been split.
7541 // In this case, we also need to split the result of this node as well.
7542 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector) {
7543 SDValue SplitVSetCC = SplitVecOp_VSETCC(N);
7544 SDValue Res = ModifyToType(SplitVSetCC, WidenVT);
7545 return Res;
7546 }
7547
7548 // If the inputs also widen, handle them directly. Otherwise widen by hand.
7549 SDValue InOp2 = N->getOperand(1);
7550 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
7551 InOp1 = GetWidenedVector(InOp1);
7552 InOp2 = GetWidenedVector(InOp2);
7553 } else {
7554 SDValue Poison = DAG.getPOISON(WidenInVT);
7555 SDValue ZeroIdx = DAG.getVectorIdxConstant(0, SDLoc(N));
7556 InOp1 = DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), WidenInVT, Poison,
7557 InOp1, ZeroIdx);
7558 InOp2 = DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), WidenInVT, Poison,
7559 InOp2, ZeroIdx);
7560 }
7561
7562 // Assume that the input and output will be widen appropriately. If not,
7563 // we will have to unroll it at some point.
7564 assert(InOp1.getValueType() == WidenInVT &&
7565 InOp2.getValueType() == WidenInVT &&
7566 "Input not widened to expected type!");
7567 (void)WidenInVT;
7568 if (N->getOpcode() == ISD::VP_SETCC) {
7569 SDValue Mask =
7570 GetWidenedMask(N->getOperand(3), WidenVT.getVectorElementCount());
7571 return DAG.getNode(ISD::VP_SETCC, SDLoc(N), WidenVT, InOp1, InOp2,
7572 N->getOperand(2), Mask, N->getOperand(4));
7573 }
7574 return DAG.getNode(ISD::SETCC, SDLoc(N), WidenVT, InOp1, InOp2,
7575 N->getOperand(2));
7576}
7577
7578SDValue DAGTypeLegalizer::WidenVecRes_STRICT_FSETCC(SDNode *N) {
7579 assert(N->getValueType(0).isVector() &&
7580 N->getOperand(1).getValueType().isVector() &&
7581 "Operands must be vectors");
7582 EVT VT = N->getValueType(0);
7583 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7584 unsigned WidenNumElts = WidenVT.getVectorNumElements();
7585 unsigned NumElts = VT.getVectorNumElements();
7586 EVT EltVT = VT.getVectorElementType();
7587
7588 SDLoc dl(N);
7589 SDValue Chain = N->getOperand(0);
7590 SDValue LHS = N->getOperand(1);
7591 SDValue RHS = N->getOperand(2);
7592 SDValue CC = N->getOperand(3);
7593 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
7594
7595 // Fully unroll and reassemble.
7596 SmallVector<SDValue, 8> Scalars(WidenNumElts, DAG.getPOISON(EltVT));
7597 SmallVector<SDValue, 8> Chains(NumElts);
7598 for (unsigned i = 0; i != NumElts; ++i) {
7599 SDValue LHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, LHS, i);
7600 SDValue RHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, RHS, i);
7601
7602 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
7603 {Chain, LHSElem, RHSElem, CC});
7604 Chains[i] = Scalars[i].getValue(1);
7605 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
7606 DAG.getBoolConstant(true, dl, EltVT, VT),
7607 DAG.getBoolConstant(false, dl, EltVT, VT));
7608 }
7609
7610 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
7611 ReplaceValueWith(SDValue(N, 1), NewChain);
7612
7613 return DAG.getBuildVector(WidenVT, dl, Scalars);
7614}
7615
7616//===----------------------------------------------------------------------===//
7617// Widen Vector Operand
7618//===----------------------------------------------------------------------===//
7619bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned OpNo) {
7620 LLVM_DEBUG(dbgs() << "Widen node operand " << OpNo << ": "; N->dump(&DAG));
7621 SDValue Res = SDValue();
7622
7623 // See if the target wants to custom widen this node.
7624 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
7625 return false;
7626
7627 switch (N->getOpcode()) {
7628 default:
7629#ifndef NDEBUG
7630 dbgs() << "WidenVectorOperand op #" << OpNo << ": ";
7631 N->dump(&DAG);
7632 dbgs() << "\n";
7633#endif
7634 report_fatal_error("Do not know how to widen this operator's operand!");
7635
7636 case ISD::BITCAST: Res = WidenVecOp_BITCAST(N); break;
7637 case ISD::FAKE_USE:
7638 Res = WidenVecOp_FAKE_USE(N);
7639 break;
7640 case ISD::CONCAT_VECTORS: Res = WidenVecOp_CONCAT_VECTORS(N); break;
7641 case ISD::INSERT_SUBVECTOR: Res = WidenVecOp_INSERT_SUBVECTOR(N); break;
7642 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecOp_EXTRACT_SUBVECTOR(N); break;
7643 case ISD::EXTRACT_VECTOR_ELT: Res = WidenVecOp_EXTRACT_VECTOR_ELT(N); break;
7644 case ISD::STORE: Res = WidenVecOp_STORE(N); break;
7645 case ISD::ATOMIC_STORE:
7646 Res = WidenVecOp_ATOMIC_STORE(cast<AtomicSDNode>(N));
7647 break;
7648 case ISD::VP_STORE: Res = WidenVecOp_VP_STORE(N, OpNo); break;
7649 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
7650 Res = WidenVecOp_VP_STRIDED_STORE(N, OpNo);
7651 break;
7655 Res = WidenVecOp_EXTEND_VECTOR_INREG(N);
7656 break;
7657 case ISD::MSTORE: Res = WidenVecOp_MSTORE(N, OpNo); break;
7658 case ISD::MGATHER: Res = WidenVecOp_MGATHER(N, OpNo); break;
7659 case ISD::MSCATTER: Res = WidenVecOp_MSCATTER(N, OpNo); break;
7660 case ISD::VP_SCATTER: Res = WidenVecOp_VP_SCATTER(N, OpNo); break;
7661 case ISD::SETCC: Res = WidenVecOp_SETCC(N); break;
7662 case ISD::STRICT_FSETCC:
7663 case ISD::STRICT_FSETCCS: Res = WidenVecOp_STRICT_FSETCC(N); break;
7664 case ISD::VSELECT: Res = WidenVecOp_VSELECT(N); break;
7665 case ISD::FLDEXP:
7666 case ISD::FCOPYSIGN:
7667 case ISD::LROUND:
7668 case ISD::LLROUND:
7669 case ISD::LRINT:
7670 case ISD::LLRINT:
7671 Res = WidenVecOp_UnrollVectorOp(N);
7672 break;
7673 case ISD::IS_FPCLASS: Res = WidenVecOp_IS_FPCLASS(N); break;
7674
7675 case ISD::ANY_EXTEND:
7676 case ISD::SIGN_EXTEND:
7677 case ISD::ZERO_EXTEND:
7678 Res = WidenVecOp_EXTEND(N);
7679 break;
7680
7681 case ISD::SCMP:
7682 case ISD::UCMP:
7683 Res = WidenVecOp_CMP(N);
7684 break;
7685
7686 case ISD::FP_EXTEND:
7688 case ISD::FP_ROUND:
7690 case ISD::FP_TO_SINT:
7692 case ISD::FP_TO_UINT:
7694 case ISD::SINT_TO_FP:
7696 case ISD::UINT_TO_FP:
7698 case ISD::TRUNCATE:
7701 Res = WidenVecOp_Convert(N);
7702 break;
7703
7706 Res = WidenVecOp_FP_TO_XINT_SAT(N);
7707 break;
7708
7711 case ISD::VECREDUCE_ADD:
7712 case ISD::VECREDUCE_MUL:
7713 case ISD::VECREDUCE_AND:
7714 case ISD::VECREDUCE_OR:
7715 case ISD::VECREDUCE_XOR:
7724 Res = WidenVecOp_VECREDUCE(N);
7725 break;
7728 Res = WidenVecOp_VECREDUCE_SEQ(N);
7729 break;
7730 case ISD::VP_REDUCE_FADD:
7731 case ISD::VP_REDUCE_SEQ_FADD:
7732 case ISD::VP_REDUCE_FMUL:
7733 case ISD::VP_REDUCE_SEQ_FMUL:
7734 case ISD::VP_REDUCE_ADD:
7735 case ISD::VP_REDUCE_MUL:
7736 case ISD::VP_REDUCE_AND:
7737 case ISD::VP_REDUCE_OR:
7738 case ISD::VP_REDUCE_XOR:
7739 case ISD::VP_REDUCE_SMAX:
7740 case ISD::VP_REDUCE_SMIN:
7741 case ISD::VP_REDUCE_UMAX:
7742 case ISD::VP_REDUCE_UMIN:
7743 case ISD::VP_REDUCE_FMAX:
7744 case ISD::VP_REDUCE_FMIN:
7745 case ISD::VP_REDUCE_FMAXIMUM:
7746 case ISD::VP_REDUCE_FMINIMUM:
7747 Res = WidenVecOp_VP_REDUCE(N);
7748 break;
7749 case ISD::CTTZ_ELTS:
7751 Res = WidenVecOp_CttzElements(N);
7752 break;
7753 case ISD::VP_CTTZ_ELTS:
7754 case ISD::VP_CTTZ_ELTS_ZERO_POISON:
7755 Res = WidenVecOp_VP_CttzElements(N);
7756 break;
7758 Res = WidenVecOp_VECTOR_FIND_LAST_ACTIVE(N);
7759 break;
7760 }
7761
7762 // If Res is null, the sub-method took care of registering the result.
7763 if (!Res.getNode()) return false;
7764
7765 // If the result is N, the sub-method updated N in place. Tell the legalizer
7766 // core about this.
7767 if (Res.getNode() == N)
7768 return true;
7769
7770
7771 if (N->isStrictFPOpcode())
7772 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
7773 "Invalid operand expansion");
7774 else
7775 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
7776 "Invalid operand expansion");
7777
7778 ReplaceValueWith(SDValue(N, 0), Res);
7779 return false;
7780}
7781
7782SDValue DAGTypeLegalizer::WidenVecOp_EXTEND(SDNode *N) {
7783 SDLoc DL(N);
7784 EVT VT = N->getValueType(0);
7785
7786 SDValue InOp = N->getOperand(0);
7787 assert(getTypeAction(InOp.getValueType()) ==
7789 "Unexpected type action");
7790 InOp = GetWidenedVector(InOp);
7793 "Input wasn't widened!");
7794
7795 // We may need to further widen the operand until it has the same total
7796 // vector size as the result.
7797 EVT InVT = InOp.getValueType();
7798 if (InVT.getSizeInBits() != VT.getSizeInBits()) {
7799 EVT InEltVT = InVT.getVectorElementType();
7800 for (EVT FixedVT : MVT::vector_valuetypes()) {
7801 EVT FixedEltVT = FixedVT.getVectorElementType();
7802 if (TLI.isTypeLegal(FixedVT) &&
7803 FixedVT.getSizeInBits() == VT.getSizeInBits() &&
7804 FixedEltVT == InEltVT) {
7805 assert(FixedVT.getVectorNumElements() >= VT.getVectorNumElements() &&
7806 "Not enough elements in the fixed type for the operand!");
7807 assert(FixedVT.getVectorNumElements() != InVT.getVectorNumElements() &&
7808 "We can't have the same type as we started with!");
7809 if (FixedVT.getVectorNumElements() > InVT.getVectorNumElements())
7810 InOp = DAG.getInsertSubvector(DL, DAG.getPOISON(FixedVT), InOp, 0);
7811 else
7812 InOp = DAG.getExtractSubvector(DL, FixedVT, InOp, 0);
7813 break;
7814 }
7815 }
7816 InVT = InOp.getValueType();
7817 if (InVT.getSizeInBits() != VT.getSizeInBits())
7818 // We couldn't find a legal vector type that was a widening of the input
7819 // and could be extended in-register to the result type, so we have to
7820 // scalarize.
7821 return WidenVecOp_Convert(N);
7822 }
7823
7824 // Use special DAG nodes to represent the operation of extending the
7825 // low lanes.
7826 switch (N->getOpcode()) {
7827 default:
7828 llvm_unreachable("Extend legalization on extend operation!");
7829 case ISD::ANY_EXTEND:
7830 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, VT, InOp);
7831 case ISD::SIGN_EXTEND:
7832 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, VT, InOp);
7833 case ISD::ZERO_EXTEND:
7834 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, VT, InOp);
7835 }
7836}
7837
7838SDValue DAGTypeLegalizer::WidenVecOp_CMP(SDNode *N) {
7839 SDLoc dl(N);
7840
7841 EVT OpVT = N->getOperand(0).getValueType();
7842 EVT ResVT = N->getValueType(0);
7843 SDValue LHS = GetWidenedVector(N->getOperand(0));
7844 SDValue RHS = GetWidenedVector(N->getOperand(1));
7845
7846 // 1. EXTRACT_SUBVECTOR
7847 // 2. SIGN_EXTEND/ZERO_EXTEND
7848 // 3. CMP
7849 LHS = DAG.getExtractSubvector(dl, OpVT, LHS, 0);
7850 RHS = DAG.getExtractSubvector(dl, OpVT, RHS, 0);
7851
7852 // At this point the result type is guaranteed to be valid, so we can use it
7853 // as the operand type by extending it appropriately
7854 ISD::NodeType ExtendOpcode =
7855 N->getOpcode() == ISD::SCMP ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
7856 LHS = DAG.getNode(ExtendOpcode, dl, ResVT, LHS);
7857 RHS = DAG.getNode(ExtendOpcode, dl, ResVT, RHS);
7858
7859 return DAG.getNode(N->getOpcode(), dl, ResVT, LHS, RHS);
7860}
7861
7862SDValue DAGTypeLegalizer::WidenVecOp_UnrollVectorOp(SDNode *N) {
7863 // The result (and first input) is legal, but the second input is illegal.
7864 // We can't do much to fix that, so just unroll and let the extracts off of
7865 // the second input be widened as needed later.
7866 return DAG.UnrollVectorOp(N);
7867}
7868
7869SDValue DAGTypeLegalizer::WidenVecOp_IS_FPCLASS(SDNode *N) {
7870 SDLoc DL(N);
7871 EVT ResultVT = N->getValueType(0);
7872 SDValue Test = N->getOperand(1);
7873 SDValue WideArg = GetWidenedVector(N->getOperand(0));
7874
7875 // Process this node similarly to SETCC.
7876 EVT WideResultVT = getSetCCResultType(WideArg.getValueType());
7877 if (ResultVT.getScalarType() == MVT::i1)
7878 WideResultVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
7879 WideResultVT.getVectorNumElements());
7880
7881 SDValue WideNode = DAG.getNode(ISD::IS_FPCLASS, DL, WideResultVT,
7882 {WideArg, Test}, N->getFlags());
7883
7884 // Extract the needed results from the result vector.
7885 EVT ResVT =
7886 EVT::getVectorVT(*DAG.getContext(), WideResultVT.getVectorElementType(),
7887 ResultVT.getVectorNumElements());
7888 SDValue CC = DAG.getExtractSubvector(DL, ResVT, WideNode, 0);
7889
7890 EVT OpVT = N->getOperand(0).getValueType();
7891 ISD::NodeType ExtendCode =
7892 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
7893 return DAG.getNode(ExtendCode, DL, ResultVT, CC);
7894}
7895
7896SDValue DAGTypeLegalizer::WidenVecOp_Convert(SDNode *N) {
7897 // Since the result is legal and the input is illegal.
7898 EVT VT = N->getValueType(0);
7899 EVT EltVT = VT.getVectorElementType();
7900 SDLoc dl(N);
7901 SDValue InOp = N->getOperand(N->isStrictFPOpcode() ? 1 : 0);
7902 assert(getTypeAction(InOp.getValueType()) ==
7904 "Unexpected type action");
7905 InOp = GetWidenedVector(InOp);
7906 EVT InVT = InOp.getValueType();
7907 unsigned Opcode = N->getOpcode();
7908
7909 // Helper to build a convert node with all scalar trailing operands.
7910 auto MakeConvertNode = [&](EVT VT, SDValue Op) -> SDValue {
7911 if (Opcode == ISD::CONVERT_TO_ARBITRARY_FP)
7912 return DAG.getNode(Opcode, dl, VT, Op, N->getOperand(1), N->getOperand(2),
7913 N->getOperand(3));
7914 if (Opcode == ISD::FP_ROUND || Opcode == ISD::CONVERT_FROM_ARBITRARY_FP)
7915 return DAG.getNode(Opcode, dl, VT, Op, N->getOperand(1));
7916 return DAG.getNode(Opcode, dl, VT, Op);
7917 };
7918
7919 // See if a widened result type would be legal, if so widen the node.
7920 // FIXME: This isn't safe for StrictFP. Other optimization here is needed.
7921 EVT WideVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
7922 InVT.getVectorElementCount());
7923 if (TLI.isTypeLegal(WideVT) && !N->isStrictFPOpcode()) {
7924 SDValue Res;
7925 if (N->isStrictFPOpcode()) {
7926 if (Opcode == ISD::STRICT_FP_ROUND)
7927 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
7928 { N->getOperand(0), InOp, N->getOperand(2) });
7929 else
7930 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
7931 { N->getOperand(0), InOp });
7932 // Legalize the chain result - switch anything that used the old chain to
7933 // use the new one.
7934 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7935 } else {
7936 Res = MakeConvertNode(WideVT, InOp);
7937 }
7938 return DAG.getExtractSubvector(dl, VT, Res, 0);
7939 }
7940
7941 EVT InEltVT = InVT.getVectorElementType();
7942
7943 // Unroll the convert into some scalar code and create a nasty build vector.
7944 unsigned NumElts = VT.getVectorNumElements();
7946 if (N->isStrictFPOpcode()) {
7947 SmallVector<SDValue, 4> NewOps(N->ops());
7948 SmallVector<SDValue, 32> OpChains;
7949 for (unsigned i=0; i < NumElts; ++i) {
7950 NewOps[1] = DAG.getExtractVectorElt(dl, InEltVT, InOp, i);
7951 Ops[i] = DAG.getNode(Opcode, dl, { EltVT, MVT::Other }, NewOps);
7952 OpChains.push_back(Ops[i].getValue(1));
7953 }
7954 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OpChains);
7955 ReplaceValueWith(SDValue(N, 1), NewChain);
7956 } else {
7957 for (unsigned i = 0; i < NumElts; ++i) {
7958 SDValue Elt = DAG.getExtractVectorElt(dl, InEltVT, InOp, i);
7959 Ops[i] = MakeConvertNode(EltVT, Elt);
7960 }
7961 }
7962
7963 return DAG.getBuildVector(VT, dl, Ops);
7964}
7965
7966SDValue DAGTypeLegalizer::WidenVecOp_FP_TO_XINT_SAT(SDNode *N) {
7967 EVT DstVT = N->getValueType(0);
7968 SDValue Src = GetWidenedVector(N->getOperand(0));
7969 EVT SrcVT = Src.getValueType();
7970 ElementCount WideNumElts = SrcVT.getVectorElementCount();
7971 SDLoc dl(N);
7972
7973 // See if a widened result type would be legal, if so widen the node.
7974 EVT WideDstVT = EVT::getVectorVT(*DAG.getContext(),
7975 DstVT.getVectorElementType(), WideNumElts);
7976 if (TLI.isTypeLegal(WideDstVT)) {
7977 SDValue Res =
7978 DAG.getNode(N->getOpcode(), dl, WideDstVT, Src, N->getOperand(1));
7979 return DAG.getNode(
7980 ISD::EXTRACT_SUBVECTOR, dl, DstVT, Res,
7981 DAG.getConstant(0, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
7982 }
7983
7984 // Give up and unroll.
7985 return DAG.UnrollVectorOp(N);
7986}
7987
7988SDValue DAGTypeLegalizer::WidenVecOp_BITCAST(SDNode *N) {
7989 EVT VT = N->getValueType(0);
7990 SDValue InOp = GetWidenedVector(N->getOperand(0));
7991 EVT InWidenVT = InOp.getValueType();
7992 SDLoc dl(N);
7993
7994 // Check if we can convert between two legal vector types and extract.
7995 TypeSize InWidenSize = InWidenVT.getSizeInBits();
7996 TypeSize Size = VT.getSizeInBits();
7997 // x86mmx is not an acceptable vector element type, so don't try.
7998 if (!VT.isVector() && VT != MVT::x86mmx &&
7999 InWidenSize.hasKnownScalarFactor(Size)) {
8000 unsigned NewNumElts = InWidenSize.getKnownScalarFactor(Size);
8001 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), VT, NewNumElts);
8002 if (TLI.isTypeLegal(NewVT)) {
8003 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
8004 return DAG.getExtractVectorElt(dl, VT, BitOp, 0);
8005 }
8006 }
8007
8008 // Handle a case like bitcast v12i8 -> v3i32. Normally that would get widened
8009 // to v16i8 -> v4i32, but for a target where v3i32 is legal but v12i8 is not,
8010 // we end up here. Handling the case here with EXTRACT_SUBVECTOR avoids
8011 // having to copy via memory.
8012 if (VT.isVector()) {
8013 EVT EltVT = VT.getVectorElementType();
8014 unsigned EltSize = EltVT.getFixedSizeInBits();
8015 if (InWidenSize.isKnownMultipleOf(EltSize)) {
8016 ElementCount NewNumElts =
8017 (InWidenVT.getVectorElementCount() * InWidenVT.getScalarSizeInBits())
8018 .divideCoefficientBy(EltSize);
8019 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NewNumElts);
8020 if (TLI.isTypeLegal(NewVT)) {
8021 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
8022 return DAG.getExtractSubvector(dl, VT, BitOp, 0);
8023 }
8024 }
8025 }
8026
8027 return CreateStackStoreLoad(InOp, VT);
8028}
8029
8030// Vectors with sizes that are not powers of 2 need to be widened to the
8031// next largest power of 2. For example, we may get a vector of 3 32-bit
8032// integers or of 6 16-bit integers, both of which have to be widened to a
8033// 128-bit vector.
8034SDValue DAGTypeLegalizer::WidenVecOp_FAKE_USE(SDNode *N) {
8035 SDValue WidenedOp = GetWidenedVector(N->getOperand(1));
8036 return DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, N->getOperand(0),
8037 WidenedOp);
8038}
8039
8040SDValue DAGTypeLegalizer::WidenVecOp_CONCAT_VECTORS(SDNode *N) {
8041 EVT VT = N->getValueType(0);
8042 EVT EltVT = VT.getVectorElementType();
8043 EVT InVT = N->getOperand(0).getValueType();
8044 SDLoc dl(N);
8045
8046 // If the widen width for this operand is the same as the width of the concat
8047 // and all but the first operand is undef, just use the widened operand.
8048 unsigned NumOperands = N->getNumOperands();
8049 if (VT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
8050 unsigned i;
8051 for (i = 1; i < NumOperands; ++i)
8052 if (!N->getOperand(i).isUndef())
8053 break;
8054
8055 if (i == NumOperands)
8056 return GetWidenedVector(N->getOperand(0));
8057 }
8058
8059 // Otherwise, fall back to a nasty build vector.
8060 unsigned NumElts = VT.getVectorNumElements();
8062
8063 unsigned NumInElts = InVT.getVectorNumElements();
8064
8065 unsigned Idx = 0;
8066 for (unsigned i=0; i < NumOperands; ++i) {
8067 SDValue InOp = N->getOperand(i);
8068 assert(getTypeAction(InOp.getValueType()) ==
8070 "Unexpected type action");
8071 InOp = GetWidenedVector(InOp);
8072 for (unsigned j = 0; j < NumInElts; ++j)
8073 Ops[Idx++] = DAG.getExtractVectorElt(dl, EltVT, InOp, j);
8074 }
8075 return DAG.getBuildVector(VT, dl, Ops);
8076}
8077
8078SDValue DAGTypeLegalizer::WidenVecOp_INSERT_SUBVECTOR(SDNode *N) {
8079 EVT VT = N->getValueType(0);
8080 SDValue SubVec = N->getOperand(1);
8081 SDValue InVec = N->getOperand(0);
8082
8083 EVT OrigVT = SubVec.getValueType();
8084 SubVec = GetWidenedVector(SubVec);
8085 EVT SubVT = SubVec.getValueType();
8086
8087 // Whether or not all the elements of the widened SubVec will be inserted into
8088 // valid indices of VT.
8089 bool IndicesValid = false;
8090 // If we statically know that VT can fit SubVT, the indices are valid.
8091 if (VT.knownBitsGE(SubVT))
8092 IndicesValid = true;
8093 else if (VT.isScalableVector() && SubVT.isFixedLengthVector()) {
8094 // Otherwise, if we're inserting a fixed vector into a scalable vector and
8095 // we know the minimum vscale we can work out if it's valid ourselves.
8096 Attribute Attr = DAG.getMachineFunction().getFunction().getFnAttribute(
8097 Attribute::VScaleRange);
8098 if (Attr.isValid()) {
8099 unsigned VScaleMin = Attr.getVScaleRangeMin();
8100 if (VT.getSizeInBits().getKnownMinValue() * VScaleMin >=
8101 SubVT.getFixedSizeInBits())
8102 IndicesValid = true;
8103 }
8104 }
8105
8106 if (!IndicesValid)
8108 "Don't know how to widen the operands for INSERT_SUBVECTOR");
8109
8110 SDLoc DL(N);
8111
8112 // We need to make sure that the indices are still valid, otherwise we might
8113 // widen what was previously well-defined to something undefined.
8114 if (InVec.isUndef() && N->getConstantOperandVal(2) == 0)
8115 return DAG.getNode(ISD::INSERT_SUBVECTOR, DL, VT, InVec, SubVec,
8116 N->getOperand(2));
8117
8118 if (OrigVT.isScalableVector()) {
8119 // When the widened types match, overwriting the start of a vector is
8120 // effectively a merge operation that can be implement as a vselect.
8121 if (SubVT == VT && N->getConstantOperandVal(2) == 0) {
8122 SDValue Mask =
8123 DAG.getMaskFromElementCount(DL, VT, OrigVT.getVectorElementCount());
8124 return DAG.getNode(ISD::VSELECT, DL, VT, Mask, SubVec, InVec);
8125 }
8126
8127 // Fallback to inserting through memory.
8128 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
8129 SDValue StackPtr = DAG.CreateStackTemporary(VT.getStoreSize(), Alignment);
8130 MachineFunction &MF = DAG.getMachineFunction();
8131 int FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
8132 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
8133
8134 MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
8137 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
8140
8141 // Write out the vector being inserting into.
8142 SDValue Ch =
8143 DAG.getStore(DAG.getEntryNode(), DL, InVec, StackPtr, StoreMMO);
8144
8145 // Build a mask to match the length of the sub-vector.
8146 SDValue Mask =
8147 DAG.getMaskFromElementCount(DL, SubVT, OrigVT.getVectorElementCount());
8148
8149 // Overwrite the sub-vector at the required offset.
8150 SDValue SubVecPtr =
8151 TLI.getVectorSubVecPointer(DAG, StackPtr, VT, OrigVT, N->getOperand(2));
8152 Ch = DAG.getMaskedStore(Ch, DL, SubVec, SubVecPtr,
8153 DAG.getPOISON(SubVecPtr.getValueType()), Mask, VT,
8154 StoreMMO, ISD::UNINDEXED, ISD::NON_EXTLOAD);
8155
8156 // Read back the result.
8157 return DAG.getLoad(VT, DL, Ch, StackPtr, LoadMMO);
8158 }
8159
8160 // If the operands can't be widened legally, just replace the INSERT_SUBVECTOR
8161 // with a series of INSERT_VECTOR_ELT
8162 unsigned Idx = N->getConstantOperandVal(2);
8163
8164 SDValue InsertElt = InVec;
8165 for (unsigned I = 0, E = OrigVT.getVectorNumElements(); I != E; ++I) {
8166 SDValue ExtractElt =
8167 DAG.getExtractVectorElt(DL, VT.getVectorElementType(), SubVec, I);
8168 InsertElt = DAG.getInsertVectorElt(DL, InsertElt, ExtractElt, I + Idx);
8169 }
8170
8171 return InsertElt;
8172}
8173
8174SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
8175 SDValue InOp = GetWidenedVector(N->getOperand(0));
8176 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SDLoc(N),
8177 N->getValueType(0), InOp, N->getOperand(1));
8178}
8179
8180SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
8181 SDValue InOp = GetWidenedVector(N->getOperand(0));
8182 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
8183 N->getValueType(0), InOp, N->getOperand(1));
8184}
8185
8186SDValue DAGTypeLegalizer::WidenVecOp_EXTEND_VECTOR_INREG(SDNode *N) {
8187 SDLoc DL(N);
8188 EVT ResVT = N->getValueType(0);
8189
8190 // Widen the input as requested by the legalizer.
8191 SDValue WideInOp = GetWidenedVector(N->getOperand(0));
8192 EVT WideInVT = WideInOp.getValueType();
8193
8194 // Simple case: if widened input is still smaller than or equal to result,
8195 // just use it directly.
8196 if (WideInVT.getSizeInBits() <= ResVT.getSizeInBits())
8197 return DAG.getNode(N->getOpcode(), DL, ResVT, WideInOp);
8198
8199 // EXTEND_VECTOR_INREG requires input bits <= result bits.
8200 // If widening makes the input larger than the original result, widen the
8201 // result to match, then extract back down.
8202 EVT ResEltVT = ResVT.getVectorElementType();
8203 unsigned EltBits = ResEltVT.getSizeInBits();
8204 assert((WideInVT.getSizeInBits() % EltBits) == 0 &&
8205 "Widened input size must be a multiple of result element size");
8206
8207 unsigned WideNumElts = WideInVT.getSizeInBits() / EltBits;
8208 EVT WideResVT = EVT::getVectorVT(*DAG.getContext(), ResEltVT, WideNumElts);
8209
8210 SDValue WideRes = DAG.getNode(N->getOpcode(), DL, WideResVT, WideInOp);
8211 return DAG.getExtractSubvector(DL, ResVT, WideRes, 0);
8212}
8213
8214SDValue DAGTypeLegalizer::WidenVecOp_STORE(SDNode *N) {
8215 // We have to widen the value, but we want only to store the original
8216 // vector type.
8217 StoreSDNode *ST = cast<StoreSDNode>(N);
8218
8219 if (!ST->getMemoryVT().getScalarType().isByteSized())
8220 return TLI.scalarizeVectorStore(ST, DAG);
8221
8222 if (ST->isTruncatingStore())
8223 return TLI.scalarizeVectorStore(ST, DAG);
8224
8225 // Generate a vector-predicated store if it is custom/legal on the target.
8226 // To avoid possible recursion, only do this if the widened mask type is
8227 // legal.
8228 // FIXME: Not all targets may support EVL in VP_STORE. These will have been
8229 // removed from the IR by the ExpandVectorPredication pass but we're
8230 // reintroducing them here.
8231 SDValue StVal = ST->getValue();
8232 EVT StVT = StVal.getValueType();
8233 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), StVT);
8234 EVT WideMaskVT = getSetCCResultType(WideVT);
8235
8236 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
8237 TLI.isTypeLegal(WideMaskVT)) {
8238 // Widen the value.
8239 SDLoc DL(N);
8240 StVal = GetWidenedVector(StVal);
8241 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
8242 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
8243 StVT.getVectorElementCount());
8244 return DAG.getStoreVP(ST->getChain(), DL, StVal, ST->getBasePtr(),
8245 ST->getOffset(), Mask, EVL, StVT, ST->getMemOperand(),
8246 ST->getAddressingMode());
8247 }
8248
8250 if (GenWidenVectorStores(StChain, ST)) {
8251 if (StChain.size() == 1)
8252 return StChain[0];
8253
8254 return DAG.getNode(ISD::TokenFactor, SDLoc(ST), MVT::Other, StChain);
8255 }
8256
8257 if (StVT.isVector()) {
8258 // If all else fails replace the store with a wide masked store.
8259 SDLoc DL(N);
8260 SDValue WideStVal = GetWidenedVector(StVal);
8261 SDValue Mask =
8262 DAG.getMaskFromElementCount(DL, WideVT, StVT.getVectorElementCount());
8263
8264 return DAG.getMaskedStore(ST->getChain(), DL, WideStVal, ST->getBasePtr(),
8265 ST->getOffset(), Mask, ST->getMemoryVT(),
8266 ST->getMemOperand(), ST->getAddressingMode(),
8267 ST->isTruncatingStore());
8268 }
8269
8270 report_fatal_error("Unable to widen vector store");
8271}
8272
8273SDValue DAGTypeLegalizer::WidenVecOp_ATOMIC_STORE(AtomicSDNode *ST) {
8274 EVT StVT = ST->getMemoryVT();
8275 SDLoc dl(ST);
8276
8277 SDValue StVal = GetWidenedVector(ST->getVal());
8278 EVT WidenVT = StVal.getValueType();
8279
8280 TypeSize StWidth = StVT.getSizeInBits();
8281 TypeSize WidenWidth = WidenVT.getSizeInBits();
8282 TypeSize WidthDiff = WidenWidth - StWidth;
8283
8284 // Find the vector type that can store the original memory width in one
8285 // atomic operation. Pass StAlign=0 (like atomic loads); a real align would
8286 // let findMemType widen the access past the value (e.g. <2 x i8> at align 4
8287 // implies a 4-byte movl, writing undef bytes past its object).
8288 std::optional<EVT> FirstVT =
8289 findMemType(DAG, TLI, StWidth.getKnownMinValue(), WidenVT, /*StAlign=*/0,
8290 WidthDiff.getKnownMinValue());
8291 if (!FirstVT)
8292 return SDValue();
8293
8294 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
8295
8296 SDValue StOp =
8297 coerceStoredValue(StVal, *FirstVT, WidenVT, FirstVTWidth, dl, DAG);
8298
8299 return DAG.getAtomic(ISD::ATOMIC_STORE, dl, *FirstVT, ST->getChain(), StOp,
8300 ST->getBasePtr(), ST->getMemOperand());
8301}
8302
8303SDValue DAGTypeLegalizer::WidenVecOp_VP_STORE(SDNode *N, unsigned OpNo) {
8304 assert((OpNo == 1 || OpNo == 3) &&
8305 "Can widen only data or mask operand of vp_store");
8306 VPStoreSDNode *ST = cast<VPStoreSDNode>(N);
8307 SDValue Mask = ST->getMask();
8308 SDValue StVal = ST->getValue();
8309 SDLoc dl(N);
8310
8311 if (OpNo == 1) {
8312 // Widen the value.
8313 StVal = GetWidenedVector(StVal);
8314
8315 // We only handle the case where the mask needs widening to an
8316 // identically-sized type as the vector inputs.
8317 assert(getTypeAction(Mask.getValueType()) ==
8319 "Unable to widen VP store");
8320 Mask = GetWidenedVector(Mask);
8321 } else {
8322 Mask = GetWidenedVector(Mask);
8323
8324 // We only handle the case where the stored value needs widening to an
8325 // identically-sized type as the mask.
8326 assert(getTypeAction(StVal.getValueType()) ==
8328 "Unable to widen VP store");
8329 StVal = GetWidenedVector(StVal);
8330 }
8331
8332 assert(Mask.getValueType().getVectorElementCount() ==
8334 "Mask and data vectors should have the same number of elements");
8335 return DAG.getStoreVP(ST->getChain(), dl, StVal, ST->getBasePtr(),
8336 ST->getOffset(), Mask, ST->getVectorLength(),
8337 ST->getMemoryVT(), ST->getMemOperand(),
8338 ST->getAddressingMode(), ST->isTruncatingStore(),
8339 ST->isCompressingStore());
8340}
8341
8342SDValue DAGTypeLegalizer::WidenVecOp_VP_STRIDED_STORE(SDNode *N,
8343 unsigned OpNo) {
8344 assert((OpNo == 1 || OpNo == 4) &&
8345 "Can widen only data or mask operand of vp_strided_store");
8346 VPStridedStoreSDNode *SST = cast<VPStridedStoreSDNode>(N);
8347 SDValue Mask = SST->getMask();
8348 SDValue StVal = SST->getValue();
8349 SDLoc DL(N);
8350
8351 if (OpNo == 1)
8352 assert(getTypeAction(Mask.getValueType()) ==
8354 "Unable to widen VP strided store");
8355 else
8356 assert(getTypeAction(StVal.getValueType()) ==
8358 "Unable to widen VP strided store");
8359
8360 StVal = GetWidenedVector(StVal);
8361 Mask = GetWidenedVector(Mask);
8362
8364 Mask.getValueType().getVectorElementCount() &&
8365 "Data and mask vectors should have the same number of elements");
8366
8367 return DAG.getStridedStoreVP(
8368 SST->getChain(), DL, StVal, SST->getBasePtr(), SST->getOffset(),
8369 SST->getStride(), Mask, SST->getVectorLength(), SST->getMemoryVT(),
8370 SST->getMemOperand(), SST->getAddressingMode(), SST->isTruncatingStore(),
8371 SST->isCompressingStore());
8372}
8373
8374SDValue DAGTypeLegalizer::WidenVecOp_MSTORE(SDNode *N, unsigned OpNo) {
8375 assert((OpNo == 1 || OpNo == 4) &&
8376 "Can widen only data or mask operand of mstore");
8377 MaskedStoreSDNode *MST = cast<MaskedStoreSDNode>(N);
8378 SDValue Mask = MST->getMask();
8379 EVT MaskVT = Mask.getValueType();
8380 SDValue StVal = MST->getValue();
8381 EVT VT = StVal.getValueType();
8382 SDLoc dl(N);
8383
8384 EVT WideVT, WideMaskVT;
8385 if (OpNo == 1) {
8386 // Widen the value.
8387 StVal = GetWidenedVector(StVal);
8388
8389 WideVT = StVal.getValueType();
8390 WideMaskVT =
8391 EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(),
8392 WideVT.getVectorElementCount());
8393 } else {
8394 WideMaskVT = TLI.getTypeToTransformTo(*DAG.getContext(), MaskVT);
8395
8396 EVT ValueVT = StVal.getValueType();
8397 WideVT = EVT::getVectorVT(*DAG.getContext(), ValueVT.getVectorElementType(),
8398 WideMaskVT.getVectorElementCount());
8399 }
8400
8401 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
8402 TLI.isTypeLegal(WideMaskVT) && !MST->isCompressingStore()) {
8403 Mask = DAG.getInsertSubvector(dl, DAG.getPOISON(WideMaskVT), Mask, 0);
8404 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8406 return DAG.getStoreVP(MST->getChain(), dl, StVal, MST->getBasePtr(),
8407 MST->getOffset(), Mask, EVL, MST->getMemoryVT(),
8408 MST->getMemOperand(), MST->getAddressingMode());
8409 }
8410
8411 if (OpNo == 1) {
8412 // The mask should be widened as well.
8413 Mask = ModifyToType(Mask, WideMaskVT, true);
8414 } else {
8415 // Widen the mask.
8416 Mask = ModifyToType(Mask, WideMaskVT, true);
8417
8418 StVal = ModifyToType(StVal, WideVT);
8419 }
8420
8421 assert(Mask.getValueType().getVectorElementCount() ==
8423 "Mask and data vectors should have the same number of elements");
8424 return DAG.getMaskedStore(MST->getChain(), dl, StVal, MST->getBasePtr(),
8425 MST->getOffset(), Mask, MST->getMemoryVT(),
8426 MST->getMemOperand(), MST->getAddressingMode(),
8427 false, MST->isCompressingStore());
8428}
8429
8430SDValue DAGTypeLegalizer::WidenVecOp_MGATHER(SDNode *N, unsigned OpNo) {
8431 assert(OpNo == 4 && "Can widen only the index of mgather");
8432 auto *MG = cast<MaskedGatherSDNode>(N);
8433 SDValue DataOp = MG->getPassThru();
8434 SDValue Mask = MG->getMask();
8435 SDValue Scale = MG->getScale();
8436
8437 // Just widen the index. It's allowed to have extra elements.
8438 SDValue Index = GetWidenedVector(MG->getIndex());
8439
8440 SDLoc dl(N);
8441 SDValue Ops[] = {MG->getChain(), DataOp, Mask, MG->getBasePtr(), Index,
8442 Scale};
8443 SDValue Res = DAG.getMaskedGather(MG->getVTList(), MG->getMemoryVT(), dl, Ops,
8444 MG->getMemOperand(), MG->getIndexType(),
8445 MG->getExtensionType());
8446 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
8447 ReplaceValueWith(SDValue(N, 0), Res.getValue(0));
8448 return SDValue();
8449}
8450
8451SDValue DAGTypeLegalizer::WidenVecOp_MSCATTER(SDNode *N, unsigned OpNo) {
8452 MaskedScatterSDNode *MSC = cast<MaskedScatterSDNode>(N);
8453 SDValue DataOp = MSC->getValue();
8454 SDValue Mask = MSC->getMask();
8455 SDValue Index = MSC->getIndex();
8456 SDValue Scale = MSC->getScale();
8457 EVT WideMemVT = MSC->getMemoryVT();
8458
8459 if (OpNo == 1) {
8460 DataOp = GetWidenedVector(DataOp);
8461 ElementCount WideEC = DataOp.getValueType().getVectorElementCount();
8462
8463 // Widen index.
8464 EVT IndexVT = Index.getValueType();
8465 EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
8466 IndexVT.getVectorElementType(), WideEC);
8467 Index = ModifyToType(Index, WideIndexVT);
8468
8469 // The mask should be widened as well.
8470 EVT MaskVT = Mask.getValueType();
8471 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
8472 MaskVT.getVectorElementType(), WideEC);
8473 Mask = ModifyToType(Mask, WideMaskVT, true);
8474
8475 // Widen the MemoryType
8476 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
8477 MSC->getMemoryVT().getScalarType(), WideEC);
8478 } else if (OpNo == 4) {
8479 // Just widen the index. It's allowed to have extra elements.
8480 Index = GetWidenedVector(Index);
8481 } else
8482 llvm_unreachable("Can't widen this operand of mscatter");
8483
8484 SDValue Ops[] = {MSC->getChain(), DataOp, Mask, MSC->getBasePtr(), Index,
8485 Scale};
8486 return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N),
8487 Ops, MSC->getMemOperand(), MSC->getIndexType(),
8488 MSC->isTruncatingStore());
8489}
8490
8491SDValue DAGTypeLegalizer::WidenVecOp_VP_SCATTER(SDNode *N, unsigned OpNo) {
8492 VPScatterSDNode *VPSC = cast<VPScatterSDNode>(N);
8493 SDValue DataOp = VPSC->getValue();
8494 SDValue Mask = VPSC->getMask();
8495 SDValue Index = VPSC->getIndex();
8496 SDValue Scale = VPSC->getScale();
8497 EVT WideMemVT = VPSC->getMemoryVT();
8498
8499 if (OpNo == 1) {
8500 DataOp = GetWidenedVector(DataOp);
8501 Index = GetWidenedVector(Index);
8502 const auto WideEC = DataOp.getValueType().getVectorElementCount();
8503 Mask = GetWidenedMask(Mask, WideEC);
8504 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
8505 VPSC->getMemoryVT().getScalarType(), WideEC);
8506 } else if (OpNo == 3) {
8507 // Just widen the index. It's allowed to have extra elements.
8508 Index = GetWidenedVector(Index);
8509 } else
8510 llvm_unreachable("Can't widen this operand of VP_SCATTER");
8511
8512 SDValue Ops[] = {
8513 VPSC->getChain(), DataOp, VPSC->getBasePtr(), Index, Scale, Mask,
8514 VPSC->getVectorLength()};
8515 return DAG.getScatterVP(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N), Ops,
8516 VPSC->getMemOperand(), VPSC->getIndexType());
8517}
8518
8519SDValue DAGTypeLegalizer::WidenVecOp_SETCC(SDNode *N) {
8520 SDValue InOp0 = GetWidenedVector(N->getOperand(0));
8521 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
8522 SDLoc dl(N);
8523 EVT VT = N->getValueType(0);
8524
8525 // WARNING: In this code we widen the compare instruction with garbage.
8526 // This garbage may contain denormal floats which may be slow. Is this a real
8527 // concern ? Should we zero the unused lanes if this is a float compare ?
8528
8529 // Get a new SETCC node to compare the newly widened operands.
8530 // Only some of the compared elements are legal.
8531 EVT SVT = getSetCCResultType(InOp0.getValueType());
8532 // The result type is legal, if its vXi1, keep vXi1 for the new SETCC.
8533 if (VT.getScalarType() == MVT::i1)
8534 SVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8535 SVT.getVectorElementCount());
8536
8537 SDValue WideSETCC = DAG.getNode(ISD::SETCC, SDLoc(N),
8538 SVT, InOp0, InOp1, N->getOperand(2));
8539
8540 // Extract the needed results from the result vector.
8541 EVT ResVT = EVT::getVectorVT(*DAG.getContext(),
8544 SDValue CC = DAG.getExtractSubvector(dl, ResVT, WideSETCC, 0);
8545
8546 EVT OpVT = N->getOperand(0).getValueType();
8547 ISD::NodeType ExtendCode =
8548 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
8549 return DAG.getNode(ExtendCode, dl, VT, CC);
8550}
8551
8552SDValue DAGTypeLegalizer::WidenVecOp_STRICT_FSETCC(SDNode *N) {
8553 SDValue Chain = N->getOperand(0);
8554 SDValue LHS = GetWidenedVector(N->getOperand(1));
8555 SDValue RHS = GetWidenedVector(N->getOperand(2));
8556 SDValue CC = N->getOperand(3);
8557 SDLoc dl(N);
8558
8559 EVT VT = N->getValueType(0);
8560 EVT EltVT = VT.getVectorElementType();
8561 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
8562 unsigned NumElts = VT.getVectorNumElements();
8563
8564 // Unroll into a build vector.
8565 SmallVector<SDValue, 8> Scalars(NumElts);
8566 SmallVector<SDValue, 8> Chains(NumElts);
8567
8568 for (unsigned i = 0; i != NumElts; ++i) {
8569 SDValue LHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, LHS, i);
8570 SDValue RHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, RHS, i);
8571
8572 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
8573 {Chain, LHSElem, RHSElem, CC});
8574 Chains[i] = Scalars[i].getValue(1);
8575 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
8576 DAG.getBoolConstant(true, dl, EltVT, VT),
8577 DAG.getBoolConstant(false, dl, EltVT, VT));
8578 }
8579
8580 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
8581 ReplaceValueWith(SDValue(N, 1), NewChain);
8582
8583 return DAG.getBuildVector(VT, dl, Scalars);
8584}
8585
8586static unsigned getExtendForIntVecReduction(unsigned Opc) {
8587 switch (Opc) {
8588 default:
8589 llvm_unreachable("Expected integer vector reduction");
8590 case ISD::VECREDUCE_ADD:
8591 case ISD::VECREDUCE_MUL:
8592 case ISD::VECREDUCE_AND:
8593 case ISD::VECREDUCE_OR:
8594 case ISD::VECREDUCE_XOR:
8595 return ISD::ANY_EXTEND;
8598 return ISD::SIGN_EXTEND;
8601 return ISD::ZERO_EXTEND;
8602 }
8603}
8604
8605SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE(SDNode *N) {
8606 SDLoc dl(N);
8607 SDValue Op = GetWidenedVector(N->getOperand(0));
8608 EVT VT = N->getValueType(0);
8609 EVT OrigVT = N->getOperand(0).getValueType();
8610 EVT WideVT = Op.getValueType();
8611 EVT ElemVT = OrigVT.getVectorElementType();
8612 SDNodeFlags Flags = N->getFlags();
8613
8614 unsigned Opc = N->getOpcode();
8615 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
8616 SDValue NeutralElem = DAG.getIdentityElement(BaseOpc, dl, ElemVT, Flags);
8617 assert(NeutralElem && "Neutral element must exist");
8618
8619 // Pad the vector with the neutral element.
8620 unsigned OrigElts = OrigVT.getVectorMinNumElements();
8621 unsigned WideElts = WideVT.getVectorMinNumElements();
8622
8623 // Generate a vp.reduce_op if it is custom/legal for the target. This avoids
8624 // needing to pad the source vector, because the inactive lanes can simply be
8625 // disabled and not contribute to the result.
8626 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opc);
8627 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WideVT)) {
8628 SDValue Start = NeutralElem;
8629 if (VT.isInteger())
8630 Start = DAG.getNode(getExtendForIntVecReduction(Opc), dl, VT, Start);
8631 assert(Start.getValueType() == VT);
8632 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8633 WideVT.getVectorElementCount());
8634 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
8635 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8636 OrigVT.getVectorElementCount());
8637 return DAG.getNode(*VPOpcode, dl, VT, {Start, Op, Mask, EVL}, Flags);
8638 }
8639
8640 if (WideVT.isScalableVector()) {
8641 unsigned GCD = std::gcd(OrigElts, WideElts);
8642 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
8644 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
8645 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
8646 Op = DAG.getInsertSubvector(dl, Op, SplatNeutral, Idx);
8647 return DAG.getNode(Opc, dl, VT, Op, Flags);
8648 }
8649
8650 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
8651 Op = DAG.getInsertVectorElt(dl, Op, NeutralElem, Idx);
8652
8653 return DAG.getNode(Opc, dl, VT, Op, Flags);
8654}
8655
8656SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE_SEQ(SDNode *N) {
8657 SDLoc dl(N);
8658 SDValue AccOp = N->getOperand(0);
8659 SDValue VecOp = N->getOperand(1);
8660 SDValue Op = GetWidenedVector(VecOp);
8661
8662 EVT VT = N->getValueType(0);
8663 EVT OrigVT = VecOp.getValueType();
8664 EVT WideVT = Op.getValueType();
8665 EVT ElemVT = OrigVT.getVectorElementType();
8666 SDNodeFlags Flags = N->getFlags();
8667
8668 unsigned Opc = N->getOpcode();
8669 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
8670 SDValue NeutralElem = DAG.getIdentityElement(BaseOpc, dl, ElemVT, Flags);
8671
8672 // Pad the vector with the neutral element.
8673 unsigned OrigElts = OrigVT.getVectorMinNumElements();
8674 unsigned WideElts = WideVT.getVectorMinNumElements();
8675
8676 // Generate a vp.reduce_op if it is custom/legal for the target. This avoids
8677 // needing to pad the source vector, because the inactive lanes can simply be
8678 // disabled and not contribute to the result.
8679 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opc);
8680 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WideVT)) {
8681 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8682 WideVT.getVectorElementCount());
8683 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
8684 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8685 OrigVT.getVectorElementCount());
8686 return DAG.getNode(*VPOpcode, dl, VT, {AccOp, Op, Mask, EVL}, Flags);
8687 }
8688
8689 if (WideVT.isScalableVector()) {
8690 unsigned GCD = std::gcd(OrigElts, WideElts);
8691 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
8693 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
8694 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
8695 Op = DAG.getInsertSubvector(dl, Op, SplatNeutral, Idx);
8696 return DAG.getNode(Opc, dl, VT, AccOp, Op, Flags);
8697 }
8698
8699 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
8700 Op = DAG.getInsertVectorElt(dl, Op, NeutralElem, Idx);
8701
8702 return DAG.getNode(Opc, dl, VT, AccOp, Op, Flags);
8703}
8704
8705SDValue DAGTypeLegalizer::WidenVecOp_VP_REDUCE(SDNode *N) {
8706 assert(N->isVPOpcode() && "Expected VP opcode");
8707
8708 SDLoc dl(N);
8709 SDValue Op = GetWidenedVector(N->getOperand(1));
8710 SDValue Mask = GetWidenedMask(N->getOperand(2),
8711 Op.getValueType().getVectorElementCount());
8712
8713 return DAG.getNode(N->getOpcode(), dl, N->getValueType(0),
8714 {N->getOperand(0), Op, Mask, N->getOperand(3)},
8715 N->getFlags());
8716}
8717
8718SDValue DAGTypeLegalizer::WidenVecOp_VSELECT(SDNode *N) {
8719 // This only gets called in the case that the left and right inputs and
8720 // result are of a legal odd vector type, and the condition is illegal i1 of
8721 // the same odd width that needs widening.
8722 EVT VT = N->getValueType(0);
8723 assert(VT.isVector() && !VT.isPow2VectorType() && isTypeLegal(VT));
8724
8725 SDValue Cond = GetWidenedVector(N->getOperand(0));
8726 SDValue LeftIn = DAG.WidenVector(N->getOperand(1), SDLoc(N));
8727 SDValue RightIn = DAG.WidenVector(N->getOperand(2), SDLoc(N));
8728 SDLoc DL(N);
8729
8730 SDValue Select = DAG.getNode(N->getOpcode(), DL, LeftIn.getValueType(), Cond,
8731 LeftIn, RightIn);
8732 return DAG.getExtractSubvector(DL, VT, Select, 0);
8733}
8734
8735SDValue DAGTypeLegalizer::WidenVecOp_CttzElements(SDNode *N) {
8736 SDLoc DL(N);
8737 SDValue Source = N->getOperand(0);
8738 EVT WideVT =
8739 TLI.getTypeToTransformTo(*DAG.getContext(), Source.getValueType());
8740
8741 SDValue WideSource;
8742 if (N->getOpcode() == ISD::CTTZ_ELTS_ZERO_POISON) {
8743 WideSource = GetWidenedVector(Source);
8744 } else {
8745 // Pad the widened portion with all-ones so the extra lanes appear as
8746 // active (non-zero) elements and do not contribute trailing zeros.
8747 SDValue AllOnes = DAG.getAllOnesConstant(DL, WideVT);
8748 WideSource = DAG.getInsertSubvector(DL, AllOnes, Source, 0);
8749 }
8750
8751 return DAG.getNode(N->getOpcode(), DL, N->getValueType(0), WideSource,
8752 N->getFlags());
8753}
8754
8755SDValue DAGTypeLegalizer::WidenVecOp_VP_CttzElements(SDNode *N) {
8756 SDLoc DL(N);
8757 SDValue Source = GetWidenedVector(N->getOperand(0));
8758 EVT SrcVT = Source.getValueType();
8759 SDValue Mask =
8760 GetWidenedMask(N->getOperand(1), SrcVT.getVectorElementCount());
8761
8762 return DAG.getNode(N->getOpcode(), DL, N->getValueType(0),
8763 {Source, Mask, N->getOperand(2)}, N->getFlags());
8764}
8765
8766SDValue DAGTypeLegalizer::WidenVecOp_VECTOR_FIND_LAST_ACTIVE(SDNode *N) {
8767 SDLoc DL(N);
8768 SDValue Mask = N->getOperand(0);
8769 EVT OrigMaskVT = Mask.getValueType();
8770 SDValue WideMask = GetWidenedVector(Mask);
8771 EVT WideMaskVT = WideMask.getValueType();
8772
8773 // Pad the mask with zeros to ensure inactive lanes don't affect the result.
8774 unsigned OrigElts = OrigMaskVT.getVectorNumElements();
8775 unsigned WideElts = WideMaskVT.getVectorNumElements();
8776 if (OrigElts != WideElts) {
8777 SDValue ZeroMask = DAG.getConstant(0, DL, WideMaskVT);
8778 WideMask = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideMaskVT, ZeroMask,
8779 Mask, DAG.getVectorIdxConstant(0, DL));
8780 }
8781
8782 return DAG.getNode(ISD::VECTOR_FIND_LAST_ACTIVE, DL, N->getValueType(0),
8783 WideMask);
8784}
8785
8786//===----------------------------------------------------------------------===//
8787// Vector Widening Utilities
8788//===----------------------------------------------------------------------===//
8789
8790// Utility function to find the type to chop up a widen vector for load/store
8791// TLI: Target lowering used to determine legal types.
8792// Width: Width left need to load/store.
8793// WidenVT: The widen vector type to load to/store from
8794// Align: If 0, don't allow use of a wider type
8795// WidenEx: If Align is not 0, the amount additional we can load/store from.
8796
8797static std::optional<EVT> findMemType(SelectionDAG &DAG,
8798 const TargetLowering &TLI, unsigned Width,
8799 EVT WidenVT, unsigned Align = 0,
8800 unsigned WidenEx = 0) {
8801 EVT WidenEltVT = WidenVT.getVectorElementType();
8802 const bool Scalable = WidenVT.isScalableVector();
8803 unsigned WidenWidth = WidenVT.getSizeInBits().getKnownMinValue();
8804 unsigned WidenEltWidth = WidenEltVT.getSizeInBits();
8805 unsigned AlignInBits = Align*8;
8806
8807 EVT RetVT = WidenEltVT;
8808 // Don't bother looking for an integer type if the vector is scalable, skip
8809 // to vector types.
8810 if (!Scalable) {
8811 // If we have one element to load/store, return it.
8812 if (Width == WidenEltWidth)
8813 return RetVT;
8814
8815 // See if there is larger legal integer than the element type to load/store.
8816 for (EVT MemVT : reverse(MVT::integer_valuetypes())) {
8817 unsigned MemVTWidth = MemVT.getSizeInBits();
8818 if (MemVT.getSizeInBits() <= WidenEltWidth)
8819 break;
8820 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
8821 if ((Action == TargetLowering::TypeLegal ||
8823 (WidenWidth % MemVTWidth) == 0 &&
8824 isPowerOf2_32(WidenWidth / MemVTWidth) &&
8825 (MemVTWidth <= Width ||
8826 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
8827 if (MemVTWidth == WidenWidth)
8828 return MemVT;
8829 RetVT = MemVT;
8830 break;
8831 }
8832 }
8833 }
8834
8835 // See if there is a larger vector type to load/store that has the same vector
8836 // element type and is evenly divisible with the WidenVT.
8837 for (EVT MemVT : reverse(MVT::vector_valuetypes())) {
8838 // Skip vector MVTs which don't match the scalable property of WidenVT.
8839 if (Scalable != MemVT.isScalableVector())
8840 continue;
8841 unsigned MemVTWidth = MemVT.getSizeInBits().getKnownMinValue();
8842 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
8843 if ((Action == TargetLowering::TypeLegal ||
8845 WidenEltVT == MemVT.getVectorElementType() &&
8846 (WidenWidth % MemVTWidth) == 0 &&
8847 isPowerOf2_32(WidenWidth / MemVTWidth) &&
8848 (MemVTWidth <= Width ||
8849 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
8850 if (RetVT.getFixedSizeInBits() < MemVTWidth || MemVT == WidenVT)
8851 return MemVT;
8852 }
8853 }
8854
8855 // Using element-wise loads and stores for widening operations is not
8856 // supported for scalable vectors
8857 if (Scalable)
8858 return std::nullopt;
8859
8860 return RetVT;
8861}
8862
8863// Builds a vector type from scalar loads
8864// VecTy: Resulting Vector type
8865// LDOps: Load operators to build a vector type
8866// [Start,End) the list of loads to use.
8869 unsigned Start, unsigned End) {
8870 SDLoc dl(LdOps[Start]);
8871 EVT LdTy = LdOps[Start].getValueType();
8872 unsigned Width = VecTy.getSizeInBits();
8873 unsigned NumElts = Width / LdTy.getSizeInBits();
8874 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), LdTy, NumElts);
8875
8876 unsigned Idx = 1;
8877 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT,LdOps[Start]);
8878
8879 for (unsigned i = Start + 1; i != End; ++i) {
8880 EVT NewLdTy = LdOps[i].getValueType();
8881 if (NewLdTy != LdTy) {
8882 NumElts = Width / NewLdTy.getSizeInBits();
8883 NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewLdTy, NumElts);
8884 VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, VecOp);
8885 // Readjust position and vector position based on new load type.
8886 Idx = Idx * LdTy.getSizeInBits() / NewLdTy.getSizeInBits();
8887 LdTy = NewLdTy;
8888 }
8889 VecOp = DAG.getInsertVectorElt(dl, VecOp, LdOps[i], Idx++);
8890 }
8891 return DAG.getNode(ISD::BITCAST, dl, VecTy, VecOp);
8892}
8893
8894SDValue DAGTypeLegalizer::GenWidenVectorLoads(SmallVectorImpl<SDValue> &LdChain,
8895 LoadSDNode *LD) {
8896 // The strategy assumes that we can efficiently load power-of-two widths.
8897 // The routine chops the vector into the largest vector loads with the same
8898 // element type or scalar loads and then recombines it to the widen vector
8899 // type.
8900 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
8901 EVT LdVT = LD->getMemoryVT();
8902 SDLoc dl(LD);
8903 assert(LdVT.isVector() && WidenVT.isVector());
8904 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
8906
8907 // Load information
8908 SDValue Chain = LD->getChain();
8909 SDValue BasePtr = LD->getBasePtr();
8910 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
8911 AAMDNodes AAInfo = LD->getAAInfo();
8912
8913 TypeSize LdWidth = LdVT.getSizeInBits();
8914 TypeSize WidenWidth = WidenVT.getSizeInBits();
8915 TypeSize WidthDiff = WidenWidth - LdWidth;
8916 // Allow wider loads if they are sufficiently aligned to avoid memory faults
8917 // and if the original load is simple.
8918 unsigned LdAlign =
8919 (!LD->isSimple() || LdVT.isScalableVector()) ? 0 : LD->getAlign().value();
8920
8921 // Find the vector type that can load from.
8922 std::optional<EVT> FirstVT =
8923 findMemType(DAG, TLI, LdWidth.getKnownMinValue(), WidenVT, LdAlign,
8924 WidthDiff.getKnownMinValue());
8925
8926 if (!FirstVT)
8927 return SDValue();
8928
8929 SmallVector<EVT, 8> MemVTs;
8930 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
8931
8932 // Unless we're able to load in one instruction we must work out how to load
8933 // the remainder.
8934 if (!TypeSize::isKnownLE(LdWidth, FirstVTWidth)) {
8935 std::optional<EVT> NewVT = FirstVT;
8936 TypeSize RemainingWidth = LdWidth;
8937 TypeSize NewVTWidth = FirstVTWidth;
8938 do {
8939 RemainingWidth -= NewVTWidth;
8940 if (TypeSize::isKnownLT(RemainingWidth, NewVTWidth)) {
8941 // The current type we are using is too large. Find a better size.
8942 NewVT = findMemType(DAG, TLI, RemainingWidth.getKnownMinValue(),
8943 WidenVT, LdAlign, WidthDiff.getKnownMinValue());
8944 if (!NewVT)
8945 return SDValue();
8946 NewVTWidth = NewVT->getSizeInBits();
8947 }
8948 MemVTs.push_back(*NewVT);
8949 } while (TypeSize::isKnownGT(RemainingWidth, NewVTWidth));
8950 }
8951
8952 SDValue LdOp = DAG.getLoad(*FirstVT, dl, Chain, BasePtr, LD->getPointerInfo(),
8953 LD->getBaseAlign(), MMOFlags, AAInfo);
8954 LdChain.push_back(LdOp.getValue(1));
8955
8956 // Check if we can load the element with one instruction.
8957 if (MemVTs.empty())
8958 return coerceLoadedValue(LdOp, *FirstVT, WidenVT, LdWidth, FirstVTWidth, dl,
8959 DAG);
8960
8961 // Load vector by using multiple loads from largest vector to scalar.
8963 LdOps.push_back(LdOp);
8964
8965 uint64_t ScaledOffset = 0;
8966 MachinePointerInfo MPI = LD->getPointerInfo();
8967
8968 // First incremement past the first load.
8969 IncrementPointer(cast<LoadSDNode>(LdOp), *FirstVT, MPI, BasePtr,
8970 &ScaledOffset);
8971
8972 for (EVT MemVT : MemVTs) {
8973 Align NewAlign = ScaledOffset == 0
8974 ? LD->getBaseAlign()
8975 : commonAlignment(LD->getAlign(), ScaledOffset);
8976 SDValue L =
8977 DAG.getLoad(MemVT, dl, Chain, BasePtr, MPI, NewAlign, MMOFlags, AAInfo);
8978
8979 LdOps.push_back(L);
8980 LdChain.push_back(L.getValue(1));
8981 IncrementPointer(cast<LoadSDNode>(L), MemVT, MPI, BasePtr, &ScaledOffset);
8982 }
8983
8984 // Build the vector from the load operations.
8985 unsigned End = LdOps.size();
8986 if (!LdOps[0].getValueType().isVector())
8987 // All the loads are scalar loads.
8988 return BuildVectorFromScalar(DAG, WidenVT, LdOps, 0, End);
8989
8990 // If the load contains vectors, build the vector using concat vector.
8991 // All of the vectors used to load are power-of-2, and the scalar loads can be
8992 // combined to make a power-of-2 vector.
8993 SmallVector<SDValue, 16> ConcatOps(End);
8994 int i = End - 1;
8995 int Idx = End;
8996 EVT LdTy = LdOps[i].getValueType();
8997 // First, combine the scalar loads to a vector.
8998 if (!LdTy.isVector()) {
8999 for (--i; i >= 0; --i) {
9000 LdTy = LdOps[i].getValueType();
9001 if (LdTy.isVector())
9002 break;
9003 }
9004 ConcatOps[--Idx] = BuildVectorFromScalar(DAG, LdTy, LdOps, i + 1, End);
9005 }
9006
9007 ConcatOps[--Idx] = LdOps[i];
9008 for (--i; i >= 0; --i) {
9009 EVT NewLdTy = LdOps[i].getValueType();
9010 if (NewLdTy != LdTy) {
9011 // Create a larger vector.
9012 TypeSize LdTySize = LdTy.getSizeInBits();
9013 TypeSize NewLdTySize = NewLdTy.getSizeInBits();
9014 assert(NewLdTySize.isScalable() == LdTySize.isScalable() &&
9015 NewLdTySize.isKnownMultipleOf(LdTySize.getKnownMinValue()));
9016 unsigned NumOps =
9017 NewLdTySize.getKnownMinValue() / LdTySize.getKnownMinValue();
9019 unsigned j = 0;
9020 for (; j != End-Idx; ++j)
9021 WidenOps[j] = ConcatOps[Idx+j];
9022 for (; j != NumOps; ++j)
9023 WidenOps[j] = DAG.getPOISON(LdTy);
9024
9025 ConcatOps[End-1] = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewLdTy,
9026 WidenOps);
9027 Idx = End - 1;
9028 LdTy = NewLdTy;
9029 }
9030 ConcatOps[--Idx] = LdOps[i];
9031 }
9032
9033 if (WidenWidth == LdTy.getSizeInBits() * (End - Idx))
9034 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
9035 ArrayRef(&ConcatOps[Idx], End - Idx));
9036
9037 // We need to fill the rest with undefs to build the vector.
9038 unsigned NumOps =
9039 WidenWidth.getKnownMinValue() / LdTy.getSizeInBits().getKnownMinValue();
9041 SDValue UndefVal = DAG.getPOISON(LdTy);
9042 {
9043 unsigned i = 0;
9044 for (; i != End-Idx; ++i)
9045 WidenOps[i] = ConcatOps[Idx+i];
9046 for (; i != NumOps; ++i)
9047 WidenOps[i] = UndefVal;
9048 }
9049 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, WidenOps);
9050}
9051
9052SDValue
9053DAGTypeLegalizer::GenWidenVectorExtLoads(SmallVectorImpl<SDValue> &LdChain,
9054 LoadSDNode *LD,
9055 ISD::LoadExtType ExtType) {
9056 // For extension loads, it may not be more efficient to chop up the vector
9057 // and then extend it. Instead, we unroll the load and build a new vector.
9058 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
9059 EVT LdVT = LD->getMemoryVT();
9060 SDLoc dl(LD);
9061 assert(LdVT.isVector() && WidenVT.isVector());
9062 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
9063
9064 // Load information
9065 SDValue Chain = LD->getChain();
9066 SDValue BasePtr = LD->getBasePtr();
9067 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
9068 AAMDNodes AAInfo = LD->getAAInfo();
9069
9070 if (LdVT.isScalableVector())
9071 return SDValue();
9072
9073 EVT EltVT = WidenVT.getVectorElementType();
9074 EVT LdEltVT = LdVT.getVectorElementType();
9075 unsigned NumElts = LdVT.getVectorNumElements();
9076
9077 // Load each element and widen.
9078 unsigned WidenNumElts = WidenVT.getVectorNumElements();
9079 SmallVector<SDValue, 16> Ops(WidenNumElts);
9080 unsigned Increment = LdEltVT.getSizeInBits() / 8;
9081 Ops[0] =
9082 DAG.getExtLoad(ExtType, dl, EltVT, Chain, BasePtr, LD->getPointerInfo(),
9083 LdEltVT, LD->getBaseAlign(), MMOFlags, AAInfo);
9084 LdChain.push_back(Ops[0].getValue(1));
9085 unsigned i = 0, Offset = Increment;
9086 for (i=1; i < NumElts; ++i, Offset += Increment) {
9087 SDValue NewBasePtr =
9088 DAG.getObjectPtrOffset(dl, BasePtr, TypeSize::getFixed(Offset));
9089 Ops[i] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, NewBasePtr,
9090 LD->getPointerInfo().getWithOffset(Offset), LdEltVT,
9091 LD->getBaseAlign(), MMOFlags, AAInfo);
9092 LdChain.push_back(Ops[i].getValue(1));
9093 }
9094
9095 // Fill the rest with undefs.
9096 SDValue UndefVal = DAG.getPOISON(EltVT);
9097 for (; i != WidenNumElts; ++i)
9098 Ops[i] = UndefVal;
9099
9100 return DAG.getBuildVector(WidenVT, dl, Ops);
9101}
9102
9103bool DAGTypeLegalizer::GenWidenVectorStores(SmallVectorImpl<SDValue> &StChain,
9104 StoreSDNode *ST) {
9105 // The strategy assumes that we can efficiently store power-of-two widths.
9106 // The routine chops the vector into the largest vector stores with the same
9107 // element type or scalar stores.
9108 SDValue Chain = ST->getChain();
9109 SDValue BasePtr = ST->getBasePtr();
9110 MachineMemOperand::Flags MMOFlags = ST->getMemOperand()->getFlags();
9111 AAMDNodes AAInfo = ST->getAAInfo();
9112 SDValue ValOp = GetWidenedVector(ST->getValue());
9113 SDLoc dl(ST);
9114
9115 EVT StVT = ST->getMemoryVT();
9116 TypeSize StWidth = StVT.getSizeInBits();
9117 EVT ValVT = ValOp.getValueType();
9118 TypeSize ValWidth = ValVT.getSizeInBits();
9119 EVT ValEltVT = ValVT.getVectorElementType();
9120 unsigned ValEltWidth = ValEltVT.getFixedSizeInBits();
9121 assert(StVT.getVectorElementType() == ValEltVT);
9122 assert(StVT.isScalableVector() == ValVT.isScalableVector() &&
9123 "Mismatch between store and value types");
9124
9125 int Idx = 0; // current index to store
9126
9127 MachinePointerInfo MPI = ST->getPointerInfo();
9128 uint64_t ScaledOffset = 0;
9129
9130 // A breakdown of how to widen this vector store. Each element of the vector
9131 // is a memory VT combined with the number of times it is to be stored to,
9132 // e,g., v5i32 -> {{v2i32,2},{i32,1}}
9134
9135 while (StWidth.isNonZero()) {
9136 // Find the largest vector type we can store with.
9137 std::optional<EVT> NewVT =
9138 findMemType(DAG, TLI, StWidth.getKnownMinValue(), ValVT);
9139 if (!NewVT)
9140 return false;
9141 MemVTs.push_back({*NewVT, 0});
9142 TypeSize NewVTWidth = NewVT->getSizeInBits();
9143
9144 do {
9145 StWidth -= NewVTWidth;
9146 MemVTs.back().second++;
9147 } while (StWidth.isNonZero() && TypeSize::isKnownGE(StWidth, NewVTWidth));
9148 }
9149
9150 for (const auto &Pair : MemVTs) {
9151 EVT NewVT = Pair.first;
9152 unsigned Count = Pair.second;
9153 TypeSize NewVTWidth = NewVT.getSizeInBits();
9154
9155 if (NewVT.isVector()) {
9156 unsigned NumVTElts = NewVT.getVectorMinNumElements();
9157 do {
9158 Align NewAlign = ScaledOffset == 0
9159 ? ST->getBaseAlign()
9160 : commonAlignment(ST->getAlign(), ScaledOffset);
9161 SDValue EOp = DAG.getExtractSubvector(dl, NewVT, ValOp, Idx);
9162 SDValue PartStore = DAG.getStore(Chain, dl, EOp, BasePtr, MPI, NewAlign,
9163 MMOFlags, AAInfo);
9164 StChain.push_back(PartStore);
9165
9166 Idx += NumVTElts;
9167 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr,
9168 &ScaledOffset);
9169 } while (--Count);
9170 } else {
9171 // Cast the vector to the scalar type we can store.
9172 unsigned NumElts = ValWidth.getFixedValue() / NewVTWidth.getFixedValue();
9173 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewVT, NumElts);
9174 SDValue VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, ValOp);
9175 // Readjust index position based on new vector type.
9176 Idx = Idx * ValEltWidth / NewVTWidth.getFixedValue();
9177 do {
9178 SDValue EOp = DAG.getExtractVectorElt(dl, NewVT, VecOp, Idx++);
9179 SDValue PartStore = DAG.getStore(Chain, dl, EOp, BasePtr, MPI,
9180 ST->getBaseAlign(), MMOFlags, AAInfo);
9181 StChain.push_back(PartStore);
9182
9183 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr);
9184 } while (--Count);
9185 // Restore index back to be relative to the original widen element type.
9186 Idx = Idx * NewVTWidth.getFixedValue() / ValEltWidth;
9187 }
9188 }
9189
9190 return true;
9191}
9192
9193/// Modifies a vector input (widen or narrows) to a vector of NVT. The
9194/// input vector must have the same element type as NVT.
9195/// FillWithZeroes specifies that the vector should be widened with zeroes.
9196SDValue DAGTypeLegalizer::ModifyToType(SDValue InOp, EVT NVT,
9197 bool FillWithZeroes) {
9198 // Note that InOp might have been widened so it might already have
9199 // the right width or it might need be narrowed.
9200 EVT InVT = InOp.getValueType();
9202 "input and widen element type must match");
9203 assert(InVT.isScalableVector() == NVT.isScalableVector() &&
9204 "cannot modify scalable vectors in this way");
9205 SDLoc dl(InOp);
9206
9207 // Check if InOp already has the right width.
9208 if (InVT == NVT)
9209 return InOp;
9210
9211 ElementCount InEC = InVT.getVectorElementCount();
9212 ElementCount WidenEC = NVT.getVectorElementCount();
9213 if (WidenEC.hasKnownScalarFactor(InEC)) {
9214 unsigned NumConcat = WidenEC.getKnownScalarFactor(InEC);
9215 SmallVector<SDValue, 16> Ops(NumConcat);
9216 SDValue FillVal =
9217 FillWithZeroes ? DAG.getConstant(0, dl, InVT) : DAG.getPOISON(InVT);
9218 Ops[0] = InOp;
9219 for (unsigned i = 1; i != NumConcat; ++i)
9220 Ops[i] = FillVal;
9221
9222 return DAG.getNode(ISD::CONCAT_VECTORS, dl, NVT, Ops);
9223 }
9224
9225 if (InEC.hasKnownScalarFactor(WidenEC))
9226 return DAG.getExtractSubvector(dl, NVT, InOp, 0);
9227
9228 assert(!InVT.isScalableVector() && !NVT.isScalableVector() &&
9229 "Scalable vectors should have been handled already.");
9230
9231 unsigned InNumElts = InEC.getFixedValue();
9232 unsigned WidenNumElts = WidenEC.getFixedValue();
9233
9234 // Fall back to extract and build (+ mask, if padding with zeros).
9235 SmallVector<SDValue, 16> Ops(WidenNumElts);
9236 EVT EltVT = NVT.getVectorElementType();
9237 unsigned MinNumElts = std::min(WidenNumElts, InNumElts);
9238 unsigned Idx;
9239 for (Idx = 0; Idx < MinNumElts; ++Idx)
9240 Ops[Idx] = DAG.getExtractVectorElt(dl, EltVT, InOp, Idx);
9241
9242 SDValue UndefVal = DAG.getPOISON(EltVT);
9243 for (; Idx < WidenNumElts; ++Idx)
9244 Ops[Idx] = UndefVal;
9245
9246 SDValue Widened = DAG.getBuildVector(NVT, dl, Ops);
9247 if (!FillWithZeroes)
9248 return Widened;
9249
9250 assert(NVT.isInteger() &&
9251 "We expect to never want to FillWithZeroes for non-integral types.");
9252
9254 MaskOps.append(MinNumElts, DAG.getAllOnesConstant(dl, EltVT));
9255 MaskOps.append(WidenNumElts - MinNumElts, DAG.getConstant(0, dl, EltVT));
9256
9257 return DAG.getNode(ISD::AND, dl, NVT, Widened,
9258 DAG.getBuildVector(NVT, dl, MaskOps));
9259}
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.