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