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