LLVM 20.0.0git
LegalizeVectorTypes.cpp
Go to the documentation of this file.
1//===------- LegalizeVectorTypes.cpp - Legalization of vector types -------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file performs vector type splitting and scalarization for LegalizeTypes.
10// Scalarization is the act of changing a computation in an illegal one-element
11// vector type to be a computation in its scalar element type. For example,
12// implementing <1 x f32> arithmetic in a scalar f32 register. This is needed
13// as a base case when scalarizing vector arithmetic like <4 x f32>, which
14// eventually decomposes to scalars if the target doesn't support v4f32 or v2f32
15// types.
16// Splitting is the act of changing a computation in an invalid vector type to
17// be a computation in two vectors of half the size. For example, implementing
18// <128 x f32> operations in terms of two <64 x f32> operations.
19//
20//===----------------------------------------------------------------------===//
21
22#include "LegalizeTypes.h"
27#include "llvm/IR/DataLayout.h"
31#include <numeric>
32
33using namespace llvm;
34
35#define DEBUG_TYPE "legalize-types"
36
37//===----------------------------------------------------------------------===//
38// Result Vector Scalarization: <1 x ty> -> ty.
39//===----------------------------------------------------------------------===//
40
41void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) {
42 LLVM_DEBUG(dbgs() << "Scalarize node result " << ResNo << ": ";
43 N->dump(&DAG));
44 SDValue R = SDValue();
45
46 switch (N->getOpcode()) {
47 default:
48#ifndef NDEBUG
49 dbgs() << "ScalarizeVectorResult #" << ResNo << ": ";
50 N->dump(&DAG);
51 dbgs() << "\n";
52#endif
53 report_fatal_error("Do not know how to scalarize the result of this "
54 "operator!\n");
55
56 case ISD::MERGE_VALUES: R = ScalarizeVecRes_MERGE_VALUES(N, ResNo);break;
57 case ISD::BITCAST: R = ScalarizeVecRes_BITCAST(N); break;
58 case ISD::BUILD_VECTOR: R = ScalarizeVecRes_BUILD_VECTOR(N); break;
59 case ISD::EXTRACT_SUBVECTOR: R = ScalarizeVecRes_EXTRACT_SUBVECTOR(N); break;
60 case ISD::FP_ROUND: R = ScalarizeVecRes_FP_ROUND(N); break;
61 case ISD::FPOWI: R = ScalarizeVecRes_ExpOp(N); break;
62 case ISD::INSERT_VECTOR_ELT: R = ScalarizeVecRes_INSERT_VECTOR_ELT(N); break;
63 case ISD::LOAD: R = ScalarizeVecRes_LOAD(cast<LoadSDNode>(N));break;
64 case ISD::SCALAR_TO_VECTOR: R = ScalarizeVecRes_SCALAR_TO_VECTOR(N); break;
65 case ISD::SIGN_EXTEND_INREG: R = ScalarizeVecRes_InregOp(N); break;
66 case ISD::VSELECT: R = ScalarizeVecRes_VSELECT(N); break;
67 case ISD::SELECT: R = ScalarizeVecRes_SELECT(N); break;
68 case ISD::SELECT_CC: R = ScalarizeVecRes_SELECT_CC(N); break;
69 case ISD::SETCC: R = ScalarizeVecRes_SETCC(N); break;
70 case ISD::UNDEF: R = ScalarizeVecRes_UNDEF(N); break;
71 case ISD::VECTOR_SHUFFLE: R = ScalarizeVecRes_VECTOR_SHUFFLE(N); break;
72 case ISD::IS_FPCLASS: R = ScalarizeVecRes_IS_FPCLASS(N); break;
76 R = ScalarizeVecRes_VecInregOp(N);
77 break;
78 case ISD::ABS:
79 case ISD::ANY_EXTEND:
80 case ISD::BITREVERSE:
81 case ISD::BSWAP:
82 case ISD::CTLZ:
84 case ISD::CTPOP:
85 case ISD::CTTZ:
87 case ISD::FABS:
88 case ISD::FACOS:
89 case ISD::FASIN:
90 case ISD::FATAN:
91 case ISD::FCEIL:
92 case ISD::FCOS:
93 case ISD::FCOSH:
94 case ISD::FEXP:
95 case ISD::FEXP2:
96 case ISD::FEXP10:
97 case ISD::FFLOOR:
98 case ISD::FLOG:
99 case ISD::FLOG10:
100 case ISD::FLOG2:
101 case ISD::FNEARBYINT:
102 case ISD::FNEG:
103 case ISD::FREEZE:
104 case ISD::ARITH_FENCE:
105 case ISD::FP_EXTEND:
106 case ISD::FP_TO_SINT:
107 case ISD::FP_TO_UINT:
108 case ISD::FRINT:
109 case ISD::LRINT:
110 case ISD::LLRINT:
111 case ISD::FROUND:
112 case ISD::FROUNDEVEN:
113 case ISD::LROUND:
114 case ISD::LLROUND:
115 case ISD::FSIN:
116 case ISD::FSINH:
117 case ISD::FSQRT:
118 case ISD::FTAN:
119 case ISD::FTANH:
120 case ISD::FTRUNC:
121 case ISD::SIGN_EXTEND:
122 case ISD::SINT_TO_FP:
123 case ISD::TRUNCATE:
124 case ISD::UINT_TO_FP:
125 case ISD::ZERO_EXTEND:
127 R = ScalarizeVecRes_UnaryOp(N);
128 break;
130 R = ScalarizeVecRes_ADDRSPACECAST(N);
131 break;
132 case ISD::FFREXP:
133 R = ScalarizeVecRes_FFREXP(N, ResNo);
134 break;
135 case ISD::ADD:
136 case ISD::AND:
137 case ISD::AVGCEILS:
138 case ISD::AVGCEILU:
139 case ISD::AVGFLOORS:
140 case ISD::AVGFLOORU:
141 case ISD::FADD:
142 case ISD::FCOPYSIGN:
143 case ISD::FDIV:
144 case ISD::FMUL:
145 case ISD::FMINNUM:
146 case ISD::FMAXNUM:
149 case ISD::FMINIMUM:
150 case ISD::FMAXIMUM:
151 case ISD::FLDEXP:
152 case ISD::ABDS:
153 case ISD::ABDU:
154 case ISD::SMIN:
155 case ISD::SMAX:
156 case ISD::UMIN:
157 case ISD::UMAX:
158
159 case ISD::SADDSAT:
160 case ISD::UADDSAT:
161 case ISD::SSUBSAT:
162 case ISD::USUBSAT:
163 case ISD::SSHLSAT:
164 case ISD::USHLSAT:
165
166 case ISD::FPOW:
167 case ISD::FREM:
168 case ISD::FSUB:
169 case ISD::MUL:
170 case ISD::MULHS:
171 case ISD::MULHU:
172 case ISD::OR:
173 case ISD::SDIV:
174 case ISD::SREM:
175 case ISD::SUB:
176 case ISD::UDIV:
177 case ISD::UREM:
178 case ISD::XOR:
179 case ISD::SHL:
180 case ISD::SRA:
181 case ISD::SRL:
182 case ISD::ROTL:
183 case ISD::ROTR:
184 R = ScalarizeVecRes_BinOp(N);
185 break;
186
187 case ISD::SCMP:
188 case ISD::UCMP:
189 R = ScalarizeVecRes_CMP(N);
190 break;
191
192 case ISD::FMA:
193 case ISD::FSHL:
194 case ISD::FSHR:
195 R = ScalarizeVecRes_TernaryOp(N);
196 break;
197
198#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
199 case ISD::STRICT_##DAGN:
200#include "llvm/IR/ConstrainedOps.def"
201 R = ScalarizeVecRes_StrictFPOp(N);
202 break;
203
206 R = ScalarizeVecRes_FP_TO_XINT_SAT(N);
207 break;
208
209 case ISD::UADDO:
210 case ISD::SADDO:
211 case ISD::USUBO:
212 case ISD::SSUBO:
213 case ISD::UMULO:
214 case ISD::SMULO:
215 R = ScalarizeVecRes_OverflowOp(N, ResNo);
216 break;
217 case ISD::SMULFIX:
218 case ISD::SMULFIXSAT:
219 case ISD::UMULFIX:
220 case ISD::UMULFIXSAT:
221 case ISD::SDIVFIX:
222 case ISD::SDIVFIXSAT:
223 case ISD::UDIVFIX:
224 case ISD::UDIVFIXSAT:
225 R = ScalarizeVecRes_FIX(N);
226 break;
227 }
228
229 // If R is null, the sub-method took care of registering the result.
230 if (R.getNode())
231 SetScalarizedVector(SDValue(N, ResNo), R);
232}
233
234SDValue DAGTypeLegalizer::ScalarizeVecRes_BinOp(SDNode *N) {
235 SDValue LHS = GetScalarizedVector(N->getOperand(0));
236 SDValue RHS = GetScalarizedVector(N->getOperand(1));
237 return DAG.getNode(N->getOpcode(), SDLoc(N),
238 LHS.getValueType(), LHS, RHS, N->getFlags());
239}
240
241SDValue DAGTypeLegalizer::ScalarizeVecRes_CMP(SDNode *N) {
242 SDLoc DL(N);
243
244 SDValue LHS = N->getOperand(0);
245 SDValue RHS = N->getOperand(1);
246 if (getTypeAction(LHS.getValueType()) ==
248 LHS = GetScalarizedVector(LHS);
249 RHS = GetScalarizedVector(RHS);
250 } else {
251 EVT VT = LHS.getValueType().getVectorElementType();
252 LHS = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, LHS,
253 DAG.getVectorIdxConstant(0, DL));
254 RHS = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, RHS,
255 DAG.getVectorIdxConstant(0, DL));
256 }
257
258 return DAG.getNode(N->getOpcode(), SDLoc(N),
259 N->getValueType(0).getVectorElementType(), LHS, RHS);
260}
261
262SDValue DAGTypeLegalizer::ScalarizeVecRes_TernaryOp(SDNode *N) {
263 SDValue Op0 = GetScalarizedVector(N->getOperand(0));
264 SDValue Op1 = GetScalarizedVector(N->getOperand(1));
265 SDValue Op2 = GetScalarizedVector(N->getOperand(2));
266 return DAG.getNode(N->getOpcode(), SDLoc(N), Op0.getValueType(), Op0, Op1,
267 Op2, N->getFlags());
268}
269
270SDValue DAGTypeLegalizer::ScalarizeVecRes_FIX(SDNode *N) {
271 SDValue Op0 = GetScalarizedVector(N->getOperand(0));
272 SDValue Op1 = GetScalarizedVector(N->getOperand(1));
273 SDValue Op2 = N->getOperand(2);
274 return DAG.getNode(N->getOpcode(), SDLoc(N), Op0.getValueType(), Op0, Op1,
275 Op2, N->getFlags());
276}
277
278SDValue DAGTypeLegalizer::ScalarizeVecRes_FFREXP(SDNode *N, unsigned ResNo) {
279 assert(N->getValueType(0).getVectorNumElements() == 1 &&
280 "Unexpected vector type!");
281 SDValue Elt = GetScalarizedVector(N->getOperand(0));
282
283 EVT VT0 = N->getValueType(0);
284 EVT VT1 = N->getValueType(1);
285 SDLoc dl(N);
286
287 SDNode *ScalarNode =
288 DAG.getNode(N->getOpcode(), dl,
289 {VT0.getScalarType(), VT1.getScalarType()}, Elt)
290 .getNode();
291
292 // Replace the other vector result not being explicitly scalarized here.
293 unsigned OtherNo = 1 - ResNo;
294 EVT OtherVT = N->getValueType(OtherNo);
295 if (getTypeAction(OtherVT) == TargetLowering::TypeScalarizeVector) {
296 SetScalarizedVector(SDValue(N, OtherNo), SDValue(ScalarNode, OtherNo));
297 } else {
298 SDValue OtherVal = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, OtherVT,
299 SDValue(ScalarNode, OtherNo));
300 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
301 }
302
303 return SDValue(ScalarNode, ResNo);
304}
305
306SDValue DAGTypeLegalizer::ScalarizeVecRes_StrictFPOp(SDNode *N) {
307 EVT VT = N->getValueType(0).getVectorElementType();
308 unsigned NumOpers = N->getNumOperands();
309 SDValue Chain = N->getOperand(0);
310 EVT ValueVTs[] = {VT, MVT::Other};
311 SDLoc dl(N);
312
313 SmallVector<SDValue, 4> Opers(NumOpers);
314
315 // The Chain is the first operand.
316 Opers[0] = Chain;
317
318 // Now process the remaining operands.
319 for (unsigned i = 1; i < NumOpers; ++i) {
320 SDValue Oper = N->getOperand(i);
321 EVT OperVT = Oper.getValueType();
322
323 if (OperVT.isVector()) {
324 if (getTypeAction(OperVT) == TargetLowering::TypeScalarizeVector)
325 Oper = GetScalarizedVector(Oper);
326 else
327 Oper = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl,
328 OperVT.getVectorElementType(), Oper,
329 DAG.getVectorIdxConstant(0, dl));
330 }
331
332 Opers[i] = Oper;
333 }
334
335 SDValue Result = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(ValueVTs),
336 Opers, N->getFlags());
337
338 // Legalize the chain result - switch anything that used the old chain to
339 // use the new one.
340 ReplaceValueWith(SDValue(N, 1), Result.getValue(1));
341 return Result;
342}
343
344SDValue DAGTypeLegalizer::ScalarizeVecRes_OverflowOp(SDNode *N,
345 unsigned ResNo) {
346 SDLoc DL(N);
347 EVT ResVT = N->getValueType(0);
348 EVT OvVT = N->getValueType(1);
349
350 SDValue ScalarLHS, ScalarRHS;
351 if (getTypeAction(ResVT) == TargetLowering::TypeScalarizeVector) {
352 ScalarLHS = GetScalarizedVector(N->getOperand(0));
353 ScalarRHS = GetScalarizedVector(N->getOperand(1));
354 } else {
355 SmallVector<SDValue, 1> ElemsLHS, ElemsRHS;
356 DAG.ExtractVectorElements(N->getOperand(0), ElemsLHS);
357 DAG.ExtractVectorElements(N->getOperand(1), ElemsRHS);
358 ScalarLHS = ElemsLHS[0];
359 ScalarRHS = ElemsRHS[0];
360 }
361
362 SDVTList ScalarVTs = DAG.getVTList(
364 SDNode *ScalarNode = DAG.getNode(
365 N->getOpcode(), DL, ScalarVTs, ScalarLHS, ScalarRHS).getNode();
366 ScalarNode->setFlags(N->getFlags());
367
368 // Replace the other vector result not being explicitly scalarized here.
369 unsigned OtherNo = 1 - ResNo;
370 EVT OtherVT = N->getValueType(OtherNo);
371 if (getTypeAction(OtherVT) == TargetLowering::TypeScalarizeVector) {
372 SetScalarizedVector(SDValue(N, OtherNo), SDValue(ScalarNode, OtherNo));
373 } else {
374 SDValue OtherVal = DAG.getNode(
375 ISD::SCALAR_TO_VECTOR, DL, OtherVT, SDValue(ScalarNode, OtherNo));
376 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
377 }
378
379 return SDValue(ScalarNode, ResNo);
380}
381
382SDValue DAGTypeLegalizer::ScalarizeVecRes_MERGE_VALUES(SDNode *N,
383 unsigned ResNo) {
384 SDValue Op = DisintegrateMERGE_VALUES(N, ResNo);
385 return GetScalarizedVector(Op);
386}
387
388SDValue DAGTypeLegalizer::ScalarizeVecRes_BITCAST(SDNode *N) {
389 SDValue Op = N->getOperand(0);
390 if (Op.getValueType().isVector()
391 && Op.getValueType().getVectorNumElements() == 1
392 && !isSimpleLegalType(Op.getValueType()))
393 Op = GetScalarizedVector(Op);
394 EVT NewVT = N->getValueType(0).getVectorElementType();
395 return DAG.getNode(ISD::BITCAST, SDLoc(N),
396 NewVT, Op);
397}
398
399SDValue DAGTypeLegalizer::ScalarizeVecRes_BUILD_VECTOR(SDNode *N) {
400 EVT EltVT = N->getValueType(0).getVectorElementType();
401 SDValue InOp = N->getOperand(0);
402 // The BUILD_VECTOR operands may be of wider element types and
403 // we may need to truncate them back to the requested return type.
404 if (EltVT.isInteger())
405 return DAG.getNode(ISD::TRUNCATE, SDLoc(N), EltVT, InOp);
406 return InOp;
407}
408
409SDValue DAGTypeLegalizer::ScalarizeVecRes_EXTRACT_SUBVECTOR(SDNode *N) {
411 N->getValueType(0).getVectorElementType(),
412 N->getOperand(0), N->getOperand(1));
413}
414
415SDValue DAGTypeLegalizer::ScalarizeVecRes_FP_ROUND(SDNode *N) {
416 SDLoc DL(N);
417 SDValue Op = N->getOperand(0);
418 EVT OpVT = Op.getValueType();
419 // The result needs scalarizing, but it's not a given that the source does.
420 // See similar logic in ScalarizeVecRes_UnaryOp.
421 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
422 Op = GetScalarizedVector(Op);
423 } else {
424 EVT VT = OpVT.getVectorElementType();
426 DAG.getVectorIdxConstant(0, DL));
427 }
428 return DAG.getNode(ISD::FP_ROUND, DL,
429 N->getValueType(0).getVectorElementType(), Op,
430 N->getOperand(1));
431}
432
433SDValue DAGTypeLegalizer::ScalarizeVecRes_ExpOp(SDNode *N) {
434 SDValue Op = GetScalarizedVector(N->getOperand(0));
435 return DAG.getNode(N->getOpcode(), SDLoc(N), Op.getValueType(), Op,
436 N->getOperand(1));
437}
438
439SDValue DAGTypeLegalizer::ScalarizeVecRes_INSERT_VECTOR_ELT(SDNode *N) {
440 // The value to insert may have a wider type than the vector element type,
441 // so be sure to truncate it to the element type if necessary.
442 SDValue Op = N->getOperand(1);
443 EVT EltVT = N->getValueType(0).getVectorElementType();
444 if (Op.getValueType() != EltVT)
445 // FIXME: Can this happen for floating point types?
446 Op = DAG.getNode(ISD::TRUNCATE, SDLoc(N), EltVT, Op);
447 return Op;
448}
449
450SDValue DAGTypeLegalizer::ScalarizeVecRes_LOAD(LoadSDNode *N) {
451 assert(N->isUnindexed() && "Indexed vector load?");
452
453 SDValue Result = DAG.getLoad(
454 ISD::UNINDEXED, N->getExtensionType(),
455 N->getValueType(0).getVectorElementType(), SDLoc(N), N->getChain(),
456 N->getBasePtr(), DAG.getUNDEF(N->getBasePtr().getValueType()),
457 N->getPointerInfo(), N->getMemoryVT().getVectorElementType(),
458 N->getOriginalAlign(), N->getMemOperand()->getFlags(), N->getAAInfo());
459
460 // Legalize the chain result - switch anything that used the old chain to
461 // use the new one.
462 ReplaceValueWith(SDValue(N, 1), Result.getValue(1));
463 return Result;
464}
465
466SDValue DAGTypeLegalizer::ScalarizeVecRes_UnaryOp(SDNode *N) {
467 // Get the dest type - it doesn't always match the input type, e.g. int_to_fp.
468 EVT DestVT = N->getValueType(0).getVectorElementType();
469 SDValue Op = N->getOperand(0);
470 EVT OpVT = Op.getValueType();
471 SDLoc DL(N);
472 // The result needs scalarizing, but it's not a given that the source does.
473 // This is a workaround for targets where it's impossible to scalarize the
474 // result of a conversion, because the source type is legal.
475 // For instance, this happens on AArch64: v1i1 is illegal but v1i{8,16,32}
476 // are widened to v8i8, v4i16, and v2i32, which is legal, because v1i64 is
477 // legal and was not scalarized.
478 // See the similar logic in ScalarizeVecRes_SETCC
479 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
480 Op = GetScalarizedVector(Op);
481 } else {
482 EVT VT = OpVT.getVectorElementType();
484 DAG.getVectorIdxConstant(0, DL));
485 }
486 return DAG.getNode(N->getOpcode(), SDLoc(N), DestVT, Op, N->getFlags());
487}
488
489SDValue DAGTypeLegalizer::ScalarizeVecRes_InregOp(SDNode *N) {
490 EVT EltVT = N->getValueType(0).getVectorElementType();
491 EVT ExtVT = cast<VTSDNode>(N->getOperand(1))->getVT().getVectorElementType();
492 SDValue LHS = GetScalarizedVector(N->getOperand(0));
493 return DAG.getNode(N->getOpcode(), SDLoc(N), EltVT,
494 LHS, DAG.getValueType(ExtVT));
495}
496
497SDValue DAGTypeLegalizer::ScalarizeVecRes_VecInregOp(SDNode *N) {
498 SDLoc DL(N);
499 SDValue Op = N->getOperand(0);
500
501 EVT OpVT = Op.getValueType();
502 EVT OpEltVT = OpVT.getVectorElementType();
503 EVT EltVT = N->getValueType(0).getVectorElementType();
504
505 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
506 Op = GetScalarizedVector(Op);
507 } else {
508 Op = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, OpEltVT, Op,
509 DAG.getVectorIdxConstant(0, DL));
510 }
511
512 switch (N->getOpcode()) {
514 return DAG.getNode(ISD::ANY_EXTEND, DL, EltVT, Op);
516 return DAG.getNode(ISD::SIGN_EXTEND, DL, EltVT, Op);
518 return DAG.getNode(ISD::ZERO_EXTEND, DL, EltVT, Op);
519 }
520
521 llvm_unreachable("Illegal extend_vector_inreg opcode");
522}
523
524SDValue DAGTypeLegalizer::ScalarizeVecRes_ADDRSPACECAST(SDNode *N) {
525 EVT DestVT = N->getValueType(0).getVectorElementType();
526 SDValue Op = N->getOperand(0);
527 EVT OpVT = Op.getValueType();
528 SDLoc DL(N);
529 // The result needs scalarizing, but it's not a given that the source does.
530 // This is a workaround for targets where it's impossible to scalarize the
531 // result of a conversion, because the source type is legal.
532 // For instance, this happens on AArch64: v1i1 is illegal but v1i{8,16,32}
533 // are widened to v8i8, v4i16, and v2i32, which is legal, because v1i64 is
534 // legal and was not scalarized.
535 // See the similar logic in ScalarizeVecRes_SETCC
536 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
537 Op = GetScalarizedVector(Op);
538 } else {
539 EVT VT = OpVT.getVectorElementType();
541 DAG.getVectorIdxConstant(0, DL));
542 }
543 auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
544 unsigned SrcAS = AddrSpaceCastN->getSrcAddressSpace();
545 unsigned DestAS = AddrSpaceCastN->getDestAddressSpace();
546 return DAG.getAddrSpaceCast(DL, DestVT, Op, SrcAS, DestAS);
547}
548
549SDValue DAGTypeLegalizer::ScalarizeVecRes_SCALAR_TO_VECTOR(SDNode *N) {
550 // If the operand is wider than the vector element type then it is implicitly
551 // truncated. Make that explicit here.
552 EVT EltVT = N->getValueType(0).getVectorElementType();
553 SDValue InOp = N->getOperand(0);
554 if (InOp.getValueType() != EltVT)
555 return DAG.getNode(ISD::TRUNCATE, SDLoc(N), EltVT, InOp);
556 return InOp;
557}
558
559SDValue DAGTypeLegalizer::ScalarizeVecRes_VSELECT(SDNode *N) {
560 SDValue Cond = N->getOperand(0);
561 EVT OpVT = Cond.getValueType();
562 SDLoc DL(N);
563 // The vselect result and true/value operands needs scalarizing, but it's
564 // not a given that the Cond does. For instance, in AVX512 v1i1 is legal.
565 // See the similar logic in ScalarizeVecRes_SETCC
566 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
567 Cond = GetScalarizedVector(Cond);
568 } else {
569 EVT VT = OpVT.getVectorElementType();
571 DAG.getVectorIdxConstant(0, DL));
572 }
573
574 SDValue LHS = GetScalarizedVector(N->getOperand(1));
576 TLI.getBooleanContents(false, false);
577 TargetLowering::BooleanContent VecBool = TLI.getBooleanContents(true, false);
578
579 // If integer and float booleans have different contents then we can't
580 // reliably optimize in all cases. There is a full explanation for this in
581 // DAGCombiner::visitSELECT() where the same issue affects folding
582 // (select C, 0, 1) to (xor C, 1).
583 if (TLI.getBooleanContents(false, false) !=
584 TLI.getBooleanContents(false, true)) {
585 // At least try the common case where the boolean is generated by a
586 // comparison.
587 if (Cond->getOpcode() == ISD::SETCC) {
588 EVT OpVT = Cond->getOperand(0).getValueType();
589 ScalarBool = TLI.getBooleanContents(OpVT.getScalarType());
590 VecBool = TLI.getBooleanContents(OpVT);
591 } else
593 }
594
595 EVT CondVT = Cond.getValueType();
596 if (ScalarBool != VecBool) {
597 switch (ScalarBool) {
599 break;
603 // Vector read from all ones, scalar expects a single 1 so mask.
604 Cond = DAG.getNode(ISD::AND, SDLoc(N), CondVT,
605 Cond, DAG.getConstant(1, SDLoc(N), CondVT));
606 break;
610 // Vector reads from a one, scalar from all ones so sign extend.
611 Cond = DAG.getNode(ISD::SIGN_EXTEND_INREG, SDLoc(N), CondVT,
612 Cond, DAG.getValueType(MVT::i1));
613 break;
614 }
615 }
616
617 // Truncate the condition if needed
618 auto BoolVT = getSetCCResultType(CondVT);
619 if (BoolVT.bitsLT(CondVT))
620 Cond = DAG.getNode(ISD::TRUNCATE, SDLoc(N), BoolVT, Cond);
621
622 return DAG.getSelect(SDLoc(N),
623 LHS.getValueType(), Cond, LHS,
624 GetScalarizedVector(N->getOperand(2)));
625}
626
627SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT(SDNode *N) {
628 SDValue LHS = GetScalarizedVector(N->getOperand(1));
629 return DAG.getSelect(SDLoc(N),
630 LHS.getValueType(), N->getOperand(0), LHS,
631 GetScalarizedVector(N->getOperand(2)));
632}
633
634SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT_CC(SDNode *N) {
635 SDValue LHS = GetScalarizedVector(N->getOperand(2));
636 return DAG.getNode(ISD::SELECT_CC, SDLoc(N), LHS.getValueType(),
637 N->getOperand(0), N->getOperand(1),
638 LHS, GetScalarizedVector(N->getOperand(3)),
639 N->getOperand(4));
640}
641
642SDValue DAGTypeLegalizer::ScalarizeVecRes_UNDEF(SDNode *N) {
643 return DAG.getUNDEF(N->getValueType(0).getVectorElementType());
644}
645
646SDValue DAGTypeLegalizer::ScalarizeVecRes_VECTOR_SHUFFLE(SDNode *N) {
647 // Figure out if the scalar is the LHS or RHS and return it.
648 SDValue Arg = N->getOperand(2).getOperand(0);
649 if (Arg.isUndef())
650 return DAG.getUNDEF(N->getValueType(0).getVectorElementType());
651 unsigned Op = !cast<ConstantSDNode>(Arg)->isZero();
652 return GetScalarizedVector(N->getOperand(Op));
653}
654
655SDValue DAGTypeLegalizer::ScalarizeVecRes_FP_TO_XINT_SAT(SDNode *N) {
656 SDValue Src = N->getOperand(0);
657 EVT SrcVT = Src.getValueType();
658 SDLoc dl(N);
659
660 // Handle case where result is scalarized but operand is not
661 if (getTypeAction(SrcVT) == TargetLowering::TypeScalarizeVector)
662 Src = GetScalarizedVector(Src);
663 else
664 Src = DAG.getNode(
666 DAG.getConstant(0, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
667
668 EVT DstVT = N->getValueType(0).getVectorElementType();
669 return DAG.getNode(N->getOpcode(), dl, DstVT, Src, N->getOperand(1));
670}
671
672SDValue DAGTypeLegalizer::ScalarizeVecRes_SETCC(SDNode *N) {
673 assert(N->getValueType(0).isVector() &&
674 N->getOperand(0).getValueType().isVector() &&
675 "Operand types must be vectors");
676 SDValue LHS = N->getOperand(0);
677 SDValue RHS = N->getOperand(1);
678 EVT OpVT = LHS.getValueType();
679 EVT NVT = N->getValueType(0).getVectorElementType();
680 SDLoc DL(N);
681
682 // The result needs scalarizing, but it's not a given that the source does.
683 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
684 LHS = GetScalarizedVector(LHS);
685 RHS = GetScalarizedVector(RHS);
686 } else {
687 EVT VT = OpVT.getVectorElementType();
688 LHS = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, LHS,
689 DAG.getVectorIdxConstant(0, DL));
690 RHS = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, RHS,
691 DAG.getVectorIdxConstant(0, DL));
692 }
693
694 // Turn it into a scalar SETCC.
695 SDValue Res = DAG.getNode(ISD::SETCC, DL, MVT::i1, LHS, RHS,
696 N->getOperand(2));
697 // Vectors may have a different boolean contents to scalars. Promote the
698 // value appropriately.
699 ISD::NodeType ExtendCode =
701 return DAG.getNode(ExtendCode, DL, NVT, Res);
702}
703
704SDValue DAGTypeLegalizer::ScalarizeVecRes_IS_FPCLASS(SDNode *N) {
705 SDLoc DL(N);
706 SDValue Arg = N->getOperand(0);
707 SDValue Test = N->getOperand(1);
708 EVT ArgVT = Arg.getValueType();
709 EVT ResultVT = N->getValueType(0).getVectorElementType();
710
711 if (getTypeAction(ArgVT) == TargetLowering::TypeScalarizeVector) {
712 Arg = GetScalarizedVector(Arg);
713 } else {
714 EVT VT = ArgVT.getVectorElementType();
715 Arg = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, Arg,
716 DAG.getVectorIdxConstant(0, DL));
717 }
718
719 SDValue Res =
720 DAG.getNode(ISD::IS_FPCLASS, DL, MVT::i1, {Arg, Test}, N->getFlags());
721 // Vectors may have a different boolean contents to scalars. Promote the
722 // value appropriately.
723 ISD::NodeType ExtendCode =
725 return DAG.getNode(ExtendCode, DL, ResultVT, Res);
726}
727
728//===----------------------------------------------------------------------===//
729// Operand Vector Scalarization <1 x ty> -> ty.
730//===----------------------------------------------------------------------===//
731
732bool DAGTypeLegalizer::ScalarizeVectorOperand(SDNode *N, unsigned OpNo) {
733 LLVM_DEBUG(dbgs() << "Scalarize node operand " << OpNo << ": ";
734 N->dump(&DAG));
735 SDValue Res = SDValue();
736
737 switch (N->getOpcode()) {
738 default:
739#ifndef NDEBUG
740 dbgs() << "ScalarizeVectorOperand Op #" << OpNo << ": ";
741 N->dump(&DAG);
742 dbgs() << "\n";
743#endif
744 report_fatal_error("Do not know how to scalarize this operator's "
745 "operand!\n");
746 case ISD::BITCAST:
747 Res = ScalarizeVecOp_BITCAST(N);
748 break;
749 case ISD::ANY_EXTEND:
750 case ISD::ZERO_EXTEND:
751 case ISD::SIGN_EXTEND:
752 case ISD::TRUNCATE:
753 case ISD::FP_TO_SINT:
754 case ISD::FP_TO_UINT:
755 case ISD::SINT_TO_FP:
756 case ISD::UINT_TO_FP:
757 case ISD::LROUND:
758 case ISD::LLROUND:
759 case ISD::LRINT:
760 case ISD::LLRINT:
761 Res = ScalarizeVecOp_UnaryOp(N);
762 break;
767 Res = ScalarizeVecOp_UnaryOp_StrictFP(N);
768 break;
770 Res = ScalarizeVecOp_CONCAT_VECTORS(N);
771 break;
773 Res = ScalarizeVecOp_INSERT_SUBVECTOR(N, OpNo);
774 break;
776 Res = ScalarizeVecOp_EXTRACT_VECTOR_ELT(N);
777 break;
778 case ISD::VSELECT:
779 Res = ScalarizeVecOp_VSELECT(N);
780 break;
781 case ISD::SETCC:
782 Res = ScalarizeVecOp_VSETCC(N);
783 break;
784 case ISD::STORE:
785 Res = ScalarizeVecOp_STORE(cast<StoreSDNode>(N), OpNo);
786 break;
788 Res = ScalarizeVecOp_STRICT_FP_ROUND(N, OpNo);
789 break;
790 case ISD::FP_ROUND:
791 Res = ScalarizeVecOp_FP_ROUND(N, OpNo);
792 break;
794 Res = ScalarizeVecOp_STRICT_FP_EXTEND(N);
795 break;
796 case ISD::FP_EXTEND:
797 Res = ScalarizeVecOp_FP_EXTEND(N);
798 break;
814 Res = ScalarizeVecOp_VECREDUCE(N);
815 break;
818 Res = ScalarizeVecOp_VECREDUCE_SEQ(N);
819 break;
820 case ISD::SCMP:
821 case ISD::UCMP:
822 Res = ScalarizeVecOp_CMP(N);
823 break;
824 }
825
826 // If the result is null, the sub-method took care of registering results etc.
827 if (!Res.getNode()) return false;
828
829 // If the result is N, the sub-method updated N in place. Tell the legalizer
830 // core about this.
831 if (Res.getNode() == N)
832 return true;
833
834 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
835 "Invalid operand expansion");
836
837 ReplaceValueWith(SDValue(N, 0), Res);
838 return false;
839}
840
841/// If the value to convert is a vector that needs to be scalarized, it must be
842/// <1 x ty>. Convert the element instead.
843SDValue DAGTypeLegalizer::ScalarizeVecOp_BITCAST(SDNode *N) {
844 SDValue Elt = GetScalarizedVector(N->getOperand(0));
845 return DAG.getNode(ISD::BITCAST, SDLoc(N),
846 N->getValueType(0), Elt);
847}
848
849/// If the input is a vector that needs to be scalarized, it must be <1 x ty>.
850/// Do the operation on the element instead.
851SDValue DAGTypeLegalizer::ScalarizeVecOp_UnaryOp(SDNode *N) {
852 assert(N->getValueType(0).getVectorNumElements() == 1 &&
853 "Unexpected vector type!");
854 SDValue Elt = GetScalarizedVector(N->getOperand(0));
855 SDValue Op = DAG.getNode(N->getOpcode(), SDLoc(N),
856 N->getValueType(0).getScalarType(), Elt);
857 // Revectorize the result so the types line up with what the uses of this
858 // expression expect.
859 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Op);
860}
861
862/// If the input is a vector that needs to be scalarized, it must be <1 x ty>.
863/// Do the strict FP operation on the element instead.
864SDValue DAGTypeLegalizer::ScalarizeVecOp_UnaryOp_StrictFP(SDNode *N) {
865 assert(N->getValueType(0).getVectorNumElements() == 1 &&
866 "Unexpected vector type!");
867 SDValue Elt = GetScalarizedVector(N->getOperand(1));
868 SDValue Res = DAG.getNode(N->getOpcode(), SDLoc(N),
869 { N->getValueType(0).getScalarType(), MVT::Other },
870 { N->getOperand(0), Elt });
871 // Legalize the chain result - switch anything that used the old chain to
872 // use the new one.
873 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
874 // Revectorize the result so the types line up with what the uses of this
875 // expression expect.
876 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
877
878 // Do our own replacement and return SDValue() to tell the caller that we
879 // handled all replacements since caller can only handle a single result.
880 ReplaceValueWith(SDValue(N, 0), Res);
881 return SDValue();
882}
883
884/// The vectors to concatenate have length one - use a BUILD_VECTOR instead.
885SDValue DAGTypeLegalizer::ScalarizeVecOp_CONCAT_VECTORS(SDNode *N) {
886 SmallVector<SDValue, 8> Ops(N->getNumOperands());
887 for (unsigned i = 0, e = N->getNumOperands(); i < e; ++i)
888 Ops[i] = GetScalarizedVector(N->getOperand(i));
889 return DAG.getBuildVector(N->getValueType(0), SDLoc(N), Ops);
890}
891
892/// The inserted subvector is to be scalarized - use insert vector element
893/// instead.
894SDValue DAGTypeLegalizer::ScalarizeVecOp_INSERT_SUBVECTOR(SDNode *N,
895 unsigned OpNo) {
896 // We should not be attempting to scalarize the containing vector
897 assert(OpNo == 1);
898 SDValue Elt = GetScalarizedVector(N->getOperand(1));
899 SDValue ContainingVec = N->getOperand(0);
901 ContainingVec.getValueType(), ContainingVec, Elt,
902 N->getOperand(2));
903}
904
905/// If the input is a vector that needs to be scalarized, it must be <1 x ty>,
906/// so just return the element, ignoring the index.
907SDValue DAGTypeLegalizer::ScalarizeVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
908 EVT VT = N->getValueType(0);
909 SDValue Res = GetScalarizedVector(N->getOperand(0));
910 if (Res.getValueType() != VT)
911 Res = VT.isFloatingPoint()
912 ? DAG.getNode(ISD::FP_EXTEND, SDLoc(N), VT, Res)
913 : DAG.getNode(ISD::ANY_EXTEND, SDLoc(N), VT, Res);
914 return Res;
915}
916
917/// If the input condition is a vector that needs to be scalarized, it must be
918/// <1 x i1>, so just convert to a normal ISD::SELECT
919/// (still with vector output type since that was acceptable if we got here).
920SDValue DAGTypeLegalizer::ScalarizeVecOp_VSELECT(SDNode *N) {
921 SDValue ScalarCond = GetScalarizedVector(N->getOperand(0));
922 EVT VT = N->getValueType(0);
923
924 return DAG.getNode(ISD::SELECT, SDLoc(N), VT, ScalarCond, N->getOperand(1),
925 N->getOperand(2));
926}
927
928/// If the operand is a vector that needs to be scalarized then the
929/// result must be v1i1, so just convert to a scalar SETCC and wrap
930/// with a scalar_to_vector since the res type is legal if we got here
931SDValue DAGTypeLegalizer::ScalarizeVecOp_VSETCC(SDNode *N) {
932 assert(N->getValueType(0).isVector() &&
933 N->getOperand(0).getValueType().isVector() &&
934 "Operand types must be vectors");
935 assert(N->getValueType(0) == MVT::v1i1 && "Expected v1i1 type");
936
937 EVT VT = N->getValueType(0);
938 SDValue LHS = GetScalarizedVector(N->getOperand(0));
939 SDValue RHS = GetScalarizedVector(N->getOperand(1));
940
941 EVT OpVT = N->getOperand(0).getValueType();
942 EVT NVT = VT.getVectorElementType();
943 SDLoc DL(N);
944 // Turn it into a scalar SETCC.
945 SDValue Res = DAG.getNode(ISD::SETCC, DL, MVT::i1, LHS, RHS,
946 N->getOperand(2));
947
948 // Vectors may have a different boolean contents to scalars. Promote the
949 // value appropriately.
950 ISD::NodeType ExtendCode =
952
953 Res = DAG.getNode(ExtendCode, DL, NVT, Res);
954
955 return DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, VT, Res);
956}
957
958/// If the value to store is a vector that needs to be scalarized, it must be
959/// <1 x ty>. Just store the element.
960SDValue DAGTypeLegalizer::ScalarizeVecOp_STORE(StoreSDNode *N, unsigned OpNo){
961 assert(N->isUnindexed() && "Indexed store of one-element vector?");
962 assert(OpNo == 1 && "Do not know how to scalarize this operand!");
963 SDLoc dl(N);
964
965 if (N->isTruncatingStore())
966 return DAG.getTruncStore(
967 N->getChain(), dl, GetScalarizedVector(N->getOperand(1)),
968 N->getBasePtr(), N->getPointerInfo(),
969 N->getMemoryVT().getVectorElementType(), N->getOriginalAlign(),
970 N->getMemOperand()->getFlags(), N->getAAInfo());
971
972 return DAG.getStore(N->getChain(), dl, GetScalarizedVector(N->getOperand(1)),
973 N->getBasePtr(), N->getPointerInfo(),
974 N->getOriginalAlign(), N->getMemOperand()->getFlags(),
975 N->getAAInfo());
976}
977
978/// If the value to round is a vector that needs to be scalarized, it must be
979/// <1 x ty>. Convert the element instead.
980SDValue DAGTypeLegalizer::ScalarizeVecOp_FP_ROUND(SDNode *N, unsigned OpNo) {
981 assert(OpNo == 0 && "Wrong operand for scalarization!");
982 SDValue Elt = GetScalarizedVector(N->getOperand(0));
983 SDValue Res = DAG.getNode(ISD::FP_ROUND, SDLoc(N),
984 N->getValueType(0).getVectorElementType(), Elt,
985 N->getOperand(1));
986 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
987}
988
989SDValue DAGTypeLegalizer::ScalarizeVecOp_STRICT_FP_ROUND(SDNode *N,
990 unsigned OpNo) {
991 assert(OpNo == 1 && "Wrong operand for scalarization!");
992 SDValue Elt = GetScalarizedVector(N->getOperand(1));
994 { N->getValueType(0).getVectorElementType(),
995 MVT::Other },
996 { N->getOperand(0), Elt, N->getOperand(2) });
997 // Legalize the chain result - switch anything that used the old chain to
998 // use the new one.
999 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
1000
1001 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
1002
1003 // Do our own replacement and return SDValue() to tell the caller that we
1004 // handled all replacements since caller can only handle a single result.
1005 ReplaceValueWith(SDValue(N, 0), Res);
1006 return SDValue();
1007}
1008
1009/// If the value to extend is a vector that needs to be scalarized, it must be
1010/// <1 x ty>. Convert the element instead.
1011SDValue DAGTypeLegalizer::ScalarizeVecOp_FP_EXTEND(SDNode *N) {
1012 SDValue Elt = GetScalarizedVector(N->getOperand(0));
1013 SDValue Res = DAG.getNode(ISD::FP_EXTEND, SDLoc(N),
1014 N->getValueType(0).getVectorElementType(), Elt);
1015 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
1016}
1017
1018/// If the value to extend is a vector that needs to be scalarized, it must be
1019/// <1 x ty>. Convert the element instead.
1020SDValue DAGTypeLegalizer::ScalarizeVecOp_STRICT_FP_EXTEND(SDNode *N) {
1021 SDValue Elt = GetScalarizedVector(N->getOperand(1));
1022 SDValue Res =
1024 {N->getValueType(0).getVectorElementType(), MVT::Other},
1025 {N->getOperand(0), Elt});
1026 // Legalize the chain result - switch anything that used the old chain to
1027 // use the new one.
1028 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
1029
1030 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
1031
1032 // Do our own replacement and return SDValue() to tell the caller that we
1033 // handled all replacements since caller can only handle a single result.
1034 ReplaceValueWith(SDValue(N, 0), Res);
1035 return SDValue();
1036}
1037
1038SDValue DAGTypeLegalizer::ScalarizeVecOp_VECREDUCE(SDNode *N) {
1039 SDValue Res = GetScalarizedVector(N->getOperand(0));
1040 // Result type may be wider than element type.
1041 if (Res.getValueType() != N->getValueType(0))
1042 Res = DAG.getNode(ISD::ANY_EXTEND, SDLoc(N), N->getValueType(0), Res);
1043 return Res;
1044}
1045
1046SDValue DAGTypeLegalizer::ScalarizeVecOp_VECREDUCE_SEQ(SDNode *N) {
1047 SDValue AccOp = N->getOperand(0);
1048 SDValue VecOp = N->getOperand(1);
1049
1050 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(N->getOpcode());
1051
1052 SDValue Op = GetScalarizedVector(VecOp);
1053 return DAG.getNode(BaseOpc, SDLoc(N), N->getValueType(0),
1054 AccOp, Op, N->getFlags());
1055}
1056
1057SDValue DAGTypeLegalizer::ScalarizeVecOp_CMP(SDNode *N) {
1058 SDValue LHS = GetScalarizedVector(N->getOperand(0));
1059 SDValue RHS = GetScalarizedVector(N->getOperand(1));
1060
1061 EVT ResVT = N->getValueType(0).getVectorElementType();
1062 SDValue Cmp = DAG.getNode(N->getOpcode(), SDLoc(N), ResVT, LHS, RHS);
1063 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Cmp);
1064}
1065
1066//===----------------------------------------------------------------------===//
1067// Result Vector Splitting
1068//===----------------------------------------------------------------------===//
1069
1070/// This method is called when the specified result of the specified node is
1071/// found to need vector splitting. At this point, the node may also have
1072/// invalid operands or may have other results that need legalization, we just
1073/// know that (at least) one result needs vector splitting.
1074void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
1075 LLVM_DEBUG(dbgs() << "Split node result: "; N->dump(&DAG));
1076 SDValue Lo, Hi;
1077
1078 // See if the target wants to custom expand this node.
1079 if (CustomLowerNode(N, N->getValueType(ResNo), true))
1080 return;
1081
1082 switch (N->getOpcode()) {
1083 default:
1084#ifndef NDEBUG
1085 dbgs() << "SplitVectorResult #" << ResNo << ": ";
1086 N->dump(&DAG);
1087 dbgs() << "\n";
1088#endif
1089 report_fatal_error("Do not know how to split the result of this "
1090 "operator!\n");
1091
1092 case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, ResNo, Lo, Hi); break;
1093 case ISD::AssertZext: SplitVecRes_AssertZext(N, Lo, Hi); break;
1094 case ISD::VSELECT:
1095 case ISD::SELECT:
1096 case ISD::VP_MERGE:
1097 case ISD::VP_SELECT: SplitRes_Select(N, Lo, Hi); break;
1098 case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break;
1099 case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break;
1100 case ISD::BITCAST: SplitVecRes_BITCAST(N, Lo, Hi); break;
1101 case ISD::BUILD_VECTOR: SplitVecRes_BUILD_VECTOR(N, Lo, Hi); break;
1102 case ISD::CONCAT_VECTORS: SplitVecRes_CONCAT_VECTORS(N, Lo, Hi); break;
1103 case ISD::EXTRACT_SUBVECTOR: SplitVecRes_EXTRACT_SUBVECTOR(N, Lo, Hi); break;
1104 case ISD::INSERT_SUBVECTOR: SplitVecRes_INSERT_SUBVECTOR(N, Lo, Hi); break;
1105 case ISD::FPOWI:
1106 case ISD::FLDEXP:
1107 case ISD::FCOPYSIGN: SplitVecRes_FPOp_MultiType(N, Lo, Hi); break;
1108 case ISD::IS_FPCLASS: SplitVecRes_IS_FPCLASS(N, Lo, Hi); break;
1109 case ISD::INSERT_VECTOR_ELT: SplitVecRes_INSERT_VECTOR_ELT(N, Lo, Hi); break;
1110 case ISD::EXPERIMENTAL_VP_SPLAT: SplitVecRes_VP_SPLAT(N, Lo, Hi); break;
1111 case ISD::SPLAT_VECTOR:
1113 SplitVecRes_ScalarOp(N, Lo, Hi);
1114 break;
1115 case ISD::STEP_VECTOR:
1116 SplitVecRes_STEP_VECTOR(N, Lo, Hi);
1117 break;
1118 case ISD::SIGN_EXTEND_INREG: SplitVecRes_InregOp(N, Lo, Hi); break;
1119 case ISD::LOAD:
1120 SplitVecRes_LOAD(cast<LoadSDNode>(N), Lo, Hi);
1121 break;
1122 case ISD::VP_LOAD:
1123 SplitVecRes_VP_LOAD(cast<VPLoadSDNode>(N), Lo, Hi);
1124 break;
1125 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
1126 SplitVecRes_VP_STRIDED_LOAD(cast<VPStridedLoadSDNode>(N), Lo, Hi);
1127 break;
1128 case ISD::MLOAD:
1129 SplitVecRes_MLOAD(cast<MaskedLoadSDNode>(N), Lo, Hi);
1130 break;
1131 case ISD::MGATHER:
1132 case ISD::VP_GATHER:
1133 SplitVecRes_Gather(cast<MemSDNode>(N), Lo, Hi, /*SplitSETCC*/ true);
1134 break;
1136 SplitVecRes_VECTOR_COMPRESS(N, Lo, Hi);
1137 break;
1138 case ISD::SETCC:
1139 case ISD::VP_SETCC:
1140 SplitVecRes_SETCC(N, Lo, Hi);
1141 break;
1143 SplitVecRes_VECTOR_REVERSE(N, Lo, Hi);
1144 break;
1146 SplitVecRes_VECTOR_SHUFFLE(cast<ShuffleVectorSDNode>(N), Lo, Hi);
1147 break;
1148 case ISD::VECTOR_SPLICE:
1149 SplitVecRes_VECTOR_SPLICE(N, Lo, Hi);
1150 break;
1152 SplitVecRes_VECTOR_DEINTERLEAVE(N);
1153 return;
1155 SplitVecRes_VECTOR_INTERLEAVE(N);
1156 return;
1157 case ISD::VAARG:
1158 SplitVecRes_VAARG(N, Lo, Hi);
1159 break;
1160
1164 SplitVecRes_ExtVecInRegOp(N, Lo, Hi);
1165 break;
1166
1167 case ISD::ABS:
1168 case ISD::VP_ABS:
1169 case ISD::BITREVERSE:
1170 case ISD::VP_BITREVERSE:
1171 case ISD::BSWAP:
1172 case ISD::VP_BSWAP:
1173 case ISD::CTLZ:
1174 case ISD::VP_CTLZ:
1175 case ISD::CTTZ:
1176 case ISD::VP_CTTZ:
1178 case ISD::VP_CTLZ_ZERO_UNDEF:
1180 case ISD::VP_CTTZ_ZERO_UNDEF:
1181 case ISD::CTPOP:
1182 case ISD::VP_CTPOP:
1183 case ISD::FABS: case ISD::VP_FABS:
1184 case ISD::FACOS:
1185 case ISD::FASIN:
1186 case ISD::FATAN:
1187 case ISD::FCEIL:
1188 case ISD::VP_FCEIL:
1189 case ISD::FCOS:
1190 case ISD::FCOSH:
1191 case ISD::FEXP:
1192 case ISD::FEXP2:
1193 case ISD::FEXP10:
1194 case ISD::FFLOOR:
1195 case ISD::VP_FFLOOR:
1196 case ISD::FLOG:
1197 case ISD::FLOG10:
1198 case ISD::FLOG2:
1199 case ISD::FNEARBYINT:
1200 case ISD::VP_FNEARBYINT:
1201 case ISD::FNEG: case ISD::VP_FNEG:
1202 case ISD::FREEZE:
1203 case ISD::ARITH_FENCE:
1204 case ISD::FP_EXTEND:
1205 case ISD::VP_FP_EXTEND:
1206 case ISD::FP_ROUND:
1207 case ISD::VP_FP_ROUND:
1208 case ISD::FP_TO_SINT:
1209 case ISD::VP_FP_TO_SINT:
1210 case ISD::FP_TO_UINT:
1211 case ISD::VP_FP_TO_UINT:
1212 case ISD::FRINT:
1213 case ISD::VP_FRINT:
1214 case ISD::LRINT:
1215 case ISD::VP_LRINT:
1216 case ISD::LLRINT:
1217 case ISD::VP_LLRINT:
1218 case ISD::FROUND:
1219 case ISD::VP_FROUND:
1220 case ISD::FROUNDEVEN:
1221 case ISD::VP_FROUNDEVEN:
1222 case ISD::LROUND:
1223 case ISD::LLROUND:
1224 case ISD::FSIN:
1225 case ISD::FSINH:
1226 case ISD::FSQRT: case ISD::VP_SQRT:
1227 case ISD::FTAN:
1228 case ISD::FTANH:
1229 case ISD::FTRUNC:
1230 case ISD::VP_FROUNDTOZERO:
1231 case ISD::SINT_TO_FP:
1232 case ISD::VP_SINT_TO_FP:
1233 case ISD::TRUNCATE:
1234 case ISD::VP_TRUNCATE:
1235 case ISD::UINT_TO_FP:
1236 case ISD::VP_UINT_TO_FP:
1237 case ISD::FCANONICALIZE:
1238 SplitVecRes_UnaryOp(N, Lo, Hi);
1239 break;
1240 case ISD::ADDRSPACECAST:
1241 SplitVecRes_ADDRSPACECAST(N, Lo, Hi);
1242 break;
1243 case ISD::FFREXP:
1244 SplitVecRes_FFREXP(N, ResNo, Lo, Hi);
1245 break;
1246
1247 case ISD::ANY_EXTEND:
1248 case ISD::SIGN_EXTEND:
1249 case ISD::ZERO_EXTEND:
1250 case ISD::VP_SIGN_EXTEND:
1251 case ISD::VP_ZERO_EXTEND:
1252 SplitVecRes_ExtendOp(N, Lo, Hi);
1253 break;
1254
1255 case ISD::ADD: case ISD::VP_ADD:
1256 case ISD::SUB: case ISD::VP_SUB:
1257 case ISD::MUL: case ISD::VP_MUL:
1258 case ISD::MULHS:
1259 case ISD::MULHU:
1260 case ISD::ABDS:
1261 case ISD::ABDU:
1262 case ISD::AVGCEILS:
1263 case ISD::AVGCEILU:
1264 case ISD::AVGFLOORS:
1265 case ISD::AVGFLOORU:
1266 case ISD::FADD: case ISD::VP_FADD:
1267 case ISD::FSUB: case ISD::VP_FSUB:
1268 case ISD::FMUL: case ISD::VP_FMUL:
1269 case ISD::FMINNUM:
1270 case ISD::FMINNUM_IEEE:
1271 case ISD::VP_FMINNUM:
1272 case ISD::FMAXNUM:
1273 case ISD::FMAXNUM_IEEE:
1274 case ISD::VP_FMAXNUM:
1275 case ISD::FMINIMUM:
1276 case ISD::VP_FMINIMUM:
1277 case ISD::FMAXIMUM:
1278 case ISD::VP_FMAXIMUM:
1279 case ISD::SDIV: case ISD::VP_SDIV:
1280 case ISD::UDIV: case ISD::VP_UDIV:
1281 case ISD::FDIV: case ISD::VP_FDIV:
1282 case ISD::FPOW:
1283 case ISD::AND: case ISD::VP_AND:
1284 case ISD::OR: case ISD::VP_OR:
1285 case ISD::XOR: case ISD::VP_XOR:
1286 case ISD::SHL: case ISD::VP_SHL:
1287 case ISD::SRA: case ISD::VP_SRA:
1288 case ISD::SRL: case ISD::VP_SRL:
1289 case ISD::UREM: case ISD::VP_UREM:
1290 case ISD::SREM: case ISD::VP_SREM:
1291 case ISD::FREM: case ISD::VP_FREM:
1292 case ISD::SMIN: case ISD::VP_SMIN:
1293 case ISD::SMAX: case ISD::VP_SMAX:
1294 case ISD::UMIN: case ISD::VP_UMIN:
1295 case ISD::UMAX: case ISD::VP_UMAX:
1296 case ISD::SADDSAT: case ISD::VP_SADDSAT:
1297 case ISD::UADDSAT: case ISD::VP_UADDSAT:
1298 case ISD::SSUBSAT: case ISD::VP_SSUBSAT:
1299 case ISD::USUBSAT: case ISD::VP_USUBSAT:
1300 case ISD::SSHLSAT:
1301 case ISD::USHLSAT:
1302 case ISD::ROTL:
1303 case ISD::ROTR:
1304 case ISD::VP_FCOPYSIGN:
1305 SplitVecRes_BinOp(N, Lo, Hi);
1306 break;
1307 case ISD::FMA: case ISD::VP_FMA:
1308 case ISD::FSHL:
1309 case ISD::VP_FSHL:
1310 case ISD::FSHR:
1311 case ISD::VP_FSHR:
1312 SplitVecRes_TernaryOp(N, Lo, Hi);
1313 break;
1314
1315 case ISD::SCMP: case ISD::UCMP:
1316 SplitVecRes_CMP(N, Lo, Hi);
1317 break;
1318
1319#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
1320 case ISD::STRICT_##DAGN:
1321#include "llvm/IR/ConstrainedOps.def"
1322 SplitVecRes_StrictFPOp(N, Lo, Hi);
1323 break;
1324
1327 SplitVecRes_FP_TO_XINT_SAT(N, Lo, Hi);
1328 break;
1329
1330 case ISD::UADDO:
1331 case ISD::SADDO:
1332 case ISD::USUBO:
1333 case ISD::SSUBO:
1334 case ISD::UMULO:
1335 case ISD::SMULO:
1336 SplitVecRes_OverflowOp(N, ResNo, Lo, Hi);
1337 break;
1338 case ISD::SMULFIX:
1339 case ISD::SMULFIXSAT:
1340 case ISD::UMULFIX:
1341 case ISD::UMULFIXSAT:
1342 case ISD::SDIVFIX:
1343 case ISD::SDIVFIXSAT:
1344 case ISD::UDIVFIX:
1345 case ISD::UDIVFIXSAT:
1346 SplitVecRes_FIX(N, Lo, Hi);
1347 break;
1348 case ISD::EXPERIMENTAL_VP_REVERSE:
1349 SplitVecRes_VP_REVERSE(N, Lo, Hi);
1350 break;
1351 }
1352
1353 // If Lo/Hi is null, the sub-method took care of registering results etc.
1354 if (Lo.getNode())
1355 SetSplitVector(SDValue(N, ResNo), Lo, Hi);
1356}
1357
1358void DAGTypeLegalizer::IncrementPointer(MemSDNode *N, EVT MemVT,
1360 uint64_t *ScaledOffset) {
1361 SDLoc DL(N);
1362 unsigned IncrementSize = MemVT.getSizeInBits().getKnownMinValue() / 8;
1363
1364 if (MemVT.isScalableVector()) {
1366 SDValue BytesIncrement = DAG.getVScale(
1367 DL, Ptr.getValueType(),
1368 APInt(Ptr.getValueSizeInBits().getFixedValue(), IncrementSize));
1369 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
1370 Flags.setNoUnsignedWrap(true);
1371 if (ScaledOffset)
1372 *ScaledOffset += IncrementSize;
1373 Ptr = DAG.getNode(ISD::ADD, DL, Ptr.getValueType(), Ptr, BytesIncrement,
1374 Flags);
1375 } else {
1376 MPI = N->getPointerInfo().getWithOffset(IncrementSize);
1377 // Increment the pointer to the other half.
1378 Ptr = DAG.getObjectPtrOffset(DL, Ptr, TypeSize::getFixed(IncrementSize));
1379 }
1380}
1381
1382std::pair<SDValue, SDValue> DAGTypeLegalizer::SplitMask(SDValue Mask) {
1383 return SplitMask(Mask, SDLoc(Mask));
1384}
1385
1386std::pair<SDValue, SDValue> DAGTypeLegalizer::SplitMask(SDValue Mask,
1387 const SDLoc &DL) {
1388 SDValue MaskLo, MaskHi;
1389 EVT MaskVT = Mask.getValueType();
1390 if (getTypeAction(MaskVT) == TargetLowering::TypeSplitVector)
1391 GetSplitVector(Mask, MaskLo, MaskHi);
1392 else
1393 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
1394 return std::make_pair(MaskLo, MaskHi);
1395}
1396
1397void DAGTypeLegalizer::SplitVecRes_BinOp(SDNode *N, SDValue &Lo, SDValue &Hi) {
1398 SDValue LHSLo, LHSHi;
1399 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1400 SDValue RHSLo, RHSHi;
1401 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
1402 SDLoc dl(N);
1403
1404 const SDNodeFlags Flags = N->getFlags();
1405 unsigned Opcode = N->getOpcode();
1406 if (N->getNumOperands() == 2) {
1407 Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(), LHSLo, RHSLo, Flags);
1408 Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(), LHSHi, RHSHi, Flags);
1409 return;
1410 }
1411
1412 assert(N->getNumOperands() == 4 && "Unexpected number of operands!");
1413 assert(N->isVPOpcode() && "Expected VP opcode");
1414
1415 SDValue MaskLo, MaskHi;
1416 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(2));
1417
1418 SDValue EVLLo, EVLHi;
1419 std::tie(EVLLo, EVLHi) =
1420 DAG.SplitEVL(N->getOperand(3), N->getValueType(0), dl);
1421
1422 Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(),
1423 {LHSLo, RHSLo, MaskLo, EVLLo}, Flags);
1424 Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(),
1425 {LHSHi, RHSHi, MaskHi, EVLHi}, Flags);
1426}
1427
1428void DAGTypeLegalizer::SplitVecRes_TernaryOp(SDNode *N, SDValue &Lo,
1429 SDValue &Hi) {
1430 SDValue Op0Lo, Op0Hi;
1431 GetSplitVector(N->getOperand(0), Op0Lo, Op0Hi);
1432 SDValue Op1Lo, Op1Hi;
1433 GetSplitVector(N->getOperand(1), Op1Lo, Op1Hi);
1434 SDValue Op2Lo, Op2Hi;
1435 GetSplitVector(N->getOperand(2), Op2Lo, Op2Hi);
1436 SDLoc dl(N);
1437
1438 const SDNodeFlags Flags = N->getFlags();
1439 unsigned Opcode = N->getOpcode();
1440 if (N->getNumOperands() == 3) {
1441 Lo = DAG.getNode(Opcode, dl, Op0Lo.getValueType(), Op0Lo, Op1Lo, Op2Lo, Flags);
1442 Hi = DAG.getNode(Opcode, dl, Op0Hi.getValueType(), Op0Hi, Op1Hi, Op2Hi, Flags);
1443 return;
1444 }
1445
1446 assert(N->getNumOperands() == 5 && "Unexpected number of operands!");
1447 assert(N->isVPOpcode() && "Expected VP opcode");
1448
1449 SDValue MaskLo, MaskHi;
1450 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(3));
1451
1452 SDValue EVLLo, EVLHi;
1453 std::tie(EVLLo, EVLHi) =
1454 DAG.SplitEVL(N->getOperand(4), N->getValueType(0), dl);
1455
1456 Lo = DAG.getNode(Opcode, dl, Op0Lo.getValueType(),
1457 {Op0Lo, Op1Lo, Op2Lo, MaskLo, EVLLo}, Flags);
1458 Hi = DAG.getNode(Opcode, dl, Op0Hi.getValueType(),
1459 {Op0Hi, Op1Hi, Op2Hi, MaskHi, EVLHi}, Flags);
1460}
1461
1462void DAGTypeLegalizer::SplitVecRes_CMP(SDNode *N, SDValue &Lo, SDValue &Hi) {
1463 LLVMContext &Ctxt = *DAG.getContext();
1464 SDLoc dl(N);
1465
1466 SDValue LHS = N->getOperand(0);
1467 SDValue RHS = N->getOperand(1);
1468
1469 SDValue LHSLo, LHSHi, RHSLo, RHSHi;
1470 if (getTypeAction(LHS.getValueType()) == TargetLowering::TypeSplitVector) {
1471 GetSplitVector(LHS, LHSLo, LHSHi);
1472 GetSplitVector(RHS, RHSLo, RHSHi);
1473 } else {
1474 std::tie(LHSLo, LHSHi) = DAG.SplitVector(LHS, dl);
1475 std::tie(RHSLo, RHSHi) = DAG.SplitVector(RHS, dl);
1476 }
1477
1478 EVT SplitResVT = N->getValueType(0).getHalfNumVectorElementsVT(Ctxt);
1479 Lo = DAG.getNode(N->getOpcode(), dl, SplitResVT, LHSLo, RHSLo);
1480 Hi = DAG.getNode(N->getOpcode(), dl, SplitResVT, LHSHi, RHSHi);
1481}
1482
1483void DAGTypeLegalizer::SplitVecRes_FIX(SDNode *N, SDValue &Lo, SDValue &Hi) {
1484 SDValue LHSLo, LHSHi;
1485 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1486 SDValue RHSLo, RHSHi;
1487 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
1488 SDLoc dl(N);
1489 SDValue Op2 = N->getOperand(2);
1490
1491 unsigned Opcode = N->getOpcode();
1492 Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(), LHSLo, RHSLo, Op2,
1493 N->getFlags());
1494 Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(), LHSHi, RHSHi, Op2,
1495 N->getFlags());
1496}
1497
1498void DAGTypeLegalizer::SplitVecRes_BITCAST(SDNode *N, SDValue &Lo,
1499 SDValue &Hi) {
1500 // We know the result is a vector. The input may be either a vector or a
1501 // scalar value.
1502 EVT LoVT, HiVT;
1503 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1504 SDLoc dl(N);
1505
1506 SDValue InOp = N->getOperand(0);
1507 EVT InVT = InOp.getValueType();
1508
1509 // Handle some special cases efficiently.
1510 switch (getTypeAction(InVT)) {
1518 break;
1521 // A scalar to vector conversion, where the scalar needs expansion.
1522 // If the vector is being split in two then we can just convert the
1523 // expanded pieces.
1524 if (LoVT == HiVT) {
1525 GetExpandedOp(InOp, Lo, Hi);
1526 if (DAG.getDataLayout().isBigEndian())
1527 std::swap(Lo, Hi);
1528 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
1529 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
1530 return;
1531 }
1532 break;
1534 // If the input is a vector that needs to be split, convert each split
1535 // piece of the input now.
1536 GetSplitVector(InOp, Lo, Hi);
1537 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
1538 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
1539 return;
1541 report_fatal_error("Scalarization of scalable vectors is not supported.");
1542 }
1543
1544 if (LoVT.isScalableVector()) {
1545 auto [InLo, InHi] = DAG.SplitVectorOperand(N, 0);
1546 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, InLo);
1547 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, InHi);
1548 return;
1549 }
1550
1551 // In the general case, convert the input to an integer and split it by hand.
1552 EVT LoIntVT = EVT::getIntegerVT(*DAG.getContext(), LoVT.getSizeInBits());
1553 EVT HiIntVT = EVT::getIntegerVT(*DAG.getContext(), HiVT.getSizeInBits());
1554 if (DAG.getDataLayout().isBigEndian())
1555 std::swap(LoIntVT, HiIntVT);
1556
1557 SplitInteger(BitConvertToInteger(InOp), LoIntVT, HiIntVT, Lo, Hi);
1558
1559 if (DAG.getDataLayout().isBigEndian())
1560 std::swap(Lo, Hi);
1561 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
1562 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
1563}
1564
1565void DAGTypeLegalizer::SplitVecRes_BUILD_VECTOR(SDNode *N, SDValue &Lo,
1566 SDValue &Hi) {
1567 EVT LoVT, HiVT;
1568 SDLoc dl(N);
1569 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1570 unsigned LoNumElts = LoVT.getVectorNumElements();
1571 SmallVector<SDValue, 8> LoOps(N->op_begin(), N->op_begin()+LoNumElts);
1572 Lo = DAG.getBuildVector(LoVT, dl, LoOps);
1573
1574 SmallVector<SDValue, 8> HiOps(N->op_begin()+LoNumElts, N->op_end());
1575 Hi = DAG.getBuildVector(HiVT, dl, HiOps);
1576}
1577
1578void DAGTypeLegalizer::SplitVecRes_CONCAT_VECTORS(SDNode *N, SDValue &Lo,
1579 SDValue &Hi) {
1580 assert(!(N->getNumOperands() & 1) && "Unsupported CONCAT_VECTORS");
1581 SDLoc dl(N);
1582 unsigned NumSubvectors = N->getNumOperands() / 2;
1583 if (NumSubvectors == 1) {
1584 Lo = N->getOperand(0);
1585 Hi = N->getOperand(1);
1586 return;
1587 }
1588
1589 EVT LoVT, HiVT;
1590 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1591
1592 SmallVector<SDValue, 8> LoOps(N->op_begin(), N->op_begin()+NumSubvectors);
1593 Lo = DAG.getNode(ISD::CONCAT_VECTORS, dl, LoVT, LoOps);
1594
1595 SmallVector<SDValue, 8> HiOps(N->op_begin()+NumSubvectors, N->op_end());
1596 Hi = DAG.getNode(ISD::CONCAT_VECTORS, dl, HiVT, HiOps);
1597}
1598
1599void DAGTypeLegalizer::SplitVecRes_EXTRACT_SUBVECTOR(SDNode *N, SDValue &Lo,
1600 SDValue &Hi) {
1601 SDValue Vec = N->getOperand(0);
1602 SDValue Idx = N->getOperand(1);
1603 SDLoc dl(N);
1604
1605 EVT LoVT, HiVT;
1606 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1607
1608 Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, LoVT, Vec, Idx);
1609 uint64_t IdxVal = Idx->getAsZExtVal();
1610 Hi = DAG.getNode(
1611 ISD::EXTRACT_SUBVECTOR, dl, HiVT, Vec,
1612 DAG.getVectorIdxConstant(IdxVal + LoVT.getVectorMinNumElements(), dl));
1613}
1614
1615void DAGTypeLegalizer::SplitVecRes_INSERT_SUBVECTOR(SDNode *N, SDValue &Lo,
1616 SDValue &Hi) {
1617 SDValue Vec = N->getOperand(0);
1618 SDValue SubVec = N->getOperand(1);
1619 SDValue Idx = N->getOperand(2);
1620 SDLoc dl(N);
1621 GetSplitVector(Vec, Lo, Hi);
1622
1623 EVT VecVT = Vec.getValueType();
1624 EVT LoVT = Lo.getValueType();
1625 EVT SubVecVT = SubVec.getValueType();
1626 unsigned VecElems = VecVT.getVectorMinNumElements();
1627 unsigned SubElems = SubVecVT.getVectorMinNumElements();
1628 unsigned LoElems = LoVT.getVectorMinNumElements();
1629
1630 // If we know the index is in the first half, and we know the subvector
1631 // doesn't cross the boundary between the halves, we can avoid spilling the
1632 // vector, and insert into the lower half of the split vector directly.
1633 unsigned IdxVal = Idx->getAsZExtVal();
1634 if (IdxVal + SubElems <= LoElems) {
1635 Lo = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, LoVT, Lo, SubVec, Idx);
1636 return;
1637 }
1638 // Similarly if the subvector is fully in the high half, but mind that we
1639 // can't tell whether a fixed-length subvector is fully within the high half
1640 // of a scalable vector.
1641 if (VecVT.isScalableVector() == SubVecVT.isScalableVector() &&
1642 IdxVal >= LoElems && IdxVal + SubElems <= VecElems) {
1643 Hi = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, Hi.getValueType(), Hi, SubVec,
1644 DAG.getVectorIdxConstant(IdxVal - LoElems, dl));
1645 return;
1646 }
1647
1648 // Spill the vector to the stack.
1649 // In cases where the vector is illegal it will be broken down into parts
1650 // and stored in parts - we should use the alignment for the smallest part.
1651 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
1653 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
1654 auto &MF = DAG.getMachineFunction();
1655 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
1656 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
1657
1658 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
1659 SmallestAlign);
1660
1661 // Store the new subvector into the specified index.
1662 SDValue SubVecPtr =
1663 TLI.getVectorSubVecPointer(DAG, StackPtr, VecVT, SubVecVT, Idx);
1664 Store = DAG.getStore(Store, dl, SubVec, SubVecPtr,
1666
1667 // Load the Lo part from the stack slot.
1668 Lo = DAG.getLoad(Lo.getValueType(), dl, Store, StackPtr, PtrInfo,
1669 SmallestAlign);
1670
1671 // Increment the pointer to the other part.
1672 auto *Load = cast<LoadSDNode>(Lo);
1673 MachinePointerInfo MPI = Load->getPointerInfo();
1674 IncrementPointer(Load, LoVT, MPI, StackPtr);
1675
1676 // Load the Hi part from the stack slot.
1677 Hi = DAG.getLoad(Hi.getValueType(), dl, Store, StackPtr, MPI, SmallestAlign);
1678}
1679
1680// Handle splitting an FP where the second operand does not match the first
1681// type. The second operand may be a scalar, or a vector that has exactly as
1682// many elements as the first
1683void DAGTypeLegalizer::SplitVecRes_FPOp_MultiType(SDNode *N, SDValue &Lo,
1684 SDValue &Hi) {
1685 SDValue LHSLo, LHSHi;
1686 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1687 SDLoc DL(N);
1688
1689 SDValue RHSLo, RHSHi;
1690 SDValue RHS = N->getOperand(1);
1691 EVT RHSVT = RHS.getValueType();
1692 if (RHSVT.isVector()) {
1693 if (getTypeAction(RHSVT) == TargetLowering::TypeSplitVector)
1694 GetSplitVector(RHS, RHSLo, RHSHi);
1695 else
1696 std::tie(RHSLo, RHSHi) = DAG.SplitVector(RHS, SDLoc(RHS));
1697
1698 Lo = DAG.getNode(N->getOpcode(), DL, LHSLo.getValueType(), LHSLo, RHSLo);
1699 Hi = DAG.getNode(N->getOpcode(), DL, LHSHi.getValueType(), LHSHi, RHSHi);
1700 } else {
1701 Lo = DAG.getNode(N->getOpcode(), DL, LHSLo.getValueType(), LHSLo, RHS);
1702 Hi = DAG.getNode(N->getOpcode(), DL, LHSHi.getValueType(), LHSHi, RHS);
1703 }
1704}
1705
1706void DAGTypeLegalizer::SplitVecRes_IS_FPCLASS(SDNode *N, SDValue &Lo,
1707 SDValue &Hi) {
1708 SDLoc DL(N);
1709 SDValue ArgLo, ArgHi;
1710 SDValue Test = N->getOperand(1);
1711 SDValue FpValue = N->getOperand(0);
1712 if (getTypeAction(FpValue.getValueType()) == TargetLowering::TypeSplitVector)
1713 GetSplitVector(FpValue, ArgLo, ArgHi);
1714 else
1715 std::tie(ArgLo, ArgHi) = DAG.SplitVector(FpValue, SDLoc(FpValue));
1716 EVT LoVT, HiVT;
1717 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1718
1719 Lo = DAG.getNode(ISD::IS_FPCLASS, DL, LoVT, ArgLo, Test, N->getFlags());
1720 Hi = DAG.getNode(ISD::IS_FPCLASS, DL, HiVT, ArgHi, Test, N->getFlags());
1721}
1722
1723void DAGTypeLegalizer::SplitVecRes_InregOp(SDNode *N, SDValue &Lo,
1724 SDValue &Hi) {
1725 SDValue LHSLo, LHSHi;
1726 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1727 SDLoc dl(N);
1728
1729 EVT LoVT, HiVT;
1730 std::tie(LoVT, HiVT) =
1731 DAG.GetSplitDestVTs(cast<VTSDNode>(N->getOperand(1))->getVT());
1732
1733 Lo = DAG.getNode(N->getOpcode(), dl, LHSLo.getValueType(), LHSLo,
1734 DAG.getValueType(LoVT));
1735 Hi = DAG.getNode(N->getOpcode(), dl, LHSHi.getValueType(), LHSHi,
1736 DAG.getValueType(HiVT));
1737}
1738
1739void DAGTypeLegalizer::SplitVecRes_ExtVecInRegOp(SDNode *N, SDValue &Lo,
1740 SDValue &Hi) {
1741 unsigned Opcode = N->getOpcode();
1742 SDValue N0 = N->getOperand(0);
1743
1744 SDLoc dl(N);
1745 SDValue InLo, InHi;
1746
1747 if (getTypeAction(N0.getValueType()) == TargetLowering::TypeSplitVector)
1748 GetSplitVector(N0, InLo, InHi);
1749 else
1750 std::tie(InLo, InHi) = DAG.SplitVectorOperand(N, 0);
1751
1752 EVT InLoVT = InLo.getValueType();
1753 unsigned InNumElements = InLoVT.getVectorNumElements();
1754
1755 EVT OutLoVT, OutHiVT;
1756 std::tie(OutLoVT, OutHiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1757 unsigned OutNumElements = OutLoVT.getVectorNumElements();
1758 assert((2 * OutNumElements) <= InNumElements &&
1759 "Illegal extend vector in reg split");
1760
1761 // *_EXTEND_VECTOR_INREG instructions extend the lowest elements of the
1762 // input vector (i.e. we only use InLo):
1763 // OutLo will extend the first OutNumElements from InLo.
1764 // OutHi will extend the next OutNumElements from InLo.
1765
1766 // Shuffle the elements from InLo for OutHi into the bottom elements to
1767 // create a 'fake' InHi.
1768 SmallVector<int, 8> SplitHi(InNumElements, -1);
1769 for (unsigned i = 0; i != OutNumElements; ++i)
1770 SplitHi[i] = i + OutNumElements;
1771 InHi = DAG.getVectorShuffle(InLoVT, dl, InLo, DAG.getUNDEF(InLoVT), SplitHi);
1772
1773 Lo = DAG.getNode(Opcode, dl, OutLoVT, InLo);
1774 Hi = DAG.getNode(Opcode, dl, OutHiVT, InHi);
1775}
1776
1777void DAGTypeLegalizer::SplitVecRes_StrictFPOp(SDNode *N, SDValue &Lo,
1778 SDValue &Hi) {
1779 unsigned NumOps = N->getNumOperands();
1780 SDValue Chain = N->getOperand(0);
1781 EVT LoVT, HiVT;
1782 SDLoc dl(N);
1783 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1784
1785 SmallVector<SDValue, 4> OpsLo(NumOps);
1786 SmallVector<SDValue, 4> OpsHi(NumOps);
1787
1788 // The Chain is the first operand.
1789 OpsLo[0] = Chain;
1790 OpsHi[0] = Chain;
1791
1792 // Now process the remaining operands.
1793 for (unsigned i = 1; i < NumOps; ++i) {
1794 SDValue Op = N->getOperand(i);
1795 SDValue OpLo = Op;
1796 SDValue OpHi = Op;
1797
1798 EVT InVT = Op.getValueType();
1799 if (InVT.isVector()) {
1800 // If the input also splits, handle it directly for a
1801 // compile time speedup. Otherwise split it by hand.
1802 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
1803 GetSplitVector(Op, OpLo, OpHi);
1804 else
1805 std::tie(OpLo, OpHi) = DAG.SplitVectorOperand(N, i);
1806 }
1807
1808 OpsLo[i] = OpLo;
1809 OpsHi[i] = OpHi;
1810 }
1811
1812 EVT LoValueVTs[] = {LoVT, MVT::Other};
1813 EVT HiValueVTs[] = {HiVT, MVT::Other};
1814 Lo = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(LoValueVTs), OpsLo,
1815 N->getFlags());
1816 Hi = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(HiValueVTs), OpsHi,
1817 N->getFlags());
1818
1819 // Build a factor node to remember that this Op is independent of the
1820 // other one.
1821 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
1822 Lo.getValue(1), Hi.getValue(1));
1823
1824 // Legalize the chain result - switch anything that used the old chain to
1825 // use the new one.
1826 ReplaceValueWith(SDValue(N, 1), Chain);
1827}
1828
1829SDValue DAGTypeLegalizer::UnrollVectorOp_StrictFP(SDNode *N, unsigned ResNE) {
1830 SDValue Chain = N->getOperand(0);
1831 EVT VT = N->getValueType(0);
1832 unsigned NE = VT.getVectorNumElements();
1833 EVT EltVT = VT.getVectorElementType();
1834 SDLoc dl(N);
1835
1837 SmallVector<SDValue, 4> Operands(N->getNumOperands());
1838
1839 // If ResNE is 0, fully unroll the vector op.
1840 if (ResNE == 0)
1841 ResNE = NE;
1842 else if (NE > ResNE)
1843 NE = ResNE;
1844
1845 //The results of each unrolled operation, including the chain.
1846 EVT ChainVTs[] = {EltVT, MVT::Other};
1848
1849 unsigned i;
1850 for (i = 0; i != NE; ++i) {
1851 Operands[0] = Chain;
1852 for (unsigned j = 1, e = N->getNumOperands(); j != e; ++j) {
1853 SDValue Operand = N->getOperand(j);
1854 EVT OperandVT = Operand.getValueType();
1855 if (OperandVT.isVector()) {
1856 EVT OperandEltVT = OperandVT.getVectorElementType();
1857 Operands[j] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, OperandEltVT,
1858 Operand, DAG.getVectorIdxConstant(i, dl));
1859 } else {
1860 Operands[j] = Operand;
1861 }
1862 }
1863 SDValue Scalar = DAG.getNode(N->getOpcode(), dl, ChainVTs, Operands);
1864 Scalar.getNode()->setFlags(N->getFlags());
1865
1866 //Add in the scalar as well as its chain value to the
1867 //result vectors.
1868 Scalars.push_back(Scalar);
1869 Chains.push_back(Scalar.getValue(1));
1870 }
1871
1872 for (; i < ResNE; ++i)
1873 Scalars.push_back(DAG.getUNDEF(EltVT));
1874
1875 // Build a new factor node to connect the chain back together.
1876 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
1877 ReplaceValueWith(SDValue(N, 1), Chain);
1878
1879 // Create a new BUILD_VECTOR node
1880 EVT VecVT = EVT::getVectorVT(*DAG.getContext(), EltVT, ResNE);
1881 return DAG.getBuildVector(VecVT, dl, Scalars);
1882}
1883
1884void DAGTypeLegalizer::SplitVecRes_OverflowOp(SDNode *N, unsigned ResNo,
1885 SDValue &Lo, SDValue &Hi) {
1886 SDLoc dl(N);
1887 EVT ResVT = N->getValueType(0);
1888 EVT OvVT = N->getValueType(1);
1889 EVT LoResVT, HiResVT, LoOvVT, HiOvVT;
1890 std::tie(LoResVT, HiResVT) = DAG.GetSplitDestVTs(ResVT);
1891 std::tie(LoOvVT, HiOvVT) = DAG.GetSplitDestVTs(OvVT);
1892
1893 SDValue LoLHS, HiLHS, LoRHS, HiRHS;
1894 if (getTypeAction(ResVT) == TargetLowering::TypeSplitVector) {
1895 GetSplitVector(N->getOperand(0), LoLHS, HiLHS);
1896 GetSplitVector(N->getOperand(1), LoRHS, HiRHS);
1897 } else {
1898 std::tie(LoLHS, HiLHS) = DAG.SplitVectorOperand(N, 0);
1899 std::tie(LoRHS, HiRHS) = DAG.SplitVectorOperand(N, 1);
1900 }
1901
1902 unsigned Opcode = N->getOpcode();
1903 SDVTList LoVTs = DAG.getVTList(LoResVT, LoOvVT);
1904 SDVTList HiVTs = DAG.getVTList(HiResVT, HiOvVT);
1905 SDNode *LoNode = DAG.getNode(Opcode, dl, LoVTs, LoLHS, LoRHS).getNode();
1906 SDNode *HiNode = DAG.getNode(Opcode, dl, HiVTs, HiLHS, HiRHS).getNode();
1907 LoNode->setFlags(N->getFlags());
1908 HiNode->setFlags(N->getFlags());
1909
1910 Lo = SDValue(LoNode, ResNo);
1911 Hi = SDValue(HiNode, ResNo);
1912
1913 // Replace the other vector result not being explicitly split here.
1914 unsigned OtherNo = 1 - ResNo;
1915 EVT OtherVT = N->getValueType(OtherNo);
1916 if (getTypeAction(OtherVT) == TargetLowering::TypeSplitVector) {
1917 SetSplitVector(SDValue(N, OtherNo),
1918 SDValue(LoNode, OtherNo), SDValue(HiNode, OtherNo));
1919 } else {
1920 SDValue OtherVal = DAG.getNode(
1921 ISD::CONCAT_VECTORS, dl, OtherVT,
1922 SDValue(LoNode, OtherNo), SDValue(HiNode, OtherNo));
1923 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
1924 }
1925}
1926
1927void DAGTypeLegalizer::SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo,
1928 SDValue &Hi) {
1929 SDValue Vec = N->getOperand(0);
1930 SDValue Elt = N->getOperand(1);
1931 SDValue Idx = N->getOperand(2);
1932 SDLoc dl(N);
1933 GetSplitVector(Vec, Lo, Hi);
1934
1935 if (ConstantSDNode *CIdx = dyn_cast<ConstantSDNode>(Idx)) {
1936 unsigned IdxVal = CIdx->getZExtValue();
1937 unsigned LoNumElts = Lo.getValueType().getVectorMinNumElements();
1938 if (IdxVal < LoNumElts) {
1940 Lo.getValueType(), Lo, Elt, Idx);
1941 return;
1942 } else if (!Vec.getValueType().isScalableVector()) {
1943 Hi = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, Hi.getValueType(), Hi, Elt,
1944 DAG.getVectorIdxConstant(IdxVal - LoNumElts, dl));
1945 return;
1946 }
1947 }
1948
1949 // Make the vector elements byte-addressable if they aren't already.
1950 EVT VecVT = Vec.getValueType();
1951 EVT EltVT = VecVT.getVectorElementType();
1952 if (!EltVT.isByteSized()) {
1953 EltVT = EltVT.changeTypeToInteger().getRoundIntegerType(*DAG.getContext());
1954 VecVT = VecVT.changeElementType(EltVT);
1955 Vec = DAG.getNode(ISD::ANY_EXTEND, dl, VecVT, Vec);
1956 // Extend the element type to match if needed.
1957 if (EltVT.bitsGT(Elt.getValueType()))
1958 Elt = DAG.getNode(ISD::ANY_EXTEND, dl, EltVT, Elt);
1959 }
1960
1961 // Spill the vector to the stack.
1962 // In cases where the vector is illegal it will be broken down into parts
1963 // and stored in parts - we should use the alignment for the smallest part.
1964 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
1966 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
1967 auto &MF = DAG.getMachineFunction();
1968 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
1969 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
1970
1971 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
1972 SmallestAlign);
1973
1974 // Store the new element. This may be larger than the vector element type,
1975 // so use a truncating store.
1976 SDValue EltPtr = TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Idx);
1977 Store = DAG.getTruncStore(
1978 Store, dl, Elt, EltPtr, MachinePointerInfo::getUnknownStack(MF), EltVT,
1979 commonAlignment(SmallestAlign,
1980 EltVT.getFixedSizeInBits() / 8));
1981
1982 EVT LoVT, HiVT;
1983 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(VecVT);
1984
1985 // Load the Lo part from the stack slot.
1986 Lo = DAG.getLoad(LoVT, dl, Store, StackPtr, PtrInfo, SmallestAlign);
1987
1988 // Increment the pointer to the other part.
1989 auto Load = cast<LoadSDNode>(Lo);
1990 MachinePointerInfo MPI = Load->getPointerInfo();
1991 IncrementPointer(Load, LoVT, MPI, StackPtr);
1992
1993 Hi = DAG.getLoad(HiVT, dl, Store, StackPtr, MPI, SmallestAlign);
1994
1995 // If we adjusted the original type, we need to truncate the results.
1996 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1997 if (LoVT != Lo.getValueType())
1998 Lo = DAG.getNode(ISD::TRUNCATE, dl, LoVT, Lo);
1999 if (HiVT != Hi.getValueType())
2000 Hi = DAG.getNode(ISD::TRUNCATE, dl, HiVT, Hi);
2001}
2002
2003void DAGTypeLegalizer::SplitVecRes_STEP_VECTOR(SDNode *N, SDValue &Lo,
2004 SDValue &Hi) {
2005 EVT LoVT, HiVT;
2006 SDLoc dl(N);
2007 assert(N->getValueType(0).isScalableVector() &&
2008 "Only scalable vectors are supported for STEP_VECTOR");
2009 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2010 SDValue Step = N->getOperand(0);
2011
2012 Lo = DAG.getNode(ISD::STEP_VECTOR, dl, LoVT, Step);
2013
2014 // Hi = Lo + (EltCnt * Step)
2015 EVT EltVT = Step.getValueType();
2016 APInt StepVal = Step->getAsAPIntVal();
2017 SDValue StartOfHi =
2018 DAG.getVScale(dl, EltVT, StepVal * LoVT.getVectorMinNumElements());
2019 StartOfHi = DAG.getSExtOrTrunc(StartOfHi, dl, HiVT.getVectorElementType());
2020 StartOfHi = DAG.getNode(ISD::SPLAT_VECTOR, dl, HiVT, StartOfHi);
2021
2022 Hi = DAG.getNode(ISD::STEP_VECTOR, dl, HiVT, Step);
2023 Hi = DAG.getNode(ISD::ADD, dl, HiVT, Hi, StartOfHi);
2024}
2025
2026void DAGTypeLegalizer::SplitVecRes_ScalarOp(SDNode *N, SDValue &Lo,
2027 SDValue &Hi) {
2028 EVT LoVT, HiVT;
2029 SDLoc dl(N);
2030 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2031 Lo = DAG.getNode(N->getOpcode(), dl, LoVT, N->getOperand(0));
2032 if (N->getOpcode() == ISD::SCALAR_TO_VECTOR) {
2033 Hi = DAG.getUNDEF(HiVT);
2034 } else {
2035 assert(N->getOpcode() == ISD::SPLAT_VECTOR && "Unexpected opcode");
2036 Hi = Lo;
2037 }
2038}
2039
2040void DAGTypeLegalizer::SplitVecRes_VP_SPLAT(SDNode *N, SDValue &Lo,
2041 SDValue &Hi) {
2042 SDLoc dl(N);
2043 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(N->getValueType(0));
2044 auto [MaskLo, MaskHi] = SplitMask(N->getOperand(1));
2045 auto [EVLLo, EVLHi] = DAG.SplitEVL(N->getOperand(2), N->getValueType(0), dl);
2046 Lo = DAG.getNode(N->getOpcode(), dl, LoVT, N->getOperand(0), MaskLo, EVLLo);
2047 Hi = DAG.getNode(N->getOpcode(), dl, HiVT, N->getOperand(0), MaskHi, EVLHi);
2048}
2049
2050void DAGTypeLegalizer::SplitVecRes_LOAD(LoadSDNode *LD, SDValue &Lo,
2051 SDValue &Hi) {
2052 assert(ISD::isUNINDEXEDLoad(LD) && "Indexed load during type legalization!");
2053 EVT LoVT, HiVT;
2054 SDLoc dl(LD);
2055 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(LD->getValueType(0));
2056
2057 ISD::LoadExtType ExtType = LD->getExtensionType();
2058 SDValue Ch = LD->getChain();
2059 SDValue Ptr = LD->getBasePtr();
2060 SDValue Offset = DAG.getUNDEF(Ptr.getValueType());
2061 EVT MemoryVT = LD->getMemoryVT();
2062 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
2063 AAMDNodes AAInfo = LD->getAAInfo();
2064
2065 EVT LoMemVT, HiMemVT;
2066 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
2067
2068 if (!LoMemVT.isByteSized() || !HiMemVT.isByteSized()) {
2069 SDValue Value, NewChain;
2070 std::tie(Value, NewChain) = TLI.scalarizeVectorLoad(LD, DAG);
2071 std::tie(Lo, Hi) = DAG.SplitVector(Value, dl);
2072 ReplaceValueWith(SDValue(LD, 1), NewChain);
2073 return;
2074 }
2075
2076 Lo = DAG.getLoad(ISD::UNINDEXED, ExtType, LoVT, dl, Ch, Ptr, Offset,
2077 LD->getPointerInfo(), LoMemVT, LD->getOriginalAlign(),
2078 MMOFlags, AAInfo);
2079
2081 IncrementPointer(LD, LoMemVT, MPI, Ptr);
2082
2083 Hi = DAG.getLoad(ISD::UNINDEXED, ExtType, HiVT, dl, Ch, Ptr, Offset, MPI,
2084 HiMemVT, LD->getOriginalAlign(), MMOFlags, AAInfo);
2085
2086 // Build a factor node to remember that this load is independent of the
2087 // other one.
2088 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2089 Hi.getValue(1));
2090
2091 // Legalize the chain result - switch anything that used the old chain to
2092 // use the new one.
2093 ReplaceValueWith(SDValue(LD, 1), Ch);
2094}
2095
2096void DAGTypeLegalizer::SplitVecRes_VP_LOAD(VPLoadSDNode *LD, SDValue &Lo,
2097 SDValue &Hi) {
2098 assert(LD->isUnindexed() && "Indexed VP load during type legalization!");
2099 EVT LoVT, HiVT;
2100 SDLoc dl(LD);
2101 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(LD->getValueType(0));
2102
2103 ISD::LoadExtType ExtType = LD->getExtensionType();
2104 SDValue Ch = LD->getChain();
2105 SDValue Ptr = LD->getBasePtr();
2106 SDValue Offset = LD->getOffset();
2107 assert(Offset.isUndef() && "Unexpected indexed variable-length load offset");
2108 Align Alignment = LD->getOriginalAlign();
2109 SDValue Mask = LD->getMask();
2110 SDValue EVL = LD->getVectorLength();
2111 EVT MemoryVT = LD->getMemoryVT();
2112
2113 EVT LoMemVT, HiMemVT;
2114 bool HiIsEmpty = false;
2115 std::tie(LoMemVT, HiMemVT) =
2116 DAG.GetDependentSplitDestVTs(MemoryVT, LoVT, &HiIsEmpty);
2117
2118 // Split Mask operand
2119 SDValue MaskLo, MaskHi;
2120 if (Mask.getOpcode() == ISD::SETCC) {
2121 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
2122 } else {
2123 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
2124 GetSplitVector(Mask, MaskLo, MaskHi);
2125 else
2126 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, dl);
2127 }
2128
2129 // Split EVL operand
2130 SDValue EVLLo, EVLHi;
2131 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(EVL, LD->getValueType(0), dl);
2132
2134 LD->getPointerInfo(), MachineMemOperand::MOLoad,
2135 LocationSize::beforeOrAfterPointer(), Alignment, LD->getAAInfo(),
2136 LD->getRanges());
2137
2138 Lo =
2139 DAG.getLoadVP(LD->getAddressingMode(), ExtType, LoVT, dl, Ch, Ptr, Offset,
2140 MaskLo, EVLLo, LoMemVT, MMO, LD->isExpandingLoad());
2141
2142 if (HiIsEmpty) {
2143 // The hi vp_load has zero storage size. We therefore simply set it to
2144 // the low vp_load and rely on subsequent removal from the chain.
2145 Hi = Lo;
2146 } else {
2147 // Generate hi vp_load.
2148 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, dl, LoMemVT, DAG,
2149 LD->isExpandingLoad());
2150
2152 if (LoMemVT.isScalableVector())
2153 MPI = MachinePointerInfo(LD->getPointerInfo().getAddrSpace());
2154 else
2155 MPI = LD->getPointerInfo().getWithOffset(
2156 LoMemVT.getStoreSize().getFixedValue());
2157
2160 Alignment, LD->getAAInfo(), LD->getRanges());
2161
2162 Hi = DAG.getLoadVP(LD->getAddressingMode(), ExtType, HiVT, dl, Ch, Ptr,
2163 Offset, MaskHi, EVLHi, HiMemVT, MMO,
2164 LD->isExpandingLoad());
2165 }
2166
2167 // Build a factor node to remember that this load is independent of the
2168 // other one.
2169 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2170 Hi.getValue(1));
2171
2172 // Legalize the chain result - switch anything that used the old chain to
2173 // use the new one.
2174 ReplaceValueWith(SDValue(LD, 1), Ch);
2175}
2176
2177void DAGTypeLegalizer::SplitVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode *SLD,
2178 SDValue &Lo, SDValue &Hi) {
2179 assert(SLD->isUnindexed() &&
2180 "Indexed VP strided load during type legalization!");
2181 assert(SLD->getOffset().isUndef() &&
2182 "Unexpected indexed variable-length load offset");
2183
2184 SDLoc DL(SLD);
2185
2186 EVT LoVT, HiVT;
2187 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(SLD->getValueType(0));
2188
2189 EVT LoMemVT, HiMemVT;
2190 bool HiIsEmpty = false;
2191 std::tie(LoMemVT, HiMemVT) =
2192 DAG.GetDependentSplitDestVTs(SLD->getMemoryVT(), LoVT, &HiIsEmpty);
2193
2194 SDValue Mask = SLD->getMask();
2195 SDValue LoMask, HiMask;
2196 if (Mask.getOpcode() == ISD::SETCC) {
2197 SplitVecRes_SETCC(Mask.getNode(), LoMask, HiMask);
2198 } else {
2199 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
2200 GetSplitVector(Mask, LoMask, HiMask);
2201 else
2202 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
2203 }
2204
2205 SDValue LoEVL, HiEVL;
2206 std::tie(LoEVL, HiEVL) =
2207 DAG.SplitEVL(SLD->getVectorLength(), SLD->getValueType(0), DL);
2208
2209 // Generate the low vp_strided_load
2210 Lo = DAG.getStridedLoadVP(
2211 SLD->getAddressingMode(), SLD->getExtensionType(), LoVT, DL,
2212 SLD->getChain(), SLD->getBasePtr(), SLD->getOffset(), SLD->getStride(),
2213 LoMask, LoEVL, LoMemVT, SLD->getMemOperand(), SLD->isExpandingLoad());
2214
2215 if (HiIsEmpty) {
2216 // The high vp_strided_load has zero storage size. We therefore simply set
2217 // it to the low vp_strided_load and rely on subsequent removal from the
2218 // chain.
2219 Hi = Lo;
2220 } else {
2221 // Generate the high vp_strided_load.
2222 // To calculate the high base address, we need to sum to the low base
2223 // address stride number of bytes for each element already loaded by low,
2224 // that is: Ptr = Ptr + (LoEVL * Stride)
2225 EVT PtrVT = SLD->getBasePtr().getValueType();
2227 DAG.getNode(ISD::MUL, DL, PtrVT, LoEVL,
2228 DAG.getSExtOrTrunc(SLD->getStride(), DL, PtrVT));
2229 SDValue Ptr =
2230 DAG.getNode(ISD::ADD, DL, PtrVT, SLD->getBasePtr(), Increment);
2231
2232 Align Alignment = SLD->getOriginalAlign();
2233 if (LoMemVT.isScalableVector())
2234 Alignment = commonAlignment(
2235 Alignment, LoMemVT.getSizeInBits().getKnownMinValue() / 8);
2236
2240 Alignment, SLD->getAAInfo(), SLD->getRanges());
2241
2243 HiVT, DL, SLD->getChain(), Ptr, SLD->getOffset(),
2244 SLD->getStride(), HiMask, HiEVL, HiMemVT, MMO,
2245 SLD->isExpandingLoad());
2246 }
2247
2248 // Build a factor node to remember that this load is independent of the
2249 // other one.
2250 SDValue Ch = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo.getValue(1),
2251 Hi.getValue(1));
2252
2253 // Legalize the chain result - switch anything that used the old chain to
2254 // use the new one.
2255 ReplaceValueWith(SDValue(SLD, 1), Ch);
2256}
2257
2258void DAGTypeLegalizer::SplitVecRes_MLOAD(MaskedLoadSDNode *MLD,
2259 SDValue &Lo, SDValue &Hi) {
2260 assert(MLD->isUnindexed() && "Indexed masked load during type legalization!");
2261 EVT LoVT, HiVT;
2262 SDLoc dl(MLD);
2263 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(MLD->getValueType(0));
2264
2265 SDValue Ch = MLD->getChain();
2266 SDValue Ptr = MLD->getBasePtr();
2267 SDValue Offset = MLD->getOffset();
2268 assert(Offset.isUndef() && "Unexpected indexed masked load offset");
2269 SDValue Mask = MLD->getMask();
2270 SDValue PassThru = MLD->getPassThru();
2271 Align Alignment = MLD->getOriginalAlign();
2272 ISD::LoadExtType ExtType = MLD->getExtensionType();
2273
2274 // Split Mask operand
2275 SDValue MaskLo, MaskHi;
2276 if (Mask.getOpcode() == ISD::SETCC) {
2277 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
2278 } else {
2279 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
2280 GetSplitVector(Mask, MaskLo, MaskHi);
2281 else
2282 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, dl);
2283 }
2284
2285 EVT MemoryVT = MLD->getMemoryVT();
2286 EVT LoMemVT, HiMemVT;
2287 bool HiIsEmpty = false;
2288 std::tie(LoMemVT, HiMemVT) =
2289 DAG.GetDependentSplitDestVTs(MemoryVT, LoVT, &HiIsEmpty);
2290
2291 SDValue PassThruLo, PassThruHi;
2292 if (getTypeAction(PassThru.getValueType()) == TargetLowering::TypeSplitVector)
2293 GetSplitVector(PassThru, PassThruLo, PassThruHi);
2294 else
2295 std::tie(PassThruLo, PassThruHi) = DAG.SplitVector(PassThru, dl);
2296
2299 LocationSize::beforeOrAfterPointer(), Alignment, MLD->getAAInfo(),
2300 MLD->getRanges());
2301
2302 Lo = DAG.getMaskedLoad(LoVT, dl, Ch, Ptr, Offset, MaskLo, PassThruLo, LoMemVT,
2303 MMO, MLD->getAddressingMode(), ExtType,
2304 MLD->isExpandingLoad());
2305
2306 if (HiIsEmpty) {
2307 // The hi masked load has zero storage size. We therefore simply set it to
2308 // the low masked load and rely on subsequent removal from the chain.
2309 Hi = Lo;
2310 } else {
2311 // Generate hi masked load.
2312 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, dl, LoMemVT, DAG,
2313 MLD->isExpandingLoad());
2314
2316 if (LoMemVT.isScalableVector())
2318 else
2319 MPI = MLD->getPointerInfo().getWithOffset(
2320 LoMemVT.getStoreSize().getFixedValue());
2321
2324 Alignment, MLD->getAAInfo(), MLD->getRanges());
2325
2326 Hi = DAG.getMaskedLoad(HiVT, dl, Ch, Ptr, Offset, MaskHi, PassThruHi,
2327 HiMemVT, MMO, MLD->getAddressingMode(), ExtType,
2328 MLD->isExpandingLoad());
2329 }
2330
2331 // Build a factor node to remember that this load is independent of the
2332 // other one.
2333 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2334 Hi.getValue(1));
2335
2336 // Legalize the chain result - switch anything that used the old chain to
2337 // use the new one.
2338 ReplaceValueWith(SDValue(MLD, 1), Ch);
2339
2340}
2341
2342void DAGTypeLegalizer::SplitVecRes_Gather(MemSDNode *N, SDValue &Lo,
2343 SDValue &Hi, bool SplitSETCC) {
2344 EVT LoVT, HiVT;
2345 SDLoc dl(N);
2346 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2347
2348 SDValue Ch = N->getChain();
2349 SDValue Ptr = N->getBasePtr();
2350 struct Operands {
2351 SDValue Mask;
2352 SDValue Index;
2353 SDValue Scale;
2354 } Ops = [&]() -> Operands {
2355 if (auto *MSC = dyn_cast<MaskedGatherSDNode>(N)) {
2356 return {MSC->getMask(), MSC->getIndex(), MSC->getScale()};
2357 }
2358 auto *VPSC = cast<VPGatherSDNode>(N);
2359 return {VPSC->getMask(), VPSC->getIndex(), VPSC->getScale()};
2360 }();
2361
2362 EVT MemoryVT = N->getMemoryVT();
2363 Align Alignment = N->getOriginalAlign();
2364
2365 // Split Mask operand
2366 SDValue MaskLo, MaskHi;
2367 if (SplitSETCC && Ops.Mask.getOpcode() == ISD::SETCC) {
2368 SplitVecRes_SETCC(Ops.Mask.getNode(), MaskLo, MaskHi);
2369 } else {
2370 std::tie(MaskLo, MaskHi) = SplitMask(Ops.Mask, dl);
2371 }
2372
2373 EVT LoMemVT, HiMemVT;
2374 // Split MemoryVT
2375 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
2376
2377 SDValue IndexHi, IndexLo;
2378 if (getTypeAction(Ops.Index.getValueType()) ==
2380 GetSplitVector(Ops.Index, IndexLo, IndexHi);
2381 else
2382 std::tie(IndexLo, IndexHi) = DAG.SplitVector(Ops.Index, dl);
2383
2385 N->getPointerInfo(), MachineMemOperand::MOLoad,
2386 LocationSize::beforeOrAfterPointer(), Alignment, N->getAAInfo(),
2387 N->getRanges());
2388
2389 if (auto *MGT = dyn_cast<MaskedGatherSDNode>(N)) {
2390 SDValue PassThru = MGT->getPassThru();
2391 SDValue PassThruLo, PassThruHi;
2392 if (getTypeAction(PassThru.getValueType()) ==
2394 GetSplitVector(PassThru, PassThruLo, PassThruHi);
2395 else
2396 std::tie(PassThruLo, PassThruHi) = DAG.SplitVector(PassThru, dl);
2397
2398 ISD::LoadExtType ExtType = MGT->getExtensionType();
2399 ISD::MemIndexType IndexTy = MGT->getIndexType();
2400
2401 SDValue OpsLo[] = {Ch, PassThruLo, MaskLo, Ptr, IndexLo, Ops.Scale};
2402 Lo = DAG.getMaskedGather(DAG.getVTList(LoVT, MVT::Other), LoMemVT, dl,
2403 OpsLo, MMO, IndexTy, ExtType);
2404
2405 SDValue OpsHi[] = {Ch, PassThruHi, MaskHi, Ptr, IndexHi, Ops.Scale};
2406 Hi = DAG.getMaskedGather(DAG.getVTList(HiVT, MVT::Other), HiMemVT, dl,
2407 OpsHi, MMO, IndexTy, ExtType);
2408 } else {
2409 auto *VPGT = cast<VPGatherSDNode>(N);
2410 SDValue EVLLo, EVLHi;
2411 std::tie(EVLLo, EVLHi) =
2412 DAG.SplitEVL(VPGT->getVectorLength(), MemoryVT, dl);
2413
2414 SDValue OpsLo[] = {Ch, Ptr, IndexLo, Ops.Scale, MaskLo, EVLLo};
2415 Lo = DAG.getGatherVP(DAG.getVTList(LoVT, MVT::Other), LoMemVT, dl, OpsLo,
2416 MMO, VPGT->getIndexType());
2417
2418 SDValue OpsHi[] = {Ch, Ptr, IndexHi, Ops.Scale, MaskHi, EVLHi};
2419 Hi = DAG.getGatherVP(DAG.getVTList(HiVT, MVT::Other), HiMemVT, dl, OpsHi,
2420 MMO, VPGT->getIndexType());
2421 }
2422
2423 // Build a factor node to remember that this load is independent of the
2424 // other one.
2425 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2426 Hi.getValue(1));
2427
2428 // Legalize the chain result - switch anything that used the old chain to
2429 // use the new one.
2430 ReplaceValueWith(SDValue(N, 1), Ch);
2431}
2432
2433void DAGTypeLegalizer::SplitVecRes_VECTOR_COMPRESS(SDNode *N, SDValue &Lo,
2434 SDValue &Hi) {
2435 // This is not "trivial", as there is a dependency between the two subvectors.
2436 // Depending on the number of 1s in the mask, the elements from the Hi vector
2437 // need to be moved to the Lo vector. Passthru values make this even harder.
2438 // We try to use VECTOR_COMPRESS if the target has custom lowering with
2439 // smaller types and passthru is undef, as it is most likely faster than the
2440 // fully expand path. Otherwise, just do the full expansion as one "big"
2441 // operation and then extract the Lo and Hi vectors from that. This gets
2442 // rid of VECTOR_COMPRESS and all other operands can be legalized later.
2443 SDLoc DL(N);
2444 EVT VecVT = N->getValueType(0);
2445
2446 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(VecVT);
2447 bool HasCustomLowering = false;
2448 EVT CheckVT = LoVT;
2449 while (CheckVT.getVectorMinNumElements() > 1) {
2450 // TLI.isOperationLegalOrCustom requires a legal type, but we could have a
2451 // custom lowering for illegal types. So we do the checks separately.
2452 if (TLI.isOperationLegal(ISD::VECTOR_COMPRESS, CheckVT) ||
2454 HasCustomLowering = true;
2455 break;
2456 }
2457 CheckVT = CheckVT.getHalfNumVectorElementsVT(*DAG.getContext());
2458 }
2459
2460 SDValue Passthru = N->getOperand(2);
2461 if (!HasCustomLowering || !Passthru.isUndef()) {
2462 SDValue Compressed = TLI.expandVECTOR_COMPRESS(N, DAG);
2463 std::tie(Lo, Hi) = DAG.SplitVector(Compressed, DL, LoVT, HiVT);
2464 return;
2465 }
2466
2467 // Try to VECTOR_COMPRESS smaller vectors and combine via a stack store+load.
2468 SDValue LoMask, HiMask;
2469 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
2470 std::tie(LoMask, HiMask) = SplitMask(N->getOperand(1));
2471
2472 SDValue UndefPassthru = DAG.getUNDEF(LoVT);
2473 Lo = DAG.getNode(ISD::VECTOR_COMPRESS, DL, LoVT, Lo, LoMask, UndefPassthru);
2474 Hi = DAG.getNode(ISD::VECTOR_COMPRESS, DL, HiVT, Hi, HiMask, UndefPassthru);
2475
2477 VecVT.getStoreSize(), DAG.getReducedAlign(VecVT, /*UseABI=*/false));
2480 MF, cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex());
2481
2482 // We store LoVec and then insert HiVec starting at offset=|1s| in LoMask.
2483 SDValue WideMask =
2484 DAG.getNode(ISD::ZERO_EXTEND, DL, LoMask.getValueType(), LoMask);
2485 SDValue Offset = DAG.getNode(ISD::VECREDUCE_ADD, DL, MVT::i32, WideMask);
2486 Offset = TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Offset);
2487
2488 SDValue Chain = DAG.getEntryNode();
2489 Chain = DAG.getStore(Chain, DL, Lo, StackPtr, PtrInfo);
2490 Chain = DAG.getStore(Chain, DL, Hi, Offset,
2492
2493 SDValue Compressed = DAG.getLoad(VecVT, DL, Chain, StackPtr, PtrInfo);
2494 std::tie(Lo, Hi) = DAG.SplitVector(Compressed, DL);
2495}
2496
2497void DAGTypeLegalizer::SplitVecRes_SETCC(SDNode *N, SDValue &Lo, SDValue &Hi) {
2498 assert(N->getValueType(0).isVector() &&
2499 N->getOperand(0).getValueType().isVector() &&
2500 "Operand types must be vectors");
2501
2502 EVT LoVT, HiVT;
2503 SDLoc DL(N);
2504 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2505
2506 // If the input also splits, handle it directly. Otherwise split it by hand.
2507 SDValue LL, LH, RL, RH;
2508 if (getTypeAction(N->getOperand(0).getValueType()) ==
2510 GetSplitVector(N->getOperand(0), LL, LH);
2511 else
2512 std::tie(LL, LH) = DAG.SplitVectorOperand(N, 0);
2513
2514 if (getTypeAction(N->getOperand(1).getValueType()) ==
2516 GetSplitVector(N->getOperand(1), RL, RH);
2517 else
2518 std::tie(RL, RH) = DAG.SplitVectorOperand(N, 1);
2519
2520 if (N->getOpcode() == ISD::SETCC) {
2521 Lo = DAG.getNode(N->getOpcode(), DL, LoVT, LL, RL, N->getOperand(2));
2522 Hi = DAG.getNode(N->getOpcode(), DL, HiVT, LH, RH, N->getOperand(2));
2523 } else {
2524 assert(N->getOpcode() == ISD::VP_SETCC && "Expected VP_SETCC opcode");
2525 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
2526 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(3));
2527 std::tie(EVLLo, EVLHi) =
2528 DAG.SplitEVL(N->getOperand(4), N->getValueType(0), DL);
2529 Lo = DAG.getNode(N->getOpcode(), DL, LoVT, LL, RL, N->getOperand(2), MaskLo,
2530 EVLLo);
2531 Hi = DAG.getNode(N->getOpcode(), DL, HiVT, LH, RH, N->getOperand(2), MaskHi,
2532 EVLHi);
2533 }
2534}
2535
2536void DAGTypeLegalizer::SplitVecRes_UnaryOp(SDNode *N, SDValue &Lo,
2537 SDValue &Hi) {
2538 // Get the dest types - they may not match the input types, e.g. int_to_fp.
2539 EVT LoVT, HiVT;
2540 SDLoc dl(N);
2541 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2542
2543 // If the input also splits, handle it directly for a compile time speedup.
2544 // Otherwise split it by hand.
2545 EVT InVT = N->getOperand(0).getValueType();
2546 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
2547 GetSplitVector(N->getOperand(0), Lo, Hi);
2548 else
2549 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
2550
2551 const SDNodeFlags Flags = N->getFlags();
2552 unsigned Opcode = N->getOpcode();
2553 if (N->getNumOperands() <= 2) {
2554 if (Opcode == ISD::FP_ROUND) {
2555 Lo = DAG.getNode(Opcode, dl, LoVT, Lo, N->getOperand(1), Flags);
2556 Hi = DAG.getNode(Opcode, dl, HiVT, Hi, N->getOperand(1), Flags);
2557 } else {
2558 Lo = DAG.getNode(Opcode, dl, LoVT, Lo, Flags);
2559 Hi = DAG.getNode(Opcode, dl, HiVT, Hi, Flags);
2560 }
2561 return;
2562 }
2563
2564 assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
2565 assert(N->isVPOpcode() && "Expected VP opcode");
2566
2567 SDValue MaskLo, MaskHi;
2568 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
2569
2570 SDValue EVLLo, EVLHi;
2571 std::tie(EVLLo, EVLHi) =
2572 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), dl);
2573
2574 Lo = DAG.getNode(Opcode, dl, LoVT, {Lo, MaskLo, EVLLo}, Flags);
2575 Hi = DAG.getNode(Opcode, dl, HiVT, {Hi, MaskHi, EVLHi}, Flags);
2576}
2577
2578void DAGTypeLegalizer::SplitVecRes_ADDRSPACECAST(SDNode *N, SDValue &Lo,
2579 SDValue &Hi) {
2580 SDLoc dl(N);
2581 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(N->getValueType(0));
2582
2583 // If the input also splits, handle it directly for a compile time speedup.
2584 // Otherwise split it by hand.
2585 EVT InVT = N->getOperand(0).getValueType();
2586 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
2587 GetSplitVector(N->getOperand(0), Lo, Hi);
2588 else
2589 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
2590
2591 auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
2592 unsigned SrcAS = AddrSpaceCastN->getSrcAddressSpace();
2593 unsigned DestAS = AddrSpaceCastN->getDestAddressSpace();
2594 Lo = DAG.getAddrSpaceCast(dl, LoVT, Lo, SrcAS, DestAS);
2595 Hi = DAG.getAddrSpaceCast(dl, HiVT, Hi, SrcAS, DestAS);
2596}
2597
2598void DAGTypeLegalizer::SplitVecRes_FFREXP(SDNode *N, unsigned ResNo,
2599 SDValue &Lo, SDValue &Hi) {
2600 SDLoc dl(N);
2601 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(N->getValueType(0));
2602 auto [LoVT1, HiVT1] = DAG.GetSplitDestVTs(N->getValueType(1));
2603
2604 // If the input also splits, handle it directly for a compile time speedup.
2605 // Otherwise split it by hand.
2606 EVT InVT = N->getOperand(0).getValueType();
2607 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
2608 GetSplitVector(N->getOperand(0), Lo, Hi);
2609 else
2610 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
2611
2612 Lo = DAG.getNode(N->getOpcode(), dl, {LoVT, LoVT1}, Lo);
2613 Hi = DAG.getNode(N->getOpcode(), dl, {HiVT, HiVT1}, Hi);
2614 Lo->setFlags(N->getFlags());
2615 Hi->setFlags(N->getFlags());
2616
2617 SDNode *HiNode = Hi.getNode();
2618 SDNode *LoNode = Lo.getNode();
2619
2620 // Replace the other vector result not being explicitly split here.
2621 unsigned OtherNo = 1 - ResNo;
2622 EVT OtherVT = N->getValueType(OtherNo);
2623 if (getTypeAction(OtherVT) == TargetLowering::TypeSplitVector) {
2624 SetSplitVector(SDValue(N, OtherNo), SDValue(LoNode, OtherNo),
2625 SDValue(HiNode, OtherNo));
2626 } else {
2627 SDValue OtherVal =
2628 DAG.getNode(ISD::CONCAT_VECTORS, dl, OtherVT, SDValue(LoNode, OtherNo),
2629 SDValue(HiNode, OtherNo));
2630 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
2631 }
2632}
2633
2634void DAGTypeLegalizer::SplitVecRes_ExtendOp(SDNode *N, SDValue &Lo,
2635 SDValue &Hi) {
2636 SDLoc dl(N);
2637 EVT SrcVT = N->getOperand(0).getValueType();
2638 EVT DestVT = N->getValueType(0);
2639 EVT LoVT, HiVT;
2640 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(DestVT);
2641
2642 // We can do better than a generic split operation if the extend is doing
2643 // more than just doubling the width of the elements and the following are
2644 // true:
2645 // - The number of vector elements is even,
2646 // - the source type is legal,
2647 // - the type of a split source is illegal,
2648 // - the type of an extended (by doubling element size) source is legal, and
2649 // - the type of that extended source when split is legal.
2650 //
2651 // This won't necessarily completely legalize the operation, but it will
2652 // more effectively move in the right direction and prevent falling down
2653 // to scalarization in many cases due to the input vector being split too
2654 // far.
2655 if (SrcVT.getVectorElementCount().isKnownEven() &&
2656 SrcVT.getScalarSizeInBits() * 2 < DestVT.getScalarSizeInBits()) {
2657 LLVMContext &Ctx = *DAG.getContext();
2658 EVT NewSrcVT = SrcVT.widenIntegerVectorElementType(Ctx);
2659 EVT SplitSrcVT = SrcVT.getHalfNumVectorElementsVT(Ctx);
2660
2661 EVT SplitLoVT, SplitHiVT;
2662 std::tie(SplitLoVT, SplitHiVT) = DAG.GetSplitDestVTs(NewSrcVT);
2663 if (TLI.isTypeLegal(SrcVT) && !TLI.isTypeLegal(SplitSrcVT) &&
2664 TLI.isTypeLegal(NewSrcVT) && TLI.isTypeLegal(SplitLoVT)) {
2665 LLVM_DEBUG(dbgs() << "Split vector extend via incremental extend:";
2666 N->dump(&DAG); dbgs() << "\n");
2667 if (!N->isVPOpcode()) {
2668 // Extend the source vector by one step.
2669 SDValue NewSrc =
2670 DAG.getNode(N->getOpcode(), dl, NewSrcVT, N->getOperand(0));
2671 // Get the low and high halves of the new, extended one step, vector.
2672 std::tie(Lo, Hi) = DAG.SplitVector(NewSrc, dl);
2673 // Extend those vector halves the rest of the way.
2674 Lo = DAG.getNode(N->getOpcode(), dl, LoVT, Lo);
2675 Hi = DAG.getNode(N->getOpcode(), dl, HiVT, Hi);
2676 return;
2677 }
2678
2679 // Extend the source vector by one step.
2680 SDValue NewSrc =
2681 DAG.getNode(N->getOpcode(), dl, NewSrcVT, N->getOperand(0),
2682 N->getOperand(1), N->getOperand(2));
2683 // Get the low and high halves of the new, extended one step, vector.
2684 std::tie(Lo, Hi) = DAG.SplitVector(NewSrc, dl);
2685
2686 SDValue MaskLo, MaskHi;
2687 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
2688
2689 SDValue EVLLo, EVLHi;
2690 std::tie(EVLLo, EVLHi) =
2691 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), dl);
2692 // Extend those vector halves the rest of the way.
2693 Lo = DAG.getNode(N->getOpcode(), dl, LoVT, {Lo, MaskLo, EVLLo});
2694 Hi = DAG.getNode(N->getOpcode(), dl, HiVT, {Hi, MaskHi, EVLHi});
2695 return;
2696 }
2697 }
2698 // Fall back to the generic unary operator splitting otherwise.
2699 SplitVecRes_UnaryOp(N, Lo, Hi);
2700}
2701
2702void DAGTypeLegalizer::SplitVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N,
2703 SDValue &Lo, SDValue &Hi) {
2704 // The low and high parts of the original input give four input vectors.
2705 SDValue Inputs[4];
2706 SDLoc DL(N);
2707 GetSplitVector(N->getOperand(0), Inputs[0], Inputs[1]);
2708 GetSplitVector(N->getOperand(1), Inputs[2], Inputs[3]);
2709 EVT NewVT = Inputs[0].getValueType();
2710 unsigned NewElts = NewVT.getVectorNumElements();
2711
2712 auto &&IsConstant = [](const SDValue &N) {
2713 APInt SplatValue;
2714 return N.getResNo() == 0 &&
2715 (ISD::isConstantSplatVector(N.getNode(), SplatValue) ||
2717 };
2718 auto &&BuildVector = [NewElts, &DAG = DAG, NewVT, &DL](SDValue &Input1,
2719 SDValue &Input2,
2721 assert(Input1->getOpcode() == ISD::BUILD_VECTOR &&
2722 Input2->getOpcode() == ISD::BUILD_VECTOR &&
2723 "Expected build vector node.");
2724 EVT EltVT = NewVT.getVectorElementType();
2725 SmallVector<SDValue> Ops(NewElts, DAG.getUNDEF(EltVT));
2726 for (unsigned I = 0; I < NewElts; ++I) {
2727 if (Mask[I] == PoisonMaskElem)
2728 continue;
2729 unsigned Idx = Mask[I];
2730 if (Idx >= NewElts)
2731 Ops[I] = Input2.getOperand(Idx - NewElts);
2732 else
2733 Ops[I] = Input1.getOperand(Idx);
2734 // Make the type of all elements the same as the element type.
2735 if (Ops[I].getValueType().bitsGT(EltVT))
2736 Ops[I] = DAG.getNode(ISD::TRUNCATE, DL, EltVT, Ops[I]);
2737 }
2738 return DAG.getBuildVector(NewVT, DL, Ops);
2739 };
2740
2741 // If Lo or Hi uses elements from at most two of the four input vectors, then
2742 // express it as a vector shuffle of those two inputs. Otherwise extract the
2743 // input elements by hand and construct the Lo/Hi output using a BUILD_VECTOR.
2744 SmallVector<int> OrigMask(N->getMask());
2745 // Try to pack incoming shuffles/inputs.
2746 auto &&TryPeekThroughShufflesInputs = [&Inputs, &NewVT, this, NewElts,
2748 // Check if all inputs are shuffles of the same operands or non-shuffles.
2750 for (unsigned Idx = 0; Idx < std::size(Inputs); ++Idx) {
2751 SDValue Input = Inputs[Idx];
2752 auto *Shuffle = dyn_cast<ShuffleVectorSDNode>(Input.getNode());
2753 if (!Shuffle ||
2754 Input.getOperand(0).getValueType() != Input.getValueType())
2755 continue;
2756 ShufflesIdxs[std::make_pair(Input.getOperand(0), Input.getOperand(1))]
2757 .push_back(Idx);
2758 ShufflesIdxs[std::make_pair(Input.getOperand(1), Input.getOperand(0))]
2759 .push_back(Idx);
2760 }
2761 for (auto &P : ShufflesIdxs) {
2762 if (P.second.size() < 2)
2763 continue;
2764 // Use shuffles operands instead of shuffles themselves.
2765 // 1. Adjust mask.
2766 for (int &Idx : Mask) {
2767 if (Idx == PoisonMaskElem)
2768 continue;
2769 unsigned SrcRegIdx = Idx / NewElts;
2770 if (Inputs[SrcRegIdx].isUndef()) {
2772 continue;
2773 }
2774 auto *Shuffle =
2775 dyn_cast<ShuffleVectorSDNode>(Inputs[SrcRegIdx].getNode());
2776 if (!Shuffle || !is_contained(P.second, SrcRegIdx))
2777 continue;
2778 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
2779 if (MaskElt == PoisonMaskElem) {
2781 continue;
2782 }
2783 Idx = MaskElt % NewElts +
2784 P.second[Shuffle->getOperand(MaskElt / NewElts) == P.first.first
2785 ? 0
2786 : 1] *
2787 NewElts;
2788 }
2789 // 2. Update inputs.
2790 Inputs[P.second[0]] = P.first.first;
2791 Inputs[P.second[1]] = P.first.second;
2792 // Clear the pair data.
2793 P.second.clear();
2794 ShufflesIdxs[std::make_pair(P.first.second, P.first.first)].clear();
2795 }
2796 // Check if any concat_vectors can be simplified.
2797 SmallBitVector UsedSubVector(2 * std::size(Inputs));
2798 for (int &Idx : Mask) {
2799 if (Idx == PoisonMaskElem)
2800 continue;
2801 unsigned SrcRegIdx = Idx / NewElts;
2802 if (Inputs[SrcRegIdx].isUndef()) {
2804 continue;
2805 }
2807 getTypeAction(Inputs[SrcRegIdx].getValueType());
2808 if (Inputs[SrcRegIdx].getOpcode() == ISD::CONCAT_VECTORS &&
2809 Inputs[SrcRegIdx].getNumOperands() == 2 &&
2810 !Inputs[SrcRegIdx].getOperand(1).isUndef() &&
2811 (TypeAction == TargetLowering::TypeLegal ||
2812 TypeAction == TargetLowering::TypeWidenVector))
2813 UsedSubVector.set(2 * SrcRegIdx + (Idx % NewElts) / (NewElts / 2));
2814 }
2815 if (UsedSubVector.count() > 1) {
2817 for (unsigned I = 0; I < std::size(Inputs); ++I) {
2818 if (UsedSubVector.test(2 * I) == UsedSubVector.test(2 * I + 1))
2819 continue;
2820 if (Pairs.empty() || Pairs.back().size() == 2)
2821 Pairs.emplace_back();
2822 if (UsedSubVector.test(2 * I)) {
2823 Pairs.back().emplace_back(I, 0);
2824 } else {
2825 assert(UsedSubVector.test(2 * I + 1) &&
2826 "Expected to be used one of the subvectors.");
2827 Pairs.back().emplace_back(I, 1);
2828 }
2829 }
2830 if (!Pairs.empty() && Pairs.front().size() > 1) {
2831 // Adjust mask.
2832 for (int &Idx : Mask) {
2833 if (Idx == PoisonMaskElem)
2834 continue;
2835 unsigned SrcRegIdx = Idx / NewElts;
2836 auto *It = find_if(
2837 Pairs, [SrcRegIdx](ArrayRef<std::pair<unsigned, int>> Idxs) {
2838 return Idxs.front().first == SrcRegIdx ||
2839 Idxs.back().first == SrcRegIdx;
2840 });
2841 if (It == Pairs.end())
2842 continue;
2843 Idx = It->front().first * NewElts + (Idx % NewElts) % (NewElts / 2) +
2844 (SrcRegIdx == It->front().first ? 0 : (NewElts / 2));
2845 }
2846 // Adjust inputs.
2847 for (ArrayRef<std::pair<unsigned, int>> Idxs : Pairs) {
2848 Inputs[Idxs.front().first] = DAG.getNode(
2850 Inputs[Idxs.front().first].getValueType(),
2851 Inputs[Idxs.front().first].getOperand(Idxs.front().second),
2852 Inputs[Idxs.back().first].getOperand(Idxs.back().second));
2853 }
2854 }
2855 }
2856 bool Changed;
2857 do {
2858 // Try to remove extra shuffles (except broadcasts) and shuffles with the
2859 // reused operands.
2860 Changed = false;
2861 for (unsigned I = 0; I < std::size(Inputs); ++I) {
2862 auto *Shuffle = dyn_cast<ShuffleVectorSDNode>(Inputs[I].getNode());
2863 if (!Shuffle)
2864 continue;
2865 if (Shuffle->getOperand(0).getValueType() != NewVT)
2866 continue;
2867 int Op = -1;
2868 if (!Inputs[I].hasOneUse() && Shuffle->getOperand(1).isUndef() &&
2869 !Shuffle->isSplat()) {
2870 Op = 0;
2871 } else if (!Inputs[I].hasOneUse() &&
2872 !Shuffle->getOperand(1).isUndef()) {
2873 // Find the only used operand, if possible.
2874 for (int &Idx : Mask) {
2875 if (Idx == PoisonMaskElem)
2876 continue;
2877 unsigned SrcRegIdx = Idx / NewElts;
2878 if (SrcRegIdx != I)
2879 continue;
2880 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
2881 if (MaskElt == PoisonMaskElem) {
2883 continue;
2884 }
2885 int OpIdx = MaskElt / NewElts;
2886 if (Op == -1) {
2887 Op = OpIdx;
2888 continue;
2889 }
2890 if (Op != OpIdx) {
2891 Op = -1;
2892 break;
2893 }
2894 }
2895 }
2896 if (Op < 0) {
2897 // Try to check if one of the shuffle operands is used already.
2898 for (int OpIdx = 0; OpIdx < 2; ++OpIdx) {
2899 if (Shuffle->getOperand(OpIdx).isUndef())
2900 continue;
2901 auto *It = find(Inputs, Shuffle->getOperand(OpIdx));
2902 if (It == std::end(Inputs))
2903 continue;
2904 int FoundOp = std::distance(std::begin(Inputs), It);
2905 // Found that operand is used already.
2906 // 1. Fix the mask for the reused operand.
2907 for (int &Idx : Mask) {
2908 if (Idx == PoisonMaskElem)
2909 continue;
2910 unsigned SrcRegIdx = Idx / NewElts;
2911 if (SrcRegIdx != I)
2912 continue;
2913 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
2914 if (MaskElt == PoisonMaskElem) {
2916 continue;
2917 }
2918 int MaskIdx = MaskElt / NewElts;
2919 if (OpIdx == MaskIdx)
2920 Idx = MaskElt % NewElts + FoundOp * NewElts;
2921 }
2922 // 2. Set Op to the unused OpIdx.
2923 Op = (OpIdx + 1) % 2;
2924 break;
2925 }
2926 }
2927 if (Op >= 0) {
2928 Changed = true;
2929 Inputs[I] = Shuffle->getOperand(Op);
2930 // Adjust mask.
2931 for (int &Idx : Mask) {
2932 if (Idx == PoisonMaskElem)
2933 continue;
2934 unsigned SrcRegIdx = Idx / NewElts;
2935 if (SrcRegIdx != I)
2936 continue;
2937 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
2938 int OpIdx = MaskElt / NewElts;
2939 if (OpIdx != Op)
2940 continue;
2941 Idx = MaskElt % NewElts + SrcRegIdx * NewElts;
2942 }
2943 }
2944 }
2945 } while (Changed);
2946 };
2947 TryPeekThroughShufflesInputs(OrigMask);
2948 // Proces unique inputs.
2949 auto &&MakeUniqueInputs = [&Inputs, &IsConstant,
2950 NewElts](SmallVectorImpl<int> &Mask) {
2951 SetVector<SDValue> UniqueInputs;
2952 SetVector<SDValue> UniqueConstantInputs;
2953 for (const auto &I : Inputs) {
2954 if (IsConstant(I))
2955 UniqueConstantInputs.insert(I);
2956 else if (!I.isUndef())
2957 UniqueInputs.insert(I);
2958 }
2959 // Adjust mask in case of reused inputs. Also, need to insert constant
2960 // inputs at first, otherwise it affects the final outcome.
2961 if (UniqueInputs.size() != std::size(Inputs)) {
2962 auto &&UniqueVec = UniqueInputs.takeVector();
2963 auto &&UniqueConstantVec = UniqueConstantInputs.takeVector();
2964 unsigned ConstNum = UniqueConstantVec.size();
2965 for (int &Idx : Mask) {
2966 if (Idx == PoisonMaskElem)
2967 continue;
2968 unsigned SrcRegIdx = Idx / NewElts;
2969 if (Inputs[SrcRegIdx].isUndef()) {
2971 continue;
2972 }
2973 const auto It = find(UniqueConstantVec, Inputs[SrcRegIdx]);
2974 if (It != UniqueConstantVec.end()) {
2975 Idx = (Idx % NewElts) +
2976 NewElts * std::distance(UniqueConstantVec.begin(), It);
2977 assert(Idx >= 0 && "Expected defined mask idx.");
2978 continue;
2979 }
2980 const auto RegIt = find(UniqueVec, Inputs[SrcRegIdx]);
2981 assert(RegIt != UniqueVec.end() && "Cannot find non-const value.");
2982 Idx = (Idx % NewElts) +
2983 NewElts * (std::distance(UniqueVec.begin(), RegIt) + ConstNum);
2984 assert(Idx >= 0 && "Expected defined mask idx.");
2985 }
2986 copy(UniqueConstantVec, std::begin(Inputs));
2987 copy(UniqueVec, std::next(std::begin(Inputs), ConstNum));
2988 }
2989 };
2990 MakeUniqueInputs(OrigMask);
2991 SDValue OrigInputs[4];
2992 copy(Inputs, std::begin(OrigInputs));
2993 for (unsigned High = 0; High < 2; ++High) {
2994 SDValue &Output = High ? Hi : Lo;
2995
2996 // Build a shuffle mask for the output, discovering on the fly which
2997 // input vectors to use as shuffle operands.
2998 unsigned FirstMaskIdx = High * NewElts;
2999 SmallVector<int> Mask(NewElts * std::size(Inputs), PoisonMaskElem);
3000 copy(ArrayRef(OrigMask).slice(FirstMaskIdx, NewElts), Mask.begin());
3001 assert(!Output && "Expected default initialized initial value.");
3002 TryPeekThroughShufflesInputs(Mask);
3003 MakeUniqueInputs(Mask);
3004 SDValue TmpInputs[4];
3005 copy(Inputs, std::begin(TmpInputs));
3006 // Track changes in the output registers.
3007 int UsedIdx = -1;
3008 bool SecondIteration = false;
3009 auto &&AccumulateResults = [&UsedIdx, &SecondIteration](unsigned Idx) {
3010 if (UsedIdx < 0) {
3011 UsedIdx = Idx;
3012 return false;
3013 }
3014 if (UsedIdx >= 0 && static_cast<unsigned>(UsedIdx) == Idx)
3015 SecondIteration = true;
3016 return SecondIteration;
3017 };
3019 Mask, std::size(Inputs), std::size(Inputs),
3020 /*NumOfUsedRegs=*/1,
3021 [&Output, &DAG = DAG, NewVT]() { Output = DAG.getUNDEF(NewVT); },
3022 [&Output, &DAG = DAG, NewVT, &DL, &Inputs,
3023 &BuildVector](ArrayRef<int> Mask, unsigned Idx, unsigned /*Unused*/) {
3024 if (Inputs[Idx]->getOpcode() == ISD::BUILD_VECTOR)
3025 Output = BuildVector(Inputs[Idx], Inputs[Idx], Mask);
3026 else
3027 Output = DAG.getVectorShuffle(NewVT, DL, Inputs[Idx],
3028 DAG.getUNDEF(NewVT), Mask);
3029 Inputs[Idx] = Output;
3030 },
3031 [&AccumulateResults, &Output, &DAG = DAG, NewVT, &DL, &Inputs,
3032 &TmpInputs,
3033 &BuildVector](ArrayRef<int> Mask, unsigned Idx1, unsigned Idx2) {
3034 if (AccumulateResults(Idx1)) {
3035 if (Inputs[Idx1]->getOpcode() == ISD::BUILD_VECTOR &&
3036 Inputs[Idx2]->getOpcode() == ISD::BUILD_VECTOR)
3037 Output = BuildVector(Inputs[Idx1], Inputs[Idx2], Mask);
3038 else
3039 Output = DAG.getVectorShuffle(NewVT, DL, Inputs[Idx1],
3040 Inputs[Idx2], Mask);
3041 } else {
3042 if (TmpInputs[Idx1]->getOpcode() == ISD::BUILD_VECTOR &&
3043 TmpInputs[Idx2]->getOpcode() == ISD::BUILD_VECTOR)
3044 Output = BuildVector(TmpInputs[Idx1], TmpInputs[Idx2], Mask);
3045 else
3046 Output = DAG.getVectorShuffle(NewVT, DL, TmpInputs[Idx1],
3047 TmpInputs[Idx2], Mask);
3048 }
3049 Inputs[Idx1] = Output;
3050 });
3051 copy(OrigInputs, std::begin(Inputs));
3052 }
3053}
3054
3055void DAGTypeLegalizer::SplitVecRes_VAARG(SDNode *N, SDValue &Lo, SDValue &Hi) {
3056 EVT OVT = N->getValueType(0);
3057 EVT NVT = OVT.getHalfNumVectorElementsVT(*DAG.getContext());
3058 SDValue Chain = N->getOperand(0);
3059 SDValue Ptr = N->getOperand(1);
3060 SDValue SV = N->getOperand(2);
3061 SDLoc dl(N);
3062
3063 const Align Alignment =
3064 DAG.getDataLayout().getABITypeAlign(NVT.getTypeForEVT(*DAG.getContext()));
3065
3066 Lo = DAG.getVAArg(NVT, dl, Chain, Ptr, SV, Alignment.value());
3067 Hi = DAG.getVAArg(NVT, dl, Lo.getValue(1), Ptr, SV, Alignment.value());
3068 Chain = Hi.getValue(1);
3069
3070 // Modified the chain - switch anything that used the old chain to use
3071 // the new one.
3072 ReplaceValueWith(SDValue(N, 1), Chain);
3073}
3074
3075void DAGTypeLegalizer::SplitVecRes_FP_TO_XINT_SAT(SDNode *N, SDValue &Lo,
3076 SDValue &Hi) {
3077 EVT DstVTLo, DstVTHi;
3078 std::tie(DstVTLo, DstVTHi) = DAG.GetSplitDestVTs(N->getValueType(0));
3079 SDLoc dl(N);
3080
3081 SDValue SrcLo, SrcHi;
3082 EVT SrcVT = N->getOperand(0).getValueType();
3083 if (getTypeAction(SrcVT) == TargetLowering::TypeSplitVector)
3084 GetSplitVector(N->getOperand(0), SrcLo, SrcHi);
3085 else
3086 std::tie(SrcLo, SrcHi) = DAG.SplitVectorOperand(N, 0);
3087
3088 Lo = DAG.getNode(N->getOpcode(), dl, DstVTLo, SrcLo, N->getOperand(1));
3089 Hi = DAG.getNode(N->getOpcode(), dl, DstVTHi, SrcHi, N->getOperand(1));
3090}
3091
3092void DAGTypeLegalizer::SplitVecRes_VECTOR_REVERSE(SDNode *N, SDValue &Lo,
3093 SDValue &Hi) {
3094 SDValue InLo, InHi;
3095 GetSplitVector(N->getOperand(0), InLo, InHi);
3096 SDLoc DL(N);
3097
3098 Lo = DAG.getNode(ISD::VECTOR_REVERSE, DL, InHi.getValueType(), InHi);
3099 Hi = DAG.getNode(ISD::VECTOR_REVERSE, DL, InLo.getValueType(), InLo);
3100}
3101
3102void DAGTypeLegalizer::SplitVecRes_VECTOR_SPLICE(SDNode *N, SDValue &Lo,
3103 SDValue &Hi) {
3104 SDLoc DL(N);
3105
3106 SDValue Expanded = TLI.expandVectorSplice(N, DAG);
3107 std::tie(Lo, Hi) = DAG.SplitVector(Expanded, DL);
3108}
3109
3110void DAGTypeLegalizer::SplitVecRes_VP_REVERSE(SDNode *N, SDValue &Lo,
3111 SDValue &Hi) {
3112 EVT VT = N->getValueType(0);
3113 SDValue Val = N->getOperand(0);
3114 SDValue Mask = N->getOperand(1);
3115 SDValue EVL = N->getOperand(2);
3116 SDLoc DL(N);
3117
3118 // Fallback to VP_STRIDED_STORE to stack followed by VP_LOAD.
3119 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
3120
3121 EVT MemVT = EVT::getVectorVT(*DAG.getContext(), VT.getVectorElementType(),
3123 SDValue StackPtr = DAG.CreateStackTemporary(MemVT.getStoreSize(), Alignment);
3124 EVT PtrVT = StackPtr.getValueType();
3125 auto &MF = DAG.getMachineFunction();
3126 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
3127 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
3128
3129 MachineMemOperand *StoreMMO = DAG.getMachineFunction().getMachineMemOperand(
3131 Alignment);
3132 MachineMemOperand *LoadMMO = DAG.getMachineFunction().getMachineMemOperand(
3134 Alignment);
3135
3136 unsigned EltWidth = VT.getScalarSizeInBits() / 8;
3137 SDValue NumElemMinus1 =
3138 DAG.getNode(ISD::SUB, DL, PtrVT, DAG.getZExtOrTrunc(EVL, DL, PtrVT),
3139 DAG.getConstant(1, DL, PtrVT));
3140 SDValue StartOffset = DAG.getNode(ISD::MUL, DL, PtrVT, NumElemMinus1,
3141 DAG.getConstant(EltWidth, DL, PtrVT));
3142 SDValue StorePtr = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, StartOffset);
3143 SDValue Stride = DAG.getConstant(-(int64_t)EltWidth, DL, PtrVT);
3144
3145 SDValue TrueMask = DAG.getBoolConstant(true, DL, Mask.getValueType(), VT);
3146 SDValue Store = DAG.getStridedStoreVP(DAG.getEntryNode(), DL, Val, StorePtr,
3147 DAG.getUNDEF(PtrVT), Stride, TrueMask,
3148 EVL, MemVT, StoreMMO, ISD::UNINDEXED);
3149
3150 SDValue Load = DAG.getLoadVP(VT, DL, Store, StackPtr, Mask, EVL, LoadMMO);
3151
3152 std::tie(Lo, Hi) = DAG.SplitVector(Load, DL);
3153}
3154
3155void DAGTypeLegalizer::SplitVecRes_VECTOR_DEINTERLEAVE(SDNode *N) {
3156
3157 SDValue Op0Lo, Op0Hi, Op1Lo, Op1Hi;
3158 GetSplitVector(N->getOperand(0), Op0Lo, Op0Hi);
3159 GetSplitVector(N->getOperand(1), Op1Lo, Op1Hi);
3160 EVT VT = Op0Lo.getValueType();
3161 SDLoc DL(N);
3163 DAG.getVTList(VT, VT), Op0Lo, Op0Hi);
3165 DAG.getVTList(VT, VT), Op1Lo, Op1Hi);
3166
3167 SetSplitVector(SDValue(N, 0), ResLo.getValue(0), ResHi.getValue(0));
3168 SetSplitVector(SDValue(N, 1), ResLo.getValue(1), ResHi.getValue(1));
3169}
3170
3171void DAGTypeLegalizer::SplitVecRes_VECTOR_INTERLEAVE(SDNode *N) {
3172 SDValue Op0Lo, Op0Hi, Op1Lo, Op1Hi;
3173 GetSplitVector(N->getOperand(0), Op0Lo, Op0Hi);
3174 GetSplitVector(N->getOperand(1), Op1Lo, Op1Hi);
3175 EVT VT = Op0Lo.getValueType();
3176 SDLoc DL(N);
3178 DAG.getVTList(VT, VT), Op0Lo, Op1Lo),
3179 DAG.getNode(ISD::VECTOR_INTERLEAVE, DL,
3180 DAG.getVTList(VT, VT), Op0Hi, Op1Hi)};
3181
3182 SetSplitVector(SDValue(N, 0), Res[0].getValue(0), Res[0].getValue(1));
3183 SetSplitVector(SDValue(N, 1), Res[1].getValue(0), Res[1].getValue(1));
3184}
3185
3186//===----------------------------------------------------------------------===//
3187// Operand Vector Splitting
3188//===----------------------------------------------------------------------===//
3189
3190/// This method is called when the specified operand of the specified node is
3191/// found to need vector splitting. At this point, all of the result types of
3192/// the node are known to be legal, but other operands of the node may need
3193/// legalization as well as the specified one.
3194bool DAGTypeLegalizer::SplitVectorOperand(SDNode *N, unsigned OpNo) {
3195 LLVM_DEBUG(dbgs() << "Split node operand: "; N->dump(&DAG));
3196 SDValue Res = SDValue();
3197
3198 // See if the target wants to custom split this node.
3199 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
3200 return false;
3201
3202 switch (N->getOpcode()) {
3203 default:
3204#ifndef NDEBUG
3205 dbgs() << "SplitVectorOperand Op #" << OpNo << ": ";
3206 N->dump(&DAG);
3207 dbgs() << "\n";
3208#endif
3209 report_fatal_error("Do not know how to split this operator's "
3210 "operand!\n");
3211
3212 case ISD::VP_SETCC:
3213 case ISD::STRICT_FSETCC:
3214 case ISD::SETCC: Res = SplitVecOp_VSETCC(N); break;
3215 case ISD::BITCAST: Res = SplitVecOp_BITCAST(N); break;
3216 case ISD::EXTRACT_SUBVECTOR: Res = SplitVecOp_EXTRACT_SUBVECTOR(N); break;
3217 case ISD::INSERT_SUBVECTOR: Res = SplitVecOp_INSERT_SUBVECTOR(N, OpNo); break;
3218 case ISD::EXTRACT_VECTOR_ELT:Res = SplitVecOp_EXTRACT_VECTOR_ELT(N); break;
3219 case ISD::CONCAT_VECTORS: Res = SplitVecOp_CONCAT_VECTORS(N); break;
3220 case ISD::VP_TRUNCATE:
3221 case ISD::TRUNCATE:
3222 Res = SplitVecOp_TruncateHelper(N);
3223 break;
3225 case ISD::VP_FP_ROUND:
3226 case ISD::FP_ROUND: Res = SplitVecOp_FP_ROUND(N); break;
3227 case ISD::FCOPYSIGN: Res = SplitVecOp_FPOpDifferentTypes(N); break;
3228 case ISD::STORE:
3229 Res = SplitVecOp_STORE(cast<StoreSDNode>(N), OpNo);
3230 break;
3231 case ISD::VP_STORE:
3232 Res = SplitVecOp_VP_STORE(cast<VPStoreSDNode>(N), OpNo);
3233 break;
3234 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
3235 Res = SplitVecOp_VP_STRIDED_STORE(cast<VPStridedStoreSDNode>(N), OpNo);
3236 break;
3237 case ISD::MSTORE:
3238 Res = SplitVecOp_MSTORE(cast<MaskedStoreSDNode>(N), OpNo);
3239 break;
3240 case ISD::MSCATTER:
3241 case ISD::VP_SCATTER:
3242 Res = SplitVecOp_Scatter(cast<MemSDNode>(N), OpNo);
3243 break;
3244 case ISD::MGATHER:
3245 case ISD::VP_GATHER:
3246 Res = SplitVecOp_Gather(cast<MemSDNode>(N), OpNo);
3247 break;
3248 case ISD::VSELECT:
3249 Res = SplitVecOp_VSELECT(N, OpNo);
3250 break;
3253 case ISD::SINT_TO_FP:
3254 case ISD::UINT_TO_FP:
3255 case ISD::VP_SINT_TO_FP:
3256 case ISD::VP_UINT_TO_FP:
3257 if (N->getValueType(0).bitsLT(
3258 N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType()))
3259 Res = SplitVecOp_TruncateHelper(N);
3260 else
3261 Res = SplitVecOp_UnaryOp(N);
3262 break;
3265 Res = SplitVecOp_FP_TO_XINT_SAT(N);
3266 break;
3267 case ISD::FP_TO_SINT:
3268 case ISD::FP_TO_UINT:
3269 case ISD::VP_FP_TO_SINT:
3270 case ISD::VP_FP_TO_UINT:
3274 case ISD::FP_EXTEND:
3275 case ISD::SIGN_EXTEND:
3276 case ISD::ZERO_EXTEND:
3277 case ISD::ANY_EXTEND:
3278 case ISD::FTRUNC:
3279 case ISD::LROUND:
3280 case ISD::LLROUND:
3281 case ISD::LRINT:
3282 case ISD::LLRINT:
3283 Res = SplitVecOp_UnaryOp(N);
3284 break;
3285 case ISD::FLDEXP:
3286 Res = SplitVecOp_FPOpDifferentTypes(N);
3287 break;
3288
3289 case ISD::SCMP:
3290 case ISD::UCMP:
3291 Res = SplitVecOp_CMP(N);
3292 break;
3293
3297 Res = SplitVecOp_ExtVecInRegOp(N);
3298 break;
3299
3302 case ISD::VECREDUCE_ADD:
3303 case ISD::VECREDUCE_MUL:
3304 case ISD::VECREDUCE_AND:
3305 case ISD::VECREDUCE_OR:
3306 case ISD::VECREDUCE_XOR:
3315 Res = SplitVecOp_VECREDUCE(N, OpNo);
3316 break;
3319 Res = SplitVecOp_VECREDUCE_SEQ(N);
3320 break;
3321 case ISD::VP_REDUCE_FADD:
3322 case ISD::VP_REDUCE_SEQ_FADD:
3323 case ISD::VP_REDUCE_FMUL:
3324 case ISD::VP_REDUCE_SEQ_FMUL:
3325 case ISD::VP_REDUCE_ADD:
3326 case ISD::VP_REDUCE_MUL:
3327 case ISD::VP_REDUCE_AND:
3328 case ISD::VP_REDUCE_OR:
3329 case ISD::VP_REDUCE_XOR:
3330 case ISD::VP_REDUCE_SMAX:
3331 case ISD::VP_REDUCE_SMIN:
3332 case ISD::VP_REDUCE_UMAX:
3333 case ISD::VP_REDUCE_UMIN:
3334 case ISD::VP_REDUCE_FMAX:
3335 case ISD::VP_REDUCE_FMIN:
3336 case ISD::VP_REDUCE_FMAXIMUM:
3337 case ISD::VP_REDUCE_FMINIMUM:
3338 Res = SplitVecOp_VP_REDUCE(N, OpNo);
3339 break;
3340 case ISD::VP_CTTZ_ELTS:
3341 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
3342 Res = SplitVecOp_VP_CttzElements(N);
3343 break;
3344 }
3345
3346 // If the result is null, the sub-method took care of registering results etc.
3347 if (!Res.getNode()) return false;
3348
3349 // If the result is N, the sub-method updated N in place. Tell the legalizer
3350 // core about this.
3351 if (Res.getNode() == N)
3352 return true;
3353
3354 if (N->isStrictFPOpcode())
3355 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
3356 "Invalid operand expansion");
3357 else
3358 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
3359 "Invalid operand expansion");
3360
3361 ReplaceValueWith(SDValue(N, 0), Res);
3362 return false;
3363}
3364
3365SDValue DAGTypeLegalizer::SplitVecOp_VSELECT(SDNode *N, unsigned OpNo) {
3366 // The only possibility for an illegal operand is the mask, since result type
3367 // legalization would have handled this node already otherwise.
3368 assert(OpNo == 0 && "Illegal operand must be mask");
3369
3370 SDValue Mask = N->getOperand(0);
3371 SDValue Src0 = N->getOperand(1);
3372 SDValue Src1 = N->getOperand(2);
3373 EVT Src0VT = Src0.getValueType();
3374 SDLoc DL(N);
3375 assert(Mask.getValueType().isVector() && "VSELECT without a vector mask?");
3376
3377 SDValue Lo, Hi;
3378 GetSplitVector(N->getOperand(0), Lo, Hi);
3379 assert(Lo.getValueType() == Hi.getValueType() &&
3380 "Lo and Hi have differing types");
3381
3382 EVT LoOpVT, HiOpVT;
3383 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(Src0VT);
3384 assert(LoOpVT == HiOpVT && "Asymmetric vector split?");
3385
3386 SDValue LoOp0, HiOp0, LoOp1, HiOp1, LoMask, HiMask;
3387 std::tie(LoOp0, HiOp0) = DAG.SplitVector(Src0, DL);
3388 std::tie(LoOp1, HiOp1) = DAG.SplitVector(Src1, DL);
3389 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
3390
3391 SDValue LoSelect =
3392 DAG.getNode(ISD::VSELECT, DL, LoOpVT, LoMask, LoOp0, LoOp1);
3393 SDValue HiSelect =
3394 DAG.getNode(ISD::VSELECT, DL, HiOpVT, HiMask, HiOp0, HiOp1);
3395
3396 return DAG.getNode(ISD::CONCAT_VECTORS, DL, Src0VT, LoSelect, HiSelect);
3397}
3398
3399SDValue DAGTypeLegalizer::SplitVecOp_VECREDUCE(SDNode *N, unsigned OpNo) {
3400 EVT ResVT = N->getValueType(0);
3401 SDValue Lo, Hi;
3402 SDLoc dl(N);
3403
3404 SDValue VecOp = N->getOperand(OpNo);
3405 EVT VecVT = VecOp.getValueType();
3406 assert(VecVT.isVector() && "Can only split reduce vector operand");
3407 GetSplitVector(VecOp, Lo, Hi);
3408 EVT LoOpVT, HiOpVT;
3409 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(VecVT);
3410
3411 // Use the appropriate scalar instruction on the split subvectors before
3412 // reducing the now partially reduced smaller vector.
3413 unsigned CombineOpc = ISD::getVecReduceBaseOpcode(N->getOpcode());
3414 SDValue Partial = DAG.getNode(CombineOpc, dl, LoOpVT, Lo, Hi, N->getFlags());
3415 return DAG.getNode(N->getOpcode(), dl, ResVT, Partial, N->getFlags());
3416}
3417
3418SDValue DAGTypeLegalizer::SplitVecOp_VECREDUCE_SEQ(SDNode *N) {
3419 EVT ResVT = N->getValueType(0);
3420 SDValue Lo, Hi;
3421 SDLoc dl(N);
3422
3423 SDValue AccOp = N->getOperand(0);
3424 SDValue VecOp = N->getOperand(1);
3425 SDNodeFlags Flags = N->getFlags();
3426
3427 EVT VecVT = VecOp.getValueType();
3428 assert(VecVT.isVector() && "Can only split reduce vector operand");
3429 GetSplitVector(VecOp, Lo, Hi);
3430 EVT LoOpVT, HiOpVT;
3431 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(VecVT);
3432
3433 // Reduce low half.
3434 SDValue Partial = DAG.getNode(N->getOpcode(), dl, ResVT, AccOp, Lo, Flags);
3435
3436 // Reduce high half, using low half result as initial value.
3437 return DAG.getNode(N->getOpcode(), dl, ResVT, Partial, Hi, Flags);
3438}
3439
3440SDValue DAGTypeLegalizer::SplitVecOp_VP_REDUCE(SDNode *N, unsigned OpNo) {
3441 assert(N->isVPOpcode() && "Expected VP opcode");
3442 assert(OpNo == 1 && "Can only split reduce vector operand");
3443
3444 unsigned Opc = N->getOpcode();
3445 EVT ResVT = N->getValueType(0);
3446 SDValue Lo, Hi;
3447 SDLoc dl(N);
3448
3449 SDValue VecOp = N->getOperand(OpNo);
3450 EVT VecVT = VecOp.getValueType();
3451 assert(VecVT.isVector() && "Can only split reduce vector operand");
3452 GetSplitVector(VecOp, Lo, Hi);
3453
3454 SDValue MaskLo, MaskHi;
3455 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(2));
3456
3457 SDValue EVLLo, EVLHi;
3458 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(N->getOperand(3), VecVT, dl);
3459
3460 const SDNodeFlags Flags = N->getFlags();
3461
3462 SDValue ResLo =
3463 DAG.getNode(Opc, dl, ResVT, {N->getOperand(0), Lo, MaskLo, EVLLo}, Flags);
3464 return DAG.getNode(Opc, dl, ResVT, {ResLo, Hi, MaskHi, EVLHi}, Flags);
3465}
3466
3467SDValue DAGTypeLegalizer::SplitVecOp_UnaryOp(SDNode *N) {
3468 // The result has a legal vector type, but the input needs splitting.
3469 EVT ResVT = N->getValueType(0);
3470 SDValue Lo, Hi;
3471 SDLoc dl(N);
3472 GetSplitVector(N->getOperand(N->isStrictFPOpcode() ? 1 : 0), Lo, Hi);
3473 EVT InVT = Lo.getValueType();
3474
3475 EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
3476 InVT.getVectorElementCount());
3477
3478 if (N->isStrictFPOpcode()) {
3479 Lo = DAG.getNode(N->getOpcode(), dl, { OutVT, MVT::Other },
3480 { N->getOperand(0), Lo });
3481 Hi = DAG.getNode(N->getOpcode(), dl, { OutVT, MVT::Other },
3482 { N->getOperand(0), Hi });
3483
3484 // Build a factor node to remember that this operation is independent
3485 // of the other one.
3486 SDValue Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
3487 Hi.getValue(1));
3488
3489 // Legalize the chain result - switch anything that used the old chain to
3490 // use the new one.
3491 ReplaceValueWith(SDValue(N, 1), Ch);
3492 } else if (N->getNumOperands() == 3) {
3493 assert(N->isVPOpcode() && "Expected VP opcode");
3494 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
3495 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
3496 std::tie(EVLLo, EVLHi) =
3497 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), dl);
3498 Lo = DAG.getNode(N->getOpcode(), dl, OutVT, Lo, MaskLo, EVLLo);
3499 Hi = DAG.getNode(N->getOpcode(), dl, OutVT, Hi, MaskHi, EVLHi);
3500 } else {
3501 Lo = DAG.getNode(N->getOpcode(), dl, OutVT, Lo);
3502 Hi = DAG.getNode(N->getOpcode(), dl, OutVT, Hi);
3503 }
3504
3505 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
3506}
3507
3508SDValue DAGTypeLegalizer::SplitVecOp_BITCAST(SDNode *N) {
3509 // For example, i64 = BITCAST v4i16 on alpha. Typically the vector will
3510 // end up being split all the way down to individual components. Convert the
3511 // split pieces into integers and reassemble.
3512 EVT ResVT = N->getValueType(0);
3513 SDValue Lo, Hi;
3514 GetSplitVector(N->getOperand(0), Lo, Hi);
3515 SDLoc dl(N);
3516
3517 if (ResVT.isScalableVector()) {
3518 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(ResVT);
3519 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
3520 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
3521 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
3522 }
3523
3524 Lo = BitConvertToInteger(Lo);
3525 Hi = BitConvertToInteger(Hi);
3526
3527 if (DAG.getDataLayout().isBigEndian())
3528 std::swap(Lo, Hi);
3529
3530 return DAG.getNode(ISD::BITCAST, dl, ResVT, JoinIntegers(Lo, Hi));
3531}
3532
3533SDValue DAGTypeLegalizer::SplitVecOp_INSERT_SUBVECTOR(SDNode *N,
3534 unsigned OpNo) {
3535 assert(OpNo == 1 && "Invalid OpNo; can only split SubVec.");
3536 // We know that the result type is legal.
3537 EVT ResVT = N->getValueType(0);
3538
3539 SDValue Vec = N->getOperand(0);
3540 SDValue SubVec = N->getOperand(1);
3541 SDValue Idx = N->getOperand(2);
3542 SDLoc dl(N);
3543
3544 SDValue Lo, Hi;
3545 GetSplitVector(SubVec, Lo, Hi);
3546
3547 uint64_t IdxVal = Idx->getAsZExtVal();
3548 uint64_t LoElts = Lo.getValueType().getVectorMinNumElements();
3549
3550 SDValue FirstInsertion =
3551 DAG.getNode(ISD::INSERT_SUBVECTOR, dl, ResVT, Vec, Lo, Idx);
3552 SDValue SecondInsertion =
3553 DAG.getNode(ISD::INSERT_SUBVECTOR, dl, ResVT, FirstInsertion, Hi,
3554 DAG.getVectorIdxConstant(IdxVal + LoElts, dl));
3555
3556 return SecondInsertion;
3557}
3558
3559SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
3560 // We know that the extracted result type is legal.
3561 EVT SubVT = N->getValueType(0);
3562 SDValue Idx = N->getOperand(1);
3563 SDLoc dl(N);
3564 SDValue Lo, Hi;
3565
3566 GetSplitVector(N->getOperand(0), Lo, Hi);
3567
3568 uint64_t LoEltsMin = Lo.getValueType().getVectorMinNumElements();
3569 uint64_t IdxVal = Idx->getAsZExtVal();
3570
3571 if (IdxVal < LoEltsMin) {
3572 assert(IdxVal + SubVT.getVectorMinNumElements() <= LoEltsMin &&
3573 "Extracted subvector crosses vector split!");
3574 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, SubVT, Lo, Idx);
3575 } else if (SubVT.isScalableVector() ==
3576 N->getOperand(0).getValueType().isScalableVector())
3577 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, SubVT, Hi,
3578 DAG.getVectorIdxConstant(IdxVal - LoEltsMin, dl));
3579
3580 // After this point the DAG node only permits extracting fixed-width
3581 // subvectors from scalable vectors.
3582 assert(SubVT.isFixedLengthVector() &&
3583 "Extracting scalable subvector from fixed-width unsupported");
3584
3585 // If the element type is i1 and we're not promoting the result, then we may
3586 // end up loading the wrong data since the bits are packed tightly into
3587 // bytes. For example, if we extract a v4i1 (legal) from a nxv4i1 (legal)
3588 // type at index 4, then we will load a byte starting at index 0.
3589 if (SubVT.getScalarType() == MVT::i1)
3590 report_fatal_error("Don't know how to extract fixed-width predicate "
3591 "subvector from a scalable predicate vector");
3592
3593 // Spill the vector to the stack. We should use the alignment for
3594 // the smallest part.
3595 SDValue Vec = N->getOperand(0);
3596 EVT VecVT = Vec.getValueType();
3597 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
3599 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
3600 auto &MF = DAG.getMachineFunction();
3601 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
3602 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
3603
3604 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
3605 SmallestAlign);
3606
3607 // Extract the subvector by loading the correct part.
3608 StackPtr = TLI.getVectorSubVecPointer(DAG, StackPtr, VecVT, SubVT, Idx);
3609
3610 return DAG.getLoad(
3611 SubVT, dl, Store, StackPtr,
3612 MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()));
3613}
3614
3615SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
3616 SDValue Vec = N->getOperand(0);
3617 SDValue Idx = N->getOperand(1);
3618 EVT VecVT = Vec.getValueType();
3619
3620 if (const ConstantSDNode *Index = dyn_cast<ConstantSDNode>(Idx)) {
3621 uint64_t IdxVal = Index->getZExtValue();
3622
3623 SDValue Lo, Hi;
3624 GetSplitVector(Vec, Lo, Hi);
3625
3626 uint64_t LoElts = Lo.getValueType().getVectorMinNumElements();
3627
3628 if (IdxVal < LoElts)
3629 return SDValue(DAG.UpdateNodeOperands(N, Lo, Idx), 0);
3630 else if (!Vec.getValueType().isScalableVector())
3631 return SDValue(DAG.UpdateNodeOperands(N, Hi,
3632 DAG.getConstant(IdxVal - LoElts, SDLoc(N),
3633 Idx.getValueType())), 0);
3634 }
3635
3636 // See if the target wants to custom expand this node.
3637 if (CustomLowerNode(N, N->getValueType(0), true))
3638 return SDValue();
3639
3640 // Make the vector elements byte-addressable if they aren't already.
3641 SDLoc dl(N);
3642 EVT EltVT = VecVT.getVectorElementType();
3643 if (!EltVT.isByteSized()) {
3644 EltVT = EltVT.changeTypeToInteger().getRoundIntegerType(*DAG.getContext());
3645 VecVT = VecVT.changeElementType(EltVT);
3646 Vec = DAG.getNode(ISD::ANY_EXTEND, dl, VecVT, Vec);
3647 SDValue NewExtract =
3648 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, Vec, Idx);
3649 return DAG.getAnyExtOrTrunc(NewExtract, dl, N->getValueType(0));
3650 }
3651
3652 // Store the vector to the stack.
3653 // In cases where the vector is illegal it will be broken down into parts
3654 // and stored in parts - we should use the alignment for the smallest part.
3655 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
3657 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
3658 auto &MF = DAG.getMachineFunction();
3659 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
3660 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
3661 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
3662 SmallestAlign);
3663
3664 // Load back the required element.
3665 StackPtr = TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Idx);
3666
3667 // EXTRACT_VECTOR_ELT can extend the element type to the width of the return
3668 // type, leaving the high bits undefined. But it can't truncate.
3669 assert(N->getValueType(0).bitsGE(EltVT) && "Illegal EXTRACT_VECTOR_ELT.");
3670
3671 return DAG.getExtLoad(
3672 ISD::EXTLOAD, dl, N->getValueType(0), Store, StackPtr,
3673 MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()), EltVT,
3674 commonAlignment(SmallestAlign, EltVT.getFixedSizeInBits() / 8));
3675}
3676
3677SDValue DAGTypeLegalizer::SplitVecOp_ExtVecInRegOp(SDNode *N) {
3678 SDValue Lo, Hi;
3679
3680 // *_EXTEND_VECTOR_INREG only reference the lower half of the input, so
3681 // splitting the result has the same effect as splitting the input operand.
3682 SplitVecRes_ExtVecInRegOp(N, Lo, Hi);
3683
3684 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), N->getValueType(0), Lo, Hi);
3685}
3686
3687SDValue DAGTypeLegalizer::SplitVecOp_Gather(MemSDNode *N, unsigned OpNo) {
3688 (void)OpNo;
3689 SDValue Lo, Hi;
3690 SplitVecRes_Gather(N, Lo, Hi);
3691
3692 SDValue Res = DAG.getNode(ISD::CONCAT_VECTORS, N, N->getValueType(0), Lo, Hi);
3693 ReplaceValueWith(SDValue(N, 0), Res);
3694 return SDValue();
3695}
3696
3697SDValue DAGTypeLegalizer::SplitVecOp_VP_STORE(VPStoreSDNode *N, unsigned OpNo) {
3698 assert(N->isUnindexed() && "Indexed vp_store of vector?");
3699 SDValue Ch = N->getChain();
3700 SDValue Ptr = N->getBasePtr();
3701 SDValue Offset = N->getOffset();
3702 assert(Offset.isUndef() && "Unexpected VP store offset");
3703 SDValue Mask = N->getMask();
3704 SDValue EVL = N->getVectorLength();
3705 SDValue Data = N->getValue();
3706 Align Alignment = N->getOriginalAlign();
3707 SDLoc DL(N);
3708
3709 SDValue DataLo, DataHi;
3710 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
3711 // Split Data operand
3712 GetSplitVector(Data, DataLo, DataHi);
3713 else
3714 std::tie(DataLo, DataHi) = DAG.SplitVector(Data, DL);
3715
3716 // Split Mask operand
3717 SDValue MaskLo, MaskHi;
3718 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC) {
3719 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
3720 } else {
3721 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
3722 GetSplitVector(Mask, MaskLo, MaskHi);
3723 else
3724 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
3725 }
3726
3727 EVT MemoryVT = N->getMemoryVT();
3728 EVT LoMemVT, HiMemVT;
3729 bool HiIsEmpty = false;
3730 std::tie(LoMemVT, HiMemVT) =
3731 DAG.GetDependentSplitDestVTs(MemoryVT, DataLo.getValueType(), &HiIsEmpty);
3732
3733 // Split EVL
3734 SDValue EVLLo, EVLHi;
3735 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(EVL, Data.getValueType(), DL);
3736
3737 SDValue Lo, Hi;
3738 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
3739 N->getPointerInfo(), MachineMemOperand::MOStore,
3740 LocationSize::beforeOrAfterPointer(), Alignment, N->getAAInfo(),
3741 N->getRanges());
3742
3743 Lo = DAG.getStoreVP(Ch, DL, DataLo, Ptr, Offset, MaskLo, EVLLo, LoMemVT, MMO,
3744 N->getAddressingMode(), N->isTruncatingStore(),
3745 N->isCompressingStore());
3746
3747 // If the hi vp_store has zero storage size, only the lo vp_store is needed.
3748 if (HiIsEmpty)
3749 return Lo;
3750
3751 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, DL, LoMemVT, DAG,
3752 N->isCompressingStore());
3753
3755 if (LoMemVT.isScalableVector()) {
3756 Alignment = commonAlignment(Alignment,
3757 LoMemVT.getSizeInBits().getKnownMinValue() / 8);
3758 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
3759 } else
3760 MPI = N->getPointerInfo().getWithOffset(
3761 LoMemVT.getStoreSize().getFixedValue());
3762
3763 MMO = DAG.getMachineFunction().getMachineMemOperand(
3765 Alignment, N->getAAInfo(), N->getRanges());
3766
3767 Hi = DAG.getStoreVP(Ch, DL, DataHi, Ptr, Offset, MaskHi, EVLHi, HiMemVT, MMO,
3768 N->getAddressingMode(), N->isTruncatingStore(),
3769 N->isCompressingStore());
3770
3771 // Build a factor node to remember that this store is independent of the
3772 // other one.
3773 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
3774}
3775
3776SDValue DAGTypeLegalizer::SplitVecOp_VP_STRIDED_STORE(VPStridedStoreSDNode *N,
3777 unsigned OpNo) {
3778 assert(N->isUnindexed() && "Indexed vp_strided_store of a vector?");
3779 assert(N->getOffset().isUndef() && "Unexpected VP strided store offset");
3780
3781 SDLoc DL(N);
3782
3783 SDValue Data = N->getValue();
3784 SDValue LoData, HiData;
3785 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
3786 GetSplitVector(Data, LoData, HiData);
3787 else
3788 std::tie(LoData, HiData) = DAG.SplitVector(Data, DL);
3789
3790 EVT LoMemVT, HiMemVT;
3791 bool HiIsEmpty = false;
3792 std::tie(LoMemVT, HiMemVT) = DAG.GetDependentSplitDestVTs(
3793 N->getMemoryVT(), LoData.getValueType(), &HiIsEmpty);
3794
3795 SDValue Mask = N->getMask();
3796 SDValue LoMask, HiMask;
3797 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC)
3798 SplitVecRes_SETCC(Mask.getNode(), LoMask, HiMask);
3799 else if (getTypeAction(Mask.getValueType()) ==
3801 GetSplitVector(Mask, LoMask, HiMask);
3802 else
3803 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
3804
3805 SDValue LoEVL, HiEVL;
3806 std::tie(LoEVL, HiEVL) =
3807 DAG.SplitEVL(N->getVectorLength(), Data.getValueType(), DL);
3808
3809 // Generate the low vp_strided_store
3810 SDValue Lo = DAG.getStridedStoreVP(
3811 N->getChain(), DL, LoData, N->getBasePtr(), N->getOffset(),
3812 N->getStride(), LoMask, LoEVL, LoMemVT, N->getMemOperand(),
3813 N->getAddressingMode(), N->isTruncatingStore(), N->isCompressingStore());
3814
3815 // If the high vp_strided_store has zero storage size, only the low
3816 // vp_strided_store is needed.
3817 if (HiIsEmpty)
3818 return Lo;
3819
3820 // Generate the high vp_strided_store.
3821 // To calculate the high base address, we need to sum to the low base
3822 // address stride number of bytes for each element already stored by low,
3823 // that is: Ptr = Ptr + (LoEVL * Stride)
3824 EVT PtrVT = N->getBasePtr().getValueType();
3826 DAG.getNode(ISD::MUL, DL, PtrVT, LoEVL,
3827 DAG.getSExtOrTrunc(N->getStride(), DL, PtrVT));
3828 SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, N->getBasePtr(), Increment);
3829
3830 Align Alignment = N->getOriginalAlign();
3831 if (LoMemVT.isScalableVector())
3832 Alignment = commonAlignment(Alignment,
3833 LoMemVT.getSizeInBits().getKnownMinValue() / 8);
3834
3835 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
3836 MachinePointerInfo(N->getPointerInfo().getAddrSpace()),
3838 Alignment, N->getAAInfo(), N->getRanges());
3839
3840 SDValue Hi = DAG.getStridedStoreVP(
3841 N->getChain(), DL, HiData, Ptr, N->getOffset(), N->getStride(), HiMask,
3842 HiEVL, HiMemVT, MMO, 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 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
3848}
3849
3850SDValue DAGTypeLegalizer::SplitVecOp_MSTORE(MaskedStoreSDNode *N,
3851 unsigned OpNo) {
3852 assert(N->isUnindexed() && "Indexed masked store of vector?");
3853 SDValue Ch = N->getChain();
3854 SDValue Ptr = N->getBasePtr();
3855 SDValue Offset = N->getOffset();
3856 assert(Offset.isUndef() && "Unexpected indexed masked store offset");
3857 SDValue Mask = N->getMask();
3858 SDValue Data = N->getValue();
3859 Align Alignment = N->getOriginalAlign();
3860 SDLoc DL(N);
3861
3862 SDValue DataLo, DataHi;
3863 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
3864 // Split Data operand
3865 GetSplitVector(Data, DataLo, DataHi);
3866 else
3867 std::tie(DataLo, DataHi) = DAG.SplitVector(Data, DL);
3868
3869 // Split Mask operand
3870 SDValue MaskLo, MaskHi;
3871 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC) {
3872 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
3873 } else {
3874 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
3875 GetSplitVector(Mask, MaskLo, MaskHi);
3876 else
3877 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
3878 }
3879
3880 EVT MemoryVT = N->getMemoryVT();
3881 EVT LoMemVT, HiMemVT;
3882 bool HiIsEmpty = false;
3883 std::tie(LoMemVT, HiMemVT) =
3884 DAG.GetDependentSplitDestVTs(MemoryVT, DataLo.getValueType(), &HiIsEmpty);
3885
3886 SDValue Lo, Hi, Res;
3887 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
3888 N->getPointerInfo(), MachineMemOperand::MOStore,
3889 LocationSize::beforeOrAfterPointer(), Alignment, N->getAAInfo(),
3890 N->getRanges());
3891
3892 Lo = DAG.getMaskedStore(Ch, DL, DataLo, Ptr, Offset, MaskLo, LoMemVT, MMO,
3893 N->getAddressingMode(), N->isTruncatingStore(),
3894 N->isCompressingStore());
3895
3896 if (HiIsEmpty) {
3897 // The hi masked store has zero storage size.
3898 // Only the lo masked store is needed.
3899 Res = Lo;
3900 } else {
3901
3902 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, DL, LoMemVT, DAG,
3903 N->isCompressingStore());
3904
3906 if (LoMemVT.isScalableVector()) {
3907 Alignment = commonAlignment(
3908 Alignment, LoMemVT.getSizeInBits().getKnownMinValue() / 8);
3909 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
3910 } else
3911 MPI = N->getPointerInfo().getWithOffset(
3912 LoMemVT.getStoreSize().getFixedValue());
3913
3914 MMO = DAG.getMachineFunction().getMachineMemOperand(
3916 Alignment, N->getAAInfo(), N->getRanges());
3917
3918 Hi = DAG.getMaskedStore(Ch, DL, DataHi, Ptr, Offset, MaskHi, HiMemVT, MMO,
3919 N->getAddressingMode(), N->isTruncatingStore(),
3920 N->isCompressingStore());
3921
3922 // Build a factor node to remember that this store is independent of the
3923 // other one.
3924 Res = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
3925 }
3926
3927 return Res;
3928}
3929
3930SDValue DAGTypeLegalizer::SplitVecOp_Scatter(MemSDNode *N, unsigned OpNo) {
3931 SDValue Ch = N->getChain();
3932 SDValue Ptr = N->getBasePtr();
3933 EVT MemoryVT = N->getMemoryVT();
3934 Align Alignment = N->getOriginalAlign();
3935 SDLoc DL(N);
3936 struct Operands {
3937 SDValue Mask;
3938 SDValue Index;
3939 SDValue Scale;
3940 SDValue Data;
3941 } Ops = [&]() -> Operands {
3942 if (auto *MSC = dyn_cast<MaskedScatterSDNode>(N)) {
3943 return {MSC->getMask(), MSC->getIndex(), MSC->getScale(),
3944 MSC->getValue()};
3945 }
3946 auto *VPSC = cast<VPScatterSDNode>(N);
3947 return {VPSC->getMask(), VPSC->getIndex(), VPSC->getScale(),
3948 VPSC->getValue()};
3949 }();
3950 // Split all operands
3951
3952 EVT LoMemVT, HiMemVT;
3953 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
3954
3955 SDValue DataLo, DataHi;
3956 if (getTypeAction(Ops.Data.getValueType()) == TargetLowering::TypeSplitVector)
3957 // Split Data operand
3958 GetSplitVector(Ops.Data, DataLo, DataHi);
3959 else
3960 std::tie(DataLo, DataHi) = DAG.SplitVector(Ops.Data, DL);
3961
3962 // Split Mask operand
3963 SDValue MaskLo, MaskHi;
3964 if (OpNo == 1 && Ops.Mask.getOpcode() == ISD::SETCC) {
3965 SplitVecRes_SETCC(Ops.Mask.getNode(), MaskLo, MaskHi);
3966 } else {
3967 std::tie(MaskLo, MaskHi) = SplitMask(Ops.Mask, DL);
3968 }
3969
3970 SDValue IndexHi, IndexLo;
3971 if (getTypeAction(Ops.Index.getValueType()) ==
3973 GetSplitVector(Ops.Index, IndexLo, IndexHi);
3974 else
3975 std::tie(IndexLo, IndexHi) = DAG.SplitVector(Ops.Index, DL);
3976
3977 SDValue Lo;
3978 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
3979 N->getPointerInfo(), MachineMemOperand::MOStore,
3980 LocationSize::beforeOrAfterPointer(), Alignment, N->getAAInfo(),
3981 N->getRanges());
3982
3983 if (auto *MSC = dyn_cast<MaskedScatterSDNode>(N)) {
3984 SDValue OpsLo[] = {Ch, DataLo, MaskLo, Ptr, IndexLo, Ops.Scale};
3985 Lo =
3986 DAG.getMaskedScatter(DAG.getVTList(MVT::Other), LoMemVT, DL, OpsLo, MMO,
3987 MSC->getIndexType(), MSC->isTruncatingStore());
3988
3989 // The order of the Scatter operation after split is well defined. The "Hi"
3990 // part comes after the "Lo". So these two operations should be chained one
3991 // after another.
3992 SDValue OpsHi[] = {Lo, DataHi, MaskHi, Ptr, IndexHi, Ops.Scale};
3993 return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), HiMemVT, DL, OpsHi,
3994 MMO, MSC->getIndexType(),
3995 MSC->isTruncatingStore());
3996 }
3997 auto *VPSC = cast<VPScatterSDNode>(N);
3998 SDValue EVLLo, EVLHi;
3999 std::tie(EVLLo, EVLHi) =
4000 DAG.SplitEVL(VPSC->getVectorLength(), Ops.Data.getValueType(), DL);
4001
4002 SDValue OpsLo[] = {Ch, DataLo, Ptr, IndexLo, Ops.Scale, MaskLo, EVLLo};
4003 Lo = DAG.getScatterVP(DAG.getVTList(MVT::Other), LoMemVT, DL, OpsLo, MMO,
4004 VPSC->getIndexType());
4005
4006 // The order of the Scatter operation after split is well defined. The "Hi"
4007 // part comes after the "Lo". So these two operations should be chained one
4008 // after another.
4009 SDValue OpsHi[] = {Lo, DataHi, Ptr, IndexHi, Ops.Scale, MaskHi, EVLHi};
4010 return DAG.getScatterVP(DAG.getVTList(MVT::Other), HiMemVT, DL, OpsHi, MMO,
4011 VPSC->getIndexType());
4012}
4013
4014SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) {
4015 assert(N->isUnindexed() && "Indexed store of vector?");
4016 assert(OpNo == 1 && "Can only split the stored value");
4017 SDLoc DL(N);
4018
4019 bool isTruncating = N->isTruncatingStore();
4020 SDValue Ch = N->getChain();
4021 SDValue Ptr = N->getBasePtr();
4022 EVT MemoryVT = N->getMemoryVT();
4023 Align Alignment = N->getOriginalAlign();
4024 MachineMemOperand::Flags MMOFlags = N->getMemOperand()->getFlags();
4025 AAMDNodes AAInfo = N->getAAInfo();
4026 SDValue Lo, Hi;
4027 GetSplitVector(N->getOperand(1), Lo, Hi);
4028
4029 EVT LoMemVT, HiMemVT;
4030 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
4031
4032 // Scalarize if the split halves are not byte-sized.
4033 if (!LoMemVT.isByteSized() || !HiMemVT.isByteSized())
4034 return TLI.scalarizeVectorStore(N, DAG);
4035
4036 if (isTruncating)
4037 Lo = DAG.getTruncStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), LoMemVT,
4038 Alignment, MMOFlags, AAInfo);
4039 else
4040 Lo = DAG.getStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), Alignment, MMOFlags,
4041 AAInfo);
4042
4044 IncrementPointer(N, LoMemVT, MPI, Ptr);
4045
4046 if (isTruncating)
4047 Hi = DAG.getTruncStore(Ch, DL, Hi, Ptr, MPI,
4048 HiMemVT, Alignment, MMOFlags, AAInfo);
4049 else
4050 Hi = DAG.getStore(Ch, DL, Hi, Ptr, MPI, Alignment, MMOFlags, AAInfo);
4051
4052 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4053}
4054
4055SDValue DAGTypeLegalizer::SplitVecOp_CONCAT_VECTORS(SDNode *N) {
4056 SDLoc DL(N);
4057
4058 // The input operands all must have the same type, and we know the result
4059 // type is valid. Convert this to a buildvector which extracts all the
4060 // input elements.
4061 // TODO: If the input elements are power-two vectors, we could convert this to
4062 // a new CONCAT_VECTORS node with elements that are half-wide.
4064 EVT EltVT = N->getValueType(0).getVectorElementType();
4065 for (const SDValue &Op : N->op_values()) {
4066 for (unsigned i = 0, e = Op.getValueType().getVectorNumElements();
4067 i != e; ++i) {
4068 Elts.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltVT, Op,
4069 DAG.getVectorIdxConstant(i, DL)));
4070 }
4071 }
4072
4073 return DAG.getBuildVector(N->getValueType(0), DL, Elts);
4074}
4075
4076SDValue DAGTypeLegalizer::SplitVecOp_TruncateHelper(SDNode *N) {
4077 // The result type is legal, but the input type is illegal. If splitting
4078 // ends up with the result type of each half still being legal, just
4079 // do that. If, however, that would result in an illegal result type,
4080 // we can try to get more clever with power-two vectors. Specifically,
4081 // split the input type, but also widen the result element size, then
4082 // concatenate the halves and truncate again. For example, consider a target
4083 // where v8i8 is legal and v8i32 is not (ARM, which doesn't have 256-bit
4084 // vectors). To perform a "%res = v8i8 trunc v8i32 %in" we do:
4085 // %inlo = v4i32 extract_subvector %in, 0
4086 // %inhi = v4i32 extract_subvector %in, 4
4087 // %lo16 = v4i16 trunc v4i32 %inlo
4088 // %hi16 = v4i16 trunc v4i32 %inhi
4089 // %in16 = v8i16 concat_vectors v4i16 %lo16, v4i16 %hi16
4090 // %res = v8i8 trunc v8i16 %in16
4091 //
4092 // Without this transform, the original truncate would end up being
4093 // scalarized, which is pretty much always a last resort.
4094 unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
4095 SDValue InVec = N->getOperand(OpNo);
4096 EVT InVT = InVec->getValueType(0);
4097 EVT OutVT = N->getValueType(0);
4098 ElementCount NumElements = OutVT.getVectorElementCount();
4099 bool IsFloat = OutVT.isFloatingPoint();
4100
4101 unsigned InElementSize = InVT.getScalarSizeInBits();
4102 unsigned OutElementSize = OutVT.getScalarSizeInBits();