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