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_EXTRACT_VECTOR_ELT(N);
770 break;
771 case ISD::VSELECT:
772 Res = ScalarizeVecOp_VSELECT(N);
773 break;
774 case ISD::SETCC:
775 Res = ScalarizeVecOp_VSETCC(N);
776 break;
777 case ISD::STORE:
778 Res = ScalarizeVecOp_STORE(cast<StoreSDNode>(N), OpNo);
779 break;
781 Res = ScalarizeVecOp_STRICT_FP_ROUND(N, OpNo);
782 break;
783 case ISD::FP_ROUND:
784 Res = ScalarizeVecOp_FP_ROUND(N, OpNo);
785 break;
787 Res = ScalarizeVecOp_STRICT_FP_EXTEND(N);
788 break;
789 case ISD::FP_EXTEND:
790 Res = ScalarizeVecOp_FP_EXTEND(N);
791 break;
807 Res = ScalarizeVecOp_VECREDUCE(N);
808 break;
811 Res = ScalarizeVecOp_VECREDUCE_SEQ(N);
812 break;
813 case ISD::SCMP:
814 case ISD::UCMP:
815 Res = ScalarizeVecOp_CMP(N);
816 break;
817 }
818
819 // If the result is null, the sub-method took care of registering results etc.
820 if (!Res.getNode()) return false;
821
822 // If the result is N, the sub-method updated N in place. Tell the legalizer
823 // core about this.
824 if (Res.getNode() == N)
825 return true;
826
827 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
828 "Invalid operand expansion");
829
830 ReplaceValueWith(SDValue(N, 0), Res);
831 return false;
832}
833
834/// If the value to convert is a vector that needs to be scalarized, it must be
835/// <1 x ty>. Convert the element instead.
836SDValue DAGTypeLegalizer::ScalarizeVecOp_BITCAST(SDNode *N) {
837 SDValue Elt = GetScalarizedVector(N->getOperand(0));
838 return DAG.getNode(ISD::BITCAST, SDLoc(N),
839 N->getValueType(0), Elt);
840}
841
842/// If the input is a vector that needs to be scalarized, it must be <1 x ty>.
843/// Do the operation on the element instead.
844SDValue DAGTypeLegalizer::ScalarizeVecOp_UnaryOp(SDNode *N) {
845 assert(N->getValueType(0).getVectorNumElements() == 1 &&
846 "Unexpected vector type!");
847 SDValue Elt = GetScalarizedVector(N->getOperand(0));
848 SDValue Op = DAG.getNode(N->getOpcode(), SDLoc(N),
849 N->getValueType(0).getScalarType(), Elt);
850 // Revectorize the result so the types line up with what the uses of this
851 // expression expect.
852 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Op);
853}
854
855/// If the input is a vector that needs to be scalarized, it must be <1 x ty>.
856/// Do the strict FP operation on the element instead.
857SDValue DAGTypeLegalizer::ScalarizeVecOp_UnaryOp_StrictFP(SDNode *N) {
858 assert(N->getValueType(0).getVectorNumElements() == 1 &&
859 "Unexpected vector type!");
860 SDValue Elt = GetScalarizedVector(N->getOperand(1));
861 SDValue Res = DAG.getNode(N->getOpcode(), SDLoc(N),
862 { N->getValueType(0).getScalarType(), MVT::Other },
863 { N->getOperand(0), Elt });
864 // Legalize the chain result - switch anything that used the old chain to
865 // use the new one.
866 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
867 // Revectorize the result so the types line up with what the uses of this
868 // expression expect.
869 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
870
871 // Do our own replacement and return SDValue() to tell the caller that we
872 // handled all replacements since caller can only handle a single result.
873 ReplaceValueWith(SDValue(N, 0), Res);
874 return SDValue();
875}
876
877/// The vectors to concatenate have length one - use a BUILD_VECTOR instead.
878SDValue DAGTypeLegalizer::ScalarizeVecOp_CONCAT_VECTORS(SDNode *N) {
879 SmallVector<SDValue, 8> Ops(N->getNumOperands());
880 for (unsigned i = 0, e = N->getNumOperands(); i < e; ++i)
881 Ops[i] = GetScalarizedVector(N->getOperand(i));
882 return DAG.getBuildVector(N->getValueType(0), SDLoc(N), Ops);
883}
884
885/// If the input is a vector that needs to be scalarized, it must be <1 x ty>,
886/// so just return the element, ignoring the index.
887SDValue DAGTypeLegalizer::ScalarizeVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
888 EVT VT = N->getValueType(0);
889 SDValue Res = GetScalarizedVector(N->getOperand(0));
890 if (Res.getValueType() != VT)
891 Res = VT.isFloatingPoint()
892 ? DAG.getNode(ISD::FP_EXTEND, SDLoc(N), VT, Res)
893 : DAG.getNode(ISD::ANY_EXTEND, SDLoc(N), VT, Res);
894 return Res;
895}
896
897/// If the input condition is a vector that needs to be scalarized, it must be
898/// <1 x i1>, so just convert to a normal ISD::SELECT
899/// (still with vector output type since that was acceptable if we got here).
900SDValue DAGTypeLegalizer::ScalarizeVecOp_VSELECT(SDNode *N) {
901 SDValue ScalarCond = GetScalarizedVector(N->getOperand(0));
902 EVT VT = N->getValueType(0);
903
904 return DAG.getNode(ISD::SELECT, SDLoc(N), VT, ScalarCond, N->getOperand(1),
905 N->getOperand(2));
906}
907
908/// If the operand is a vector that needs to be scalarized then the
909/// result must be v1i1, so just convert to a scalar SETCC and wrap
910/// with a scalar_to_vector since the res type is legal if we got here
911SDValue DAGTypeLegalizer::ScalarizeVecOp_VSETCC(SDNode *N) {
912 assert(N->getValueType(0).isVector() &&
913 N->getOperand(0).getValueType().isVector() &&
914 "Operand types must be vectors");
915 assert(N->getValueType(0) == MVT::v1i1 && "Expected v1i1 type");
916
917 EVT VT = N->getValueType(0);
918 SDValue LHS = GetScalarizedVector(N->getOperand(0));
919 SDValue RHS = GetScalarizedVector(N->getOperand(1));
920
921 EVT OpVT = N->getOperand(0).getValueType();
922 EVT NVT = VT.getVectorElementType();
923 SDLoc DL(N);
924 // Turn it into a scalar SETCC.
925 SDValue Res = DAG.getNode(ISD::SETCC, DL, MVT::i1, LHS, RHS,
926 N->getOperand(2));
927
928 // Vectors may have a different boolean contents to scalars. Promote the
929 // value appropriately.
930 ISD::NodeType ExtendCode =
932
933 Res = DAG.getNode(ExtendCode, DL, NVT, Res);
934
935 return DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, VT, Res);
936}
937
938/// If the value to store is a vector that needs to be scalarized, it must be
939/// <1 x ty>. Just store the element.
940SDValue DAGTypeLegalizer::ScalarizeVecOp_STORE(StoreSDNode *N, unsigned OpNo){
941 assert(N->isUnindexed() && "Indexed store of one-element vector?");
942 assert(OpNo == 1 && "Do not know how to scalarize this operand!");
943 SDLoc dl(N);
944
945 if (N->isTruncatingStore())
946 return DAG.getTruncStore(
947 N->getChain(), dl, GetScalarizedVector(N->getOperand(1)),
948 N->getBasePtr(), N->getPointerInfo(),
949 N->getMemoryVT().getVectorElementType(), N->getOriginalAlign(),
950 N->getMemOperand()->getFlags(), N->getAAInfo());
951
952 return DAG.getStore(N->getChain(), dl, GetScalarizedVector(N->getOperand(1)),
953 N->getBasePtr(), N->getPointerInfo(),
954 N->getOriginalAlign(), N->getMemOperand()->getFlags(),
955 N->getAAInfo());
956}
957
958/// If the value to round is a vector that needs to be scalarized, it must be
959/// <1 x ty>. Convert the element instead.
960SDValue DAGTypeLegalizer::ScalarizeVecOp_FP_ROUND(SDNode *N, unsigned OpNo) {
961 assert(OpNo == 0 && "Wrong operand for scalarization!");
962 SDValue Elt = GetScalarizedVector(N->getOperand(0));
963 SDValue Res = DAG.getNode(ISD::FP_ROUND, SDLoc(N),
964 N->getValueType(0).getVectorElementType(), Elt,
965 N->getOperand(1));
966 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
967}
968
969SDValue DAGTypeLegalizer::ScalarizeVecOp_STRICT_FP_ROUND(SDNode *N,
970 unsigned OpNo) {
971 assert(OpNo == 1 && "Wrong operand for scalarization!");
972 SDValue Elt = GetScalarizedVector(N->getOperand(1));
974 { N->getValueType(0).getVectorElementType(),
975 MVT::Other },
976 { N->getOperand(0), Elt, N->getOperand(2) });
977 // Legalize the chain result - switch anything that used the old chain to
978 // use the new one.
979 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
980
981 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
982
983 // Do our own replacement and return SDValue() to tell the caller that we
984 // handled all replacements since caller can only handle a single result.
985 ReplaceValueWith(SDValue(N, 0), Res);
986 return SDValue();
987}
988
989/// If the value to extend is a vector that needs to be scalarized, it must be
990/// <1 x ty>. Convert the element instead.
991SDValue DAGTypeLegalizer::ScalarizeVecOp_FP_EXTEND(SDNode *N) {
992 SDValue Elt = GetScalarizedVector(N->getOperand(0));
994 N->getValueType(0).getVectorElementType(), Elt);
995 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
996}
997
998/// If the value to extend is a vector that needs to be scalarized, it must be
999/// <1 x ty>. Convert the element instead.
1000SDValue DAGTypeLegalizer::ScalarizeVecOp_STRICT_FP_EXTEND(SDNode *N) {
1001 SDValue Elt = GetScalarizedVector(N->getOperand(1));
1002 SDValue Res =
1004 {N->getValueType(0).getVectorElementType(), MVT::Other},
1005 {N->getOperand(0), Elt});
1006 // Legalize the chain result - switch anything that used the old chain to
1007 // use the new one.
1008 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
1009
1010 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
1011
1012 // Do our own replacement and return SDValue() to tell the caller that we
1013 // handled all replacements since caller can only handle a single result.
1014 ReplaceValueWith(SDValue(N, 0), Res);
1015 return SDValue();
1016}
1017
1018SDValue DAGTypeLegalizer::ScalarizeVecOp_VECREDUCE(SDNode *N) {
1019 SDValue Res = GetScalarizedVector(N->getOperand(0));
1020 // Result type may be wider than element type.
1021 if (Res.getValueType() != N->getValueType(0))
1022 Res = DAG.getNode(ISD::ANY_EXTEND, SDLoc(N), N->getValueType(0), Res);
1023 return Res;
1024}
1025
1026SDValue DAGTypeLegalizer::ScalarizeVecOp_VECREDUCE_SEQ(SDNode *N) {
1027 SDValue AccOp = N->getOperand(0);
1028 SDValue VecOp = N->getOperand(1);
1029
1030 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(N->getOpcode());
1031
1032 SDValue Op = GetScalarizedVector(VecOp);
1033 return DAG.getNode(BaseOpc, SDLoc(N), N->getValueType(0),
1034 AccOp, Op, N->getFlags());
1035}
1036
1037SDValue DAGTypeLegalizer::ScalarizeVecOp_CMP(SDNode *N) {
1038 SDValue LHS = GetScalarizedVector(N->getOperand(0));
1039 SDValue RHS = GetScalarizedVector(N->getOperand(1));
1040
1041 EVT ResVT = N->getValueType(0).getVectorElementType();
1042 SDValue Cmp = DAG.getNode(N->getOpcode(), SDLoc(N), ResVT, LHS, RHS);
1043 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Cmp);
1044}
1045
1046//===----------------------------------------------------------------------===//
1047// Result Vector Splitting
1048//===----------------------------------------------------------------------===//
1049
1050/// This method is called when the specified result of the specified node is
1051/// found to need vector splitting. At this point, the node may also have
1052/// invalid operands or may have other results that need legalization, we just
1053/// know that (at least) one result needs vector splitting.
1054void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
1055 LLVM_DEBUG(dbgs() << "Split node result: "; N->dump(&DAG));
1056 SDValue Lo, Hi;
1057
1058 // See if the target wants to custom expand this node.
1059 if (CustomLowerNode(N, N->getValueType(ResNo), true))
1060 return;
1061
1062 switch (N->getOpcode()) {
1063 default:
1064#ifndef NDEBUG
1065 dbgs() << "SplitVectorResult #" << ResNo << ": ";
1066 N->dump(&DAG);
1067 dbgs() << "\n";
1068#endif
1069 report_fatal_error("Do not know how to split the result of this "
1070 "operator!\n");
1071
1072 case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, ResNo, Lo, Hi); break;
1073 case ISD::AssertZext: SplitVecRes_AssertZext(N, Lo, Hi); break;
1074 case ISD::VSELECT:
1075 case ISD::SELECT:
1076 case ISD::VP_MERGE:
1077 case ISD::VP_SELECT: SplitRes_Select(N, Lo, Hi); break;
1078 case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break;
1079 case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break;
1080 case ISD::BITCAST: SplitVecRes_BITCAST(N, Lo, Hi); break;
1081 case ISD::BUILD_VECTOR: SplitVecRes_BUILD_VECTOR(N, Lo, Hi); break;
1082 case ISD::CONCAT_VECTORS: SplitVecRes_CONCAT_VECTORS(N, Lo, Hi); break;
1083 case ISD::EXTRACT_SUBVECTOR: SplitVecRes_EXTRACT_SUBVECTOR(N, Lo, Hi); break;
1084 case ISD::INSERT_SUBVECTOR: SplitVecRes_INSERT_SUBVECTOR(N, Lo, Hi); break;
1085 case ISD::FPOWI:
1086 case ISD::FLDEXP:
1087 case ISD::FCOPYSIGN: SplitVecRes_FPOp_MultiType(N, Lo, Hi); break;
1088 case ISD::IS_FPCLASS: SplitVecRes_IS_FPCLASS(N, Lo, Hi); break;
1089 case ISD::INSERT_VECTOR_ELT: SplitVecRes_INSERT_VECTOR_ELT(N, Lo, Hi); break;
1090 case ISD::EXPERIMENTAL_VP_SPLAT: SplitVecRes_VP_SPLAT(N, Lo, Hi); break;
1091 case ISD::SPLAT_VECTOR:
1093 SplitVecRes_ScalarOp(N, Lo, Hi);
1094 break;
1095 case ISD::STEP_VECTOR:
1096 SplitVecRes_STEP_VECTOR(N, Lo, Hi);
1097 break;
1098 case ISD::SIGN_EXTEND_INREG: SplitVecRes_InregOp(N, Lo, Hi); break;
1099 case ISD::LOAD:
1100 SplitVecRes_LOAD(cast<LoadSDNode>(N), Lo, Hi);
1101 break;
1102 case ISD::VP_LOAD:
1103 SplitVecRes_VP_LOAD(cast<VPLoadSDNode>(N), Lo, Hi);
1104 break;
1105 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
1106 SplitVecRes_VP_STRIDED_LOAD(cast<VPStridedLoadSDNode>(N), Lo, Hi);
1107 break;
1108 case ISD::MLOAD:
1109 SplitVecRes_MLOAD(cast<MaskedLoadSDNode>(N), Lo, Hi);
1110 break;
1111 case ISD::MGATHER:
1112 case ISD::VP_GATHER:
1113 SplitVecRes_Gather(cast<MemSDNode>(N), Lo, Hi, /*SplitSETCC*/ true);
1114 break;
1116 SplitVecRes_VECTOR_COMPRESS(N, Lo, Hi);
1117 break;
1118 case ISD::SETCC:
1119 case ISD::VP_SETCC:
1120 SplitVecRes_SETCC(N, Lo, Hi);
1121 break;
1123 SplitVecRes_VECTOR_REVERSE(N, Lo, Hi);
1124 break;
1126 SplitVecRes_VECTOR_SHUFFLE(cast<ShuffleVectorSDNode>(N), Lo, Hi);
1127 break;
1128 case ISD::VECTOR_SPLICE:
1129 SplitVecRes_VECTOR_SPLICE(N, Lo, Hi);
1130 break;
1132 SplitVecRes_VECTOR_DEINTERLEAVE(N);
1133 return;
1135 SplitVecRes_VECTOR_INTERLEAVE(N);
1136 return;
1137 case ISD::VAARG:
1138 SplitVecRes_VAARG(N, Lo, Hi);
1139 break;
1140
1144 SplitVecRes_ExtVecInRegOp(N, Lo, Hi);
1145 break;
1146
1147 case ISD::ABS:
1148 case ISD::VP_ABS:
1149 case ISD::BITREVERSE:
1150 case ISD::VP_BITREVERSE:
1151 case ISD::BSWAP:
1152 case ISD::VP_BSWAP:
1153 case ISD::CTLZ:
1154 case ISD::VP_CTLZ:
1155 case ISD::CTTZ:
1156 case ISD::VP_CTTZ:
1158 case ISD::VP_CTLZ_ZERO_UNDEF:
1160 case ISD::VP_CTTZ_ZERO_UNDEF:
1161 case ISD::CTPOP:
1162 case ISD::VP_CTPOP:
1163 case ISD::FABS: case ISD::VP_FABS:
1164 case ISD::FACOS:
1165 case ISD::FASIN:
1166 case ISD::FATAN:
1167 case ISD::FCEIL:
1168 case ISD::VP_FCEIL:
1169 case ISD::FCOS:
1170 case ISD::FCOSH:
1171 case ISD::FEXP:
1172 case ISD::FEXP2:
1173 case ISD::FEXP10:
1174 case ISD::FFLOOR:
1175 case ISD::VP_FFLOOR:
1176 case ISD::FLOG:
1177 case ISD::FLOG10:
1178 case ISD::FLOG2:
1179 case ISD::FNEARBYINT:
1180 case ISD::VP_FNEARBYINT:
1181 case ISD::FNEG: case ISD::VP_FNEG:
1182 case ISD::FREEZE:
1183 case ISD::ARITH_FENCE:
1184 case ISD::FP_EXTEND:
1185 case ISD::VP_FP_EXTEND:
1186 case ISD::FP_ROUND:
1187 case ISD::VP_FP_ROUND:
1188 case ISD::FP_TO_SINT:
1189 case ISD::VP_FP_TO_SINT:
1190 case ISD::FP_TO_UINT:
1191 case ISD::VP_FP_TO_UINT:
1192 case ISD::FRINT:
1193 case ISD::VP_FRINT:
1194 case ISD::LRINT:
1195 case ISD::VP_LRINT:
1196 case ISD::LLRINT:
1197 case ISD::VP_LLRINT:
1198 case ISD::FROUND:
1199 case ISD::VP_FROUND:
1200 case ISD::FROUNDEVEN:
1201 case ISD::VP_FROUNDEVEN:
1202 case ISD::FSIN:
1203 case ISD::FSINH:
1204 case ISD::FSQRT: case ISD::VP_SQRT:
1205 case ISD::FTAN:
1206 case ISD::FTANH:
1207 case ISD::FTRUNC:
1208 case ISD::VP_FROUNDTOZERO:
1209 case ISD::SINT_TO_FP:
1210 case ISD::VP_SINT_TO_FP:
1211 case ISD::TRUNCATE:
1212 case ISD::VP_TRUNCATE:
1213 case ISD::UINT_TO_FP:
1214 case ISD::VP_UINT_TO_FP:
1215 case ISD::FCANONICALIZE:
1216 SplitVecRes_UnaryOp(N, Lo, Hi);
1217 break;
1218 case ISD::ADDRSPACECAST:
1219 SplitVecRes_ADDRSPACECAST(N, Lo, Hi);
1220 break;
1221 case ISD::FFREXP:
1222 SplitVecRes_FFREXP(N, ResNo, Lo, Hi);
1223 break;
1224
1225 case ISD::ANY_EXTEND:
1226 case ISD::SIGN_EXTEND:
1227 case ISD::ZERO_EXTEND:
1228 case ISD::VP_SIGN_EXTEND:
1229 case ISD::VP_ZERO_EXTEND:
1230 SplitVecRes_ExtendOp(N, Lo, Hi);
1231 break;
1232
1233 case ISD::ADD: case ISD::VP_ADD:
1234 case ISD::SUB: case ISD::VP_SUB:
1235 case ISD::MUL: case ISD::VP_MUL:
1236 case ISD::MULHS:
1237 case ISD::MULHU:
1238 case ISD::ABDS:
1239 case ISD::ABDU:
1240 case ISD::AVGCEILS:
1241 case ISD::AVGCEILU:
1242 case ISD::AVGFLOORS:
1243 case ISD::AVGFLOORU:
1244 case ISD::FADD: case ISD::VP_FADD:
1245 case ISD::FSUB: case ISD::VP_FSUB:
1246 case ISD::FMUL: case ISD::VP_FMUL:
1247 case ISD::FMINNUM:
1248 case ISD::FMINNUM_IEEE:
1249 case ISD::VP_FMINNUM:
1250 case ISD::FMAXNUM:
1251 case ISD::FMAXNUM_IEEE:
1252 case ISD::VP_FMAXNUM:
1253 case ISD::FMINIMUM:
1254 case ISD::VP_FMINIMUM:
1255 case ISD::FMAXIMUM:
1256 case ISD::VP_FMAXIMUM:
1257 case ISD::SDIV: case ISD::VP_SDIV:
1258 case ISD::UDIV: case ISD::VP_UDIV:
1259 case ISD::FDIV: case ISD::VP_FDIV:
1260 case ISD::FPOW:
1261 case ISD::AND: case ISD::VP_AND:
1262 case ISD::OR: case ISD::VP_OR:
1263 case ISD::XOR: case ISD::VP_XOR:
1264 case ISD::SHL: case ISD::VP_SHL:
1265 case ISD::SRA: case ISD::VP_SRA:
1266 case ISD::SRL: case ISD::VP_SRL:
1267 case ISD::UREM: case ISD::VP_UREM:
1268 case ISD::SREM: case ISD::VP_SREM:
1269 case ISD::FREM: case ISD::VP_FREM:
1270 case ISD::SMIN: case ISD::VP_SMIN:
1271 case ISD::SMAX: case ISD::VP_SMAX:
1272 case ISD::UMIN: case ISD::VP_UMIN:
1273 case ISD::UMAX: case ISD::VP_UMAX:
1274 case ISD::SADDSAT: case ISD::VP_SADDSAT:
1275 case ISD::UADDSAT: case ISD::VP_UADDSAT:
1276 case ISD::SSUBSAT: case ISD::VP_SSUBSAT:
1277 case ISD::USUBSAT: case ISD::VP_USUBSAT:
1278 case ISD::SSHLSAT:
1279 case ISD::USHLSAT:
1280 case ISD::ROTL:
1281 case ISD::ROTR:
1282 case ISD::VP_FCOPYSIGN:
1283 SplitVecRes_BinOp(N, Lo, Hi);
1284 break;
1285 case ISD::FMA: case ISD::VP_FMA:
1286 case ISD::FSHL:
1287 case ISD::VP_FSHL:
1288 case ISD::FSHR:
1289 case ISD::VP_FSHR:
1290 SplitVecRes_TernaryOp(N, Lo, Hi);
1291 break;
1292
1293 case ISD::SCMP: case ISD::UCMP:
1294 SplitVecRes_CMP(N, Lo, Hi);
1295 break;
1296
1297#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
1298 case ISD::STRICT_##DAGN:
1299#include "llvm/IR/ConstrainedOps.def"
1300 SplitVecRes_StrictFPOp(N, Lo, Hi);
1301 break;
1302
1305 SplitVecRes_FP_TO_XINT_SAT(N, Lo, Hi);
1306 break;
1307
1308 case ISD::UADDO:
1309 case ISD::SADDO:
1310 case ISD::USUBO:
1311 case ISD::SSUBO:
1312 case ISD::UMULO:
1313 case ISD::SMULO:
1314 SplitVecRes_OverflowOp(N, ResNo, Lo, Hi);
1315 break;
1316 case ISD::SMULFIX:
1317 case ISD::SMULFIXSAT:
1318 case ISD::UMULFIX:
1319 case ISD::UMULFIXSAT:
1320 case ISD::SDIVFIX:
1321 case ISD::SDIVFIXSAT:
1322 case ISD::UDIVFIX:
1323 case ISD::UDIVFIXSAT:
1324 SplitVecRes_FIX(N, Lo, Hi);
1325 break;
1326 case ISD::EXPERIMENTAL_VP_REVERSE:
1327 SplitVecRes_VP_REVERSE(N, Lo, Hi);
1328 break;
1329 }
1330
1331 // If Lo/Hi is null, the sub-method took care of registering results etc.
1332 if (Lo.getNode())
1333 SetSplitVector(SDValue(N, ResNo), Lo, Hi);
1334}
1335
1336void DAGTypeLegalizer::IncrementPointer(MemSDNode *N, EVT MemVT,
1338 uint64_t *ScaledOffset) {
1339 SDLoc DL(N);
1340 unsigned IncrementSize = MemVT.getSizeInBits().getKnownMinValue() / 8;
1341
1342 if (MemVT.isScalableVector()) {
1344 SDValue BytesIncrement = DAG.getVScale(
1345 DL, Ptr.getValueType(),
1346 APInt(Ptr.getValueSizeInBits().getFixedValue(), IncrementSize));
1347 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
1348 Flags.setNoUnsignedWrap(true);
1349 if (ScaledOffset)
1350 *ScaledOffset += IncrementSize;
1351 Ptr = DAG.getNode(ISD::ADD, DL, Ptr.getValueType(), Ptr, BytesIncrement,
1352 Flags);
1353 } else {
1354 MPI = N->getPointerInfo().getWithOffset(IncrementSize);
1355 // Increment the pointer to the other half.
1356 Ptr = DAG.getObjectPtrOffset(DL, Ptr, TypeSize::getFixed(IncrementSize));
1357 }
1358}
1359
1360std::pair<SDValue, SDValue> DAGTypeLegalizer::SplitMask(SDValue Mask) {
1361 return SplitMask(Mask, SDLoc(Mask));
1362}
1363
1364std::pair<SDValue, SDValue> DAGTypeLegalizer::SplitMask(SDValue Mask,
1365 const SDLoc &DL) {
1366 SDValue MaskLo, MaskHi;
1367 EVT MaskVT = Mask.getValueType();
1368 if (getTypeAction(MaskVT) == TargetLowering::TypeSplitVector)
1369 GetSplitVector(Mask, MaskLo, MaskHi);
1370 else
1371 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
1372 return std::make_pair(MaskLo, MaskHi);
1373}
1374
1375void DAGTypeLegalizer::SplitVecRes_BinOp(SDNode *N, SDValue &Lo, SDValue &Hi) {
1376 SDValue LHSLo, LHSHi;
1377 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1378 SDValue RHSLo, RHSHi;
1379 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
1380 SDLoc dl(N);
1381
1382 const SDNodeFlags Flags = N->getFlags();
1383 unsigned Opcode = N->getOpcode();
1384 if (N->getNumOperands() == 2) {
1385 Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(), LHSLo, RHSLo, Flags);
1386 Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(), LHSHi, RHSHi, Flags);
1387 return;
1388 }
1389
1390 assert(N->getNumOperands() == 4 && "Unexpected number of operands!");
1391 assert(N->isVPOpcode() && "Expected VP opcode");
1392
1393 SDValue MaskLo, MaskHi;
1394 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(2));
1395
1396 SDValue EVLLo, EVLHi;
1397 std::tie(EVLLo, EVLHi) =
1398 DAG.SplitEVL(N->getOperand(3), N->getValueType(0), dl);
1399
1400 Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(),
1401 {LHSLo, RHSLo, MaskLo, EVLLo}, Flags);
1402 Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(),
1403 {LHSHi, RHSHi, MaskHi, EVLHi}, Flags);
1404}
1405
1406void DAGTypeLegalizer::SplitVecRes_TernaryOp(SDNode *N, SDValue &Lo,
1407 SDValue &Hi) {
1408 SDValue Op0Lo, Op0Hi;
1409 GetSplitVector(N->getOperand(0), Op0Lo, Op0Hi);
1410 SDValue Op1Lo, Op1Hi;
1411 GetSplitVector(N->getOperand(1), Op1Lo, Op1Hi);
1412 SDValue Op2Lo, Op2Hi;
1413 GetSplitVector(N->getOperand(2), Op2Lo, Op2Hi);
1414 SDLoc dl(N);
1415
1416 const SDNodeFlags Flags = N->getFlags();
1417 unsigned Opcode = N->getOpcode();
1418 if (N->getNumOperands() == 3) {
1419 Lo = DAG.getNode(Opcode, dl, Op0Lo.getValueType(), Op0Lo, Op1Lo, Op2Lo, Flags);
1420 Hi = DAG.getNode(Opcode, dl, Op0Hi.getValueType(), Op0Hi, Op1Hi, Op2Hi, Flags);
1421 return;
1422 }
1423
1424 assert(N->getNumOperands() == 5 && "Unexpected number of operands!");
1425 assert(N->isVPOpcode() && "Expected VP opcode");
1426
1427 SDValue MaskLo, MaskHi;
1428 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(3));
1429
1430 SDValue EVLLo, EVLHi;
1431 std::tie(EVLLo, EVLHi) =
1432 DAG.SplitEVL(N->getOperand(4), N->getValueType(0), dl);
1433
1434 Lo = DAG.getNode(Opcode, dl, Op0Lo.getValueType(),
1435 {Op0Lo, Op1Lo, Op2Lo, MaskLo, EVLLo}, Flags);
1436 Hi = DAG.getNode(Opcode, dl, Op0Hi.getValueType(),
1437 {Op0Hi, Op1Hi, Op2Hi, MaskHi, EVLHi}, Flags);
1438}
1439
1440void DAGTypeLegalizer::SplitVecRes_CMP(SDNode *N, SDValue &Lo, SDValue &Hi) {
1441 LLVMContext &Ctxt = *DAG.getContext();
1442 SDLoc dl(N);
1443
1444 SDValue LHS = N->getOperand(0);
1445 SDValue RHS = N->getOperand(1);
1446
1447 SDValue LHSLo, LHSHi, RHSLo, RHSHi;
1448 if (getTypeAction(LHS.getValueType()) == TargetLowering::TypeSplitVector) {
1449 GetSplitVector(LHS, LHSLo, LHSHi);
1450 GetSplitVector(RHS, RHSLo, RHSHi);
1451 } else {
1452 std::tie(LHSLo, LHSHi) = DAG.SplitVector(LHS, dl);
1453 std::tie(RHSLo, RHSHi) = DAG.SplitVector(RHS, dl);
1454 }
1455
1456 EVT SplitResVT = N->getValueType(0).getHalfNumVectorElementsVT(Ctxt);
1457 Lo = DAG.getNode(N->getOpcode(), dl, SplitResVT, LHSLo, RHSLo);
1458 Hi = DAG.getNode(N->getOpcode(), dl, SplitResVT, LHSHi, RHSHi);
1459}
1460
1461void DAGTypeLegalizer::SplitVecRes_FIX(SDNode *N, SDValue &Lo, SDValue &Hi) {
1462 SDValue LHSLo, LHSHi;
1463 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1464 SDValue RHSLo, RHSHi;
1465 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
1466 SDLoc dl(N);
1467 SDValue Op2 = N->getOperand(2);
1468
1469 unsigned Opcode = N->getOpcode();
1470 Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(), LHSLo, RHSLo, Op2,
1471 N->getFlags());
1472 Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(), LHSHi, RHSHi, Op2,
1473 N->getFlags());
1474}
1475
1476void DAGTypeLegalizer::SplitVecRes_BITCAST(SDNode *N, SDValue &Lo,
1477 SDValue &Hi) {
1478 // We know the result is a vector. The input may be either a vector or a
1479 // scalar value.
1480 EVT LoVT, HiVT;
1481 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1482 SDLoc dl(N);
1483
1484 SDValue InOp = N->getOperand(0);
1485 EVT InVT = InOp.getValueType();
1486
1487 // Handle some special cases efficiently.
1488 switch (getTypeAction(InVT)) {
1496 break;
1499 // A scalar to vector conversion, where the scalar needs expansion.
1500 // If the vector is being split in two then we can just convert the
1501 // expanded pieces.
1502 if (LoVT == HiVT) {
1503 GetExpandedOp(InOp, Lo, Hi);
1504 if (DAG.getDataLayout().isBigEndian())
1505 std::swap(Lo, Hi);
1506 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
1507 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
1508 return;
1509 }
1510 break;
1512 // If the input is a vector that needs to be split, convert each split
1513 // piece of the input now.
1514 GetSplitVector(InOp, Lo, Hi);
1515 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
1516 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
1517 return;
1519 report_fatal_error("Scalarization of scalable vectors is not supported.");
1520 }
1521
1522 if (LoVT.isScalableVector()) {
1523 auto [InLo, InHi] = DAG.SplitVectorOperand(N, 0);
1524 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, InLo);
1525 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, InHi);
1526 return;
1527 }
1528
1529 // In the general case, convert the input to an integer and split it by hand.
1530 EVT LoIntVT = EVT::getIntegerVT(*DAG.getContext(), LoVT.getSizeInBits());
1531 EVT HiIntVT = EVT::getIntegerVT(*DAG.getContext(), HiVT.getSizeInBits());
1532 if (DAG.getDataLayout().isBigEndian())
1533 std::swap(LoIntVT, HiIntVT);
1534
1535 SplitInteger(BitConvertToInteger(InOp), LoIntVT, HiIntVT, Lo, Hi);
1536
1537 if (DAG.getDataLayout().isBigEndian())
1538 std::swap(Lo, Hi);
1539 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
1540 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
1541}
1542
1543void DAGTypeLegalizer::SplitVecRes_BUILD_VECTOR(SDNode *N, SDValue &Lo,
1544 SDValue &Hi) {
1545 EVT LoVT, HiVT;
1546 SDLoc dl(N);
1547 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1548 unsigned LoNumElts = LoVT.getVectorNumElements();
1549 SmallVector<SDValue, 8> LoOps(N->op_begin(), N->op_begin()+LoNumElts);
1550 Lo = DAG.getBuildVector(LoVT, dl, LoOps);
1551
1552 SmallVector<SDValue, 8> HiOps(N->op_begin()+LoNumElts, N->op_end());
1553 Hi = DAG.getBuildVector(HiVT, dl, HiOps);
1554}
1555
1556void DAGTypeLegalizer::SplitVecRes_CONCAT_VECTORS(SDNode *N, SDValue &Lo,
1557 SDValue &Hi) {
1558 assert(!(N->getNumOperands() & 1) && "Unsupported CONCAT_VECTORS");
1559 SDLoc dl(N);
1560 unsigned NumSubvectors = N->getNumOperands() / 2;
1561 if (NumSubvectors == 1) {
1562 Lo = N->getOperand(0);
1563 Hi = N->getOperand(1);
1564 return;
1565 }
1566
1567 EVT LoVT, HiVT;
1568 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1569
1570 SmallVector<SDValue, 8> LoOps(N->op_begin(), N->op_begin()+NumSubvectors);
1571 Lo = DAG.getNode(ISD::CONCAT_VECTORS, dl, LoVT, LoOps);
1572
1573 SmallVector<SDValue, 8> HiOps(N->op_begin()+NumSubvectors, N->op_end());
1574 Hi = DAG.getNode(ISD::CONCAT_VECTORS, dl, HiVT, HiOps);
1575}
1576
1577void DAGTypeLegalizer::SplitVecRes_EXTRACT_SUBVECTOR(SDNode *N, SDValue &Lo,
1578 SDValue &Hi) {
1579 SDValue Vec = N->getOperand(0);
1580 SDValue Idx = N->getOperand(1);
1581 SDLoc dl(N);
1582
1583 EVT LoVT, HiVT;
1584 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1585
1586 Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, LoVT, Vec, Idx);
1587 uint64_t IdxVal = Idx->getAsZExtVal();
1588 Hi = DAG.getNode(
1589 ISD::EXTRACT_SUBVECTOR, dl, HiVT, Vec,
1590 DAG.getVectorIdxConstant(IdxVal + LoVT.getVectorMinNumElements(), dl));
1591}
1592
1593void DAGTypeLegalizer::SplitVecRes_INSERT_SUBVECTOR(SDNode *N, SDValue &Lo,
1594 SDValue &Hi) {
1595 SDValue Vec = N->getOperand(0);
1596 SDValue SubVec = N->getOperand(1);
1597 SDValue Idx = N->getOperand(2);
1598 SDLoc dl(N);
1599 GetSplitVector(Vec, Lo, Hi);
1600
1601 EVT VecVT = Vec.getValueType();
1602 EVT LoVT = Lo.getValueType();
1603 EVT SubVecVT = SubVec.getValueType();
1604 unsigned VecElems = VecVT.getVectorMinNumElements();
1605 unsigned SubElems = SubVecVT.getVectorMinNumElements();
1606 unsigned LoElems = LoVT.getVectorMinNumElements();
1607
1608 // If we know the index is in the first half, and we know the subvector
1609 // doesn't cross the boundary between the halves, we can avoid spilling the
1610 // vector, and insert into the lower half of the split vector directly.
1611 unsigned IdxVal = Idx->getAsZExtVal();
1612 if (IdxVal + SubElems <= LoElems) {
1613 Lo = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, LoVT, Lo, SubVec, Idx);
1614 return;
1615 }
1616 // Similarly if the subvector is fully in the high half, but mind that we
1617 // can't tell whether a fixed-length subvector is fully within the high half
1618 // of a scalable vector.
1619 if (VecVT.isScalableVector() == SubVecVT.isScalableVector() &&
1620 IdxVal >= LoElems && IdxVal + SubElems <= VecElems) {
1621 Hi = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, Hi.getValueType(), Hi, SubVec,
1622 DAG.getVectorIdxConstant(IdxVal - LoElems, dl));
1623 return;
1624 }
1625
1626 // Spill the vector to the stack.
1627 // In cases where the vector is illegal it will be broken down into parts
1628 // and stored in parts - we should use the alignment for the smallest part.
1629 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
1631 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
1632 auto &MF = DAG.getMachineFunction();
1633 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
1634 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
1635
1636 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
1637 SmallestAlign);
1638
1639 // Store the new subvector into the specified index.
1640 SDValue SubVecPtr =
1641 TLI.getVectorSubVecPointer(DAG, StackPtr, VecVT, SubVecVT, Idx);
1642 Store = DAG.getStore(Store, dl, SubVec, SubVecPtr,
1644
1645 // Load the Lo part from the stack slot.
1646 Lo = DAG.getLoad(Lo.getValueType(), dl, Store, StackPtr, PtrInfo,
1647 SmallestAlign);
1648
1649 // Increment the pointer to the other part.
1650 auto *Load = cast<LoadSDNode>(Lo);
1651 MachinePointerInfo MPI = Load->getPointerInfo();
1652 IncrementPointer(Load, LoVT, MPI, StackPtr);
1653
1654 // Load the Hi part from the stack slot.
1655 Hi = DAG.getLoad(Hi.getValueType(), dl, Store, StackPtr, MPI, SmallestAlign);
1656}
1657
1658// Handle splitting an FP where the second operand does not match the first
1659// type. The second operand may be a scalar, or a vector that has exactly as
1660// many elements as the first
1661void DAGTypeLegalizer::SplitVecRes_FPOp_MultiType(SDNode *N, SDValue &Lo,
1662 SDValue &Hi) {
1663 SDValue LHSLo, LHSHi;
1664 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1665 SDLoc DL(N);
1666
1667 SDValue RHSLo, RHSHi;
1668 SDValue RHS = N->getOperand(1);
1669 EVT RHSVT = RHS.getValueType();
1670 if (RHSVT.isVector()) {
1671 if (getTypeAction(RHSVT) == TargetLowering::TypeSplitVector)
1672 GetSplitVector(RHS, RHSLo, RHSHi);
1673 else
1674 std::tie(RHSLo, RHSHi) = DAG.SplitVector(RHS, SDLoc(RHS));
1675
1676 Lo = DAG.getNode(N->getOpcode(), DL, LHSLo.getValueType(), LHSLo, RHSLo);
1677 Hi = DAG.getNode(N->getOpcode(), DL, LHSHi.getValueType(), LHSHi, RHSHi);
1678 } else {
1679 Lo = DAG.getNode(N->getOpcode(), DL, LHSLo.getValueType(), LHSLo, RHS);
1680 Hi = DAG.getNode(N->getOpcode(), DL, LHSHi.getValueType(), LHSHi, RHS);
1681 }
1682}
1683
1684void DAGTypeLegalizer::SplitVecRes_IS_FPCLASS(SDNode *N, SDValue &Lo,
1685 SDValue &Hi) {
1686 SDLoc DL(N);
1687 SDValue ArgLo, ArgHi;
1688 SDValue Test = N->getOperand(1);
1689 SDValue FpValue = N->getOperand(0);
1690 if (getTypeAction(FpValue.getValueType()) == TargetLowering::TypeSplitVector)
1691 GetSplitVector(FpValue, ArgLo, ArgHi);
1692 else
1693 std::tie(ArgLo, ArgHi) = DAG.SplitVector(FpValue, SDLoc(FpValue));
1694 EVT LoVT, HiVT;
1695 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1696
1697 Lo = DAG.getNode(ISD::IS_FPCLASS, DL, LoVT, ArgLo, Test, N->getFlags());
1698 Hi = DAG.getNode(ISD::IS_FPCLASS, DL, HiVT, ArgHi, Test, N->getFlags());
1699}
1700
1701void DAGTypeLegalizer::SplitVecRes_InregOp(SDNode *N, SDValue &Lo,
1702 SDValue &Hi) {
1703 SDValue LHSLo, LHSHi;
1704 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1705 SDLoc dl(N);
1706
1707 EVT LoVT, HiVT;
1708 std::tie(LoVT, HiVT) =
1709 DAG.GetSplitDestVTs(cast<VTSDNode>(N->getOperand(1))->getVT());
1710
1711 Lo = DAG.getNode(N->getOpcode(), dl, LHSLo.getValueType(), LHSLo,
1712 DAG.getValueType(LoVT));
1713 Hi = DAG.getNode(N->getOpcode(), dl, LHSHi.getValueType(), LHSHi,
1714 DAG.getValueType(HiVT));
1715}
1716
1717void DAGTypeLegalizer::SplitVecRes_ExtVecInRegOp(SDNode *N, SDValue &Lo,
1718 SDValue &Hi) {
1719 unsigned Opcode = N->getOpcode();
1720 SDValue N0 = N->getOperand(0);
1721
1722 SDLoc dl(N);
1723 SDValue InLo, InHi;
1724
1725 if (getTypeAction(N0.getValueType()) == TargetLowering::TypeSplitVector)
1726 GetSplitVector(N0, InLo, InHi);
1727 else
1728 std::tie(InLo, InHi) = DAG.SplitVectorOperand(N, 0);
1729
1730 EVT InLoVT = InLo.getValueType();
1731 unsigned InNumElements = InLoVT.getVectorNumElements();
1732
1733 EVT OutLoVT, OutHiVT;
1734 std::tie(OutLoVT, OutHiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1735 unsigned OutNumElements = OutLoVT.getVectorNumElements();
1736 assert((2 * OutNumElements) <= InNumElements &&
1737 "Illegal extend vector in reg split");
1738
1739 // *_EXTEND_VECTOR_INREG instructions extend the lowest elements of the
1740 // input vector (i.e. we only use InLo):
1741 // OutLo will extend the first OutNumElements from InLo.
1742 // OutHi will extend the next OutNumElements from InLo.
1743
1744 // Shuffle the elements from InLo for OutHi into the bottom elements to
1745 // create a 'fake' InHi.
1746 SmallVector<int, 8> SplitHi(InNumElements, -1);
1747 for (unsigned i = 0; i != OutNumElements; ++i)
1748 SplitHi[i] = i + OutNumElements;
1749 InHi = DAG.getVectorShuffle(InLoVT, dl, InLo, DAG.getUNDEF(InLoVT), SplitHi);
1750
1751 Lo = DAG.getNode(Opcode, dl, OutLoVT, InLo);
1752 Hi = DAG.getNode(Opcode, dl, OutHiVT, InHi);
1753}
1754
1755void DAGTypeLegalizer::SplitVecRes_StrictFPOp(SDNode *N, SDValue &Lo,
1756 SDValue &Hi) {
1757 unsigned NumOps = N->getNumOperands();
1758 SDValue Chain = N->getOperand(0);
1759 EVT LoVT, HiVT;
1760 SDLoc dl(N);
1761 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1762
1763 SmallVector<SDValue, 4> OpsLo(NumOps);
1764 SmallVector<SDValue, 4> OpsHi(NumOps);
1765
1766 // The Chain is the first operand.
1767 OpsLo[0] = Chain;
1768 OpsHi[0] = Chain;
1769
1770 // Now process the remaining operands.
1771 for (unsigned i = 1; i < NumOps; ++i) {
1772 SDValue Op = N->getOperand(i);
1773 SDValue OpLo = Op;
1774 SDValue OpHi = Op;
1775
1776 EVT InVT = Op.getValueType();
1777 if (InVT.isVector()) {
1778 // If the input also splits, handle it directly for a
1779 // compile time speedup. Otherwise split it by hand.
1780 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
1781 GetSplitVector(Op, OpLo, OpHi);
1782 else
1783 std::tie(OpLo, OpHi) = DAG.SplitVectorOperand(N, i);
1784 }
1785
1786 OpsLo[i] = OpLo;
1787 OpsHi[i] = OpHi;
1788 }
1789
1790 EVT LoValueVTs[] = {LoVT, MVT::Other};
1791 EVT HiValueVTs[] = {HiVT, MVT::Other};
1792 Lo = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(LoValueVTs), OpsLo,
1793 N->getFlags());
1794 Hi = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(HiValueVTs), OpsHi,
1795 N->getFlags());
1796
1797 // Build a factor node to remember that this Op is independent of the
1798 // other one.
1799 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
1800 Lo.getValue(1), Hi.getValue(1));
1801
1802 // Legalize the chain result - switch anything that used the old chain to
1803 // use the new one.
1804 ReplaceValueWith(SDValue(N, 1), Chain);
1805}
1806
1807SDValue DAGTypeLegalizer::UnrollVectorOp_StrictFP(SDNode *N, unsigned ResNE) {
1808 SDValue Chain = N->getOperand(0);
1809 EVT VT = N->getValueType(0);
1810 unsigned NE = VT.getVectorNumElements();
1811 EVT EltVT = VT.getVectorElementType();
1812 SDLoc dl(N);
1813
1815 SmallVector<SDValue, 4> Operands(N->getNumOperands());
1816
1817 // If ResNE is 0, fully unroll the vector op.
1818 if (ResNE == 0)
1819 ResNE = NE;
1820 else if (NE > ResNE)
1821 NE = ResNE;
1822
1823 //The results of each unrolled operation, including the chain.
1824 EVT ChainVTs[] = {EltVT, MVT::Other};
1826
1827 unsigned i;
1828 for (i = 0; i != NE; ++i) {
1829 Operands[0] = Chain;
1830 for (unsigned j = 1, e = N->getNumOperands(); j != e; ++j) {
1831 SDValue Operand = N->getOperand(j);
1832 EVT OperandVT = Operand.getValueType();
1833 if (OperandVT.isVector()) {
1834 EVT OperandEltVT = OperandVT.getVectorElementType();
1835 Operands[j] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, OperandEltVT,
1836 Operand, DAG.getVectorIdxConstant(i, dl));
1837 } else {
1838 Operands[j] = Operand;
1839 }
1840 }
1841 SDValue Scalar = DAG.getNode(N->getOpcode(), dl, ChainVTs, Operands);
1842 Scalar.getNode()->setFlags(N->getFlags());
1843
1844 //Add in the scalar as well as its chain value to the
1845 //result vectors.
1846 Scalars.push_back(Scalar);
1847 Chains.push_back(Scalar.getValue(1));
1848 }
1849
1850 for (; i < ResNE; ++i)
1851 Scalars.push_back(DAG.getUNDEF(EltVT));
1852
1853 // Build a new factor node to connect the chain back together.
1854 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
1855 ReplaceValueWith(SDValue(N, 1), Chain);
1856
1857 // Create a new BUILD_VECTOR node
1858 EVT VecVT = EVT::getVectorVT(*DAG.getContext(), EltVT, ResNE);
1859 return DAG.getBuildVector(VecVT, dl, Scalars);
1860}
1861
1862void DAGTypeLegalizer::SplitVecRes_OverflowOp(SDNode *N, unsigned ResNo,
1863 SDValue &Lo, SDValue &Hi) {
1864 SDLoc dl(N);
1865 EVT ResVT = N->getValueType(0);
1866 EVT OvVT = N->getValueType(1);
1867 EVT LoResVT, HiResVT, LoOvVT, HiOvVT;
1868 std::tie(LoResVT, HiResVT) = DAG.GetSplitDestVTs(ResVT);
1869 std::tie(LoOvVT, HiOvVT) = DAG.GetSplitDestVTs(OvVT);
1870
1871 SDValue LoLHS, HiLHS, LoRHS, HiRHS;
1872 if (getTypeAction(ResVT) == TargetLowering::TypeSplitVector) {
1873 GetSplitVector(N->getOperand(0), LoLHS, HiLHS);
1874 GetSplitVector(N->getOperand(1), LoRHS, HiRHS);
1875 } else {
1876 std::tie(LoLHS, HiLHS) = DAG.SplitVectorOperand(N, 0);
1877 std::tie(LoRHS, HiRHS) = DAG.SplitVectorOperand(N, 1);
1878 }
1879
1880 unsigned Opcode = N->getOpcode();
1881 SDVTList LoVTs = DAG.getVTList(LoResVT, LoOvVT);
1882 SDVTList HiVTs = DAG.getVTList(HiResVT, HiOvVT);
1883 SDNode *LoNode = DAG.getNode(Opcode, dl, LoVTs, LoLHS, LoRHS).getNode();
1884 SDNode *HiNode = DAG.getNode(Opcode, dl, HiVTs, HiLHS, HiRHS).getNode();
1885 LoNode->setFlags(N->getFlags());
1886 HiNode->setFlags(N->getFlags());
1887
1888 Lo = SDValue(LoNode, ResNo);
1889 Hi = SDValue(HiNode, ResNo);
1890
1891 // Replace the other vector result not being explicitly split here.
1892 unsigned OtherNo = 1 - ResNo;
1893 EVT OtherVT = N->getValueType(OtherNo);
1894 if (getTypeAction(OtherVT) == TargetLowering::TypeSplitVector) {
1895 SetSplitVector(SDValue(N, OtherNo),
1896 SDValue(LoNode, OtherNo), SDValue(HiNode, OtherNo));
1897 } else {
1898 SDValue OtherVal = DAG.getNode(
1899 ISD::CONCAT_VECTORS, dl, OtherVT,
1900 SDValue(LoNode, OtherNo), SDValue(HiNode, OtherNo));
1901 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
1902 }
1903}
1904
1905void DAGTypeLegalizer::SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo,
1906 SDValue &Hi) {
1907 SDValue Vec = N->getOperand(0);
1908 SDValue Elt = N->getOperand(1);
1909 SDValue Idx = N->getOperand(2);
1910 SDLoc dl(N);
1911 GetSplitVector(Vec, Lo, Hi);
1912
1913 if (ConstantSDNode *CIdx = dyn_cast<ConstantSDNode>(Idx)) {
1914 unsigned IdxVal = CIdx->getZExtValue();
1915 unsigned LoNumElts = Lo.getValueType().getVectorMinNumElements();
1916 if (IdxVal < LoNumElts) {
1918 Lo.getValueType(), Lo, Elt, Idx);
1919 return;
1920 } else if (!Vec.getValueType().isScalableVector()) {
1921 Hi = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, Hi.getValueType(), Hi, Elt,
1922 DAG.getVectorIdxConstant(IdxVal - LoNumElts, dl));
1923 return;
1924 }
1925 }
1926
1927 // Make the vector elements byte-addressable if they aren't already.
1928 EVT VecVT = Vec.getValueType();
1929 EVT EltVT = VecVT.getVectorElementType();
1930 if (!EltVT.isByteSized()) {
1931 EltVT = EltVT.changeTypeToInteger().getRoundIntegerType(*DAG.getContext());
1932 VecVT = VecVT.changeElementType(EltVT);
1933 Vec = DAG.getNode(ISD::ANY_EXTEND, dl, VecVT, Vec);
1934 // Extend the element type to match if needed.
1935 if (EltVT.bitsGT(Elt.getValueType()))
1936 Elt = DAG.getNode(ISD::ANY_EXTEND, dl, EltVT, Elt);
1937 }
1938
1939 // Spill the vector to the stack.
1940 // In cases where the vector is illegal it will be broken down into parts
1941 // and stored in parts - we should use the alignment for the smallest part.
1942 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
1944 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
1945 auto &MF = DAG.getMachineFunction();
1946 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
1947 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
1948
1949 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
1950 SmallestAlign);
1951
1952 // Store the new element. This may be larger than the vector element type,
1953 // so use a truncating store.
1954 SDValue EltPtr = TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Idx);
1955 Store = DAG.getTruncStore(
1956 Store, dl, Elt, EltPtr, MachinePointerInfo::getUnknownStack(MF), EltVT,
1957 commonAlignment(SmallestAlign,
1958 EltVT.getFixedSizeInBits() / 8));
1959
1960 EVT LoVT, HiVT;
1961 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(VecVT);
1962
1963 // Load the Lo part from the stack slot.
1964 Lo = DAG.getLoad(LoVT, dl, Store, StackPtr, PtrInfo, SmallestAlign);
1965
1966 // Increment the pointer to the other part.
1967 auto Load = cast<LoadSDNode>(Lo);
1968 MachinePointerInfo MPI = Load->getPointerInfo();
1969 IncrementPointer(Load, LoVT, MPI, StackPtr);
1970
1971 Hi = DAG.getLoad(HiVT, dl, Store, StackPtr, MPI, SmallestAlign);
1972
1973 // If we adjusted the original type, we need to truncate the results.
1974 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1975 if (LoVT != Lo.getValueType())
1976 Lo = DAG.getNode(ISD::TRUNCATE, dl, LoVT, Lo);
1977 if (HiVT != Hi.getValueType())
1978 Hi = DAG.getNode(ISD::TRUNCATE, dl, HiVT, Hi);
1979}
1980
1981void DAGTypeLegalizer::SplitVecRes_STEP_VECTOR(SDNode *N, SDValue &Lo,
1982 SDValue &Hi) {
1983 EVT LoVT, HiVT;
1984 SDLoc dl(N);
1985 assert(N->getValueType(0).isScalableVector() &&
1986 "Only scalable vectors are supported for STEP_VECTOR");
1987 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1988 SDValue Step = N->getOperand(0);
1989
1990 Lo = DAG.getNode(ISD::STEP_VECTOR, dl, LoVT, Step);
1991
1992 // Hi = Lo + (EltCnt * Step)
1993 EVT EltVT = Step.getValueType();
1994 APInt StepVal = Step->getAsAPIntVal();
1995 SDValue StartOfHi =
1996 DAG.getVScale(dl, EltVT, StepVal * LoVT.getVectorMinNumElements());
1997 StartOfHi = DAG.getSExtOrTrunc(StartOfHi, dl, HiVT.getVectorElementType());
1998 StartOfHi = DAG.getNode(ISD::SPLAT_VECTOR, dl, HiVT, StartOfHi);
1999
2000 Hi = DAG.getNode(ISD::STEP_VECTOR, dl, HiVT, Step);
2001 Hi = DAG.getNode(ISD::ADD, dl, HiVT, Hi, StartOfHi);
2002}
2003
2004void DAGTypeLegalizer::SplitVecRes_ScalarOp(SDNode *N, SDValue &Lo,
2005 SDValue &Hi) {
2006 EVT LoVT, HiVT;
2007 SDLoc dl(N);
2008 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2009 Lo = DAG.getNode(N->getOpcode(), dl, LoVT, N->getOperand(0));
2010 if (N->getOpcode() == ISD::SCALAR_TO_VECTOR) {
2011 Hi = DAG.getUNDEF(HiVT);
2012 } else {
2013 assert(N->getOpcode() == ISD::SPLAT_VECTOR && "Unexpected opcode");
2014 Hi = Lo;
2015 }
2016}
2017
2018void DAGTypeLegalizer::SplitVecRes_VP_SPLAT(SDNode *N, SDValue &Lo,
2019 SDValue &Hi) {
2020 SDLoc dl(N);
2021 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(N->getValueType(0));
2022 auto [MaskLo, MaskHi] = SplitMask(N->getOperand(1));
2023 auto [EVLLo, EVLHi] = DAG.SplitEVL(N->getOperand(2), N->getValueType(0), dl);
2024 Lo = DAG.getNode(N->getOpcode(), dl, LoVT, N->getOperand(0), MaskLo, EVLLo);
2025 Hi = DAG.getNode(N->getOpcode(), dl, HiVT, N->getOperand(0), MaskHi, EVLHi);
2026}
2027
2028void DAGTypeLegalizer::SplitVecRes_LOAD(LoadSDNode *LD, SDValue &Lo,
2029 SDValue &Hi) {
2030 assert(ISD::isUNINDEXEDLoad(LD) && "Indexed load during type legalization!");
2031 EVT LoVT, HiVT;
2032 SDLoc dl(LD);
2033 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(LD->getValueType(0));
2034
2035 ISD::LoadExtType ExtType = LD->getExtensionType();
2036 SDValue Ch = LD->getChain();
2037 SDValue Ptr = LD->getBasePtr();
2038 SDValue Offset = DAG.getUNDEF(Ptr.getValueType());
2039 EVT MemoryVT = LD->getMemoryVT();
2040 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
2041 AAMDNodes AAInfo = LD->getAAInfo();
2042
2043 EVT LoMemVT, HiMemVT;
2044 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
2045
2046 if (!LoMemVT.isByteSized() || !HiMemVT.isByteSized()) {
2047 SDValue Value, NewChain;
2048 std::tie(Value, NewChain) = TLI.scalarizeVectorLoad(LD, DAG);
2049 std::tie(Lo, Hi) = DAG.SplitVector(Value, dl);
2050 ReplaceValueWith(SDValue(LD, 1), NewChain);
2051 return;
2052 }
2053
2054 Lo = DAG.getLoad(ISD::UNINDEXED, ExtType, LoVT, dl, Ch, Ptr, Offset,
2055 LD->getPointerInfo(), LoMemVT, LD->getOriginalAlign(),
2056 MMOFlags, AAInfo);
2057
2059 IncrementPointer(LD, LoMemVT, MPI, Ptr);
2060
2061 Hi = DAG.getLoad(ISD::UNINDEXED, ExtType, HiVT, dl, Ch, Ptr, Offset, MPI,
2062 HiMemVT, LD->getOriginalAlign(), MMOFlags, AAInfo);
2063
2064 // Build a factor node to remember that this load is independent of the
2065 // other one.
2066 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2067 Hi.getValue(1));
2068
2069 // Legalize the chain result - switch anything that used the old chain to
2070 // use the new one.
2071 ReplaceValueWith(SDValue(LD, 1), Ch);
2072}
2073
2074void DAGTypeLegalizer::SplitVecRes_VP_LOAD(VPLoadSDNode *LD, SDValue &Lo,
2075 SDValue &Hi) {
2076 assert(LD->isUnindexed() && "Indexed VP load during type legalization!");
2077 EVT LoVT, HiVT;
2078 SDLoc dl(LD);
2079 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(LD->getValueType(0));
2080
2081 ISD::LoadExtType ExtType = LD->getExtensionType();
2082 SDValue Ch = LD->getChain();
2083 SDValue Ptr = LD->getBasePtr();
2084 SDValue Offset = LD->getOffset();
2085 assert(Offset.isUndef() && "Unexpected indexed variable-length load offset");
2086 Align Alignment = LD->getOriginalAlign();
2087 SDValue Mask = LD->getMask();
2088 SDValue EVL = LD->getVectorLength();
2089 EVT MemoryVT = LD->getMemoryVT();
2090
2091 EVT LoMemVT, HiMemVT;
2092 bool HiIsEmpty = false;
2093 std::tie(LoMemVT, HiMemVT) =
2094 DAG.GetDependentSplitDestVTs(MemoryVT, LoVT, &HiIsEmpty);
2095
2096 // Split Mask operand
2097 SDValue MaskLo, MaskHi;
2098 if (Mask.getOpcode() == ISD::SETCC) {
2099 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
2100 } else {
2101 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
2102 GetSplitVector(Mask, MaskLo, MaskHi);
2103 else
2104 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, dl);
2105 }
2106
2107 // Split EVL operand
2108 SDValue EVLLo, EVLHi;
2109 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(EVL, LD->getValueType(0), dl);
2110
2112 LD->getPointerInfo(), MachineMemOperand::MOLoad,
2113 LocationSize::beforeOrAfterPointer(), Alignment, LD->getAAInfo(),
2114 LD->getRanges());
2115
2116 Lo =
2117 DAG.getLoadVP(LD->getAddressingMode(), ExtType, LoVT, dl, Ch, Ptr, Offset,
2118 MaskLo, EVLLo, LoMemVT, MMO, LD->isExpandingLoad());
2119
2120 if (HiIsEmpty) {
2121 // The hi vp_load has zero storage size. We therefore simply set it to
2122 // the low vp_load and rely on subsequent removal from the chain.
2123 Hi = Lo;
2124 } else {
2125 // Generate hi vp_load.
2126 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, dl, LoMemVT, DAG,
2127 LD->isExpandingLoad());
2128
2130 if (LoMemVT.isScalableVector())
2131 MPI = MachinePointerInfo(LD->getPointerInfo().getAddrSpace());
2132 else
2133 MPI = LD->getPointerInfo().getWithOffset(
2134 LoMemVT.getStoreSize().getFixedValue());
2135
2138 Alignment, LD->getAAInfo(), LD->getRanges());
2139
2140 Hi = DAG.getLoadVP(LD->getAddressingMode(), ExtType, HiVT, dl, Ch, Ptr,
2141 Offset, MaskHi, EVLHi, HiMemVT, MMO,
2142 LD->isExpandingLoad());
2143 }
2144
2145 // Build a factor node to remember that this load is independent of the
2146 // other one.
2147 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2148 Hi.getValue(1));
2149
2150 // Legalize the chain result - switch anything that used the old chain to
2151 // use the new one.
2152 ReplaceValueWith(SDValue(LD, 1), Ch);
2153}
2154
2155void DAGTypeLegalizer::SplitVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode *SLD,
2156 SDValue &Lo, SDValue &Hi) {
2157 assert(SLD->isUnindexed() &&
2158 "Indexed VP strided load during type legalization!");
2159 assert(SLD->getOffset().isUndef() &&
2160 "Unexpected indexed variable-length load offset");
2161
2162 SDLoc DL(SLD);
2163
2164 EVT LoVT, HiVT;
2165 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(SLD->getValueType(0));
2166
2167 EVT LoMemVT, HiMemVT;
2168 bool HiIsEmpty = false;
2169 std::tie(LoMemVT, HiMemVT) =
2170 DAG.GetDependentSplitDestVTs(SLD->getMemoryVT(), LoVT, &HiIsEmpty);
2171
2172 SDValue Mask = SLD->getMask();
2173 SDValue LoMask, HiMask;
2174 if (Mask.getOpcode() == ISD::SETCC) {
2175 SplitVecRes_SETCC(Mask.getNode(), LoMask, HiMask);
2176 } else {
2177 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
2178 GetSplitVector(Mask, LoMask, HiMask);
2179 else
2180 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
2181 }
2182
2183 SDValue LoEVL, HiEVL;
2184 std::tie(LoEVL, HiEVL) =
2185 DAG.SplitEVL(SLD->getVectorLength(), SLD->getValueType(0), DL);
2186
2187 // Generate the low vp_strided_load
2188 Lo = DAG.getStridedLoadVP(
2189 SLD->getAddressingMode(), SLD->getExtensionType(), LoVT, DL,
2190 SLD->getChain(), SLD->getBasePtr(), SLD->getOffset(), SLD->getStride(),
2191 LoMask, LoEVL, LoMemVT, SLD->getMemOperand(), SLD->isExpandingLoad());
2192
2193 if (HiIsEmpty) {
2194 // The high vp_strided_load has zero storage size. We therefore simply set
2195 // it to the low vp_strided_load and rely on subsequent removal from the
2196 // chain.
2197 Hi = Lo;
2198 } else {
2199 // Generate the high vp_strided_load.
2200 // To calculate the high base address, we need to sum to the low base
2201 // address stride number of bytes for each element already loaded by low,
2202 // that is: Ptr = Ptr + (LoEVL * Stride)
2203 EVT PtrVT = SLD->getBasePtr().getValueType();
2205 DAG.getNode(ISD::MUL, DL, PtrVT, LoEVL,
2206 DAG.getSExtOrTrunc(SLD->getStride(), DL, PtrVT));
2207 SDValue Ptr =
2208 DAG.getNode(ISD::ADD, DL, PtrVT, SLD->getBasePtr(), Increment);
2209
2210 Align Alignment = SLD->getOriginalAlign();
2211 if (LoMemVT.isScalableVector())
2212 Alignment = commonAlignment(
2213 Alignment, LoMemVT.getSizeInBits().getKnownMinValue() / 8);
2214
2218 Alignment, SLD->getAAInfo(), SLD->getRanges());
2219
2221 HiVT, DL, SLD->getChain(), Ptr, SLD->getOffset(),
2222 SLD->getStride(), HiMask, HiEVL, HiMemVT, MMO,
2223 SLD->isExpandingLoad());
2224 }
2225
2226 // Build a factor node to remember that this load is independent of the
2227 // other one.
2228 SDValue Ch = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo.getValue(1),
2229 Hi.getValue(1));
2230
2231 // Legalize the chain result - switch anything that used the old chain to
2232 // use the new one.
2233 ReplaceValueWith(SDValue(SLD, 1), Ch);
2234}
2235
2236void DAGTypeLegalizer::SplitVecRes_MLOAD(MaskedLoadSDNode *MLD,
2237 SDValue &Lo, SDValue &Hi) {
2238 assert(MLD->isUnindexed() && "Indexed masked load during type legalization!");
2239 EVT LoVT, HiVT;
2240 SDLoc dl(MLD);
2241 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(MLD->getValueType(0));
2242
2243 SDValue Ch = MLD->getChain();
2244 SDValue Ptr = MLD->getBasePtr();
2245 SDValue Offset = MLD->getOffset();
2246 assert(Offset.isUndef() && "Unexpected indexed masked load offset");
2247 SDValue Mask = MLD->getMask();
2248 SDValue PassThru = MLD->getPassThru();
2249 Align Alignment = MLD->getOriginalAlign();
2250 ISD::LoadExtType ExtType = MLD->getExtensionType();
2251
2252 // Split Mask operand
2253 SDValue MaskLo, MaskHi;
2254 if (Mask.getOpcode() == ISD::SETCC) {
2255 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
2256 } else {
2257 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
2258 GetSplitVector(Mask, MaskLo, MaskHi);
2259 else
2260 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, dl);
2261 }
2262
2263 EVT MemoryVT = MLD->getMemoryVT();
2264 EVT LoMemVT, HiMemVT;
2265 bool HiIsEmpty = false;
2266 std::tie(LoMemVT, HiMemVT) =
2267 DAG.GetDependentSplitDestVTs(MemoryVT, LoVT, &HiIsEmpty);
2268
2269 SDValue PassThruLo, PassThruHi;
2270 if (getTypeAction(PassThru.getValueType()) == TargetLowering::TypeSplitVector)
2271 GetSplitVector(PassThru, PassThruLo, PassThruHi);
2272 else
2273 std::tie(PassThruLo, PassThruHi) = DAG.SplitVector(PassThru, dl);
2274
2277 LocationSize::beforeOrAfterPointer(), Alignment, MLD->getAAInfo(),
2278 MLD->getRanges());
2279
2280 Lo = DAG.getMaskedLoad(LoVT, dl, Ch, Ptr, Offset, MaskLo, PassThruLo, LoMemVT,
2281 MMO, MLD->getAddressingMode(), ExtType,
2282 MLD->isExpandingLoad());
2283
2284 if (HiIsEmpty) {
2285 // The hi masked load has zero storage size. We therefore simply set it to
2286 // the low masked load and rely on subsequent removal from the chain.
2287 Hi = Lo;
2288 } else {
2289 // Generate hi masked load.
2290 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, dl, LoMemVT, DAG,
2291 MLD->isExpandingLoad());
2292
2294 if (LoMemVT.isScalableVector())
2296 else
2297 MPI = MLD->getPointerInfo().getWithOffset(
2298 LoMemVT.getStoreSize().getFixedValue());
2299
2302 Alignment, MLD->getAAInfo(), MLD->getRanges());
2303
2304 Hi = DAG.getMaskedLoad(HiVT, dl, Ch, Ptr, Offset, MaskHi, PassThruHi,
2305 HiMemVT, MMO, MLD->getAddressingMode(), ExtType,
2306 MLD->isExpandingLoad());
2307 }
2308
2309 // Build a factor node to remember that this load is independent of the
2310 // other one.
2311 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2312 Hi.getValue(1));
2313
2314 // Legalize the chain result - switch anything that used the old chain to
2315 // use the new one.
2316 ReplaceValueWith(SDValue(MLD, 1), Ch);
2317
2318}
2319
2320void DAGTypeLegalizer::SplitVecRes_Gather(MemSDNode *N, SDValue &Lo,
2321 SDValue &Hi, bool SplitSETCC) {
2322 EVT LoVT, HiVT;
2323 SDLoc dl(N);
2324 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2325
2326 SDValue Ch = N->getChain();
2327 SDValue Ptr = N->getBasePtr();
2328 struct Operands {
2329 SDValue Mask;
2330 SDValue Index;
2331 SDValue Scale;
2332 } Ops = [&]() -> Operands {
2333 if (auto *MSC = dyn_cast<MaskedGatherSDNode>(N)) {
2334 return {MSC->getMask(), MSC->getIndex(), MSC->getScale()};
2335 }
2336 auto *VPSC = cast<VPGatherSDNode>(N);
2337 return {VPSC->getMask(), VPSC->getIndex(), VPSC->getScale()};
2338 }();
2339
2340 EVT MemoryVT = N->getMemoryVT();
2341 Align Alignment = N->getOriginalAlign();
2342
2343 // Split Mask operand
2344 SDValue MaskLo, MaskHi;
2345 if (SplitSETCC && Ops.Mask.getOpcode() == ISD::SETCC) {
2346 SplitVecRes_SETCC(Ops.Mask.getNode(), MaskLo, MaskHi);
2347 } else {
2348 std::tie(MaskLo, MaskHi) = SplitMask(Ops.Mask, dl);
2349 }
2350
2351 EVT LoMemVT, HiMemVT;
2352 // Split MemoryVT
2353 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
2354
2355 SDValue IndexHi, IndexLo;
2356 if (getTypeAction(Ops.Index.getValueType()) ==
2358 GetSplitVector(Ops.Index, IndexLo, IndexHi);
2359 else
2360 std::tie(IndexLo, IndexHi) = DAG.SplitVector(Ops.Index, dl);
2361
2363 N->getPointerInfo(), MachineMemOperand::MOLoad,
2364 LocationSize::beforeOrAfterPointer(), Alignment, N->getAAInfo(),
2365 N->getRanges());
2366
2367 if (auto *MGT = dyn_cast<MaskedGatherSDNode>(N)) {
2368 SDValue PassThru = MGT->getPassThru();
2369 SDValue PassThruLo, PassThruHi;
2370 if (getTypeAction(PassThru.getValueType()) ==
2372 GetSplitVector(PassThru, PassThruLo, PassThruHi);
2373 else
2374 std::tie(PassThruLo, PassThruHi) = DAG.SplitVector(PassThru, dl);
2375
2376 ISD::LoadExtType ExtType = MGT->getExtensionType();
2377 ISD::MemIndexType IndexTy = MGT->getIndexType();
2378
2379 SDValue OpsLo[] = {Ch, PassThruLo, MaskLo, Ptr, IndexLo, Ops.Scale};
2380 Lo = DAG.getMaskedGather(DAG.getVTList(LoVT, MVT::Other), LoMemVT, dl,
2381 OpsLo, MMO, IndexTy, ExtType);
2382
2383 SDValue OpsHi[] = {Ch, PassThruHi, MaskHi, Ptr, IndexHi, Ops.Scale};
2384 Hi = DAG.getMaskedGather(DAG.getVTList(HiVT, MVT::Other), HiMemVT, dl,
2385 OpsHi, MMO, IndexTy, ExtType);
2386 } else {
2387 auto *VPGT = cast<VPGatherSDNode>(N);
2388 SDValue EVLLo, EVLHi;
2389 std::tie(EVLLo, EVLHi) =
2390 DAG.SplitEVL(VPGT->getVectorLength(), MemoryVT, dl);
2391
2392 SDValue OpsLo[] = {Ch, Ptr, IndexLo, Ops.Scale, MaskLo, EVLLo};
2393 Lo = DAG.getGatherVP(DAG.getVTList(LoVT, MVT::Other), LoMemVT, dl, OpsLo,
2394 MMO, VPGT->getIndexType());
2395
2396 SDValue OpsHi[] = {Ch, Ptr, IndexHi, Ops.Scale, MaskHi, EVLHi};
2397 Hi = DAG.getGatherVP(DAG.getVTList(HiVT, MVT::Other), HiMemVT, dl, OpsHi,
2398 MMO, VPGT->getIndexType());
2399 }
2400
2401 // Build a factor node to remember that this load is independent of the
2402 // other one.
2403 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2404 Hi.getValue(1));
2405
2406 // Legalize the chain result - switch anything that used the old chain to
2407 // use the new one.
2408 ReplaceValueWith(SDValue(N, 1), Ch);
2409}
2410
2411void DAGTypeLegalizer::SplitVecRes_VECTOR_COMPRESS(SDNode *N, SDValue &Lo,
2412 SDValue &Hi) {
2413 // This is not "trivial", as there is a dependency between the two subvectors.
2414 // Depending on the number of 1s in the mask, the elements from the Hi vector
2415 // need to be moved to the Lo vector. So we just perform this as one "big"
2416 // operation and then extract the Lo and Hi vectors from that. This gets rid
2417 // of VECTOR_COMPRESS and all other operands can be legalized later.
2418 SDValue Compressed = TLI.expandVECTOR_COMPRESS(N, DAG);
2419 std::tie(Lo, Hi) = DAG.SplitVector(Compressed, SDLoc(N));
2420}
2421
2422void DAGTypeLegalizer::SplitVecRes_SETCC(SDNode *N, SDValue &Lo, SDValue &Hi) {
2423 assert(N->getValueType(0).isVector() &&
2424 N->getOperand(0).getValueType().isVector() &&
2425 "Operand types must be vectors");
2426
2427 EVT LoVT, HiVT;
2428 SDLoc DL(N);
2429 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2430
2431 // If the input also splits, handle it directly. Otherwise split it by hand.
2432 SDValue LL, LH, RL, RH;
2433 if (getTypeAction(N->getOperand(0).getValueType()) ==
2435 GetSplitVector(N->getOperand(0), LL, LH);
2436 else
2437 std::tie(LL, LH) = DAG.SplitVectorOperand(N, 0);
2438
2439 if (getTypeAction(N->getOperand(1).getValueType()) ==
2441 GetSplitVector(N->getOperand(1), RL, RH);
2442 else
2443 std::tie(RL, RH) = DAG.SplitVectorOperand(N, 1);
2444
2445 if (N->getOpcode() == ISD::SETCC) {
2446 Lo = DAG.getNode(N->getOpcode(), DL, LoVT, LL, RL, N->getOperand(2));
2447 Hi = DAG.getNode(N->getOpcode(), DL, HiVT, LH, RH, N->getOperand(2));
2448 } else {
2449 assert(N->getOpcode() == ISD::VP_SETCC && "Expected VP_SETCC opcode");
2450 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
2451 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(3));
2452 std::tie(EVLLo, EVLHi) =
2453 DAG.SplitEVL(N->getOperand(4), N->getValueType(0), DL);
2454 Lo = DAG.getNode(N->getOpcode(), DL, LoVT, LL, RL, N->getOperand(2), MaskLo,
2455 EVLLo);
2456 Hi = DAG.getNode(N->getOpcode(), DL, HiVT, LH, RH, N->getOperand(2), MaskHi,
2457 EVLHi);
2458 }
2459}
2460
2461void DAGTypeLegalizer::SplitVecRes_UnaryOp(SDNode *N, SDValue &Lo,
2462 SDValue &Hi) {
2463 // Get the dest types - they may not match the input types, e.g. int_to_fp.
2464 EVT LoVT, HiVT;
2465 SDLoc dl(N);
2466 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2467
2468 // If the input also splits, handle it directly for a compile time speedup.
2469 // Otherwise split it by hand.
2470 EVT InVT = N->getOperand(0).getValueType();
2471 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
2472 GetSplitVector(N->getOperand(0), Lo, Hi);
2473 else
2474 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
2475
2476 const SDNodeFlags Flags = N->getFlags();
2477 unsigned Opcode = N->getOpcode();
2478 if (N->getNumOperands() <= 2) {
2479 if (Opcode == ISD::FP_ROUND) {
2480 Lo = DAG.getNode(Opcode, dl, LoVT, Lo, N->getOperand(1), Flags);
2481 Hi = DAG.getNode(Opcode, dl, HiVT, Hi, N->getOperand(1), Flags);
2482 } else {
2483 Lo = DAG.getNode(Opcode, dl, LoVT, Lo, Flags);
2484 Hi = DAG.getNode(Opcode, dl, HiVT, Hi, Flags);
2485 }
2486 return;
2487 }
2488
2489 assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
2490 assert(N->isVPOpcode() && "Expected VP opcode");
2491
2492 SDValue MaskLo, MaskHi;
2493 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
2494
2495 SDValue EVLLo, EVLHi;
2496 std::tie(EVLLo, EVLHi) =
2497 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), dl);
2498
2499 Lo = DAG.getNode(Opcode, dl, LoVT, {Lo, MaskLo, EVLLo}, Flags);
2500 Hi = DAG.getNode(Opcode, dl, HiVT, {Hi, MaskHi, EVLHi}, Flags);
2501}
2502
2503void DAGTypeLegalizer::SplitVecRes_ADDRSPACECAST(SDNode *N, SDValue &Lo,
2504 SDValue &Hi) {
2505 SDLoc dl(N);
2506 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(N->getValueType(0));
2507
2508 // If the input also splits, handle it directly for a compile time speedup.
2509 // Otherwise split it by hand.
2510 EVT InVT = N->getOperand(0).getValueType();
2511 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
2512 GetSplitVector(N->getOperand(0), Lo, Hi);
2513 else
2514 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
2515
2516 auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
2517 unsigned SrcAS = AddrSpaceCastN->getSrcAddressSpace();
2518 unsigned DestAS = AddrSpaceCastN->getDestAddressSpace();
2519 Lo = DAG.getAddrSpaceCast(dl, LoVT, Lo, SrcAS, DestAS);
2520 Hi = DAG.getAddrSpaceCast(dl, HiVT, Hi, SrcAS, DestAS);
2521}
2522
2523void DAGTypeLegalizer::SplitVecRes_FFREXP(SDNode *N, unsigned ResNo,
2524 SDValue &Lo, SDValue &Hi) {
2525 SDLoc dl(N);
2526 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(N->getValueType(0));
2527 auto [LoVT1, HiVT1] = DAG.GetSplitDestVTs(N->getValueType(1));
2528
2529 // If the input also splits, handle it directly for a compile time speedup.
2530 // Otherwise split it by hand.
2531 EVT InVT = N->getOperand(0).getValueType();
2532 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
2533 GetSplitVector(N->getOperand(0), Lo, Hi);
2534 else
2535 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
2536
2537 Lo = DAG.getNode(N->getOpcode(), dl, {LoVT, LoVT1}, Lo);
2538 Hi = DAG.getNode(N->getOpcode(), dl, {HiVT, HiVT1}, Hi);
2539 Lo->setFlags(N->getFlags());
2540 Hi->setFlags(N->getFlags());
2541
2542 SDNode *HiNode = Hi.getNode();
2543 SDNode *LoNode = Lo.getNode();
2544
2545 // Replace the other vector result not being explicitly split here.
2546 unsigned OtherNo = 1 - ResNo;
2547 EVT OtherVT = N->getValueType(OtherNo);
2548 if (getTypeAction(OtherVT) == TargetLowering::TypeSplitVector) {
2549 SetSplitVector(SDValue(N, OtherNo), SDValue(LoNode, OtherNo),
2550 SDValue(HiNode, OtherNo));
2551 } else {
2552 SDValue OtherVal =
2553 DAG.getNode(ISD::CONCAT_VECTORS, dl, OtherVT, SDValue(LoNode, OtherNo),
2554 SDValue(HiNode, OtherNo));
2555 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
2556 }
2557}
2558
2559void DAGTypeLegalizer::SplitVecRes_ExtendOp(SDNode *N, SDValue &Lo,
2560 SDValue &Hi) {
2561 SDLoc dl(N);
2562 EVT SrcVT = N->getOperand(0).getValueType();
2563 EVT DestVT = N->getValueType(0);
2564 EVT LoVT, HiVT;
2565 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(DestVT);
2566
2567 // We can do better than a generic split operation if the extend is doing
2568 // more than just doubling the width of the elements and the following are
2569 // true:
2570 // - The number of vector elements is even,
2571 // - the source type is legal,
2572 // - the type of a split source is illegal,
2573 // - the type of an extended (by doubling element size) source is legal, and
2574 // - the type of that extended source when split is legal.
2575 //
2576 // This won't necessarily completely legalize the operation, but it will
2577 // more effectively move in the right direction and prevent falling down
2578 // to scalarization in many cases due to the input vector being split too
2579 // far.
2580 if (SrcVT.getVectorElementCount().isKnownEven() &&
2581 SrcVT.getScalarSizeInBits() * 2 < DestVT.getScalarSizeInBits()) {
2582 LLVMContext &Ctx = *DAG.getContext();
2583 EVT NewSrcVT = SrcVT.widenIntegerVectorElementType(Ctx);
2584 EVT SplitSrcVT = SrcVT.getHalfNumVectorElementsVT(Ctx);
2585
2586 EVT SplitLoVT, SplitHiVT;
2587 std::tie(SplitLoVT, SplitHiVT) = DAG.GetSplitDestVTs(NewSrcVT);
2588 if (TLI.isTypeLegal(SrcVT) && !TLI.isTypeLegal(SplitSrcVT) &&
2589 TLI.isTypeLegal(NewSrcVT) && TLI.isTypeLegal(SplitLoVT)) {
2590 LLVM_DEBUG(dbgs() << "Split vector extend via incremental extend:";
2591 N->dump(&DAG); dbgs() << "\n");
2592 if (!N->isVPOpcode()) {
2593 // Extend the source vector by one step.
2594 SDValue NewSrc =
2595 DAG.getNode(N->getOpcode(), dl, NewSrcVT, N->getOperand(0));
2596 // Get the low and high halves of the new, extended one step, vector.
2597 std::tie(Lo, Hi) = DAG.SplitVector(NewSrc, dl);
2598 // Extend those vector halves the rest of the way.
2599 Lo = DAG.getNode(N->getOpcode(), dl, LoVT, Lo);
2600 Hi = DAG.getNode(N->getOpcode(), dl, HiVT, Hi);
2601 return;
2602 }
2603
2604 // Extend the source vector by one step.
2605 SDValue NewSrc =
2606 DAG.getNode(N->getOpcode(), dl, NewSrcVT, N->getOperand(0),
2607 N->getOperand(1), N->getOperand(2));
2608 // Get the low and high halves of the new, extended one step, vector.
2609 std::tie(Lo, Hi) = DAG.SplitVector(NewSrc, dl);
2610
2611 SDValue MaskLo, MaskHi;
2612 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
2613
2614 SDValue EVLLo, EVLHi;
2615 std::tie(EVLLo, EVLHi) =
2616 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), dl);
2617 // Extend those vector halves the rest of the way.
2618 Lo = DAG.getNode(N->getOpcode(), dl, LoVT, {Lo, MaskLo, EVLLo});
2619 Hi = DAG.getNode(N->getOpcode(), dl, HiVT, {Hi, MaskHi, EVLHi});
2620 return;
2621 }
2622 }
2623 // Fall back to the generic unary operator splitting otherwise.
2624 SplitVecRes_UnaryOp(N, Lo, Hi);
2625}
2626
2627void DAGTypeLegalizer::SplitVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N,
2628 SDValue &Lo, SDValue &Hi) {
2629 // The low and high parts of the original input give four input vectors.
2630 SDValue Inputs[4];
2631 SDLoc DL(N);
2632 GetSplitVector(N->getOperand(0), Inputs[0], Inputs[1]);
2633 GetSplitVector(N->getOperand(1), Inputs[2], Inputs[3]);
2634 EVT NewVT = Inputs[0].getValueType();
2635 unsigned NewElts = NewVT.getVectorNumElements();
2636
2637 auto &&IsConstant = [](const SDValue &N) {
2638 APInt SplatValue;
2639 return N.getResNo() == 0 &&
2640 (ISD::isConstantSplatVector(N.getNode(), SplatValue) ||
2642 };
2643 auto &&BuildVector = [NewElts, &DAG = DAG, NewVT, &DL](SDValue &Input1,
2644 SDValue &Input2,
2646 assert(Input1->getOpcode() == ISD::BUILD_VECTOR &&
2647 Input2->getOpcode() == ISD::BUILD_VECTOR &&
2648 "Expected build vector node.");
2649 EVT EltVT = NewVT.getVectorElementType();
2650 SmallVector<SDValue> Ops(NewElts, DAG.getUNDEF(EltVT));
2651 for (unsigned I = 0; I < NewElts; ++I) {
2652 if (Mask[I] == PoisonMaskElem)
2653 continue;
2654 unsigned Idx = Mask[I];
2655 if (Idx >= NewElts)
2656 Ops[I] = Input2.getOperand(Idx - NewElts);
2657 else
2658 Ops[I] = Input1.getOperand(Idx);
2659 // Make the type of all elements the same as the element type.
2660 if (Ops[I].getValueType().bitsGT(EltVT))
2661 Ops[I] = DAG.getNode(ISD::TRUNCATE, DL, EltVT, Ops[I]);
2662 }
2663 return DAG.getBuildVector(NewVT, DL, Ops);
2664 };
2665
2666 // If Lo or Hi uses elements from at most two of the four input vectors, then
2667 // express it as a vector shuffle of those two inputs. Otherwise extract the
2668 // input elements by hand and construct the Lo/Hi output using a BUILD_VECTOR.
2669 SmallVector<int> OrigMask(N->getMask());
2670 // Try to pack incoming shuffles/inputs.
2671 auto &&TryPeekThroughShufflesInputs = [&Inputs, &NewVT, this, NewElts,
2673 // Check if all inputs are shuffles of the same operands or non-shuffles.
2675 for (unsigned Idx = 0; Idx < std::size(Inputs); ++Idx) {
2676 SDValue Input = Inputs[Idx];
2677 auto *Shuffle = dyn_cast<ShuffleVectorSDNode>(Input.getNode());
2678 if (!Shuffle ||
2679 Input.getOperand(0).getValueType() != Input.getValueType())
2680 continue;
2681 ShufflesIdxs[std::make_pair(Input.getOperand(0), Input.getOperand(1))]
2682 .push_back(Idx);
2683 ShufflesIdxs[std::make_pair(Input.getOperand(1), Input.getOperand(0))]
2684 .push_back(Idx);
2685 }
2686 for (auto &P : ShufflesIdxs) {
2687 if (P.second.size() < 2)
2688 continue;
2689 // Use shuffles operands instead of shuffles themselves.
2690 // 1. Adjust mask.
2691 for (int &Idx : Mask) {
2692 if (Idx == PoisonMaskElem)
2693 continue;
2694 unsigned SrcRegIdx = Idx / NewElts;
2695 if (Inputs[SrcRegIdx].isUndef()) {
2697 continue;
2698 }
2699 auto *Shuffle =
2700 dyn_cast<ShuffleVectorSDNode>(Inputs[SrcRegIdx].getNode());
2701 if (!Shuffle || !is_contained(P.second, SrcRegIdx))
2702 continue;
2703 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
2704 if (MaskElt == PoisonMaskElem) {
2706 continue;
2707 }
2708 Idx = MaskElt % NewElts +
2709 P.second[Shuffle->getOperand(MaskElt / NewElts) == P.first.first
2710 ? 0
2711 : 1] *
2712 NewElts;
2713 }
2714 // 2. Update inputs.
2715 Inputs[P.second[0]] = P.first.first;
2716 Inputs[P.second[1]] = P.first.second;
2717 // Clear the pair data.
2718 P.second.clear();
2719 ShufflesIdxs[std::make_pair(P.first.second, P.first.first)].clear();
2720 }
2721 // Check if any concat_vectors can be simplified.
2722 SmallBitVector UsedSubVector(2 * std::size(Inputs));
2723 for (int &Idx : Mask) {
2724 if (Idx == PoisonMaskElem)
2725 continue;
2726 unsigned SrcRegIdx = Idx / NewElts;
2727 if (Inputs[SrcRegIdx].isUndef()) {
2729 continue;
2730 }
2732 getTypeAction(Inputs[SrcRegIdx].getValueType());
2733 if (Inputs[SrcRegIdx].getOpcode() == ISD::CONCAT_VECTORS &&
2734 Inputs[SrcRegIdx].getNumOperands() == 2 &&
2735 !Inputs[SrcRegIdx].getOperand(1).isUndef() &&
2736 (TypeAction == TargetLowering::TypeLegal ||
2737 TypeAction == TargetLowering::TypeWidenVector))
2738 UsedSubVector.set(2 * SrcRegIdx + (Idx % NewElts) / (NewElts / 2));
2739 }
2740 if (UsedSubVector.count() > 1) {
2742 for (unsigned I = 0; I < std::size(Inputs); ++I) {
2743 if (UsedSubVector.test(2 * I) == UsedSubVector.test(2 * I + 1))
2744 continue;
2745 if (Pairs.empty() || Pairs.back().size() == 2)
2746 Pairs.emplace_back();
2747 if (UsedSubVector.test(2 * I)) {
2748 Pairs.back().emplace_back(I, 0);
2749 } else {
2750 assert(UsedSubVector.test(2 * I + 1) &&
2751 "Expected to be used one of the subvectors.");
2752 Pairs.back().emplace_back(I, 1);
2753 }
2754 }
2755 if (!Pairs.empty() && Pairs.front().size() > 1) {
2756 // Adjust mask.
2757 for (int &Idx : Mask) {
2758 if (Idx == PoisonMaskElem)
2759 continue;
2760 unsigned SrcRegIdx = Idx / NewElts;
2761 auto *It = find_if(
2762 Pairs, [SrcRegIdx](ArrayRef<std::pair<unsigned, int>> Idxs) {
2763 return Idxs.front().first == SrcRegIdx ||
2764 Idxs.back().first == SrcRegIdx;
2765 });
2766 if (It == Pairs.end())
2767 continue;
2768 Idx = It->front().first * NewElts + (Idx % NewElts) % (NewElts / 2) +
2769 (SrcRegIdx == It->front().first ? 0 : (NewElts / 2));
2770 }
2771 // Adjust inputs.
2772 for (ArrayRef<std::pair<unsigned, int>> Idxs : Pairs) {
2773 Inputs[Idxs.front().first] = DAG.getNode(
2775 Inputs[Idxs.front().first].getValueType(),
2776 Inputs[Idxs.front().first].getOperand(Idxs.front().second),
2777 Inputs[Idxs.back().first].getOperand(Idxs.back().second));
2778 }
2779 }
2780 }
2781 bool Changed;
2782 do {
2783 // Try to remove extra shuffles (except broadcasts) and shuffles with the
2784 // reused operands.
2785 Changed = false;
2786 for (unsigned I = 0; I < std::size(Inputs); ++I) {
2787 auto *Shuffle = dyn_cast<ShuffleVectorSDNode>(Inputs[I].getNode());
2788 if (!Shuffle)
2789 continue;
2790 if (Shuffle->getOperand(0).getValueType() != NewVT)
2791 continue;
2792 int Op = -1;
2793 if (!Inputs[I].hasOneUse() && Shuffle->getOperand(1).isUndef() &&
2794 !Shuffle->isSplat()) {
2795 Op = 0;
2796 } else if (!Inputs[I].hasOneUse() &&
2797 !Shuffle->getOperand(1).isUndef()) {
2798 // Find the only used operand, if possible.
2799 for (int &Idx : Mask) {
2800 if (Idx == PoisonMaskElem)
2801 continue;
2802 unsigned SrcRegIdx = Idx / NewElts;
2803 if (SrcRegIdx != I)
2804 continue;
2805 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
2806 if (MaskElt == PoisonMaskElem) {
2808 continue;
2809 }
2810 int OpIdx = MaskElt / NewElts;
2811 if (Op == -1) {
2812 Op = OpIdx;
2813 continue;
2814 }
2815 if (Op != OpIdx) {
2816 Op = -1;
2817 break;
2818 }
2819 }
2820 }
2821 if (Op < 0) {
2822 // Try to check if one of the shuffle operands is used already.
2823 for (int OpIdx = 0; OpIdx < 2; ++OpIdx) {
2824 if (Shuffle->getOperand(OpIdx).isUndef())
2825 continue;
2826 auto *It = find(Inputs, Shuffle->getOperand(OpIdx));
2827 if (It == std::end(Inputs))
2828 continue;
2829 int FoundOp = std::distance(std::begin(Inputs), It);
2830 // Found that operand is used already.
2831 // 1. Fix the mask for the reused operand.
2832 for (int &Idx : Mask) {
2833 if (Idx == PoisonMaskElem)
2834 continue;
2835 unsigned SrcRegIdx = Idx / NewElts;
2836 if (SrcRegIdx != I)
2837 continue;
2838 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
2839 if (MaskElt == PoisonMaskElem) {
2841 continue;
2842 }
2843 int MaskIdx = MaskElt / NewElts;
2844 if (OpIdx == MaskIdx)
2845 Idx = MaskElt % NewElts + FoundOp * NewElts;
2846 }
2847 // 2. Set Op to the unused OpIdx.
2848 Op = (OpIdx + 1) % 2;
2849 break;
2850 }
2851 }
2852 if (Op >= 0) {
2853 Changed = true;
2854 Inputs[I] = Shuffle->getOperand(Op);
2855 // Adjust mask.
2856 for (int &Idx : Mask) {
2857 if (Idx == PoisonMaskElem)
2858 continue;
2859 unsigned SrcRegIdx = Idx / NewElts;
2860 if (SrcRegIdx != I)
2861 continue;
2862 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
2863 int OpIdx = MaskElt / NewElts;
2864 if (OpIdx != Op)
2865 continue;
2866 Idx = MaskElt % NewElts + SrcRegIdx * NewElts;
2867 }
2868 }
2869 }
2870 } while (Changed);
2871 };
2872 TryPeekThroughShufflesInputs(OrigMask);
2873 // Proces unique inputs.
2874 auto &&MakeUniqueInputs = [&Inputs, &IsConstant,
2875 NewElts](SmallVectorImpl<int> &Mask) {
2876 SetVector<SDValue> UniqueInputs;
2877 SetVector<SDValue> UniqueConstantInputs;
2878 for (const auto &I : Inputs) {
2879 if (IsConstant(I))
2880 UniqueConstantInputs.insert(I);
2881 else if (!I.isUndef())
2882 UniqueInputs.insert(I);
2883 }
2884 // Adjust mask in case of reused inputs. Also, need to insert constant
2885 // inputs at first, otherwise it affects the final outcome.
2886 if (UniqueInputs.size() != std::size(Inputs)) {
2887 auto &&UniqueVec = UniqueInputs.takeVector();
2888 auto &&UniqueConstantVec = UniqueConstantInputs.takeVector();
2889 unsigned ConstNum = UniqueConstantVec.size();
2890 for (int &Idx : Mask) {
2891 if (Idx == PoisonMaskElem)
2892 continue;
2893 unsigned SrcRegIdx = Idx / NewElts;
2894 if (Inputs[SrcRegIdx].isUndef()) {
2896 continue;
2897 }
2898 const auto It = find(UniqueConstantVec, Inputs[SrcRegIdx]);
2899 if (It != UniqueConstantVec.end()) {
2900 Idx = (Idx % NewElts) +
2901 NewElts * std::distance(UniqueConstantVec.begin(), It);
2902 assert(Idx >= 0 && "Expected defined mask idx.");
2903 continue;
2904 }
2905 const auto RegIt = find(UniqueVec, Inputs[SrcRegIdx]);
2906 assert(RegIt != UniqueVec.end() && "Cannot find non-const value.");
2907 Idx = (Idx % NewElts) +
2908 NewElts * (std::distance(UniqueVec.begin(), RegIt) + ConstNum);
2909 assert(Idx >= 0 && "Expected defined mask idx.");
2910 }
2911 copy(UniqueConstantVec, std::begin(Inputs));
2912 copy(UniqueVec, std::next(std::begin(Inputs), ConstNum));
2913 }
2914 };
2915 MakeUniqueInputs(OrigMask);
2916 SDValue OrigInputs[4];
2917 copy(Inputs, std::begin(OrigInputs));
2918 for (unsigned High = 0; High < 2; ++High) {
2919 SDValue &Output = High ? Hi : Lo;
2920
2921 // Build a shuffle mask for the output, discovering on the fly which
2922 // input vectors to use as shuffle operands.
2923 unsigned FirstMaskIdx = High * NewElts;
2924 SmallVector<int> Mask(NewElts * std::size(Inputs), PoisonMaskElem);
2925 copy(ArrayRef(OrigMask).slice(FirstMaskIdx, NewElts), Mask.begin());
2926 assert(!Output && "Expected default initialized initial value.");
2927 TryPeekThroughShufflesInputs(Mask);
2928 MakeUniqueInputs(Mask);
2929 SDValue TmpInputs[4];
2930 copy(Inputs, std::begin(TmpInputs));
2931 // Track changes in the output registers.
2932 int UsedIdx = -1;
2933 bool SecondIteration = false;
2934 auto &&AccumulateResults = [&UsedIdx, &SecondIteration](unsigned Idx) {
2935 if (UsedIdx < 0) {
2936 UsedIdx = Idx;
2937 return false;
2938 }
2939 if (UsedIdx >= 0 && static_cast<unsigned>(UsedIdx) == Idx)
2940 SecondIteration = true;
2941 return SecondIteration;
2942 };
2944 Mask, std::size(Inputs), std::size(Inputs),
2945 /*NumOfUsedRegs=*/1,
2946 [&Output, &DAG = DAG, NewVT]() { Output = DAG.getUNDEF(NewVT); },
2947 [&Output, &DAG = DAG, NewVT, &DL, &Inputs,
2948 &BuildVector](ArrayRef<int> Mask, unsigned Idx, unsigned /*Unused*/) {
2949 if (Inputs[Idx]->getOpcode() == ISD::BUILD_VECTOR)
2950 Output = BuildVector(Inputs[Idx], Inputs[Idx], Mask);
2951 else
2952 Output = DAG.getVectorShuffle(NewVT, DL, Inputs[Idx],
2953 DAG.getUNDEF(NewVT), Mask);
2954 Inputs[Idx] = Output;
2955 },
2956 [&AccumulateResults, &Output, &DAG = DAG, NewVT, &DL, &Inputs,
2957 &TmpInputs,
2958 &BuildVector](ArrayRef<int> Mask, unsigned Idx1, unsigned Idx2) {
2959 if (AccumulateResults(Idx1)) {
2960 if (Inputs[Idx1]->getOpcode() == ISD::BUILD_VECTOR &&
2961 Inputs[Idx2]->getOpcode() == ISD::BUILD_VECTOR)
2962 Output = BuildVector(Inputs[Idx1], Inputs[Idx2], Mask);
2963 else
2964 Output = DAG.getVectorShuffle(NewVT, DL, Inputs[Idx1],
2965 Inputs[Idx2], Mask);
2966 } else {
2967 if (TmpInputs[Idx1]->getOpcode() == ISD::BUILD_VECTOR &&
2968 TmpInputs[Idx2]->getOpcode() == ISD::BUILD_VECTOR)
2969 Output = BuildVector(TmpInputs[Idx1], TmpInputs[Idx2], Mask);
2970 else
2971 Output = DAG.getVectorShuffle(NewVT, DL, TmpInputs[Idx1],
2972 TmpInputs[Idx2], Mask);
2973 }
2974 Inputs[Idx1] = Output;
2975 });
2976 copy(OrigInputs, std::begin(Inputs));
2977 }
2978}
2979
2980void DAGTypeLegalizer::SplitVecRes_VAARG(SDNode *N, SDValue &Lo, SDValue &Hi) {
2981 EVT OVT = N->getValueType(0);
2982 EVT NVT = OVT.getHalfNumVectorElementsVT(*DAG.getContext());
2983 SDValue Chain = N->getOperand(0);
2984 SDValue Ptr = N->getOperand(1);
2985 SDValue SV = N->getOperand(2);
2986 SDLoc dl(N);
2987
2988 const Align Alignment =
2989 DAG.getDataLayout().getABITypeAlign(NVT.getTypeForEVT(*DAG.getContext()));
2990
2991 Lo = DAG.getVAArg(NVT, dl, Chain, Ptr, SV, Alignment.value());
2992 Hi = DAG.getVAArg(NVT, dl, Lo.getValue(1), Ptr, SV, Alignment.value());
2993 Chain = Hi.getValue(1);
2994
2995 // Modified the chain - switch anything that used the old chain to use
2996 // the new one.
2997 ReplaceValueWith(SDValue(N, 1), Chain);
2998}
2999
3000void DAGTypeLegalizer::SplitVecRes_FP_TO_XINT_SAT(SDNode *N, SDValue &Lo,
3001 SDValue &Hi) {
3002 EVT DstVTLo, DstVTHi;
3003 std::tie(DstVTLo, DstVTHi) = DAG.GetSplitDestVTs(N->getValueType(0));
3004 SDLoc dl(N);
3005
3006 SDValue SrcLo, SrcHi;
3007 EVT SrcVT = N->getOperand(0).getValueType();
3008 if (getTypeAction(SrcVT) == TargetLowering::TypeSplitVector)
3009 GetSplitVector(N->getOperand(0), SrcLo, SrcHi);
3010 else
3011 std::tie(SrcLo, SrcHi) = DAG.SplitVectorOperand(N, 0);
3012
3013 Lo = DAG.getNode(N->getOpcode(), dl, DstVTLo, SrcLo, N->getOperand(1));
3014 Hi = DAG.getNode(N->getOpcode(), dl, DstVTHi, SrcHi, N->getOperand(1));
3015}
3016
3017void DAGTypeLegalizer::SplitVecRes_VECTOR_REVERSE(SDNode *N, SDValue &Lo,
3018 SDValue &Hi) {
3019 SDValue InLo, InHi;
3020 GetSplitVector(N->getOperand(0), InLo, InHi);
3021 SDLoc DL(N);
3022
3023 Lo = DAG.getNode(ISD::VECTOR_REVERSE, DL, InHi.getValueType(), InHi);
3024 Hi = DAG.getNode(ISD::VECTOR_REVERSE, DL, InLo.getValueType(), InLo);
3025}
3026
3027void DAGTypeLegalizer::SplitVecRes_VECTOR_SPLICE(SDNode *N, SDValue &Lo,
3028 SDValue &Hi) {
3029 SDLoc DL(N);
3030
3031 SDValue Expanded = TLI.expandVectorSplice(N, DAG);
3032 std::tie(Lo, Hi) = DAG.SplitVector(Expanded, DL);
3033}
3034
3035void DAGTypeLegalizer::SplitVecRes_VP_REVERSE(SDNode *N, SDValue &Lo,
3036 SDValue &Hi) {
3037 EVT VT = N->getValueType(0);
3038 SDValue Val = N->getOperand(0);
3039 SDValue Mask = N->getOperand(1);
3040 SDValue EVL = N->getOperand(2);
3041 SDLoc DL(N);
3042
3043 // Fallback to VP_STRIDED_STORE to stack followed by VP_LOAD.
3044 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
3045
3046 EVT MemVT = EVT::getVectorVT(*DAG.getContext(), VT.getVectorElementType(),
3048 SDValue StackPtr = DAG.CreateStackTemporary(MemVT.getStoreSize(), Alignment);
3049 EVT PtrVT = StackPtr.getValueType();
3050 auto &MF = DAG.getMachineFunction();
3051 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
3052 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
3053
3054 MachineMemOperand *StoreMMO = DAG.getMachineFunction().getMachineMemOperand(
3056 Alignment);
3057 MachineMemOperand *LoadMMO = DAG.getMachineFunction().getMachineMemOperand(
3059 Alignment);
3060
3061 unsigned EltWidth = VT.getScalarSizeInBits() / 8;
3062 SDValue NumElemMinus1 =
3063 DAG.getNode(ISD::SUB, DL, PtrVT, DAG.getZExtOrTrunc(EVL, DL, PtrVT),
3064 DAG.getConstant(1, DL, PtrVT));
3065 SDValue StartOffset = DAG.getNode(ISD::MUL, DL, PtrVT, NumElemMinus1,
3066 DAG.getConstant(EltWidth, DL, PtrVT));
3067 SDValue StorePtr = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, StartOffset);
3068 SDValue Stride = DAG.getConstant(-(int64_t)EltWidth, DL, PtrVT);
3069
3070 SDValue TrueMask = DAG.getBoolConstant(true, DL, Mask.getValueType(), VT);
3071 SDValue Store = DAG.getStridedStoreVP(DAG.getEntryNode(), DL, Val, StorePtr,
3072 DAG.getUNDEF(PtrVT), Stride, TrueMask,
3073 EVL, MemVT, StoreMMO, ISD::UNINDEXED);
3074
3075 SDValue Load = DAG.getLoadVP(VT, DL, Store, StackPtr, Mask, EVL, LoadMMO);
3076
3077 std::tie(Lo, Hi) = DAG.SplitVector(Load, DL);
3078}
3079
3080void DAGTypeLegalizer::SplitVecRes_VECTOR_DEINTERLEAVE(SDNode *N) {
3081
3082 SDValue Op0Lo, Op0Hi, Op1Lo, Op1Hi;
3083 GetSplitVector(N->getOperand(0), Op0Lo, Op0Hi);
3084 GetSplitVector(N->getOperand(1), Op1Lo, Op1Hi);
3085 EVT VT = Op0Lo.getValueType();
3086 SDLoc DL(N);
3088 DAG.getVTList(VT, VT), Op0Lo, Op0Hi);
3090 DAG.getVTList(VT, VT), Op1Lo, Op1Hi);
3091
3092 SetSplitVector(SDValue(N, 0), ResLo.getValue(0), ResHi.getValue(0));
3093 SetSplitVector(SDValue(N, 1), ResLo.getValue(1), ResHi.getValue(1));
3094}
3095
3096void DAGTypeLegalizer::SplitVecRes_VECTOR_INTERLEAVE(SDNode *N) {
3097 SDValue Op0Lo, Op0Hi, Op1Lo, Op1Hi;
3098 GetSplitVector(N->getOperand(0), Op0Lo, Op0Hi);
3099 GetSplitVector(N->getOperand(1), Op1Lo, Op1Hi);
3100 EVT VT = Op0Lo.getValueType();
3101 SDLoc DL(N);
3103 DAG.getVTList(VT, VT), Op0Lo, Op1Lo),
3104 DAG.getNode(ISD::VECTOR_INTERLEAVE, DL,
3105 DAG.getVTList(VT, VT), Op0Hi, Op1Hi)};
3106
3107 SetSplitVector(SDValue(N, 0), Res[0].getValue(0), Res[0].getValue(1));
3108 SetSplitVector(SDValue(N, 1), Res[1].getValue(0), Res[1].getValue(1));
3109}
3110
3111//===----------------------------------------------------------------------===//
3112// Operand Vector Splitting
3113//===----------------------------------------------------------------------===//
3114
3115/// This method is called when the specified operand of the specified node is
3116/// found to need vector splitting. At this point, all of the result types of
3117/// the node are known to be legal, but other operands of the node may need
3118/// legalization as well as the specified one.
3119bool DAGTypeLegalizer::SplitVectorOperand(SDNode *N, unsigned OpNo) {
3120 LLVM_DEBUG(dbgs() << "Split node operand: "; N->dump(&DAG));
3121 SDValue Res = SDValue();
3122
3123 // See if the target wants to custom split this node.
3124 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
3125 return false;
3126
3127 switch (N->getOpcode()) {
3128 default:
3129#ifndef NDEBUG
3130 dbgs() << "SplitVectorOperand Op #" << OpNo << ": ";
3131 N->dump(&DAG);
3132 dbgs() << "\n";
3133#endif
3134 report_fatal_error("Do not know how to split this operator's "
3135 "operand!\n");
3136
3137 case ISD::VP_SETCC:
3138 case ISD::STRICT_FSETCC:
3139 case ISD::SETCC: Res = SplitVecOp_VSETCC(N); break;
3140 case ISD::BITCAST: Res = SplitVecOp_BITCAST(N); break;
3141 case ISD::EXTRACT_SUBVECTOR: Res = SplitVecOp_EXTRACT_SUBVECTOR(N); break;
3142 case ISD::INSERT_SUBVECTOR: Res = SplitVecOp_INSERT_SUBVECTOR(N, OpNo); break;
3143 case ISD::EXTRACT_VECTOR_ELT:Res = SplitVecOp_EXTRACT_VECTOR_ELT(N); break;
3144 case ISD::CONCAT_VECTORS: Res = SplitVecOp_CONCAT_VECTORS(N); break;
3145 case ISD::VP_TRUNCATE:
3146 case ISD::TRUNCATE:
3147 Res = SplitVecOp_TruncateHelper(N);
3148 break;
3150 case ISD::VP_FP_ROUND:
3151 case ISD::FP_ROUND: Res = SplitVecOp_FP_ROUND(N); break;
3152 case ISD::FCOPYSIGN: Res = SplitVecOp_FPOpDifferentTypes(N); break;
3153 case ISD::STORE:
3154 Res = SplitVecOp_STORE(cast<StoreSDNode>(N), OpNo);
3155 break;
3156 case ISD::VP_STORE:
3157 Res = SplitVecOp_VP_STORE(cast<VPStoreSDNode>(N), OpNo);
3158 break;
3159 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
3160 Res = SplitVecOp_VP_STRIDED_STORE(cast<VPStridedStoreSDNode>(N), OpNo);
3161 break;
3162 case ISD::MSTORE:
3163 Res = SplitVecOp_MSTORE(cast<MaskedStoreSDNode>(N), OpNo);
3164 break;
3165 case ISD::MSCATTER:
3166 case ISD::VP_SCATTER:
3167 Res = SplitVecOp_Scatter(cast<MemSDNode>(N), OpNo);
3168 break;
3169 case ISD::MGATHER:
3170 case ISD::VP_GATHER:
3171 Res = SplitVecOp_Gather(cast<MemSDNode>(N), OpNo);
3172 break;
3173 case ISD::VSELECT:
3174 Res = SplitVecOp_VSELECT(N, OpNo);
3175 break;
3178 case ISD::SINT_TO_FP:
3179 case ISD::UINT_TO_FP:
3180 case ISD::VP_SINT_TO_FP:
3181 case ISD::VP_UINT_TO_FP:
3182 if (N->getValueType(0).bitsLT(
3183 N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType()))
3184 Res = SplitVecOp_TruncateHelper(N);
3185 else
3186 Res = SplitVecOp_UnaryOp(N);
3187 break;
3190 Res = SplitVecOp_FP_TO_XINT_SAT(N);
3191 break;
3192 case ISD::FP_TO_SINT:
3193 case ISD::FP_TO_UINT:
3194 case ISD::VP_FP_TO_SINT:
3195 case ISD::VP_FP_TO_UINT:
3199 case ISD::FP_EXTEND:
3200 case ISD::SIGN_EXTEND:
3201 case ISD::ZERO_EXTEND:
3202 case ISD::ANY_EXTEND:
3203 case ISD::FTRUNC:
3204 case ISD::LRINT:
3205 case ISD::LLRINT:
3206 Res = SplitVecOp_UnaryOp(N);
3207 break;
3208 case ISD::FLDEXP:
3209 Res = SplitVecOp_FPOpDifferentTypes(N);
3210 break;
3211
3212 case ISD::SCMP:
3213 case ISD::UCMP:
3214 Res = SplitVecOp_CMP(N);
3215 break;
3216
3220 Res = SplitVecOp_ExtVecInRegOp(N);
3221 break;
3222
3225 case ISD::VECREDUCE_ADD:
3226 case ISD::VECREDUCE_MUL:
3227 case ISD::VECREDUCE_AND:
3228 case ISD::VECREDUCE_OR:
3229 case ISD::VECREDUCE_XOR:
3238 Res = SplitVecOp_VECREDUCE(N, OpNo);
3239 break;
3242 Res = SplitVecOp_VECREDUCE_SEQ(N);
3243 break;
3244 case ISD::VP_REDUCE_FADD:
3245 case ISD::VP_REDUCE_SEQ_FADD:
3246 case ISD::VP_REDUCE_FMUL:
3247 case ISD::VP_REDUCE_SEQ_FMUL:
3248 case ISD::VP_REDUCE_ADD:
3249 case ISD::VP_REDUCE_MUL:
3250 case ISD::VP_REDUCE_AND:
3251 case ISD::VP_REDUCE_OR:
3252 case ISD::VP_REDUCE_XOR:
3253 case ISD::VP_REDUCE_SMAX:
3254 case ISD::VP_REDUCE_SMIN:
3255 case ISD::VP_REDUCE_UMAX:
3256 case ISD::VP_REDUCE_UMIN:
3257 case ISD::VP_REDUCE_FMAX:
3258 case ISD::VP_REDUCE_FMIN:
3259 case ISD::VP_REDUCE_FMAXIMUM:
3260 case ISD::VP_REDUCE_FMINIMUM:
3261 Res = SplitVecOp_VP_REDUCE(N, OpNo);
3262 break;
3263 case ISD::VP_CTTZ_ELTS:
3264 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
3265 Res = SplitVecOp_VP_CttzElements(N);
3266 break;
3267 }
3268
3269 // If the result is null, the sub-method took care of registering results etc.
3270 if (!Res.getNode()) return false;
3271
3272 // If the result is N, the sub-method updated N in place. Tell the legalizer
3273 // core about this.
3274 if (Res.getNode() == N)
3275 return true;
3276
3277 if (N->isStrictFPOpcode())
3278 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
3279 "Invalid operand expansion");
3280 else
3281 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
3282 "Invalid operand expansion");
3283
3284 ReplaceValueWith(SDValue(N, 0), Res);
3285 return false;
3286}
3287
3288SDValue DAGTypeLegalizer::SplitVecOp_VSELECT(SDNode *N, unsigned OpNo) {
3289 // The only possibility for an illegal operand is the mask, since result type
3290 // legalization would have handled this node already otherwise.
3291 assert(OpNo == 0 && "Illegal operand must be mask");
3292
3293 SDValue Mask = N->getOperand(0);
3294 SDValue Src0 = N->getOperand(1);
3295 SDValue Src1 = N->getOperand(2);
3296 EVT Src0VT = Src0.getValueType();
3297 SDLoc DL(N);
3298 assert(Mask.getValueType().isVector() && "VSELECT without a vector mask?");
3299
3300 SDValue Lo, Hi;
3301 GetSplitVector(N->getOperand(0), Lo, Hi);
3302 assert(Lo.getValueType() == Hi.getValueType() &&
3303 "Lo and Hi have differing types");
3304
3305 EVT LoOpVT, HiOpVT;
3306 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(Src0VT);
3307 assert(LoOpVT == HiOpVT && "Asymmetric vector split?");
3308
3309 SDValue LoOp0, HiOp0, LoOp1, HiOp1, LoMask, HiMask;
3310 std::tie(LoOp0, HiOp0) = DAG.SplitVector(Src0, DL);
3311 std::tie(LoOp1, HiOp1) = DAG.SplitVector(Src1, DL);
3312 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
3313
3314 SDValue LoSelect =
3315 DAG.getNode(ISD::VSELECT, DL, LoOpVT, LoMask, LoOp0, LoOp1);
3316 SDValue HiSelect =
3317 DAG.getNode(ISD::VSELECT, DL, HiOpVT, HiMask, HiOp0, HiOp1);
3318
3319 return DAG.getNode(ISD::CONCAT_VECTORS, DL, Src0VT, LoSelect, HiSelect);
3320}
3321
3322SDValue DAGTypeLegalizer::SplitVecOp_VECREDUCE(SDNode *N, unsigned OpNo) {
3323 EVT ResVT = N->getValueType(0);
3324 SDValue Lo, Hi;
3325 SDLoc dl(N);
3326
3327 SDValue VecOp = N->getOperand(OpNo);
3328 EVT VecVT = VecOp.getValueType();
3329 assert(VecVT.isVector() && "Can only split reduce vector operand");
3330 GetSplitVector(VecOp, Lo, Hi);
3331 EVT LoOpVT, HiOpVT;
3332 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(VecVT);
3333
3334 // Use the appropriate scalar instruction on the split subvectors before
3335 // reducing the now partially reduced smaller vector.
3336 unsigned CombineOpc = ISD::getVecReduceBaseOpcode(N->getOpcode());
3337 SDValue Partial = DAG.getNode(CombineOpc, dl, LoOpVT, Lo, Hi, N->getFlags());
3338 return DAG.getNode(N->getOpcode(), dl, ResVT, Partial, N->getFlags());
3339}
3340
3341SDValue DAGTypeLegalizer::SplitVecOp_VECREDUCE_SEQ(SDNode *N) {
3342 EVT ResVT = N->getValueType(0);
3343 SDValue Lo, Hi;
3344 SDLoc dl(N);
3345
3346 SDValue AccOp = N->getOperand(0);
3347 SDValue VecOp = N->getOperand(1);
3348 SDNodeFlags Flags = N->getFlags();
3349
3350 EVT VecVT = VecOp.getValueType();
3351 assert(VecVT.isVector() && "Can only split reduce vector operand");
3352 GetSplitVector(VecOp, Lo, Hi);
3353 EVT LoOpVT, HiOpVT;
3354 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(VecVT);
3355
3356 // Reduce low half.
3357 SDValue Partial = DAG.getNode(N->getOpcode(), dl, ResVT, AccOp, Lo, Flags);
3358
3359 // Reduce high half, using low half result as initial value.
3360 return DAG.getNode(N->getOpcode(), dl, ResVT, Partial, Hi, Flags);
3361}
3362
3363SDValue DAGTypeLegalizer::SplitVecOp_VP_REDUCE(SDNode *N, unsigned OpNo) {
3364 assert(N->isVPOpcode() && "Expected VP opcode");
3365 assert(OpNo == 1 && "Can only split reduce vector operand");
3366
3367 unsigned Opc = N->getOpcode();
3368 EVT ResVT = N->getValueType(0);
3369 SDValue Lo, Hi;
3370 SDLoc dl(N);
3371
3372 SDValue VecOp = N->getOperand(OpNo);
3373 EVT VecVT = VecOp.getValueType();
3374 assert(VecVT.isVector() && "Can only split reduce vector operand");
3375 GetSplitVector(VecOp, Lo, Hi);
3376
3377 SDValue MaskLo, MaskHi;
3378 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(2));
3379
3380 SDValue EVLLo, EVLHi;
3381 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(N->getOperand(3), VecVT, dl);
3382
3383 const SDNodeFlags Flags = N->getFlags();
3384
3385 SDValue ResLo =
3386 DAG.getNode(Opc, dl, ResVT, {N->getOperand(0), Lo, MaskLo, EVLLo}, Flags);
3387 return DAG.getNode(Opc, dl, ResVT, {ResLo, Hi, MaskHi, EVLHi}, Flags);
3388}
3389
3390SDValue DAGTypeLegalizer::SplitVecOp_UnaryOp(SDNode *N) {
3391 // The result has a legal vector type, but the input needs splitting.
3392 EVT ResVT = N->getValueType(0);
3393 SDValue Lo, Hi;
3394 SDLoc dl(N);
3395 GetSplitVector(N->getOperand(N->isStrictFPOpcode() ? 1 : 0), Lo, Hi);
3396 EVT InVT = Lo.getValueType();
3397
3398 EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
3399 InVT.getVectorElementCount());
3400
3401 if (N->isStrictFPOpcode()) {
3402 Lo = DAG.getNode(N->getOpcode(), dl, { OutVT, MVT::Other },
3403 { N->getOperand(0), Lo });
3404 Hi = DAG.getNode(N->getOpcode(), dl, { OutVT, MVT::Other },
3405 { N->getOperand(0), Hi });
3406
3407 // Build a factor node to remember that this operation is independent
3408 // of the other one.
3409 SDValue Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
3410 Hi.getValue(1));
3411
3412 // Legalize the chain result - switch anything that used the old chain to
3413 // use the new one.
3414 ReplaceValueWith(SDValue(N, 1), Ch);
3415 } else if (N->getNumOperands() == 3) {
3416 assert(N->isVPOpcode() && "Expected VP opcode");
3417 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
3418 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
3419 std::tie(EVLLo, EVLHi) =
3420 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), dl);
3421 Lo = DAG.getNode(N->getOpcode(), dl, OutVT, Lo, MaskLo, EVLLo);
3422 Hi = DAG.getNode(N->getOpcode(), dl, OutVT, Hi, MaskHi, EVLHi);
3423 } else {
3424 Lo = DAG.getNode(N->getOpcode(), dl, OutVT, Lo);
3425 Hi = DAG.getNode(N->getOpcode(), dl, OutVT, Hi);
3426 }
3427
3428 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
3429}
3430
3431SDValue DAGTypeLegalizer::SplitVecOp_BITCAST(SDNode *N) {
3432 // For example, i64 = BITCAST v4i16 on alpha. Typically the vector will
3433 // end up being split all the way down to individual components. Convert the
3434 // split pieces into integers and reassemble.
3435 EVT ResVT = N->getValueType(0);
3436 SDValue Lo, Hi;
3437 GetSplitVector(N->getOperand(0), Lo, Hi);
3438 SDLoc dl(N);
3439
3440 if (ResVT.isScalableVector()) {
3441 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(ResVT);
3442 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
3443 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
3444 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
3445 }
3446
3447 Lo = BitConvertToInteger(Lo);
3448 Hi = BitConvertToInteger(Hi);
3449
3450 if (DAG.getDataLayout().isBigEndian())
3451 std::swap(Lo, Hi);
3452
3453 return DAG.getNode(ISD::BITCAST, dl, ResVT, JoinIntegers(Lo, Hi));
3454}
3455
3456SDValue DAGTypeLegalizer::SplitVecOp_INSERT_SUBVECTOR(SDNode *N,
3457 unsigned OpNo) {
3458 assert(OpNo == 1 && "Invalid OpNo; can only split SubVec.");
3459 // We know that the result type is legal.
3460 EVT ResVT = N->getValueType(0);
3461
3462 SDValue Vec = N->getOperand(0);
3463 SDValue SubVec = N->getOperand(1);
3464 SDValue Idx = N->getOperand(2);
3465 SDLoc dl(N);
3466
3467 SDValue Lo, Hi;
3468 GetSplitVector(SubVec, Lo, Hi);
3469
3470 uint64_t IdxVal = Idx->getAsZExtVal();
3471 uint64_t LoElts = Lo.getValueType().getVectorMinNumElements();
3472
3473 SDValue FirstInsertion =
3474 DAG.getNode(ISD::INSERT_SUBVECTOR, dl, ResVT, Vec, Lo, Idx);
3475 SDValue SecondInsertion =
3476 DAG.getNode(ISD::INSERT_SUBVECTOR, dl, ResVT, FirstInsertion, Hi,
3477 DAG.getVectorIdxConstant(IdxVal + LoElts, dl));
3478
3479 return SecondInsertion;
3480}
3481
3482SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
3483 // We know that the extracted result type is legal.
3484 EVT SubVT = N->getValueType(0);
3485 SDValue Idx = N->getOperand(1);
3486 SDLoc dl(N);
3487 SDValue Lo, Hi;
3488
3489 GetSplitVector(N->getOperand(0), Lo, Hi);
3490
3491 uint64_t LoEltsMin = Lo.getValueType().getVectorMinNumElements();
3492 uint64_t IdxVal = Idx->getAsZExtVal();
3493
3494 if (IdxVal < LoEltsMin) {
3495 assert(IdxVal + SubVT.getVectorMinNumElements() <= LoEltsMin &&
3496 "Extracted subvector crosses vector split!");
3497 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, SubVT, Lo, Idx);
3498 } else if (SubVT.isScalableVector() ==
3499 N->getOperand(0).getValueType().isScalableVector())
3500 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, SubVT, Hi,
3501 DAG.getVectorIdxConstant(IdxVal - LoEltsMin, dl));
3502
3503 // After this point the DAG node only permits extracting fixed-width
3504 // subvectors from scalable vectors.
3505 assert(SubVT.isFixedLengthVector() &&
3506 "Extracting scalable subvector from fixed-width unsupported");
3507
3508 // If the element type is i1 and we're not promoting the result, then we may
3509 // end up loading the wrong data since the bits are packed tightly into
3510 // bytes. For example, if we extract a v4i1 (legal) from a nxv4i1 (legal)
3511 // type at index 4, then we will load a byte starting at index 0.
3512 if (SubVT.getScalarType() == MVT::i1)
3513 report_fatal_error("Don't know how to extract fixed-width predicate "
3514 "subvector from a scalable predicate vector");
3515
3516 // Spill the vector to the stack. We should use the alignment for
3517 // the smallest part.
3518 SDValue Vec = N->getOperand(0);
3519 EVT VecVT = Vec.getValueType();
3520 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
3522 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
3523 auto &MF = DAG.getMachineFunction();
3524 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
3525 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
3526
3527 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
3528 SmallestAlign);
3529
3530 // Extract the subvector by loading the correct part.
3531 StackPtr = TLI.getVectorSubVecPointer(DAG, StackPtr, VecVT, SubVT, Idx);
3532
3533 return DAG.getLoad(
3534 SubVT, dl, Store, StackPtr,
3535 MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()));
3536}
3537
3538SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
3539 SDValue Vec = N->getOperand(0);
3540 SDValue Idx = N->getOperand(1);
3541 EVT VecVT = Vec.getValueType();
3542
3543 if (const ConstantSDNode *Index = dyn_cast<ConstantSDNode>(Idx)) {
3544 uint64_t IdxVal = Index->getZExtValue();
3545
3546 SDValue Lo, Hi;
3547 GetSplitVector(Vec, Lo, Hi);
3548
3549 uint64_t LoElts = Lo.getValueType().getVectorMinNumElements();
3550
3551 if (IdxVal < LoElts)
3552 return SDValue(DAG.UpdateNodeOperands(N, Lo, Idx), 0);
3553 else if (!Vec.getValueType().isScalableVector())
3554 return SDValue(DAG.UpdateNodeOperands(N, Hi,
3555 DAG.getConstant(IdxVal - LoElts, SDLoc(N),
3556 Idx.getValueType())), 0);
3557 }
3558
3559 // See if the target wants to custom expand this node.
3560 if (CustomLowerNode(N, N->getValueType(0), true))
3561 return SDValue();
3562
3563 // Make the vector elements byte-addressable if they aren't already.
3564 SDLoc dl(N);
3565 EVT EltVT = VecVT.getVectorElementType();
3566 if (!EltVT.isByteSized()) {
3567 EltVT = EltVT.changeTypeToInteger().getRoundIntegerType(*DAG.getContext());
3568 VecVT = VecVT.changeElementType(EltVT);
3569 Vec = DAG.getNode(ISD::ANY_EXTEND, dl, VecVT, Vec);
3570 SDValue NewExtract =
3571 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, Vec, Idx);
3572 return DAG.getAnyExtOrTrunc(NewExtract, dl, N->getValueType(0));
3573 }
3574
3575 // Store the vector to the stack.
3576 // In cases where the vector is illegal it will be broken down into parts
3577 // and stored in parts - we should use the alignment for the smallest part.
3578 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
3580 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
3581 auto &MF = DAG.getMachineFunction();
3582 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
3583 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
3584 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
3585 SmallestAlign);
3586
3587 // Load back the required element.
3588 StackPtr = TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Idx);
3589
3590 // EXTRACT_VECTOR_ELT can extend the element type to the width of the return
3591 // type, leaving the high bits undefined. But it can't truncate.
3592 assert(N->getValueType(0).bitsGE(EltVT) && "Illegal EXTRACT_VECTOR_ELT.");
3593
3594 return DAG.getExtLoad(
3595 ISD::EXTLOAD, dl, N->getValueType(0), Store, StackPtr,
3596 MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()), EltVT,
3597 commonAlignment(SmallestAlign, EltVT.getFixedSizeInBits() / 8));
3598}
3599
3600SDValue DAGTypeLegalizer::SplitVecOp_ExtVecInRegOp(SDNode *N) {
3601 SDValue Lo, Hi;
3602
3603 // *_EXTEND_VECTOR_INREG only reference the lower half of the input, so
3604 // splitting the result has the same effect as splitting the input operand.
3605 SplitVecRes_ExtVecInRegOp(N, Lo, Hi);
3606
3607 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), N->getValueType(0), Lo, Hi);
3608}
3609
3610SDValue DAGTypeLegalizer::SplitVecOp_Gather(MemSDNode *N, unsigned OpNo) {
3611 (void)OpNo;
3612 SDValue Lo, Hi;
3613 SplitVecRes_Gather(N, Lo, Hi);
3614
3615 SDValue Res = DAG.getNode(ISD::CONCAT_VECTORS, N, N->getValueType(0), Lo, Hi);
3616 ReplaceValueWith(SDValue(N, 0), Res);
3617 return SDValue();
3618}
3619
3620SDValue DAGTypeLegalizer::SplitVecOp_VP_STORE(VPStoreSDNode *N, unsigned OpNo) {
3621 assert(N->isUnindexed() && "Indexed vp_store of vector?");
3622 SDValue Ch = N->getChain();
3623 SDValue Ptr = N->getBasePtr();
3624 SDValue Offset = N->getOffset();
3625 assert(Offset.isUndef() && "Unexpected VP store offset");
3626 SDValue Mask = N->getMask();
3627 SDValue EVL = N->getVectorLength();
3628 SDValue Data = N->getValue();
3629 Align Alignment = N->getOriginalAlign();
3630 SDLoc DL(N);
3631
3632 SDValue DataLo, DataHi;
3633 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
3634 // Split Data operand
3635 GetSplitVector(Data, DataLo, DataHi);
3636 else
3637 std::tie(DataLo, DataHi) = DAG.SplitVector(Data, DL);
3638
3639 // Split Mask operand
3640 SDValue MaskLo, MaskHi;
3641 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC) {
3642 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
3643 } else {
3644 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
3645 GetSplitVector(Mask, MaskLo, MaskHi);
3646 else
3647 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
3648 }
3649
3650 EVT MemoryVT = N->getMemoryVT();
3651 EVT LoMemVT, HiMemVT;
3652 bool HiIsEmpty = false;
3653 std::tie(LoMemVT, HiMemVT) =
3654 DAG.GetDependentSplitDestVTs(MemoryVT, DataLo.getValueType(), &HiIsEmpty);
3655
3656 // Split EVL
3657 SDValue EVLLo, EVLHi;
3658 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(EVL, Data.getValueType(), DL);
3659
3660 SDValue Lo, Hi;
3661 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
3662 N->getPointerInfo(), MachineMemOperand::MOStore,
3663 LocationSize::beforeOrAfterPointer(), Alignment, N->getAAInfo(),
3664 N->getRanges());
3665
3666 Lo = DAG.getStoreVP(Ch, DL, DataLo, Ptr, Offset, MaskLo, EVLLo, LoMemVT, MMO,
3667 N->getAddressingMode(), N->isTruncatingStore(),
3668 N->isCompressingStore());
3669
3670 // If the hi vp_store has zero storage size, only the lo vp_store is needed.
3671 if (HiIsEmpty)
3672 return Lo;
3673
3674 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, DL, LoMemVT, DAG,
3675 N->isCompressingStore());
3676
3678 if (LoMemVT.isScalableVector()) {
3679 Alignment = commonAlignment(Alignment,
3680 LoMemVT.getSizeInBits().getKnownMinValue() / 8);
3681 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
3682 } else
3683 MPI = N->getPointerInfo().getWithOffset(
3684 LoMemVT.getStoreSize().getFixedValue());
3685
3686 MMO = DAG.getMachineFunction().getMachineMemOperand(
3688 Alignment, N->getAAInfo(), N->getRanges());
3689
3690 Hi = DAG.getStoreVP(Ch, DL, DataHi, Ptr, Offset, MaskHi, EVLHi, HiMemVT, MMO,
3691 N->getAddressingMode(), N->isTruncatingStore(),
3692 N->isCompressingStore());
3693
3694 // Build a factor node to remember that this store is independent of the
3695 // other one.
3696 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
3697}
3698
3699SDValue DAGTypeLegalizer::SplitVecOp_VP_STRIDED_STORE(VPStridedStoreSDNode *N,
3700 unsigned OpNo) {
3701 assert(N->isUnindexed() && "Indexed vp_strided_store of a vector?");
3702 assert(N->getOffset().isUndef() && "Unexpected VP strided store offset");
3703
3704 SDLoc DL(N);
3705
3706 SDValue Data = N->getValue();
3707 SDValue LoData, HiData;
3708 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
3709 GetSplitVector(Data, LoData, HiData);
3710 else
3711 std::tie(LoData, HiData) = DAG.SplitVector(Data, DL);
3712
3713 EVT LoMemVT, HiMemVT;
3714 bool HiIsEmpty = false;
3715 std::tie(LoMemVT, HiMemVT) = DAG.GetDependentSplitDestVTs(
3716 N->getMemoryVT(), LoData.getValueType(), &HiIsEmpty);
3717
3718 SDValue Mask = N->getMask();
3719 SDValue LoMask, HiMask;
3720 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC)
3721 SplitVecRes_SETCC(Mask.getNode(), LoMask, HiMask);
3722 else if (getTypeAction(Mask.getValueType()) ==
3724 GetSplitVector(Mask, LoMask, HiMask);
3725 else
3726 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
3727
3728 SDValue LoEVL, HiEVL;
3729 std::tie(LoEVL, HiEVL) =
3730 DAG.SplitEVL(N->getVectorLength(), Data.getValueType(), DL);
3731
3732 // Generate the low vp_strided_store
3733 SDValue Lo = DAG.getStridedStoreVP(
3734 N->getChain(), DL, LoData, N->getBasePtr(), N->getOffset(),
3735 N->getStride(), LoMask, LoEVL, LoMemVT, N->getMemOperand(),
3736 N->getAddressingMode(), N->isTruncatingStore(), N->isCompressingStore());
3737
3738 // If the high vp_strided_store has zero storage size, only the low
3739 // vp_strided_store is needed.
3740 if (HiIsEmpty)
3741 return Lo;
3742
3743 // Generate the high vp_strided_store.
3744 // To calculate the high base address, we need to sum to the low base
3745 // address stride number of bytes for each element already stored by low,
3746 // that is: Ptr = Ptr + (LoEVL * Stride)
3747 EVT PtrVT = N->getBasePtr().getValueType();
3749 DAG.getNode(ISD::MUL, DL, PtrVT, LoEVL,
3750 DAG.getSExtOrTrunc(N->getStride(), DL, PtrVT));
3751 SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, N->getBasePtr(), Increment);
3752
3753 Align Alignment = N->getOriginalAlign();
3754 if (LoMemVT.isScalableVector())
3755 Alignment = commonAlignment(Alignment,
3756 LoMemVT.getSizeInBits().getKnownMinValue() / 8);
3757
3758 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
3759 MachinePointerInfo(N->getPointerInfo().getAddrSpace()),
3761 Alignment, N->getAAInfo(), N->getRanges());
3762
3763 SDValue Hi = DAG.getStridedStoreVP(
3764 N->getChain(), DL, HiData, Ptr, N->getOffset(), N->getStride(), HiMask,
3765 HiEVL, HiMemVT, MMO, N->getAddressingMode(), N->isTruncatingStore(),
3766 N->isCompressingStore());
3767
3768 // Build a factor node to remember that this store is independent of the
3769 // other one.
3770 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
3771}
3772
3773SDValue DAGTypeLegalizer::SplitVecOp_MSTORE(MaskedStoreSDNode *N,
3774 unsigned OpNo) {
3775 assert(N->isUnindexed() && "Indexed masked store of vector?");
3776 SDValue Ch = N->getChain();
3777 SDValue Ptr = N->getBasePtr();
3778 SDValue Offset = N->getOffset();
3779 assert(Offset.isUndef() && "Unexpected indexed masked store offset");
3780 SDValue Mask = N->getMask();
3781 SDValue Data = N->getValue();
3782 Align Alignment = N->getOriginalAlign();
3783 SDLoc DL(N);
3784
3785 SDValue DataLo, DataHi;
3786 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
3787 // Split Data operand
3788 GetSplitVector(Data, DataLo, DataHi);
3789 else
3790 std::tie(DataLo, DataHi) = DAG.SplitVector(Data, DL);
3791
3792 // Split Mask operand
3793 SDValue MaskLo, MaskHi;
3794 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC) {
3795 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
3796 } else {
3797 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
3798 GetSplitVector(Mask, MaskLo, MaskHi);
3799 else
3800 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
3801 }
3802
3803 EVT MemoryVT = N->getMemoryVT();
3804 EVT LoMemVT, HiMemVT;
3805 bool HiIsEmpty = false;
3806 std::tie(LoMemVT, HiMemVT) =
3807 DAG.GetDependentSplitDestVTs(MemoryVT, DataLo.getValueType(), &HiIsEmpty);
3808
3809 SDValue Lo, Hi, Res;
3810 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
3811 N->getPointerInfo(), MachineMemOperand::MOStore,
3812 LocationSize::beforeOrAfterPointer(), Alignment, N->getAAInfo(),
3813 N->getRanges());
3814
3815 Lo = DAG.getMaskedStore(Ch, DL, DataLo, Ptr, Offset, MaskLo, LoMemVT, MMO,
3816 N->getAddressingMode(), N->isTruncatingStore(),
3817 N->isCompressingStore());
3818
3819 if (HiIsEmpty) {
3820 // The hi masked store has zero storage size.
3821 // Only the lo masked store is needed.
3822 Res = Lo;
3823 } else {
3824
3825 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, DL, LoMemVT, DAG,
3826 N->isCompressingStore());
3827
3829 if (LoMemVT.isScalableVector()) {
3830 Alignment = commonAlignment(
3831 Alignment, LoMemVT.getSizeInBits().getKnownMinValue() / 8);
3832 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
3833 } else
3834 MPI = N->getPointerInfo().getWithOffset(
3835 LoMemVT.getStoreSize().getFixedValue());
3836
3837 MMO = DAG.getMachineFunction().getMachineMemOperand(
3839 Alignment, N->getAAInfo(), N->getRanges());
3840
3841 Hi = DAG.getMaskedStore(Ch, DL, DataHi, Ptr, Offset, MaskHi, HiMemVT, MMO,
3842 N->getAddressingMode(), N->isTruncatingStore(),
3843 N->isCompressingStore());
3844
3845 // Build a factor node to remember that this store is independent of the
3846 // other one.
3847 Res = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
3848 }
3849
3850 return Res;
3851}
3852
3853SDValue DAGTypeLegalizer::SplitVecOp_Scatter(MemSDNode *N, unsigned OpNo) {
3854 SDValue Ch = N->getChain();
3855 SDValue Ptr = N->getBasePtr();
3856 EVT MemoryVT = N->getMemoryVT();
3857 Align Alignment = N->getOriginalAlign();
3858 SDLoc DL(N);
3859 struct Operands {
3860 SDValue Mask;
3861 SDValue Index;
3862 SDValue Scale;
3863 SDValue Data;
3864 } Ops = [&]() -> Operands {
3865 if (auto *MSC = dyn_cast<MaskedScatterSDNode>(N)) {
3866 return {MSC->getMask(), MSC->getIndex(), MSC->getScale(),
3867 MSC->getValue()};
3868 }
3869 auto *VPSC = cast<VPScatterSDNode>(N);
3870 return {VPSC->getMask(), VPSC->getIndex(), VPSC->getScale(),
3871 VPSC->getValue()};
3872 }();
3873 // Split all operands
3874
3875 EVT LoMemVT, HiMemVT;
3876 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
3877
3878 SDValue DataLo, DataHi;
3879 if (getTypeAction(Ops.Data.getValueType()) == TargetLowering::TypeSplitVector)
3880 // Split Data operand
3881 GetSplitVector(Ops.Data, DataLo, DataHi);
3882 else
3883 std::tie(DataLo, DataHi) = DAG.SplitVector(Ops.Data, DL);
3884
3885 // Split Mask operand
3886 SDValue MaskLo, MaskHi;
3887 if (OpNo == 1 && Ops.Mask.getOpcode() == ISD::SETCC) {
3888 SplitVecRes_SETCC(Ops.Mask.getNode(), MaskLo, MaskHi);
3889 } else {
3890 std::tie(MaskLo, MaskHi) = SplitMask(Ops.Mask, DL);
3891 }
3892
3893 SDValue IndexHi, IndexLo;
3894 if (getTypeAction(Ops.Index.getValueType()) ==
3896 GetSplitVector(Ops.Index, IndexLo, IndexHi);
3897 else
3898 std::tie(IndexLo, IndexHi) = DAG.SplitVector(Ops.Index, DL);
3899
3900 SDValue Lo;
3901 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
3902 N->getPointerInfo(), MachineMemOperand::MOStore,
3903 LocationSize::beforeOrAfterPointer(), Alignment, N->getAAInfo(),
3904 N->getRanges());
3905
3906 if (auto *MSC = dyn_cast<MaskedScatterSDNode>(N)) {
3907 SDValue OpsLo[] = {Ch, DataLo, MaskLo, Ptr, IndexLo, Ops.Scale};
3908 Lo =
3909 DAG.getMaskedScatter(DAG.getVTList(MVT::Other), LoMemVT, DL, OpsLo, MMO,
3910 MSC->getIndexType(), MSC->isTruncatingStore());
3911
3912 // The order of the Scatter operation after split is well defined. The "Hi"
3913 // part comes after the "Lo". So these two operations should be chained one
3914 // after another.
3915 SDValue OpsHi[] = {Lo, DataHi, MaskHi, Ptr, IndexHi, Ops.Scale};
3916 return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), HiMemVT, DL, OpsHi,
3917 MMO, MSC->getIndexType(),
3918 MSC->isTruncatingStore());
3919 }
3920 auto *VPSC = cast<VPScatterSDNode>(N);
3921 SDValue EVLLo, EVLHi;
3922 std::tie(EVLLo, EVLHi) =
3923 DAG.SplitEVL(VPSC->getVectorLength(), Ops.Data.getValueType(), DL);
3924
3925 SDValue OpsLo[] = {Ch, DataLo, Ptr, IndexLo, Ops.Scale, MaskLo, EVLLo};
3926 Lo = DAG.getScatterVP(DAG.getVTList(MVT::Other), LoMemVT, DL, OpsLo, MMO,
3927 VPSC->getIndexType());
3928
3929 // The order of the Scatter operation after split is well defined. The "Hi"
3930 // part comes after the "Lo". So these two operations should be chained one
3931 // after another.
3932 SDValue OpsHi[] = {Lo, DataHi, Ptr, IndexHi, Ops.Scale, MaskHi, EVLHi};
3933 return DAG.getScatterVP(DAG.getVTList(MVT::Other), HiMemVT, DL, OpsHi, MMO,
3934 VPSC->getIndexType());
3935}
3936
3937SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) {
3938 assert(N->isUnindexed() && "Indexed store of vector?");
3939 assert(OpNo == 1 && "Can only split the stored value");
3940 SDLoc DL(N);
3941
3942 bool isTruncating = N->isTruncatingStore();
3943 SDValue Ch = N->getChain();
3944 SDValue Ptr = N->getBasePtr();
3945 EVT MemoryVT = N->getMemoryVT();
3946 Align Alignment = N->getOriginalAlign();
3947 MachineMemOperand::Flags MMOFlags = N->getMemOperand()->getFlags();
3948 AAMDNodes AAInfo = N->getAAInfo();
3949 SDValue Lo, Hi;
3950 GetSplitVector(N->getOperand(1), Lo, Hi);
3951
3952 EVT LoMemVT, HiMemVT;
3953 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
3954
3955 // Scalarize if the split halves are not byte-sized.
3956 if (!LoMemVT.isByteSized() || !HiMemVT.isByteSized())
3957 return TLI.scalarizeVectorStore(N, DAG);
3958
3959 if (isTruncating)
3960 Lo = DAG.getTruncStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), LoMemVT,
3961 Alignment, MMOFlags, AAInfo);
3962 else
3963 Lo = DAG.getStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), Alignment, MMOFlags,
3964 AAInfo);
3965
3967 IncrementPointer(N, LoMemVT, MPI, Ptr);
3968
3969 if (isTruncating)
3970 Hi = DAG.getTruncStore(Ch, DL, Hi, Ptr, MPI,
3971 HiMemVT, Alignment, MMOFlags, AAInfo);
3972 else
3973 Hi = DAG.getStore(Ch, DL, Hi, Ptr, MPI, Alignment, MMOFlags, AAInfo);
3974
3975 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
3976}
3977
3978SDValue DAGTypeLegalizer::SplitVecOp_CONCAT_VECTORS(SDNode *N) {
3979 SDLoc DL(N);
3980
3981 // The input operands all must have the same type, and we know the result
3982 // type is valid. Convert this to a buildvector which extracts all the
3983 // input elements.
3984 // TODO: If the input elements are power-two vectors, we could convert this to
3985 // a new CONCAT_VECTORS node with elements that are half-wide.
3987 EVT EltVT = N->getValueType(0).getVectorElementType();
3988 for (const SDValue &Op : N->op_values()) {
3989 for (unsigned i = 0, e = Op.getValueType().getVectorNumElements();
3990 i != e; ++i) {
3991 Elts.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltVT, Op,
3992 DAG.getVectorIdxConstant(i, DL)));
3993 }
3994 }
3995
3996 return DAG.getBuildVector(N->getValueType(0), DL, Elts);
3997}
3998
3999SDValue DAGTypeLegalizer::SplitVecOp_TruncateHelper(SDNode *N) {
4000 // The result type is legal, but the input type is illegal. If splitting
4001 // ends up with the result type of each half still being legal, just
4002 // do that. If, however, that would result in an illegal result type,
4003 // we can try to get more clever with power-two vectors. Specifically,
4004 // split the input type, but also widen the result element size, then
4005 // concatenate the halves and truncate again. For example, consider a target
4006 // where v8i8 is legal and v8i32 is not (ARM, which doesn't have 256-bit
4007 // vectors). To perform a "%res = v8i8 trunc v8i32 %in" we do:
4008 // %inlo = v4i32 extract_subvector %in, 0
4009 // %inhi = v4i32 extract_subvector %in, 4
4010 // %lo16 = v4i16 trunc v4i32 %inlo
4011 // %hi16 = v4i16 trunc v4i32 %inhi
4012 // %in16 = v8i16 concat_vectors v4i16 %lo16, v4i16 %hi16
4013 // %res = v8i8 trunc v8i16 %in16
4014 //
4015 // Without this transform, the original truncate would end up being
4016 // scalarized, which is pretty much always a last resort.
4017 unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
4018 SDValue InVec = N->getOperand(OpNo);
4019 EVT InVT = InVec->getValueType(0);
4020 EVT OutVT = N->getValueType(0);
4021 ElementCount NumElements = OutVT.getVectorElementCount();
4022 bool IsFloat = OutVT.isFloatingPoint();
4023
4024 unsigned InElementSize = InVT.getScalarSizeInBits();
4025 unsigned OutElementSize = OutVT.getScalarSizeInBits();
4026
4027 // Determine the split output VT. If its legal we can just split dirctly.
4028 EVT LoOutVT, HiOutVT;
4029 std::tie(LoOutVT, HiOutVT) = DAG.GetSplitDestVTs(OutVT);
4030 assert(LoOutVT == HiOutVT && "Unequal split?");
4031
4032 // If the input elements are only 1/2 the width of the result elements,
4033 // just use the normal splitting. Our trick only work if there's room
4034 // to split more than once.
4035 if (isTypeLegal(LoOutVT) ||
4036 InElementSize <= OutElementSize * 2)
4037 return SplitVecOp_UnaryOp(N);
4038 SDLoc DL(N);
4039
4040 // Don't touch if this will be scalarized.
4041 EVT FinalVT = InVT;
4042 while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
4043 FinalVT = FinalVT.getHalfNumVectorElementsVT(*DAG.getContext());
4044
4045 if (getTypeAction(FinalVT) == TargetLowering::TypeScalarizeVector)
4046 return SplitVecOp_UnaryOp(N);
4047
4048 // Get the split input vector.
4049 SDValue InLoVec, InHiVec;
4050 GetSplitVector(InVec, InLoVec, InHiVec);
4051
4052 // Truncate them to 1/2 the element size.
4053 //
4054 // This assumes the number of elements is a power of two; any vector that
4055 // isn't should be widened, not split.
4056 EVT HalfElementVT = IsFloat ?
4057 EVT::getFloatingPointVT(InElementSize/2) :
4058 EVT::getIntegerVT(*DAG.getContext(), InElementSize/2);
4059 EVT HalfVT = EVT::getVectorVT(*DAG.getContext(), HalfElementVT,
4060 NumElements.divideCoefficientBy(2));
4061
4062 SDValue HalfLo;
4063 SDValue HalfHi;
4064 SDValue Chain;
4065 if (N->isStrictFPOpcode()) {
4066 HalfLo = DAG.getNode(N->getOpcode(), DL, {HalfVT, MVT::Other},
4067 {N->getOperand(0), InLoVec});
4068 HalfHi = DAG.getNode(N->getOpcode(), DL, {HalfVT, MVT::Other},
4069 {N->getOperand(0), InHiVec});
4070 // Legalize the chain result - switch anything that used the old chain to
4071 // use the new one.
4072 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, HalfLo.getValue(1),
4073 HalfHi.getValue(1));
4074 } else {
4075 HalfLo = DAG.getNode(N->getOpcode(), DL, HalfVT, InLoVec);
4076 HalfHi = DAG.getNode(N->getOpcode(), DL, HalfVT, InHiVec);
4077 }
4078
4079 // Concatenate them to get the full intermediate truncation result.
4080 EVT InterVT = EVT::getVectorVT(*DAG.getContext(), HalfElementVT, NumElements);
4081 SDValue InterVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InterVT, HalfLo,
4082 HalfHi);
4083 // Now finish up by truncating all the way down to the original result
4084 // type. This should normally be something that ends up being legal directly,
4085 // but in theory if a target has very wide vectors and an annoyingly
4086 // restricted set of legal types, this split can chain to build things up.
4087
4088 if (N->isStrictFPOpcode()) {
4089 SDValue Res = DAG.getNode(
4090 ISD::STRICT_FP_ROUND, DL, {OutVT, MVT::Other},
4091 {Chain, InterVec,
4092 DAG.getTargetConstant(0, DL, TLI.getPointerTy(DAG.getDataLayout()))});
4093 // Relink the chain
4094 ReplaceValueWith(SDValue(N, 1), SDValue(Res.getNode(), 1));
4095 return Res;
4096 }
4097
4098 return IsFloat
4099 ? DAG.getNode(ISD::FP_ROUND, DL, OutVT, InterVec,
4100 DAG.getTargetConstant(
4101 0, DL, TLI.getPointerTy(DAG.getDataLayout())))
4102 : DAG.getNode(ISD::TRUNCATE, DL, OutVT, InterVec);
4103}
4104
4105SDValue DAGTypeLegalizer::SplitVecOp_VSETCC(SDNode *N) {
4106 bool isStrict = N->getOpcode() == ISD::STRICT_FSETCC;
4107 assert(N->getValueType(0).isVector() &&
4108 N->getOperand(isStrict ? 1 : 0).getValueType().isVector() &&
4109 "Operand types must be vectors");
4110 // The result has a legal vector type, but the input needs splitting.
4111 SDValue Lo0, Hi0, Lo1, Hi1, LoRes, HiRes;
4112 SDLoc DL(N);
4113 GetSplitVector(N->getOperand(isStrict ? 1 : 0), Lo0, Hi0);
4114 GetSplitVector(N->getOperand(isStrict ? 2 : 1), Lo1, Hi1);
4115
4116 auto PartEltCnt = Lo0.getValueType().getVectorElementCount();
4117
4118 LLVMContext &Context = *DAG.getContext();
4119 EVT PartResVT = EVT::getVectorVT(Context, MVT::i1, PartEltCnt);
4120 EVT WideResVT = EVT::getVectorVT(Context, MVT::i1, PartEltCnt*2);
4121