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