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