LLVM 19.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 switch (N->getOpcode()) {
47 default:
48#ifndef NDEBUG
49 dbgs() << "ScalarizeVectorResult #" << ResNo << ": ";
50 N->dump(&DAG);
51 dbgs() << "\n";
52#endif
53 report_fatal_error("Do not know how to scalarize the result of this "
54 "operator!\n");
55
56 case ISD::MERGE_VALUES: R = ScalarizeVecRes_MERGE_VALUES(N, ResNo);break;
57 case ISD::BITCAST: R = ScalarizeVecRes_BITCAST(N); break;
58 case ISD::BUILD_VECTOR: R = ScalarizeVecRes_BUILD_VECTOR(N); break;
59 case ISD::EXTRACT_SUBVECTOR: R = ScalarizeVecRes_EXTRACT_SUBVECTOR(N); break;
60 case ISD::FP_ROUND: R = ScalarizeVecRes_FP_ROUND(N); break;
61 case ISD::FPOWI: R = ScalarizeVecRes_ExpOp(N); break;
62 case ISD::INSERT_VECTOR_ELT: R = ScalarizeVecRes_INSERT_VECTOR_ELT(N); break;
63 case ISD::LOAD: R = ScalarizeVecRes_LOAD(cast<LoadSDNode>(N));break;
64 case ISD::SCALAR_TO_VECTOR: R = ScalarizeVecRes_SCALAR_TO_VECTOR(N); break;
65 case ISD::SIGN_EXTEND_INREG: R = ScalarizeVecRes_InregOp(N); break;
66 case ISD::VSELECT: R = ScalarizeVecRes_VSELECT(N); break;
67 case ISD::SELECT: R = ScalarizeVecRes_SELECT(N); break;
68 case ISD::SELECT_CC: R = ScalarizeVecRes_SELECT_CC(N); break;
69 case ISD::SETCC: R = ScalarizeVecRes_SETCC(N); break;
70 case ISD::UNDEF: R = ScalarizeVecRes_UNDEF(N); break;
71 case ISD::VECTOR_SHUFFLE: R = ScalarizeVecRes_VECTOR_SHUFFLE(N); break;
72 case ISD::IS_FPCLASS: R = ScalarizeVecRes_IS_FPCLASS(N); break;
76 R = ScalarizeVecRes_VecInregOp(N);
77 break;
78 case ISD::ABS:
79 case ISD::ANY_EXTEND:
80 case ISD::BITREVERSE:
81 case ISD::BSWAP:
82 case ISD::CTLZ:
84 case ISD::CTPOP:
85 case ISD::CTTZ:
87 case ISD::FABS:
88 case ISD::FACOS:
89 case ISD::FASIN:
90 case ISD::FATAN:
91 case ISD::FCEIL:
92 case ISD::FCOS:
93 case ISD::FCOSH:
94 case ISD::FEXP:
95 case ISD::FEXP2:
96 case ISD::FEXP10:
97 case ISD::FFLOOR:
98 case ISD::FLOG:
99 case ISD::FLOG10:
100 case ISD::FLOG2:
101 case ISD::FNEARBYINT:
102 case ISD::FNEG:
103 case ISD::FREEZE:
104 case ISD::ARITH_FENCE:
105 case ISD::FP_EXTEND:
106 case ISD::FP_TO_SINT:
107 case ISD::FP_TO_UINT:
108 case ISD::FRINT:
109 case ISD::LRINT:
110 case ISD::LLRINT:
111 case ISD::FROUND:
112 case ISD::FROUNDEVEN:
113 case ISD::FSIN:
114 case ISD::FSINH:
115 case ISD::FSQRT:
116 case ISD::FTAN:
117 case ISD::FTANH:
118 case ISD::FTRUNC:
119 case ISD::SIGN_EXTEND:
120 case ISD::SINT_TO_FP:
121 case ISD::TRUNCATE:
122 case ISD::UINT_TO_FP:
123 case ISD::ZERO_EXTEND:
125 R = ScalarizeVecRes_UnaryOp(N);
126 break;
128 R = ScalarizeVecRes_ADDRSPACECAST(N);
129 break;
130 case ISD::FFREXP:
131 R = ScalarizeVecRes_FFREXP(N, ResNo);
132 break;
133 case ISD::ADD:
134 case ISD::AND:
135 case ISD::AVGCEILS:
136 case ISD::AVGCEILU:
137 case ISD::AVGFLOORS:
138 case ISD::AVGFLOORU:
139 case ISD::FADD:
140 case ISD::FCOPYSIGN:
141 case ISD::FDIV:
142 case ISD::FMUL:
143 case ISD::FMINNUM:
144 case ISD::FMAXNUM:
147 case ISD::FMINIMUM:
148 case ISD::FMAXIMUM:
149 case ISD::FLDEXP:
150 case ISD::SMIN:
151 case ISD::SMAX:
152 case ISD::UMIN:
153 case ISD::UMAX:
154
155 case ISD::SADDSAT:
156 case ISD::UADDSAT:
157 case ISD::SSUBSAT:
158 case ISD::USUBSAT:
159 case ISD::SSHLSAT:
160 case ISD::USHLSAT:
161
162 case ISD::FPOW:
163 case ISD::FREM:
164 case ISD::FSUB:
165 case ISD::MUL:
166 case ISD::MULHS:
167 case ISD::MULHU:
168 case ISD::OR:
169 case ISD::SDIV:
170 case ISD::SREM:
171 case ISD::SUB:
172 case ISD::UDIV:
173 case ISD::UREM:
174 case ISD::XOR:
175 case ISD::SHL:
176 case ISD::SRA:
177 case ISD::SRL:
178 case ISD::ROTL:
179 case ISD::ROTR:
180 R = ScalarizeVecRes_BinOp(N);
181 break;
182
183 case ISD::SCMP:
184 case ISD::UCMP:
185 R = ScalarizeVecRes_CMP(N);
186 break;
187
188 case ISD::FMA:
189 case ISD::FSHL:
190 case ISD::FSHR:
191 R = ScalarizeVecRes_TernaryOp(N);
192 break;
193
194#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
195 case ISD::STRICT_##DAGN:
196#include "llvm/IR/ConstrainedOps.def"
197 R = ScalarizeVecRes_StrictFPOp(N);
198 break;
199
202 R = ScalarizeVecRes_FP_TO_XINT_SAT(N);
203 break;
204
205 case ISD::UADDO:
206 case ISD::SADDO:
207 case ISD::USUBO:
208 case ISD::SSUBO:
209 case ISD::UMULO:
210 case ISD::SMULO:
211 R = ScalarizeVecRes_OverflowOp(N, ResNo);
212 break;
213 case ISD::SMULFIX:
214 case ISD::SMULFIXSAT:
215 case ISD::UMULFIX:
216 case ISD::UMULFIXSAT:
217 case ISD::SDIVFIX:
218 case ISD::SDIVFIXSAT:
219 case ISD::UDIVFIX:
220 case ISD::UDIVFIXSAT:
221 R = ScalarizeVecRes_FIX(N);
222 break;
223 }
224
225 // If R is null, the sub-method took care of registering the result.
226 if (R.getNode())
227 SetScalarizedVector(SDValue(N, ResNo), R);
228}
229
230SDValue DAGTypeLegalizer::ScalarizeVecRes_BinOp(SDNode *N) {
231 SDValue LHS = GetScalarizedVector(N->getOperand(0));
232 SDValue RHS = GetScalarizedVector(N->getOperand(1));
233 return DAG.getNode(N->getOpcode(), SDLoc(N),
234 LHS.getValueType(), LHS, RHS, N->getFlags());
235}
236
237SDValue DAGTypeLegalizer::ScalarizeVecRes_CMP(SDNode *N) {
238 SDLoc DL(N);
239
240 SDValue LHS = N->getOperand(0);
241 SDValue RHS = N->getOperand(1);
242 if (getTypeAction(LHS.getValueType()) ==
244 LHS = GetScalarizedVector(LHS);
245 RHS = GetScalarizedVector(RHS);
246 } else {
247 EVT VT = LHS.getValueType().getVectorElementType();
248 LHS = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, LHS,
249 DAG.getVectorIdxConstant(0, DL));
250 RHS = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, RHS,
251 DAG.getVectorIdxConstant(0, DL));
252 }
253
254 return DAG.getNode(N->getOpcode(), SDLoc(N),
255 N->getValueType(0).getVectorElementType(), LHS, RHS);
256}
257
258SDValue DAGTypeLegalizer::ScalarizeVecRes_TernaryOp(SDNode *N) {
259 SDValue Op0 = GetScalarizedVector(N->getOperand(0));
260 SDValue Op1 = GetScalarizedVector(N->getOperand(1));
261 SDValue Op2 = GetScalarizedVector(N->getOperand(2));
262 return DAG.getNode(N->getOpcode(), SDLoc(N), Op0.getValueType(), Op0, Op1,
263 Op2, N->getFlags());
264}
265
266SDValue DAGTypeLegalizer::ScalarizeVecRes_FIX(SDNode *N) {
267 SDValue Op0 = GetScalarizedVector(N->getOperand(0));
268 SDValue Op1 = GetScalarizedVector(N->getOperand(1));
269 SDValue Op2 = N->getOperand(2);
270 return DAG.getNode(N->getOpcode(), SDLoc(N), Op0.getValueType(), Op0, Op1,
271 Op2, N->getFlags());
272}
273
274SDValue DAGTypeLegalizer::ScalarizeVecRes_FFREXP(SDNode *N, unsigned ResNo) {
275 assert(N->getValueType(0).getVectorNumElements() == 1 &&
276 "Unexpected vector type!");
277 SDValue Elt = GetScalarizedVector(N->getOperand(0));
278
279 EVT VT0 = N->getValueType(0);
280 EVT VT1 = N->getValueType(1);
281 SDLoc dl(N);
282
283 SDNode *ScalarNode =
284 DAG.getNode(N->getOpcode(), dl,
285 {VT0.getScalarType(), VT1.getScalarType()}, Elt)
286 .getNode();
287
288 // Replace the other vector result not being explicitly scalarized here.
289 unsigned OtherNo = 1 - ResNo;
290 EVT OtherVT = N->getValueType(OtherNo);
291 if (getTypeAction(OtherVT) == TargetLowering::TypeScalarizeVector) {
292 SetScalarizedVector(SDValue(N, OtherNo), SDValue(ScalarNode, OtherNo));
293 } else {
294 SDValue OtherVal = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, OtherVT,
295 SDValue(ScalarNode, OtherNo));
296 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
297 }
298
299 return SDValue(ScalarNode, ResNo);
300}
301
302SDValue DAGTypeLegalizer::ScalarizeVecRes_StrictFPOp(SDNode *N) {
303 EVT VT = N->getValueType(0).getVectorElementType();
304 unsigned NumOpers = N->getNumOperands();
305 SDValue Chain = N->getOperand(0);
306 EVT ValueVTs[] = {VT, MVT::Other};
307 SDLoc dl(N);
308
309 SmallVector<SDValue, 4> Opers(NumOpers);
310
311 // The Chain is the first operand.
312 Opers[0] = Chain;
313
314 // Now process the remaining operands.
315 for (unsigned i = 1; i < NumOpers; ++i) {
316 SDValue Oper = N->getOperand(i);
317 EVT OperVT = Oper.getValueType();
318
319 if (OperVT.isVector()) {
320 if (getTypeAction(OperVT) == TargetLowering::TypeScalarizeVector)
321 Oper = GetScalarizedVector(Oper);
322 else
323 Oper = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl,
324 OperVT.getVectorElementType(), Oper,
325 DAG.getVectorIdxConstant(0, dl));
326 }
327
328 Opers[i] = Oper;
329 }
330
331 SDValue Result = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(ValueVTs),
332 Opers, N->getFlags());
333
334 // Legalize the chain result - switch anything that used the old chain to
335 // use the new one.
336 ReplaceValueWith(SDValue(N, 1), Result.getValue(1));
337 return Result;
338}
339
340SDValue DAGTypeLegalizer::ScalarizeVecRes_OverflowOp(SDNode *N,
341 unsigned ResNo) {
342 SDLoc DL(N);
343 EVT ResVT = N->getValueType(0);
344 EVT OvVT = N->getValueType(1);
345
346 SDValue ScalarLHS, ScalarRHS;
347 if (getTypeAction(ResVT) == TargetLowering::TypeScalarizeVector) {
348 ScalarLHS = GetScalarizedVector(N->getOperand(0));
349 ScalarRHS = GetScalarizedVector(N->getOperand(1));
350 } else {
351 SmallVector<SDValue, 1> ElemsLHS, ElemsRHS;
352 DAG.ExtractVectorElements(N->getOperand(0), ElemsLHS);
353 DAG.ExtractVectorElements(N->getOperand(1), ElemsRHS);
354 ScalarLHS = ElemsLHS[0];
355 ScalarRHS = ElemsRHS[0];
356 }
357
358 SDVTList ScalarVTs = DAG.getVTList(
360 SDNode *ScalarNode = DAG.getNode(
361 N->getOpcode(), DL, ScalarVTs, ScalarLHS, ScalarRHS).getNode();
362 ScalarNode->setFlags(N->getFlags());
363
364 // Replace the other vector result not being explicitly scalarized here.
365 unsigned OtherNo = 1 - ResNo;
366 EVT OtherVT = N->getValueType(OtherNo);
367 if (getTypeAction(OtherVT) == TargetLowering::TypeScalarizeVector) {
368 SetScalarizedVector(SDValue(N, OtherNo), SDValue(ScalarNode, OtherNo));
369 } else {
370 SDValue OtherVal = DAG.getNode(
371 ISD::SCALAR_TO_VECTOR, DL, OtherVT, SDValue(ScalarNode, OtherNo));
372 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
373 }
374
375 return SDValue(ScalarNode, ResNo);
376}
377
378SDValue DAGTypeLegalizer::ScalarizeVecRes_MERGE_VALUES(SDNode *N,
379 unsigned ResNo) {
380 SDValue Op = DisintegrateMERGE_VALUES(N, ResNo);
381 return GetScalarizedVector(Op);
382}
383
384SDValue DAGTypeLegalizer::ScalarizeVecRes_BITCAST(SDNode *N) {
385 SDValue Op = N->getOperand(0);
386 if (Op.getValueType().isVector()
387 && Op.getValueType().getVectorNumElements() == 1
388 && !isSimpleLegalType(Op.getValueType()))
389 Op = GetScalarizedVector(Op);
390 EVT NewVT = N->getValueType(0).getVectorElementType();
391 return DAG.getNode(ISD::BITCAST, SDLoc(N),
392 NewVT, Op);
393}
394
395SDValue DAGTypeLegalizer::ScalarizeVecRes_BUILD_VECTOR(SDNode *N) {
396 EVT EltVT = N->getValueType(0).getVectorElementType();
397 SDValue InOp = N->getOperand(0);
398 // The BUILD_VECTOR operands may be of wider element types and
399 // we may need to truncate them back to the requested return type.
400 if (EltVT.isInteger())
401 return DAG.getNode(ISD::TRUNCATE, SDLoc(N), EltVT, InOp);
402 return InOp;
403}
404
405SDValue DAGTypeLegalizer::ScalarizeVecRes_EXTRACT_SUBVECTOR(SDNode *N) {
407 N->getValueType(0).getVectorElementType(),
408 N->getOperand(0), N->getOperand(1));
409}
410
411SDValue DAGTypeLegalizer::ScalarizeVecRes_FP_ROUND(SDNode *N) {
412 SDLoc DL(N);
413 SDValue Op = N->getOperand(0);
414 EVT OpVT = Op.getValueType();
415 // The result needs scalarizing, but it's not a given that the source does.
416 // See similar logic in ScalarizeVecRes_UnaryOp.
417 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
418 Op = GetScalarizedVector(Op);
419 } else {
420 EVT VT = OpVT.getVectorElementType();
422 DAG.getVectorIdxConstant(0, DL));
423 }
424 return DAG.getNode(ISD::FP_ROUND, DL,
425 N->getValueType(0).getVectorElementType(), Op,
426 N->getOperand(1));
427}
428
429SDValue DAGTypeLegalizer::ScalarizeVecRes_ExpOp(SDNode *N) {
430 SDValue Op = GetScalarizedVector(N->getOperand(0));
431 return DAG.getNode(N->getOpcode(), SDLoc(N), Op.getValueType(), Op,
432 N->getOperand(1));
433}
434
435SDValue DAGTypeLegalizer::ScalarizeVecRes_INSERT_VECTOR_ELT(SDNode *N) {
436 // The value to insert may have a wider type than the vector element type,
437 // so be sure to truncate it to the element type if necessary.
438 SDValue Op = N->getOperand(1);
439 EVT EltVT = N->getValueType(0).getVectorElementType();
440 if (Op.getValueType() != EltVT)
441 // FIXME: Can this happen for floating point types?
442 Op = DAG.getNode(ISD::TRUNCATE, SDLoc(N), EltVT, Op);
443 return Op;
444}
445
446SDValue DAGTypeLegalizer::ScalarizeVecRes_LOAD(LoadSDNode *N) {
447 assert(N->isUnindexed() && "Indexed vector load?");
448
449 SDValue Result = DAG.getLoad(
450 ISD::UNINDEXED, N->getExtensionType(),
451 N->getValueType(0).getVectorElementType(), SDLoc(N), N->getChain(),
452 N->getBasePtr(), DAG.getUNDEF(N->getBasePtr().getValueType()),
453 N->getPointerInfo(), N->getMemoryVT().getVectorElementType(),
454 N->getOriginalAlign(), N->getMemOperand()->getFlags(), N->getAAInfo());
455
456 // Legalize the chain result - switch anything that used the old chain to
457 // use the new one.
458 ReplaceValueWith(SDValue(N, 1), Result.getValue(1));
459 return Result;
460}
461
462SDValue DAGTypeLegalizer::ScalarizeVecRes_UnaryOp(SDNode *N) {
463 // Get the dest type - it doesn't always match the input type, e.g. int_to_fp.
464 EVT DestVT = N->getValueType(0).getVectorElementType();
465 SDValue Op = N->getOperand(0);
466 EVT OpVT = Op.getValueType();
467 SDLoc DL(N);
468 // The result needs scalarizing, but it's not a given that the source does.
469 // This is a workaround for targets where it's impossible to scalarize the
470 // result of a conversion, because the source type is legal.
471 // For instance, this happens on AArch64: v1i1 is illegal but v1i{8,16,32}
472 // are widened to v8i8, v4i16, and v2i32, which is legal, because v1i64 is
473 // legal and was not scalarized.
474 // See the similar logic in ScalarizeVecRes_SETCC
475 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
476 Op = GetScalarizedVector(Op);
477 } else {
478 EVT VT = OpVT.getVectorElementType();
480 DAG.getVectorIdxConstant(0, DL));
481 }
482 return DAG.getNode(N->getOpcode(), SDLoc(N), DestVT, Op, N->getFlags());
483}
484
485SDValue DAGTypeLegalizer::ScalarizeVecRes_InregOp(SDNode *N) {
486 EVT EltVT = N->getValueType(0).getVectorElementType();
487 EVT ExtVT = cast<VTSDNode>(N->getOperand(1))->getVT().getVectorElementType();
488 SDValue LHS = GetScalarizedVector(N->getOperand(0));
489 return DAG.getNode(N->getOpcode(), SDLoc(N), EltVT,
490 LHS, DAG.getValueType(ExtVT));
491}
492
493SDValue DAGTypeLegalizer::ScalarizeVecRes_VecInregOp(SDNode *N) {
494 SDLoc DL(N);
495 SDValue Op = N->getOperand(0);
496
497 EVT OpVT = Op.getValueType();
498 EVT OpEltVT = OpVT.getVectorElementType();
499 EVT EltVT = N->getValueType(0).getVectorElementType();
500
501 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
502 Op = GetScalarizedVector(Op);
503 } else {
504 Op = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, OpEltVT, Op,
505 DAG.getVectorIdxConstant(0, DL));
506 }
507
508 switch (N->getOpcode()) {
510 return DAG.getNode(ISD::ANY_EXTEND, DL, EltVT, Op);
512 return DAG.getNode(ISD::SIGN_EXTEND, DL, EltVT, Op);
514 return DAG.getNode(ISD::ZERO_EXTEND, DL, EltVT, Op);
515 }
516
517 llvm_unreachable("Illegal extend_vector_inreg opcode");
518}
519
520SDValue DAGTypeLegalizer::ScalarizeVecRes_ADDRSPACECAST(SDNode *N) {
521 EVT DestVT = N->getValueType(0).getVectorElementType();
522 SDValue Op = N->getOperand(0);
523 EVT OpVT = Op.getValueType();
524 SDLoc DL(N);
525 // The result needs scalarizing, but it's not a given that the source does.
526 // This is a workaround for targets where it's impossible to scalarize the
527 // result of a conversion, because the source type is legal.
528 // For instance, this happens on AArch64: v1i1 is illegal but v1i{8,16,32}
529 // are widened to v8i8, v4i16, and v2i32, which is legal, because v1i64 is
530 // legal and was not scalarized.
531 // See the similar logic in ScalarizeVecRes_SETCC
532 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
533 Op = GetScalarizedVector(Op);
534 } else {
535 EVT VT = OpVT.getVectorElementType();
537 DAG.getVectorIdxConstant(0, DL));
538 }
539 auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
540 unsigned SrcAS = AddrSpaceCastN->getSrcAddressSpace();
541 unsigned DestAS = AddrSpaceCastN->getDestAddressSpace();
542 return DAG.getAddrSpaceCast(DL, DestVT, Op, SrcAS, DestAS);
543}
544
545SDValue DAGTypeLegalizer::ScalarizeVecRes_SCALAR_TO_VECTOR(SDNode *N) {
546 // If the operand is wider than the vector element type then it is implicitly
547 // truncated. Make that explicit here.
548 EVT EltVT = N->getValueType(0).getVectorElementType();
549 SDValue InOp = N->getOperand(0);
550 if (InOp.getValueType() != EltVT)
551 return DAG.getNode(ISD::TRUNCATE, SDLoc(N), EltVT, InOp);
552 return InOp;
553}
554
555SDValue DAGTypeLegalizer::ScalarizeVecRes_VSELECT(SDNode *N) {
556 SDValue Cond = N->getOperand(0);
557 EVT OpVT = Cond.getValueType();
558 SDLoc DL(N);
559 // The vselect result and true/value operands needs scalarizing, but it's
560 // not a given that the Cond does. For instance, in AVX512 v1i1 is legal.
561 // See the similar logic in ScalarizeVecRes_SETCC
562 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
563 Cond = GetScalarizedVector(Cond);
564 } else {
565 EVT VT = OpVT.getVectorElementType();
567 DAG.getVectorIdxConstant(0, DL));
568 }
569
570 SDValue LHS = GetScalarizedVector(N->getOperand(1));
572 TLI.getBooleanContents(false, false);
573 TargetLowering::BooleanContent VecBool = TLI.getBooleanContents(true, false);
574
575 // If integer and float booleans have different contents then we can't
576 // reliably optimize in all cases. There is a full explanation for this in
577 // DAGCombiner::visitSELECT() where the same issue affects folding
578 // (select C, 0, 1) to (xor C, 1).
579 if (TLI.getBooleanContents(false, false) !=
580 TLI.getBooleanContents(false, true)) {
581 // At least try the common case where the boolean is generated by a
582 // comparison.
583 if (Cond->getOpcode() == ISD::SETCC) {
584 EVT OpVT = Cond->getOperand(0).getValueType();
585 ScalarBool = TLI.getBooleanContents(OpVT.getScalarType());
586 VecBool = TLI.getBooleanContents(OpVT);
587 } else
589 }
590
591 EVT CondVT = Cond.getValueType();
592 if (ScalarBool != VecBool) {
593 switch (ScalarBool) {
595 break;
599 // Vector read from all ones, scalar expects a single 1 so mask.
600 Cond = DAG.getNode(ISD::AND, SDLoc(N), CondVT,
601 Cond, DAG.getConstant(1, SDLoc(N), CondVT));
602 break;
606 // Vector reads from a one, scalar from all ones so sign extend.
607 Cond = DAG.getNode(ISD::SIGN_EXTEND_INREG, SDLoc(N), CondVT,
608 Cond, DAG.getValueType(MVT::i1));
609 break;
610 }
611 }
612
613 // Truncate the condition if needed
614 auto BoolVT = getSetCCResultType(CondVT);
615 if (BoolVT.bitsLT(CondVT))
616 Cond = DAG.getNode(ISD::TRUNCATE, SDLoc(N), BoolVT, Cond);
617
618 return DAG.getSelect(SDLoc(N),
619 LHS.getValueType(), Cond, LHS,
620 GetScalarizedVector(N->getOperand(2)));
621}
622
623SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT(SDNode *N) {
624 SDValue LHS = GetScalarizedVector(N->getOperand(1));
625 return DAG.getSelect(SDLoc(N),
626 LHS.getValueType(), N->getOperand(0), LHS,
627 GetScalarizedVector(N->getOperand(2)));
628}
629
630SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT_CC(SDNode *N) {
631 SDValue LHS = GetScalarizedVector(N->getOperand(2));
632 return DAG.getNode(ISD::SELECT_CC, SDLoc(N), LHS.getValueType(),
633 N->getOperand(0), N->getOperand(1),
634 LHS, GetScalarizedVector(N->getOperand(3)),
635 N->getOperand(4));
636}
637
638SDValue DAGTypeLegalizer::ScalarizeVecRes_UNDEF(SDNode *N) {
639 return DAG.getUNDEF(N->getValueType(0).getVectorElementType());
640}
641
642SDValue DAGTypeLegalizer::ScalarizeVecRes_VECTOR_SHUFFLE(SDNode *N) {
643 // Figure out if the scalar is the LHS or RHS and return it.
644 SDValue Arg = N->getOperand(2).getOperand(0);
645 if (Arg.isUndef())
646 return DAG.getUNDEF(N->getValueType(0).getVectorElementType());
647 unsigned Op = !cast<ConstantSDNode>(Arg)->isZero();
648 return GetScalarizedVector(N->getOperand(Op));
649}
650
651SDValue DAGTypeLegalizer::ScalarizeVecRes_FP_TO_XINT_SAT(SDNode *N) {
652 SDValue Src = N->getOperand(0);
653 EVT SrcVT = Src.getValueType();
654 SDLoc dl(N);
655
656 // Handle case where result is scalarized but operand is not
657 if (getTypeAction(SrcVT) == TargetLowering::TypeScalarizeVector)
658 Src = GetScalarizedVector(Src);
659 else
660 Src = DAG.getNode(
662 DAG.getConstant(0, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
663
664 EVT DstVT = N->getValueType(0).getVectorElementType();
665 return DAG.getNode(N->getOpcode(), dl, DstVT, Src, N->getOperand(1));
666}
667
668SDValue DAGTypeLegalizer::ScalarizeVecRes_SETCC(SDNode *N) {
669 assert(N->getValueType(0).isVector() &&
670 N->getOperand(0).getValueType().isVector() &&
671 "Operand types must be vectors");
672 SDValue LHS = N->getOperand(0);
673 SDValue RHS = N->getOperand(1);
674 EVT OpVT = LHS.getValueType();
675 EVT NVT = N->getValueType(0).getVectorElementType();
676 SDLoc DL(N);
677
678 // The result needs scalarizing, but it's not a given that the source does.
679 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
680 LHS = GetScalarizedVector(LHS);
681 RHS = GetScalarizedVector(RHS);
682 } else {
683 EVT VT = OpVT.getVectorElementType();
684 LHS = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, LHS,
685 DAG.getVectorIdxConstant(0, DL));
686 RHS = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, RHS,
687 DAG.getVectorIdxConstant(0, DL));
688 }
689
690 // Turn it into a scalar SETCC.
691 SDValue Res = DAG.getNode(ISD::SETCC, DL, MVT::i1, LHS, RHS,
692 N->getOperand(2));
693 // Vectors may have a different boolean contents to scalars. Promote the
694 // value appropriately.
695 ISD::NodeType ExtendCode =
697 return DAG.getNode(ExtendCode, DL, NVT, Res);
698}
699
700SDValue DAGTypeLegalizer::ScalarizeVecRes_IS_FPCLASS(SDNode *N) {
701 SDLoc DL(N);
702 SDValue Arg = N->getOperand(0);
703 SDValue Test = N->getOperand(1);
704 EVT ArgVT = Arg.getValueType();
705 EVT ResultVT = N->getValueType(0).getVectorElementType();
706
707 if (getTypeAction(ArgVT) == TargetLowering::TypeScalarizeVector) {
708 Arg = GetScalarizedVector(Arg);
709 } else {
710 EVT VT = ArgVT.getVectorElementType();
711 Arg = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, Arg,
712 DAG.getVectorIdxConstant(0, DL));
713 }
714
715 SDValue Res =
716 DAG.getNode(ISD::IS_FPCLASS, DL, MVT::i1, {Arg, Test}, N->getFlags());
717 // Vectors may have a different boolean contents to scalars. Promote the
718 // value appropriately.
719 ISD::NodeType ExtendCode =
721 return DAG.getNode(ExtendCode, DL, ResultVT, Res);
722}
723
724//===----------------------------------------------------------------------===//
725// Operand Vector Scalarization <1 x ty> -> ty.
726//===----------------------------------------------------------------------===//
727
728bool DAGTypeLegalizer::ScalarizeVectorOperand(SDNode *N, unsigned OpNo) {
729 LLVM_DEBUG(dbgs() << "Scalarize node operand " << OpNo << ": ";
730 N->dump(&DAG));
731 SDValue Res = SDValue();
732
733 switch (N->getOpcode()) {
734 default:
735#ifndef NDEBUG
736 dbgs() << "ScalarizeVectorOperand Op #" << OpNo << ": ";
737 N->dump(&DAG);
738 dbgs() << "\n";
739#endif
740 report_fatal_error("Do not know how to scalarize this operator's "
741 "operand!\n");
742 case ISD::BITCAST:
743 Res = ScalarizeVecOp_BITCAST(N);
744 break;
745 case ISD::ANY_EXTEND:
746 case ISD::ZERO_EXTEND:
747 case ISD::SIGN_EXTEND:
748 case ISD::TRUNCATE:
749 case ISD::FP_TO_SINT:
750 case ISD::FP_TO_UINT:
751 case ISD::SINT_TO_FP:
752 case ISD::UINT_TO_FP:
753 case ISD::LRINT:
754 case ISD::LLRINT:
755 Res = ScalarizeVecOp_UnaryOp(N);
756 break;
761 Res = ScalarizeVecOp_UnaryOp_StrictFP(N);
762 break;
764 Res = ScalarizeVecOp_CONCAT_VECTORS(N);
765 break;
767 Res = ScalarizeVecOp_EXTRACT_VECTOR_ELT(N);
768 break;
769 case ISD::VSELECT:
770 Res = ScalarizeVecOp_VSELECT(N);
771 break;
772 case ISD::SETCC:
773 Res = ScalarizeVecOp_VSETCC(N);
774 break;
775 case ISD::STORE:
776 Res = ScalarizeVecOp_STORE(cast<StoreSDNode>(N), OpNo);
777 break;
779 Res = ScalarizeVecOp_STRICT_FP_ROUND(N, OpNo);
780 break;
781 case ISD::FP_ROUND:
782 Res = ScalarizeVecOp_FP_ROUND(N, OpNo);
783 break;
785 Res = ScalarizeVecOp_STRICT_FP_EXTEND(N);
786 break;
787 case ISD::FP_EXTEND:
788 Res = ScalarizeVecOp_FP_EXTEND(N);
789 break;
805 Res = ScalarizeVecOp_VECREDUCE(N);
806 break;
809 Res = ScalarizeVecOp_VECREDUCE_SEQ(N);
810 break;
811 case ISD::SCMP:
812 case ISD::UCMP:
813 Res = ScalarizeVecOp_CMP(N);
814 break;
815 }
816
817 // If the result is null, the sub-method took care of registering results etc.
818 if (!Res.getNode()) return false;
819
820 // If the result is N, the sub-method updated N in place. Tell the legalizer
821 // core about this.
822 if (Res.getNode() == N)
823 return true;
824
825 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
826 "Invalid operand expansion");
827
828 ReplaceValueWith(SDValue(N, 0), Res);
829 return false;
830}
831
832/// If the value to convert is a vector that needs to be scalarized, it must be
833/// <1 x ty>. Convert the element instead.
834SDValue DAGTypeLegalizer::ScalarizeVecOp_BITCAST(SDNode *N) {
835 SDValue Elt = GetScalarizedVector(N->getOperand(0));
836 return DAG.getNode(ISD::BITCAST, SDLoc(N),
837 N->getValueType(0), Elt);
838}
839
840/// If the input is a vector that needs to be scalarized, it must be <1 x ty>.
841/// Do the operation on the element instead.
842SDValue DAGTypeLegalizer::ScalarizeVecOp_UnaryOp(SDNode *N) {
843 assert(N->getValueType(0).getVectorNumElements() == 1 &&
844 "Unexpected vector type!");
845 SDValue Elt = GetScalarizedVector(N->getOperand(0));
846 SDValue Op = DAG.getNode(N->getOpcode(), SDLoc(N),
847 N->getValueType(0).getScalarType(), Elt);
848 // Revectorize the result so the types line up with what the uses of this
849 // expression expect.
850 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Op);
851}
852
853/// If the input is a vector that needs to be scalarized, it must be <1 x ty>.
854/// Do the strict FP operation on the element instead.
855SDValue DAGTypeLegalizer::ScalarizeVecOp_UnaryOp_StrictFP(SDNode *N) {
856 assert(N->getValueType(0).getVectorNumElements() == 1 &&
857 "Unexpected vector type!");
858 SDValue Elt = GetScalarizedVector(N->getOperand(1));
859 SDValue Res = DAG.getNode(N->getOpcode(), SDLoc(N),
860 { N->getValueType(0).getScalarType(), MVT::Other },
861 { N->getOperand(0), Elt });
862 // Legalize the chain result - switch anything that used the old chain to
863 // use the new one.
864 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
865 // Revectorize the result so the types line up with what the uses of this
866 // expression expect.
867 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
868
869 // Do our own replacement and return SDValue() to tell the caller that we
870 // handled all replacements since caller can only handle a single result.
871 ReplaceValueWith(SDValue(N, 0), Res);
872 return SDValue();
873}
874
875/// The vectors to concatenate have length one - use a BUILD_VECTOR instead.
876SDValue DAGTypeLegalizer::ScalarizeVecOp_CONCAT_VECTORS(SDNode *N) {
877 SmallVector<SDValue, 8> Ops(N->getNumOperands());
878 for (unsigned i = 0, e = N->getNumOperands(); i < e; ++i)
879 Ops[i] = GetScalarizedVector(N->getOperand(i));
880 return DAG.getBuildVector(N->getValueType(0), SDLoc(N), Ops);
881}
882
883/// If the input is a vector that needs to be scalarized, it must be <1 x ty>,
884/// so just return the element, ignoring the index.
885SDValue DAGTypeLegalizer::ScalarizeVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
886 EVT VT = N->getValueType(0);
887 SDValue Res = GetScalarizedVector(N->getOperand(0));
888 if (Res.getValueType() != VT)
889 Res = VT.isFloatingPoint()
890 ? DAG.getNode(ISD::FP_EXTEND, SDLoc(N), VT, Res)
891 : DAG.getNode(ISD::ANY_EXTEND, SDLoc(N), VT, Res);
892 return Res;
893}
894
895/// If the input condition is a vector that needs to be scalarized, it must be
896/// <1 x i1>, so just convert to a normal ISD::SELECT
897/// (still with vector output type since that was acceptable if we got here).
898SDValue DAGTypeLegalizer::ScalarizeVecOp_VSELECT(SDNode *N) {
899 SDValue ScalarCond = GetScalarizedVector(N->getOperand(0));
900 EVT VT = N->getValueType(0);
901
902 return DAG.getNode(ISD::SELECT, SDLoc(N), VT, ScalarCond, N->getOperand(1),
903 N->getOperand(2));
904}
905
906/// If the operand is a vector that needs to be scalarized then the
907/// result must be v1i1, so just convert to a scalar SETCC and wrap
908/// with a scalar_to_vector since the res type is legal if we got here
909SDValue DAGTypeLegalizer::ScalarizeVecOp_VSETCC(SDNode *N) {
910 assert(N->getValueType(0).isVector() &&
911 N->getOperand(0).getValueType().isVector() &&
912 "Operand types must be vectors");
913 assert(N->getValueType(0) == MVT::v1i1 && "Expected v1i1 type");
914
915 EVT VT = N->getValueType(0);
916 SDValue LHS = GetScalarizedVector(N->getOperand(0));
917 SDValue RHS = GetScalarizedVector(N->getOperand(1));
918
919 EVT OpVT = N->getOperand(0).getValueType();
920 EVT NVT = VT.getVectorElementType();
921 SDLoc DL(N);
922 // Turn it into a scalar SETCC.
923 SDValue Res = DAG.getNode(ISD::SETCC, DL, MVT::i1, LHS, RHS,
924 N->getOperand(2));
925
926 // Vectors may have a different boolean contents to scalars. Promote the
927 // value appropriately.
928 ISD::NodeType ExtendCode =
930
931 Res = DAG.getNode(ExtendCode, DL, NVT, Res);
932
933 return DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, VT, Res);
934}
935
936/// If the value to store is a vector that needs to be scalarized, it must be
937/// <1 x ty>. Just store the element.
938SDValue DAGTypeLegalizer::ScalarizeVecOp_STORE(StoreSDNode *N, unsigned OpNo){
939 assert(N->isUnindexed() && "Indexed store of one-element vector?");
940 assert(OpNo == 1 && "Do not know how to scalarize this operand!");
941 SDLoc dl(N);
942
943 if (N->isTruncatingStore())
944 return DAG.getTruncStore(
945 N->getChain(), dl, GetScalarizedVector(N->getOperand(1)),
946 N->getBasePtr(), N->getPointerInfo(),
947 N->getMemoryVT().getVectorElementType(), N->getOriginalAlign(),
948 N->getMemOperand()->getFlags(), N->getAAInfo());
949
950 return DAG.getStore(N->getChain(), dl, GetScalarizedVector(N->getOperand(1)),
951 N->getBasePtr(), N->getPointerInfo(),
952 N->getOriginalAlign(), N->getMemOperand()->getFlags(),
953 N->getAAInfo());
954}
955
956/// If the value to round is a vector that needs to be scalarized, it must be
957/// <1 x ty>. Convert the element instead.
958SDValue DAGTypeLegalizer::ScalarizeVecOp_FP_ROUND(SDNode *N, unsigned OpNo) {
959 assert(OpNo == 0 && "Wrong operand for scalarization!");
960 SDValue Elt = GetScalarizedVector(N->getOperand(0));
961 SDValue Res = DAG.getNode(ISD::FP_ROUND, SDLoc(N),
962 N->getValueType(0).getVectorElementType(), Elt,
963 N->getOperand(1));
964 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
965}
966
967SDValue DAGTypeLegalizer::ScalarizeVecOp_STRICT_FP_ROUND(SDNode *N,
968 unsigned OpNo) {
969 assert(OpNo == 1 && "Wrong operand for scalarization!");
970 SDValue Elt = GetScalarizedVector(N->getOperand(1));
972 { N->getValueType(0).getVectorElementType(),
973 MVT::Other },
974 { N->getOperand(0), Elt, N->getOperand(2) });
975 // Legalize the chain result - switch anything that used the old chain to
976 // use the new one.
977 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
978
979 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
980
981 // Do our own replacement and return SDValue() to tell the caller that we
982 // handled all replacements since caller can only handle a single result.
983 ReplaceValueWith(SDValue(N, 0), Res);
984 return SDValue();
985}
986
987/// If the value to extend is a vector that needs to be scalarized, it must be
988/// <1 x ty>. Convert the element instead.
989SDValue DAGTypeLegalizer::ScalarizeVecOp_FP_EXTEND(SDNode *N) {
990 SDValue Elt = GetScalarizedVector(N->getOperand(0));
992 N->getValueType(0).getVectorElementType(), Elt);
993 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
994}
995
996/// If the value to extend is a vector that needs to be scalarized, it must be
997/// <1 x ty>. Convert the element instead.
998SDValue DAGTypeLegalizer::ScalarizeVecOp_STRICT_FP_EXTEND(SDNode *N) {
999 SDValue Elt = GetScalarizedVector(N->getOperand(1));
1000 SDValue Res =
1002 {N->getValueType(0).getVectorElementType(), MVT::Other},
1003 {N->getOperand(0), Elt});
1004 // Legalize the chain result - switch anything that used the old chain to
1005 // use the new one.
1006 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
1007
1008 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
1009
1010 // Do our own replacement and return SDValue() to tell the caller that we
1011 // handled all replacements since caller can only handle a single result.
1012 ReplaceValueWith(SDValue(N, 0), Res);
1013 return SDValue();
1014}
1015
1016SDValue DAGTypeLegalizer::ScalarizeVecOp_VECREDUCE(SDNode *N) {
1017 SDValue Res = GetScalarizedVector(N->getOperand(0));
1018 // Result type may be wider than element type.
1019 if (Res.getValueType() != N->getValueType(0))
1020 Res = DAG.getNode(ISD::ANY_EXTEND, SDLoc(N), N->getValueType(0), Res);
1021 return Res;
1022}
1023
1024SDValue DAGTypeLegalizer::ScalarizeVecOp_VECREDUCE_SEQ(SDNode *N) {
1025 SDValue AccOp = N->getOperand(0);
1026 SDValue VecOp = N->getOperand(1);
1027
1028 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(N->getOpcode());
1029
1030 SDValue Op = GetScalarizedVector(VecOp);
1031 return DAG.getNode(BaseOpc, SDLoc(N), N->getValueType(0),
1032 AccOp, Op, N->getFlags());
1033}
1034
1035SDValue DAGTypeLegalizer::ScalarizeVecOp_CMP(SDNode *N) {
1036 SDValue LHS = GetScalarizedVector(N->getOperand(0));
1037 SDValue RHS = GetScalarizedVector(N->getOperand(1));
1038
1039 EVT ResVT = N->getValueType(0).getVectorElementType();
1040 SDValue Cmp = DAG.getNode(N->getOpcode(), SDLoc(N), ResVT, LHS, RHS);
1041 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Cmp);
1042}
1043
1044//===----------------------------------------------------------------------===//
1045// Result Vector Splitting
1046//===----------------------------------------------------------------------===//
1047
1048/// This method is called when the specified result of the specified node is
1049/// found to need vector splitting. At this point, the node may also have
1050/// invalid operands or may have other results that need legalization, we just
1051/// know that (at least) one result needs vector splitting.
1052void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
1053 LLVM_DEBUG(dbgs() << "Split node result: "; N->dump(&DAG));
1054 SDValue Lo, Hi;
1055
1056 // See if the target wants to custom expand this node.
1057 if (CustomLowerNode(N, N->getValueType(ResNo), true))
1058 return;
1059
1060 switch (N->getOpcode()) {
1061 default:
1062#ifndef NDEBUG
1063 dbgs() << "SplitVectorResult #" << ResNo << ": ";
1064 N->dump(&DAG);
1065 dbgs() << "\n";
1066#endif
1067 report_fatal_error("Do not know how to split the result of this "
1068 "operator!\n");
1069
1070 case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, ResNo, Lo, Hi); break;
1071 case ISD::AssertZext: SplitVecRes_AssertZext(N, Lo, Hi); break;
1072 case ISD::VSELECT:
1073 case ISD::SELECT:
1074 case ISD::VP_MERGE:
1075 case ISD::VP_SELECT: SplitRes_Select(N, Lo, Hi); break;
1076 case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break;
1077 case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break;
1078 case ISD::BITCAST: SplitVecRes_BITCAST(N, Lo, Hi); break;
1079 case ISD::BUILD_VECTOR: SplitVecRes_BUILD_VECTOR(N, Lo, Hi); break;
1080 case ISD::CONCAT_VECTORS: SplitVecRes_CONCAT_VECTORS(N, Lo, Hi); break;
1081 case ISD::EXTRACT_SUBVECTOR: SplitVecRes_EXTRACT_SUBVECTOR(N, Lo, Hi); break;
1082 case ISD::INSERT_SUBVECTOR: SplitVecRes_INSERT_SUBVECTOR(N, Lo, Hi); break;
1083 case ISD::FPOWI:
1084 case ISD::FLDEXP:
1085 case ISD::FCOPYSIGN: SplitVecRes_FPOp_MultiType(N, Lo, Hi); break;
1086 case ISD::IS_FPCLASS: SplitVecRes_IS_FPCLASS(N, Lo, Hi); break;
1087 case ISD::INSERT_VECTOR_ELT: SplitVecRes_INSERT_VECTOR_ELT(N, Lo, Hi); break;
1088 case ISD::SPLAT_VECTOR:
1090 SplitVecRes_ScalarOp(N, Lo, Hi);
1091 break;
1092 case ISD::STEP_VECTOR:
1093 SplitVecRes_STEP_VECTOR(N, Lo, Hi);
1094 break;
1095 case ISD::SIGN_EXTEND_INREG: SplitVecRes_InregOp(N, Lo, Hi); break;
1096 case ISD::LOAD:
1097 SplitVecRes_LOAD(cast<LoadSDNode>(N), Lo, Hi);
1098 break;
1099 case ISD::VP_LOAD:
1100 SplitVecRes_VP_LOAD(cast<VPLoadSDNode>(N), Lo, Hi);
1101 break;
1102 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
1103 SplitVecRes_VP_STRIDED_LOAD(cast<VPStridedLoadSDNode>(N), Lo, Hi);
1104 break;
1105 case ISD::MLOAD:
1106 SplitVecRes_MLOAD(cast<MaskedLoadSDNode>(N), Lo, Hi);
1107 break;
1108 case ISD::MGATHER:
1109 case ISD::VP_GATHER:
1110 SplitVecRes_Gather(cast<MemSDNode>(N), Lo, Hi, /*SplitSETCC*/ true);
1111 break;
1112 case ISD::SETCC:
1113 case ISD::VP_SETCC:
1114 SplitVecRes_SETCC(N, Lo, Hi);
1115 break;
1117 SplitVecRes_VECTOR_REVERSE(N, Lo, Hi);
1118 break;
1120 SplitVecRes_VECTOR_SHUFFLE(cast<ShuffleVectorSDNode>(N), Lo, Hi);
1121 break;
1122 case ISD::VECTOR_SPLICE:
1123 SplitVecRes_VECTOR_SPLICE(N, Lo, Hi);
1124 break;
1126 SplitVecRes_VECTOR_DEINTERLEAVE(N);
1127 return;
1129 SplitVecRes_VECTOR_INTERLEAVE(N);
1130 return;
1131 case ISD::VAARG:
1132 SplitVecRes_VAARG(N, Lo, Hi);
1133 break;
1134
1138 SplitVecRes_ExtVecInRegOp(N, Lo, Hi);
1139 break;
1140
1141 case ISD::ABS:
1142 case ISD::VP_ABS:
1143 case ISD::BITREVERSE:
1144 case ISD::VP_BITREVERSE:
1145 case ISD::BSWAP:
1146 case ISD::VP_BSWAP:
1147 case ISD::CTLZ:
1148 case ISD::VP_CTLZ:
1149 case ISD::CTTZ:
1150 case ISD::VP_CTTZ:
1152 case ISD::VP_CTLZ_ZERO_UNDEF:
1154 case ISD::VP_CTTZ_ZERO_UNDEF:
1155 case ISD::CTPOP:
1156 case ISD::VP_CTPOP:
1157 case ISD::FABS: case ISD::VP_FABS:
1158 case ISD::FACOS:
1159 case ISD::FASIN:
1160 case ISD::FATAN:
1161 case ISD::FCEIL:
1162 case ISD::VP_FCEIL:
1163 case ISD::FCOS:
1164 case ISD::FCOSH:
1165 case ISD::FEXP:
1166 case ISD::FEXP2:
1167 case ISD::FEXP10:
1168 case ISD::FFLOOR:
1169 case ISD::VP_FFLOOR:
1170 case ISD::FLOG:
1171 case ISD::FLOG10:
1172 case ISD::FLOG2:
1173 case ISD::FNEARBYINT:
1174 case ISD::VP_FNEARBYINT:
1175 case ISD::FNEG: case ISD::VP_FNEG:
1176 case ISD::FREEZE:
1177 case ISD::ARITH_FENCE:
1178 case ISD::FP_EXTEND:
1179 case ISD::VP_FP_EXTEND:
1180 case ISD::FP_ROUND:
1181 case ISD::VP_FP_ROUND:
1182 case ISD::FP_TO_SINT:
1183 case ISD::VP_FP_TO_SINT:
1184 case ISD::FP_TO_UINT:
1185 case ISD::VP_FP_TO_UINT:
1186 case ISD::FRINT:
1187 case ISD::VP_FRINT:
1188 case ISD::LRINT:
1189 case ISD::VP_LRINT:
1190 case ISD::LLRINT:
1191 case ISD::VP_LLRINT:
1192 case ISD::FROUND:
1193 case ISD::VP_FROUND:
1194 case ISD::FROUNDEVEN:
1195 case ISD::VP_FROUNDEVEN:
1196 case ISD::FSIN:
1197 case ISD::FSINH:
1198 case ISD::FSQRT: case ISD::VP_SQRT:
1199 case ISD::FTAN:
1200 case ISD::FTANH:
1201 case ISD::FTRUNC:
1202 case ISD::VP_FROUNDTOZERO:
1203 case ISD::SINT_TO_FP:
1204 case ISD::VP_SINT_TO_FP:
1205 case ISD::TRUNCATE:
1206 case ISD::VP_TRUNCATE:
1207 case ISD::UINT_TO_FP:
1208 case ISD::VP_UINT_TO_FP:
1209 case ISD::FCANONICALIZE:
1210 SplitVecRes_UnaryOp(N, Lo, Hi);
1211 break;
1212 case ISD::ADDRSPACECAST:
1213 SplitVecRes_ADDRSPACECAST(N, Lo, Hi);
1214 break;
1215 case ISD::FFREXP:
1216 SplitVecRes_FFREXP(N, ResNo, Lo, Hi);
1217 break;
1218
1219 case ISD::ANY_EXTEND:
1220 case ISD::SIGN_EXTEND:
1221 case ISD::ZERO_EXTEND:
1222 case ISD::VP_SIGN_EXTEND:
1223 case ISD::VP_ZERO_EXTEND:
1224 SplitVecRes_ExtendOp(N, Lo, Hi);
1225 break;
1226
1227 case ISD::ADD: case ISD::VP_ADD:
1228 case ISD::SUB: case ISD::VP_SUB:
1229 case ISD::MUL: case ISD::VP_MUL:
1230 case ISD::MULHS:
1231 case ISD::MULHU:
1232 case ISD::AVGCEILS:
1233 case ISD::AVGCEILU:
1234 case ISD::AVGFLOORS:
1235 case ISD::AVGFLOORU:
1236 case ISD::FADD: case ISD::VP_FADD:
1237 case ISD::FSUB: case ISD::VP_FSUB:
1238 case ISD::FMUL: case ISD::VP_FMUL:
1239 case ISD::FMINNUM:
1240 case ISD::FMINNUM_IEEE:
1241 case ISD::VP_FMINNUM:
1242 case ISD::FMAXNUM:
1243 case ISD::FMAXNUM_IEEE:
1244 case ISD::VP_FMAXNUM:
1245 case ISD::FMINIMUM:
1246 case ISD::VP_FMINIMUM:
1247 case ISD::FMAXIMUM:
1248 case ISD::VP_FMAXIMUM:
1249 case ISD::SDIV: case ISD::VP_SDIV:
1250 case ISD::UDIV: case ISD::VP_UDIV:
1251 case ISD::FDIV: case ISD::VP_FDIV:
1252 case ISD::FPOW:
1253 case ISD::AND: case ISD::VP_AND:
1254 case ISD::OR: case ISD::VP_OR:
1255 case ISD::XOR: case ISD::VP_XOR:
1256 case ISD::SHL: case ISD::VP_SHL:
1257 case ISD::SRA: case ISD::VP_SRA:
1258 case ISD::SRL: case ISD::VP_SRL:
1259 case ISD::UREM: case ISD::VP_UREM:
1260 case ISD::SREM: case ISD::VP_SREM:
1261 case ISD::FREM: case ISD::VP_FREM:
1262 case ISD::SMIN: case ISD::VP_SMIN:
1263 case ISD::SMAX: case ISD::VP_SMAX:
1264 case ISD::UMIN: case ISD::VP_UMIN:
1265 case ISD::UMAX: case ISD::VP_UMAX:
1266 case ISD::SADDSAT: case ISD::VP_SADDSAT:
1267 case ISD::UADDSAT: case ISD::VP_UADDSAT:
1268 case ISD::SSUBSAT: case ISD::VP_SSUBSAT:
1269 case ISD::USUBSAT: case ISD::VP_USUBSAT:
1270 case ISD::SSHLSAT:
1271 case ISD::USHLSAT:
1272 case ISD::ROTL:
1273 case ISD::ROTR:
1274 case ISD::VP_FCOPYSIGN:
1275 SplitVecRes_BinOp(N, Lo, Hi);
1276 break;
1277 case ISD::FMA: case ISD::VP_FMA:
1278 case ISD::FSHL:
1279 case ISD::VP_FSHL:
1280 case ISD::FSHR:
1281 case ISD::VP_FSHR:
1282 SplitVecRes_TernaryOp(N, Lo, Hi);
1283 break;
1284
1285 case ISD::SCMP: case ISD::UCMP:
1286 SplitVecRes_CMP(N, Lo, Hi);
1287 break;
1288
1289#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
1290 case ISD::STRICT_##DAGN:
1291#include "llvm/IR/ConstrainedOps.def"
1292 SplitVecRes_StrictFPOp(N, Lo, Hi);
1293 break;
1294
1297 SplitVecRes_FP_TO_XINT_SAT(N, Lo, Hi);
1298 break;
1299
1300 case ISD::UADDO:
1301 case ISD::SADDO:
1302 case ISD::USUBO:
1303 case ISD::SSUBO:
1304 case ISD::UMULO:
1305 case ISD::SMULO:
1306 SplitVecRes_OverflowOp(N, ResNo, Lo, Hi);
1307 break;
1308 case ISD::SMULFIX:
1309 case ISD::SMULFIXSAT:
1310 case ISD::UMULFIX:
1311 case ISD::UMULFIXSAT:
1312 case ISD::SDIVFIX:
1313 case ISD::SDIVFIXSAT:
1314 case ISD::UDIVFIX:
1315 case ISD::UDIVFIXSAT:
1316 SplitVecRes_FIX(N, Lo, Hi);
1317 break;
1318 case ISD::EXPERIMENTAL_VP_REVERSE:
1319 SplitVecRes_VP_REVERSE(N, Lo, Hi);
1320 break;
1321 }
1322
1323 // If Lo/Hi is null, the sub-method took care of registering results etc.
1324 if (Lo.getNode())
1325 SetSplitVector(SDValue(N, ResNo), Lo, Hi);
1326}
1327
1328void DAGTypeLegalizer::IncrementPointer(MemSDNode *N, EVT MemVT,
1330 uint64_t *ScaledOffset) {
1331 SDLoc DL(N);
1332 unsigned IncrementSize = MemVT.getSizeInBits().getKnownMinValue() / 8;
1333
1334 if (MemVT.isScalableVector()) {
1336 SDValue BytesIncrement = DAG.getVScale(
1337 DL, Ptr.getValueType(),
1338 APInt(Ptr.getValueSizeInBits().getFixedValue(), IncrementSize));
1339 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
1340 Flags.setNoUnsignedWrap(true);
1341 if (ScaledOffset)
1342 *ScaledOffset += IncrementSize;
1343 Ptr = DAG.getNode(ISD::ADD, DL, Ptr.getValueType(), Ptr, BytesIncrement,
1344 Flags);
1345 } else {
1346 MPI = N->getPointerInfo().getWithOffset(IncrementSize);
1347 // Increment the pointer to the other half.
1348 Ptr = DAG.getObjectPtrOffset(DL, Ptr, TypeSize::getFixed(IncrementSize));
1349 }
1350}
1351
1352std::pair<SDValue, SDValue> DAGTypeLegalizer::SplitMask(SDValue Mask) {
1353 return SplitMask(Mask, SDLoc(Mask));
1354}
1355
1356std::pair<SDValue, SDValue> DAGTypeLegalizer::SplitMask(SDValue Mask,
1357 const SDLoc &DL) {
1358 SDValue MaskLo, MaskHi;
1359 EVT MaskVT = Mask.getValueType();
1360 if (getTypeAction(MaskVT) == TargetLowering::TypeSplitVector)
1361 GetSplitVector(Mask, MaskLo, MaskHi);
1362 else
1363 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
1364 return std::make_pair(MaskLo, MaskHi);
1365}
1366
1367void DAGTypeLegalizer::SplitVecRes_BinOp(SDNode *N, SDValue &Lo, SDValue &Hi) {
1368 SDValue LHSLo, LHSHi;
1369 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1370 SDValue RHSLo, RHSHi;
1371 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
1372 SDLoc dl(N);
1373
1374 const SDNodeFlags Flags = N->getFlags();
1375 unsigned Opcode = N->getOpcode();
1376 if (N->getNumOperands() == 2) {
1377 Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(), LHSLo, RHSLo, Flags);
1378 Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(), LHSHi, RHSHi, Flags);
1379 return;
1380 }
1381
1382 assert(N->getNumOperands() == 4 && "Unexpected number of operands!");
1383 assert(N->isVPOpcode() && "Expected VP opcode");
1384
1385 SDValue MaskLo, MaskHi;
1386 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(2));
1387
1388 SDValue EVLLo, EVLHi;
1389 std::tie(EVLLo, EVLHi) =
1390 DAG.SplitEVL(N->getOperand(3), N->getValueType(0), dl);
1391
1392 Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(),
1393 {LHSLo, RHSLo, MaskLo, EVLLo}, Flags);
1394 Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(),
1395 {LHSHi, RHSHi, MaskHi, EVLHi}, Flags);
1396}
1397
1398void DAGTypeLegalizer::SplitVecRes_TernaryOp(SDNode *N, SDValue &Lo,
1399 SDValue &Hi) {
1400 SDValue Op0Lo, Op0Hi;
1401 GetSplitVector(N->getOperand(0), Op0Lo, Op0Hi);
1402 SDValue Op1Lo, Op1Hi;
1403 GetSplitVector(N->getOperand(1), Op1Lo, Op1Hi);
1404 SDValue Op2Lo, Op2Hi;
1405 GetSplitVector(N->getOperand(2), Op2Lo, Op2Hi);
1406 SDLoc dl(N);
1407
1408 const SDNodeFlags Flags = N->getFlags();
1409 unsigned Opcode = N->getOpcode();
1410 if (N->getNumOperands() == 3) {
1411 Lo = DAG.getNode(Opcode, dl, Op0Lo.getValueType(), Op0Lo, Op1Lo, Op2Lo, Flags);
1412 Hi = DAG.getNode(Opcode, dl, Op0Hi.getValueType(), Op0Hi, Op1Hi, Op2Hi, Flags);
1413 return;
1414 }
1415
1416 assert(N->getNumOperands() == 5 && "Unexpected number of operands!");
1417 assert(N->isVPOpcode() && "Expected VP opcode");
1418
1419 SDValue MaskLo, MaskHi;
1420 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(3));
1421
1422 SDValue EVLLo, EVLHi;
1423 std::tie(EVLLo, EVLHi) =
1424 DAG.SplitEVL(N->getOperand(4), N->getValueType(0), dl);
1425
1426 Lo = DAG.getNode(Opcode, dl, Op0Lo.getValueType(),
1427 {Op0Lo, Op1Lo, Op2Lo, MaskLo, EVLLo}, Flags);
1428 Hi = DAG.getNode(Opcode, dl, Op0Hi.getValueType(),
1429 {Op0Hi, Op1Hi, Op2Hi, MaskHi, EVLHi}, Flags);
1430}
1431
1432void DAGTypeLegalizer::SplitVecRes_CMP(SDNode *N, SDValue &Lo, SDValue &Hi) {
1433 LLVMContext &Ctxt = *DAG.getContext();
1434 SDLoc dl(N);
1435
1436 SDValue LHS = N->getOperand(0);
1437 SDValue RHS = N->getOperand(1);
1438
1439 SDValue LHSLo, LHSHi, RHSLo, RHSHi;
1440 if (getTypeAction(LHS.getValueType()) == TargetLowering::TypeSplitVector) {
1441 GetSplitVector(LHS, LHSLo, LHSHi);
1442 GetSplitVector(RHS, RHSLo, RHSHi);
1443 } else {
1444 std::tie(LHSLo, LHSHi) = DAG.SplitVector(LHS, dl);
1445 std::tie(RHSLo, RHSHi) = DAG.SplitVector(RHS, dl);
1446 }
1447
1448 EVT SplitResVT = N->getValueType(0).getHalfNumVectorElementsVT(Ctxt);
1449 Lo = DAG.getNode(N->getOpcode(), dl, SplitResVT, LHSLo, RHSLo);
1450 Hi = DAG.getNode(N->getOpcode(), dl, SplitResVT, LHSHi, RHSHi);
1451}
1452
1453void DAGTypeLegalizer::SplitVecRes_FIX(SDNode *N, SDValue &Lo, SDValue &Hi) {
1454 SDValue LHSLo, LHSHi;
1455 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1456 SDValue RHSLo, RHSHi;
1457 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
1458 SDLoc dl(N);
1459 SDValue Op2 = N->getOperand(2);
1460
1461 unsigned Opcode = N->getOpcode();
1462 Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(), LHSLo, RHSLo, Op2,
1463 N->getFlags());
1464 Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(), LHSHi, RHSHi, Op2,
1465 N->getFlags());
1466}
1467
1468void DAGTypeLegalizer::SplitVecRes_BITCAST(SDNode *N, SDValue &Lo,
1469 SDValue &Hi) {
1470 // We know the result is a vector. The input may be either a vector or a
1471 // scalar value.
1472 EVT LoVT, HiVT;
1473 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1474 SDLoc dl(N);
1475
1476 SDValue InOp = N->getOperand(0);
1477 EVT InVT = InOp.getValueType();
1478
1479 // Handle some special cases efficiently.
1480 switch (getTypeAction(InVT)) {
1488 break;
1491 // A scalar to vector conversion, where the scalar needs expansion.
1492 // If the vector is being split in two then we can just convert the
1493 // expanded pieces.
1494 if (LoVT == HiVT) {
1495 GetExpandedOp(InOp, Lo, Hi);
1496 if (DAG.getDataLayout().isBigEndian())
1497 std::swap(Lo, Hi);
1498 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
1499 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
1500 return;
1501 }
1502 break;
1504 // If the input is a vector that needs to be split, convert each split
1505 // piece of the input now.
1506 GetSplitVector(InOp, Lo, Hi);
1507 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
1508 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
1509 return;
1511 report_fatal_error("Scalarization of scalable vectors is not supported.");
1512 }
1513
1514 if (LoVT.isScalableVector()) {
1515 auto [InLo, InHi] = DAG.SplitVectorOperand(N, 0);
1516 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, InLo);
1517 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, InHi);
1518 return;
1519 }
1520
1521 // In the general case, convert the input to an integer and split it by hand.
1522 EVT LoIntVT = EVT::getIntegerVT(*DAG.getContext(), LoVT.getSizeInBits());
1523 EVT HiIntVT = EVT::getIntegerVT(*DAG.getContext(), HiVT.getSizeInBits());
1524 if (DAG.getDataLayout().isBigEndian())
1525 std::swap(LoIntVT, HiIntVT);
1526
1527 SplitInteger(BitConvertToInteger(InOp), LoIntVT, HiIntVT, Lo, Hi);
1528
1529 if (DAG.getDataLayout().isBigEndian())
1530 std::swap(Lo, Hi);
1531 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
1532 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
1533}
1534
1535void DAGTypeLegalizer::SplitVecRes_BUILD_VECTOR(SDNode *N, SDValue &Lo,
1536 SDValue &Hi) {
1537 EVT LoVT, HiVT;
1538 SDLoc dl(N);
1539 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1540 unsigned LoNumElts = LoVT.getVectorNumElements();
1541 SmallVector<SDValue, 8> LoOps(N->op_begin(), N->op_begin()+LoNumElts);
1542 Lo = DAG.getBuildVector(LoVT, dl, LoOps);
1543
1544 SmallVector<SDValue, 8> HiOps(N->op_begin()+LoNumElts, N->op_end());
1545 Hi = DAG.getBuildVector(HiVT, dl, HiOps);
1546}
1547
1548void DAGTypeLegalizer::SplitVecRes_CONCAT_VECTORS(SDNode *N, SDValue &Lo,
1549 SDValue &Hi) {
1550 assert(!(N->getNumOperands() & 1) && "Unsupported CONCAT_VECTORS");
1551 SDLoc dl(N);
1552 unsigned NumSubvectors = N->getNumOperands() / 2;
1553 if (NumSubvectors == 1) {
1554 Lo = N->getOperand(0);
1555 Hi = N->getOperand(1);
1556 return;
1557 }
1558
1559 EVT LoVT, HiVT;
1560 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1561
1562 SmallVector<SDValue, 8> LoOps(N->op_begin(), N->op_begin()+NumSubvectors);
1563 Lo = DAG.getNode(ISD::CONCAT_VECTORS, dl, LoVT, LoOps);
1564
1565 SmallVector<SDValue, 8> HiOps(N->op_begin()+NumSubvectors, N->op_end());
1566 Hi = DAG.getNode(ISD::CONCAT_VECTORS, dl, HiVT, HiOps);
1567}
1568
1569void DAGTypeLegalizer::SplitVecRes_EXTRACT_SUBVECTOR(SDNode *N, SDValue &Lo,
1570 SDValue &Hi) {
1571 SDValue Vec = N->getOperand(0);
1572 SDValue Idx = N->getOperand(1);
1573 SDLoc dl(N);
1574
1575 EVT LoVT, HiVT;
1576 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1577
1578 Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, LoVT, Vec, Idx);
1579 uint64_t IdxVal = Idx->getAsZExtVal();
1580 Hi = DAG.getNode(
1581 ISD::EXTRACT_SUBVECTOR, dl, HiVT, Vec,
1582 DAG.getVectorIdxConstant(IdxVal + LoVT.getVectorMinNumElements(), dl));
1583}
1584
1585void DAGTypeLegalizer::SplitVecRes_INSERT_SUBVECTOR(SDNode *N, SDValue &Lo,
1586 SDValue &Hi) {
1587 SDValue Vec = N->getOperand(0);
1588 SDValue SubVec = N->getOperand(1);
1589 SDValue Idx = N->getOperand(2);
1590 SDLoc dl(N);
1591 GetSplitVector(Vec, Lo, Hi);
1592
1593 EVT VecVT = Vec.getValueType();
1594 EVT LoVT = Lo.getValueType();
1595 EVT SubVecVT = SubVec.getValueType();
1596 unsigned VecElems = VecVT.getVectorMinNumElements();
1597 unsigned SubElems = SubVecVT.getVectorMinNumElements();
1598 unsigned LoElems = LoVT.getVectorMinNumElements();
1599
1600 // If we know the index is in the first half, and we know the subvector
1601 // doesn't cross the boundary between the halves, we can avoid spilling the
1602 // vector, and insert into the lower half of the split vector directly.
1603 unsigned IdxVal = Idx->getAsZExtVal();
1604 if (IdxVal + SubElems <= LoElems) {
1605 Lo = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, LoVT, Lo, SubVec, Idx);
1606 return;
1607 }
1608 // Similarly if the subvector is fully in the high half, but mind that we
1609 // can't tell whether a fixed-length subvector is fully within the high half
1610 // of a scalable vector.
1611 if (VecVT.isScalableVector() == SubVecVT.isScalableVector() &&
1612 IdxVal >= LoElems && IdxVal + SubElems <= VecElems) {
1613 Hi = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, Hi.getValueType(), Hi, SubVec,
1614 DAG.getVectorIdxConstant(IdxVal - LoElems, dl));
1615 return;
1616 }
1617
1618 // Spill the vector to the stack.
1619 // In cases where the vector is illegal it will be broken down into parts
1620 // and stored in parts - we should use the alignment for the smallest part.
1621 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
1623 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
1624 auto &MF = DAG.getMachineFunction();
1625 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
1626 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
1627
1628 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
1629 SmallestAlign);
1630
1631 // Store the new subvector into the specified index.
1632 SDValue SubVecPtr =
1633 TLI.getVectorSubVecPointer(DAG, StackPtr, VecVT, SubVecVT, Idx);
1634 Store = DAG.getStore(Store, dl, SubVec, SubVecPtr,
1636
1637 // Load the Lo part from the stack slot.
1638 Lo = DAG.getLoad(Lo.getValueType(), dl, Store, StackPtr, PtrInfo,
1639 SmallestAlign);
1640
1641 // Increment the pointer to the other part.
1642 auto *Load = cast<LoadSDNode>(Lo);
1643 MachinePointerInfo MPI = Load->getPointerInfo();
1644 IncrementPointer(Load, LoVT, MPI, StackPtr);
1645
1646 // Load the Hi part from the stack slot.
1647 Hi = DAG.getLoad(Hi.getValueType(), dl, Store, StackPtr, MPI, SmallestAlign);
1648}
1649
1650// Handle splitting an FP where the second operand does not match the first
1651// type. The second operand may be a scalar, or a vector that has exactly as
1652// many elements as the first
1653void DAGTypeLegalizer::SplitVecRes_FPOp_MultiType(SDNode *N, SDValue &Lo,
1654 SDValue &Hi) {
1655 SDValue LHSLo, LHSHi;
1656 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1657 SDLoc DL(N);
1658
1659 SDValue RHSLo, RHSHi;
1660 SDValue RHS = N->getOperand(1);
1661 EVT RHSVT = RHS.getValueType();
1662 if (RHSVT.isVector()) {
1663 if (getTypeAction(RHSVT) == TargetLowering::TypeSplitVector)
1664 GetSplitVector(RHS, RHSLo, RHSHi);
1665 else
1666 std::tie(RHSLo, RHSHi) = DAG.SplitVector(RHS, SDLoc(RHS));
1667
1668 Lo = DAG.getNode(N->getOpcode(), DL, LHSLo.getValueType(), LHSLo, RHSLo);
1669 Hi = DAG.getNode(N->getOpcode(), DL, LHSHi.getValueType(), LHSHi, RHSHi);
1670 } else {
1671 Lo = DAG.getNode(N->getOpcode(), DL, LHSLo.getValueType(), LHSLo, RHS);
1672 Hi = DAG.getNode(N->getOpcode(), DL, LHSHi.getValueType(), LHSHi, RHS);
1673 }
1674}
1675
1676void DAGTypeLegalizer::SplitVecRes_IS_FPCLASS(SDNode *N, SDValue &Lo,
1677 SDValue &Hi) {
1678 SDLoc DL(N);
1679 SDValue ArgLo, ArgHi;
1680 SDValue Test = N->getOperand(1);
1681 SDValue FpValue = N->getOperand(0);
1682 if (getTypeAction(FpValue.getValueType()) == TargetLowering::TypeSplitVector)
1683 GetSplitVector(FpValue, ArgLo, ArgHi);
1684 else
1685 std::tie(ArgLo, ArgHi) = DAG.SplitVector(FpValue, SDLoc(FpValue));
1686 EVT LoVT, HiVT;
1687 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1688
1689 Lo = DAG.getNode(ISD::IS_FPCLASS, DL, LoVT, ArgLo, Test, N->getFlags());
1690 Hi = DAG.getNode(ISD::IS_FPCLASS, DL, HiVT, ArgHi, Test, N->getFlags());
1691}
1692
1693void DAGTypeLegalizer::SplitVecRes_InregOp(SDNode *N, SDValue &Lo,
1694 SDValue &Hi) {
1695 SDValue LHSLo, LHSHi;
1696 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1697 SDLoc dl(N);
1698
1699 EVT LoVT, HiVT;
1700 std::tie(LoVT, HiVT) =
1701 DAG.GetSplitDestVTs(cast<VTSDNode>(N->getOperand(1))->getVT());
1702
1703 Lo = DAG.getNode(N->getOpcode(), dl, LHSLo.getValueType(), LHSLo,
1704 DAG.getValueType(LoVT));
1705 Hi = DAG.getNode(N->getOpcode(), dl, LHSHi.getValueType(), LHSHi,
1706 DAG.getValueType(HiVT));
1707}
1708
1709void DAGTypeLegalizer::SplitVecRes_ExtVecInRegOp(SDNode *N, SDValue &Lo,
1710 SDValue &Hi) {
1711 unsigned Opcode = N->getOpcode();
1712 SDValue N0 = N->getOperand(0);
1713
1714 SDLoc dl(N);
1715 SDValue InLo, InHi;
1716
1717 if (getTypeAction(N0.getValueType()) == TargetLowering::TypeSplitVector)
1718 GetSplitVector(N0, InLo, InHi);
1719 else
1720 std::tie(InLo, InHi) = DAG.SplitVectorOperand(N, 0);
1721
1722 EVT InLoVT = InLo.getValueType();
1723 unsigned InNumElements = InLoVT.getVectorNumElements();
1724
1725 EVT OutLoVT, OutHiVT;
1726 std::tie(OutLoVT, OutHiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1727 unsigned OutNumElements = OutLoVT.getVectorNumElements();
1728 assert((2 * OutNumElements) <= InNumElements &&
1729 "Illegal extend vector in reg split");
1730
1731 // *_EXTEND_VECTOR_INREG instructions extend the lowest elements of the
1732 // input vector (i.e. we only use InLo):
1733 // OutLo will extend the first OutNumElements from InLo.
1734 // OutHi will extend the next OutNumElements from InLo.
1735
1736 // Shuffle the elements from InLo for OutHi into the bottom elements to
1737 // create a 'fake' InHi.
1738 SmallVector<int, 8> SplitHi(InNumElements, -1);
1739 for (unsigned i = 0; i != OutNumElements; ++i)
1740 SplitHi[i] = i + OutNumElements;
1741 InHi = DAG.getVectorShuffle(InLoVT, dl, InLo, DAG.getUNDEF(InLoVT), SplitHi);
1742
1743 Lo = DAG.getNode(Opcode, dl, OutLoVT, InLo);
1744 Hi = DAG.getNode(Opcode, dl, OutHiVT, InHi);
1745}
1746
1747void DAGTypeLegalizer::SplitVecRes_StrictFPOp(SDNode *N, SDValue &Lo,
1748 SDValue &Hi) {
1749 unsigned NumOps = N->getNumOperands();
1750 SDValue Chain = N->getOperand(0);
1751 EVT LoVT, HiVT;
1752 SDLoc dl(N);
1753 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1754
1755 SmallVector<SDValue, 4> OpsLo(NumOps);
1756 SmallVector<SDValue, 4> OpsHi(NumOps);
1757
1758 // The Chain is the first operand.
1759 OpsLo[0] = Chain;
1760 OpsHi[0] = Chain;
1761
1762 // Now process the remaining operands.
1763 for (unsigned i = 1; i < NumOps; ++i) {
1764 SDValue Op = N->getOperand(i);
1765 SDValue OpLo = Op;
1766 SDValue OpHi = Op;
1767
1768 EVT InVT = Op.getValueType();
1769 if (InVT.isVector()) {
1770 // If the input also splits, handle it directly for a
1771 // compile time speedup. Otherwise split it by hand.
1772 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
1773 GetSplitVector(Op, OpLo, OpHi);
1774 else
1775 std::tie(OpLo, OpHi) = DAG.SplitVectorOperand(N, i);
1776 }
1777
1778 OpsLo[i] = OpLo;
1779 OpsHi[i] = OpHi;
1780 }
1781
1782 EVT LoValueVTs[] = {LoVT, MVT::Other};
1783 EVT HiValueVTs[] = {HiVT, MVT::Other};
1784 Lo = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(LoValueVTs), OpsLo,
1785 N->getFlags());
1786 Hi = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(HiValueVTs), OpsHi,
1787 N->getFlags());
1788
1789 // Build a factor node to remember that this Op is independent of the
1790 // other one.
1791 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
1792 Lo.getValue(1), Hi.getValue(1));
1793
1794 // Legalize the chain result - switch anything that used the old chain to
1795 // use the new one.
1796 ReplaceValueWith(SDValue(N, 1), Chain);
1797}
1798
1799SDValue DAGTypeLegalizer::UnrollVectorOp_StrictFP(SDNode *N, unsigned ResNE) {
1800 SDValue Chain = N->getOperand(0);
1801 EVT VT = N->getValueType(0);
1802 unsigned NE = VT.getVectorNumElements();
1803 EVT EltVT = VT.getVectorElementType();
1804 SDLoc dl(N);
1805
1807 SmallVector<SDValue, 4> Operands(N->getNumOperands());
1808
1809 // If ResNE is 0, fully unroll the vector op.
1810 if (ResNE == 0)
1811 ResNE = NE;
1812 else if (NE > ResNE)
1813 NE = ResNE;
1814
1815 //The results of each unrolled operation, including the chain.
1816 EVT ChainVTs[] = {EltVT, MVT::Other};
1818
1819 unsigned i;
1820 for (i = 0; i != NE; ++i) {
1821 Operands[0] = Chain;
1822 for (unsigned j = 1, e = N->getNumOperands(); j != e; ++j) {
1823 SDValue Operand = N->getOperand(j);
1824 EVT OperandVT = Operand.getValueType();
1825 if (OperandVT.isVector()) {
1826 EVT OperandEltVT = OperandVT.getVectorElementType();
1827 Operands[j] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, OperandEltVT,
1828 Operand, DAG.getVectorIdxConstant(i, dl));
1829 } else {
1830 Operands[j] = Operand;
1831 }
1832 }
1833 SDValue Scalar = DAG.getNode(N->getOpcode(), dl, ChainVTs, Operands);
1834 Scalar.getNode()->setFlags(N->getFlags());
1835
1836 //Add in the scalar as well as its chain value to the
1837 //result vectors.
1838 Scalars.push_back(Scalar);
1839 Chains.push_back(Scalar.getValue(1));
1840 }
1841
1842 for (; i < ResNE; ++i)
1843 Scalars.push_back(DAG.getUNDEF(EltVT));
1844
1845 // Build a new factor node to connect the chain back together.
1846 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
1847 ReplaceValueWith(SDValue(N, 1), Chain);
1848
1849 // Create a new BUILD_VECTOR node
1850 EVT VecVT = EVT::getVectorVT(*DAG.getContext(), EltVT, ResNE);
1851 return DAG.getBuildVector(VecVT, dl, Scalars);
1852}
1853
1854void DAGTypeLegalizer::SplitVecRes_OverflowOp(SDNode *N, unsigned ResNo,
1855 SDValue &Lo, SDValue &Hi) {
1856 SDLoc dl(N);
1857 EVT ResVT = N->getValueType(0);
1858 EVT OvVT = N->getValueType(1);
1859 EVT LoResVT, HiResVT, LoOvVT, HiOvVT;
1860 std::tie(LoResVT, HiResVT) = DAG.GetSplitDestVTs(ResVT);
1861 std::tie(LoOvVT, HiOvVT) = DAG.GetSplitDestVTs(OvVT);
1862
1863 SDValue LoLHS, HiLHS, LoRHS, HiRHS;
1864 if (getTypeAction(ResVT) == TargetLowering::TypeSplitVector) {
1865 GetSplitVector(N->getOperand(0), LoLHS, HiLHS);
1866 GetSplitVector(N->getOperand(1), LoRHS, HiRHS);
1867 } else {
1868 std::tie(LoLHS, HiLHS) = DAG.SplitVectorOperand(N, 0);
1869 std::tie(LoRHS, HiRHS) = DAG.SplitVectorOperand(N, 1);
1870 }
1871
1872 unsigned Opcode = N->getOpcode();
1873 SDVTList LoVTs = DAG.getVTList(LoResVT, LoOvVT);
1874 SDVTList HiVTs = DAG.getVTList(HiResVT, HiOvVT);
1875 SDNode *LoNode = DAG.getNode(Opcode, dl, LoVTs, LoLHS, LoRHS).getNode();
1876 SDNode *HiNode = DAG.getNode(Opcode, dl, HiVTs, HiLHS, HiRHS).getNode();
1877 LoNode->setFlags(N->getFlags());
1878 HiNode->setFlags(N->getFlags());
1879
1880 Lo = SDValue(LoNode, ResNo);
1881 Hi = SDValue(HiNode, ResNo);
1882
1883 // Replace the other vector result not being explicitly split here.
1884 unsigned OtherNo = 1 - ResNo;
1885 EVT OtherVT = N->getValueType(OtherNo);
1886 if (getTypeAction(OtherVT) == TargetLowering::TypeSplitVector) {
1887 SetSplitVector(SDValue(N, OtherNo),
1888 SDValue(LoNode, OtherNo), SDValue(HiNode, OtherNo));
1889 } else {
1890 SDValue OtherVal = DAG.getNode(
1891 ISD::CONCAT_VECTORS, dl, OtherVT,
1892 SDValue(LoNode, OtherNo), SDValue(HiNode, OtherNo));
1893 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
1894 }
1895}
1896
1897void DAGTypeLegalizer::SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo,
1898 SDValue &Hi) {
1899 SDValue Vec = N->getOperand(0);
1900 SDValue Elt = N->getOperand(1);
1901 SDValue Idx = N->getOperand(2);
1902 SDLoc dl(N);
1903 GetSplitVector(Vec, Lo, Hi);
1904
1905 if (ConstantSDNode *CIdx = dyn_cast<ConstantSDNode>(Idx)) {
1906 unsigned IdxVal = CIdx->getZExtValue();
1907 unsigned LoNumElts = Lo.getValueType().getVectorMinNumElements();
1908 if (IdxVal < LoNumElts) {
1910 Lo.getValueType(), Lo, Elt, Idx);
1911 return;
1912 } else if (!Vec.getValueType().isScalableVector()) {
1913 Hi = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, Hi.getValueType(), Hi, Elt,
1914 DAG.getVectorIdxConstant(IdxVal - LoNumElts, dl));
1915 return;
1916 }
1917 }
1918
1919 // Make the vector elements byte-addressable if they aren't already.
1920 EVT VecVT = Vec.getValueType();
1921 EVT EltVT = VecVT.getVectorElementType();
1922 if (!EltVT.isByteSized()) {
1923 EltVT = EltVT.changeTypeToInteger().getRoundIntegerType(*DAG.getContext());
1924 VecVT = VecVT.changeElementType(EltVT);
1925 Vec = DAG.getNode(ISD::ANY_EXTEND, dl, VecVT, Vec);
1926 // Extend the element type to match if needed.
1927 if (EltVT.bitsGT(Elt.getValueType()))
1928 Elt = DAG.getNode(ISD::ANY_EXTEND, dl, EltVT, Elt);
1929 }
1930
1931 // Spill the vector to the stack.
1932 // In cases where the vector is illegal it will be broken down into parts
1933 // and stored in parts - we should use the alignment for the smallest part.
1934 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
1936 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
1937 auto &MF = DAG.getMachineFunction();
1938 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
1939 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
1940
1941 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
1942 SmallestAlign);
1943
1944 // Store the new element. This may be larger than the vector element type,
1945 // so use a truncating store.
1946 SDValue EltPtr = TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Idx);
1947 Store = DAG.getTruncStore(
1948 Store, dl, Elt, EltPtr, MachinePointerInfo::getUnknownStack(MF), EltVT,
1949 commonAlignment(SmallestAlign,
1950 EltVT.getFixedSizeInBits() / 8));
1951
1952 EVT LoVT, HiVT;
1953 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(VecVT);
1954
1955 // Load the Lo part from the stack slot.
1956 Lo = DAG.getLoad(LoVT, dl, Store, StackPtr, PtrInfo, SmallestAlign);
1957
1958 // Increment the pointer to the other part.
1959 auto Load = cast<LoadSDNode>(Lo);
1960 MachinePointerInfo MPI = Load->getPointerInfo();
1961 IncrementPointer(Load, LoVT, MPI, StackPtr);
1962
1963 Hi = DAG.getLoad(HiVT, dl, Store, StackPtr, MPI, SmallestAlign);
1964
1965 // If we adjusted the original type, we need to truncate the results.
1966 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1967 if (LoVT != Lo.getValueType())
1968 Lo = DAG.getNode(ISD::TRUNCATE, dl, LoVT, Lo);
1969 if (HiVT != Hi.getValueType())
1970 Hi = DAG.getNode(ISD::TRUNCATE, dl, HiVT, Hi);
1971}
1972
1973void DAGTypeLegalizer::SplitVecRes_STEP_VECTOR(SDNode *N, SDValue &Lo,
1974 SDValue &Hi) {
1975 EVT LoVT, HiVT;
1976 SDLoc dl(N);
1977 assert(N->getValueType(0).isScalableVector() &&
1978 "Only scalable vectors are supported for STEP_VECTOR");
1979 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1980 SDValue Step = N->getOperand(0);
1981
1982 Lo = DAG.getNode(ISD::STEP_VECTOR, dl, LoVT, Step);
1983
1984 // Hi = Lo + (EltCnt * Step)
1985 EVT EltVT = Step.getValueType();
1986 APInt StepVal = Step->getAsAPIntVal();
1987 SDValue StartOfHi =
1988 DAG.getVScale(dl, EltVT, StepVal * LoVT.getVectorMinNumElements());
1989 StartOfHi = DAG.getSExtOrTrunc(StartOfHi, dl, HiVT.getVectorElementType());
1990 StartOfHi = DAG.getNode(ISD::SPLAT_VECTOR, dl, HiVT, StartOfHi);
1991
1992 Hi = DAG.getNode(ISD::STEP_VECTOR, dl, HiVT, Step);
1993 Hi = DAG.getNode(ISD::ADD, dl, HiVT, Hi, StartOfHi);
1994}
1995
1996void DAGTypeLegalizer::SplitVecRes_ScalarOp(SDNode *N, SDValue &Lo,
1997 SDValue &Hi) {
1998 EVT LoVT, HiVT;
1999 SDLoc dl(N);
2000 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2001 Lo = DAG.getNode(N->getOpcode(), dl, LoVT, N->getOperand(0));
2002 if (N->getOpcode() == ISD::SCALAR_TO_VECTOR) {
2003 Hi = DAG.getUNDEF(HiVT);
2004 } else {
2005 assert(N->getOpcode() == ISD::SPLAT_VECTOR && "Unexpected opcode");
2006 Hi = Lo;
2007 }
2008}
2009
2010void DAGTypeLegalizer::SplitVecRes_LOAD(LoadSDNode *LD, SDValue &Lo,
2011 SDValue &Hi) {
2012 assert(ISD::isUNINDEXEDLoad(LD) && "Indexed load during type legalization!");
2013 EVT LoVT, HiVT;
2014 SDLoc dl(LD);
2015 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(LD->getValueType(0));
2016
2017 ISD::LoadExtType ExtType = LD->getExtensionType();
2018 SDValue Ch = LD->getChain();
2019 SDValue Ptr = LD->getBasePtr();
2020 SDValue Offset = DAG.getUNDEF(Ptr.getValueType());
2021 EVT MemoryVT = LD->getMemoryVT();
2022 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
2023 AAMDNodes AAInfo = LD->getAAInfo();
2024
2025 EVT LoMemVT, HiMemVT;
2026 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
2027
2028 if (!LoMemVT.isByteSized() || !HiMemVT.isByteSized()) {
2029 SDValue Value, NewChain;
2030 std::tie(Value, NewChain) = TLI.scalarizeVectorLoad(LD, DAG);
2031 std::tie(Lo, Hi) = DAG.SplitVector(Value, dl);
2032 ReplaceValueWith(SDValue(LD, 1), NewChain);
2033 return;
2034 }
2035
2036 Lo = DAG.getLoad(ISD::UNINDEXED, ExtType, LoVT, dl, Ch, Ptr, Offset,
2037 LD->getPointerInfo(), LoMemVT, LD->getOriginalAlign(),
2038 MMOFlags, AAInfo);
2039
2041 IncrementPointer(LD, LoMemVT, MPI, Ptr);
2042
2043 Hi = DAG.getLoad(ISD::UNINDEXED, ExtType, HiVT, dl, Ch, Ptr, Offset, MPI,
2044 HiMemVT, LD->getOriginalAlign(), MMOFlags, AAInfo);
2045
2046 // Build a factor node to remember that this load is independent of the
2047 // other one.
2048 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2049 Hi.getValue(1));
2050
2051 // Legalize the chain result - switch anything that used the old chain to
2052 // use the new one.
2053 ReplaceValueWith(SDValue(LD, 1), Ch);
2054}
2055
2056void DAGTypeLegalizer::SplitVecRes_VP_LOAD(VPLoadSDNode *LD, SDValue &Lo,
2057 SDValue &Hi) {
2058 assert(LD->isUnindexed() && "Indexed VP load during type legalization!");
2059 EVT LoVT, HiVT;
2060 SDLoc dl(LD);
2061 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(LD->getValueType(0));
2062
2063 ISD::LoadExtType ExtType = LD->getExtensionType();
2064 SDValue Ch = LD->getChain();
2065 SDValue Ptr = LD->getBasePtr();
2066 SDValue Offset = LD->getOffset();
2067 assert(Offset.isUndef() && "Unexpected indexed variable-length load offset");
2068 Align Alignment = LD->getOriginalAlign();
2069 SDValue Mask = LD->getMask();
2070 SDValue EVL = LD->getVectorLength();
2071 EVT MemoryVT = LD->getMemoryVT();
2072
2073 EVT LoMemVT, HiMemVT;
2074 bool HiIsEmpty = false;
2075 std::tie(LoMemVT, HiMemVT) =
2076 DAG.GetDependentSplitDestVTs(MemoryVT, LoVT, &HiIsEmpty);
2077
2078 // Split Mask operand
2079 SDValue MaskLo, MaskHi;
2080 if (Mask.getOpcode() == ISD::SETCC) {
2081 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
2082 } else {
2083 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
2084 GetSplitVector(Mask, MaskLo, MaskHi);
2085 else
2086 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, dl);
2087 }
2088
2089 // Split EVL operand
2090 SDValue EVLLo, EVLHi;
2091 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(EVL, LD->getValueType(0), dl);
2092
2094 LD->getPointerInfo(), MachineMemOperand::MOLoad,
2095 LocationSize::beforeOrAfterPointer(), Alignment, LD->getAAInfo(),
2096 LD->getRanges());
2097
2098 Lo =
2099 DAG.getLoadVP(LD->getAddressingMode(), ExtType, LoVT, dl, Ch, Ptr, Offset,
2100 MaskLo, EVLLo, LoMemVT, MMO, LD->isExpandingLoad());
2101
2102 if (HiIsEmpty) {
2103 // The hi vp_load has zero storage size. We therefore simply set it to
2104 // the low vp_load and rely on subsequent removal from the chain.
2105 Hi = Lo;
2106 } else {
2107 // Generate hi vp_load.
2108 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, dl, LoMemVT, DAG,
2109 LD->isExpandingLoad());
2110
2112 if (LoMemVT.isScalableVector())
2113 MPI = MachinePointerInfo(LD->getPointerInfo().getAddrSpace());
2114 else
2115 MPI = LD->getPointerInfo().getWithOffset(
2116 LoMemVT.getStoreSize().getFixedValue());
2117
2120 Alignment, LD->getAAInfo(), LD->getRanges());
2121
2122 Hi = DAG.getLoadVP(LD->getAddressingMode(), ExtType, HiVT, dl, Ch, Ptr,
2123 Offset, MaskHi, EVLHi, HiMemVT, MMO,
2124 LD->isExpandingLoad());
2125 }
2126
2127 // Build a factor node to remember that this load is independent of the
2128 // other one.
2129 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2130 Hi.getValue(1));
2131
2132 // Legalize the chain result - switch anything that used the old chain to
2133 // use the new one.
2134 ReplaceValueWith(SDValue(LD, 1), Ch);
2135}
2136
2137void DAGTypeLegalizer::SplitVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode *SLD,
2138 SDValue &Lo, SDValue &Hi) {
2139 assert(SLD->isUnindexed() &&
2140 "Indexed VP strided load during type legalization!");
2141 assert(SLD->getOffset().isUndef() &&
2142 "Unexpected indexed variable-length load offset");
2143
2144 SDLoc DL(SLD);
2145
2146 EVT LoVT, HiVT;
2147 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(SLD->getValueType(0));
2148
2149 EVT LoMemVT, HiMemVT;
2150 bool HiIsEmpty = false;
2151 std::tie(LoMemVT, HiMemVT) =
2152 DAG.GetDependentSplitDestVTs(SLD->getMemoryVT(), LoVT, &HiIsEmpty);
2153
2154 SDValue Mask = SLD->getMask();
2155 SDValue LoMask, HiMask;
2156 if (Mask.getOpcode() == ISD::SETCC) {
2157 SplitVecRes_SETCC(Mask.getNode(), LoMask, HiMask);
2158 } else {
2159 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
2160 GetSplitVector(Mask, LoMask, HiMask);
2161 else
2162 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
2163 }
2164
2165 SDValue LoEVL, HiEVL;
2166 std::tie(LoEVL, HiEVL) =
2167 DAG.SplitEVL(SLD->getVectorLength(), SLD->getValueType(0), DL);
2168
2169 // Generate the low vp_strided_load
2170 Lo = DAG.getStridedLoadVP(
2171 SLD->getAddressingMode(), SLD->getExtensionType(), LoVT, DL,
2172 SLD->getChain(), SLD->getBasePtr(), SLD->getOffset(), SLD->getStride(),
2173 LoMask, LoEVL, LoMemVT, SLD->getMemOperand(), SLD->isExpandingLoad());
2174
2175 if (HiIsEmpty) {
2176 // The high vp_strided_load has zero storage size. We therefore simply set
2177 // it to the low vp_strided_load and rely on subsequent removal from the
2178 // chain.
2179 Hi = Lo;
2180 } else {
2181 // Generate the high vp_strided_load.
2182 // To calculate the high base address, we need to sum to the low base
2183 // address stride number of bytes for each element already loaded by low,
2184 // that is: Ptr = Ptr + (LoEVL * Stride)
2185 EVT PtrVT = SLD->getBasePtr().getValueType();
2187 DAG.getNode(ISD::MUL, DL, PtrVT, LoEVL,
2188 DAG.getSExtOrTrunc(SLD->getStride(), DL, PtrVT));
2189 SDValue Ptr =
2190 DAG.getNode(ISD::ADD, DL, PtrVT, SLD->getBasePtr(), Increment);
2191
2192 Align Alignment = SLD->getOriginalAlign();
2193 if (LoMemVT.isScalableVector())
2194 Alignment = commonAlignment(
2195 Alignment, LoMemVT.getSizeInBits().getKnownMinValue() / 8);
2196
2200 Alignment, SLD->getAAInfo(), SLD->getRanges());
2201
2203 HiVT, DL, SLD->getChain(), Ptr, SLD->getOffset(),
2204 SLD->getStride(), HiMask, HiEVL, HiMemVT, MMO,
2205 SLD->isExpandingLoad());
2206 }
2207
2208 // Build a factor node to remember that this load is independent of the
2209 // other one.
2210 SDValue Ch = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo.getValue(1),
2211 Hi.getValue(1));
2212
2213 // Legalize the chain result - switch anything that used the old chain to
2214 // use the new one.
2215 ReplaceValueWith(SDValue(SLD, 1), Ch);
2216}
2217
2218void DAGTypeLegalizer::SplitVecRes_MLOAD(MaskedLoadSDNode *MLD,
2219 SDValue &Lo, SDValue &Hi) {
2220 assert(MLD->isUnindexed() && "Indexed masked load during type legalization!");
2221 EVT LoVT, HiVT;
2222 SDLoc dl(MLD);
2223 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(MLD->getValueType(0));
2224
2225 SDValue Ch = MLD->getChain();
2226 SDValue Ptr = MLD->getBasePtr();
2227 SDValue Offset = MLD->getOffset();
2228 assert(Offset.isUndef() && "Unexpected indexed masked load offset");
2229 SDValue Mask = MLD->getMask();
2230 SDValue PassThru = MLD->getPassThru();
2231 Align Alignment = MLD->getOriginalAlign();
2232 ISD::LoadExtType ExtType = MLD->getExtensionType();
2233
2234 // Split Mask operand
2235 SDValue MaskLo, MaskHi;
2236 if (Mask.getOpcode() == ISD::SETCC) {
2237 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
2238 } else {
2239 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
2240 GetSplitVector(Mask, MaskLo, MaskHi);
2241 else
2242 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, dl);
2243 }
2244
2245 EVT MemoryVT = MLD->getMemoryVT();
2246 EVT LoMemVT, HiMemVT;
2247 bool HiIsEmpty = false;
2248 std::tie(LoMemVT, HiMemVT) =
2249 DAG.GetDependentSplitDestVTs(MemoryVT, LoVT, &HiIsEmpty);
2250
2251 SDValue PassThruLo, PassThruHi;
2252 if (getTypeAction(PassThru.getValueType()) == TargetLowering::TypeSplitVector)
2253 GetSplitVector(PassThru, PassThruLo, PassThruHi);
2254 else
2255 std::tie(PassThruLo, PassThruHi) = DAG.SplitVector(PassThru, dl);
2256
2259 LocationSize::beforeOrAfterPointer(), Alignment, MLD->getAAInfo(),
2260 MLD->getRanges());
2261
2262 Lo = DAG.getMaskedLoad(LoVT, dl, Ch, Ptr, Offset, MaskLo, PassThruLo, LoMemVT,
2263 MMO, MLD->getAddressingMode(), ExtType,
2264 MLD->isExpandingLoad());
2265
2266 if (HiIsEmpty) {
2267 // The hi masked load has zero storage size. We therefore simply set it to
2268 // the low masked load and rely on subsequent removal from the chain.
2269 Hi = Lo;
2270 } else {
2271 // Generate hi masked load.
2272 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, dl, LoMemVT, DAG,
2273 MLD->isExpandingLoad());
2274
2276 if (LoMemVT.isScalableVector())
2278 else
2279 MPI = MLD->getPointerInfo().getWithOffset(
2280 LoMemVT.getStoreSize().getFixedValue());
2281
2284 Alignment, MLD->getAAInfo(), MLD->getRanges());
2285
2286 Hi = DAG.getMaskedLoad(HiVT, dl, Ch, Ptr, Offset, MaskHi, PassThruHi,
2287 HiMemVT, MMO, MLD->getAddressingMode(), ExtType,
2288 MLD->isExpandingLoad());
2289 }
2290
2291 // Build a factor node to remember that this load is independent of the
2292 // other one.
2293 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2294 Hi.getValue(1));
2295
2296 // Legalize the chain result - switch anything that used the old chain to
2297 // use the new one.
2298 ReplaceValueWith(SDValue(MLD, 1), Ch);
2299
2300}
2301
2302void DAGTypeLegalizer::SplitVecRes_Gather(MemSDNode *N, SDValue &Lo,
2303 SDValue &Hi, bool SplitSETCC) {
2304 EVT LoVT, HiVT;
2305 SDLoc dl(N);
2306 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2307
2308 SDValue Ch = N->getChain();
2309 SDValue Ptr = N->getBasePtr();
2310 struct Operands {
2311 SDValue Mask;
2312 SDValue Index;
2313 SDValue Scale;
2314 } Ops = [&]() -> Operands {
2315 if (auto *MSC = dyn_cast<MaskedGatherSDNode>(N)) {
2316 return {MSC->getMask(), MSC->getIndex(), MSC->getScale()};
2317 }
2318 auto *VPSC = cast<VPGatherSDNode>(N);
2319 return {VPSC->getMask(), VPSC->getIndex(), VPSC->getScale()};
2320 }();
2321
2322 EVT MemoryVT = N->getMemoryVT();
2323 Align Alignment = N->getOriginalAlign();
2324
2325 // Split Mask operand
2326 SDValue MaskLo, MaskHi;
2327 if (SplitSETCC && Ops.Mask.getOpcode() == ISD::SETCC) {
2328 SplitVecRes_SETCC(Ops.Mask.getNode(), MaskLo, MaskHi);
2329 } else {
2330 std::tie(MaskLo, MaskHi) = SplitMask(Ops.Mask, dl);
2331 }
2332
2333 EVT LoMemVT, HiMemVT;
2334 // Split MemoryVT
2335 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
2336
2337 SDValue IndexHi, IndexLo;
2338 if (getTypeAction(Ops.Index.getValueType()) ==
2340 GetSplitVector(Ops.Index, IndexLo, IndexHi);
2341 else
2342 std::tie(IndexLo, IndexHi) = DAG.SplitVector(Ops.Index, dl);
2343
2345 N->getPointerInfo(), MachineMemOperand::MOLoad,
2346 LocationSize::beforeOrAfterPointer(), Alignment, N->getAAInfo(),
2347 N->getRanges());
2348
2349 if (auto *MGT = dyn_cast<MaskedGatherSDNode>(N)) {
2350 SDValue PassThru = MGT->getPassThru();
2351 SDValue PassThruLo, PassThruHi;
2352 if (getTypeAction(PassThru.getValueType()) ==
2354 GetSplitVector(PassThru, PassThruLo, PassThruHi);
2355 else
2356 std::tie(PassThruLo, PassThruHi) = DAG.SplitVector(PassThru, dl);
2357
2358 ISD::LoadExtType ExtType = MGT->getExtensionType();
2359 ISD::MemIndexType IndexTy = MGT->getIndexType();
2360
2361 SDValue OpsLo[] = {Ch, PassThruLo, MaskLo, Ptr, IndexLo, Ops.Scale};
2362 Lo = DAG.getMaskedGather(DAG.getVTList(LoVT, MVT::Other), LoMemVT, dl,
2363 OpsLo, MMO, IndexTy, ExtType);
2364
2365 SDValue OpsHi[] = {Ch, PassThruHi, MaskHi, Ptr, IndexHi, Ops.Scale};
2366 Hi = DAG.getMaskedGather(DAG.getVTList(HiVT, MVT::Other), HiMemVT, dl,
2367 OpsHi, MMO, IndexTy, ExtType);
2368 } else {
2369 auto *VPGT = cast<VPGatherSDNode>(N);
2370 SDValue EVLLo, EVLHi;
2371 std::tie(EVLLo, EVLHi) =
2372 DAG.SplitEVL(VPGT->getVectorLength(), MemoryVT, dl);
2373
2374 SDValue OpsLo[] = {Ch, Ptr, IndexLo, Ops.Scale, MaskLo, EVLLo};
2375 Lo = DAG.getGatherVP(DAG.getVTList(LoVT, MVT::Other), LoMemVT, dl, OpsLo,
2376 MMO, VPGT->getIndexType());
2377
2378 SDValue OpsHi[] = {Ch, Ptr, IndexHi, Ops.Scale, MaskHi, EVLHi};
2379 Hi = DAG.getGatherVP(DAG.getVTList(HiVT, MVT::Other), HiMemVT, dl, OpsHi,
2380 MMO, VPGT->getIndexType());
2381 }
2382
2383 // Build a factor node to remember that this load is independent of the
2384 // other one.
2385 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2386 Hi.getValue(1));
2387
2388 // Legalize the chain result - switch anything that used the old chain to
2389 // use the new one.
2390 ReplaceValueWith(SDValue(N, 1), Ch);
2391}
2392
2393void DAGTypeLegalizer::SplitVecRes_SETCC(SDNode *N, SDValue &Lo, SDValue &Hi) {
2394 assert(N->getValueType(0).isVector() &&
2395 N->getOperand(0).getValueType().isVector() &&
2396 "Operand types must be vectors");
2397
2398 EVT LoVT, HiVT;
2399 SDLoc DL(N);
2400 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2401
2402 // If the input also splits, handle it directly. Otherwise split it by hand.
2403 SDValue LL, LH, RL, RH;
2404 if (getTypeAction(N->getOperand(0).getValueType()) ==
2406 GetSplitVector(N->getOperand(0), LL, LH);
2407 else
2408 std::tie(LL, LH) = DAG.SplitVectorOperand(N, 0);
2409
2410 if (getTypeAction(N->getOperand(1).getValueType()) ==
2412 GetSplitVector(N->getOperand(1), RL, RH);
2413 else
2414 std::tie(RL, RH) = DAG.SplitVectorOperand(N, 1);
2415
2416 if (N->getOpcode() == ISD::SETCC) {
2417 Lo = DAG.getNode(N->getOpcode(), DL, LoVT, LL, RL, N->getOperand(2));
2418 Hi = DAG.getNode(N->getOpcode(), DL, HiVT, LH, RH, N->getOperand(2));
2419 } else {
2420 assert(N->getOpcode() == ISD::VP_SETCC && "Expected VP_SETCC opcode");
2421 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
2422 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(3));
2423 std::tie(EVLLo, EVLHi) =
2424 DAG.SplitEVL(N->getOperand(4), N->getValueType(0), DL);
2425 Lo = DAG.getNode(N->getOpcode(), DL, LoVT, LL, RL, N->getOperand(2), MaskLo,
2426 EVLLo);
2427 Hi = DAG.getNode(N->getOpcode(), DL, HiVT, LH, RH, N->getOperand(2), MaskHi,
2428 EVLHi);
2429 }
2430}
2431
2432void DAGTypeLegalizer::SplitVecRes_UnaryOp(SDNode *N, SDValue &Lo,
2433 SDValue &Hi) {
2434 // Get the dest types - they may not match the input types, e.g. int_to_fp.
2435 EVT LoVT, HiVT;
2436 SDLoc dl(N);
2437 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2438
2439 // If the input also splits, handle it directly for a compile time speedup.
2440 // Otherwise split it by hand.
2441 EVT InVT = N->getOperand(0).getValueType();
2442 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
2443 GetSplitVector(N->getOperand(0), Lo, Hi);
2444 else
2445 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
2446
2447 const SDNodeFlags Flags = N->getFlags();
2448 unsigned Opcode = N->getOpcode();
2449 if (N->getNumOperands() <= 2) {
2450 if (Opcode == ISD::FP_ROUND) {
2451 Lo = DAG.getNode(Opcode, dl, LoVT, Lo, N->getOperand(1), Flags);
2452 Hi = DAG.getNode(Opcode, dl, HiVT, Hi, N->getOperand(1), Flags);
2453 } else {
2454 Lo = DAG.getNode(Opcode, dl, LoVT, Lo, Flags);
2455 Hi = DAG.getNode(Opcode, dl, HiVT, Hi, Flags);
2456 }
2457 return;
2458 }
2459
2460 assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
2461 assert(N->isVPOpcode() && "Expected VP opcode");
2462
2463 SDValue MaskLo, MaskHi;
2464 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
2465
2466 SDValue EVLLo, EVLHi;
2467 std::tie(EVLLo, EVLHi) =
2468 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), dl);
2469
2470 Lo = DAG.getNode(Opcode, dl, LoVT, {Lo, MaskLo, EVLLo}, Flags);
2471 Hi = DAG.getNode(Opcode, dl, HiVT, {Hi, MaskHi, EVLHi}, Flags);
2472}
2473
2474void DAGTypeLegalizer::SplitVecRes_ADDRSPACECAST(SDNode *N, SDValue &Lo,
2475 SDValue &Hi) {
2476 SDLoc dl(N);
2477 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(N->getValueType(0));
2478
2479 // If the input also splits, handle it directly for a compile time speedup.
2480 // Otherwise split it by hand.
2481 EVT InVT = N->getOperand(0).getValueType();
2482 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
2483 GetSplitVector(N->getOperand(0), Lo, Hi);
2484 else
2485 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
2486
2487 auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
2488 unsigned SrcAS = AddrSpaceCastN->getSrcAddressSpace();
2489 unsigned DestAS = AddrSpaceCastN->getDestAddressSpace();
2490 Lo = DAG.getAddrSpaceCast(dl, LoVT, Lo, SrcAS, DestAS);
2491 Hi = DAG.getAddrSpaceCast(dl, HiVT, Hi, SrcAS, DestAS);
2492}
2493
2494void DAGTypeLegalizer::SplitVecRes_FFREXP(SDNode *N, unsigned ResNo,
2495 SDValue &Lo, SDValue &Hi) {
2496 SDLoc dl(N);
2497 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(N->getValueType(0));
2498 auto [LoVT1, HiVT1] = DAG.GetSplitDestVTs(N->getValueType(1));
2499
2500 // If the input also splits, handle it directly for a compile time speedup.
2501 // Otherwise split it by hand.
2502 EVT InVT = N->getOperand(0).getValueType();
2503 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
2504 GetSplitVector(N->getOperand(0), Lo, Hi);
2505 else
2506 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
2507
2508 Lo = DAG.getNode(N->getOpcode(), dl, {LoVT, LoVT1}, Lo);
2509 Hi = DAG.getNode(N->getOpcode(), dl, {HiVT, HiVT1}, Hi);
2510 Lo->setFlags(N->getFlags());
2511 Hi->setFlags(N->getFlags());
2512
2513 SDNode *HiNode = Hi.getNode();
2514 SDNode *LoNode = Lo.getNode();
2515
2516 // Replace the other vector result not being explicitly split here.
2517 unsigned OtherNo = 1 - ResNo;
2518 EVT OtherVT = N->getValueType(OtherNo);
2519 if (getTypeAction(OtherVT) == TargetLowering::TypeSplitVector) {
2520 SetSplitVector(SDValue(N, OtherNo), SDValue(LoNode, OtherNo),
2521 SDValue(HiNode, OtherNo));
2522 } else {
2523 SDValue OtherVal =
2524 DAG.getNode(ISD::CONCAT_VECTORS, dl, OtherVT, SDValue(LoNode, OtherNo),
2525 SDValue(HiNode, OtherNo));
2526 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
2527 }
2528}
2529
2530void DAGTypeLegalizer::SplitVecRes_ExtendOp(SDNode *N, SDValue &Lo,
2531 SDValue &Hi) {
2532 SDLoc dl(N);
2533 EVT SrcVT = N->getOperand(0).getValueType();
2534 EVT DestVT = N->getValueType(0);
2535 EVT LoVT, HiVT;
2536 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(DestVT);
2537
2538 // We can do better than a generic split operation if the extend is doing
2539 // more than just doubling the width of the elements and the following are
2540 // true:
2541 // - The number of vector elements is even,
2542 // - the source type is legal,
2543 // - the type of a split source is illegal,
2544 // - the type of an extended (by doubling element size) source is legal, and
2545 // - the type of that extended source when split is legal.
2546 //
2547 // This won't necessarily completely legalize the operation, but it will
2548 // more effectively move in the right direction and prevent falling down
2549 // to scalarization in many cases due to the input vector being split too
2550 // far.
2551 if (SrcVT.getVectorElementCount().isKnownEven() &&
2552 SrcVT.getScalarSizeInBits() * 2 < DestVT.getScalarSizeInBits()) {
2553 LLVMContext &Ctx = *DAG.getContext();
2554 EVT NewSrcVT = SrcVT.widenIntegerVectorElementType(Ctx);
2555 EVT SplitSrcVT = SrcVT.getHalfNumVectorElementsVT(Ctx);
2556
2557 EVT SplitLoVT, SplitHiVT;
2558 std::tie(SplitLoVT, SplitHiVT) = DAG.GetSplitDestVTs(NewSrcVT);
2559 if (TLI.isTypeLegal(SrcVT) && !TLI.isTypeLegal(SplitSrcVT) &&
2560 TLI.isTypeLegal(NewSrcVT) && TLI.isTypeLegal(SplitLoVT)) {
2561 LLVM_DEBUG(dbgs() << "Split vector extend via incremental extend:";
2562 N->dump(&DAG); dbgs() << "\n");
2563 if (!N->isVPOpcode()) {
2564 // Extend the source vector by one step.
2565 SDValue NewSrc =
2566 DAG.getNode(N->getOpcode(), dl, NewSrcVT, N->getOperand(0));
2567 // Get the low and high halves of the new, extended one step, vector.
2568 std::tie(Lo, Hi) = DAG.SplitVector(NewSrc, dl);
2569 // Extend those vector halves the rest of the way.
2570 Lo = DAG.getNode(N->getOpcode(), dl, LoVT, Lo);
2571 Hi = DAG.getNode(N->getOpcode(), dl, HiVT, Hi);
2572 return;
2573 }
2574
2575 // Extend the source vector by one step.
2576 SDValue NewSrc =
2577 DAG.getNode(N->getOpcode(), dl, NewSrcVT, N->getOperand(0),
2578 N->getOperand(1), N->getOperand(2));
2579 // Get the low and high halves of the new, extended one step, vector.
2580 std::tie(Lo, Hi) = DAG.SplitVector(NewSrc, dl);
2581
2582 SDValue MaskLo, MaskHi;
2583 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
2584
2585 SDValue EVLLo, EVLHi;
2586 std::tie(EVLLo, EVLHi) =
2587 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), dl);
2588 // Extend those vector halves the rest of the way.
2589 Lo = DAG.getNode(N->getOpcode(), dl, LoVT, {Lo, MaskLo, EVLLo});
2590 Hi = DAG.getNode(N->getOpcode(), dl, HiVT, {Hi, MaskHi, EVLHi});
2591 return;
2592 }
2593 }
2594 // Fall back to the generic unary operator splitting otherwise.
2595 SplitVecRes_UnaryOp(N, Lo, Hi);
2596}
2597
2598void DAGTypeLegalizer::SplitVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N,
2599 SDValue &Lo, SDValue &Hi) {
2600 // The low and high parts of the original input give four input vectors.
2601 SDValue Inputs[4];
2602 SDLoc DL(N);
2603 GetSplitVector(N->getOperand(0), Inputs[0], Inputs[1]);
2604 GetSplitVector(N->getOperand(1), Inputs[2], Inputs[3]);
2605 EVT NewVT = Inputs[0].getValueType();
2606 unsigned NewElts = NewVT.getVectorNumElements();
2607
2608 auto &&IsConstant = [](const SDValue &N) {
2609 APInt SplatValue;
2610 return N.getResNo() == 0 &&
2611 (ISD::isConstantSplatVector(N.getNode(), SplatValue) ||
2613 };
2614 auto &&BuildVector = [NewElts, &DAG = DAG, NewVT, &DL](SDValue &Input1,
2615 SDValue &Input2,
2617 assert(Input1->getOpcode() == ISD::BUILD_VECTOR &&
2618 Input2->getOpcode() == ISD::BUILD_VECTOR &&
2619 "Expected build vector node.");
2620 EVT EltVT = NewVT.getVectorElementType();
2621 SmallVector<SDValue> Ops(NewElts, DAG.getUNDEF(EltVT));
2622 for (unsigned I = 0; I < NewElts; ++I) {
2623 if (Mask[I] == PoisonMaskElem)
2624 continue;
2625 unsigned Idx = Mask[I];
2626 if (Idx >= NewElts)
2627 Ops[I] = Input2.getOperand(Idx - NewElts);
2628 else
2629 Ops[I] = Input1.getOperand(Idx);
2630 // Make the type of all elements the same as the element type.
2631 if (Ops[I].getValueType().bitsGT(EltVT))
2632 Ops[I] = DAG.getNode(ISD::TRUNCATE, DL, EltVT, Ops[I]);
2633 }
2634 return DAG.getBuildVector(NewVT, DL, Ops);
2635 };
2636
2637 // If Lo or Hi uses elements from at most two of the four input vectors, then
2638 // express it as a vector shuffle of those two inputs. Otherwise extract the
2639 // input elements by hand and construct the Lo/Hi output using a BUILD_VECTOR.
2640 SmallVector<int> OrigMask(N->getMask());
2641 // Try to pack incoming shuffles/inputs.
2642 auto &&TryPeekThroughShufflesInputs = [&Inputs, &NewVT, this, NewElts,
2644 // Check if all inputs are shuffles of the same operands or non-shuffles.
2646 for (unsigned Idx = 0; Idx < std::size(Inputs); ++Idx) {
2647 SDValue Input = Inputs[Idx];
2648 auto *Shuffle = dyn_cast<ShuffleVectorSDNode>(Input.getNode());
2649 if (!Shuffle ||
2650 Input.getOperand(0).getValueType() != Input.getValueType())
2651 continue;
2652 ShufflesIdxs[std::make_pair(Input.getOperand(0), Input.getOperand(1))]
2653 .push_back(Idx);
2654 ShufflesIdxs[std::make_pair(Input.getOperand(1), Input.getOperand(0))]
2655 .push_back(Idx);
2656 }
2657 for (auto &P : ShufflesIdxs) {
2658 if (P.second.size() < 2)
2659 continue;
2660 // Use shuffles operands instead of shuffles themselves.
2661 // 1. Adjust mask.
2662 for (int &Idx : Mask) {
2663 if (Idx == PoisonMaskElem)
2664 continue;
2665 unsigned SrcRegIdx = Idx / NewElts;
2666 if (Inputs[SrcRegIdx].isUndef()) {
2668 continue;
2669 }
2670 auto *Shuffle =
2671 dyn_cast<ShuffleVectorSDNode>(Inputs[SrcRegIdx].getNode());
2672 if (!Shuffle || !is_contained(P.second, SrcRegIdx))
2673 continue;
2674 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
2675 if (MaskElt == PoisonMaskElem) {
2677 continue;
2678 }
2679 Idx = MaskElt % NewElts +
2680 P.second[Shuffle->getOperand(MaskElt / NewElts) == P.first.first
2681 ? 0
2682 : 1] *
2683 NewElts;
2684 }
2685 // 2. Update inputs.
2686 Inputs[P.second[0]] = P.first.first;
2687 Inputs[P.second[1]] = P.first.second;
2688 // Clear the pair data.
2689 P.second.clear();
2690 ShufflesIdxs[std::make_pair(P.first.second, P.first.first)].clear();
2691 }
2692 // Check if any concat_vectors can be simplified.
2693 SmallBitVector UsedSubVector(2 * std::size(Inputs));
2694 for (int &Idx : Mask) {
2695 if (Idx == PoisonMaskElem)
2696 continue;
2697 unsigned SrcRegIdx = Idx / NewElts;
2698 if (Inputs[SrcRegIdx].isUndef()) {
2700 continue;
2701 }
2703 getTypeAction(Inputs[SrcRegIdx].getValueType());
2704 if (Inputs[SrcRegIdx].getOpcode() == ISD::CONCAT_VECTORS &&
2705 Inputs[SrcRegIdx].getNumOperands() == 2 &&
2706 !Inputs[SrcRegIdx].getOperand(1).isUndef() &&
2707 (TypeAction == TargetLowering::TypeLegal ||
2708 TypeAction == TargetLowering::TypeWidenVector))
2709 UsedSubVector.set(2 * SrcRegIdx + (Idx % NewElts) / (NewElts / 2));
2710 }
2711 if (UsedSubVector.count() > 1) {
2713 for (unsigned I = 0; I < std::size(Inputs); ++I) {
2714 if (UsedSubVector.test(2 * I) == UsedSubVector.test(2 * I + 1))
2715 continue;
2716 if (Pairs.empty() || Pairs.back().size() == 2)
2717 Pairs.emplace_back();
2718 if (UsedSubVector.test(2 * I)) {
2719 Pairs.back().emplace_back(I, 0);
2720 } else {
2721 assert(UsedSubVector.test(2 * I + 1) &&
2722 "Expected to be used one of the subvectors.");
2723 Pairs.back().emplace_back(I, 1);
2724 }
2725 }
2726 if (!Pairs.empty() && Pairs.front().size() > 1) {
2727 // Adjust mask.
2728 for (int &Idx : Mask) {
2729 if (Idx == PoisonMaskElem)
2730 continue;
2731 unsigned SrcRegIdx = Idx / NewElts;
2732 auto *It = find_if(
2733 Pairs, [SrcRegIdx](ArrayRef<std::pair<unsigned, int>> Idxs) {
2734 return Idxs.front().first == SrcRegIdx ||
2735 Idxs.back().first == SrcRegIdx;
2736 });
2737 if (It == Pairs.end())
2738 continue;
2739 Idx = It->front().first * NewElts + (Idx % NewElts) % (NewElts / 2) +
2740 (SrcRegIdx == It->front().first ? 0 : (NewElts / 2));
2741 }
2742 // Adjust inputs.
2743 for (ArrayRef<std::pair<unsigned, int>> Idxs : Pairs) {
2744 Inputs[Idxs.front().first] = DAG.getNode(
2746 Inputs[Idxs.front().first].getValueType(),
2747 Inputs[Idxs.front().first].getOperand(Idxs.front().second),
2748 Inputs[Idxs.back().first].getOperand(Idxs.back().second));
2749 }
2750 }
2751 }
2752 bool Changed;
2753 do {
2754 // Try to remove extra shuffles (except broadcasts) and shuffles with the
2755 // reused operands.
2756 Changed = false;
2757 for (unsigned I = 0; I < std::size(Inputs); ++I) {
2758 auto *Shuffle = dyn_cast<ShuffleVectorSDNode>(Inputs[I].getNode());
2759 if (!Shuffle)
2760 continue;
2761 if (Shuffle->getOperand(0).getValueType() != NewVT)
2762 continue;
2763 int Op = -1;
2764 if (!Inputs[I].hasOneUse() && Shuffle->getOperand(1).isUndef() &&
2765 !Shuffle->isSplat()) {
2766 Op = 0;
2767 } else if (!Inputs[I].hasOneUse() &&
2768 !Shuffle->getOperand(1).isUndef()) {
2769 // Find the only used operand, if possible.
2770 for (int &Idx : Mask) {
2771 if (Idx == PoisonMaskElem)
2772 continue;
2773 unsigned SrcRegIdx = Idx / NewElts;
2774 if (SrcRegIdx != I)
2775 continue;
2776 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
2777 if (MaskElt == PoisonMaskElem) {
2779 continue;
2780 }
2781 int OpIdx = MaskElt / NewElts;
2782 if (Op == -1) {
2783 Op = OpIdx;
2784 continue;
2785 }
2786 if (Op != OpIdx) {
2787 Op = -1;
2788 break;
2789 }
2790 }
2791 }
2792 if (Op < 0) {
2793 // Try to check if one of the shuffle operands is used already.
2794 for (int OpIdx = 0; OpIdx < 2; ++OpIdx) {
2795 if (Shuffle->getOperand(OpIdx).isUndef())
2796 continue;
2797 auto *It = find(Inputs, Shuffle->getOperand(OpIdx));
2798 if (It == std::end(Inputs))
2799 continue;
2800 int FoundOp = std::distance(std::begin(Inputs), It);
2801 // Found that operand is used already.
2802 // 1. Fix the mask for the reused operand.
2803 for (int &Idx : Mask) {
2804 if (Idx == PoisonMaskElem)
2805 continue;
2806 unsigned SrcRegIdx = Idx / NewElts;
2807 if (SrcRegIdx != I)
2808 continue;
2809 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
2810 if (MaskElt == PoisonMaskElem) {
2812 continue;
2813 }
2814 int MaskIdx = MaskElt / NewElts;
2815 if (OpIdx == MaskIdx)
2816 Idx = MaskElt % NewElts + FoundOp * NewElts;
2817 }
2818 // 2. Set Op to the unused OpIdx.
2819 Op = (OpIdx + 1) % 2;
2820 break;
2821 }
2822 }
2823 if (Op >= 0) {
2824 Changed = true;
2825 Inputs[I] = Shuffle->getOperand(Op);
2826 // Adjust mask.
2827 for (int &Idx : Mask) {
2828 if (Idx == PoisonMaskElem)
2829 continue;
2830 unsigned SrcRegIdx = Idx / NewElts;
2831 if (SrcRegIdx != I)
2832 continue;
2833 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
2834 int OpIdx = MaskElt / NewElts;
2835 if (OpIdx != Op)
2836 continue;
2837 Idx = MaskElt % NewElts + SrcRegIdx * NewElts;
2838 }
2839 }
2840 }
2841 } while (Changed);
2842 };
2843 TryPeekThroughShufflesInputs(OrigMask);
2844 // Proces unique inputs.
2845 auto &&MakeUniqueInputs = [&Inputs, &IsConstant,
2846 NewElts](SmallVectorImpl<int> &Mask) {
2847 SetVector<SDValue> UniqueInputs;
2848 SetVector<SDValue> UniqueConstantInputs;
2849 for (const auto &I : Inputs) {
2850 if (IsConstant(I))
2851 UniqueConstantInputs.insert(I);
2852 else if (!I.isUndef())
2853 UniqueInputs.insert(I);
2854 }
2855 // Adjust mask in case of reused inputs. Also, need to insert constant
2856 // inputs at first, otherwise it affects the final outcome.
2857 if (UniqueInputs.size() != std::size(Inputs)) {
2858 auto &&UniqueVec = UniqueInputs.takeVector();
2859 auto &&UniqueConstantVec = UniqueConstantInputs.takeVector();
2860 unsigned ConstNum = UniqueConstantVec.size();
2861 for (int &Idx : Mask) {
2862 if (Idx == PoisonMaskElem)
2863 continue;
2864 unsigned SrcRegIdx = Idx / NewElts;
2865 if (Inputs[SrcRegIdx].isUndef()) {
2867 continue;
2868 }
2869 const auto It = find(UniqueConstantVec, Inputs[SrcRegIdx]);
2870 if (It != UniqueConstantVec.end()) {
2871 Idx = (Idx % NewElts) +
2872 NewElts * std::distance(UniqueConstantVec.begin(), It);
2873 assert(Idx >= 0 && "Expected defined mask idx.");
2874 continue;
2875 }
2876 const auto RegIt = find(UniqueVec, Inputs[SrcRegIdx]);
2877 assert(RegIt != UniqueVec.end() && "Cannot find non-const value.");
2878 Idx = (Idx % NewElts) +
2879 NewElts * (std::distance(UniqueVec.begin(), RegIt) + ConstNum);
2880 assert(Idx >= 0 && "Expected defined mask idx.");
2881 }
2882 copy(UniqueConstantVec, std::begin(Inputs));
2883 copy(UniqueVec, std::next(std::begin(Inputs), ConstNum));
2884 }
2885 };
2886 MakeUniqueInputs(OrigMask);
2887 SDValue OrigInputs[4];
2888 copy(Inputs, std::begin(OrigInputs));
2889 for (unsigned High = 0; High < 2; ++High) {
2890 SDValue &Output = High ? Hi : Lo;
2891
2892 // Build a shuffle mask for the output, discovering on the fly which
2893 // input vectors to use as shuffle operands.
2894 unsigned FirstMaskIdx = High * NewElts;
2895 SmallVector<int> Mask(NewElts * std::size(Inputs), PoisonMaskElem);
2896 copy(ArrayRef(OrigMask).slice(FirstMaskIdx, NewElts), Mask.begin());
2897 assert(!Output && "Expected default initialized initial value.");
2898 TryPeekThroughShufflesInputs(Mask);
2899 MakeUniqueInputs(Mask);
2900 SDValue TmpInputs[4];
2901 copy(Inputs, std::begin(TmpInputs));
2902 // Track changes in the output registers.
2903 int UsedIdx = -1;
2904 bool SecondIteration = false;
2905 auto &&AccumulateResults = [&UsedIdx, &SecondIteration](unsigned Idx) {
2906 if (UsedIdx < 0) {
2907 UsedIdx = Idx;
2908 return false;
2909 }
2910 if (UsedIdx >= 0 && static_cast<unsigned>(UsedIdx) == Idx)
2911 SecondIteration = true;
2912 return SecondIteration;
2913 };
2915 Mask, std::size(Inputs), std::size(Inputs),
2916 /*NumOfUsedRegs=*/1,
2917 [&Output, &DAG = DAG, NewVT]() { Output = DAG.getUNDEF(NewVT); },
2918 [&Output, &DAG = DAG, NewVT, &DL, &Inputs,
2919 &BuildVector](ArrayRef<int> Mask, unsigned Idx, unsigned /*Unused*/) {
2920 if (Inputs[Idx]->getOpcode() == ISD::BUILD_VECTOR)
2921 Output = BuildVector(Inputs[Idx], Inputs[Idx], Mask);
2922 else
2923 Output = DAG.getVectorShuffle(NewVT, DL, Inputs[Idx],
2924 DAG.getUNDEF(NewVT), Mask);
2925 Inputs[Idx] = Output;
2926 },
2927 [&AccumulateResults, &Output, &DAG = DAG, NewVT, &DL, &Inputs,
2928 &TmpInputs,
2929 &BuildVector](ArrayRef<int> Mask, unsigned Idx1, unsigned Idx2) {
2930 if (AccumulateResults(Idx1)) {
2931 if (Inputs[Idx1]->getOpcode() == ISD::BUILD_VECTOR &&
2932 Inputs[Idx2]->getOpcode() == ISD::BUILD_VECTOR)
2933 Output = BuildVector(Inputs[Idx1], Inputs[Idx2], Mask);
2934 else
2935 Output = DAG.getVectorShuffle(NewVT, DL, Inputs[Idx1],
2936 Inputs[Idx2], Mask);
2937 } else {
2938 if (TmpInputs[Idx1]->getOpcode() == ISD::BUILD_VECTOR &&
2939 TmpInputs[Idx2]->getOpcode() == ISD::BUILD_VECTOR)
2940 Output = BuildVector(TmpInputs[Idx1], TmpInputs[Idx2], Mask);
2941 else
2942 Output = DAG.getVectorShuffle(NewVT, DL, TmpInputs[Idx1],
2943 TmpInputs[Idx2], Mask);
2944 }
2945 Inputs[Idx1] = Output;
2946 });
2947 copy(OrigInputs, std::begin(Inputs));
2948 }
2949}
2950
2951void DAGTypeLegalizer::SplitVecRes_VAARG(SDNode *N, SDValue &Lo, SDValue &Hi) {
2952 EVT OVT = N->getValueType(0);
2953 EVT NVT = OVT.getHalfNumVectorElementsVT(*DAG.getContext());
2954 SDValue Chain = N->getOperand(0);
2955 SDValue Ptr = N->getOperand(1);
2956 SDValue SV = N->getOperand(2);
2957 SDLoc dl(N);
2958
2959 const Align Alignment =
2960 DAG.getDataLayout().getABITypeAlign(NVT.getTypeForEVT(*DAG.getContext()));
2961
2962 Lo = DAG.getVAArg(NVT, dl, Chain, Ptr, SV, Alignment.value());
2963 Hi = DAG.getVAArg(NVT, dl, Lo.getValue(1), Ptr, SV, Alignment.value());
2964 Chain = Hi.getValue(1);
2965
2966 // Modified the chain - switch anything that used the old chain to use
2967 // the new one.
2968 ReplaceValueWith(SDValue(N, 1), Chain);
2969}
2970
2971void DAGTypeLegalizer::SplitVecRes_FP_TO_XINT_SAT(SDNode *N, SDValue &Lo,
2972 SDValue &Hi) {
2973 EVT DstVTLo, DstVTHi;
2974 std::tie(DstVTLo, DstVTHi) = DAG.GetSplitDestVTs(N->getValueType(0));
2975 SDLoc dl(N);
2976
2977 SDValue SrcLo, SrcHi;
2978 EVT SrcVT = N->getOperand(0).getValueType();
2979 if (getTypeAction(SrcVT) == TargetLowering::TypeSplitVector)
2980 GetSplitVector(N->getOperand(0), SrcLo, SrcHi);
2981 else
2982 std::tie(SrcLo, SrcHi) = DAG.SplitVectorOperand(N, 0);
2983
2984 Lo = DAG.getNode(N->getOpcode(), dl, DstVTLo, SrcLo, N->getOperand(1));
2985 Hi = DAG.getNode(N->getOpcode(), dl, DstVTHi, SrcHi, N->getOperand(1));
2986}
2987
2988void DAGTypeLegalizer::SplitVecRes_VECTOR_REVERSE(SDNode *N, SDValue &Lo,
2989 SDValue &Hi) {
2990 SDValue InLo, InHi;
2991 GetSplitVector(N->getOperand(0), InLo, InHi);
2992 SDLoc DL(N);
2993
2994 Lo = DAG.getNode(ISD::VECTOR_REVERSE, DL, InHi.getValueType(), InHi);
2995 Hi = DAG.getNode(ISD::VECTOR_REVERSE, DL, InLo.getValueType(), InLo);
2996}
2997
2998void DAGTypeLegalizer::SplitVecRes_VECTOR_SPLICE(SDNode *N, SDValue &Lo,
2999 SDValue &Hi) {
3000 SDLoc DL(N);
3001
3002 SDValue Expanded = TLI.expandVectorSplice(N, DAG);
3003 std::tie(Lo, Hi) = DAG.SplitVector(Expanded, DL);
3004}
3005
3006void DAGTypeLegalizer::SplitVecRes_VP_REVERSE(SDNode *N, SDValue &Lo,
3007 SDValue &Hi) {
3008 EVT VT = N->getValueType(0);
3009 SDValue Val = N->getOperand(0);
3010 SDValue Mask = N->getOperand(1);
3011 SDValue EVL = N->getOperand(2);
3012 SDLoc DL(N);
3013
3014 // Fallback to VP_STRIDED_STORE to stack followed by VP_LOAD.
3015 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
3016
3017 EVT MemVT = EVT::getVectorVT(*DAG.getContext(), VT.getVectorElementType(),
3019 SDValue StackPtr = DAG.CreateStackTemporary(MemVT.getStoreSize(), Alignment);
3020 EVT PtrVT = StackPtr.getValueType();
3021 auto &MF = DAG.getMachineFunction();
3022 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
3023 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
3024
3025 MachineMemOperand *StoreMMO = DAG.getMachineFunction().getMachineMemOperand(
3027 Alignment);
3028 MachineMemOperand *LoadMMO = DAG.getMachineFunction().getMachineMemOperand(
3030 Alignment);
3031
3032 unsigned EltWidth = VT.getScalarSizeInBits() / 8;
3033 SDValue NumElemMinus1 =
3034 DAG.getNode(ISD::SUB, DL, PtrVT, DAG.getZExtOrTrunc(EVL, DL, PtrVT),
3035 DAG.getConstant(1, DL, PtrVT));
3036 SDValue StartOffset = DAG.getNode(ISD::MUL, DL, PtrVT, NumElemMinus1,
3037 DAG.getConstant(EltWidth, DL, PtrVT));
3038 SDValue StorePtr = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, StartOffset);
3039 SDValue Stride = DAG.getConstant(-(int64_t)EltWidth, DL, PtrVT);
3040
3041 SDValue TrueMask = DAG.getBoolConstant(true, DL, Mask.getValueType(), VT);
3042 SDValue Store = DAG.getStridedStoreVP(DAG.getEntryNode(), DL, Val, StorePtr,
3043 DAG.getUNDEF(PtrVT), Stride, TrueMask,
3044 EVL, MemVT, StoreMMO, ISD::UNINDEXED);
3045
3046 SDValue Load = DAG.getLoadVP(VT, DL, Store, StackPtr, Mask, EVL, LoadMMO);
3047
3048 std::tie(Lo, Hi) = DAG.SplitVector(Load, DL);
3049}
3050
3051void DAGTypeLegalizer::SplitVecRes_VECTOR_DEINTERLEAVE(SDNode *N) {
3052
3053 SDValue Op0Lo, Op0Hi, Op1Lo, Op1Hi;
3054 GetSplitVector(N->getOperand(0), Op0Lo, Op0Hi);
3055 GetSplitVector(N->getOperand(1), Op1Lo, Op1Hi);
3056 EVT VT = Op0Lo.getValueType();
3057 SDLoc DL(N);
3059 DAG.getVTList(VT, VT), Op0Lo, Op0Hi);
3061 DAG.getVTList(VT, VT), Op1Lo, Op1Hi);
3062
3063 SetSplitVector(SDValue(N, 0), ResLo.getValue(0), ResHi.getValue(0));
3064 SetSplitVector(SDValue(N, 1), ResLo.getValue(1), ResHi.getValue(1));
3065}
3066
3067void DAGTypeLegalizer::SplitVecRes_VECTOR_INTERLEAVE(SDNode *N) {
3068 SDValue Op0Lo, Op0Hi, Op1Lo, Op1Hi;
3069 GetSplitVector(N->getOperand(0), Op0Lo, Op0Hi);
3070 GetSplitVector(N->getOperand(1), Op1Lo, Op1Hi);
3071 EVT VT = Op0Lo.getValueType();
3072 SDLoc DL(N);
3074 DAG.getVTList(VT, VT), Op0Lo, Op1Lo),
3075 DAG.getNode(ISD::VECTOR_INTERLEAVE, DL,
3076 DAG.getVTList(VT, VT), Op0Hi, Op1Hi)};
3077
3078 SetSplitVector(SDValue(N, 0), Res[0].getValue(0), Res[0].getValue(1));
3079 SetSplitVector(SDValue(N, 1), Res[1].getValue(0), Res[1].getValue(1));
3080}
3081
3082//===----------------------------------------------------------------------===//
3083// Operand Vector Splitting
3084//===----------------------------------------------------------------------===//
3085
3086/// This method is called when the specified operand of the specified node is
3087/// found to need vector splitting. At this point, all of the result types of
3088/// the node are known to be legal, but other operands of the node may need
3089/// legalization as well as the specified one.
3090bool DAGTypeLegalizer::SplitVectorOperand(SDNode *N, unsigned OpNo) {
3091 LLVM_DEBUG(dbgs() << "Split node operand: "; N->dump(&DAG));
3092 SDValue Res = SDValue();
3093
3094 // See if the target wants to custom split this node.
3095 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
3096 return false;
3097
3098 switch (N->getOpcode()) {
3099 default:
3100#ifndef NDEBUG
3101 dbgs() << "SplitVectorOperand Op #" << OpNo << ": ";
3102 N->dump(&DAG);
3103 dbgs() << "\n";
3104#endif
3105 report_fatal_error("Do not know how to split this operator's "
3106 "operand!\n");
3107
3108 case ISD::VP_SETCC:
3109 case ISD::STRICT_FSETCC:
3110 case ISD::SETCC: Res = SplitVecOp_VSETCC(N); break;
3111 case ISD::BITCAST: Res = SplitVecOp_BITCAST(N); break;
3112 case ISD::EXTRACT_SUBVECTOR: Res = SplitVecOp_EXTRACT_SUBVECTOR(N); break;
3113 case ISD::INSERT_SUBVECTOR: Res = SplitVecOp_INSERT_SUBVECTOR(N, OpNo); break;
3114 case ISD::EXTRACT_VECTOR_ELT:Res = SplitVecOp_EXTRACT_VECTOR_ELT(N); break;
3115 case ISD::CONCAT_VECTORS: Res = SplitVecOp_CONCAT_VECTORS(N); break;
3116 case ISD::VP_TRUNCATE:
3117 case ISD::TRUNCATE:
3118 Res = SplitVecOp_TruncateHelper(N);
3119 break;
3121 case ISD::VP_FP_ROUND:
3122 case ISD::FP_ROUND: Res = SplitVecOp_FP_ROUND(N); break;
3123 case ISD::FCOPYSIGN: Res = SplitVecOp_FPOpDifferentTypes(N); break;
3124 case ISD::STORE:
3125 Res = SplitVecOp_STORE(cast<StoreSDNode>(N), OpNo);
3126 break;
3127 case ISD::VP_STORE:
3128 Res = SplitVecOp_VP_STORE(cast<VPStoreSDNode>(N), OpNo);
3129 break;
3130 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
3131 Res = SplitVecOp_VP_STRIDED_STORE(cast<VPStridedStoreSDNode>(N), OpNo);
3132 break;
3133 case ISD::MSTORE:
3134 Res = SplitVecOp_MSTORE(cast<MaskedStoreSDNode>(N), OpNo);
3135 break;
3136 case ISD::MSCATTER:
3137 case ISD::VP_SCATTER:
3138 Res = SplitVecOp_Scatter(cast<MemSDNode>(N), OpNo);
3139 break;
3140 case ISD::MGATHER:
3141 case ISD::VP_GATHER:
3142 Res = SplitVecOp_Gather(cast<MemSDNode>(N), OpNo);
3143 break;
3144 case ISD::VSELECT:
3145 Res = SplitVecOp_VSELECT(N, OpNo);
3146 break;
3149 case ISD::SINT_TO_FP:
3150 case ISD::UINT_TO_FP:
3151 case ISD::VP_SINT_TO_FP:
3152 case ISD::VP_UINT_TO_FP:
3153 if (N->getValueType(0).bitsLT(
3154 N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType()))
3155 Res = SplitVecOp_TruncateHelper(N);
3156 else
3157 Res = SplitVecOp_UnaryOp(N);
3158 break;
3161 Res = SplitVecOp_FP_TO_XINT_SAT(N);
3162 break;
3163 case ISD::FP_TO_SINT:
3164 case ISD::FP_TO_UINT:
3165 case ISD::VP_FP_TO_SINT:
3166 case ISD::VP_FP_TO_UINT:
3170 case ISD::FP_EXTEND:
3171 case ISD::SIGN_EXTEND:
3172 case ISD::ZERO_EXTEND:
3173 case ISD::ANY_EXTEND:
3174 case ISD::FTRUNC:
3175 case ISD::LRINT:
3176 case ISD::LLRINT:
3177 Res = SplitVecOp_UnaryOp(N);
3178 break;
3179 case ISD::FLDEXP:
3180 Res = SplitVecOp_FPOpDifferentTypes(N);
3181 break;
3182
3183 case ISD::SCMP:
3184 case ISD::UCMP:
3185 Res = SplitVecOp_CMP(N);
3186 break;
3187
3191 Res = SplitVecOp_ExtVecInRegOp(N);
3192 break;
3193
3196 case ISD::VECREDUCE_ADD:
3197 case ISD::VECREDUCE_MUL:
3198 case ISD::VECREDUCE_AND:
3199 case ISD::VECREDUCE_OR:
3200 case ISD::VECREDUCE_XOR:
3209 Res = SplitVecOp_VECREDUCE(N, OpNo);
3210 break;
3213 Res = SplitVecOp_VECREDUCE_SEQ(N);
3214 break;
3215 case ISD::VP_REDUCE_FADD:
3216 case ISD::VP_REDUCE_SEQ_FADD:
3217 case ISD::VP_REDUCE_FMUL:
3218 case ISD::VP_REDUCE_SEQ_FMUL:
3219 case ISD::VP_REDUCE_ADD:
3220 case ISD::VP_REDUCE_MUL:
3221 case ISD::VP_REDUCE_AND:
3222 case ISD::VP_REDUCE_OR:
3223 case ISD::VP_REDUCE_XOR:
3224 case ISD::VP_REDUCE_SMAX:
3225 case ISD::VP_REDUCE_SMIN:
3226 case ISD::VP_REDUCE_UMAX:
3227 case ISD::VP_REDUCE_UMIN:
3228 case ISD::VP_REDUCE_FMAX:
3229 case ISD::VP_REDUCE_FMIN:
3230 case ISD::VP_REDUCE_FMAXIMUM:
3231 case ISD::VP_REDUCE_FMINIMUM:
3232 Res = SplitVecOp_VP_REDUCE(N, OpNo);
3233 break;
3234 case ISD::VP_CTTZ_ELTS:
3235 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
3236 Res = SplitVecOp_VP_CttzElements(N);
3237 break;
3238 }
3239
3240 // If the result is null, the sub-method took care of registering results etc.
3241 if (!Res.getNode()) return false;
3242
3243 // If the result is N, the sub-method updated N in place. Tell the legalizer
3244 // core about this.
3245 if (Res.getNode() == N)
3246 return true;
3247
3248 if (N->isStrictFPOpcode())
3249 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
3250 "Invalid operand expansion");
3251 else
3252 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
3253 "Invalid operand expansion");
3254
3255 ReplaceValueWith(SDValue(N, 0), Res);
3256 return false;
3257}
3258
3259SDValue DAGTypeLegalizer::SplitVecOp_VSELECT(SDNode *N, unsigned OpNo) {
3260 // The only possibility for an illegal operand is the mask, since result type
3261 // legalization would have handled this node already otherwise.
3262 assert(OpNo == 0 && "Illegal operand must be mask");
3263
3264 SDValue Mask = N->getOperand(0);
3265 SDValue Src0 = N->getOperand(1);
3266 SDValue Src1 = N->getOperand(2);
3267 EVT Src0VT = Src0.getValueType();
3268 SDLoc DL(N);
3269 assert(Mask.getValueType().isVector() && "VSELECT without a vector mask?");
3270
3271 SDValue Lo, Hi;
3272 GetSplitVector(N->getOperand(0), Lo, Hi);
3273 assert(Lo.getValueType() == Hi.getValueType() &&
3274 "Lo and Hi have differing types");
3275
3276 EVT LoOpVT, HiOpVT;
3277 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(Src0VT);
3278 assert(LoOpVT == HiOpVT && "Asymmetric vector split?");
3279
3280 SDValue LoOp0, HiOp0, LoOp1, HiOp1, LoMask, HiMask;
3281 std::tie(LoOp0, HiOp0) = DAG.SplitVector(Src0, DL);
3282 std::tie(LoOp1, HiOp1) = DAG.SplitVector(Src1, DL);
3283 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
3284
3285 SDValue LoSelect =
3286 DAG.getNode(ISD::VSELECT, DL, LoOpVT, LoMask, LoOp0, LoOp1);
3287 SDValue HiSelect =
3288 DAG.getNode(ISD::VSELECT, DL, HiOpVT, HiMask, HiOp0, HiOp1);
3289
3290 return DAG.getNode(ISD::CONCAT_VECTORS, DL, Src0VT, LoSelect, HiSelect);
3291}
3292
3293SDValue DAGTypeLegalizer::SplitVecOp_VECREDUCE(SDNode *N, unsigned OpNo) {
3294 EVT ResVT = N->getValueType(0);
3295 SDValue Lo, Hi;
3296 SDLoc dl(N);
3297
3298 SDValue VecOp = N->getOperand(OpNo);
3299 EVT VecVT = VecOp.getValueType();
3300 assert(VecVT.isVector() && "Can only split reduce vector operand");
3301 GetSplitVector(VecOp, Lo, Hi);
3302 EVT LoOpVT, HiOpVT;
3303 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(VecVT);
3304
3305 // Use the appropriate scalar instruction on the split subvectors before
3306 // reducing the now partially reduced smaller vector.
3307 unsigned CombineOpc = ISD::getVecReduceBaseOpcode(N->getOpcode());
3308 SDValue Partial = DAG.getNode(CombineOpc, dl, LoOpVT, Lo, Hi, N->getFlags());
3309 return DAG.getNode(N->getOpcode(), dl, ResVT, Partial, N->getFlags());
3310}
3311
3312SDValue DAGTypeLegalizer::SplitVecOp_VECREDUCE_SEQ(SDNode *N) {
3313 EVT ResVT = N->getValueType(0);
3314 SDValue Lo, Hi;
3315 SDLoc dl(N);
3316
3317 SDValue AccOp = N->getOperand(0);
3318 SDValue VecOp = N->getOperand(1);
3319 SDNodeFlags Flags = N->getFlags();
3320
3321 EVT VecVT = VecOp.getValueType();
3322 assert(VecVT.isVector() && "Can only split reduce vector operand");
3323 GetSplitVector(VecOp, Lo, Hi);
3324 EVT LoOpVT, HiOpVT;
3325 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(VecVT);
3326
3327 // Reduce low half.
3328 SDValue Partial = DAG.getNode(N->getOpcode(), dl, ResVT, AccOp, Lo, Flags);
3329
3330 // Reduce high half, using low half result as initial value.
3331 return DAG.getNode(N->getOpcode(), dl, ResVT, Partial, Hi, Flags);
3332}
3333
3334SDValue DAGTypeLegalizer::SplitVecOp_VP_REDUCE(SDNode *N, unsigned OpNo) {
3335 assert(N->isVPOpcode() && "Expected VP opcode");
3336 assert(OpNo == 1 && "Can only split reduce vector operand");
3337
3338 unsigned Opc = N->getOpcode();
3339 EVT ResVT = N->getValueType(0);
3340 SDValue Lo, Hi;
3341 SDLoc dl(N);
3342
3343 SDValue VecOp = N->getOperand(OpNo);
3344 EVT VecVT = VecOp.getValueType();
3345 assert(VecVT.isVector() && "Can only split reduce vector operand");
3346 GetSplitVector(VecOp, Lo, Hi);
3347
3348 SDValue MaskLo, MaskHi;
3349 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(2));
3350
3351 SDValue EVLLo, EVLHi;
3352 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(N->getOperand(3), VecVT, dl);
3353
3354 const SDNodeFlags Flags = N->getFlags();
3355
3356 SDValue ResLo =
3357 DAG.getNode(Opc, dl, ResVT, {N->getOperand(0), Lo, MaskLo, EVLLo}, Flags);
3358 return DAG.getNode(Opc, dl, ResVT, {ResLo, Hi, MaskHi, EVLHi}, Flags);
3359}
3360
3361SDValue DAGTypeLegalizer::SplitVecOp_UnaryOp(SDNode *N) {
3362 // The result has a legal vector type, but the input needs splitting.
3363 EVT ResVT = N->getValueType(0);
3364 SDValue Lo, Hi;
3365 SDLoc dl(N);
3366 GetSplitVector(N->getOperand(N->isStrictFPOpcode() ? 1 : 0), Lo, Hi);
3367 EVT InVT = Lo.getValueType();
3368
3369 EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
3370 InVT.getVectorElementCount());
3371
3372 if (N->isStrictFPOpcode()) {
3373 Lo = DAG.getNode(N->getOpcode(), dl, { OutVT, MVT::Other },
3374 { N->getOperand(0), Lo });
3375 Hi = DAG.getNode(N->getOpcode(), dl, { OutVT, MVT::Other },
3376 { N->getOperand(0), Hi });
3377
3378 // Build a factor node to remember that this operation is independent
3379 // of the other one.
3380 SDValue Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
3381 Hi.getValue(1));
3382
3383 // Legalize the chain result - switch anything that used the old chain to
3384 // use the new one.
3385 ReplaceValueWith(SDValue(N, 1), Ch);
3386 } else if (N->getNumOperands() == 3) {
3387 assert(N->isVPOpcode() && "Expected VP opcode");
3388 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
3389 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
3390 std::tie(EVLLo, EVLHi) =
3391 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), dl);
3392 Lo = DAG.getNode(N->getOpcode(), dl, OutVT, Lo, MaskLo, EVLLo);
3393 Hi = DAG.getNode(N->getOpcode(), dl, OutVT, Hi, MaskHi, EVLHi);
3394 } else {
3395 Lo = DAG.getNode(N->getOpcode(), dl, OutVT, Lo);
3396 Hi = DAG.getNode(N->getOpcode(), dl, OutVT, Hi);
3397 }
3398
3399 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
3400}
3401
3402SDValue DAGTypeLegalizer::SplitVecOp_BITCAST(SDNode *N) {
3403 // For example, i64 = BITCAST v4i16 on alpha. Typically the vector will
3404 // end up being split all the way down to individual components. Convert the
3405 // split pieces into integers and reassemble.
3406 EVT ResVT = N->getValueType(0);
3407 SDValue Lo, Hi;
3408 GetSplitVector(N->getOperand(0), Lo, Hi);
3409 SDLoc dl(N);
3410
3411 if (ResVT.isScalableVector()) {
3412 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(ResVT);
3413 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
3414 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
3415 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
3416 }
3417
3418 Lo = BitConvertToInteger(Lo);
3419 Hi = BitConvertToInteger(Hi);
3420
3421 if (DAG.getDataLayout().isBigEndian())
3422 std::swap(Lo, Hi);
3423
3424 return DAG.getNode(ISD::BITCAST, dl, ResVT, JoinIntegers(Lo, Hi));
3425}
3426
3427SDValue DAGTypeLegalizer::SplitVecOp_INSERT_SUBVECTOR(SDNode *N,
3428 unsigned OpNo) {
3429 assert(OpNo == 1 && "Invalid OpNo; can only split SubVec.");
3430 // We know that the result type is legal.
3431 EVT ResVT = N->getValueType(0);
3432
3433 SDValue Vec = N->getOperand(0);
3434 SDValue SubVec = N->getOperand(1);
3435 SDValue Idx = N->getOperand(2);
3436 SDLoc dl(N);
3437
3438 SDValue Lo, Hi;
3439 GetSplitVector(SubVec, Lo, Hi);
3440
3441 uint64_t IdxVal = Idx->getAsZExtVal();
3442 uint64_t LoElts = Lo.getValueType().getVectorMinNumElements();
3443
3444 SDValue FirstInsertion =
3445 DAG.getNode(ISD::INSERT_SUBVECTOR, dl, ResVT, Vec, Lo, Idx);
3446 SDValue SecondInsertion =
3447 DAG.getNode(ISD::INSERT_SUBVECTOR, dl, ResVT, FirstInsertion, Hi,
3448 DAG.getVectorIdxConstant(IdxVal + LoElts, dl));
3449
3450 return SecondInsertion;
3451}
3452
3453SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
3454 // We know that the extracted result type is legal.
3455 EVT SubVT = N->getValueType(0);
3456 SDValue Idx = N->getOperand(1);
3457 SDLoc dl(N);
3458 SDValue Lo, Hi;
3459
3460 GetSplitVector(N->getOperand(0), Lo, Hi);
3461
3462 uint64_t LoEltsMin = Lo.getValueType().getVectorMinNumElements();
3463 uint64_t IdxVal = Idx->getAsZExtVal();
3464
3465 if (IdxVal < LoEltsMin) {
3466 assert(IdxVal + SubVT.getVectorMinNumElements() <= LoEltsMin &&
3467 "Extracted subvector crosses vector split!");
3468 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, SubVT, Lo, Idx);
3469 } else if (SubVT.isScalableVector() ==
3470 N->getOperand(0).getValueType().isScalableVector())
3471 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, SubVT, Hi,
3472 DAG.getVectorIdxConstant(IdxVal - LoEltsMin, dl));
3473
3474 // After this point the DAG node only permits extracting fixed-width
3475 // subvectors from scalable vectors.
3476 assert(SubVT.isFixedLengthVector() &&
3477 "Extracting scalable subvector from fixed-width unsupported");
3478
3479 // If the element type is i1 and we're not promoting the result, then we may
3480 // end up loading the wrong data since the bits are packed tightly into
3481 // bytes. For example, if we extract a v4i1 (legal) from a nxv4i1 (legal)
3482 // type at index 4, then we will load a byte starting at index 0.
3483 if (SubVT.getScalarType() == MVT::i1)
3484 report_fatal_error("Don't know how to extract fixed-width predicate "
3485 "subvector from a scalable predicate vector");
3486
3487 // Spill the vector to the stack. We should use the alignment for
3488 // the smallest part.
3489 SDValue Vec = N->getOperand(0);
3490 EVT VecVT = Vec.getValueType();
3491 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
3493 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
3494 auto &MF = DAG.getMachineFunction();
3495 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
3496 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
3497
3498 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
3499 SmallestAlign);
3500
3501 // Extract the subvector by loading the correct part.
3502 StackPtr = TLI.getVectorSubVecPointer(DAG, StackPtr, VecVT, SubVT, Idx);
3503
3504 return DAG.getLoad(
3505 SubVT, dl, Store, StackPtr,
3506 MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()));
3507}
3508
3509SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
3510 SDValue Vec = N->getOperand(0);
3511 SDValue Idx = N->getOperand(1);
3512 EVT VecVT = Vec.getValueType();
3513
3514 if (const ConstantSDNode *Index = dyn_cast<ConstantSDNode>(Idx)) {
3515 uint64_t IdxVal = Index->getZExtValue();
3516
3517 SDValue Lo, Hi;
3518 GetSplitVector(Vec, Lo, Hi);
3519
3520 uint64_t LoElts = Lo.getValueType().getVectorMinNumElements();
3521
3522 if (IdxVal < LoElts)
3523 return SDValue(DAG.UpdateNodeOperands(N, Lo, Idx), 0);
3524 else if (!Vec.getValueType().isScalableVector())
3525 return SDValue(DAG.UpdateNodeOperands(N, Hi,
3526 DAG.getConstant(IdxVal - LoElts, SDLoc(N),
3527 Idx.getValueType())), 0);
3528 }
3529
3530 // See if the target wants to custom expand this node.
3531 if (CustomLowerNode(N, N->getValueType(0), true))
3532 return SDValue();
3533
3534 // Make the vector elements byte-addressable if they aren't already.
3535 SDLoc dl(N);
3536 EVT EltVT = VecVT.getVectorElementType();
3537 if (!EltVT.isByteSized()) {
3538 EltVT = EltVT.changeTypeToInteger().getRoundIntegerType(*DAG.getContext());
3539 VecVT = VecVT.changeElementType(EltVT);
3540 Vec = DAG.getNode(ISD::ANY_EXTEND, dl, VecVT, Vec);
3541 SDValue NewExtract =
3542 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, Vec, Idx);
3543 return DAG.getAnyExtOrTrunc(NewExtract, dl, N->getValueType(0));
3544 }
3545
3546 // Store the vector to the stack.
3547 // In cases where the vector is illegal it will be broken down into parts
3548 // and stored in parts - we should use the alignment for the smallest part.
3549 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
3551 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
3552 auto &MF = DAG.getMachineFunction();
3553 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
3554 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
3555 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
3556 SmallestAlign);
3557
3558 // Load back the required element.
3559 StackPtr = TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Idx);
3560
3561 // EXTRACT_VECTOR_ELT can extend the element type to the width of the return
3562 // type, leaving the high bits undefined. But it can't truncate.
3563 assert(N->getValueType(0).bitsGE(EltVT) && "Illegal EXTRACT_VECTOR_ELT.");
3564
3565 return DAG.getExtLoad(
3566 ISD::EXTLOAD, dl, N->getValueType(0), Store, StackPtr,
3567 MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()), EltVT,
3568 commonAlignment(SmallestAlign, EltVT.getFixedSizeInBits() / 8));
3569}
3570
3571SDValue DAGTypeLegalizer::SplitVecOp_ExtVecInRegOp(SDNode *N) {
3572 SDValue Lo, Hi;
3573
3574 // *_EXTEND_VECTOR_INREG only reference the lower half of the input, so
3575 // splitting the result has the same effect as splitting the input operand.
3576 SplitVecRes_ExtVecInRegOp(N, Lo, Hi);
3577
3578 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), N->getValueType(0), Lo, Hi);
3579}
3580
3581SDValue DAGTypeLegalizer::SplitVecOp_Gather(MemSDNode *N, unsigned OpNo) {
3582 (void)OpNo;
3583 SDValue Lo, Hi;
3584 SplitVecRes_Gather(N, Lo, Hi);
3585
3586 SDValue Res = DAG.getNode(ISD::CONCAT_VECTORS, N, N->getValueType(0), Lo, Hi);
3587 ReplaceValueWith(SDValue(N, 0), Res);
3588 return SDValue();
3589}
3590
3591SDValue DAGTypeLegalizer::SplitVecOp_VP_STORE(VPStoreSDNode *N, unsigned OpNo) {
3592 assert(N->isUnindexed() && "Indexed vp_store of vector?");
3593 SDValue Ch = N->getChain();
3594 SDValue Ptr = N->getBasePtr();
3595 SDValue Offset = N->getOffset();
3596 assert(Offset.isUndef() && "Unexpected VP store offset");
3597 SDValue Mask = N->getMask();
3598 SDValue EVL = N->getVectorLength();
3599 SDValue Data = N->getValue();
3600 Align Alignment = N->getOriginalAlign();
3601 SDLoc DL(N);
3602
3603 SDValue DataLo, DataHi;
3604 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
3605 // Split Data operand
3606 GetSplitVector(Data, DataLo, DataHi);
3607 else
3608 std::tie(DataLo, DataHi) = DAG.SplitVector(Data, DL);
3609
3610 // Split Mask operand
3611 SDValue MaskLo, MaskHi;
3612 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC) {
3613 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
3614 } else {
3615 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
3616 GetSplitVector(Mask, MaskLo, MaskHi);
3617 else
3618 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
3619 }
3620
3621 EVT MemoryVT = N->getMemoryVT();
3622 EVT LoMemVT, HiMemVT;
3623 bool HiIsEmpty = false;
3624 std::tie(LoMemVT, HiMemVT) =
3625 DAG.GetDependentSplitDestVTs(MemoryVT, DataLo.getValueType(), &HiIsEmpty);
3626
3627 // Split EVL
3628 SDValue EVLLo, EVLHi;
3629 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(EVL, Data.getValueType(), DL);
3630
3631 SDValue Lo, Hi;
3632 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
3633 N->getPointerInfo(), MachineMemOperand::MOStore,
3634 LocationSize::beforeOrAfterPointer(), Alignment, N->getAAInfo(),
3635 N->getRanges());
3636
3637 Lo = DAG.getStoreVP(Ch, DL, DataLo, Ptr, Offset, MaskLo, EVLLo, LoMemVT, MMO,
3638 N->getAddressingMode(), N->isTruncatingStore(),
3639 N->isCompressingStore());
3640
3641 // If the hi vp_store has zero storage size, only the lo vp_store is needed.
3642 if (HiIsEmpty)
3643 return Lo;
3644
3645 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, DL, LoMemVT, DAG,
3646 N->isCompressingStore());
3647
3649 if (LoMemVT.isScalableVector()) {
3650 Alignment = commonAlignment(Alignment,
3651 LoMemVT.getSizeInBits().getKnownMinValue() / 8);
3652 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
3653 } else
3654 MPI = N->getPointerInfo().getWithOffset(
3655 LoMemVT.getStoreSize().getFixedValue());
3656
3657 MMO = DAG.getMachineFunction().getMachineMemOperand(
3659 Alignment, N->getAAInfo(), N->getRanges());
3660
3661 Hi = DAG.getStoreVP(Ch, DL, DataHi, Ptr, Offset, MaskHi, EVLHi, HiMemVT, MMO,
3662 N->getAddressingMode(), N->isTruncatingStore(),
3663 N->isCompressingStore());
3664
3665 // Build a factor node to remember that this store is independent of the
3666 // other one.
3667 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
3668}
3669
3670SDValue DAGTypeLegalizer::SplitVecOp_VP_STRIDED_STORE(VPStridedStoreSDNode *N,
3671 unsigned OpNo) {
3672 assert(N->isUnindexed() && "Indexed vp_strided_store of a vector?");
3673 assert(N->getOffset().isUndef() && "Unexpected VP strided store offset");
3674
3675 SDLoc DL(N);
3676
3677 SDValue Data = N->getValue();
3678 SDValue LoData, HiData;
3679 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
3680 GetSplitVector(Data, LoData, HiData);
3681 else
3682 std::tie(LoData, HiData) = DAG.SplitVector(Data, DL);
3683
3684 EVT LoMemVT, HiMemVT;
3685 bool HiIsEmpty = false;
3686 std::tie(LoMemVT, HiMemVT) = DAG.GetDependentSplitDestVTs(
3687 N->getMemoryVT(), LoData.getValueType(), &HiIsEmpty);
3688
3689 SDValue Mask = N->getMask();
3690 SDValue LoMask, HiMask;
3691 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC)
3692 SplitVecRes_SETCC(Mask.getNode(), LoMask, HiMask);
3693 else if (getTypeAction(Mask.getValueType()) ==
3695 GetSplitVector(Mask, LoMask, HiMask);
3696 else
3697 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
3698
3699 SDValue LoEVL, HiEVL;
3700 std::tie(LoEVL, HiEVL) =
3701 DAG.SplitEVL(N->getVectorLength(), Data.getValueType(), DL);
3702
3703 // Generate the low vp_strided_store
3704 SDValue Lo = DAG.getStridedStoreVP(
3705 N->getChain(), DL, LoData, N->getBasePtr(), N->getOffset(),
3706 N->getStride(), LoMask, LoEVL, LoMemVT, N->getMemOperand(),
3707 N->getAddressingMode(), N->isTruncatingStore(), N->isCompressingStore());
3708
3709 // If the high vp_strided_store has zero storage size, only the low
3710 // vp_strided_store is needed.
3711 if (HiIsEmpty)
3712 return Lo;
3713
3714 // Generate the high vp_strided_store.
3715 // To calculate the high base address, we need to sum to the low base
3716 // address stride number of bytes for each element already stored by low,
3717 // that is: Ptr = Ptr + (LoEVL * Stride)
3718 EVT PtrVT = N->getBasePtr().getValueType();
3720 DAG.getNode(ISD::MUL, DL, PtrVT, LoEVL,
3721 DAG.getSExtOrTrunc(N->getStride(), DL, PtrVT));
3722 SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, N->getBasePtr(), Increment);
3723
3724 Align Alignment = N->getOriginalAlign();
3725 if (LoMemVT.isScalableVector())
3726 Alignment = commonAlignment(Alignment,
3727 LoMemVT.getSizeInBits().getKnownMinValue() / 8);
3728
3729 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
3730 MachinePointerInfo(N->getPointerInfo().getAddrSpace()),
3732 Alignment, N->getAAInfo(), N->getRanges());
3733
3734 SDValue Hi = DAG.getStridedStoreVP(
3735 N->getChain(), DL, HiData, Ptr, N->getOffset(), N->getStride(), HiMask,
3736 HiEVL, HiMemVT, MMO, N->getAddressingMode(), N->isTruncatingStore(),
3737 N->isCompressingStore());
3738
3739 // Build a factor node to remember that this store is independent of the
3740 // other one.
3741 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
3742}
3743
3744SDValue DAGTypeLegalizer::SplitVecOp_MSTORE(MaskedStoreSDNode *N,
3745 unsigned OpNo) {
3746 assert(N->isUnindexed() && "Indexed masked store of vector?");
3747 SDValue Ch = N->getChain();
3748 SDValue Ptr = N->getBasePtr();
3749 SDValue Offset = N->getOffset();
3750 assert(Offset.isUndef() && "Unexpected indexed masked store offset");
3751 SDValue Mask = N->getMask();
3752 SDValue Data = N->getValue();
3753 Align Alignment = N->getOriginalAlign();
3754 SDLoc DL(N);
3755
3756 SDValue DataLo, DataHi;
3757 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
3758 // Split Data operand
3759 GetSplitVector(Data, DataLo, DataHi);
3760 else
3761 std::tie(DataLo, DataHi) = DAG.SplitVector(Data, DL);
3762
3763 // Split Mask operand
3764 SDValue MaskLo, MaskHi;
3765 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC) {
3766 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
3767 } else {
3768 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
3769 GetSplitVector(Mask, MaskLo, MaskHi);
3770 else
3771 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
3772 }
3773
3774 EVT MemoryVT = N->getMemoryVT();
3775 EVT LoMemVT, HiMemVT;
3776 bool HiIsEmpty = false;
3777 std::tie(LoMemVT, HiMemVT) =
3778 DAG.GetDependentSplitDestVTs(MemoryVT, DataLo.getValueType(), &HiIsEmpty);
3779
3780 SDValue Lo, Hi, Res;
3781 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
3782 N->getPointerInfo(), MachineMemOperand::MOStore,
3783 LocationSize::beforeOrAfterPointer(), Alignment, N->getAAInfo(),
3784 N->getRanges());
3785
3786 Lo = DAG.getMaskedStore(Ch, DL, DataLo, Ptr, Offset, MaskLo, LoMemVT, MMO,
3787 N->getAddressingMode(), N->isTruncatingStore(),
3788 N->isCompressingStore());
3789
3790 if (HiIsEmpty) {
3791 // The hi masked store has zero storage size.
3792 // Only the lo masked store is needed.
3793 Res = Lo;
3794 } else {
3795
3796 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, DL, LoMemVT, DAG,
3797 N->isCompressingStore());
3798
3800 if (LoMemVT.isScalableVector()) {
3801 Alignment = commonAlignment(
3802 Alignment, LoMemVT.getSizeInBits().getKnownMinValue() / 8);
3803 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
3804 } else
3805 MPI = N->getPointerInfo().getWithOffset(
3806 LoMemVT.getStoreSize().getFixedValue());
3807
3808 MMO = DAG.getMachineFunction().getMachineMemOperand(
3810 Alignment, N->getAAInfo(), N->getRanges());
3811
3812 Hi = DAG.getMaskedStore(Ch, DL, DataHi, Ptr, Offset, MaskHi, HiMemVT, MMO,
3813 N->getAddressingMode(), N->isTruncatingStore(),
3814 N->isCompressingStore());
3815
3816 // Build a factor node to remember that this store is independent of the
3817 // other one.
3818 Res = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
3819 }
3820
3821 return Res;
3822}
3823
3824SDValue DAGTypeLegalizer::SplitVecOp_Scatter(MemSDNode *N, unsigned OpNo) {
3825 SDValue Ch = N->getChain();
3826 SDValue Ptr = N->getBasePtr();
3827 EVT MemoryVT = N->getMemoryVT();
3828 Align Alignment = N->getOriginalAlign();
3829 SDLoc DL(N);
3830 struct Operands {
3831 SDValue Mask;
3832 SDValue Index;
3833 SDValue Scale;
3834 SDValue Data;
3835 } Ops = [&]() -> Operands {
3836 if (auto *MSC = dyn_cast<MaskedScatterSDNode>(N)) {
3837 return {MSC->getMask(), MSC->getIndex(), MSC->getScale(),
3838 MSC->getValue()};
3839 }
3840 auto *VPSC = cast<VPScatterSDNode>(N);
3841 return {VPSC->getMask(), VPSC->getIndex(), VPSC->getScale(),
3842 VPSC->getValue()};
3843 }();
3844 // Split all operands
3845
3846 EVT LoMemVT, HiMemVT;
3847 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
3848
3849 SDValue DataLo, DataHi;
3850 if (getTypeAction(Ops.Data.getValueType()) == TargetLowering::TypeSplitVector)
3851 // Split Data operand
3852 GetSplitVector(Ops.Data, DataLo, DataHi);
3853 else
3854 std::tie(DataLo, DataHi) = DAG.SplitVector(Ops.Data, DL);
3855
3856 // Split Mask operand
3857 SDValue MaskLo, MaskHi;
3858 if (OpNo == 1 && Ops.Mask.getOpcode() == ISD::SETCC) {
3859 SplitVecRes_SETCC(Ops.Mask.getNode(), MaskLo, MaskHi);
3860 } else {
3861 std::tie(MaskLo, MaskHi) = SplitMask(Ops.Mask, DL);
3862 }
3863
3864 SDValue IndexHi, IndexLo;
3865 if (getTypeAction(Ops.Index.getValueType()) ==
3867 GetSplitVector(Ops.Index, IndexLo, IndexHi);
3868 else
3869 std::tie(IndexLo, IndexHi) = DAG.SplitVector(Ops.Index, DL);
3870
3871 SDValue Lo;
3872 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
3873 N->getPointerInfo(), MachineMemOperand::MOStore,
3874 LocationSize::beforeOrAfterPointer(), Alignment, N->getAAInfo(),
3875 N->getRanges());
3876
3877 if (auto *MSC = dyn_cast<MaskedScatterSDNode>(N)) {
3878 SDValue OpsLo[] = {Ch, DataLo, MaskLo, Ptr, IndexLo, Ops.Scale};
3879 Lo =
3880 DAG.getMaskedScatter(DAG.getVTList(MVT::Other), LoMemVT, DL, OpsLo, MMO,
3881 MSC->getIndexType(), MSC->isTruncatingStore());
3882
3883 // The order of the Scatter operation after split is well defined. The "Hi"
3884 // part comes after the "Lo". So these two operations should be chained one
3885 // after another.
3886 SDValue OpsHi[] = {Lo, DataHi, MaskHi, Ptr, IndexHi, Ops.Scale};
3887 return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), HiMemVT, DL, OpsHi,
3888 MMO, MSC->getIndexType(),
3889 MSC->isTruncatingStore());
3890 }
3891 auto *VPSC = cast<VPScatterSDNode>(N);
3892 SDValue EVLLo, EVLHi;
3893 std::tie(EVLLo, EVLHi) =
3894 DAG.SplitEVL(VPSC->getVectorLength(), Ops.Data.getValueType(), DL);
3895
3896 SDValue OpsLo[] = {Ch, DataLo, Ptr, IndexLo, Ops.Scale, MaskLo, EVLLo};
3897 Lo = DAG.getScatterVP(DAG.getVTList(MVT::Other), LoMemVT, DL, OpsLo, MMO,
3898 VPSC->getIndexType());
3899
3900 // The order of the Scatter operation after split is well defined. The "Hi"
3901 // part comes after the "Lo". So these two operations should be chained one
3902 // after another.
3903 SDValue OpsHi[] = {Lo, DataHi, Ptr, IndexHi, Ops.Scale, MaskHi, EVLHi};
3904 return DAG.getScatterVP(DAG.getVTList(MVT::Other), HiMemVT, DL, OpsHi, MMO,
3905 VPSC->getIndexType());
3906}
3907
3908SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) {
3909 assert(N->isUnindexed() && "Indexed store of vector?");
3910 assert(OpNo == 1 && "Can only split the stored value");
3911 SDLoc DL(N);
3912
3913 bool isTruncating = N->isTruncatingStore();
3914 SDValue Ch = N->getChain();
3915 SDValue Ptr = N->getBasePtr();
3916 EVT MemoryVT = N->getMemoryVT();
3917 Align Alignment = N->getOriginalAlign();
3918 MachineMemOperand::Flags MMOFlags = N->getMemOperand()->getFlags();
3919 AAMDNodes AAInfo = N->getAAInfo();
3920 SDValue Lo, Hi;
3921 GetSplitVector(N->getOperand(1), Lo, Hi);
3922
3923 EVT LoMemVT, HiMemVT;
3924 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
3925
3926 // Scalarize if the split halves are not byte-sized.
3927 if (!LoMemVT.isByteSized() || !HiMemVT.isByteSized())
3928 return TLI.scalarizeVectorStore(N, DAG);
3929
3930 if (isTruncating)
3931 Lo = DAG.getTruncStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), LoMemVT,
3932 Alignment, MMOFlags, AAInfo);
3933 else
3934 Lo = DAG.getStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), Alignment, MMOFlags,
3935 AAInfo);
3936
3938 IncrementPointer(N, LoMemVT, MPI, Ptr);
3939
3940 if (isTruncating)
3941 Hi = DAG.getTruncStore(Ch, DL, Hi, Ptr, MPI,
3942 HiMemVT, Alignment, MMOFlags, AAInfo);
3943 else
3944 Hi = DAG.getStore(Ch, DL, Hi, Ptr, MPI, Alignment, MMOFlags, AAInfo);
3945
3946 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
3947}
3948
3949SDValue DAGTypeLegalizer::SplitVecOp_CONCAT_VECTORS(SDNode *N) {
3950 SDLoc DL(N);
3951
3952 // The input operands all must have the same type, and we know the result
3953 // type is valid. Convert this to a buildvector which extracts all the
3954 // input elements.
3955 // TODO: If the input elements are power-two vectors, we could convert this to
3956 // a new CONCAT_VECTORS node with elements that are half-wide.
3958 EVT EltVT = N->getValueType(0).getVectorElementType();
3959 for (const SDValue &Op : N->op_values()) {
3960 for (unsigned i = 0, e = Op.getValueType().getVectorNumElements();
3961 i != e; ++i) {
3962 Elts.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltVT, Op,
3963 DAG.getVectorIdxConstant(i, DL)));
3964 }
3965 }
3966
3967 return DAG.getBuildVector(N->getValueType(0), DL, Elts);
3968}
3969
3970SDValue DAGTypeLegalizer::SplitVecOp_TruncateHelper(SDNode *N) {
3971 // The result type is legal, but the input type is illegal. If splitting
3972 // ends up with the result type of each half still being legal, just
3973 // do that. If, however, that would result in an illegal result type,
3974 // we can try to get more clever with power-two vectors. Specifically,
3975 // split the input type, but also widen the result element size, then
3976 // concatenate the halves and truncate again. For example, consider a target
3977 // where v8i8 is legal and v8i32 is not (ARM, which doesn't have 256-bit
3978 // vectors). To perform a "%res = v8i8 trunc v8i32 %in" we do:
3979 // %inlo = v4i32 extract_subvector %in, 0
3980 // %inhi = v4i32 extract_subvector %in, 4
3981 // %lo16 = v4i16 trunc v4i32 %inlo
3982 // %hi16 = v4i16 trunc v4i32 %inhi
3983 // %in16 = v8i16 concat_vectors v4i16 %lo16, v4i16 %hi16
3984 // %res = v8i8 trunc v8i16 %in16
3985 //
3986 // Without this transform, the original truncate would end up being
3987 // scalarized, which is pretty much always a last resort.
3988 unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
3989 SDValue InVec = N->getOperand(OpNo);
3990 EVT InVT = InVec->getValueType(0);
3991 EVT OutVT = N->getValueType(0);
3992 ElementCount NumElements = OutVT.getVectorElementCount();
3993 bool IsFloat = OutVT.isFloatingPoint();
3994
3995 unsigned InElementSize = InVT.getScalarSizeInBits();
3996 unsigned OutElementSize = OutVT.getScalarSizeInBits();
3997
3998 // Determine the split output VT. If its legal we can just split dirctly.
3999 EVT LoOutVT, HiOutVT;
4000 std::tie(LoOutVT, HiOutVT) = DAG.GetSplitDestVTs(OutVT);
4001 assert(LoOutVT == HiOutVT && "Unequal split?");
4002
4003 // If the input elements are only 1/2 the width of the result elements,
4004 // just use the normal splitting. Our trick only work if there's room
4005 // to split more than once.
4006 if (isTypeLegal(LoOutVT) ||
4007 InElementSize <= OutElementSize * 2)
4008 return SplitVecOp_UnaryOp(N);
4009 SDLoc DL(N);
4010
4011 // Don't touch if this will be scalarized.
4012 EVT FinalVT = InVT;
4013 while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
4014 FinalVT = FinalVT.getHalfNumVectorElementsVT(*DAG.getContext());
4015
4016 if (getTypeAction(FinalVT) == TargetLowering::TypeScalarizeVector)
4017 return SplitVecOp_UnaryOp(N);
4018
4019 // Get the split input vector.
4020 SDValue InLoVec, InHiVec;
4021 GetSplitVector(InVec, InLoVec, InHiVec);
4022
4023 // Truncate them to 1/2 the element size.
4024 //
4025 // This assumes the number of elements is a power of two; any vector that
4026 // isn't should be widened, not split.
4027 EVT HalfElementVT = IsFloat ?
4028 EVT::getFloatingPointVT(InElementSize/2) :
4029 EVT::getIntegerVT(*DAG.getContext(), InElementSize/2);
4030 EVT HalfVT = EVT::getVectorVT(*DAG.getContext(), HalfElementVT,
4031 NumElements.divideCoefficientBy(2));
4032
4033 SDValue HalfLo;
4034 SDValue HalfHi;
4035 SDValue Chain;
4036 if (N->isStrictFPOpcode()) {
4037 HalfLo = DAG.getNode(N->getOpcode(), DL, {HalfVT, MVT::Other},
4038 {N->getOperand(0), InLoVec});
4039 HalfHi = DAG.getNode(N->getOpcode(), DL, {HalfVT, MVT::Other},
4040 {N->getOperand(0), InHiVec});
4041 // Legalize the chain result - switch anything that used the old chain to
4042 // use the new one.
4043 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, HalfLo.getValue(1),
4044 HalfHi.getValue(1));
4045 } else {
4046 HalfLo = DAG.getNode(N->getOpcode(), DL, HalfVT, InLoVec);
4047 HalfHi = DAG.getNode(N->getOpcode(), DL, HalfVT, InHiVec);
4048 }
4049
4050 // Concatenate them to get the full intermediate truncation result.
4051 EVT InterVT = EVT::getVectorVT(*DAG.getContext(), HalfElementVT, NumElements);
4052 SDValue InterVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InterVT, HalfLo,
4053 HalfHi);
4054 // Now finish up by truncating all the way down to the original result
4055 // type. This should normally be something that ends up being legal directly,
4056 // but in theory if a target has very wide vectors and an annoyingly
4057 // restricted set of legal types, this split can chain to build things up.
4058
4059 if (N->isStrictFPOpcode()) {
4060 SDValue Res = DAG.getNode(
4061 ISD::STRICT_FP_ROUND, DL, {OutVT, MVT::Other},
4062 {Chain, InterVec,
4063 DAG.getTargetConstant(0, DL, TLI.getPointerTy(DAG.getDataLayout()))});
4064 // Relink the chain
4065 ReplaceValueWith(SDValue(N, 1), SDValue(Res.getNode(), 1));
4066 return Res;
4067 }
4068
4069 return IsFloat
4070 ? DAG.getNode(ISD::FP_ROUND, DL, OutVT, InterVec,
4071 DAG.getTargetConstant(
4072 0, DL, TLI.getPointerTy(DAG.getDataLayout())))
4073 : DAG.getNode(ISD::TRUNCATE, DL, OutVT, InterVec);
4074}
4075
4076SDValue DAGTypeLegalizer::SplitVecOp_VSETCC(SDNode *N) {
4077 bool isStrict = N->getOpcode() == ISD::STRICT_FSETCC;
4078 assert(N->getValueType(0).isVector() &&
4079 N->getOperand(isStrict ? 1 : 0).getValueType().isVector() &&
4080 "Operand types must be vectors");
4081 // The result has a legal vector type, but the input needs splitting.
4082 SDValue Lo0, Hi0, Lo1, Hi1, LoRes, HiRes;
4083 SDLoc DL(N);
4084 GetSplitVector(N->getOperand(isStrict ? 1 : 0), Lo0, Hi0);
4085 GetSplitVector(N->getOperand(isStrict ? 2 : 1), Lo1, Hi1);
4086
4087 auto PartEltCnt = Lo0.getValueType().getVectorElementCount();
4088
4089 LLVMContext &Context = *DAG.getContext();
4090 EVT PartResVT = EVT::getVectorVT(Context, MVT::i1, PartEltCnt);
4091 EVT WideResVT = EVT::getVectorVT(Context, MVT::i1, PartEltCnt*2);
4092
4093 if (N->getOpcode() == ISD::SETCC) {
4094 LoRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Lo0, Lo1, N->getOperand(2));
4095 HiRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Hi0, Hi1, N->getOperand(2));
4096 } else if (N->getOpcode() == ISD::STRICT_FSETCC) {
4097 LoRes = DAG.getNode(ISD::STRICT_FSETCC, DL,
4098 DAG.getVTList(PartResVT, N->getValueType(1)),
4099 N->getOperand(0), Lo0, Lo1, N->getOperand(3));
4100 HiRes = DAG.getNode(ISD::STRICT_FSETCC, DL,
4101 DAG.getVTList(PartResVT, N->getValueType(1)),
4102 N->getOperand(0), Hi0, Hi1, N->getOperand(3));
4103 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
4104 LoRes.getValue(1), HiRes.getValue(1));
4105 ReplaceValueWith(SDValue(N, 1), NewChain);
4106 } else {
4107 assert(N->getOpcode() == ISD::VP_SETCC && "Expected VP_SETCC opcode");
4108 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
4109 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(3));
4110 std::tie(EVLLo, EVLHi) =
4111 DAG.SplitEVL(N->getOperand(4), N->getValueType(0), DL);
4112 LoRes = DAG.getNode(ISD::VP_SETCC, DL, PartResVT, Lo0, Lo1,
4113 N->getOperand(2), MaskLo, EVLLo);
4114 HiRes = DAG.getNode(ISD::VP_SETCC, DL, PartResVT, Hi0, Hi1,
4115 N->getOperand(2), MaskHi, EVLHi);
4116 }
4117 SDValue Con = DAG.getNode(ISD::CONCAT_VECTORS, DL, WideResVT, LoRes, HiRes);
4118
4119 EVT OpVT = N->getOperand(0).getValueType();
4120 ISD::NodeType ExtendCode =
4122 return DAG.getNode(ExtendCode, DL, N->getValueType(0), Con);
4123}
4124
4125
4126SDValue DAGTypeLegalizer::SplitVecOp_FP_ROUND(SDNode *N) {
4127 // The result has a legal vector type, but the input needs splitting.
4128 EVT ResVT = N->getValueType(0);
4129 SDValue Lo, Hi;
4130 SDLoc DL(N);
4131 GetSplitVector(N->getOperand(N->isStrictFPOpcode() ? 1 : 0), Lo, Hi);
4132 EVT InVT = Lo.getValueType();
4133
4134 EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
4135 InVT.getVectorElementCount());
4136
4137 if (N->isStrictFPOpcode()) {
4138 Lo = DAG.getNode(N->getOpcode(), DL, { OutVT, MVT::Other },
4139 { N->getOperand(0), Lo, N->getOperand(2) });
4140 Hi = DAG.getNode(N->getOpcode(), DL, { OutVT, MVT::Other },
4141 { N->getOperand(0), Hi, N->getOperand(2) });
4142 // Legalize the chain result - switch anything that used the old chain to
4143 // use the new one.
4144 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
4145 Lo.getValue(1), Hi.getValue(1));
4146 ReplaceValueWith(SDValue(N, 1), NewChain);
4147 } else if (N->getOpcode() == ISD::VP_FP_ROUND) {
4148 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
4149 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
4150 std::tie(EVLLo, EVLHi) =
4151 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), DL);
4152 Lo = DAG.getNode(ISD::VP_FP_ROUND, DL, OutVT, Lo, MaskLo, EVLLo);
4153 Hi = DAG.getNode(ISD::VP_FP_ROUND, DL, OutVT, Hi, MaskHi, EVLHi);
4154 } else {
4155 Lo = DAG.getNode(ISD::FP_ROUND, DL, OutVT, Lo, N->getOperand(1));
4156 Hi = DAG.getNode(ISD::FP_ROUND, DL, OutVT, Hi, N->getOperand(1));
4157 }
4158
4159 return DAG.getNode(ISD::CONCAT_VECTORS, DL, ResVT, Lo, Hi);
4160}
4161
4162// Split a vector type in an FP binary operation where the second operand has a
4163// different type from the first.
4164//
4165// The result (and the first input) has a legal vector type, but the second
4166// input needs splitting.
4167SDValue DAGTypeLegalizer::SplitVecOp_FPOpDifferentTypes(SDNode *N) {
4168 SDLoc DL(N);
4169
4170 EVT LHSLoVT, LHSHiVT;
4171 std::tie(LHSLoVT, LHSHiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
4172
4173 if (!isTypeLegal(LHSLoVT) || !isTypeLegal(LHSHiVT))
4174 return DAG.UnrollVectorOp(N, N->getValueType(0).getVectorNumElements());
4175
4176 SDValue LHSLo, LHSHi;
4177 std::tie(LHSLo, LHSHi) =
4178 DAG.SplitVector(N->getOperand(0), DL, LHSLoVT, LHSHiVT);
4179
4180 SDValue RHSLo, RHSHi;
4181 std::tie(RHSLo, RHSHi) = DAG.SplitVector(N->getOperand(1), DL);
4182
4183 SDValue Lo = DAG.getNode(N->getOpcode(), DL, LHSLoVT, LHSLo, RHSLo);
4184 SDValue Hi = DAG.getNode(N->getOpcode(), DL, LHSHiVT, LHSHi, RHSHi);
4185
4186 return DAG.getNode(ISD::CONCAT_VECTORS, DL, N->getValueType(0), Lo, Hi);
4187}
4188
4189SDValue DAGTypeLegalizer::SplitVecOp_CMP(SDNode *N) {
4190 LLVMContext &Ctxt = *DAG.getContext();
4191 SDLoc dl(N);
4192
4193 SDValue LHSLo, LHSHi, RHSLo, RHSHi;
4194 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
4195 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
4196
4197 EVT ResVT = N->getValueType(0);
4198 ElementCount SplitOpEC = LHSLo.getValueType().getVectorElementCount();
4199 EVT NewResVT =
4200 EVT::getVectorVT(Ctxt, ResVT.getVectorElementType(), SplitOpEC);
4201
4202 SDValue Lo = DAG.getNode(N->getOpcode(), dl, NewResVT, LHSLo, RHSLo);
4203 SDValue Hi = DAG.getNode(N->getOpcode(), dl, NewResVT, LHSHi, RHSHi);
4204
4205 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
4206}
4207
4208SDValue DAGTypeLegalizer::SplitVecOp_FP_TO_XINT_SAT(SDNode *N) {
4209 EVT ResVT = N->getValueType(0);
4210 SDValue Lo, Hi;
4211 SDLoc dl(N);
4212 GetSplitVector(N->getOperand(0), Lo, Hi);
4213 EVT InVT = Lo.getValueType();
4214
4215 EVT NewResVT =
4216 EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
4217 InVT.getVectorElementCount());
4218
4219 Lo = DAG.getNode(N->getOpcode(), dl, NewResVT, Lo, N->getOperand(1));
4220 Hi = DAG.getNode(N->getOpcode(), dl, NewResVT, Hi, N->getOperand(1));
4221
4222 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
4223}
4224
4225SDValue DAGTypeLegalizer::SplitVecOp_VP_CttzElements(SDNode *N) {
4226 SDLoc DL(N);
4227 EVT ResVT = N->getValueType(0);
4228
4229 SDValue Lo, Hi;
4230 SDValue VecOp = N->getOperand(0);
4231 GetSplitVector(VecOp, Lo, Hi);
4232
4233 auto [MaskLo, MaskHi] = SplitMask(N->getOperand(1));
4234 auto [EVLLo, EVLHi] =
4235 DAG.SplitEVL(N->getOperand(2), VecOp.getValueType(), DL);
4236 SDValue VLo = DAG.getZExtOrTrunc(EVLLo, DL, ResVT);
4237
4238 // if VP_CTTZ_ELTS(Lo) != EVLLo => VP_CTTZ_ELTS(Lo).
4239 // else => EVLLo + (VP_CTTZ_ELTS(Hi) or VP_CTTZ_ELTS_ZERO_UNDEF(Hi)).
4240 SDValue ResLo = DAG.getNode(ISD::VP_CTTZ_ELTS, DL, ResVT, Lo, MaskLo, EVLLo);
4241 SDValue ResLoNotEVL =
4242 DAG.getSetCC(DL, getSetCCResultType(ResVT), ResLo, VLo, ISD::SETNE);
4243 SDValue ResHi = DAG.getNode(N->getOpcode(), DL, ResVT, Hi, MaskHi, EVLHi);
4244 return DAG.getSelect(DL, ResVT, ResLoNotEVL, ResLo,
4245 DAG.getNode(ISD::ADD, DL, ResVT, VLo, ResHi));
4246}
4247
4248//===----------------------------------------------------------------------===//
4249// Result Vector Widening
4250//===----------------------------------------------------------------------===//
4251
4252void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
4253 LLVM_DEBUG(dbgs() << "Widen node result " << ResNo << ": "; N->dump(&DAG));
4254
4255 // See if the target wants to custom widen this node.
4256 if (CustomWidenLowerNode(N, N->getValueType(ResNo)))
4257 return;
4258
4259 SDValue Res = SDValue();
4260
4261 auto unrollExpandedOp = [&]() {
4262 // We're going to widen this vector op to a legal type by padding with undef
4263 // elements. If the wide vector op is eventually going to be expanded to
4264 // scalar libcalls, then unroll into scalar ops now to avoid unnecessary
4265 // libcalls on the undef elements.
4266 EVT VT = N->getValueType(0);
4267 EVT WideVecVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
4268 if (!TLI.isOperationLegalOrCustom(N->getOpcode(), WideVecVT) &&
4269 TLI.isOperationExpand(N->getOpcode(), VT.getScalarType())) {
4270 Res = DAG.UnrollVectorOp(N, WideVecVT.getVectorNumElements());
4271 return true;
4272 }
4273 return false;
4274 };
4275
4276 switch (N->getOpcode()) {
4277 default:
4278#ifndef NDEBUG
4279 dbgs() << "WidenVectorResult #" << ResNo << ": ";
4280 N->dump(&DAG);
4281 dbgs() << "\n";
4282#endif
4283 report_fatal_error("Do not know how to widen the result of this operator!");
4284
4285 case ISD::MERGE_VALUES: Res = WidenVecRes_MERGE_VALUES(N, ResNo); break;
4286 case ISD::ADDRSPACECAST:
4287 Res = WidenVecRes_ADDRSPACECAST(N);
4288 break;
4289 case ISD::AssertZext: Res = WidenVecRes_AssertZext(N); break;
4290 case ISD::BITCAST: Res = WidenVecRes_BITCAST(N); break;
4291 case ISD::BUILD_VECTOR: Res = WidenVecRes_BUILD_VECTOR(N); break;
4292 case ISD::CONCAT_VECTORS: Res = WidenVecRes_CONCAT_VECTORS(N); break;
4294 Res = WidenVecRes_INSERT_SUBVECTOR(N);
4295 break;
4296 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecRes_EXTRACT_SUBVECTOR(N); break;
4297 case ISD::INSERT_VECTOR_ELT: Res = WidenVecRes_INSERT_VECTOR_ELT(N); break;
4298 case ISD::LOAD: Res = WidenVecRes_LOAD(N); break;
4299 case ISD::STEP_VECTOR:
4300 case ISD::SPLAT_VECTOR:
4302 Res = WidenVecRes_ScalarOp(N);
4303 break;
4304 case ISD::SIGN_EXTEND_INREG: Res = WidenVecRes_InregOp(N); break;
4305 case ISD::VSELECT:
4306 case ISD::SELECT:
4307 case ISD::VP_SELECT:
4308 case ISD::VP_MERGE:
4309 Res = WidenVecRes_Select(N);
4310 break;
4311 case ISD::SELECT_CC: Res = WidenVecRes_SELECT_CC(N); break;
4312 case ISD::VP_SETCC:
4313 case ISD::SETCC: Res = WidenVecRes_SETCC(N); break;
4314 case ISD::UNDEF: Res = WidenVecRes_UNDEF(N); break;
4316 Res = WidenVecRes_VECTOR_SHUFFLE(cast<ShuffleVectorSDNode>(N));
4317 break;
4318 case ISD::VP_LOAD:
4319 Res = WidenVecRes_VP_LOAD(cast<VPLoadSDNode>(N));
4320 break;
4321 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
4322 Res = WidenVecRes_VP_STRIDED_LOAD(cast<VPStridedLoadSDNode>(N));
4323 break;
4324 case ISD::MLOAD:
4325 Res = WidenVecRes_MLOAD(cast<MaskedLoadSDNode>(N));
4326 break;
4327 case ISD::MGATHER:
4328 Res = WidenVecRes_MGATHER(cast<MaskedGatherSDNode>(N));
4329 break;
4330 case ISD::VP_GATHER:
4331 Res = WidenVecRes_VP_GATHER(cast<VPGatherSDNode>(N));
4332 break;
4334 Res = WidenVecRes_VECTOR_REVERSE(N);
4335 break;
4336
4337 case ISD::ADD: case ISD::VP_ADD:
4338 case ISD::AND: case ISD::VP_AND:
4339 case ISD::MUL: case ISD::VP_MUL:
4340 case ISD::MULHS:
4341 case ISD::MULHU:
4342 case ISD::OR: case ISD::VP_OR:
4343 case ISD::SUB: case ISD::VP_SUB:
4344 case ISD::XOR: case ISD::VP_XOR:
4345 case ISD::SHL: case ISD::VP_SHL:
4346 case ISD::SRA: case ISD::VP_SRA:
4347 case ISD::SRL: case ISD::VP_SRL:
4348 case ISD::FMINNUM:
4349 case ISD::FMINNUM_IEEE:
4350 case ISD::VP_FMINNUM:
4351 case ISD::FMAXNUM:
4352 case ISD::FMAXNUM_IEEE:
4353 case ISD::VP_FMAXNUM:
4354 case ISD::FMINIMUM:
4355 case ISD::VP_FMINIMUM:
4356 case ISD::FMAXIMUM:
4357 case ISD::VP_FMAXIMUM:
4358 case ISD::SMIN: case ISD::VP_SMIN:
4359 case ISD::SMAX: case ISD::VP_SMAX:
4360 case ISD::UMIN: case ISD::VP_UMIN:
4361 case ISD::UMAX: case ISD::VP_UMAX:
4362 case ISD::UADDSAT: case ISD::VP_UADDSAT:
4363 case ISD::SADDSAT: case ISD::VP_SADDSAT:
4364 case ISD::USUBSAT: case ISD::VP_USUBSAT:
4365 case ISD::SSUBSAT: case ISD::VP_SSUBSAT:
4366 case ISD::SSHLSAT:
4367 case ISD::USHLSAT:
4368 case ISD::ROTL:
4369 case ISD::ROTR:
4370 case ISD::AVGFLOORS:
4371 case ISD::AVGFLOORU:
4372 case ISD::AVGCEILS:
4373 case ISD::AVGCEILU:
4374 // Vector-predicated binary op widening. Note that -- unlike the
4375 // unpredicated versions -- we don't have to worry about trapping on
4376 // operations like UDIV, FADD, etc., as we pass on the original vector
4377 // length parameter. This means the widened elements containing garbage
4378 // aren't active.
4379 case ISD::VP_SDIV:
4380 case ISD::VP_UDIV:
4381 case ISD::VP_SREM:
4382 case ISD::VP_UREM:
4383 case ISD::VP_FADD:
4384 case ISD::VP_FSUB:
4385 case ISD::VP_FMUL:
4386 case ISD::VP_FDIV:
4387 case ISD::VP_FREM:
4388 case ISD::VP_FCOPYSIGN:
4389 Res = WidenVecRes_Binary(N);
4390 break;
4391
4392 case ISD::SCMP:
4393 case ISD::UCMP:
4394 Res = WidenVecRes_CMP(N);
4395 break;
4396
4397 case ISD::FPOW:
4398 case ISD::FREM:
4399 if (unrollExpandedOp())
4400 break;
4401 // If the target has custom/legal support for the scalar FP intrinsic ops
4402 // (they are probably not destined to become libcalls), then widen those
4403 // like any other binary ops.
4404 [[fallthrough]];
4405
4406 case ISD::FADD:
4407 case ISD::FMUL:
4408 case ISD::FSUB:
4409 case ISD::FDIV:
4410 case ISD::SDIV:
4411 case ISD::UDIV:
4412 case ISD::SREM:
4413 case ISD::UREM:
4414 Res = WidenVecRes_BinaryCanTrap(N);
4415 break;
4416
4417 case ISD::SMULFIX:
4418 case ISD::SMULFIXSAT:
4419 case ISD::UMULFIX:
4420 case ISD::UMULFIXSAT:
4421 // These are binary operations, but with an extra operand that shouldn't
4422 // be widened (the scale).
4423 Res = WidenVecRes_BinaryWithExtraScalarOp(N);
4424 break;
4425
4426#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
4427 case ISD::STRICT_##DAGN:
4428#include "llvm/IR/ConstrainedOps.def"
4429 Res = WidenVecRes_StrictFP(N);
4430 break;
4431
4432 case ISD::UADDO:
4433 case ISD::SADDO:
4434 case ISD::USUBO:
4435 case ISD::SSUBO:
4436 case ISD::UMULO:
4437 case ISD::SMULO:
4438 Res = WidenVecRes_OverflowOp(N, ResNo);
4439 break;
4440
4441 case ISD::FCOPYSIGN:
4442 Res = WidenVecRes_FCOPYSIGN(N);
4443 break;
4444
4445 case ISD::IS_FPCLASS:
4446 case ISD::FPTRUNC_ROUND:
4447 Res = WidenVecRes_UnarySameEltsWithScalarArg(N);
4448 break;
4449
4450 case ISD::FLDEXP:
4451 case ISD::FPOWI:
4452 if (!unrollExpandedOp())
4453 Res = WidenVecRes_ExpOp(N);
4454 break;
4455
4459 Res = WidenVecRes_EXTEND_VECTOR_INREG(N);
4460 break;
4461
4462 case ISD::ANY_EXTEND:
4463 case ISD::FP_EXTEND:
4464 case ISD::VP_FP_EXTEND:
4465 case ISD::FP_ROUND:
4466 case ISD::VP_FP_ROUND:
4467 case ISD::FP_TO_SINT:
4468 case ISD::VP_FP_TO_SINT:
4469 case ISD::FP_TO_UINT:
4470 case ISD::VP_FP_TO_UINT:
4471 case ISD::SIGN_EXTEND:
4472 case ISD::VP_SIGN_EXTEND:
4473 case ISD::SINT_TO_FP:
4474 case ISD::VP_SINT_TO_FP:
4475 case ISD::VP_TRUNCATE:
4476 case ISD::TRUNCATE:
4477 case ISD::UINT_TO_FP:
4478 case ISD::VP_UINT_TO_FP:
4479 case ISD::ZERO_EXTEND:
4480 case ISD::VP_ZERO_EXTEND:
4481 Res = WidenVecRes_Convert(N);
4482 break;
4483
4486 Res = WidenVecRes_FP_TO_XINT_SAT(N);
4487 break;
4488
4489 case ISD::LRINT:
4490 case ISD::LLRINT:
4491 case ISD::VP_LRINT:
4492 case ISD::VP_LLRINT:
4493 Res = WidenVecRes_XRINT(N);
4494 break;
4495
4496 case ISD::FABS:
4497 case ISD::FACOS:
4498 case ISD::FASIN:
4499 case ISD::FATAN:
4500 case ISD::FCEIL:
4501 case ISD::FCOS:
4502 case ISD::FCOSH:
4503 case ISD::FEXP:
4504 case ISD::FEXP2:
4505 case ISD::FEXP10:
4506 case ISD::FFLOOR:
4507 case ISD::FLOG:
4508 case ISD::FLOG10:
4509 case ISD::FLOG2:
4510 case ISD::FNEARBYINT:
4511 case ISD::FRINT:
4512 case ISD::FROUND:
4513 case ISD::FROUNDEVEN:
4514 case ISD::FSIN:
4515 case ISD::FSINH:
4516 case ISD::FSQRT:
4517 case ISD::FTAN:
4518 case ISD::FTANH:
4519 case ISD::FTRUNC:
4520 if (unrollExpandedOp())
4521 break;
4522 // If the target has custom/legal support for the scalar FP intrinsic ops
4523 // (they are probably not destined to become libcalls), then widen those
4524 // like any other unary ops.
4525 [[fallthrough]];
4526
4527 case ISD::ABS:
4528 case ISD::VP_ABS:
4529 case ISD::BITREVERSE:
4530 case ISD::VP_BITREVERSE:
4531 case ISD::BSWAP:
4532 case ISD::VP_BSWAP:
4533 case ISD::CTLZ:
4534 case ISD::VP_CTLZ:
4536 case ISD::VP_CTLZ_ZERO_UNDEF:
4537 case ISD::CTPOP:
4538 case ISD::VP_CTPOP:
4539 case ISD::CTTZ:
4540 case ISD::VP_CTTZ:
4542 case ISD::VP_CTTZ_ZERO_UNDEF:
4543 case ISD::FNEG: case ISD::VP_FNEG:
4544 case ISD::VP_FABS:
4545 case ISD::VP_SQRT:
4546 case ISD::VP_FCEIL:
4547 case ISD::VP_FFLOOR:
4548 case ISD::VP_FRINT:
4549 case ISD::VP_FNEARBYINT:
4550 case ISD::VP_FROUND:
4551 case ISD::VP_FROUNDEVEN:
4552 case ISD::VP_FROUNDTOZERO:
4553 case ISD::FREEZE:
4554 case ISD::ARITH_FENCE:
4555 case ISD::FCANONICALIZE:
4556 Res = WidenVecRes_Unary(N);
4557 break;
4558 case ISD::FMA: case ISD::VP_FMA:
4559 case ISD::FSHL:
4560 case ISD::VP_FSHL:
4561 case ISD::FSHR:
4562 case ISD::VP_FSHR:
4563 Res = WidenVecRes_Ternary(N);
4564 break;
4565 }
4566
4567 // If Res is null, the sub-method took care of registering the result.
4568 if (Res.getNode())
4569 SetWidenedVector(SDValue(N, ResNo), Res);
4570}
4571
4572SDValue DAGTypeLegalizer::WidenVecRes_Ternary(SDNode *N) {
4573 // Ternary op widening.
4574 SDLoc dl(N);
4575 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
4576 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
4577 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
4578 SDValue InOp3 = GetWidenedVector(N->getOperand(2));
4579 if (N->getNumOperands() == 3)
4580 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3);
4581
4582 assert(N->getNumOperands() == 5 && "Unexpected number of operands!");
4583 assert(N->isVPOpcode() && "Expected VP opcode");
4584
4585 SDValue Mask =
4586 GetWidenedMask(N->getOperand(3), WidenVT.getVectorElementCount());
4587 return DAG.getNode(N->getOpcode(), dl, WidenVT,
4588 {InOp1, InOp2, InOp3, Mask, N->getOperand(4)});
4589}
4590
4591SDValue DAGTypeLegalizer::WidenVecRes_Binary(SDNode *N) {
4592 // Binary op widening.
4593 SDLoc dl(N);
4594 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
4595 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
4596 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
4597 if (N->getNumOperands() == 2)
4598 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2,
4599 N->getFlags());
4600
4601 assert(N->getNumOperands() == 4 && "Unexpected number of operands!");
4602 assert(N->isVPOpcode() && "Expected VP opcode");
4603
4604 SDValue Mask =
4605 GetWidenedMask(N->getOperand(2), WidenVT.getVectorElementCount());
4606 return DAG.getNode(N->getOpcode(), dl, WidenVT,
4607 {InOp1, InOp2, Mask, N->getOperand(3)}, N->getFlags());
4608}
4609
4610SDValue DAGTypeLegalizer::WidenVecRes_CMP(SDNode *N) {
4611 LLVMContext &Ctxt = *DAG.getContext();
4612 SDLoc dl(N);
4613
4614 SDValue LHS = N->getOperand(0);
4615 SDValue RHS = N->getOperand(1);
4616 EVT OpVT = LHS.getValueType();
4617 if (getTypeAction(OpVT) == TargetLowering::TypeWidenVector) {
4618 LHS = GetWidenedVector(LHS);
4619 RHS = GetWidenedVector(RHS);
4620 OpVT = LHS.getValueType();
4621 }
4622
4623 EVT WidenResVT = TLI.getTypeToTransformTo(Ctxt, N->getValueType(0));
4624 ElementCount WidenResEC = WidenResVT.getVectorElementCount();
4625 if (WidenResEC == OpVT.getVectorElementCount()) {
4626 return DAG.getNode(N->getOpcode(), dl, WidenResVT, LHS, RHS);
4627 }
4628
4629 return DAG.UnrollVectorOp(N, WidenResVT.getVectorNumElements());
4630}
4631
4632SDValue DAGTypeLegalizer::WidenVecRes_BinaryWithExtraScalarOp(SDNode *N) {
4633 // Binary op widening, but with an extra operand that shouldn't be widened.
4634 SDLoc dl(N);
4635 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
4636 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
4637 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
4638 SDValue InOp3 = N->getOperand(2);
4639 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3,
4640 N->getFlags());
4641}
4642
4643// Given a vector of operations that have been broken up to widen, see
4644// if we can collect them together into the next widest legal VT. This
4645// implementation is trap-safe.
4647 SmallVectorImpl<SDValue> &ConcatOps,
4648 unsigned ConcatEnd, EVT VT, EVT MaxVT,
4649 EVT WidenVT) {
4650 // Check to see if we have a single operation with the widen type.
4651 if (ConcatEnd == 1) {
4652 VT = ConcatOps[0].getValueType();
4653 if (VT == WidenVT)
4654 return ConcatOps[0];
4655 }
4656
4657 SDLoc dl(ConcatOps[0]);
4658 EVT WidenEltVT = WidenVT.getVectorElementType();
4659
4660 // while (Some element of ConcatOps is not of type MaxVT) {
4661 // From the end of ConcatOps, collect elements of the same type and put
4662 // them into an op of the next larger supported type
4663 // }
4664 while (ConcatOps[ConcatEnd-1].getValueType() != MaxVT) {
4665 int Idx = ConcatEnd - 1;
4666 VT = ConcatOps[Idx--].getValueType();
4667 while (Idx >= 0 && ConcatOps[Idx].getValueType() == VT)
4668 Idx--;
4669
4670 int NextSize = VT.isVector() ? VT.getVectorNumElements() : 1;
4671 EVT NextVT;
4672 do {
4673 NextSize *= 2;
4674 NextVT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NextSize);
4675 } while (!TLI.isTypeLegal(NextVT));
4676
4677 if (!VT.isVector()) {
4678 // Scalar type, create an INSERT_VECTOR_ELEMENT of type NextVT
4679 SDValue VecOp = DAG.getUNDEF(NextVT);
4680 unsigned NumToInsert = ConcatEnd - Idx - 1;
4681 for (unsigned i = 0, OpIdx = Idx+1; i < NumToInsert; i++, OpIdx++) {
4682 VecOp = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, NextVT, VecOp,
4683 ConcatOps[OpIdx], DAG.getVectorIdxConstant(i, dl));
4684 }
4685 ConcatOps[Idx+1] = VecOp;
4686 ConcatEnd = Idx + 2;
4687 } else {
4688 // Vector type, create a CONCAT_VECTORS of type NextVT
4689 SDValue undefVec = DAG.getUNDEF(VT);
4690 unsigned OpsToConcat = NextSize/VT.getVectorNumElements();
4691 SmallVector<SDValue, 16> SubConcatOps(OpsToConcat);
4692 unsigned RealVals = ConcatEnd - Idx - 1;
4693 unsigned SubConcatEnd = 0;
4694 unsigned SubConcatIdx = Idx + 1;
4695 while (SubConcatEnd < RealVals)
4696 SubConcatOps[SubConcatEnd++] = ConcatOps[++Idx];
4697 while (SubConcatEnd < OpsToConcat)
4698 SubConcatOps[SubConcatEnd++] = undefVec;
4699 ConcatOps[SubConcatIdx] = DAG.getNode(ISD::CONCAT_VECTORS, dl,
4700 NextVT, SubConcatOps);
4701 ConcatEnd = SubConcatIdx + 1;
4702 }
4703 }
4704
4705 // Check to see if we have a single operation with the widen type.
4706 if (ConcatEnd == 1) {
4707 VT = ConcatOps[0].getValueType();
4708 if (VT == WidenVT)
4709 return ConcatOps[0];
4710 }
4711
4712 // add undefs of size MaxVT until ConcatOps grows to length of WidenVT
4713 unsigned NumOps = WidenVT.getVectorNumElements()/MaxVT.getVectorNumElements();
4714 if (NumOps != ConcatEnd ) {
4715 SDValue UndefVal = DAG.getUNDEF(MaxVT);
4716 for (unsigned j = ConcatEnd; j < NumOps; ++j)
4717 ConcatOps[j] = UndefVal;
4718 }
4719 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
4720 ArrayRef(ConcatOps.data(), NumOps));
4721}
4722
4723SDValue DAGTypeLegalizer::WidenVecRes_BinaryCanTrap(SDNode *N) {
4724 // Binary op widening for operations that can trap.
4725 unsigned Opcode = N->getOpcode();
4726 SDLoc dl(N);
4727 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
4728 EVT WidenEltVT = WidenVT.getVectorElementType();
4729 EVT VT = WidenVT;
4730 unsigned NumElts = VT.getVectorMinNumElements();
4731 const SDNodeFlags Flags = N->getFlags();
4732 while (!TLI.isTypeLegal(VT) && NumElts != 1) {
4733 NumElts = NumElts / 2;
4734 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
4735 }
4736
4737 if (NumElts != 1 && !TLI.canOpTrap(N->getOpcode(), VT)) {
4738 // Operation doesn't trap so just widen as normal.
4739 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
4740 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
4741 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, Flags);
4742 }
4743
4744 // FIXME: Improve support for scalable vectors.
4745 assert(!VT.isScalableVector() && "Scalable vectors not handled yet.");
4746
4747 // No legal vector version so unroll the vector operation and then widen.
4748 if (NumElts == 1)
4749 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
4750
4751 // Since the operation can trap, apply operation on the original vector.
4752 EVT MaxVT = VT;
4753 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
4754 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
4755 unsigned CurNumElts = N->getValueType(0).getVectorNumElements();
4756
4757 SmallVector<SDValue, 16> ConcatOps(CurNumElts);
4758 unsigned ConcatEnd = 0; // Current ConcatOps index.
4759 int Idx = 0; // Current Idx into input vectors.
4760
4761 // NumElts := greatest legal vector size (at most WidenVT)
4762 // while (orig. vector has unhandled elements) {
4763 // take munches of size NumElts from the beginning and add to ConcatOps
4764 // NumElts := next smaller supported vector size or 1
4765 // }
4766 while (CurNumElts != 0) {
4767 while (CurNumElts >= NumElts) {
4768 SDValue EOp1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, InOp1,
4769 DAG.getVectorIdxConstant(Idx, dl));
4770 SDValue EOp2 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, InOp2,
4771 DAG.getVectorIdxConstant(Idx, dl));
4772 ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, VT, EOp1, EOp2, Flags);
4773 Idx += NumElts;
4774 CurNumElts -= NumElts;
4775 }
4776 do {
4777 NumElts = NumElts / 2;
4778 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
4779 } while (!TLI.isTypeLegal(VT) && NumElts != 1);
4780
4781 if (NumElts == 1) {
4782 for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
4783 SDValue EOp1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, WidenEltVT,
4784 InOp1, DAG.getVectorIdxConstant(Idx, dl));
4785 SDValue EOp2 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, WidenEltVT,
4786 InOp2, DAG.getVectorIdxConstant(Idx, dl));
4787 ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, WidenEltVT,
4788 EOp1, EOp2, Flags);
4789 }
4790 CurNumElts = 0;
4791 }
4792 }
4793
4794 return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
4795}
4796
4797SDValue DAGTypeLegalizer::WidenVecRes_StrictFP(SDNode *N) {
4798 switch (N->getOpcode()) {
4799 case ISD::STRICT_FSETCC:
4801 return WidenVecRes_STRICT_FSETCC(N);
4808 return WidenVecRes_Convert_StrictFP(N);
4809 default:
4810 break;
4811 }
4812
4813 // StrictFP op widening for operations that can trap.
4814 unsigned NumOpers = N->getNumOperands();
4815 unsigned Opcode = N->getOpcode();
4816 SDLoc dl(N);
4817 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
4818 EVT WidenEltVT = WidenVT.getVectorElementType();
4819 EVT VT = WidenVT;
4820 unsigned NumElts = VT.getVectorNumElements();
4821 while (!TLI.isTypeLegal(VT) && NumElts != 1) {
4822 NumElts = NumElts / 2;
4823 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
4824 }
4825
4826 // No legal vector version so unroll the vector operation and then widen.
4827 if (NumElts == 1)
4828 return UnrollVectorOp_StrictFP(N, WidenVT.getVectorNumElements());
4829
4830 // Since the operation can trap, apply operation on the original vector.
4831 EVT MaxVT = VT;
4833 unsigned CurNumElts = N->getValueType(0).getVectorNumElements();
4834
4835 SmallVector<SDValue, 16> ConcatOps(CurNumElts);
4837 unsigned ConcatEnd = 0; // Current ConcatOps index.
4838 int Idx = 0; // Current Idx into input vectors.
4839
4840 // The Chain is the first operand.
4841 InOps.push_back(N->getOperand(0));
4842
4843 // Now process the remaining operands.
4844 for (unsigned i = 1; i < NumOpers; ++i) {
4845 SDValue Oper = N->getOperand(i);
4846
4847 EVT OpVT = Oper.getValueType();
4848 if (OpVT.isVector()) {
4849 if (getTypeAction(OpVT) == TargetLowering::TypeWidenVector)
4850 Oper = GetWidenedVector(Oper);
4851 else {
4852 EVT WideOpVT =
4853 EVT::getVectorVT(*DAG.getContext(), OpVT.getVectorElementType(),
4854 WidenVT.getVectorElementCount());
4855 Oper = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WideOpVT,
4856 DAG.getUNDEF(WideOpVT), Oper,
4857 DAG.getVectorIdxConstant(0, dl));
4858 }
4859 }
4860
4861 InOps.push_back(Oper);
4862 }
4863
4864 // NumElts := greatest legal vector size (at most WidenVT)
4865 // while (orig. vector has unhandled elements) {
4866 // take munches of size NumElts from the beginning and add to ConcatOps
4867 // NumElts := next smaller supported vector size or 1
4868 // }
4869 while (CurNumElts != 0) {
4870 while (CurNumElts >= NumElts) {
4872
4873 for (unsigned i = 0; i < NumOpers; ++i) {
4874 SDValue Op = InOps[i];
4875
4876 EVT OpVT = Op.getValueType();
4877 if (OpVT.isVector()) {
4878 EVT OpExtractVT =
4879 EVT::getVectorVT(*DAG.getContext(), OpVT.getVectorElementType(),
4881 Op = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, OpExtractVT, Op,
4882 DAG.getVectorIdxConstant(Idx, dl));
4883 }
4884
4885 EOps.push_back(Op);
4886 }
4887
4888 EVT OperVT[] = {VT, MVT::Other};
4889 SDValue Oper = DAG.getNode(Opcode, dl, OperVT, EOps);
4890 ConcatOps[ConcatEnd++] = Oper;
4891 Chains.push_back(Oper.getValue(1));
4892 Idx += NumElts;
4893 CurNumElts -= NumElts;
4894 }
4895 do {
4896 NumElts = NumElts / 2;
4897 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
4898 } while (!TLI.isTypeLegal(VT) && NumElts != 1);
4899
4900 if (NumElts == 1) {
4901 for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
4903
4904 for (unsigned i = 0; i < NumOpers; ++i) {
4905 SDValue Op = InOps[i];
4906
4907 EVT OpVT = Op.getValueType();
4908 if (OpVT.isVector())
4909 Op = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl,
4910 OpVT.getVectorElementType(), Op,
4911 DAG.getVectorIdxConstant(Idx, dl));
4912
4913 EOps.push_back(Op);
4914 }
4915
4916 EVT WidenVT[] = {WidenEltVT, MVT::Other};
4917 SDValue Oper = DAG.getNode(Opcode, dl, WidenVT, EOps);
4918 ConcatOps[ConcatEnd++] = Oper;
4919 Chains.push_back(Oper.getValue(1));
4920 }
4921 CurNumElts = 0;
4922 }
4923 }
4924
4925 // Build a factor node to remember all the Ops that have been created.
4926 SDValue NewChain;
4927 if (Chains.size() == 1)
4928 NewChain = Chains[0];
4929 else
4930 NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
4931 ReplaceValueWith(SDValue(N, 1), NewChain);
4932
4933 return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
4934}
4935
4936SDValue DAGTypeLegalizer::WidenVecRes_OverflowOp(SDNode *N, unsigned ResNo) {
4937 SDLoc DL(N);
4938 EVT ResVT = N->getValueType(0);
4939 EVT OvVT = N->getValueType(1);
4940 EVT WideResVT, WideOvVT;
4941 SDValue WideLHS, WideRHS;
4942
4943 // TODO: This might result in a widen/split loop.
4944 if (ResNo == 0) {
4945 WideResVT = TLI.getTypeToTransformTo(*DAG.getContext(), ResVT);
4946 WideOvVT = EVT::getVectorVT(
4947 *DAG.getContext(), OvVT.getVectorElementType(),
4948 WideResVT.getVectorNumElements());
4949
4950 WideLHS = GetWidenedVector(N->getOperand(0));
4951 WideRHS = GetWidenedVector(N->getOperand(1));
4952 } else {
4953 WideOvVT = TLI.getTypeToTransformTo(*DAG.getContext(), OvVT);
4954 WideResVT = EVT::getVectorVT(
4955 *DAG.getContext(), ResVT.getVectorElementType(),
4956 WideOvVT.getVectorNumElements());
4957
4958 SDValue Zero = DAG.getVectorIdxConstant(0, DL);
4959 WideLHS = DAG.getNode(
4960 ISD::INSERT_SUBVECTOR, DL, WideResVT, DAG.getUNDEF(WideResVT),
4961 N->getOperand(0), Zero);
4962 WideRHS = DAG.getNode(
4963 ISD::INSERT_SUBVECTOR, DL, WideResVT, DAG.getUNDEF(WideResVT),
4964 N->getOperand(1), Zero);
4965 }
4966
4967 SDVTList WideVTs = DAG.getVTList(WideResVT, WideOvVT);
4968 SDNode *WideNode = DAG.getNode(
4969 N->getOpcode(), DL, WideVTs, WideLHS, WideRHS).getNode();
4970
4971 // Replace the other vector result not being explicitly widened here.
4972 unsigned OtherNo = 1 - ResNo;
4973 EVT OtherVT = N->getValueType(OtherNo);
4974 if (getTypeAction(OtherVT) == TargetLowering::TypeWidenVector) {
4975 SetWidenedVector(SDValue(N, OtherNo), SDValue(WideNode, OtherNo));
4976 } else {
4977 SDValue Zero = DAG.getVectorIdxConstant(0, DL);
4978 SDValue OtherVal = DAG.getNode(
4979 ISD::EXTRACT_SUBVECTOR, DL, OtherVT, SDValue(WideNode, OtherNo), Zero);
4980 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
4981 }
4982
4983 return SDValue(WideNode, ResNo);
4984}
4985
4986SDValue DAGTypeLegalizer::WidenVecRes_Convert(SDNode *N) {
4987 LLVMContext &Ctx = *DAG.getContext();
4988 SDValue InOp = N->getOperand(0);
4989 SDLoc DL(N);
4990
4991 EVT WidenVT = TLI.getTypeToTransformTo(Ctx, N->getValueType(0));
4992 ElementCount WidenEC = WidenVT.getVectorElementCount();
4993
4994 EVT InVT = InOp.getValueType();
4995
4996 unsigned Opcode = N->getOpcode();
4997 const SDNodeFlags Flags = N->getFlags();
4998
4999 // Handle the case of ZERO_EXTEND where the promoted InVT element size does
5000 // not equal that of WidenVT.
5001 if (N->getOpcode() == ISD::ZERO_EXTEND &&
5002 getTypeAction(InVT) == TargetLowering::TypePromoteInteger &&
5003 TLI.getTypeToTransformTo(Ctx, InVT).getScalarSizeInBits() !=
5004 WidenVT.getScalarSizeInBits()) {
5005 InOp = ZExtPromotedInteger(InOp);
5006 InVT = InOp.getValueType();
5007 if (WidenVT.getScalarSizeInBits() < InVT.getScalarSizeInBits())
5008 Opcode = ISD::TRUNCATE;
5009 }
5010
5011 EVT InEltVT = InVT.getVectorElementType();
5012 EVT InWidenVT = EVT::getVectorVT(Ctx, InEltVT, WidenEC);
5013 ElementCount InVTEC = InVT.getVectorElementCount();
5014
5015 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
5016 InOp = GetWidenedVector(N->getOperand(0));
5017 InVT = InOp.getValueType();
5018 InVTEC = InVT.getVectorElementCount();
5019 if (InVTEC == WidenEC) {
5020 if (N->getNumOperands() == 1)
5021 return DAG.getNode(Opcode, DL, WidenVT, InOp);
5022 if (N->getNumOperands() == 3) {
5023 assert(N->isVPOpcode() && "Expected VP opcode");
5024 SDValue Mask =
5025 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
5026 return DAG.getNode(Opcode, DL, WidenVT, InOp, Mask, N->getOperand(2));
5027 }
5028 return DAG.getNode(Opcode, DL, WidenVT, InOp, N->getOperand(1), Flags);
5029 }
5030 if (WidenVT.getSizeInBits() == InVT.getSizeInBits()) {
5031 // If both input and result vector types are of same width, extend
5032 // operations should be done with SIGN/ZERO_EXTEND_VECTOR_INREG, which
5033 // accepts fewer elements in the result than in the input.
5034 if (Opcode == ISD::ANY_EXTEND)
5035 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
5036 if (Opcode == ISD::SIGN_EXTEND)
5037 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
5038 if (Opcode == ISD::ZERO_EXTEND)
5039 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
5040 }
5041 }
5042
5043 if (TLI.isTypeLegal(InWidenVT)) {
5044 // Because the result and the input are different vector types, widening
5045 // the result could create a legal type but widening the input might make
5046 // it an illegal type that might lead to repeatedly splitting the input
5047 // and then widening it. To avoid this, we widen the input only if
5048 // it results in a legal type.
5049 if (WidenEC.isKnownMultipleOf(InVTEC.getKnownMinValue())) {
5050 // Widen the input and call convert on the widened input vector.
5051 unsigned NumConcat =
5052 WidenEC.getKnownMinValue() / InVTEC.getKnownMinValue();
5053 SmallVector<SDValue, 16> Ops(NumConcat, DAG.getUNDEF(InVT));
5054 Ops[0] = InOp;
5055 SDValue InVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InWidenVT, Ops);
5056 if (N->getNumOperands() == 1)
5057 return DAG.getNode(Opcode, DL, WidenVT, InVec);
5058 return DAG.getNode(Opcode, DL, WidenVT, InVec, N->getOperand(1), Flags);
5059 }
5060
5061 if (InVTEC.isKnownMultipleOf(WidenEC.getKnownMinValue())) {
5062 SDValue InVal = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, InWidenVT, InOp,
5063 DAG.getVectorIdxConstant(0, DL));
5064 // Extract the input and convert the shorten input vector.
5065 if (N->getNumOperands() == 1)
5066 return DAG.getNode(Opcode, DL, WidenVT, InVal);
5067 return DAG.getNode(Opcode, DL, WidenVT, InVal, N->getOperand(1), Flags);
5068 }
5069 }
5070
5071 // Otherwise unroll into some nasty scalar code and rebuild the vector.
5072 EVT EltVT = WidenVT.getVectorElementType();
5073 SmallVector<SDValue, 16> Ops(WidenEC.getFixedValue(), DAG.getUNDEF(EltVT));
5074 // Use the original element count so we don't do more scalar opts than
5075 // necessary.
5076 unsigned MinElts = N->getValueType(0).getVectorNumElements();
5077 for (unsigned i=0; i < MinElts; ++i) {
5078 SDValue Val = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, InEltVT, InOp,
5079 DAG.getVectorIdxConstant(i, DL));
5080 if (N->getNumOperands() == 1)
5081 Ops[i] = DAG.getNode(Opcode, DL, EltVT, Val);
5082 else
5083 Ops[i] = DAG.getNode(Opcode, DL, EltVT, Val, N->getOperand(1), Flags);
5084 }
5085
5086 return DAG.getBuildVector(WidenVT, DL, Ops);
5087}
5088
5089SDValue DAGTypeLegalizer::WidenVecRes_FP_TO_XINT_SAT(SDNode *N) {
5090 SDLoc dl(N);
5091 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5092 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
5093
5094 SDValue Src = N->getOperand(0);
5095 EVT SrcVT = Src.getValueType();
5096
5097 // Also widen the input.
5098 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
5099 Src = GetWidenedVector(Src);
5100 SrcVT = Src.getValueType();
5101 }
5102
5103 // Input and output not widened to the same size, give up.
5104 if (WidenNumElts != SrcVT.getVectorElementCount())
5105 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
5106
5107 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src, N->getOperand(1));
5108}
5109
5110SDValue DAGTypeLegalizer::WidenVecRes_XRINT(SDNode *N) {
5111 SDLoc dl(N);
5112 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5113 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
5114
5115 SDValue Src = N->getOperand(0);
5116 EVT SrcVT = Src.getValueType();
5117
5118 // Also widen the input.
5119 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
5120 Src = GetWidenedVector(Src);
5121 SrcVT = Src.getValueType();
5122 }
5123
5124 // Input and output not widened to the same size, give up.
5125 if (WidenNumElts != SrcVT.getVectorElementCount())
5126 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
5127
5128 if (N->getNumOperands() == 1)
5129 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src);
5130
5131 assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
5132 assert(N->isVPOpcode() && "Expected VP opcode");
5133
5134 SDValue Mask =
5135 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
5136 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src, Mask, N->getOperand(2));
5137}
5138
5139SDValue DAGTypeLegalizer::WidenVecRes_Convert_StrictFP(SDNode *N) {
5140 SDValue InOp = N->getOperand(1);
5141 SDLoc DL(N);
5142 SmallVector<SDValue, 4> NewOps(N->op_begin(), N->op_end());
5143
5144 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5145 unsigned WidenNumElts = WidenVT.getVectorNumElements();
5146
5147 EVT InVT = InOp.getValueType();
5148 EVT InEltVT = InVT.getVectorElementType();
5149
5150 unsigned Opcode = N->getOpcode();
5151
5152 // FIXME: Optimizations need to be implemented here.
5153
5154 // Otherwise unroll into some nasty scalar code and rebuild the vector.
5155 EVT EltVT = WidenVT.getVectorElementType();
5156 std::array<EVT, 2> EltVTs = {{EltVT, MVT::Other}};
5157 SmallVector<SDValue, 16> Ops(WidenNumElts, DAG.getUNDEF(EltVT));
5158 SmallVector<SDValue, 32> OpChains;
5159 // Use the original element count so we don't do more scalar opts than
5160 // necessary.
5161 unsigned MinElts = N->getValueType(0).getVectorNumElements();
5162 for (unsigned i=0; i < MinElts; ++i) {
5163 NewOps[1] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, InEltVT, InOp,
5164 DAG.getVectorIdxConstant(i, DL));
5165 Ops[i] = DAG.getNode(Opcode, DL, EltVTs, NewOps);
5166 OpChains.push_back(Ops[i].getValue(1));
5167 }
5168 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OpChains);
5169 ReplaceValueWith(SDValue(N, 1), NewChain);
5170
5171 return DAG.getBuildVector(WidenVT, DL, Ops);
5172}
5173
5174SDValue DAGTypeLegalizer::WidenVecRes_EXTEND_VECTOR_INREG(SDNode *N) {
5175 unsigned Opcode = N->getOpcode();
5176 SDValue InOp = N->getOperand(0);
5177 SDLoc DL(N);
5178
5179 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5180 EVT WidenSVT = WidenVT.getVectorElementType();
5181 unsigned WidenNumElts = WidenVT.getVectorNumElements();
5182
5183 EVT InVT = InOp.getValueType();
5184 EVT InSVT = InVT.getVectorElementType();
5185 unsigned InVTNumElts = InVT.getVectorNumElements();
5186
5187 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
5188 InOp = GetWidenedVector(InOp);
5189 InVT = InOp.getValueType();
5190 if (InVT.getSizeInBits() == WidenVT.getSizeInBits()) {
5191 switch (Opcode) {
5195 return DAG.getNode(Opcode, DL, WidenVT, InOp);
5196 }
5197 }
5198 }
5199
5200 // Unroll, extend the scalars and rebuild the vector.
5202 for (unsigned i = 0, e = std::min(InVTNumElts, WidenNumElts); i != e; ++i) {
5203 SDValue Val = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, InSVT, InOp,
5204 DAG.getVectorIdxConstant(i, DL));
5205 switch (Opcode) {
5207 Val = DAG.getNode(ISD::ANY_EXTEND, DL, WidenSVT, Val);
5208 break;
5210 Val = DAG.getNode(ISD::SIGN_EXTEND, DL, WidenSVT, Val);
5211 break;
5213 Val = DAG.getNode(ISD::ZERO_EXTEND, DL, WidenSVT, Val);
5214 break;
5215 default:
5216 llvm_unreachable("A *_EXTEND_VECTOR_INREG node was expected");
5217 }
5218 Ops.push_back(Val);
5219 }
5220
5221 while (Ops.size() != WidenNumElts)
5222 Ops.push_back(DAG.getUNDEF(WidenSVT));
5223
5224 return DAG.getBuildVector(WidenVT, DL, Ops);
5225}
5226
5227SDValue DAGTypeLegalizer::WidenVecRes_FCOPYSIGN(SDNode *N) {
5228 // If this is an FCOPYSIGN with same input types, we can treat it as a
5229 // normal (can trap) binary op.
5230 if (N->getOperand(0).getValueType() == N->getOperand(1).getValueType())
5231 return WidenVecRes_BinaryCanTrap(N);
5232
5233 // If the types are different, fall back to unrolling.
5234 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5235 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
5236}
5237
5238/// Result and first source operand are different scalar types, but must have
5239/// the same number of elements. There is an additional control argument which
5240/// should be passed through unchanged.
5241SDValue DAGTypeLegalizer::WidenVecRes_UnarySameEltsWithScalarArg(SDNode *N) {
5242 SDValue FpValue = N->getOperand(0);
5243 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5244 if (getTypeAction(FpValue.getValueType()) != TargetLowering::TypeWidenVector)
5245 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
5246 SDValue Arg = GetWidenedVector(FpValue);
5247 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, {Arg, N->getOperand(1)},
5248 N->getFlags());
5249}
5250
5251SDValue DAGTypeLegalizer::WidenVecRes_ExpOp(SDNode *N) {
5252 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5253 SDValue InOp = GetWidenedVector(N->getOperand(0));
5254 SDValue RHS = N->getOperand(1);
5255 EVT ExpVT = RHS.getValueType();
5256 SDValue ExpOp = RHS;
5257 if (ExpVT.isVector()) {
5258 EVT WideExpVT =
5260 ExpOp = ModifyToType(RHS, WideExpVT);
5261 }
5262
5263 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, ExpOp);
5264}
5265
5266SDValue DAGTypeLegalizer::WidenVecRes_Unary(SDNode *N) {
5267 // Unary op widening.
5268 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5269 SDValue InOp = GetWidenedVector(N->getOperand(0));
5270 if (N->getNumOperands() == 1)
5271 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, N->getFlags());
5272
5273 assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
5274 assert(N->isVPOpcode() && "Expected VP opcode");
5275
5276 SDValue Mask =
5277 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
5278 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT,
5279 {InOp, Mask, N->getOperand(2)});
5280}
5281
5282SDValue DAGTypeLegalizer::WidenVecRes_InregOp(SDNode *N) {
5283 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5284 EVT ExtVT = EVT::getVectorVT(*DAG.getContext(),
5285 cast<VTSDNode>(N->getOperand(1))->getVT()
5286 .getVectorElementType(),
5287 WidenVT.getVectorNumElements());
5288 SDValue WidenLHS = GetWidenedVector(N->getOperand(0));
5289 return DAG.getNode(N->getOpcode(), SDLoc(N),
5290 WidenVT, WidenLHS, DAG.getValueType(ExtVT));
5291}
5292
5293SDValue DAGTypeLegalizer::WidenVecRes_MERGE_VALUES(SDNode *N, unsigned ResNo) {
5294 SDValue WidenVec = DisintegrateMERGE_VALUES(N, ResNo);
5295 return GetWidenedVector(WidenVec);
5296}
5297
5298SDValue DAGTypeLegalizer::WidenVecRes_ADDRSPACECAST(SDNode *N) {
5299 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5300 SDValue InOp = GetWidenedVector(N->getOperand(0));
5301 auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
5302
5303 return DAG.getAddrSpaceCast(SDLoc(N), WidenVT, InOp,
5304 AddrSpaceCastN->getSrcAddressSpace(),
5305 AddrSpaceCastN->getDestAddressSpace());
5306}
5307
5308SDValue DAGTypeLegalizer::WidenVecRes_BITCAST(SDNode *N) {
5309 SDValue InOp = N->getOperand(0);
5310 EVT InVT = InOp.getValueType();
5311 EVT VT = N->getValueType(0);
5312 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
5313 SDLoc dl(N);
5314
5315 switch (getTypeAction(InVT)) {
5317 break;
5319 report_fatal_error("Scalarization of scalable vectors is not supported.");
5321 // If the incoming type is a vector that is being promoted, then
5322 // we know that the elements are arranged differently and that we
5323 // must perform the conversion using a stack slot.
5324 if (InVT.isVector())
5325 break;
5326
5327 // If the InOp is promoted to the same size, convert it. Otherwise,
5328 // fall out of the switch and widen the promoted input.
5329 SDValue NInOp = GetPromotedInteger(InOp);
5330 EVT NInVT = NInOp.getValueType();
5331 if (WidenVT.bitsEq(NInVT)) {
5332 // For big endian targets we need to shift the input integer or the
5333 // interesting bits will end up at the wrong place.
5334 if (DAG.getDataLayout().isBigEndian()) {
5335 unsigned ShiftAmt = NInVT.getSizeInBits() - InVT.getSizeInBits();
5336 EVT ShiftAmtTy = TLI.getShiftAmountTy(NInVT, DAG.getDataLayout());
5337 assert(ShiftAmt < WidenVT.getSizeInBits() && "Too large shift amount!");
5338 NInOp = DAG.getNode(ISD::SHL, dl, NInVT, NInOp,
5339 DAG.getConstant(ShiftAmt, dl, ShiftAmtTy));
5340 }
5341 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NInOp);
5342 }
5343 InOp = NInOp;
5344 InVT = NInVT;
5345 break;
5346 }
5354 break;
5356 // If the InOp is widened to the same size, convert it. Otherwise, fall
5357 // out of the switch and widen the widened input.
5358 InOp = GetWidenedVector(InOp);
5359 InVT = InOp.getValueType();
5360 if (WidenVT.bitsEq(InVT))
5361 // The input widens to the same size. Convert to the widen value.
5362 return DAG.getNode(ISD::BITCAST, dl, WidenVT, InOp);
5363 break;
5364 }
5365
5366 unsigned WidenSize = WidenVT.getSizeInBits();
5367 unsigned InSize = InVT.getSizeInBits();
5368 unsigned InScalarSize = InVT.getScalarSizeInBits();
5369 // x86mmx is not an acceptable vector element type, so don't try.
5370 if (WidenSize % InScalarSize == 0 && InVT != MVT::x86mmx) {
5371 // Determine new input vector type. The new input vector type will use
5372 // the same element type (if its a vector) or use the input type as a
5373 // vector. It is the same size as the type to widen to.
5374 EVT NewInVT;
5375 unsigned NewNumParts = WidenSize / InSize;
5376 if (InVT.isVector()) {
5377 EVT InEltVT = InVT.getVectorElementType();
5378 NewInVT = EVT::getVectorVT(*DAG.getContext(), InEltVT,
5379 WidenSize / InEltVT.getSizeInBits());
5380 } else {
5381 // For big endian systems, using the promoted input scalar type
5382 // to produce the scalar_to_vector would put the desired bits into
5383 // the least significant byte(s) of the wider element zero. This
5384 // will mean that the users of the result vector are using incorrect
5385 // bits. Use the original input type instead. Although either input
5386 // type can be used on little endian systems, for consistency we
5387 // use the original type there as well.
5388 EVT OrigInVT = N->getOperand(0).getValueType();
5389 NewNumParts = WidenSize / OrigInVT.getSizeInBits();
5390 NewInVT = EVT::getVectorVT(*DAG.getContext(), OrigInVT, NewNumParts);
5391 }
5392
5393 if (TLI.isTypeLegal(NewInVT)) {
5394 SDValue NewVec;
5395 if (InVT.isVector()) {
5396 // Because the result and the input are different vector types, widening
5397 // the result could create a legal type but widening the input might
5398 // make it an illegal type that might lead to repeatedly splitting the
5399 // input and then widening it. To avoid this, we widen the input only if
5400 // it results in a legal type.
5401 if (WidenSize % InSize == 0) {
5402 SmallVector<SDValue, 16> Ops(NewNumParts, DAG.getUNDEF(InVT));
5403 Ops[0] = InOp;
5404
5405 NewVec = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewInVT, Ops);
5406 } else {
5408 DAG.ExtractVectorElements(InOp, Ops);
5409 Ops.append(WidenSize / InScalarSize - Ops.size(),
5410 DAG.getUNDEF(InVT.getVectorElementType()));
5411
5412 NewVec = DAG.getNode(ISD::BUILD_VECTOR, dl, NewInVT, Ops);
5413 }
5414 } else {
5415 NewVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewInVT, InOp);
5416 }
5417 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NewVec);
5418 }
5419 }
5420
5421 return CreateStackStoreLoad(InOp, WidenVT);
5422}
5423
5424SDValue DAGTypeLegalizer::WidenVecRes_BUILD_VECTOR(SDNode *N) {
5425 SDLoc dl(N);
5426 // Build a vector with undefined for the new nodes.
5427 EVT VT = N->getValueType(0);
5428
5429 // Integer BUILD_VECTOR operands may be larger than the node's vector element
5430 // type. The UNDEFs need to have the same type as the existing operands.
5431 EVT EltVT = N->getOperand(0).getValueType();
5432 unsigned NumElts = VT.getVectorNumElements();
5433
5434 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
5435 unsigned WidenNumElts = WidenVT.getVectorNumElements();
5436
5437 SmallVector<SDValue, 16> NewOps(N->op_begin(), N->op_end());
5438 assert(WidenNumElts >= NumElts && "Shrinking vector instead of widening!");
5439 NewOps.append(WidenNumElts - NumElts, DAG.getUNDEF(EltVT));
5440
5441 return DAG.getBuildVector(WidenVT, dl, NewOps);
5442}
5443
5444SDValue DAGTypeLegalizer::WidenVecRes_CONCAT_VECTORS(SDNode *N) {
5445 EVT InVT = N->getOperand(0).getValueType();
5446 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5447 SDLoc dl(N);
5448 unsigned NumOperands = N->getNumOperands();
5449
5450 bool InputWidened = false; // Indicates we need to widen the input.
5451 if (getTypeAction(InVT) != TargetLowering::TypeWidenVector) {
5452 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
5453 unsigned NumInElts = InVT.getVectorMinNumElements();
5454 if (WidenNumElts % NumInElts == 0) {
5455 // Add undef vectors to widen to correct length.
5456 unsigned NumConcat = WidenNumElts / NumInElts;
5457 SDValue UndefVal = DAG.getUNDEF(InVT);
5458 SmallVector<SDValue, 16> Ops(NumConcat);
5459 for (unsigned i=0; i < NumOperands; ++i)
5460 Ops[i] = N->getOperand(i);
5461 for (unsigned i = NumOperands; i != NumConcat; ++i)
5462 Ops[i] = UndefVal;
5463 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Ops);
5464 }
5465 } else {
5466 InputWidened = true;
5467 if (WidenVT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
5468 // The inputs and the result are widen to the same value.
5469 unsigned i;
5470 for (i=1; i < NumOperands; ++i)
5471 if (!N->getOperand(i).isUndef())
5472 break;
5473
5474 if (i == NumOperands)
5475 // Everything but the first operand is an UNDEF so just return the
5476 // widened first operand.
5477 return GetWidenedVector(N->getOperand(0));
5478
5479 if (NumOperands == 2) {
5480 assert(!WidenVT.isScalableVector() &&
5481 "Cannot use vector shuffles to widen CONCAT_VECTOR result");
5482 unsigned WidenNumElts = WidenVT.getVectorNumElements();
5483 unsigned NumInElts = InVT.getVectorNumElements();
5484
5485 // Replace concat of two operands with a shuffle.
5486 SmallVector<int, 16> MaskOps(WidenNumElts, -1);
5487 for (unsigned i = 0; i < NumInElts; ++i) {
5488 MaskOps[i] = i;
5489 MaskOps[i + NumInElts] = i + WidenNumElts;
5490 }
5491 return DAG.getVectorShuffle(WidenVT, dl,
5492 GetWidenedVector(N->getOperand(0)),
5493 GetWidenedVector(N->getOperand(1)),
5494 MaskOps);
5495 }
5496 }
5497 }
5498
5499 assert(!WidenVT.isScalableVector() &&
5500 "Cannot use build vectors to widen CONCAT_VECTOR result");
5501 unsigned WidenNumElts = WidenVT.getVectorNumElements();
5502 unsigned NumInElts = InVT.getVectorNumElements();
5503
5504 // Fall back to use extracts and build vector.
5505 EVT EltVT = WidenVT.getVectorElementType();
5506 SmallVector<SDValue, 16> Ops(WidenNumElts);
5507 unsigned Idx = 0;
5508 for (unsigned i=0; i < NumOperands; ++i) {
5509 SDValue InOp = N->getOperand(i);
5510 if (InputWidened)
5511 InOp = GetWidenedVector(InOp);
5512 for (unsigned j = 0; j < NumInElts; ++j)
5513 Ops[Idx++] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp,
5514 DAG.getVectorIdxConstant(j, dl));
5515 }
5516 SDValue UndefVal = DAG.getUNDEF(EltVT);
5517 for (; Idx < WidenNumElts; ++Idx)
5518 Ops[Idx] = UndefVal;
5519 return DAG.getBuildVector(WidenVT, dl, Ops);
5520}
5521
5522SDValue DAGTypeLegalizer::WidenVecRes_INSERT_SUBVECTOR(SDNode *N) {
5523 EVT VT = N->getValueType(0);
5524 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
5525 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5526 SDValue InOp2 = N->getOperand(1);
5527 SDValue Idx = N->getOperand(2);
5528 SDLoc dl(N);
5529 return DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WidenVT, InOp1, InOp2, Idx);
5530}
5531
5532SDValue DAGTypeLegalizer::WidenVecRes_EXTRACT_SUBVECTOR(SDNode *N) {
5533 EVT VT = N->getValueType(0);
5534 EVT EltVT = VT.getVectorElementType();
5535 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
5536 SDValue InOp = N->getOperand(0);
5537 SDValue Idx = N->getOperand(1);
5538 SDLoc dl(N);
5539
5540 auto InOpTypeAction = getTypeAction(InOp.getValueType());
5541 if (InOpTypeAction == TargetLowering::TypeWidenVector)
5542 InOp = GetWidenedVector(InOp);
5543
5544 EVT InVT = InOp.getValueType();
5545
5546 // Check if we can just return the input vector after widening.
5547 uint64_t IdxVal = Idx->getAsZExtVal();
5548 if (IdxVal == 0 && InVT == WidenVT)
5549 return InOp;
5550
5551 // Check if we can extract from the vector.
5552 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
5553 unsigned InNumElts = InVT.getVectorMinNumElements();
5554 unsigned VTNumElts = VT.getVectorMinNumElements();
5555 assert(IdxVal % VTNumElts == 0 &&
5556 "Expected Idx to be a multiple of subvector minimum vector length");
5557 if (IdxVal % WidenNumElts == 0 && IdxVal + WidenNumElts < InNumElts)
5558 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, WidenVT, InOp, Idx);
5559
5560 if (VT.isScalableVector()) {
5561 // Try to split the operation up into smaller extracts and concat the
5562 // results together, e.g.
5563 // nxv6i64 extract_subvector(nxv12i64, 6)
5564 // <->
5565 // nxv8i64 concat(
5566 // nxv2i64 extract_subvector(nxv16i64, 6)
5567 // nxv2i64 extract_subvector(nxv16i64, 8)
5568 // nxv2i64 extract_subvector(nxv16i64, 10)
5569 // undef)
5570 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
5571 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
5572 "down type's element count");
5573 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
5575 // Avoid recursion around e.g. nxv1i8.
5576 if (getTypeAction(PartVT) != TargetLowering::TypeWidenVector) {
5578 unsigned I = 0;
5579 for (; I < VTNumElts / GCD; ++I)
5580 Parts.push_back(
5581 DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, PartVT, InOp,
5582 DAG.getVectorIdxConstant(IdxVal + I * GCD, dl)));
5583 for (; I < WidenNumElts / GCD; ++I)
5584 Parts.push_back(DAG.getUNDEF(PartVT));
5585
5586 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
5587 }
5588
5589 report_fatal_error("Don't know how to widen the result of "
5590 "EXTRACT_SUBVECTOR for scalable vectors");
5591 }
5592
5593 // We could try widening the input to the right length but for now, extract
5594 // the original elements, fill the rest with undefs and build a vector.
5595 SmallVector<SDValue, 16> Ops(WidenNumElts);
5596 unsigned i;
5597 for (i = 0; i < VTNumElts; ++i)
5598 Ops[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp,
5599 DAG.getVectorIdxConstant(IdxVal + i, dl));
5600
5601 SDValue UndefVal = DAG.getUNDEF(EltVT);
5602 for (; i < WidenNumElts; ++i)
5603 Ops[i] = UndefVal;
5604 return DAG.getBuildVector(WidenVT, dl, Ops);
5605}
5606
5607SDValue DAGTypeLegalizer::WidenVecRes_AssertZext(SDNode *N) {
5608 SDValue InOp = ModifyToType(
5609 N->getOperand(0),
5610 TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)), true);
5611 return DAG.getNode(ISD::AssertZext, SDLoc(N), InOp.getValueType(), InOp,
5612 N->getOperand(1));
5613}
5614
5615SDValue DAGTypeLegalizer::WidenVecRes_INSERT_VECTOR_ELT(SDNode *N) {
5616 SDValue InOp = GetWidenedVector(N->getOperand(0));
5617 return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(N),
5618 InOp.getValueType(), InOp,
5619 N->getOperand(1), N->getOperand(2));
5620}
5621
5622SDValue DAGTypeLegalizer::WidenVecRes_LOAD(SDNode *N) {
5623 LoadSDNode *LD = cast<LoadSDNode>(N);
5624 ISD::LoadExtType ExtType = LD->getExtensionType();
5625
5626 // A vector must always be stored in memory as-is, i.e. without any padding
5627 // between the elements, since various code depend on it, e.g. in the
5628 // handling of a bitcast of a vector type to int, which may be done with a
5629 // vector store followed by an integer load. A vector that does not have
5630 // elements that are byte-sized must therefore be stored as an integer
5631 // built out of the extracted vector elements.
5632 if (!LD->getMemoryVT().isByteSized()) {
5633 SDValue Value, NewChain;
5634 std::tie(Value, NewChain) = TLI.scalarizeVectorLoad(LD, DAG);
5635 ReplaceValueWith(SDValue(LD, 0), Value);
5636 ReplaceValueWith(SDValue(LD, 1), NewChain);
5637 return SDValue();
5638 }
5639
5640 // Generate a vector-predicated load if it is custom/legal on the target. To
5641 // avoid possible recursion, only do this if the widened mask type is legal.
5642 // FIXME: Not all targets may support EVL in VP_LOAD. These will have been
5643 // removed from the IR by the ExpandVectorPredication pass but we're
5644 // reintroducing them here.
5645 EVT LdVT = LD->getMemoryVT();
5646 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), LdVT);
5647 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
5648 WideVT.getVectorElementCount());
5649 if (ExtType == ISD::NON_EXTLOAD &&
5650 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WideVT) &&
5651 TLI.isTypeLegal(WideMaskVT)) {
5652 SDLoc DL(N);
5653 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
5654 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
5655 LdVT.getVectorElementCount());
5656 const auto *MMO = LD->getMemOperand();
5657 SDValue NewLoad =
5658 DAG.getLoadVP(WideVT, DL, LD->getChain(), LD->getBasePtr(), Mask, EVL,
5659 MMO->getPointerInfo(), MMO->getAlign(), MMO->getFlags(),
5660 MMO->getAAInfo());
5661
5662 // Modified the chain - switch anything that used the old chain to use
5663 // the new one.
5664 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
5665
5666 return NewLoad;
5667 }
5668
5670 SmallVector<SDValue, 16> LdChain; // Chain for the series of load
5671 if (ExtType != ISD::NON_EXTLOAD)
5672 Result = GenWidenVectorExtLoads(LdChain, LD, ExtType);
5673 else
5674 Result = GenWidenVectorLoads(LdChain, LD);
5675
5676 if (Result) {
5677 // If we generate a single load, we can use that for the chain. Otherwise,
5678 // build a factor node to remember the multiple loads are independent and
5679 // chain to that.
5680 SDValue NewChain;
5681 if (LdChain.size() == 1)
5682 NewChain = LdChain[0];
5683 else
5684 NewChain = DAG.getNode(ISD::TokenFactor, SDLoc(LD), MVT::Other, LdChain);
5685
5686 // Modified the chain - switch anything that used the old chain to use
5687 // the new one.
5688 ReplaceValueWith(SDValue(N, 1), NewChain);
5689
5690 return Result;
5691 }
5692
5693 report_fatal_error("Unable to widen vector load");
5694}
5695
5696SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD(VPLoadSDNode *N) {
5697 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5698 SDValue Mask = N->getMask();
5699 SDValue EVL = N->getVectorLength();
5700 ISD::LoadExtType ExtType = N->getExtensionType();
5701 SDLoc dl(N);
5702
5703 // The mask should be widened as well
5704 assert(getTypeAction(Mask.getValueType()) ==
5706 "Unable to widen binary VP op");
5707 Mask = GetWidenedVector(Mask);
5708 assert(Mask.getValueType().getVectorElementCount() ==
5709 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
5711 "Unable to widen vector load");
5712
5713 SDValue Res =
5714 DAG.getLoadVP(N->getAddressingMode(), ExtType, WidenVT, dl, N->getChain(),
5715 N->getBasePtr(), N->getOffset(), Mask, EVL,
5716 N->getMemoryVT(), N->getMemOperand(), N->isExpandingLoad());
5717 // Legalize the chain result - switch anything that used the old chain to
5718 // use the new one.
5719 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
5720 return Res;
5721}
5722
5723SDValue DAGTypeLegalizer::WidenVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode *N) {
5724 SDLoc DL(N);
5725
5726 // The mask should be widened as well
5727 SDValue Mask = N->getMask();
5728 assert(getTypeAction(Mask.getValueType()) ==
5730 "Unable to widen VP strided load");
5731 Mask = GetWidenedVector(Mask);
5732
5733 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5734 assert(Mask.getValueType().getVectorElementCount() ==
5735 WidenVT.getVectorElementCount() &&
5736 "Data and mask vectors should have the same number of elements");
5737
5738 SDValue Res = DAG.getStridedLoadVP(
5739 N->getAddressingMode(), N->getExtensionType(), WidenVT, DL, N->getChain(),
5740 N->getBasePtr(), N->getOffset(), N->getStride(), Mask,
5741 N->getVectorLength(), N->getMemoryVT(), N->getMemOperand(),
5742 N->isExpandingLoad());
5743
5744 // Legalize the chain result - switch anything that used the old chain to
5745 // use the new one.
5746 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
5747 return Res;
5748}
5749
5750SDValue DAGTypeLegalizer::WidenVecRes_MLOAD(MaskedLoadSDNode *N) {
5751
5752 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),N->getValueType(0));
5753 SDValue Mask = N->getMask();
5754 EVT MaskVT = Mask.getValueType();
5755 SDValue PassThru = GetWidenedVector(N->getPassThru());
5756 ISD::LoadExtType ExtType = N->getExtensionType();
5757 SDLoc dl(N);
5758
5759 // The mask should be widened as well
5760 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
5761 MaskVT.getVectorElementType(),
5762 WidenVT.getVectorNumElements());
5763 Mask = ModifyToType(Mask, WideMaskVT, true);
5764
5765 SDValue Res = DAG.getMaskedLoad(
5766 WidenVT, dl, N->getChain(), N->getBasePtr(), N->getOffset(), Mask,
5767 PassThru, N->getMemoryVT(), N->getMemOperand(), N->getAddressingMode(),
5768 ExtType, N->isExpandingLoad());
5769 // Legalize the chain result - switch anything that used the old chain to
5770 // use the new one.
5771 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
5772 return Res;
5773}
5774
5775SDValue DAGTypeLegalizer::WidenVecRes_MGATHER(MaskedGatherSDNode *N) {
5776
5777 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5778 SDValue Mask = N->getMask();
5779 EVT MaskVT = Mask.getValueType();
5780 SDValue PassThru = GetWidenedVector(N->getPassThru());
5781 SDValue Scale = N->getScale();
5782 unsigned NumElts = WideVT.getVectorNumElements();
5783 SDLoc dl(N);
5784
5785 // The mask should be widened as well
5786 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
5787 MaskVT.getVectorElementType(),
5788 WideVT.getVectorNumElements());
5789 Mask = ModifyToType(Mask, WideMaskVT, true);
5790
5791 // Widen the Index operand
5792 SDValue Index = N->getIndex();
5793 EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
5794 Index.getValueType().getScalarType(),
5795 NumElts);
5796 Index = ModifyToType(Index, WideIndexVT);
5797 SDValue Ops[] = { N->getChain(), PassThru, Mask, N->getBasePtr(), Index,
5798 Scale };
5799
5800 // Widen the MemoryType
5801 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
5802 N->getMemoryVT().getScalarType(), NumElts);
5803 SDValue Res = DAG.getMaskedGather(DAG.getVTList(WideVT, MVT::Other),
5804 WideMemVT, dl, Ops, N->getMemOperand(),
5805 N->getIndexType(), N->getExtensionType());
5806
5807 // Legalize the chain result - switch anything that used the old chain to
5808 // use the new one.
5809 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
5810 return Res;
5811}
5812
5813SDValue DAGTypeLegalizer::WidenVecRes_VP_GATHER(VPGatherSDNode *N) {
5814 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5815 SDValue Mask = N->getMask();
5816 SDValue Scale = N->getScale();
5817 ElementCount WideEC = WideVT.getVectorElementCount();
5818 SDLoc dl(N);
5819
5820 SDValue Index = GetWidenedVector(N->getIndex());
5821 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
5822 N->getMemoryVT().getScalarType(), WideEC);
5823 Mask = GetWidenedMask(Mask, WideEC);
5824
5825 SDValue Ops[] = {N->getChain(), N->getBasePtr(), Index, Scale,
5826 Mask, N->getVectorLength()};
5827 SDValue Res = DAG.getGatherVP(DAG.getVTList(WideVT, MVT::Other), WideMemVT,
5828 dl, Ops, N->getMemOperand(), N->getIndexType());
5829
5830 // Legalize the chain result - switch anything that used the old chain to
5831 // use the new one.
5832 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
5833 return Res;
5834}
5835
5836SDValue DAGTypeLegalizer::WidenVecRes_ScalarOp(SDNode *N) {
5837 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5838 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, N->getOperand(0));
5839}
5840
5841// Return true is this is a SETCC node or a strict version of it.
5842static inline bool isSETCCOp(unsigned Opcode) {
5843 switch (Opcode) {
5844 case ISD::SETCC:
5845 case ISD::STRICT_FSETCC:
5847 return true;
5848 }
5849 return false;
5850}
5851
5852// Return true if this is a node that could have two SETCCs as operands.
5853static inline bool isLogicalMaskOp(unsigned Opcode) {
5854 switch (Opcode) {
5855 case ISD::AND:
5856 case ISD::OR:
5857 case ISD::XOR:
5858 return true;
5859 }
5860 return false;
5861}
5862
5863// If N is a SETCC or a strict variant of it, return the type
5864// of the compare operands.
5866 unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
5867 return N->getOperand(OpNo).getValueType();
5868}
5869
5870// This is used just for the assert in convertMask(). Check that this either
5871// a SETCC or a previously handled SETCC by convertMask().
5872#ifndef NDEBUG
5873static inline bool isSETCCorConvertedSETCC(SDValue N) {
5874 if (N.getOpcode() == ISD::EXTRACT_SUBVECTOR)
5875 N = N.getOperand(0);
5876 else if (N.getOpcode() == ISD::CONCAT_VECTORS) {
5877 for (unsigned i = 1; i < N->getNumOperands(); ++i)
5878 if (!N->getOperand(i)->isUndef())
5879 return false;
5880 N = N.getOperand(0);
5881 }
5882
5883 if (N.getOpcode() == ISD::TRUNCATE)
5884 N = N.getOperand(0);
5885 else if (N.getOpcode() == ISD::SIGN_EXTEND)
5886 N = N.getOperand(0);
5887
5888 if (isLogicalMaskOp(N.getOpcode()))
5889 return isSETCCorConvertedSETCC(N.getOperand(0)) &&
5890 isSETCCorConvertedSETCC(N.getOperand(1));
5891
5892 return (isSETCCOp(N.getOpcode()) ||
5894}
5895#endif
5896
5897// Return a mask of vector type MaskVT to replace InMask. Also adjust MaskVT
5898// to ToMaskVT if needed with vector extension or truncation.
5899SDValue DAGTypeLegalizer::convertMask(SDValue InMask, EVT MaskVT,
5900 EVT ToMaskVT) {
5901 // Currently a SETCC or a AND/OR/XOR with two SETCCs are handled.
5902 // FIXME: This code seems to be too restrictive, we might consider
5903 // generalizing it or dropping it.
5904 assert(isSETCCorConvertedSETCC(InMask) && "Unexpected mask argument.");
5905
5906 // Make a new Mask node, with a legal result VT.
5907 SDValue Mask;
5909 for (unsigned i = 0, e = InMask->getNumOperands(); i < e; ++i)
5910 Ops.push_back(InMask->getOperand(i));
5911 if (InMask->isStrictFPOpcode()) {
5912 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask),
5913 { MaskVT, MVT::Other }, Ops);
5914 ReplaceValueWith(InMask.getValue(1), Mask.getValue(1));
5915 }
5916 else
5917 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask), MaskVT, Ops);
5918
5919 // If MaskVT has smaller or bigger elements than ToMaskVT, a vector sign
5920 // extend or truncate is needed.
5921 LLVMContext &Ctx = *DAG.getContext();
5922 unsigned MaskScalarBits = MaskVT.getScalarSizeInBits();
5923 unsigned ToMaskScalBits = ToMaskVT.getScalarSizeInBits();
5924 if (MaskScalarBits < ToMaskScalBits) {
5925 EVT ExtVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
5926 MaskVT.getVectorNumElements());
5927 Mask = DAG.getNode(ISD::SIGN_EXTEND, SDLoc(Mask), ExtVT, Mask);
5928 } else if (MaskScalarBits > ToMaskScalBits) {
5929 EVT TruncVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
5930 MaskVT.getVectorNumElements());
5931 Mask = DAG.getNode(ISD::TRUNCATE, SDLoc(Mask), TruncVT, Mask);
5932 }
5933
5934 assert(Mask->getValueType(0).getScalarSizeInBits() ==
5935 ToMaskVT.getScalarSizeInBits() &&
5936 "Mask should have the right element size by now.");
5937
5938 // Adjust Mask to the right number of elements.
5939 unsigned CurrMaskNumEls = Mask->getValueType(0).getVectorNumElements();
5940 if (CurrMaskNumEls > ToMaskVT.getVectorNumElements()) {
5941 SDValue ZeroIdx = DAG.getVectorIdxConstant(0, SDLoc(Mask));
5942 Mask = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SDLoc(Mask), ToMaskVT, Mask,
5943 ZeroIdx);
5944 } else if (CurrMaskNumEls < ToMaskVT.getVectorNumElements()) {
5945 unsigned NumSubVecs = (ToMaskVT.getVectorNumElements() / CurrMaskNumEls);
5946 EVT SubVT = Mask->getValueType(0);
5947 SmallVector<SDValue, 16> SubOps(NumSubVecs, DAG.getUNDEF(SubVT));
5948 SubOps[0] = Mask;
5949 Mask = DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Mask), ToMaskVT, SubOps);
5950 }
5951
5952 assert((Mask->getValueType(0) == ToMaskVT) &&
5953 "A mask of ToMaskVT should have been produced by now.");
5954
5955 return Mask;
5956}
5957
5958// This method tries to handle some special cases for the vselect mask
5959// and if needed adjusting the mask vector type to match that of the VSELECT.
5960// Without it, many cases end up with scalarization of the SETCC, with many
5961// unnecessary instructions.
5962SDValue DAGTypeLegalizer::WidenVSELECTMask(SDNode *N) {
5963 LLVMContext &Ctx = *DAG.getContext();
5964 SDValue Cond = N->getOperand(0);
5965
5966 if (N->getOpcode() != ISD::VSELECT)
5967 return SDValue();
5968
5969 if (!isSETCCOp(Cond->getOpcode()) && !isLogicalMaskOp(Cond->getOpcode()))
5970 return SDValue();
5971
5972 // If this is a splitted VSELECT that was previously already handled, do
5973 // nothing.
5974 EVT CondVT = Cond->getValueType(0);
5975 if (CondVT.getScalarSizeInBits() != 1)
5976 return SDValue();
5977
5978 EVT VSelVT = N->getValueType(0);
5979
5980 // This method can't handle scalable vector types.
5981 // FIXME: This support could be added in the future.
5982 if (VSelVT.isScalableVector())
5983 return SDValue();
5984
5985 // Only handle vector types which are a power of 2.
5986 if (!isPowerOf2_64(VSelVT.getSizeInBits()))
5987 return SDValue();
5988
5989 // Don't touch if this will be scalarized.
5990 EVT FinalVT = VSelVT;
5991 while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
5992 FinalVT = FinalVT.getHalfNumVectorElementsVT(Ctx);
5993
5994 if (FinalVT.getVectorNumElements() == 1)
5995 return SDValue();
5996
5997 // If there is support for an i1 vector mask, don't touch.
5998 if (isSETCCOp(Cond.getOpcode())) {
5999 EVT SetCCOpVT = getSETCCOperandType(Cond);
6000 while (TLI.getTypeAction(Ctx, SetCCOpVT) != TargetLowering::TypeLegal)
6001 SetCCOpVT = TLI.getTypeToTransformTo(Ctx, SetCCOpVT);
6002 EVT SetCCResVT = getSetCCResultType(SetCCOpVT);
6003 if (SetCCResVT.getScalarSizeInBits() == 1)
6004 return SDValue();
6005 } else if (CondVT.getScalarType() == MVT::i1) {
6006 // If there is support for an i1 vector mask (or only scalar i1 conditions),
6007 // don't touch.
6008 while (TLI.getTypeAction(Ctx, CondVT) != TargetLowering::TypeLegal)
6009 CondVT = TLI.getTypeToTransformTo(Ctx, CondVT);
6010
6011 if (CondVT.getScalarType() == MVT::i1)
6012 return SDValue();
6013 }
6014
6015 // Widen the vselect result type if needed.
6016 if (getTypeAction(VSelVT) == TargetLowering::TypeWidenVector)
6017 VSelVT = TLI.getTypeToTransformTo(Ctx, VSelVT);
6018
6019 // The mask of the VSELECT should have integer elements.
6020 EVT ToMaskVT = VSelVT;
6021 if (!ToMaskVT.getScalarType().isInteger())
6022 ToMaskVT = ToMaskVT.changeVectorElementTypeToInteger();
6023
6024 SDValue Mask;
6025 if (isSETCCOp(Cond->getOpcode())) {
6026 EVT MaskVT = getSetCCResultType(getSETCCOperandType(Cond));
6027 Mask = convertMask(Cond, MaskVT, ToMaskVT);
6028 } else if (isLogicalMaskOp(Cond->getOpcode()) &&
6029 isSETCCOp(Cond->getOperand(0).getOpcode()) &&
6030 isSETCCOp(Cond->getOperand(1).getOpcode())) {
6031 // Cond is (AND/OR/XOR (SETCC, SETCC))
6032 SDValue SETCC0 = Cond->getOperand(0);
6033 SDValue SETCC1 = Cond->getOperand(1);
6034 EVT VT0 = getSetCCResultType(getSETCCOperandType(SETCC0));
6035 EVT VT1 = getSetCCResultType(getSETCCOperandType(SETCC1));
6036 unsigned ScalarBits0 = VT0.getScalarSizeInBits();
6037 unsigned ScalarBits1 = VT1.getScalarSizeInBits();
6038 unsigned ScalarBits_ToMask = ToMaskVT.getScalarSizeInBits();
6039 EVT MaskVT;
6040 // If the two SETCCs have different VTs, either extend/truncate one of
6041 // them to the other "towards" ToMaskVT, or truncate one and extend the
6042 // other to ToMaskVT.
6043 if (ScalarBits0 != ScalarBits1) {
6044 EVT NarrowVT = ((ScalarBits0 < ScalarBits1) ? VT0 : VT1);
6045 EVT WideVT = ((NarrowVT == VT0) ? VT1 : VT0);
6046 if (ScalarBits_ToMask >= WideVT.getScalarSizeInBits())
6047 MaskVT = WideVT;
6048 else if (ScalarBits_ToMask <= NarrowVT.getScalarSizeInBits())
6049 MaskVT = NarrowVT;
6050 else
6051 MaskVT = ToMaskVT;
6052 } else
6053 // If the two SETCCs have the same VT, don't change it.
6054 MaskVT = VT0;
6055
6056 // Make new SETCCs and logical nodes.
6057 SETCC0 = convertMask(SETCC0, VT0, MaskVT);
6058 SETCC1 = convertMask(SETCC1, VT1, MaskVT);
6059 Cond = DAG.getNode(Cond->getOpcode(), SDLoc(Cond), MaskVT, SETCC0, SETCC1);
6060
6061 // Convert the logical op for VSELECT if needed.
6062 Mask = convertMask(Cond, MaskVT, ToMaskVT);
6063 } else
6064 return SDValue();
6065
6066 return Mask;
6067}
6068
6069SDValue DAGTypeLegalizer::WidenVecRes_Select(SDNode *N) {
6070 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6071 ElementCount WidenEC = WidenVT.getVectorElementCount();
6072
6073 SDValue Cond1 = N->getOperand(0);
6074 EVT CondVT = Cond1.getValueType();
6075 unsigned Opcode = N->getOpcode();
6076 if (CondVT.isVector()) {
6077 if (SDValue WideCond = WidenVSELECTMask(N)) {
6078 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
6079 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
6080 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
6081 return DAG.getNode(Opcode, SDLoc(N), WidenVT, WideCond, InOp1, InOp2);
6082 }
6083
6084 EVT CondEltVT = CondVT.getVectorElementType();
6085 EVT CondWidenVT = EVT::getVectorVT(*DAG.getContext(), CondEltVT, WidenEC);
6086 if (getTypeAction(CondVT) == TargetLowering::TypeWidenVector)
6087 Cond1 = GetWidenedVector(Cond1);
6088
6089 // If we have to split the condition there is no point in widening the
6090 // select. This would result in an cycle of widening the select ->
6091 // widening the condition operand -> splitting the condition operand ->
6092 // splitting the select -> widening the select. Instead split this select
6093 // further and widen the resulting type.
6094 if (getTypeAction(CondVT) == TargetLowering::TypeSplitVector) {
6095 SDValue SplitSelect = SplitVecOp_VSELECT(N, 0);
6096 SDValue Res = ModifyToType(SplitSelect, WidenVT);
6097 return Res;
6098 }
6099
6100 if (Cond1.getValueType() != CondWidenVT)
6101 Cond1 = ModifyToType(Cond1, CondWidenVT);
6102 }
6103
6104 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
6105 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
6106 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
6107 if (Opcode == ISD::VP_SELECT || Opcode == ISD::VP_MERGE)
6108 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2,
6109 N->getOperand(3));
6110 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2);
6111}
6112
6113SDValue DAGTypeLegalizer::WidenVecRes_SELECT_CC(SDNode *N) {
6114 SDValue InOp1 = GetWidenedVector(N->getOperand(2));
6115 SDValue InOp2 = GetWidenedVector(N->getOperand(3));
6116 return DAG.getNode(ISD::SELECT_CC, SDLoc(N),
6117 InOp1.getValueType(), N->getOperand(0),
6118 N->getOperand(1), InOp1, InOp2, N->getOperand(4));
6119}
6120
6121SDValue DAGTypeLegalizer::WidenVecRes_UNDEF(SDNode *N) {
6122 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6123 return DAG.getUNDEF(WidenVT);
6124}
6125
6126SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N) {
6127 EVT VT = N->getValueType(0);
6128 SDLoc dl(N);
6129
6130 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6131 unsigned NumElts = VT.getVectorNumElements();
6132 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6133
6134 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
6135 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
6136
6137 // Adjust mask based on new input vector length.
6138 SmallVector<int, 16> NewMask;
6139 for (unsigned i = 0; i != NumElts; ++i) {
6140 int Idx = N->getMaskElt(i);
6141 if (Idx < (int)NumElts)
6142 NewMask.push_back(Idx);
6143 else
6144 NewMask.push_back(Idx - NumElts + WidenNumElts);
6145 }
6146 for (unsigned i = NumElts; i != WidenNumElts; ++i)
6147 NewMask.push_back(-1);
6148 return DAG.getVectorShuffle(WidenVT, dl, InOp1, InOp2, NewMask);
6149}
6150
6151SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_REVERSE(SDNode *N) {
6152 EVT VT = N->getValueType(0);
6153 EVT EltVT = VT.getVectorElementType();
6154 SDLoc dl(N);
6155
6156 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6157 SDValue OpValue = GetWidenedVector(N->getOperand(0));
6158 assert(WidenVT == OpValue.getValueType() && "Unexpected widened vector type");
6159
6160 SDValue ReverseVal = DAG.getNode(ISD::VECTOR_REVERSE, dl, WidenVT, OpValue);
6161 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6162 unsigned VTNumElts = VT.getVectorMinNumElements();
6163 unsigned IdxVal = WidenNumElts - VTNumElts;
6164
6165 if (VT.isScalableVector()) {
6166 // Try to split the 'Widen ReverseVal' into smaller extracts and concat the
6167 // results together, e.g.(nxv6i64 -> nxv8i64)
6168 // nxv8i64 vector_reverse
6169 // <->
6170 // nxv8i64 concat(
6171 // nxv2i64 extract_subvector(nxv8i64, 2)
6172 // nxv2i64 extract_subvector(nxv8i64, 4)
6173 // nxv2i64 extract_subvector(nxv8i64, 6)
6174 // nxv2i64 undef)
6175
6176 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
6177 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
6179 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
6180 "down type's element count");
6182 unsigned i = 0;
6183 for (; i < VTNumElts / GCD; ++i)
6184 Parts.push_back(
6185 DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, PartVT, ReverseVal,
6186 DAG.getVectorIdxConstant(IdxVal + i * GCD, dl)));
6187 for (; i < WidenNumElts / GCD; ++i)
6188 Parts.push_back(DAG.getUNDEF(PartVT));
6189
6190 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
6191 }
6192
6193 // Use VECTOR_SHUFFLE to combine new vector from 'ReverseVal' for
6194 // fixed-vectors.
6196 for (unsigned i = 0; i != VTNumElts; ++i) {
6197 Mask.push_back(IdxVal + i);
6198 }
6199 for (unsigned i = VTNumElts; i != WidenNumElts; ++i)
6200 Mask.push_back(-1);
6201
6202 return DAG.getVectorShuffle(WidenVT, dl, ReverseVal, DAG.getUNDEF(WidenVT),
6203 Mask);
6204}
6205
6206SDValue DAGTypeLegalizer::WidenVecRes_SETCC(SDNode *N) {
6207 assert(N->getValueType(0).isVector() &&
6208 N->getOperand(0).getValueType().isVector() &&
6209 "Operands must be vectors");
6210 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6211 ElementCount WidenEC = WidenVT.getVectorElementCount();
6212
6213 SDValue InOp1 = N->getOperand(0);
6214 EVT InVT = InOp1.getValueType();
6215 assert(InVT.isVector() && "can not widen non-vector type");
6216 EVT WidenInVT =
6217 EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), WidenEC);
6218
6219 // The input and output types often differ here, and it could be that while
6220 // we'd prefer to widen the result type, the input operands have been split.
6221 // In this case, we also need to split the result of this node as well.
6222 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector) {
6223 SDValue SplitVSetCC = SplitVecOp_VSETCC(N);
6224 SDValue Res = ModifyToType(SplitVSetCC, WidenVT);
6225 return Res;
6226 }
6227
6228 // If the inputs also widen, handle them directly. Otherwise widen by hand.
6229 SDValue InOp2 = N->getOperand(1);
6230 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
6231 InOp1 = GetWidenedVector(InOp1);
6232 InOp2 = GetWidenedVector(InOp2);
6233 } else {
6234 InOp1 = DAG.WidenVector(InOp1, SDLoc(N));
6235 InOp2 = DAG.WidenVector(InOp2, SDLoc(N));
6236 }
6237
6238 // Assume that the input and output will be widen appropriately. If not,
6239 // we will have to unroll it at some point.
6240 assert(InOp1.getValueType() == WidenInVT &&
6241 InOp2.getValueType() == WidenInVT &&
6242 "Input not widened to expected type!");
6243 (void)WidenInVT;
6244 if (N->getOpcode() == ISD::VP_SETCC) {
6245 SDValue Mask =
6246 GetWidenedMask(N->getOperand(3), WidenVT.getVectorElementCount());
6247 return DAG.getNode(ISD::VP_SETCC, SDLoc(N), WidenVT, InOp1, InOp2,
6248 N->getOperand(2), Mask, N->getOperand(4));
6249 }
6250 return DAG.getNode(ISD::SETCC, SDLoc(N), WidenVT, InOp1, InOp2,
6251 N->getOperand(2));
6252}
6253
6254SDValue DAGTypeLegalizer::WidenVecRes_STRICT_FSETCC(SDNode *N) {
6255 assert(N->getValueType(0).isVector() &&
6256 N->getOperand(1).getValueType().isVector() &&
6257 "Operands must be vectors");
6258 EVT VT = N->getValueType(0);
6259 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6260 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6261 unsigned NumElts = VT.getVectorNumElements();
6262 EVT EltVT = VT.getVectorElementType();
6263
6264 SDLoc dl(N);
6265 SDValue Chain = N->getOperand(0);
6266 SDValue LHS = N->getOperand(1);
6267 SDValue RHS = N->getOperand(2);
6268 SDValue CC = N->getOperand(3);
6269 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
6270
6271 // Fully unroll and reassemble.
6272 SmallVector<SDValue, 8> Scalars(WidenNumElts, DAG.getUNDEF(EltVT));
6273 SmallVector<SDValue, 8> Chains(NumElts);
6274 for (unsigned i = 0; i != NumElts; ++i) {
6275 SDValue LHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, LHS,
6276 DAG.getVectorIdxConstant(i, dl));
6277 SDValue RHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, RHS,
6278 DAG.getVectorIdxConstant(i, dl));
6279
6280 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
6281 {Chain, LHSElem, RHSElem, CC});
6282 Chains[i] = Scalars[i].getValue(1);
6283 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
6284 DAG.getBoolConstant(true, dl, EltVT, VT),
6285 DAG.getBoolConstant(false, dl, EltVT, VT));
6286 }
6287
6288 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
6289 ReplaceValueWith(SDValue(N, 1), NewChain);
6290
6291 return DAG.getBuildVector(WidenVT, dl, Scalars);
6292}
6293
6294//===----------------------------------------------------------------------===//
6295// Widen Vector Operand
6296//===----------------------------------------------------------------------===//
6297bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned OpNo) {
6298 LLVM_DEBUG(dbgs() << "Widen node operand " << OpNo << ": "; N->dump(&DAG));
6299 SDValue Res = SDValue();
6300
6301 // See if the target wants to custom widen this node.
6302 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
6303 return false;
6304
6305 switch (N->getOpcode()) {
6306 default:
6307#ifndef NDEBUG
6308 dbgs() << "WidenVectorOperand op #" << OpNo << ": ";
6309 N->dump(&DAG);
6310 dbgs() << "\n";
6311#endif
6312 report_fatal_error("Do not know how to widen this operator's operand!");
6313
6314 case ISD::BITCAST: Res = WidenVecOp_BITCAST(N); break;
6315 case ISD::CONCAT_VECTORS: Res = WidenVecOp_CONCAT_VECTORS(N); break;
6316 case ISD::INSERT_SUBVECTOR: Res = WidenVecOp_INSERT_SUBVECTOR(N); break;
6317 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecOp_EXTRACT_SUBVECTOR(N); break;
6318 case ISD::EXTRACT_VECTOR_ELT: Res = WidenVecOp_EXTRACT_VECTOR_ELT(N); break;
6319 case ISD::STORE: Res = WidenVecOp_STORE(N); break;
6320 case ISD::VP_STORE: Res = WidenVecOp_VP_STORE(N, OpNo); break;
6321 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
6322 Res = WidenVecOp_VP_STRIDED_STORE(N, OpNo);
6323 break;
6327 Res = WidenVecOp_EXTEND_VECTOR_INREG(N);
6328 break;
6329 case ISD::MSTORE: Res = WidenVecOp_MSTORE(N, OpNo); break;
6330 case ISD::MGATHER: Res = WidenVecOp_MGATHER(N, OpNo); break;
6331 case ISD::MSCATTER: Res = WidenVecOp_MSCATTER(N, OpNo); break;
6332 case ISD::VP_SCATTER: Res = WidenVecOp_VP_SCATTER(N, OpNo); break;
6333 case ISD::SETCC: Res = WidenVecOp_SETCC(N); break;
6334 case ISD::STRICT_FSETCC:
6335 case ISD::STRICT_FSETCCS: Res = WidenVecOp_STRICT_FSETCC(N); break;
6336 case ISD::VSELECT: Res = WidenVecOp_VSELECT(N); break;
6337 case ISD::FLDEXP:
6338 case ISD::FCOPYSIGN:
6339 case ISD::LRINT:
6340 case ISD::LLRINT:
6341 Res = WidenVecOp_UnrollVectorOp(N);
6342 break;
6343 case ISD::IS_FPCLASS: Res = WidenVecOp_IS_FPCLASS(N); break;
6344
6345 case ISD::ANY_EXTEND:
6346 case ISD::SIGN_EXTEND:
6347 case ISD::ZERO_EXTEND:
6348 Res = WidenVecOp_EXTEND(N);
6349 break;
6350
6351 case ISD::SCMP:
6352 case ISD::UCMP:
6353 Res = WidenVecOp_CMP(N);
6354 break;
6355
6356 case ISD::FP_EXTEND:
6358 case ISD::FP_ROUND:
6360 case ISD::FP_TO_SINT:
6362 case ISD::FP_TO_UINT:
6364 case ISD::SINT_TO_FP:
6366 case ISD::UINT_TO_FP:
6368 case ISD::TRUNCATE:
6369 Res = WidenVecOp_Convert(N);
6370 break;
6371
6374 Res = WidenVecOp_FP_TO_XINT_SAT(N);
6375 break;
6376
6379 case ISD::VECREDUCE_ADD:
6380 case ISD::VECREDUCE_MUL:
6381 case ISD::VECREDUCE_AND:
6382 case ISD::VECREDUCE_OR:
6383 case ISD::VECREDUCE_XOR:
6392 Res = WidenVecOp_VECREDUCE(N);
6393 break;
6396 Res = WidenVecOp_VECREDUCE_SEQ(N);
6397 break;
6398 case ISD::VP_REDUCE_FADD:
6399 case ISD::VP_REDUCE_SEQ_FADD:
6400 case ISD::VP_REDUCE_FMUL:
6401 case ISD::VP_REDUCE_SEQ_FMUL:
6402 case ISD::VP_REDUCE_ADD:
6403 case ISD::VP_REDUCE_MUL:
6404 case ISD::VP_REDUCE_AND:
6405 case ISD::VP_REDUCE_OR:
6406 case ISD::VP_REDUCE_XOR:
6407 case ISD::VP_REDUCE_SMAX:
6408 case ISD::VP_REDUCE_SMIN:
6409 case ISD::VP_REDUCE_UMAX:
6410 case ISD::VP_REDUCE_UMIN:
6411 case ISD::VP_REDUCE_FMAX:
6412 case ISD::VP_REDUCE_FMIN:
6413 case ISD::VP_REDUCE_FMAXIMUM:
6414 case ISD::VP_REDUCE_FMINIMUM:
6415 Res = WidenVecOp_VP_REDUCE(N);
6416 break;
6417 case ISD::VP_CTTZ_ELTS:
6418 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
6419 Res = WidenVecOp_VP_CttzElements(N);
6420 break;
6421 }
6422
6423 // If Res is null, the sub-method took care of registering the result.
6424 if (!Res.getNode()) return false;
6425
6426 // If the result is N, the sub-method updated N in place. Tell the legalizer
6427 // core about this.
6428 if (Res.getNode() == N)
6429 return true;
6430
6431
6432 if (N->isStrictFPOpcode())
6433 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
6434 "Invalid operand expansion");
6435 else
6436 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
6437 "Invalid operand expansion");
6438
6439 ReplaceValueWith(SDValue(N, 0), Res);
6440 return false;
6441}
6442
6443SDValue DAGTypeLegalizer::WidenVecOp_EXTEND(SDNode *N) {
6444 SDLoc DL(N);
6445 EVT VT = N->getValueType(0);
6446
6447 SDValue InOp = N->getOperand(0);
6448 assert(getTypeAction(InOp.getValueType()) ==
6450 "Unexpected type action");
6451 InOp = GetWidenedVector(InOp);
6454 "Input wasn't widened!");
6455
6456 // We may need to further widen the operand until it has the same total
6457 // vector size as the result.
6458 EVT InVT = InOp.getValueType();
6459 if (InVT.getSizeInBits() != VT.getSizeInBits()) {
6460 EVT InEltVT = InVT.getVectorElementType();
6461 for (EVT FixedVT : MVT::vector_valuetypes()) {
6462 EVT FixedEltVT = FixedVT.getVectorElementType();
6463 if (TLI.isTypeLegal(FixedVT) &&
6464 FixedVT.getSizeInBits() == VT.getSizeInBits() &&
6465 FixedEltVT == InEltVT) {
6466 assert(FixedVT.getVectorNumElements() >= VT.getVectorNumElements() &&
6467 "Not enough elements in the fixed type for the operand!");
6468 assert(FixedVT.getVectorNumElements() != InVT.getVectorNumElements() &&
6469 "We can't have the same type as we started with!");
6470 if (FixedVT.getVectorNumElements() > InVT.getVectorNumElements())
6471 InOp = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, FixedVT,
6472 DAG.getUNDEF(FixedVT), InOp,
6473 DAG.getVectorIdxConstant(0, DL));
6474 else
6475 InOp = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, FixedVT, InOp,
6476 DAG.getVectorIdxConstant(0, DL));
6477 break;
6478 }
6479 }
6480 InVT = InOp.getValueType();
6481 if (InVT.getSizeInBits() != VT.getSizeInBits())
6482 // We couldn't find a legal vector type that was a widening of the input
6483 // and could be extended in-register to the result type, so we have to
6484 // scalarize.
6485 return WidenVecOp_Convert(N);
6486 }
6487
6488 // Use special DAG nodes to represent the operation of extending the
6489 // low lanes.
6490 switch (N->getOpcode()) {
6491 default:
6492 llvm_unreachable("Extend legalization on extend operation!");
6493 case ISD::ANY_EXTEND:
6494 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, VT, InOp);
6495 case ISD::SIGN_EXTEND:
6496 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, VT, InOp);
6497 case ISD::ZERO_EXTEND:
6498 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, VT, InOp);
6499 }
6500}
6501
6502SDValue DAGTypeLegalizer::WidenVecOp_CMP(SDNode *N) {
6503 SDLoc dl(N);
6504
6505 EVT OpVT = N->getOperand(0).getValueType();
6506 EVT ResVT = N->getValueType(0);
6507 SDValue LHS = GetWidenedVector(N->getOperand(0));
6508 SDValue RHS = GetWidenedVector(N->getOperand(1));
6509
6510 // 1. EXTRACT_SUBVECTOR
6511 // 2. SIGN_EXTEND/ZERO_EXTEND
6512 // 3. CMP
6513 LHS = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, OpVT, LHS,
6514 DAG.getVectorIdxConstant(0, dl));
6515 RHS = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, OpVT, RHS,
6516 DAG.getVectorIdxConstant(0, dl));
6517
6518 // At this point the result type is guaranteed to be valid, so we can use it
6519 // as the operand type by extending it appropriately
6520 ISD::NodeType ExtendOpcode =
6521 N->getOpcode() == ISD::SCMP ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
6522 LHS = DAG.getNode(ExtendOpcode, dl, ResVT, LHS);
6523 RHS = DAG.getNode(ExtendOpcode, dl, ResVT, RHS);
6524
6525 return DAG.getNode(N->getOpcode(), dl, ResVT, LHS, RHS);
6526}
6527
6528SDValue DAGTypeLegalizer::WidenVecOp_UnrollVectorOp(SDNode *N) {
6529 // The result (and first input) is legal, but the second input is illegal.
6530 // We can't do much to fix that, so just unroll and let the extracts off of
6531 // the second input be widened as needed later.
6532 return DAG.UnrollVectorOp(N);
6533}
6534
6535SDValue DAGTypeLegalizer::WidenVecOp_IS_FPCLASS(SDNode *N) {
6536 SDLoc DL(N);
6537 EVT ResultVT = N->getValueType(0);
6538 SDValue Test = N->getOperand(1);
6539 SDValue WideArg = GetWidenedVector(N->getOperand(0));
6540
6541 // Process this node similarly to SETCC.
6542 EVT WideResultVT = getSetCCResultType(WideArg.getValueType());
6543 if (ResultVT.getScalarType() == MVT::i1)
6544 WideResultVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
6545 WideResultVT.getVectorNumElements());
6546
6547 SDValue WideNode = DAG.getNode(ISD::IS_FPCLASS, DL, WideResultVT,
6548 {WideArg, Test}, N->getFlags());
6549
6550 // Extract the needed results from the result vector.
6551 EVT ResVT =
6552 EVT::getVectorVT(*DAG.getContext(), WideResultVT.getVectorElementType(),
6553 ResultVT.getVectorNumElements());
6554 SDValue CC = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, ResVT, WideNode,
6555 DAG.getVectorIdxConstant(0, DL));
6556
6557 EVT OpVT = N->getOperand(0).getValueType();
6558 ISD::NodeType ExtendCode =
6560 return DAG.getNode(ExtendCode, DL, ResultVT, CC);
6561}
6562
6563SDValue DAGTypeLegalizer::WidenVecOp_Convert(SDNode *N) {
6564 // Since the result is legal and the input is illegal.
6565 EVT VT = N->getValueType(0);
6566 EVT EltVT = VT.getVectorElementType();
6567 SDLoc dl(N);
6568 SDValue InOp = N->getOperand(N->isStrictFPOpcode() ? 1 : 0);
6569 assert(getTypeAction(InOp.getValueType()) ==
6571 "Unexpected type action");
6572 InOp = GetWidenedVector(InOp);
6573 EVT InVT = InOp.getValueType();
6574 unsigned Opcode = N->getOpcode();
6575
6576 // See if a widened result type would be legal, if so widen the node.
6577 // FIXME: This isn't safe for StrictFP. Other optimization here is needed.
6578 EVT WideVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
6579 InVT.getVectorElementCount());
6580 if (TLI.isTypeLegal(WideVT) && !N->isStrictFPOpcode()) {
6581 SDValue Res;
6582 if (N->isStrictFPOpcode()) {
6583 if (Opcode == ISD::STRICT_FP_ROUND)
6584 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
6585 { N->getOperand(0), InOp, N->getOperand(2) });
6586 else
6587 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
6588 { N->getOperand(0), InOp });
6589 // Legalize the chain result - switch anything that used the old chain to
6590 // use the new one.
6591 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6592 } else {
6593 if (Opcode == ISD::FP_ROUND)
6594 Res = DAG.getNode(Opcode, dl, WideVT, InOp, N->getOperand(1));
6595 else
6596 Res = DAG.getNode(Opcode, dl, WideVT, InOp);
6597 }
6598 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, Res,
6599 DAG.getVectorIdxConstant(0, dl));
6600 }
6601
6602 EVT InEltVT = InVT.getVectorElementType();
6603
6604 // Unroll the convert into some scalar code and create a nasty build vector.
6605 unsigned NumElts = VT.getVectorNumElements();
6606 SmallVector<SDValue, 16> Ops(NumElts);
6607 if (N->isStrictFPOpcode()) {
6608 SmallVector<SDValue, 4> NewOps(N->op_begin(), N->op_end());
6609 SmallVector<SDValue, 32> OpChains;
6610 for (unsigned i=0; i < NumElts; ++i) {
6611 NewOps[1] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, InEltVT, InOp,
6612 DAG.getVectorIdxConstant(i, dl));
6613 Ops[i] = DAG.getNode(Opcode, dl, { EltVT, MVT::Other }, NewOps);
6614 OpChains.push_back(Ops[i].getValue(1));
6615 }
6616 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OpChains);
6617 ReplaceValueWith(SDValue(N, 1), NewChain);
6618 } else {
6619 for (unsigned i = 0; i < NumElts; ++i)
6620 Ops[i] = DAG.getNode(Opcode, dl, EltVT,
6621 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, InEltVT,
6622 InOp, DAG.getVectorIdxConstant(i, dl)));
6623 }
6624
6625 return DAG.getBuildVector(VT, dl, Ops);
6626}
6627
6628SDValue DAGTypeLegalizer::WidenVecOp_FP_TO_XINT_SAT(SDNode *N) {
6629 EVT DstVT = N->getValueType(0);
6630 SDValue Src = GetWidenedVector(N->getOperand(0));
6631 EVT SrcVT = Src.getValueType();
6632 ElementCount WideNumElts = SrcVT.getVectorElementCount();
6633 SDLoc dl(N);
6634
6635 // See if a widened result type would be legal, if so widen the node.
6636 EVT WideDstVT = EVT::getVectorVT(*DAG.getContext(),
6637 DstVT.getVectorElementType(), WideNumElts);
6638 if (TLI.isTypeLegal(WideDstVT)) {
6639 SDValue Res =
6640 DAG.getNode(N->getOpcode(), dl, WideDstVT, Src, N->getOperand(1));
6641 return DAG.getNode(
6642 ISD::EXTRACT_SUBVECTOR, dl, DstVT, Res,
6643 DAG.getConstant(0, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
6644 }
6645
6646 // Give up and unroll.
6647 return DAG.UnrollVectorOp(N);
6648}
6649
6650SDValue DAGTypeLegalizer::WidenVecOp_BITCAST(SDNode *N) {
6651 EVT VT = N->getValueType(0);
6652 SDValue InOp = GetWidenedVector(N->getOperand(0));
6653 EVT InWidenVT = InOp.getValueType();
6654 SDLoc dl(N);
6655
6656 // Check if we can convert between two legal vector types and extract.
6657 TypeSize InWidenSize = InWidenVT.getSizeInBits();
6659 // x86mmx is not an acceptable vector element type, so don't try.
6660 if (!VT.isVector() && VT != MVT::x86mmx &&
6661 InWidenSize.hasKnownScalarFactor(Size)) {
6662 unsigned NewNumElts = InWidenSize.getKnownScalarFactor(Size);
6663 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), VT, NewNumElts);
6664 if (TLI.isTypeLegal(NewVT)) {
6665 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
6666 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, VT, BitOp,
6667 DAG.getVectorIdxConstant(0, dl));
6668 }
6669 }
6670
6671 // Handle a case like bitcast v12i8 -> v3i32. Normally that would get widened
6672 // to v16i8 -> v4i32, but for a target where v3i32 is legal but v12i8 is not,
6673 // we end up here. Handling the case here with EXTRACT_SUBVECTOR avoids
6674 // having to copy via memory.
6675 if (VT.isVector()) {
6676 EVT EltVT = VT.getVectorElementType();
6677 unsigned EltSize = EltVT.getFixedSizeInBits();
6678 if (InWidenSize.isKnownMultipleOf(EltSize)) {
6679 ElementCount NewNumElts =
6680 (InWidenVT.getVectorElementCount() * InWidenVT.getScalarSizeInBits())
6681 .divideCoefficientBy(EltSize);
6682 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NewNumElts);
6683 if (TLI.isTypeLegal(NewVT)) {
6684 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
6685 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, BitOp,
6686 DAG.getVectorIdxConstant(0, dl));
6687 }
6688 }
6689 }
6690
6691 return CreateStackStoreLoad(InOp, VT);
6692}
6693
6694SDValue DAGTypeLegalizer::WidenVecOp_CONCAT_VECTORS(SDNode *N) {
6695 EVT VT = N->getValueType(0);
6696 EVT EltVT = VT.getVectorElementType();
6697 EVT InVT = N->getOperand(0).getValueType();
6698 SDLoc dl(N);
6699
6700 // If the widen width for this operand is the same as the width of the concat
6701 // and all but the first operand is undef, just use the widened operand.
6702 unsigned NumOperands = N->getNumOperands();
6703 if (VT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
6704 unsigned i;
6705 for (i = 1; i < NumOperands; ++i)
6706 if (!N->getOperand(i).isUndef())
6707 break;
6708
6709 if (i == NumOperands)
6710 return GetWidenedVector(N->getOperand(0));
6711 }
6712
6713 // Otherwise, fall back to a nasty build vector.
6714 unsigned NumElts = VT.getVectorNumElements();
6715 SmallVector<SDValue, 16> Ops(NumElts);
6716
6717 unsigned NumInElts = InVT.getVectorNumElements();
6718
6719 unsigned Idx = 0;
6720 for (unsigned i=0; i < NumOperands; ++i) {
6721 SDValue InOp = N->getOperand(i);
6722 assert(getTypeAction(InOp.getValueType()) ==
6724 "Unexpected type action");
6725 InOp = GetWidenedVector(InOp);
6726 for (unsigned j = 0; j < NumInElts; ++j)
6727 Ops[Idx++] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp,
6728 DAG.getVectorIdxConstant(j, dl));
6729 }
6730 return DAG.getBuildVector(VT, dl, Ops);
6731}
6732
6733SDValue DAGTypeLegalizer::WidenVecOp_INSERT_SUBVECTOR(SDNode *N) {
6734 EVT VT = N->getValueType(0);
6735 SDValue SubVec = N->getOperand(1);
6736 SDValue InVec = N->getOperand(0);
6737
6738 if (getTypeAction(SubVec.getValueType()) == TargetLowering::TypeWidenVector)
6739 SubVec = GetWidenedVector(SubVec);
6740
6741 EVT SubVT = SubVec.getValueType();
6742
6743 // Whether or not all the elements of the widened SubVec will be inserted into
6744 // valid indices of VT.
6745 bool IndicesValid = false;
6746 // If we statically know that VT can fit SubVT, the indices are valid.
6747 if (VT.knownBitsGE(SubVT))
6748 IndicesValid = true;
6749 else if (VT.isScalableVector() && SubVT.isFixedLengthVector()) {
6750 // Otherwise, if we're inserting a fixed vector into a scalable vector and
6751 // we know the minimum vscale we can work out if it's valid ourselves.
6752 Attribute Attr = DAG.getMachineFunction().getFunction().getFnAttribute(
6753 Attribute::VScaleRange);
6754 if (Attr.isValid()) {
6755 unsigned VScaleMin = Attr.getVScaleRangeMin();
6756 if (VT.getSizeInBits().getKnownMinValue() * VScaleMin >=
6757 SubVT.getFixedSizeInBits())
6758 IndicesValid = true;
6759 }
6760 }
6761
6762 // We need to make sure that the indices are still valid, otherwise we might
6763 // widen what was previously well-defined to something undefined.
6764 if (IndicesValid && InVec.isUndef() && N->getConstantOperandVal(2) == 0)
6765 return DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), VT, InVec, SubVec,
6766 N->getOperand(2));
6767
6768 report_fatal_error("Don't know how to widen the operands for "
6769 "INSERT_SUBVECTOR");
6770}
6771
6772SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
6773 SDValue InOp = GetWidenedVector(N->getOperand(0));
6774 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SDLoc(N),
6775 N->getValueType(0), InOp, N->getOperand(1));
6776}
6777
6778SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
6779 SDValue InOp = GetWidenedVector(N->getOperand(0));
6780 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
6781 N->getValueType(0), InOp, N->getOperand(1));
6782}
6783
6784SDValue DAGTypeLegalizer::WidenVecOp_EXTEND_VECTOR_INREG(SDNode *N) {
6785 SDValue InOp = GetWidenedVector(N->getOperand(0));
6786 return DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0), InOp);
6787}
6788
6789SDValue DAGTypeLegalizer::WidenVecOp_STORE(SDNode *N) {
6790 // We have to widen the value, but we want only to store the original
6791 // vector type.
6792 StoreSDNode *ST = cast<StoreSDNode>(N);
6793
6794 if (!ST->getMemoryVT().getScalarType().isByteSized())
6795 return TLI.scalarizeVectorStore(ST, DAG);
6796
6797 if (ST->isTruncatingStore())
6798 return TLI.scalarizeVectorStore(ST, DAG);
6799
6800 // Generate a vector-predicated store if it is custom/legal on the target.
6801 // To avoid possible recursion, only do this if the widened mask type is
6802 // legal.
6803 // FIXME: Not all targets may support EVL in VP_STORE. These will have been
6804 // removed from the IR by the ExpandVectorPredication pass but we're
6805 // reintroducing them here.
6806 SDValue StVal = ST->getValue();
6807 EVT StVT = StVal.getValueType();
6808 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), StVT);
6809 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
6810 WideVT.getVectorElementCount());
6811
6812 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
6813 TLI.isTypeLegal(WideMaskVT)) {
6814 // Widen the value.
6815 SDLoc DL(N);
6816 StVal = GetWidenedVector(StVal);
6817 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
6818 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
6819 StVT.getVectorElementCount());
6820 return DAG.getStoreVP(ST->getChain(), DL, StVal, ST->getBasePtr(),
6821 DAG.getUNDEF(ST->getBasePtr().getValueType()), Mask,
6822 EVL, StVT, ST->getMemOperand(),
6823 ST->getAddressingMode());
6824 }
6825
6827 if (GenWidenVectorStores(StChain, ST)) {
6828 if (StChain.size() == 1)
6829 return StChain[0];
6830
6831 return DAG.getNode(ISD::TokenFactor, SDLoc(ST), MVT::Other, StChain);
6832 }
6833
6834 report_fatal_error("Unable to widen vector store");
6835}
6836
6837SDValue DAGTypeLegalizer::WidenVecOp_VP_STORE(SDNode *N, unsigned OpNo) {
6838 assert((OpNo == 1 || OpNo == 3) &&
6839 "Can widen only data or mask operand of vp_store");
6840 VPStoreSDNode *ST = cast<VPStoreSDNode>(N);
6841 SDValue Mask = ST->getMask();
6842 SDValue StVal = ST->getValue();
6843 SDLoc dl(N);
6844
6845 if (OpNo == 1) {
6846 // Widen the value.
6847 StVal = GetWidenedVector(StVal);
6848
6849 // We only handle the case where the mask needs widening to an
6850 // identically-sized type as the vector inputs.
6851 assert(getTypeAction(Mask.getValueType()) ==
6853 "Unable to widen VP store");
6854 Mask = GetWidenedVector(Mask);
6855 } else {
6856 Mask = GetWidenedVector(Mask);
6857
6858 // We only handle the case where the stored value needs widening to an
6859 // identically-sized type as the mask.
6860 assert(getTypeAction(StVal.getValueType()) ==
6862 "Unable to widen VP store");
6863 StVal = GetWidenedVector(StVal);
6864 }
6865
6866 assert(Mask.getValueType().getVectorElementCount() ==
6868 "Mask and data vectors should have the same number of elements");
6869 return DAG.getStoreVP(ST->getChain(), dl, StVal, ST->getBasePtr(),
6870 ST->getOffset(), Mask, ST->getVectorLength(),
6871 ST->getMemoryVT(), ST->getMemOperand(),
6872 ST->getAddressingMode(), ST->isTruncatingStore(),
6873 ST->isCompressingStore());
6874}
6875
6876SDValue DAGTypeLegalizer::WidenVecOp_VP_STRIDED_STORE(SDNode *N,
6877 unsigned OpNo) {
6878 assert((OpNo == 1 || OpNo == 4) &&
6879 "Can widen only data or mask operand of vp_strided_store");
6880 VPStridedStoreSDNode *SST = cast<VPStridedStoreSDNode>(N);
6881 SDValue Mask = SST->getMask();
6882 SDValue StVal = SST->getValue();
6883 SDLoc DL(N);
6884
6885 if (OpNo == 1)
6886 assert(getTypeAction(Mask.getValueType()) ==
6888 "Unable to widen VP strided store");
6889 else
6890 assert(getTypeAction(StVal.getValueType()) ==
6892 "Unable to widen VP strided store");
6893
6894 StVal = GetWidenedVector(StVal);
6895 Mask = GetWidenedVector(Mask);
6896
6898 Mask.getValueType().getVectorElementCount() &&
6899 "Data and mask vectors should have the same number of elements");
6900
6901 return DAG.getStridedStoreVP(
6902 SST->getChain(), DL, StVal, SST->getBasePtr(), SST->getOffset(),
6903 SST->getStride(), Mask, SST->getVectorLength(), SST->getMemoryVT(),
6904 SST->getMemOperand(), SST->getAddressingMode(), SST->isTruncatingStore(),
6905 SST->isCompressingStore());
6906}
6907
6908SDValue DAGTypeLegalizer::WidenVecOp_MSTORE(SDNode *N, unsigned OpNo) {
6909 assert((OpNo == 1 || OpNo == 4) &&
6910 "Can widen only data or mask operand of mstore");
6911 MaskedStoreSDNode *MST = cast<MaskedStoreSDNode>(N);
6912 SDValue Mask = MST->getMask();
6913 EVT MaskVT = Mask.getValueType();
6914 SDValue StVal = MST->getValue();
6915 SDLoc dl(N);
6916
6917 if (OpNo == 1) {
6918 // Widen the value.
6919 StVal = GetWidenedVector(StVal);
6920
6921 // The mask should be widened as well.
6922 EVT WideVT = StVal.getValueType();
6923 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
6924 MaskVT.getVectorElementType(),
6925 WideVT.getVectorNumElements());
6926 Mask = ModifyToType(Mask, WideMaskVT, true);
6927 } else {
6928 // Widen the mask.
6929 EVT WideMaskVT = TLI.getTypeToTransformTo(*DAG.getContext(), MaskVT);
6930 Mask = ModifyToType(Mask, WideMaskVT, true);
6931
6932 EVT ValueVT = StVal.getValueType();
6933 EVT WideVT = EVT::getVectorVT(*DAG.getContext(),
6934 ValueVT.getVectorElementType(),
6935 WideMaskVT.getVectorNumElements());
6936 StVal = ModifyToType(StVal, WideVT);
6937 }
6938
6939 assert(Mask.getValueType().getVectorNumElements() ==
6941 "Mask and data vectors should have the same number of elements");
6942 return DAG.getMaskedStore(MST->getChain(), dl, StVal, MST->getBasePtr(),
6943 MST->getOffset(), Mask, MST->getMemoryVT(),
6944 MST->getMemOperand(), MST->getAddressingMode(),
6945 false, MST->isCompressingStore());
6946}
6947
6948SDValue DAGTypeLegalizer::WidenVecOp_MGATHER(SDNode *N, unsigned OpNo) {
6949 assert(OpNo == 4 && "Can widen only the index of mgather");
6950 auto *MG = cast<MaskedGatherSDNode>(N);
6951 SDValue DataOp = MG->getPassThru();
6952 SDValue Mask = MG->getMask();
6953 SDValue Scale = MG->getScale();
6954
6955 // Just widen the index. It's allowed to have extra elements.
6956 SDValue Index = GetWidenedVector(MG->getIndex());
6957
6958 SDLoc dl(N);
6959 SDValue Ops[] = {MG->getChain(), DataOp, Mask, MG->getBasePtr(), Index,
6960 Scale};
6961 SDValue Res = DAG.getMaskedGather(MG->getVTList(), MG->getMemoryVT(), dl, Ops,
6962 MG->getMemOperand(), MG->getIndexType(),
6963 MG->getExtensionType());
6964 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6965 ReplaceValueWith(SDValue(N, 0), Res.getValue(0));
6966 return SDValue();
6967}
6968
6969SDValue DAGTypeLegalizer::WidenVecOp_MSCATTER(SDNode *N, unsigned OpNo) {
6970 MaskedScatterSDNode *MSC = cast<MaskedScatterSDNode>(N);
6971 SDValue DataOp = MSC->getValue();
6972 SDValue Mask = MSC->getMask();
6973 SDValue Index = MSC->getIndex();
6974 SDValue Scale = MSC->getScale();
6975 EVT WideMemVT = MSC->getMemoryVT();
6976
6977 if (OpNo == 1) {
6978 DataOp = GetWidenedVector(DataOp);
6979 unsigned NumElts = DataOp.getValueType().getVectorNumElements();
6980
6981 // Widen index.
6982 EVT IndexVT = Index.getValueType();
6983 EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
6984 IndexVT.getVectorElementType(), NumElts);
6985 Index = ModifyToType(Index, WideIndexVT);
6986
6987 // The mask should be widened as well.
6988 EVT MaskVT = Mask.getValueType();
6989 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
6990 MaskVT.getVectorElementType(), NumElts);
6991 Mask = ModifyToType(Mask, WideMaskVT, true);
6992
6993 // Widen the MemoryType
6994 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
6995 MSC->getMemoryVT().getScalarType(), NumElts);
6996 } else if (OpNo == 4) {
6997 // Just widen the index. It's allowed to have extra elements.
6998 Index = GetWidenedVector(Index);
6999 } else
7000 llvm_unreachable("Can't widen this operand of mscatter");
7001
7002 SDValue Ops[] = {MSC->getChain(), DataOp, Mask, MSC->getBasePtr(), Index,
7003 Scale};
7004 return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N),
7005 Ops, MSC->getMemOperand(), MSC->getIndexType(),
7006 MSC->isTruncatingStore());
7007}
7008
7009SDValue DAGTypeLegalizer::WidenVecOp_VP_SCATTER(SDNode *N, unsigned OpNo) {
7010 VPScatterSDNode *VPSC = cast<VPScatterSDNode>(N);
7011 SDValue DataOp = VPSC->getValue();
7012 SDValue Mask = VPSC->getMask();
7013 SDValue Index = VPSC->getIndex();
7014 SDValue Scale = VPSC->getScale();
7015 EVT WideMemVT = VPSC->getMemoryVT();
7016
7017 if (OpNo == 1) {
7018 DataOp = GetWidenedVector(DataOp);
7019 Index = GetWidenedVector(Index);
7020 const auto WideEC = DataOp.getValueType().getVectorElementCount();
7021 Mask = GetWidenedMask(Mask, WideEC);
7022 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
7023 VPSC->getMemoryVT().getScalarType(), WideEC);
7024 } else if (OpNo == 3) {
7025 // Just widen the index. It's allowed to have extra elements.
7026 Index = GetWidenedVector(Index);
7027 } else
7028 llvm_unreachable("Can't widen this operand of VP_SCATTER");
7029
7030 SDValue Ops[] = {
7031 VPSC->getChain(), DataOp, VPSC->getBasePtr(), Index, Scale, Mask,
7032 VPSC->getVectorLength()};
7033 return DAG.getScatterVP(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N), Ops,
7034 VPSC->getMemOperand(), VPSC->getIndexType());
7035}
7036
7037SDValue DAGTypeLegalizer::WidenVecOp_SETCC(SDNode *N) {
7038 SDValue InOp0 = GetWidenedVector(N->getOperand(0));
7039 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
7040 SDLoc dl(N);
7041 EVT VT = N->getValueType(0);
7042
7043 // WARNING: In this code we widen the compare instruction with garbage.
7044 // This garbage may contain denormal floats which may be slow. Is this a real
7045 // concern ? Should we zero the unused lanes if this is a float compare ?
7046
7047 // Get a new SETCC node to compare the newly widened operands.
7048 // Only some of the compared elements are legal.
7049 EVT SVT = getSetCCResultType(InOp0.getValueType());
7050 // The result type is legal, if its vXi1, keep vXi1 for the new SETCC.
7051 if (VT.getScalarType() == MVT::i1)
7052 SVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
7053 SVT.getVectorElementCount());
7054
7055 SDValue WideSETCC = DAG.getNode(ISD::SETCC, SDLoc(N),
7056 SVT, InOp0, InOp1, N->getOperand(2));
7057
7058 // Extract the needed results from the result vector.
7059 EVT ResVT = EVT::getVectorVT(*DAG.getContext(),
7062 SDValue CC = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, ResVT, WideSETCC,
7063 DAG.getVectorIdxConstant(0, dl));
7064
7065 EVT OpVT = N->getOperand(0).getValueType();
7066 ISD::NodeType ExtendCode =
7068 return DAG.getNode(ExtendCode, dl, VT, CC);
7069}
7070
7071SDValue DAGTypeLegalizer::WidenVecOp_STRICT_FSETCC(SDNode *N) {
7072 SDValue Chain = N->getOperand(0);
7073 SDValue LHS = GetWidenedVector(N->getOperand(1));
7074 SDValue RHS = GetWidenedVector(N->getOperand(2));
7075 SDValue CC = N->getOperand(3);
7076 SDLoc dl(N);
7077
7078 EVT VT = N->getValueType(0);
7079 EVT EltVT = VT.getVectorElementType();
7080 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
7081 unsigned NumElts = VT.getVectorNumElements();
7082
7083 // Unroll into a build vector.
7084 SmallVector<SDValue, 8> Scalars(NumElts);
7085 SmallVector<SDValue, 8> Chains(NumElts);
7086
7087 for (unsigned i = 0; i != NumElts; ++i) {
7088 SDValue LHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, LHS,
7089 DAG.getVectorIdxConstant(i, dl));
7090 SDValue RHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, RHS,
7091 DAG.getVectorIdxConstant(i, dl));
7092
7093 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
7094 {Chain, LHSElem, RHSElem, CC});
7095 Chains[i] = Scalars[i].getValue(1);
7096 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
7097 DAG.getBoolConstant(true, dl, EltVT, VT),
7098 DAG.getBoolConstant(false, dl, EltVT, VT));
7099 }
7100
7101 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
7102 ReplaceValueWith(SDValue(N, 1), NewChain);
7103
7104 return DAG.getBuildVector(VT, dl, Scalars);
7105}
7106
7107SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE(SDNode *N) {
7108 SDLoc dl(N);
7109 SDValue Op = GetWidenedVector(N->getOperand(0));
7110 EVT OrigVT = N->getOperand(0).getValueType();
7111 EVT WideVT = Op.getValueType();
7112 EVT ElemVT = OrigVT.getVectorElementType();
7113 SDNodeFlags Flags = N->getFlags();
7114
7115 unsigned Opc = N->getOpcode();
7116 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
7117 SDValue NeutralElem = DAG.getNeutralElement(BaseOpc, dl, ElemVT, Flags);
7118 assert(NeutralElem && "Neutral element must exist");
7119
7120 // Pad the vector with the neutral element.
7121 unsigned OrigElts = OrigVT.getVectorMinNumElements();
7122 unsigned WideElts = WideVT.getVectorMinNumElements();
7123
7124 if (WideVT.isScalableVector()) {
7125 unsigned GCD = std::gcd(OrigElts, WideElts);
7126 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
7128 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
7129 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
7130 Op = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WideVT, Op, SplatNeutral,
7131 DAG.getVectorIdxConstant(Idx, dl));
7132 return DAG.getNode(Opc, dl, N->getValueType(0), Op, Flags);
7133 }
7134
7135 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
7136 Op = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, WideVT, Op, NeutralElem,
7137 DAG.getVectorIdxConstant(Idx, dl));
7138
7139 return DAG.getNode(Opc, dl, N->getValueType(0), Op, Flags);
7140}
7141
7142SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE_SEQ(SDNode *N) {
7143 SDLoc dl(N);
7144 SDValue AccOp = N->getOperand(0);
7145 SDValue VecOp = N->getOperand(1);
7146 SDValue Op = GetWidenedVector(VecOp);
7147
7148 EVT OrigVT = VecOp.getValueType();
7149 EVT WideVT = Op.getValueType();
7150 EVT ElemVT = OrigVT.getVectorElementType();
7151 SDNodeFlags Flags = N->getFlags();
7152
7153 unsigned Opc = N->getOpcode();
7154 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
7155 SDValue NeutralElem = DAG.getNeutralElement(BaseOpc, dl, ElemVT, Flags);
7156
7157 // Pad the vector with the neutral element.
7158 unsigned OrigElts = OrigVT.getVectorMinNumElements();
7159 unsigned WideElts = WideVT.getVectorMinNumElements();
7160
7161 if (WideVT.isScalableVector()) {
7162 unsigned GCD = std::gcd(OrigElts, WideElts);
7163 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
7165 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
7166 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
7167 Op = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WideVT, Op, SplatNeutral,
7168 DAG.getVectorIdxConstant(Idx, dl));
7169 return DAG.getNode(Opc, dl, N->getValueType(0), AccOp, Op, Flags);
7170 }
7171
7172 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
7173 Op = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, WideVT, Op, NeutralElem,
7174 DAG.getVectorIdxConstant(Idx, dl));
7175
7176 return DAG.getNode(Opc, dl, N->getValueType(0), AccOp, Op, Flags);
7177}
7178
7179SDValue DAGTypeLegalizer::WidenVecOp_VP_REDUCE(SDNode *N) {
7180 assert(N->isVPOpcode() && "Expected VP opcode");
7181
7182 SDLoc dl(N);
7183 SDValue Op = GetWidenedVector(N->getOperand(1));
7184 SDValue Mask = GetWidenedMask(N->getOperand(2),
7185 Op.getValueType().getVectorElementCount());
7186
7187 return DAG.getNode(N->getOpcode(), dl, N->getValueType(0),
7188 {N->getOperand(0), Op, Mask, N->getOperand(3)},
7189 N->getFlags());
7190}
7191
7192SDValue DAGTypeLegalizer::WidenVecOp_VSELECT(SDNode *N) {
7193 // This only gets called in the case that the left and right inputs and
7194 // result are of a legal odd vector type, and the condition is illegal i1 of
7195 // the same odd width that needs widening.
7196 EVT VT = N->getValueType(0);
7197 assert(VT.isVector() && !VT.isPow2VectorType() && isTypeLegal(VT));
7198
7199 SDValue Cond = GetWidenedVector(N->getOperand(0));
7200 SDValue LeftIn = DAG.WidenVector(N->getOperand(1), SDLoc(N));
7201 SDValue RightIn = DAG.WidenVector(N->getOperand(2), SDLoc(N));
7202 SDLoc DL(N);
7203
7204 SDValue Select = DAG.getNode(N->getOpcode(), DL, LeftIn.getValueType(), Cond,
7205 LeftIn, RightIn);
7206 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, Select,
7207 DAG.getVectorIdxConstant(0, DL));
7208}
7209
7210SDValue DAGTypeLegalizer::WidenVecOp_VP_CttzElements(SDNode *N) {
7211 SDLoc DL(N);
7212 SDValue Source = GetWidenedVector(N->getOperand(0));
7213 EVT SrcVT = Source.getValueType();
7214 SDValue Mask =
7215 GetWidenedMask(N->getOperand(1), SrcVT.getVectorElementCount());
7216
7217 return DAG.getNode(N->getOpcode(), DL, N->getValueType(0),
7218 {Source, Mask, N->getOperand(2)}, N->getFlags());
7219}
7220
7221//===----------------------------------------------------------------------===//
7222// Vector Widening Utilities
7223//===----------------------------------------------------------------------===//
7224
7225// Utility function to find the type to chop up a widen vector for load/store
7226// TLI: Target lowering used to determine legal types.
7227// Width: Width left need to load/store.
7228// WidenVT: The widen vector type to load to/store from
7229// Align: If 0, don't allow use of a wider type
7230// WidenEx: If Align is not 0, the amount additional we can load/store from.
7231
7232static std::optional<EVT> findMemType(SelectionDAG &DAG,
7233 const TargetLowering &TLI, unsigned Width,
7234 EVT WidenVT, unsigned Align = 0,
7235 unsigned WidenEx = 0) {
7236 EVT WidenEltVT = WidenVT.getVectorElementType();
7237 const bool Scalable = WidenVT.isScalableVector();
7238 unsigned WidenWidth = WidenVT.getSizeInBits().getKnownMinValue();
7239 unsigned WidenEltWidth = WidenEltVT.getSizeInBits();
7240 unsigned AlignInBits = Align*8;
7241
7242 // If we have one element to load/store, return it.
7243 EVT RetVT = WidenEltVT;
7244 if (!Scalable && Width == WidenEltWidth)
7245 return RetVT;
7246
7247 // Don't bother looking for an integer type if the vector is scalable, skip
7248 // to vector types.
7249 if (!Scalable) {
7250 // See if there is larger legal integer than the element type to load/store.
7251 for (EVT MemVT : reverse(MVT::integer_valuetypes())) {
7252 unsigned MemVTWidth = MemVT.getSizeInBits();
7253 if (MemVT.getSizeInBits() <= WidenEltWidth)
7254 break;
7255 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
7256 if ((Action == TargetLowering::TypeLegal ||
7258 (WidenWidth % MemVTWidth) == 0 &&
7259 isPowerOf2_32(WidenWidth / MemVTWidth) &&
7260 (MemVTWidth <= Width ||
7261 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
7262 if (MemVTWidth == WidenWidth)
7263 return MemVT;
7264 RetVT = MemVT;
7265 break;
7266 }
7267 }
7268 }
7269
7270 // See if there is a larger vector type to load/store that has the same vector
7271 // element type and is evenly divisible with the WidenVT.
7272 for (EVT MemVT : reverse(MVT::vector_valuetypes())) {
7273 // Skip vector MVTs which don't match the scalable property of WidenVT.
7274 if (Scalable != MemVT.isScalableVector())
7275 continue;
7276 unsigned MemVTWidth = MemVT.getSizeInBits().getKnownMinValue();
7277 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
7278 if ((Action == TargetLowering::TypeLegal ||
7280 WidenEltVT == MemVT.getVectorElementType() &&
7281 (WidenWidth % MemVTWidth) == 0 &&
7282 isPowerOf2_32(WidenWidth / MemVTWidth) &&
7283 (MemVTWidth <= Width ||
7284 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
7285 if (RetVT.getFixedSizeInBits() < MemVTWidth || MemVT == WidenVT)
7286 return MemVT;
7287 }
7288 }
7289
7290 // Using element-wise loads and stores for widening operations is not
7291 // supported for scalable vectors
7292 if (Scalable)
7293 return std::nullopt;
7294
7295 return RetVT;
7296}
7297
7298// Builds a vector type from scalar loads
7299// VecTy: Resulting Vector type
7300// LDOps: Load operators to build a vector type
7301// [Start,End) the list of loads to use.
7304 unsigned Start, unsigned End) {
7305 SDLoc dl(LdOps[Start]);
7306 EVT LdTy = LdOps[Start].getValueType();
7307 unsigned Width = VecTy.getSizeInBits();
7308 unsigned NumElts = Width / LdTy.getSizeInBits();
7309 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), LdTy, NumElts);
7310
7311 unsigned Idx = 1;
7312 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT,LdOps[Start]);
7313
7314 for (unsigned i = Start + 1; i != End; ++i) {
7315 EVT NewLdTy = LdOps[i].getValueType();
7316 if (NewLdTy != LdTy) {
7317 NumElts = Width / NewLdTy.getSizeInBits();
7318 NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewLdTy, NumElts);
7319 VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, VecOp);
7320 // Readjust position and vector position based on new load type.
7321 Idx = Idx * LdTy.getSizeInBits() / NewLdTy.getSizeInBits();
7322 LdTy = NewLdTy;
7323 }
7324 VecOp = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, NewVecVT, VecOp, LdOps[i],
7325 DAG.getVectorIdxConstant(Idx++, dl));
7326 }
7327 return DAG.getNode(ISD::BITCAST, dl, VecTy, VecOp);
7328}
7329
7330SDValue DAGTypeLegalizer::GenWidenVectorLoads(SmallVectorImpl<SDValue> &LdChain,
7331 LoadSDNode *LD) {
7332 // The strategy assumes that we can efficiently load power-of-two widths.
7333 // The routine chops the vector into the largest vector loads with the same
7334 // element type or scalar loads and then recombines it to the widen vector
7335 // type.
7336 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
7337 EVT LdVT = LD->getMemoryVT();
7338 SDLoc dl(LD);
7339 assert(LdVT.isVector() && WidenVT.isVector());
7340 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
7342
7343 // Load information
7344 SDValue Chain = LD->getChain();
7345 SDValue BasePtr = LD->getBasePtr();
7346 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
7347 AAMDNodes AAInfo = LD->getAAInfo();
7348
7349 TypeSize LdWidth = LdVT.getSizeInBits();
7350 TypeSize WidenWidth = WidenVT.getSizeInBits();
7351 TypeSize WidthDiff = WidenWidth - LdWidth;
7352 // Allow wider loads if they are sufficiently aligned to avoid memory faults
7353 // and if the original load is simple.
7354 unsigned LdAlign =
7355 (!LD->isSimple() || LdVT.isScalableVector()) ? 0 : LD->getAlign().value();
7356
7357 // Find the vector type that can load from.
7358 std::optional<EVT> FirstVT =
7359 findMemType(DAG, TLI, LdWidth.getKnownMinValue(), WidenVT, LdAlign,
7360 WidthDiff.getKnownMinValue());
7361
7362 if (!FirstVT)
7363 return SDValue();
7364
7365 SmallVector<EVT, 8> MemVTs;
7366 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
7367
7368 // Unless we're able to load in one instruction we must work out how to load
7369 // the remainder.
7370 if (!TypeSize::isKnownLE(LdWidth, FirstVTWidth)) {
7371 std::optional<EVT> NewVT = FirstVT;
7372 TypeSize RemainingWidth = LdWidth;
7373 TypeSize NewVTWidth = FirstVTWidth;
7374 do {
7375 RemainingWidth -= NewVTWidth;
7376 if (TypeSize::isKnownLT(RemainingWidth, NewVTWidth)) {
7377 // The current type we are using is too large. Find a better size.
7378 NewVT = findMemType(DAG, TLI, RemainingWidth.getKnownMinValue(),
7379 WidenVT, LdAlign, WidthDiff.getKnownMinValue());
7380 if (!NewVT)
7381 return SDValue();
7382 NewVTWidth = NewVT->getSizeInBits();
7383 }
7384 MemVTs.push_back(*NewVT);
7385 } while (TypeSize::isKnownGT(RemainingWidth, NewVTWidth));
7386 }
7387
7388 SDValue LdOp = DAG.getLoad(*FirstVT, dl, Chain, BasePtr, LD->getPointerInfo(),
7389 LD->getOriginalAlign(), MMOFlags, AAInfo);
7390 LdChain.push_back(LdOp.getValue(1));
7391
7392 // Check if we can load the element with one instruction.
7393 if (MemVTs.empty()) {
7394 assert(TypeSize::isKnownLE(LdWidth, FirstVTWidth));
7395 if (!FirstVT->isVector()) {
7396 unsigned NumElts =
7397 WidenWidth.getFixedValue() / FirstVTWidth.getFixedValue();
7398 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), *FirstVT, NumElts);
7399 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT, LdOp);
7400 return DAG.getNode(ISD::BITCAST, dl, WidenVT, VecOp);
7401 }
7402 if (FirstVT == WidenVT)
7403 return LdOp;
7404
7405 // TODO: We don't currently have any tests that exercise this code path.
7406 assert(WidenWidth.getFixedValue() % FirstVTWidth.getFixedValue() == 0);
7407 unsigned NumConcat =
7408 WidenWidth.getFixedValue() / FirstVTWidth.getFixedValue();
7409 SmallVector<SDValue, 16> ConcatOps(NumConcat);
7410 SDValue UndefVal = DAG.getUNDEF(*FirstVT);
7411 ConcatOps[0] = LdOp;
7412 for (unsigned i = 1; i != NumConcat; ++i)
7413 ConcatOps[i] = UndefVal;
7414 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, ConcatOps);
7415 }
7416
7417 // Load vector by using multiple loads from largest vector to scalar.
7419 LdOps.push_back(LdOp);
7420
7421 uint64_t ScaledOffset = 0;
7422 MachinePointerInfo MPI = LD->getPointerInfo();
7423
7424 // First incremement past the first load.
7425 IncrementPointer(cast<LoadSDNode>(LdOp), *FirstVT, MPI, BasePtr,
7426 &ScaledOffset);
7427
7428 for (EVT MemVT : MemVTs) {
7429 Align NewAlign = ScaledOffset == 0
7430 ? LD->getOriginalAlign()
7431 : commonAlignment(LD->getAlign(), ScaledOffset);
7432 SDValue L =
7433 DAG.getLoad(MemVT, dl, Chain, BasePtr, MPI, NewAlign, MMOFlags, AAInfo);
7434
7435 LdOps.push_back(L);
7436 LdChain.push_back(L.getValue(1));
7437 IncrementPointer(cast<LoadSDNode>(L), MemVT, MPI, BasePtr, &ScaledOffset);
7438 }
7439
7440 // Build the vector from the load operations.
7441 unsigned End = LdOps.size();
7442 if (!LdOps[0].getValueType().isVector())
7443 // All the loads are scalar loads.
7444 return BuildVectorFromScalar(DAG, WidenVT, LdOps, 0, End);
7445
7446 // If the load contains vectors, build the vector using concat vector.
7447 // All of the vectors used to load are power-of-2, and the scalar loads can be
7448 // combined to make a power-of-2 vector.
7449 SmallVector<SDValue, 16> ConcatOps(End);
7450 int i = End - 1;
7451 int Idx = End;
7452 EVT LdTy = LdOps[i].getValueType();
7453 // First, combine the scalar loads to a vector.
7454 if (!LdTy.isVector()) {
7455 for (--i; i >= 0; --i) {
7456 LdTy = LdOps[i].getValueType();
7457 if (LdTy.isVector())
7458 break;
7459 }
7460 ConcatOps[--Idx] = BuildVectorFromScalar(DAG, LdTy, LdOps, i + 1, End);
7461 }
7462
7463 ConcatOps[--Idx] = LdOps[i];
7464 for (--i; i >= 0; --i) {
7465 EVT NewLdTy = LdOps[i].getValueType();
7466 if (NewLdTy != LdTy) {
7467 // Create a larger vector.
7468 TypeSize LdTySize = LdTy.getSizeInBits();
7469 TypeSize NewLdTySize = NewLdTy.getSizeInBits();
7470 assert(NewLdTySize.isScalable() == LdTySize.isScalable() &&
7471 NewLdTySize.isKnownMultipleOf(LdTySize.getKnownMinValue()));
7472 unsigned NumOps =
7473 NewLdTySize.getKnownMinValue() / LdTySize.getKnownMinValue();
7474 SmallVector<SDValue, 16> WidenOps(NumOps);
7475 unsigned j = 0;
7476 for (; j != End-Idx; ++j)
7477 WidenOps[j] = ConcatOps[Idx+j];
7478 for (; j != NumOps; ++j)
7479 WidenOps[j] = DAG.getUNDEF(LdTy);
7480
7481 ConcatOps[End-1] = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewLdTy,
7482 WidenOps);
7483 Idx = End - 1;
7484 LdTy = NewLdTy;
7485 }
7486 ConcatOps[--Idx] = LdOps[i];
7487 }
7488
7489 if (WidenWidth == LdTy.getSizeInBits() * (End - Idx))
7490 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
7491 ArrayRef(&ConcatOps[Idx], End - Idx));
7492
7493 // We need to fill the rest with undefs to build the vector.
7494 unsigned NumOps =
7495 WidenWidth.getKnownMinValue() / LdTy.getSizeInBits().getKnownMinValue();
7496 SmallVector<SDValue, 16> WidenOps(NumOps);
7497 SDValue UndefVal = DAG.getUNDEF(LdTy);
7498 {
7499 unsigned i = 0;
7500 for (; i != End-Idx; ++i)
7501 WidenOps[i] = ConcatOps[Idx+i];
7502 for (; i != NumOps; ++i)
7503 WidenOps[i] = UndefVal;
7504 }
7505 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, WidenOps);
7506}
7507
7508SDValue
7509DAGTypeLegalizer::GenWidenVectorExtLoads(SmallVectorImpl<SDValue> &LdChain,
7510 LoadSDNode *LD,
7511 ISD::LoadExtType ExtType) {
7512 // For extension loads, it may not be more efficient to chop up the vector
7513 // and then extend it. Instead, we unroll the load and build a new vector.
7514 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
7515 EVT LdVT = LD->getMemoryVT();
7516 SDLoc dl(LD);
7517 assert(LdVT.isVector() && WidenVT.isVector());
7518 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
7519
7520 // Load information
7521 SDValue Chain = LD->getChain();
7522 SDValue BasePtr = LD->getBasePtr();
7523 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
7524 AAMDNodes AAInfo = LD->getAAInfo();
7525
7526 if (LdVT.isScalableVector())
7527 report_fatal_error("Generating widen scalable extending vector loads is "
7528 "not yet supported");
7529
7530 EVT EltVT = WidenVT.getVectorElementType();
7531 EVT LdEltVT = LdVT.getVectorElementType();
7532 unsigned NumElts = LdVT.getVectorNumElements();
7533
7534 // Load each element and widen.
7535 unsigned WidenNumElts = WidenVT.getVectorNumElements();
7536 SmallVector<SDValue, 16> Ops(WidenNumElts);
7537 unsigned Increment = LdEltVT.getSizeInBits() / 8;
7538 Ops[0] =
7539 DAG.getExtLoad(ExtType, dl, EltVT, Chain, BasePtr, LD->getPointerInfo(),
7540 LdEltVT, LD->getOriginalAlign(), MMOFlags, AAInfo);
7541 LdChain.push_back(Ops[0].getValue(1));
7542 unsigned i = 0, Offset = Increment;
7543 for (i=1; i < NumElts; ++i, Offset += Increment) {
7544 SDValue NewBasePtr =
7545 DAG.getObjectPtrOffset(dl, BasePtr, TypeSize::getFixed(Offset));
7546 Ops[i] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, NewBasePtr,
7547 LD->getPointerInfo().getWithOffset(Offset), LdEltVT,
7548 LD->getOriginalAlign(), MMOFlags, AAInfo);
7549 LdChain.push_back(Ops[i].getValue(1));
7550 }
7551
7552 // Fill the rest with undefs.
7553 SDValue UndefVal = DAG.getUNDEF(EltVT);
7554 for (; i != WidenNumElts; ++i)
7555 Ops[i] = UndefVal;
7556
7557 return DAG.getBuildVector(WidenVT, dl, Ops);
7558}
7559
7560bool DAGTypeLegalizer::GenWidenVectorStores(SmallVectorImpl<SDValue> &StChain,
7561 StoreSDNode *ST) {
7562 // The strategy assumes that we can efficiently store power-of-two widths.
7563 // The routine chops the vector into the largest vector stores with the same
7564 // element type or scalar stores.
7565 SDValue Chain = ST->getChain();
7566 SDValue BasePtr = ST->getBasePtr();
7567 MachineMemOperand::Flags MMOFlags = ST->getMemOperand()->getFlags();
7568 AAMDNodes AAInfo = ST->getAAInfo();
7569 SDValue ValOp = GetWidenedVector(ST->getValue());
7570 SDLoc dl(ST);
7571
7572 EVT StVT = ST->getMemoryVT();
7573 TypeSize StWidth = StVT.getSizeInBits();
7574 EVT ValVT = ValOp.getValueType();
7575 TypeSize ValWidth = ValVT.getSizeInBits();
7576 EVT ValEltVT = ValVT.getVectorElementType();
7577 unsigned ValEltWidth = ValEltVT.getFixedSizeInBits();
7578 assert(StVT.getVectorElementType() == ValEltVT);
7579 assert(StVT.isScalableVector() == ValVT.isScalableVector() &&
7580 "Mismatch between store and value types");
7581
7582 int Idx = 0; // current index to store
7583
7584 MachinePointerInfo MPI = ST->getPointerInfo();
7585 uint64_t ScaledOffset = 0;
7586
7587 // A breakdown of how to widen this vector store. Each element of the vector
7588 // is a memory VT combined with the number of times it is to be stored to,
7589 // e,g., v5i32 -> {{v2i32,2},{i32,1}}
7591
7592 while (StWidth.isNonZero()) {
7593 // Find the largest vector type we can store with.
7594 std::optional<EVT> NewVT =
7595 findMemType(DAG, TLI, StWidth.getKnownMinValue(), ValVT);
7596 if (!NewVT)
7597 return false;
7598 MemVTs.push_back({*NewVT, 0});
7599 TypeSize NewVTWidth = NewVT->getSizeInBits();
7600
7601 do {
7602 StWidth -= NewVTWidth;
7603 MemVTs.back().second++;
7604 } while (StWidth.isNonZero() && TypeSize::isKnownGE(StWidth, NewVTWidth));
7605 }
7606
7607 for (const auto &Pair : MemVTs) {
7608 EVT NewVT = Pair.first;
7609 unsigned Count = Pair.second;
7610 TypeSize NewVTWidth = NewVT.getSizeInBits();
7611
7612 if (NewVT.isVector()) {
7613 unsigned NumVTElts = NewVT.getVectorMinNumElements();
7614 do {
7615 Align NewAlign = ScaledOffset == 0
7616 ? ST->getOriginalAlign()
7617 : commonAlignment(ST->getAlign(), ScaledOffset);
7618 SDValue EOp = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, NewVT, ValOp,
7619 DAG.getVectorIdxConstant(Idx, dl));
7620 SDValue PartStore = DAG.getStore(Chain, dl, EOp, BasePtr, MPI, NewAlign,
7621 MMOFlags, AAInfo);
7622 StChain.push_back(PartStore);
7623
7624 Idx += NumVTElts;
7625 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr,
7626 &ScaledOffset);
7627 } while (--Count);
7628 } else {
7629 // Cast the vector to the scalar type we can store.
7630 unsigned NumElts = ValWidth.getFixedValue() / NewVTWidth.getFixedValue();
7631 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewVT, NumElts);
7632 SDValue VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, ValOp);
7633 // Readjust index position based on new vector type.
7634 Idx = Idx * ValEltWidth / NewVTWidth.getFixedValue();
7635 do {
7636 SDValue EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NewVT, VecOp,
7637 DAG.getVectorIdxConstant(Idx++, dl));
7638 SDValue PartStore =
7639 DAG.getStore(Chain, dl, EOp, BasePtr, MPI, ST->getOriginalAlign(),
7640 MMOFlags, AAInfo);
7641 StChain.push_back(PartStore);
7642
7643 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr);
7644 } while (--Count);
7645 // Restore index back to be relative to the original widen element type.
7646 Idx = Idx * NewVTWidth.getFixedValue() / ValEltWidth;
7647 }
7648 }
7649
7650 return true;
7651}
7652
7653/// Modifies a vector input (widen or narrows) to a vector of NVT. The
7654/// input vector must have the same element type as NVT.
7655/// FillWithZeroes specifies that the vector should be widened with zeroes.
7656SDValue DAGTypeLegalizer::ModifyToType(SDValue InOp, EVT NVT,
7657 bool FillWithZeroes) {
7658 // Note that InOp might have been widened so it might already have
7659 // the right width or it might need be narrowed.
7660 EVT InVT = InOp.getValueType();
7662 "input and widen element type must match");
7663 assert(InVT.isScalableVector() == NVT.isScalableVector() &&
7664 "cannot modify scalable vectors in this way");
7665 SDLoc dl(InOp);
7666
7667 // Check if InOp already has the right width.
7668 if (InVT == NVT)
7669 return InOp;
7670
7671 ElementCount InEC = InVT.getVectorElementCount();
7672 ElementCount WidenEC = NVT.getVectorElementCount();
7673 if (WidenEC.hasKnownScalarFactor(InEC)) {
7674 unsigned NumConcat = WidenEC.getKnownScalarFactor(InEC);
7675 SmallVector<SDValue, 16> Ops(NumConcat);
7676 SDValue FillVal = FillWithZeroes ? DAG.getConstant(0, dl, InVT) :
7677 DAG.getUNDEF(InVT);
7678 Ops[0] = InOp;
7679 for (unsigned i = 1; i != NumConcat; ++i)
7680 Ops[i] = FillVal;
7681
7682 return DAG.getNode(ISD::CONCAT_VECTORS, dl, NVT, Ops);
7683 }
7684
7685 if (InEC.hasKnownScalarFactor(WidenEC))
7686 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, NVT, InOp,
7687 DAG.getVectorIdxConstant(0, dl));
7688
7689 assert(!InVT.isScalableVector() && !NVT.isScalableVector() &&
7690 "Scalable vectors should have been handled already.");
7691
7692 unsigned InNumElts = InEC.getFixedValue();
7693 unsigned WidenNumElts = WidenEC.getFixedValue();
7694
7695 // Fall back to extract and build (+ mask, if padding with zeros).
7696 SmallVector<SDValue, 16> Ops(WidenNumElts);
7697 EVT EltVT = NVT.getVectorElementType();
7698 unsigned MinNumElts = std::min(WidenNumElts, InNumElts);
7699 unsigned Idx;
7700 for (Idx = 0; Idx < MinNumElts; ++Idx)
7701 Ops[Idx] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp,
7702 DAG.getVectorIdxConstant(Idx, dl));
7703
7704 SDValue UndefVal = DAG.getUNDEF(EltVT);
7705 for (; Idx < WidenNumElts; ++Idx)
7706 Ops[Idx] = UndefVal;
7707
7708 SDValue Widened = DAG.getBuildVector(NVT, dl, Ops);
7709 if (!FillWithZeroes)
7710 return Widened;
7711
7712 assert(NVT.isInteger() &&
7713 "We expect to never want to FillWithZeroes for non-integral types.");
7714
7716 MaskOps.append(MinNumElts, DAG.getAllOnesConstant(dl, EltVT));
7717 MaskOps.append(WidenNumElts - MinNumElts, DAG.getConstant(0, dl, EltVT));
7718
7719 return DAG.getNode(ISD::AND, dl, NVT, Widened,
7720 DAG.getBuildVector(NVT, dl, MaskOps));
7721}
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
amdgpu AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
#define LLVM_DEBUG(X)
Definition: Debug.h:101
uint64_t Size
bool End
Definition: ELF_riscv.cpp:480
static bool isUndef(ArrayRef< int > Mask)
static SDValue BuildVectorFromScalar(SelectionDAG &DAG, EVT VecTy, SmallVectorImpl< SDValue > &LdOps, unsigned Start, unsigned End)
static EVT getSETCCOperandType(SDValue N)
static bool isSETCCOp(unsigned Opcode)
static bool isLogicalMaskOp(unsigned Opcode)
static bool isSETCCorConvertedSETCC(SDValue N)
static SDValue CollectOpsToWiden(SelectionDAG &DAG, const TargetLowering &TLI, SmallVectorImpl< SDValue > &ConcatOps, unsigned ConcatEnd, EVT VT, EVT MaxVT, EVT WidenVT)
static std::optional< EVT > findMemType(SelectionDAG &DAG, const TargetLowering &TLI, unsigned Width, EVT WidenVT, unsigned Align=0, unsigned WidenEx=0)
#define I(x, y, z)
Definition: MD5.cpp:58
mir Rename Register Operands
This file provides utility analysis objects describing memory locations.
uint64_t High
#define P(N)
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements the SmallBitVector class.
static llvm::Type * getVectorElementType(llvm::Type *Ty)
static std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
Definition: VPlanSLP.cpp:191
Value * RHS
Value * LHS
Class for arbitrary precision integers.
Definition: APInt.h:78
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
unsigned getVScaleRangeMin() const
Returns the minimum value for the vscale_range attribute.
Definition: Attributes.cpp:459
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition: Attributes.h:203
This class represents an Operation in the Expression.
bool isBigEndian() const
Definition: DataLayout.h:239
static constexpr ElementCount getScalable(ScalarTy MinVal)
Definition: TypeSize.h:314
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
This class is used to represent ISD::LOAD nodes.
static constexpr LocationSize beforeOrAfterPointer()
Any location before or after the base pointer (but still within the underlying object).
static auto integer_valuetypes()
static auto vector_valuetypes()
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
A description of a memory reference used in the backend.
Flags
Flags values. These may be or'd together.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
const MachinePointerInfo & getPointerInfo() const
Flags getFlags() const
Return the raw flags of the source value,.
Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
AAMDNodes getAAInfo() const
Return the AA tags for the memory reference.
This class implements a map that also provides access to all stored values in a deterministic order.
Definition: MapVector.h:36
This class is used to represent an MGATHER node.
const SDValue & getIndex() const
const SDValue & getScale() const
const SDValue & getBasePtr() const
const SDValue & getMask() const
ISD::MemIndexType getIndexType() const
How is Index applied to BasePtr when computing addresses.
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,...
This class is used to represent an MSCATTER node.
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.
const MDNode * getRanges() const
Returns the Ranges that describes the dereference.
AAMDNodes getAAInfo() const
Returns the AA info that describes the dereference.
Align getOriginalAlign() const
Returns alignment and volatility of the memory access.
MachineMemOperand * getMemOperand() const
Return a 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.
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.
void setFlags(SDNodeFlags NewFlags)
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.
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...
Definition: SelectionDAG.h:227
Align getReducedAlign(EVT VT, bool UseABI)
In most cases this function returns the ABI alignment for a given type, except for illegal vector typ...
SDValue getMaskedGather(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType, ISD::LoadExtType ExtTy)
SDValue getAddrSpaceCast(const SDLoc &dl, EVT VT, SDValue Ptr, unsigned SrcAS, unsigned DestAS)
Return an AddrSpaceCastSDNode.
SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
void ExtractVectorElements(SDValue Op, SmallVectorImpl< SDValue > &Args, unsigned Start=0, unsigned Count=0, EVT EltVT=EVT())
Append the extracted elements from Start to Count out of the vector Op in Args.
SDValue getVScale(const SDLoc &DL, EVT VT, APInt MulImm, bool ConstantFold=true)
Return a node that represents the runtime scaling 'MulImm * RuntimeVL'.
SDValue getStridedLoadVP(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, const SDLoc &DL, SDValue Chain, SDValue Ptr, SDValue Offset, SDValue Stride, SDValue Mask, SDValue EVL, EVT MemVT, MachineMemOperand *MMO, bool IsExpanding=false)
SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
std::pair< EVT, EVT > GetSplitDestVTs(const EVT &VT) const
Compute the VTs needed for the low/hi parts of a type which is split (or expanded) into two not neces...
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getGatherVP(SDVTList VTs, EVT VT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType)
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
Definition: SelectionDAG.h:840
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
const DataLayout & getDataLayout() const
Definition: SelectionDAG.h:486
SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
std::pair< SDValue, SDValue > SplitEVL(SDValue N, EVT VecVT, const SDLoc &DL)
Split the explicit vector length parameter of a VP operation.
SDValue getLoadVP(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, SDValue Offset, SDValue Mask, SDValue EVL, MachinePointerInfo PtrInfo, EVT MemVT, Align Alignment, MachineMemOperand::Flags MMOFlags, const AAMDNodes &AAInfo, const MDNode *Ranges=nullptr, bool IsExpanding=false)
SDValue getValueType(EVT)
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
MachineFunction & getMachineFunction() const
Definition: SelectionDAG.h:481
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
Definition: SelectionDAG.h:499
SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
std::pair< EVT, EVT > GetDependentSplitDestVTs(const EVT &VT, const EVT &EnvVT, bool *HiIsEmpty) const
Compute the VTs needed for the low/hi parts of a type, dependent on an enveloping VT that has been sp...
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
Definition: SelectionDAG.h:568
SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
A vector that has set insertion semantics.
Definition: SetVector.h:57
size_type size() const
Determine the number of elements in the SetVector.
Definition: SetVector.h:98
Vector takeVector()
Clear the SetVector and return the underlying vector.
Definition: SetVector.h:87
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition: SetVector.h:162
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
bool empty() const
Definition: SmallVector.h:94
size_t size() const
Definition: SmallVector.h:91
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:950
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:696
void push_back(const T &Elt)
Definition: SmallVector.h:426
pointer data()
Return a pointer to the vector's buffer, even if empty().
Definition: SmallVector.h:299
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
This class is used to represent ISD::STORE nodes.
bool isOperationExpand(unsigned Op, EVT VT) const
Return true if the specified operation is illegal on this target or unlikely to be made legal with cu...
virtual bool canOpTrap(unsigned Op, EVT VT) const
Returns true if the operation can trap for the value type.
virtual MVT getVectorIdxTy(const DataLayout &DL) const
Returns the type to be used for the index operand of: ISD::INSERT_VECTOR_ELT, ISD::EXTRACT_VECTOR_ELT...
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
EVT getShiftAmountTy(EVT LHSTy, const DataLayout &DL) const
Returns the type for the shift amount of a shift opcode.
virtual EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const
For types supported by the target, this is an identity function.
BooleanContent getBooleanContents(bool isVec, bool isFloat) const
For targets without i1 registers, this gives the nature of the high-bits of boolean values held in ty...
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
BooleanContent
Enum that describes how the target represents true/false values.
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
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 ...
virtual MVT getVPExplicitVectorLengthTy() const
Returns the type to be used for the EVL/AVL operand of VP nodes: ISD::VP_ADD, ISD::VP_SUB,...
static ISD::NodeType getExtendForContent(BooleanContent Content)
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
SDValue scalarizeVectorStore(StoreSDNode *ST, SelectionDAG &DAG) const
SDValue expandVectorSplice(SDNode *Node, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::VECTOR_SPLICE.
SDValue getVectorSubVecPointer(SelectionDAG &DAG, SDValue VecPtr, EVT VecVT, EVT SubVecVT, SDValue Index) const
Get a pointer to a sub-vector of type SubVecVT at index Idx located in memory for a vector of type Ve...
std::pair< SDValue, SDValue > scalarizeVectorLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Turn load of vector type into a load of the individual elements.
SDValue IncrementMemoryAddress(SDValue Addr, SDValue Mask, const SDLoc &DL, EVT DataVT, SelectionDAG &DAG, bool IsCompressedMemory) const
Increments memory address Addr according to the type of the value DataVT that should be stored.
SDValue getVectorElementPointer(SelectionDAG &DAG, SDValue VecPtr, EVT VecVT, SDValue Index) const
Get a pointer to vector element Idx located in memory for a vector of type VecVT starting at a base a...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition: TypeSize.h:345
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.
This class is used to represent an VP_SCATTER 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.
LLVM Value Representation.
Definition: Value.h:74
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:183
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:271
constexpr ScalarTy getFixedValue() const
Definition: TypeSize.h:202
static constexpr bool isKnownLE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition: TypeSize.h:232
constexpr bool isNonZero() const
Definition: TypeSize.h:158
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:279
static constexpr bool isKnownLT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition: TypeSize.h:218
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition: TypeSize.h:171
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:179
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition: TypeSize.h:168
static constexpr bool isKnownGT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition: TypeSize.h:225
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:254
static constexpr bool isKnownGE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition: TypeSize.h:239
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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.
Definition: BitmaskEnum.h:121
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
Definition: ISDOpcodes.h:40
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
Definition: ISDOpcodes.h:770
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
Definition: ISDOpcodes.h:243
@ CTLZ_ZERO_UNDEF
Definition: ISDOpcodes.h:743
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
Definition: ISDOpcodes.h:490
@ VECREDUCE_SEQ_FADD
Generic reduction nodes.
Definition: ISDOpcodes.h:1372
@ VECREDUCE_SMIN
Definition: ISDOpcodes.h:1403
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
Definition: ISDOpcodes.h:573
@ BSWAP
Byte Swap and Counting operators.
Definition: ISDOpcodes.h:734
@ SMULFIX
RESULT = [US]MULFIX(LHS, RHS, SCALE) - Perform fixed point multiplication on 2 integers with the same...
Definition: ISDOpcodes.h:374
@ ADD
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:246
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
Definition: ISDOpcodes.h:1064
@ SMULFIXSAT
Same as the corresponding unsaturated fixed point instructions, but the result is clamped between the...
Definition: ISDOpcodes.h:380
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition: ISDOpcodes.h:803
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
Definition: ISDOpcodes.h:497
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Definition: ISDOpcodes.h:810
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
Definition: ISDOpcodes.h:557
@ VECREDUCE_FMAX
FMIN/FMAX nodes can have flags, for NaN/NoNaN variants.
Definition: ISDOpcodes.h:1388
@ FADD
Simple binary floating point operators.
Definition: ISDOpcodes.h:397
@ VECREDUCE_FMAXIMUM
FMINIMUM/FMAXIMUM nodes propatate NaNs and signed zeroes using the llvm.minimum and llvm....
Definition: ISDOpcodes.h:1392
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
Definition: ISDOpcodes.h:708
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
Definition: ISDOpcodes.h:840
@ VECREDUCE_SMAX
Definition: ISDOpcodes.h:1402
@ STRICT_FSETCCS
Definition: ISDOpcodes.h:491
@ FPTRUNC_ROUND
Definition: ISDOpcodes.h:494
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
Definition: ISDOpcodes.h:923
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
Definition: ISDOpcodes.h:966
@ SDIVFIX
RESULT = [US]DIVFIX(LHS, RHS, SCALE) - Perform fixed point division on 2 integers with the same width...
Definition: ISDOpcodes.h:387
@ FrameIndex
Definition: ISDOpcodes.h:80
@ SIGN_EXTEND
Conversion operators.
Definition: ISDOpcodes.h:794
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
Definition: ISDOpcodes.h:676
@ STRICT_UINT_TO_FP
Definition: ISDOpcodes.h:464
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
Definition: ISDOpcodes.h:634
@ VECREDUCE_FADD
These reductions have relaxed evaluation order semantics, and have a single vector operand.
Definition: ISDOpcodes.h:1385
@ CTTZ_ZERO_UNDEF
Bit counting operators with an undefined result for zero inputs.
Definition: ISDOpcodes.h:742
@ VECREDUCE_FMIN
Definition: ISDOpcodes.h:1389
@ FNEG
Perform various unary floating-point operations inspired by libm.
Definition: ISDOpcodes.h:950
@ SSUBO
Same for subtraction.
Definition: ISDOpcodes.h:334
@ VECTOR_INTERLEAVE
VECTOR_INTERLEAVE(VEC1, VEC2) - Returns two vectors with all input and output vectors having the same...
Definition: ISDOpcodes.h:600
@ STEP_VECTOR
STEP_VECTOR(IMM) - Returns a scalable vector whose lanes are comprised of a linear sequence of unsign...
Definition: ISDOpcodes.h:660
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
Definition: ISDOpcodes.h:514
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
Definition: ISDOpcodes.h:521
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
Definition: ISDOpcodes.h:356
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition: ISDOpcodes.h:747
@ UNDEF
UNDEF - An undefined node.
Definition: ISDOpcodes.h:218
@ VECREDUCE_UMAX
Definition: ISDOpcodes.h:1404
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
Definition: ISDOpcodes.h:641
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
Definition: ISDOpcodes.h:330
@ ARITH_FENCE
ARITH_FENCE - This corresponds to a arithmetic fence intrinsic.
Definition: ISDOpcodes.h:1258
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
Definition: ISDOpcodes.h:1397
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition: ISDOpcodes.h:665
@ SHL
Shift and rotation operations.
Definition: ISDOpcodes.h:725
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition: ISDOpcodes.h:614
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition: ISDOpcodes.h:587
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimumNumber or maximumNumber on two values,...
Definition: ISDOpcodes.h:1011
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition: ISDOpcodes.h:549
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition: ISDOpcodes.h:800
@ FP_TO_UINT_SAT
Definition: ISDOpcodes.h:876
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition: ISDOpcodes.h:762
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two values.
Definition: ISDOpcodes.h:998
@ SSHLSAT
RESULT = [US]SHLSAT(LHS, RHS) - Perform saturation left shift.
Definition: ISDOpcodes.h:366
@ SMULO
Same for multiplication.
Definition: ISDOpcodes.h:338
@ ANY_EXTEND_VECTOR_INREG
ANY_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register any-extension of the low la...
Definition: ISDOpcodes.h:829
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition: ISDOpcodes.h:818
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition: ISDOpcodes.h:688
@ VECTOR_REVERSE
VECTOR_REVERSE(VECTOR) - Returns a vector, of the same type as VECTOR, whose elements are shuffled us...
Definition: ISDOpcodes.h:605
@ SDIVFIXSAT
Same as the corresponding unsaturated fixed point instructions, but the result is clamped between the...
Definition: ISDOpcodes.h:393
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition: ISDOpcodes.h:908
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition: ISDOpcodes.h:756
@ STRICT_SINT_TO_FP
STRICT_[US]INT_TO_FP - Convert a signed or unsigned integer to a floating point value.
Definition: ISDOpcodes.h:463
@ VECREDUCE_UMIN
Definition: ISDOpcodes.h:1405
@ STRICT_FP_TO_UINT
Definition: ISDOpcodes.h:457
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
Definition: ISDOpcodes.h:479
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition: ISDOpcodes.h:456
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
Definition: ISDOpcodes.h:1017
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition: ISDOpcodes.h:856
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition: ISDOpcodes.h:484
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:700
@ SCMP
[US]CMP - 3-way comparison of signed or unsigned integers.
Definition: ISDOpcodes.h:696
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
Definition: ISDOpcodes.h:671
@ VECREDUCE_FMUL
Definition: ISDOpcodes.h:1386
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
Definition: ISDOpcodes.h:538
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition: ISDOpcodes.h:52
@ VECTOR_SPLICE
VECTOR_SPLICE(VEC1, VEC2, IMM) - Returns a subvector of the same type as VEC1/VEC2 from CONCAT_VECTOR...
Definition: ISDOpcodes.h:626
@ FFREXP
FFREXP - frexp, extract fractional and exponent component of a floating-point value.
Definition: ISDOpcodes.h:971
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
Definition: ISDOpcodes.h:889
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
Definition: ISDOpcodes.h:851
@ ADDRSPACECAST
ADDRSPACECAST - This operator converts between pointers of different address spaces.
Definition: ISDOpcodes.h:927
@ 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:875
@ VECREDUCE_FMINIMUM
Definition: ISDOpcodes.h:1393
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition: ISDOpcodes.h:806
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
Definition: ISDOpcodes.h:1179
@ VECREDUCE_SEQ_FMUL
Definition: ISDOpcodes.h:1373
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
Definition: ISDOpcodes.h:507
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
Definition: ISDOpcodes.h:347
@ AssertZext
Definition: ISDOpcodes.h:62
@ VECTOR_DEINTERLEAVE
VECTOR_DEINTERLEAVE(VEC1, VEC2) - Returns two vectors with all input and output vectors having the sa...
Definition: ISDOpcodes.h:594
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition: ISDOpcodes.h:529
bool isBuildVectorOfConstantSDNodes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR node of all ConstantSDNode or undef.
bool isUNINDEXEDLoad(const SDNode *N)
Returns true if the specified node is an unindexed load.
MemIndexType
MemIndexType enum - This enum defines how to interpret MGATHER/SCATTER's index parameter when calcula...
Definition: ISDOpcodes.h:1528
bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
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).
Definition: ISDOpcodes.h:1546
LegalityPredicate isVector(unsigned TypeIdx)
True iff the specified type index is a vector.
constexpr double e
Definition: MathExtras.h:47
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
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:1742
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition: MathExtras.h:296
auto reverse(ContainerTy &&C)
Definition: STLExtras.h:419
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition: MathExtras.h:291
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167
constexpr int PoisonMaskElem
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)> ManyInputsAction)
Splits and processes shuffle mask depending on the number of input and output registers.
DWARFExpression::Operation Op
OutputIt copy(R &&Range, OutputIt Out)
Definition: STLExtras.h:1824
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:1749
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition: STLExtras.h:1879
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Definition: Alignment.h:212
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:860
#define N
This is used by foldAnyOrAllBitsSet() to capture a source value (Root) and the bit indexes (Mask) nee...
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
Definition: Metadata.h:760
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
uint64_t value() const
This is a hole in the type system and should not be abused.
Definition: Alignment.h:85
Extended Value Type.
Definition: ValueTypes.h:34
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
Definition: ValueTypes.h:93
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
Definition: ValueTypes.h:380
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:73
EVT changeTypeToInteger() const
Return the type converted to an equivalently sized integer or vector with integer element type.
Definition: ValueTypes.h:120
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
Definition: ValueTypes.h:274
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
Definition: ValueTypes.h:146
ElementCount getVectorElementCount() const
Definition: ValueTypes.h:340
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition: ValueTypes.h:358
bool isByteSized() const
Return true if the bit size is a multiple of 8.
Definition: ValueTypes.h:233
EVT changeElementType(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:112
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
Definition: ValueTypes.h:349
uint64_t getScalarSizeInBits() const
Definition: ValueTypes.h:370
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
Definition: ValueTypes.h:455
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
Definition: ValueTypes.h:64
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
Definition: ValueTypes.h:366
EVT widenIntegerVectorElementType(LLVMContext &Context) const
Return a VT for an integer vector type with the size of the elements doubled.
Definition: ValueTypes.h:429
bool isFixedLengthVector() const
Definition: ValueTypes.h:177
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
Definition: ValueTypes.h:58
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:404
bool isVector() const
Return true if this is a vector value type.
Definition: ValueTypes.h:167
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
Definition: ValueTypes.h:313
bool bitsEq(EVT VT) const
Return true if this has the same number of bits as VT.
Definition: ValueTypes.h:246
Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
Definition: ValueTypes.cpp:203
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
Definition: ValueTypes.h:173
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:258
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition: ValueTypes.h:318
EVT changeVectorElementType(EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
Definition: ValueTypes.h:101
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Definition: ValueTypes.h:326
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
Definition: ValueTypes.h:438
bool isInteger() const
Return true if this is an integer or a vector integer type.
Definition: ValueTypes.h:151
This class contains a discriminated union of information about pointers in memory operands,...
unsigned getAddrSpace() const
Return the LLVM IR address space number that this pointer points into.
MachinePointerInfo getWithOffset(int64_t O) const
static MachinePointerInfo getUnknownStack(MachineFunction &MF)
Stack memory without other information.
static MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
These are IR-level optimization flags that may be propagated to SDNodes.
This represents a list of ValueType's that has been intern'd by a SelectionDAG.