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