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