LLVM 23.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
58 R = ScalarizeVecRes_LOOP_DEPENDENCE_MASK(N);
59 break;
60 case ISD::MERGE_VALUES: R = ScalarizeVecRes_MERGE_VALUES(N, ResNo);break;
61 case ISD::BITCAST: R = ScalarizeVecRes_BITCAST(N); break;
62 case ISD::BUILD_VECTOR: R = ScalarizeVecRes_BUILD_VECTOR(N); break;
63 case ISD::EXTRACT_SUBVECTOR: R = ScalarizeVecRes_EXTRACT_SUBVECTOR(N); break;
64 case ISD::FP_ROUND: R = ScalarizeVecRes_FP_ROUND(N); break;
66 R = ScalarizeVecRes_CONVERT_FROM_ARBITRARY_FP(N);
67 break;
68 case ISD::AssertZext:
69 case ISD::AssertSext:
70 case ISD::FPOWI:
72 R = ScalarizeVecRes_UnaryOpWithExtraInput(N);
73 break;
74 case ISD::INSERT_VECTOR_ELT: R = ScalarizeVecRes_INSERT_VECTOR_ELT(N); break;
76 R = ScalarizeVecRes_ATOMIC_LOAD(cast<AtomicSDNode>(N));
77 break;
78 case ISD::LOAD: R = ScalarizeVecRes_LOAD(cast<LoadSDNode>(N));break;
79 case ISD::SCALAR_TO_VECTOR: R = ScalarizeVecRes_SCALAR_TO_VECTOR(N); break;
80 case ISD::SIGN_EXTEND_INREG: R = ScalarizeVecRes_InregOp(N); break;
81 case ISD::VSELECT: R = ScalarizeVecRes_VSELECT(N); break;
82 case ISD::SELECT: R = ScalarizeVecRes_SELECT(N); break;
83 case ISD::SELECT_CC: R = ScalarizeVecRes_SELECT_CC(N); break;
84 case ISD::SETCC: R = ScalarizeVecRes_SETCC(N); break;
85 case ISD::POISON:
86 case ISD::UNDEF: R = ScalarizeVecRes_UNDEF(N); break;
87 case ISD::VECTOR_SHUFFLE: R = ScalarizeVecRes_VECTOR_SHUFFLE(N); break;
88 case ISD::IS_FPCLASS: R = ScalarizeVecRes_IS_FPCLASS(N); break;
92 R = ScalarizeVecRes_VecInregOp(N);
93 break;
94 case ISD::ABS:
95 case ISD::ANY_EXTEND:
96 case ISD::BITREVERSE:
97 case ISD::BSWAP:
98 case ISD::CTLZ:
100 case ISD::CTPOP:
101 case ISD::CTTZ:
103 case ISD::FABS:
104 case ISD::FACOS:
105 case ISD::FASIN:
106 case ISD::FATAN:
107 case ISD::FCEIL:
108 case ISD::FCOS:
109 case ISD::FCOSH:
110 case ISD::FEXP:
111 case ISD::FEXP2:
112 case ISD::FEXP10:
113 case ISD::FFLOOR:
114 case ISD::FLOG:
115 case ISD::FLOG10:
116 case ISD::FLOG2:
117 case ISD::FNEARBYINT:
118 case ISD::FNEG:
119 case ISD::FREEZE:
120 case ISD::ARITH_FENCE:
121 case ISD::FP_EXTEND:
122 case ISD::FP_TO_SINT:
123 case ISD::FP_TO_UINT:
124 case ISD::FRINT:
125 case ISD::LRINT:
126 case ISD::LLRINT:
127 case ISD::FROUND:
128 case ISD::FROUNDEVEN:
129 case ISD::LROUND:
130 case ISD::LLROUND:
131 case ISD::FSIN:
132 case ISD::FSINH:
133 case ISD::FSQRT:
134 case ISD::FTAN:
135 case ISD::FTANH:
136 case ISD::FTRUNC:
137 case ISD::SIGN_EXTEND:
138 case ISD::SINT_TO_FP:
139 case ISD::TRUNCATE:
140 case ISD::UINT_TO_FP:
141 case ISD::ZERO_EXTEND:
143 R = ScalarizeVecRes_UnaryOp(N);
144 break;
146 R = ScalarizeVecRes_ADDRSPACECAST(N);
147 break;
148 case ISD::FMODF:
149 case ISD::FFREXP:
150 case ISD::FSINCOS:
151 case ISD::FSINCOSPI:
152 R = ScalarizeVecRes_UnaryOpWithTwoResults(N, ResNo);
153 break;
154 case ISD::ADD:
155 case ISD::AND:
156 case ISD::AVGCEILS:
157 case ISD::AVGCEILU:
158 case ISD::AVGFLOORS:
159 case ISD::AVGFLOORU:
160 case ISD::FADD:
161 case ISD::FCOPYSIGN:
162 case ISD::FDIV:
163 case ISD::FMUL:
164 case ISD::FMINNUM:
165 case ISD::FMAXNUM:
168 case ISD::FMINIMUM:
169 case ISD::FMAXIMUM:
170 case ISD::FMINIMUMNUM:
171 case ISD::FMAXIMUMNUM:
172 case ISD::FLDEXP:
173 case ISD::ABDS:
174 case ISD::ABDU:
175 case ISD::SMIN:
176 case ISD::SMAX:
177 case ISD::UMIN:
178 case ISD::UMAX:
179
180 case ISD::SADDSAT:
181 case ISD::UADDSAT:
182 case ISD::SSUBSAT:
183 case ISD::USUBSAT:
184 case ISD::SSHLSAT:
185 case ISD::USHLSAT:
186
187 case ISD::FPOW:
188 case ISD::FATAN2:
189 case ISD::FREM:
190 case ISD::FSUB:
191 case ISD::MUL:
192 case ISD::MULHS:
193 case ISD::MULHU:
194 case ISD::OR:
195 case ISD::SDIV:
196 case ISD::SREM:
197 case ISD::SUB:
198 case ISD::UDIV:
199 case ISD::UREM:
200 case ISD::XOR:
201 case ISD::SHL:
202 case ISD::SRA:
203 case ISD::SRL:
204 case ISD::ROTL:
205 case ISD::ROTR:
206 case ISD::CLMUL:
207 case ISD::CLMULR:
208 case ISD::CLMULH:
209 R = ScalarizeVecRes_BinOp(N);
210 break;
211
212 case ISD::MASKED_UDIV:
213 case ISD::MASKED_SDIV:
214 case ISD::MASKED_UREM:
215 case ISD::MASKED_SREM:
216 R = ScalarizeVecRes_MaskedBinOp(N);
217 break;
218
219 case ISD::SCMP:
220 case ISD::UCMP:
221 R = ScalarizeVecRes_CMP(N);
222 break;
223
224 case ISD::FMA:
225 case ISD::FSHL:
226 case ISD::FSHR:
227 R = ScalarizeVecRes_TernaryOp(N);
228 break;
229
230#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
231 case ISD::STRICT_##DAGN:
232#include "llvm/IR/ConstrainedOps.def"
233 R = ScalarizeVecRes_StrictFPOp(N);
234 break;
235
238 R = ScalarizeVecRes_FP_TO_XINT_SAT(N);
239 break;
240
241 case ISD::UADDO:
242 case ISD::SADDO:
243 case ISD::USUBO:
244 case ISD::SSUBO:
245 case ISD::UMULO:
246 case ISD::SMULO:
247 R = ScalarizeVecRes_OverflowOp(N, ResNo);
248 break;
249 case ISD::SMULFIX:
250 case ISD::SMULFIXSAT:
251 case ISD::UMULFIX:
252 case ISD::UMULFIXSAT:
253 case ISD::SDIVFIX:
254 case ISD::SDIVFIXSAT:
255 case ISD::UDIVFIX:
256 case ISD::UDIVFIXSAT:
257 R = ScalarizeVecRes_FIX(N);
258 break;
259 }
260
261 // If R is null, the sub-method took care of registering the result.
262 if (R.getNode())
263 SetScalarizedVector(SDValue(N, ResNo), R);
264}
265
266SDValue DAGTypeLegalizer::ScalarizeVecRes_BinOp(SDNode *N) {
267 SDValue LHS = GetScalarizedVector(N->getOperand(0));
268 SDValue RHS = GetScalarizedVector(N->getOperand(1));
269 return DAG.getNode(N->getOpcode(), SDLoc(N),
270 LHS.getValueType(), LHS, RHS, N->getFlags());
271}
272
273SDValue DAGTypeLegalizer::ScalarizeVecRes_MaskedBinOp(SDNode *N) {
274 SDLoc DL(N);
275 SDValue LHS = GetScalarizedVector(N->getOperand(0));
276 SDValue RHS = GetScalarizedVector(N->getOperand(1));
277 SDValue Mask = N->getOperand(2);
278 EVT MaskVT = Mask.getValueType();
279 // The vselect result and input vectors need scalarizing, but it's
280 // not a given that the mask does. For instance, in AVX512 v1i1 is legal.
281 // See the similar logic in ScalarizeVecRes_SETCC.
282 if (getTypeAction(MaskVT) == TargetLowering::TypeScalarizeVector)
283 Mask = GetScalarizedVector(Mask);
284 else
285 Mask = DAG.getExtractVectorElt(DL, MaskVT.getVectorElementType(), Mask, 0);
286 // Vectors may have a different boolean contents to scalars, so truncate to i1
287 // and let type legalization promote appropriately.
288 Mask = DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, Mask);
289 // Masked binary ops don't have UB on disabled lanes but produce poison, so
290 // use 1 as the divisor to avoid division by zero and overflow.
291 SDValue Divisor = DAG.getSelect(DL, LHS.getValueType(), Mask, RHS,
292 DAG.getConstant(1, DL, LHS.getValueType()));
293 return DAG.getNode(ISD::getUnmaskedBinOpOpcode(N->getOpcode()), DL,
294 LHS.getValueType(), LHS, Divisor);
295}
296
297SDValue DAGTypeLegalizer::ScalarizeVecRes_CMP(SDNode *N) {
298 SDLoc DL(N);
299
300 SDValue LHS = N->getOperand(0);
301 SDValue RHS = N->getOperand(1);
302 if (getTypeAction(LHS.getValueType()) ==
304 LHS = GetScalarizedVector(LHS);
305 RHS = GetScalarizedVector(RHS);
306 } else {
307 EVT VT = LHS.getValueType().getVectorElementType();
308 LHS = DAG.getExtractVectorElt(DL, VT, LHS, 0);
309 RHS = DAG.getExtractVectorElt(DL, VT, RHS, 0);
310 }
311
312 return DAG.getNode(N->getOpcode(), SDLoc(N),
313 N->getValueType(0).getVectorElementType(), LHS, RHS);
314}
315
316SDValue DAGTypeLegalizer::ScalarizeVecRes_TernaryOp(SDNode *N) {
317 SDValue Op0 = GetScalarizedVector(N->getOperand(0));
318 SDValue Op1 = GetScalarizedVector(N->getOperand(1));
319 SDValue Op2 = GetScalarizedVector(N->getOperand(2));
320 return DAG.getNode(N->getOpcode(), SDLoc(N), Op0.getValueType(), Op0, Op1,
321 Op2, N->getFlags());
322}
323
324SDValue DAGTypeLegalizer::ScalarizeVecRes_FIX(SDNode *N) {
325 SDValue Op0 = GetScalarizedVector(N->getOperand(0));
326 SDValue Op1 = GetScalarizedVector(N->getOperand(1));
327 SDValue Op2 = N->getOperand(2);
328 return DAG.getNode(N->getOpcode(), SDLoc(N), Op0.getValueType(), Op0, Op1,
329 Op2, N->getFlags());
330}
331
333DAGTypeLegalizer::ScalarizeVecRes_UnaryOpWithTwoResults(SDNode *N,
334 unsigned ResNo) {
335 assert(N->getValueType(0).getVectorNumElements() == 1 &&
336 "Unexpected vector type!");
337 SDValue Elt = GetScalarizedVector(N->getOperand(0));
338
339 EVT VT0 = N->getValueType(0);
340 EVT VT1 = N->getValueType(1);
341 SDLoc dl(N);
342
343 SDNode *ScalarNode =
344 DAG.getNode(N->getOpcode(), dl,
345 {VT0.getScalarType(), VT1.getScalarType()}, Elt)
346 .getNode();
347
348 // Replace the other vector result not being explicitly scalarized here.
349 unsigned OtherNo = 1 - ResNo;
350 EVT OtherVT = N->getValueType(OtherNo);
351 if (getTypeAction(OtherVT) == TargetLowering::TypeScalarizeVector) {
352 SetScalarizedVector(SDValue(N, OtherNo), SDValue(ScalarNode, OtherNo));
353 } else {
354 SDValue OtherVal = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, OtherVT,
355 SDValue(ScalarNode, OtherNo));
356 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
357 }
358
359 return SDValue(ScalarNode, ResNo);
360}
361
362SDValue DAGTypeLegalizer::ScalarizeVecRes_StrictFPOp(SDNode *N) {
363 EVT VT = N->getValueType(0).getVectorElementType();
364 unsigned NumOpers = N->getNumOperands();
365 SDValue Chain = N->getOperand(0);
366 EVT ValueVTs[] = {VT, MVT::Other};
367 SDLoc dl(N);
368
369 SmallVector<SDValue, 4> Opers(NumOpers);
370
371 // The Chain is the first operand.
372 Opers[0] = Chain;
373
374 // Now process the remaining operands.
375 for (unsigned i = 1; i < NumOpers; ++i) {
376 SDValue Oper = N->getOperand(i);
377 EVT OperVT = Oper.getValueType();
378
379 if (OperVT.isVector()) {
380 if (getTypeAction(OperVT) == TargetLowering::TypeScalarizeVector)
381 Oper = GetScalarizedVector(Oper);
382 else
383 Oper =
384 DAG.getExtractVectorElt(dl, OperVT.getVectorElementType(), Oper, 0);
385 }
386
387 Opers[i] = Oper;
388 }
389
390 SDValue Result = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(ValueVTs),
391 Opers, N->getFlags());
392
393 // Legalize the chain result - switch anything that used the old chain to
394 // use the new one.
395 ReplaceValueWith(SDValue(N, 1), Result.getValue(1));
396 return Result;
397}
398
399SDValue DAGTypeLegalizer::ScalarizeVecRes_OverflowOp(SDNode *N,
400 unsigned ResNo) {
401 SDLoc DL(N);
402 EVT ResVT = N->getValueType(0);
403 EVT OvVT = N->getValueType(1);
404
405 SDValue ScalarLHS, ScalarRHS;
406 if (getTypeAction(ResVT) == TargetLowering::TypeScalarizeVector) {
407 ScalarLHS = GetScalarizedVector(N->getOperand(0));
408 ScalarRHS = GetScalarizedVector(N->getOperand(1));
409 } else {
410 SmallVector<SDValue, 1> ElemsLHS, ElemsRHS;
411 DAG.ExtractVectorElements(N->getOperand(0), ElemsLHS);
412 DAG.ExtractVectorElements(N->getOperand(1), ElemsRHS);
413 ScalarLHS = ElemsLHS[0];
414 ScalarRHS = ElemsRHS[0];
415 }
416
417 SDVTList ScalarVTs = DAG.getVTList(
419 SDNode *ScalarNode = DAG.getNode(N->getOpcode(), DL, ScalarVTs,
420 {ScalarLHS, ScalarRHS}, N->getFlags())
421 .getNode();
422
423 // Replace the other vector result not being explicitly scalarized here.
424 unsigned OtherNo = 1 - ResNo;
425 EVT OtherVT = N->getValueType(OtherNo);
426 if (getTypeAction(OtherVT) == TargetLowering::TypeScalarizeVector) {
427 SetScalarizedVector(SDValue(N, OtherNo), SDValue(ScalarNode, OtherNo));
428 } else {
429 SDValue OtherVal = DAG.getNode(
430 ISD::SCALAR_TO_VECTOR, DL, OtherVT, SDValue(ScalarNode, OtherNo));
431 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
432 }
433
434 return SDValue(ScalarNode, ResNo);
435}
436
437SDValue DAGTypeLegalizer::ScalarizeVecRes_MERGE_VALUES(SDNode *N,
438 unsigned ResNo) {
439 SDValue Op = DisintegrateMERGE_VALUES(N, ResNo);
440 return GetScalarizedVector(Op);
441}
442
443SDValue DAGTypeLegalizer::ScalarizeVecRes_LOOP_DEPENDENCE_MASK(SDNode *N) {
444 SDLoc DL(N);
445 SDValue SourceValue = N->getOperand(0);
446 SDValue SinkValue = N->getOperand(1);
447 SDValue EltSizeInBytes = N->getOperand(2);
448 SDValue LaneOffset = N->getOperand(3);
449
450 EVT PtrVT = SourceValue->getValueType(0);
451 bool IsReadAfterWrite = N->getOpcode() == ISD::LOOP_DEPENDENCE_RAW_MASK;
452
453 // Take the difference between the pointers and divided by the element size,
454 // to see how many lanes separate them.
455 SDValue Diff = DAG.getNode(ISD::SUB, DL, PtrVT, SinkValue, SourceValue);
456 if (IsReadAfterWrite)
457 Diff = DAG.getNode(ISD::ABS, DL, PtrVT, Diff);
458 Diff = DAG.getNode(ISD::SDIV, DL, PtrVT, Diff, EltSizeInBytes);
459
460 // The pointers do not alias if:
461 // * Diff <= 0 || LaneOffset < Diff (WAR_MASK)
462 // * Diff == 0 || LaneOffset < abs(Diff) (RAW_MASK)
463 // Note: If LaneOffset is zero, both cases will fold to "true".
464 EVT CmpVT = TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(),
465 Diff.getValueType());
466 SDValue Zero = DAG.getConstant(0, DL, PtrVT);
467 SDValue Cmp = DAG.getSetCC(DL, CmpVT, Diff, Zero,
468 IsReadAfterWrite ? ISD::SETEQ : ISD::SETLE);
469 return DAG.getNode(ISD::OR, DL, CmpVT, Cmp,
470 DAG.getSetCC(DL, CmpVT, LaneOffset, Diff, ISD::SETULT));
471}
472
473SDValue DAGTypeLegalizer::ScalarizeVecRes_BITCAST(SDNode *N) {
474 SDValue Op = N->getOperand(0);
475 if (getTypeAction(Op.getValueType()) == TargetLowering::TypeScalarizeVector)
476 Op = GetScalarizedVector(Op);
477 EVT NewVT = N->getValueType(0).getVectorElementType();
478 return DAG.getNode(ISD::BITCAST, SDLoc(N),
479 NewVT, Op);
480}
481
482SDValue DAGTypeLegalizer::ScalarizeVecRes_BUILD_VECTOR(SDNode *N) {
483 EVT EltVT = N->getValueType(0).getVectorElementType();
484 SDValue InOp = N->getOperand(0);
485 // The BUILD_VECTOR operands may be of wider element types and
486 // we may need to truncate them back to the requested return type.
487 if (EltVT.isInteger())
488 return DAG.getNode(ISD::TRUNCATE, SDLoc(N), EltVT, InOp);
489 return InOp;
490}
491
492SDValue DAGTypeLegalizer::ScalarizeVecRes_EXTRACT_SUBVECTOR(SDNode *N) {
493 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
494 N->getValueType(0).getVectorElementType(),
495 N->getOperand(0), N->getOperand(1));
496}
497
498SDValue DAGTypeLegalizer::ScalarizeVecRes_FP_ROUND(SDNode *N) {
499 SDLoc DL(N);
500 SDValue Op = N->getOperand(0);
501 EVT OpVT = Op.getValueType();
502 // The result needs scalarizing, but it's not a given that the source does.
503 // See similar logic in ScalarizeVecRes_UnaryOp.
504 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
505 Op = GetScalarizedVector(Op);
506 } else {
507 EVT VT = OpVT.getVectorElementType();
508 Op = DAG.getExtractVectorElt(DL, VT, Op, 0);
509 }
510 return DAG.getNode(ISD::FP_ROUND, DL,
511 N->getValueType(0).getVectorElementType(), Op,
512 N->getOperand(1));
513}
514
515SDValue DAGTypeLegalizer::ScalarizeVecRes_CONVERT_FROM_ARBITRARY_FP(SDNode *N) {
516 SDLoc DL(N);
517 SDValue Op = N->getOperand(0);
518 EVT OpVT = Op.getValueType();
519 // The result needs scalarizing, but it's not a given that the source does.
520 // See similar logic in ScalarizeVecRes_UnaryOp.
521 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
522 Op = GetScalarizedVector(Op);
523 } else {
524 EVT VT = OpVT.getVectorElementType();
525 Op = DAG.getExtractVectorElt(DL, VT, Op, 0);
526 }
527 return DAG.getNode(ISD::CONVERT_FROM_ARBITRARY_FP, DL,
528 N->getValueType(0).getVectorElementType(), Op,
529 N->getOperand(1));
530}
531
532SDValue DAGTypeLegalizer::ScalarizeVecRes_UnaryOpWithExtraInput(SDNode *N) {
533 SDValue Op = GetScalarizedVector(N->getOperand(0));
534 return DAG.getNode(N->getOpcode(), SDLoc(N), Op.getValueType(), Op,
535 N->getOperand(1));
536}
537
538SDValue DAGTypeLegalizer::ScalarizeVecRes_INSERT_VECTOR_ELT(SDNode *N) {
539 // The value to insert may have a wider type than the vector element type,
540 // so be sure to truncate it to the element type if necessary.
541 SDValue Op = N->getOperand(1);
542 EVT EltVT = N->getValueType(0).getVectorElementType();
543 if (Op.getValueType() != EltVT)
544 // FIXME: Can this happen for floating point types?
545 Op = DAG.getNode(ISD::TRUNCATE, SDLoc(N), EltVT, Op);
546 return Op;
547}
548
549SDValue DAGTypeLegalizer::ScalarizeVecRes_ATOMIC_LOAD(AtomicSDNode *N) {
550 SDValue Result = DAG.getAtomicLoad(
551 N->getExtensionType(), SDLoc(N), N->getMemoryVT().getVectorElementType(),
552 N->getValueType(0).getVectorElementType(), N->getChain(), N->getBasePtr(),
553 N->getMemOperand());
554
555 // Legalize the chain result - switch anything that used the old chain to
556 // use the new one.
557 ReplaceValueWith(SDValue(N, 1), Result.getValue(1));
558 return Result;
559}
560
561SDValue DAGTypeLegalizer::ScalarizeVecRes_LOAD(LoadSDNode *N) {
562 assert(N->isUnindexed() && "Indexed vector load?");
563
564 SDValue Result = DAG.getLoad(
565 ISD::UNINDEXED, N->getExtensionType(),
566 N->getValueType(0).getVectorElementType(), SDLoc(N), N->getChain(),
567 N->getBasePtr(), DAG.getUNDEF(N->getBasePtr().getValueType()),
568 N->getPointerInfo(), N->getMemoryVT().getVectorElementType(),
569 N->getBaseAlign(), N->getMemOperand()->getFlags(), N->getAAInfo());
570
571 // Legalize the chain result - switch anything that used the old chain to
572 // use the new one.
573 ReplaceValueWith(SDValue(N, 1), Result.getValue(1));
574 return Result;
575}
576
577SDValue DAGTypeLegalizer::ScalarizeVecRes_UnaryOp(SDNode *N) {
578 // Get the dest type - it doesn't always match the input type, e.g. int_to_fp.
579 EVT DestVT = N->getValueType(0).getVectorElementType();
580 SDValue Op = N->getOperand(0);
581 EVT OpVT = Op.getValueType();
582 SDLoc DL(N);
583 // The result needs scalarizing, but it's not a given that the source does.
584 // This is a workaround for targets where it's impossible to scalarize the
585 // result of a conversion, because the source type is legal.
586 // For instance, this happens on AArch64: v1i1 is illegal but v1i{8,16,32}
587 // are widened to v8i8, v4i16, and v2i32, which is legal, because v1i64 is
588 // legal and was not scalarized.
589 // See the similar logic in ScalarizeVecRes_SETCC
590 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
591 Op = GetScalarizedVector(Op);
592 } else {
593 EVT VT = OpVT.getVectorElementType();
594 Op = DAG.getExtractVectorElt(DL, VT, Op, 0);
595 }
596 return DAG.getNode(N->getOpcode(), SDLoc(N), DestVT, Op, N->getFlags());
597}
598
599SDValue DAGTypeLegalizer::ScalarizeVecRes_InregOp(SDNode *N) {
600 EVT EltVT = N->getValueType(0).getVectorElementType();
601 EVT ExtVT = cast<VTSDNode>(N->getOperand(1))->getVT().getVectorElementType();
602 SDValue LHS = GetScalarizedVector(N->getOperand(0));
603 return DAG.getNode(N->getOpcode(), SDLoc(N), EltVT,
604 LHS, DAG.getValueType(ExtVT));
605}
606
607SDValue DAGTypeLegalizer::ScalarizeVecRes_VecInregOp(SDNode *N) {
608 SDLoc DL(N);
609 SDValue Op = N->getOperand(0);
610
611 EVT OpVT = Op.getValueType();
612 EVT OpEltVT = OpVT.getVectorElementType();
613 EVT EltVT = N->getValueType(0).getVectorElementType();
614
615 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
616 Op = GetScalarizedVector(Op);
617 } else {
618 Op = DAG.getExtractVectorElt(DL, OpEltVT, Op, 0);
619 }
620
621 switch (N->getOpcode()) {
623 return DAG.getNode(ISD::ANY_EXTEND, DL, EltVT, Op);
625 return DAG.getNode(ISD::SIGN_EXTEND, DL, EltVT, Op);
627 return DAG.getNode(ISD::ZERO_EXTEND, DL, EltVT, Op);
628 }
629
630 llvm_unreachable("Illegal extend_vector_inreg opcode");
631}
632
633SDValue DAGTypeLegalizer::ScalarizeVecRes_ADDRSPACECAST(SDNode *N) {
634 EVT DestVT = N->getValueType(0).getVectorElementType();
635 SDValue Op = N->getOperand(0);
636 EVT OpVT = Op.getValueType();
637 SDLoc DL(N);
638 // The result needs scalarizing, but it's not a given that the source does.
639 // This is a workaround for targets where it's impossible to scalarize the
640 // result of a conversion, because the source type is legal.
641 // For instance, this happens on AArch64: v1i1 is illegal but v1i{8,16,32}
642 // are widened to v8i8, v4i16, and v2i32, which is legal, because v1i64 is
643 // legal and was not scalarized.
644 // See the similar logic in ScalarizeVecRes_SETCC
645 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
646 Op = GetScalarizedVector(Op);
647 } else {
648 EVT VT = OpVT.getVectorElementType();
649 Op = DAG.getExtractVectorElt(DL, VT, Op, 0);
650 }
651 auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
652 unsigned SrcAS = AddrSpaceCastN->getSrcAddressSpace();
653 unsigned DestAS = AddrSpaceCastN->getDestAddressSpace();
654 return DAG.getAddrSpaceCast(DL, DestVT, Op, SrcAS, DestAS);
655}
656
657SDValue DAGTypeLegalizer::ScalarizeVecRes_SCALAR_TO_VECTOR(SDNode *N) {
658 // If the operand is wider than the vector element type then it is implicitly
659 // truncated. Make that explicit here.
660 EVT EltVT = N->getValueType(0).getVectorElementType();
661 SDValue InOp = N->getOperand(0);
662 if (InOp.getValueType() != EltVT)
663 return DAG.getNode(ISD::TRUNCATE, SDLoc(N), EltVT, InOp);
664 return InOp;
665}
666
667SDValue DAGTypeLegalizer::ScalarizeVecRes_VSELECT(SDNode *N) {
668 SDValue Cond = N->getOperand(0);
669 EVT OpVT = Cond.getValueType();
670 SDLoc DL(N);
671 // The vselect result and true/value operands needs scalarizing, but it's
672 // not a given that the Cond does. For instance, in AVX512 v1i1 is legal.
673 // See the similar logic in ScalarizeVecRes_SETCC
674 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
675 Cond = GetScalarizedVector(Cond);
676 } else {
677 EVT VT = OpVT.getVectorElementType();
678 Cond = DAG.getExtractVectorElt(DL, VT, Cond, 0);
679 }
680
681 SDValue LHS = GetScalarizedVector(N->getOperand(1));
683 TLI.getBooleanContents(false, false);
684 TargetLowering::BooleanContent VecBool = TLI.getBooleanContents(true, false);
685
686 // If integer and float booleans have different contents then we can't
687 // reliably optimize in all cases. There is a full explanation for this in
688 // DAGCombiner::visitSELECT() where the same issue affects folding
689 // (select C, 0, 1) to (xor C, 1).
690 if (TLI.getBooleanContents(false, false) !=
691 TLI.getBooleanContents(false, true)) {
692 // At least try the common case where the boolean is generated by a
693 // comparison.
694 if (Cond->getOpcode() == ISD::SETCC) {
695 EVT OpVT = Cond->getOperand(0).getValueType();
696 ScalarBool = TLI.getBooleanContents(OpVT.getScalarType());
697 VecBool = TLI.getBooleanContents(OpVT);
698 } else
700 }
701
702 EVT CondVT = Cond.getValueType();
703 if (ScalarBool != VecBool) {
704 switch (ScalarBool) {
706 break;
710 // Vector read from all ones, scalar expects a single 1 so mask.
711 Cond = DAG.getNode(ISD::AND, SDLoc(N), CondVT,
712 Cond, DAG.getConstant(1, SDLoc(N), CondVT));
713 break;
717 // Vector reads from a one, scalar from all ones so sign extend.
718 Cond = DAG.getNode(ISD::SIGN_EXTEND_INREG, SDLoc(N), CondVT,
719 Cond, DAG.getValueType(MVT::i1));
720 break;
721 }
722 }
723
724 // Truncate the condition if needed
725 auto BoolVT = getSetCCResultType(CondVT);
726 if (BoolVT.bitsLT(CondVT))
727 Cond = DAG.getNode(ISD::TRUNCATE, SDLoc(N), BoolVT, Cond);
728
729 return DAG.getSelect(SDLoc(N),
730 LHS.getValueType(), Cond, LHS,
731 GetScalarizedVector(N->getOperand(2)));
732}
733
734SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT(SDNode *N) {
735 SDValue LHS = GetScalarizedVector(N->getOperand(1));
736 return DAG.getSelect(SDLoc(N),
737 LHS.getValueType(), N->getOperand(0), LHS,
738 GetScalarizedVector(N->getOperand(2)));
739}
740
741SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT_CC(SDNode *N) {
742 SDValue LHS = GetScalarizedVector(N->getOperand(2));
743 return DAG.getNode(ISD::SELECT_CC, SDLoc(N), LHS.getValueType(),
744 N->getOperand(0), N->getOperand(1),
745 LHS, GetScalarizedVector(N->getOperand(3)),
746 N->getOperand(4));
747}
748
749SDValue DAGTypeLegalizer::ScalarizeVecRes_UNDEF(SDNode *N) {
750 return DAG.getUNDEF(N->getValueType(0).getVectorElementType());
751}
752
753SDValue DAGTypeLegalizer::ScalarizeVecRes_VECTOR_SHUFFLE(SDNode *N) {
754 // Figure out if the scalar is the LHS or RHS and return it.
755 SDValue Arg = N->getOperand(2).getOperand(0);
756 if (Arg.isUndef())
757 return DAG.getUNDEF(N->getValueType(0).getVectorElementType());
758 unsigned Op = !cast<ConstantSDNode>(Arg)->isZero();
759 return GetScalarizedVector(N->getOperand(Op));
760}
761
762SDValue DAGTypeLegalizer::ScalarizeVecRes_FP_TO_XINT_SAT(SDNode *N) {
763 SDValue Src = N->getOperand(0);
764 EVT SrcVT = Src.getValueType();
765 SDLoc dl(N);
766
767 // Handle case where result is scalarized but operand is not
768 if (getTypeAction(SrcVT) == TargetLowering::TypeScalarizeVector)
769 Src = GetScalarizedVector(Src);
770 else
771 Src = DAG.getNode(
773 DAG.getConstant(0, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
774
775 EVT DstVT = N->getValueType(0).getVectorElementType();
776 return DAG.getNode(N->getOpcode(), dl, DstVT, Src, N->getOperand(1));
777}
778
779SDValue DAGTypeLegalizer::ScalarizeVecRes_SETCC(SDNode *N) {
780 assert(N->getValueType(0).isVector() &&
781 N->getOperand(0).getValueType().isVector() &&
782 "Operand types must be vectors");
783 SDValue LHS = N->getOperand(0);
784 SDValue RHS = N->getOperand(1);
785 EVT OpVT = LHS.getValueType();
786 EVT NVT = N->getValueType(0).getVectorElementType();
787 SDLoc DL(N);
788
789 // The result needs scalarizing, but it's not a given that the source does.
790 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
791 LHS = GetScalarizedVector(LHS);
792 RHS = GetScalarizedVector(RHS);
793 } else {
794 EVT VT = OpVT.getVectorElementType();
795 LHS = DAG.getExtractVectorElt(DL, VT, LHS, 0);
796 RHS = DAG.getExtractVectorElt(DL, VT, RHS, 0);
797 }
798
799 // Turn it into a scalar SETCC.
800 SDValue Res = DAG.getNode(ISD::SETCC, DL, MVT::i1, LHS, RHS,
801 N->getOperand(2));
802 // Vectors may have a different boolean contents to scalars. Promote the
803 // value appropriately.
804 ISD::NodeType ExtendCode =
805 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
806 return DAG.getNode(ExtendCode, DL, NVT, Res);
807}
808
809SDValue DAGTypeLegalizer::ScalarizeVecRes_IS_FPCLASS(SDNode *N) {
810 SDLoc DL(N);
811 SDValue Arg = N->getOperand(0);
812 SDValue Test = N->getOperand(1);
813 EVT ArgVT = Arg.getValueType();
814 EVT ResultVT = N->getValueType(0).getVectorElementType();
815
816 if (getTypeAction(ArgVT) == TargetLowering::TypeScalarizeVector) {
817 Arg = GetScalarizedVector(Arg);
818 } else {
819 EVT VT = ArgVT.getVectorElementType();
820 Arg = DAG.getExtractVectorElt(DL, VT, Arg, 0);
821 }
822
823 SDValue Res =
824 DAG.getNode(ISD::IS_FPCLASS, DL, MVT::i1, {Arg, Test}, N->getFlags());
825 // Vectors may have a different boolean contents to scalars. Promote the
826 // value appropriately.
827 ISD::NodeType ExtendCode =
828 TargetLowering::getExtendForContent(TLI.getBooleanContents(ArgVT));
829 return DAG.getNode(ExtendCode, DL, ResultVT, Res);
830}
831
832//===----------------------------------------------------------------------===//
833// Operand Vector Scalarization <1 x ty> -> ty.
834//===----------------------------------------------------------------------===//
835
836bool DAGTypeLegalizer::ScalarizeVectorOperand(SDNode *N, unsigned OpNo) {
837 LLVM_DEBUG(dbgs() << "Scalarize node operand " << OpNo << ": ";
838 N->dump(&DAG));
839 SDValue Res = SDValue();
840
841 switch (N->getOpcode()) {
842 default:
843#ifndef NDEBUG
844 dbgs() << "ScalarizeVectorOperand Op #" << OpNo << ": ";
845 N->dump(&DAG);
846 dbgs() << "\n";
847#endif
848 report_fatal_error("Do not know how to scalarize this operator's "
849 "operand!\n");
850 case ISD::BITCAST:
851 Res = ScalarizeVecOp_BITCAST(N);
852 break;
853 case ISD::FAKE_USE:
854 Res = ScalarizeVecOp_FAKE_USE(N);
855 break;
856 case ISD::ANY_EXTEND:
857 case ISD::ZERO_EXTEND:
858 case ISD::SIGN_EXTEND:
859 case ISD::TRUNCATE:
860 case ISD::FP_TO_SINT:
861 case ISD::FP_TO_UINT:
862 case ISD::SINT_TO_FP:
863 case ISD::UINT_TO_FP:
864 case ISD::LROUND:
865 case ISD::LLROUND:
866 case ISD::LRINT:
867 case ISD::LLRINT:
868 Res = ScalarizeVecOp_UnaryOp(N);
869 break;
873 Res = ScalarizeVecOp_UnaryOpWithExtraInput(N);
874 break;
879 Res = ScalarizeVecOp_UnaryOp_StrictFP(N);
880 break;
882 Res = ScalarizeVecOp_CONCAT_VECTORS(N);
883 break;
885 Res = ScalarizeVecOp_INSERT_SUBVECTOR(N, OpNo);
886 break;
888 Res = ScalarizeVecOp_EXTRACT_VECTOR_ELT(N);
889 break;
890 case ISD::VSELECT:
891 Res = ScalarizeVecOp_VSELECT(N);
892 break;
893 case ISD::SETCC:
894 Res = ScalarizeVecOp_VSETCC(N);
895 break;
898 Res = ScalarizeVecOp_VSTRICT_FSETCC(N, OpNo);
899 break;
900 case ISD::STORE:
901 Res = ScalarizeVecOp_STORE(cast<StoreSDNode>(N), OpNo);
902 break;
904 Res = ScalarizeVecOp_STRICT_FP_ROUND(N, OpNo);
905 break;
906 case ISD::FP_ROUND:
907 Res = ScalarizeVecOp_FP_ROUND(N, OpNo);
908 break;
910 Res = ScalarizeVecOp_STRICT_FP_EXTEND(N);
911 break;
912 case ISD::FP_EXTEND:
913 Res = ScalarizeVecOp_FP_EXTEND(N);
914 break;
930 Res = ScalarizeVecOp_VECREDUCE(N);
931 break;
934 Res = ScalarizeVecOp_VECREDUCE_SEQ(N);
935 break;
936 case ISD::SCMP:
937 case ISD::UCMP:
938 Res = ScalarizeVecOp_CMP(N);
939 break;
941 Res = ScalarizeVecOp_VECTOR_FIND_LAST_ACTIVE(N);
942 break;
943 case ISD::CTTZ_ELTS:
945 Res = ScalarizeVecOp_CTTZ_ELTS(N);
946 break;
947 case ISD::MASKED_UDIV:
948 case ISD::MASKED_SDIV:
949 case ISD::MASKED_UREM:
950 case ISD::MASKED_SREM:
951 Res = ScalarizeVecOp_MaskedBinOp(N, OpNo);
952 break;
953 }
954
955 // If the result is null, the sub-method took care of registering results etc.
956 if (!Res.getNode()) return false;
957
958 // If the result is N, the sub-method updated N in place. Tell the legalizer
959 // core about this.
960 if (Res.getNode() == N)
961 return true;
962
963 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
964 "Invalid operand expansion");
965
966 ReplaceValueWith(SDValue(N, 0), Res);
967 return false;
968}
969
970/// If the value to convert is a vector that needs to be scalarized, it must be
971/// <1 x ty>. Convert the element instead.
972SDValue DAGTypeLegalizer::ScalarizeVecOp_BITCAST(SDNode *N) {
973 SDValue Elt = GetScalarizedVector(N->getOperand(0));
974 return DAG.getNode(ISD::BITCAST, SDLoc(N),
975 N->getValueType(0), Elt);
976}
977
978// Need to legalize vector operands of fake uses. Must be <1 x ty>.
979SDValue DAGTypeLegalizer::ScalarizeVecOp_FAKE_USE(SDNode *N) {
980 assert(N->getOperand(1).getValueType().getVectorNumElements() == 1 &&
981 "Fake Use: Unexpected vector type!");
982 SDValue Elt = GetScalarizedVector(N->getOperand(1));
983 return DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, N->getOperand(0), Elt);
984}
985
986/// If the input is a vector that needs to be scalarized, it must be <1 x ty>.
987/// Do the operation on the element instead.
988SDValue DAGTypeLegalizer::ScalarizeVecOp_UnaryOp(SDNode *N) {
989 assert(N->getValueType(0).getVectorNumElements() == 1 &&
990 "Unexpected vector type!");
991 SDValue Elt = GetScalarizedVector(N->getOperand(0));
992 SDValue Op = DAG.getNode(N->getOpcode(), SDLoc(N),
993 N->getValueType(0).getScalarType(), Elt);
994 // Revectorize the result so the types line up with what the uses of this
995 // expression expect.
996 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Op);
997}
998
999/// Same as ScalarizeVecOp_UnaryOp with an extra operand (for example a
1000/// typesize).
1001SDValue DAGTypeLegalizer::ScalarizeVecOp_UnaryOpWithExtraInput(SDNode *N) {
1002 assert(N->getValueType(0).getVectorNumElements() == 1 &&
1003 "Unexpected vector type!");
1004 SDValue Elt = GetScalarizedVector(N->getOperand(0));
1005 SDValue Op =
1006 DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0).getScalarType(),
1007 Elt, N->getOperand(1));
1008 // Revectorize the result so the types line up with what the uses of this
1009 // expression expect.
1010 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Op);
1011}
1012
1013/// If the input is a vector that needs to be scalarized, it must be <1 x ty>.
1014/// Do the strict FP operation on the element instead.
1015SDValue DAGTypeLegalizer::ScalarizeVecOp_UnaryOp_StrictFP(SDNode *N) {
1016 assert(N->getValueType(0).getVectorNumElements() == 1 &&
1017 "Unexpected vector type!");
1018 SDValue Elt = GetScalarizedVector(N->getOperand(1));
1019 SDValue Res = DAG.getNode(N->getOpcode(), SDLoc(N),
1020 { N->getValueType(0).getScalarType(), MVT::Other },
1021 { N->getOperand(0), Elt });
1022 // Legalize the chain result - switch anything that used the old chain to
1023 // use the new one.
1024 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
1025 // Revectorize the result so the types line up with what the uses of this
1026 // expression expect.
1027 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
1028
1029 // Do our own replacement and return SDValue() to tell the caller that we
1030 // handled all replacements since caller can only handle a single result.
1031 ReplaceValueWith(SDValue(N, 0), Res);
1032 return SDValue();
1033}
1034
1035/// The vectors to concatenate have length one - use a BUILD_VECTOR instead.
1036SDValue DAGTypeLegalizer::ScalarizeVecOp_CONCAT_VECTORS(SDNode *N) {
1037 SmallVector<SDValue, 8> Ops(N->getNumOperands());
1038 for (unsigned i = 0, e = N->getNumOperands(); i < e; ++i)
1039 Ops[i] = GetScalarizedVector(N->getOperand(i));
1040 return DAG.getBuildVector(N->getValueType(0), SDLoc(N), Ops);
1041}
1042
1043/// The inserted subvector is to be scalarized - use insert vector element
1044/// instead.
1045SDValue DAGTypeLegalizer::ScalarizeVecOp_INSERT_SUBVECTOR(SDNode *N,
1046 unsigned OpNo) {
1047 // We should not be attempting to scalarize the containing vector
1048 assert(OpNo == 1);
1049 SDValue Elt = GetScalarizedVector(N->getOperand(1));
1050 SDValue ContainingVec = N->getOperand(0);
1051 return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(N),
1052 ContainingVec.getValueType(), ContainingVec, Elt,
1053 N->getOperand(2));
1054}
1055
1056/// If the input is a vector that needs to be scalarized, it must be <1 x ty>,
1057/// so just return the element, ignoring the index.
1058SDValue DAGTypeLegalizer::ScalarizeVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
1059 EVT VT = N->getValueType(0);
1060 SDValue Res = GetScalarizedVector(N->getOperand(0));
1061 if (Res.getValueType() != VT)
1062 Res = VT.isFloatingPoint()
1063 ? DAG.getNode(ISD::FP_EXTEND, SDLoc(N), VT, Res)
1064 : DAG.getNode(ISD::ANY_EXTEND, SDLoc(N), VT, Res);
1065 return Res;
1066}
1067
1068/// If the input condition is a vector that needs to be scalarized, it must be
1069/// <1 x i1>, so just convert to a normal ISD::SELECT
1070/// (still with vector output type since that was acceptable if we got here).
1071SDValue DAGTypeLegalizer::ScalarizeVecOp_VSELECT(SDNode *N) {
1072 SDValue ScalarCond = GetScalarizedVector(N->getOperand(0));
1073 EVT VT = N->getValueType(0);
1074
1075 return DAG.getNode(ISD::SELECT, SDLoc(N), VT, ScalarCond, N->getOperand(1),
1076 N->getOperand(2));
1077}
1078
1079/// If the operand is a vector that needs to be scalarized then the
1080/// result must be v1i1, so just convert to a scalar SETCC and wrap
1081/// with a scalar_to_vector since the res type is legal if we got here
1082SDValue DAGTypeLegalizer::ScalarizeVecOp_VSETCC(SDNode *N) {
1083 assert(N->getValueType(0).isVector() &&
1084 N->getOperand(0).getValueType().isVector() &&
1085 "Operand types must be vectors");
1086 assert(N->getValueType(0) == MVT::v1i1 && "Expected v1i1 type");
1087
1088 EVT VT = N->getValueType(0);
1089 SDValue LHS = GetScalarizedVector(N->getOperand(0));
1090 SDValue RHS = GetScalarizedVector(N->getOperand(1));
1091
1092 EVT OpVT = N->getOperand(0).getValueType();
1093 EVT NVT = VT.getVectorElementType();
1094 SDLoc DL(N);
1095 // Turn it into a scalar SETCC.
1096 SDValue Res = DAG.getNode(ISD::SETCC, DL, MVT::i1, LHS, RHS,
1097 N->getOperand(2));
1098
1099 // Vectors may have a different boolean contents to scalars. Promote the
1100 // value appropriately.
1101 ISD::NodeType ExtendCode =
1102 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
1103
1104 Res = DAG.getNode(ExtendCode, DL, NVT, Res);
1105
1106 return DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, VT, Res);
1107}
1108
1109// Similiar to ScalarizeVecOp_VSETCC, with added logic to update chains.
1110SDValue DAGTypeLegalizer::ScalarizeVecOp_VSTRICT_FSETCC(SDNode *N,
1111 unsigned OpNo) {
1112 assert(OpNo == 1 && "Wrong operand for scalarization!");
1113 assert(N->getValueType(0).isVector() &&
1114 N->getOperand(1).getValueType().isVector() &&
1115 "Operand types must be vectors");
1116 assert(N->getValueType(0) == MVT::v1i1 && "Expected v1i1 type");
1117
1118 EVT VT = N->getValueType(0);
1119 SDValue Ch = N->getOperand(0);
1120 SDValue LHS = GetScalarizedVector(N->getOperand(1));
1121 SDValue RHS = GetScalarizedVector(N->getOperand(2));
1122 SDValue CC = N->getOperand(3);
1123
1124 EVT OpVT = N->getOperand(1).getValueType();
1125 EVT NVT = VT.getVectorElementType();
1126 SDLoc DL(N);
1127 SDValue Res = DAG.getNode(N->getOpcode(), DL, {MVT::i1, MVT::Other},
1128 {Ch, LHS, RHS, CC});
1129
1130 // Legalize the chain result - switch anything that used the old chain to
1131 // use the new one.
1132 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
1133
1134 ISD::NodeType ExtendCode =
1135 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
1136
1137 Res = DAG.getNode(ExtendCode, DL, NVT, Res);
1138 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, VT, Res);
1139
1140 // Do our own replacement and return SDValue() to tell the caller that we
1141 // handled all replacements since caller can only handle a single result.
1142 ReplaceValueWith(SDValue(N, 0), Res);
1143 return SDValue();
1144}
1145
1146/// If the value to store is a vector that needs to be scalarized, it must be
1147/// <1 x ty>. Just store the element.
1148SDValue DAGTypeLegalizer::ScalarizeVecOp_STORE(StoreSDNode *N, unsigned OpNo){
1149 assert(N->isUnindexed() && "Indexed store of one-element vector?");
1150 assert(OpNo == 1 && "Do not know how to scalarize this operand!");
1151 SDLoc dl(N);
1152
1153 if (N->isTruncatingStore())
1154 return DAG.getTruncStore(
1155 N->getChain(), dl, GetScalarizedVector(N->getOperand(1)),
1156 N->getBasePtr(), N->getPointerInfo(),
1157 N->getMemoryVT().getVectorElementType(), N->getBaseAlign(),
1158 N->getMemOperand()->getFlags(), N->getAAInfo());
1159
1160 return DAG.getStore(N->getChain(), dl, GetScalarizedVector(N->getOperand(1)),
1161 N->getBasePtr(), N->getPointerInfo(), N->getBaseAlign(),
1162 N->getMemOperand()->getFlags(), N->getAAInfo());
1163}
1164
1165/// If the value to round is a vector that needs to be scalarized, it must be
1166/// <1 x ty>. Convert the element instead.
1167SDValue DAGTypeLegalizer::ScalarizeVecOp_FP_ROUND(SDNode *N, unsigned OpNo) {
1168 assert(OpNo == 0 && "Wrong operand for scalarization!");
1169 SDValue Elt = GetScalarizedVector(N->getOperand(0));
1170 SDValue Res = DAG.getNode(ISD::FP_ROUND, SDLoc(N),
1171 N->getValueType(0).getVectorElementType(), Elt,
1172 N->getOperand(1));
1173 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
1174}
1175
1176SDValue DAGTypeLegalizer::ScalarizeVecOp_STRICT_FP_ROUND(SDNode *N,
1177 unsigned OpNo) {
1178 assert(OpNo == 1 && "Wrong operand for scalarization!");
1179 SDValue Elt = GetScalarizedVector(N->getOperand(1));
1180 SDValue Res =
1181 DAG.getNode(ISD::STRICT_FP_ROUND, SDLoc(N),
1182 {N->getValueType(0).getVectorElementType(), MVT::Other},
1183 {N->getOperand(0), Elt, N->getOperand(2)});
1184 // Legalize the chain result - switch anything that used the old chain to
1185 // use the new one.
1186 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
1187
1188 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
1189
1190 // Do our own replacement and return SDValue() to tell the caller that we
1191 // handled all replacements since caller can only handle a single result.
1192 ReplaceValueWith(SDValue(N, 0), Res);
1193 return SDValue();
1194}
1195
1196/// If the value to extend is a vector that needs to be scalarized, it must be
1197/// <1 x ty>. Convert the element instead.
1198SDValue DAGTypeLegalizer::ScalarizeVecOp_FP_EXTEND(SDNode *N) {
1199 SDValue Elt = GetScalarizedVector(N->getOperand(0));
1200 SDValue Res = DAG.getNode(ISD::FP_EXTEND, SDLoc(N),
1201 N->getValueType(0).getVectorElementType(), Elt);
1202 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
1203}
1204
1205/// If the value to extend is a vector that needs to be scalarized, it must be
1206/// <1 x ty>. Convert the element instead.
1207SDValue DAGTypeLegalizer::ScalarizeVecOp_STRICT_FP_EXTEND(SDNode *N) {
1208 SDValue Elt = GetScalarizedVector(N->getOperand(1));
1209 SDValue Res =
1210 DAG.getNode(ISD::STRICT_FP_EXTEND, SDLoc(N),
1211 {N->getValueType(0).getVectorElementType(), MVT::Other},
1212 {N->getOperand(0), Elt});
1213 // Legalize the chain result - switch anything that used the old chain to
1214 // use the new one.
1215 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
1216
1217 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
1218
1219 // Do our own replacement and return SDValue() to tell the caller that we
1220 // handled all replacements since caller can only handle a single result.
1221 ReplaceValueWith(SDValue(N, 0), Res);
1222 return SDValue();
1223}
1224
1225SDValue DAGTypeLegalizer::ScalarizeVecOp_VECREDUCE(SDNode *N) {
1226 SDValue Res = GetScalarizedVector(N->getOperand(0));
1227 // Result type may be wider than element type.
1228 if (Res.getValueType() != N->getValueType(0))
1229 Res = DAG.getNode(ISD::ANY_EXTEND, SDLoc(N), N->getValueType(0), Res);
1230 return Res;
1231}
1232
1233SDValue DAGTypeLegalizer::ScalarizeVecOp_VECREDUCE_SEQ(SDNode *N) {
1234 SDValue AccOp = N->getOperand(0);
1235 SDValue VecOp = N->getOperand(1);
1236
1237 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(N->getOpcode());
1238
1239 SDValue Op = GetScalarizedVector(VecOp);
1240 return DAG.getNode(BaseOpc, SDLoc(N), N->getValueType(0),
1241 AccOp, Op, N->getFlags());
1242}
1243
1244SDValue DAGTypeLegalizer::ScalarizeVecOp_CMP(SDNode *N) {
1245 SDValue LHS = GetScalarizedVector(N->getOperand(0));
1246 SDValue RHS = GetScalarizedVector(N->getOperand(1));
1247
1248 EVT ResVT = N->getValueType(0).getVectorElementType();
1249 SDValue Cmp = DAG.getNode(N->getOpcode(), SDLoc(N), ResVT, LHS, RHS);
1250 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Cmp);
1251}
1252
1253SDValue DAGTypeLegalizer::ScalarizeVecOp_VECTOR_FIND_LAST_ACTIVE(SDNode *N) {
1254 // Since there is no "none-active" result, the only valid return for <1 x ty>
1255 // is 0. Note: Since we check the high mask during splitting this is safe.
1256 // As e.g., a <2 x ty> operation would split to:
1257 // any_active(%hi_mask) ? (1 + last_active(%hi_mask))
1258 // : `last_active(%lo_mask)`
1259 // Which then scalarizes to:
1260 // %mask[1] ? 1 : 0
1261 EVT VT = N->getValueType(0);
1262 return DAG.getConstant(0, SDLoc(N), VT);
1263}
1264
1265SDValue DAGTypeLegalizer::ScalarizeVecOp_CTTZ_ELTS(SDNode *N) {
1266 // The number of trailing zero elements is 1 if the element is 0, and 0
1267 // otherwise.
1268 if (N->getOpcode() == ISD::CTTZ_ELTS_ZERO_POISON)
1269 return DAG.getConstant(0, SDLoc(N), N->getValueType(0));
1270 SDValue Op = GetScalarizedVector(N->getOperand(0));
1271 SDValue SetCC =
1272 DAG.getSetCC(SDLoc(N), MVT::i1, Op,
1273 DAG.getConstant(0, SDLoc(N), Op.getValueType()), ISD::SETEQ);
1274 return DAG.getZExtOrTrunc(SetCC, SDLoc(N), N->getValueType(0));
1275}
1276
1277SDValue DAGTypeLegalizer::ScalarizeVecOp_MaskedBinOp(SDNode *N, unsigned OpNo) {
1278 assert(OpNo == 2 && "Can only scalarize mask operand");
1279 SDLoc DL(N);
1280 EVT VT = N->getOperand(0).getValueType().getVectorElementType();
1281 SDValue LHS = DAG.getExtractVectorElt(DL, VT, N->getOperand(0), 0);
1282 SDValue RHS = DAG.getExtractVectorElt(DL, VT, N->getOperand(1), 0);
1283 SDValue Mask = GetScalarizedVector(N->getOperand(2));
1284 // Vectors may have a different boolean contents to scalars, so truncate to i1
1285 // and let type legalization promote appropriately.
1286 Mask = DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, Mask);
1287 // Masked binary ops don't have UB on disabled lanes but produce poison, so
1288 // use 1 as the divisor to avoid division by zero and overflow.
1289 SDValue BinOp =
1290 DAG.getNode(ISD::getUnmaskedBinOpOpcode(N->getOpcode()), DL, VT, LHS,
1291 DAG.getSelect(DL, VT, Mask, RHS, DAG.getConstant(1, DL, VT)));
1292 return DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, N->getValueType(0), BinOp);
1293}
1294
1295//===----------------------------------------------------------------------===//
1296// Result Vector Splitting
1297//===----------------------------------------------------------------------===//
1298
1299/// This method is called when the specified result of the specified node is
1300/// found to need vector splitting. At this point, the node may also have
1301/// invalid operands or may have other results that need legalization, we just
1302/// know that (at least) one result needs vector splitting.
1303void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
1304 LLVM_DEBUG(dbgs() << "Split node result: "; N->dump(&DAG));
1305 SDValue Lo, Hi;
1306
1307 // See if the target wants to custom expand this node.
1308 if (CustomLowerNode(N, N->getValueType(ResNo), true))
1309 return;
1310
1311 switch (N->getOpcode()) {
1312 default:
1313#ifndef NDEBUG
1314 dbgs() << "SplitVectorResult #" << ResNo << ": ";
1315 N->dump(&DAG);
1316 dbgs() << "\n";
1317#endif
1318 report_fatal_error("Do not know how to split the result of this "
1319 "operator!\n");
1320
1323 SplitVecRes_LOOP_DEPENDENCE_MASK(N, Lo, Hi);
1324 break;
1325 case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, ResNo, Lo, Hi); break;
1326 case ISD::AssertZext: SplitVecRes_AssertZext(N, Lo, Hi); break;
1327 case ISD::AssertSext: SplitVecRes_AssertSext(N, Lo, Hi); break;
1328 case ISD::VSELECT:
1329 case ISD::SELECT:
1330 case ISD::VP_MERGE:
1331 case ISD::VP_SELECT: SplitRes_Select(N, Lo, Hi); break;
1332 case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break;
1333 case ISD::POISON:
1334 case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break;
1335 case ISD::BITCAST: SplitVecRes_BITCAST(N, Lo, Hi); break;
1336 case ISD::BUILD_VECTOR: SplitVecRes_BUILD_VECTOR(N, Lo, Hi); break;
1337 case ISD::CONCAT_VECTORS: SplitVecRes_CONCAT_VECTORS(N, Lo, Hi); break;
1338 case ISD::EXTRACT_SUBVECTOR: SplitVecRes_EXTRACT_SUBVECTOR(N, Lo, Hi); break;
1339 case ISD::INSERT_SUBVECTOR: SplitVecRes_INSERT_SUBVECTOR(N, Lo, Hi); break;
1340 case ISD::FPOWI:
1341 case ISD::FLDEXP:
1342 case ISD::FCOPYSIGN: SplitVecRes_FPOp_MultiType(N, Lo, Hi); break;
1343 case ISD::IS_FPCLASS: SplitVecRes_IS_FPCLASS(N, Lo, Hi); break;
1344 case ISD::INSERT_VECTOR_ELT: SplitVecRes_INSERT_VECTOR_ELT(N, Lo, Hi); break;
1345 case ISD::SPLAT_VECTOR:
1347 SplitVecRes_ScalarOp(N, Lo, Hi);
1348 break;
1349 case ISD::STEP_VECTOR:
1350 SplitVecRes_STEP_VECTOR(N, Lo, Hi);
1351 break;
1352 case ISD::SIGN_EXTEND_INREG: SplitVecRes_InregOp(N, Lo, Hi); break;
1353 case ISD::LOAD:
1354 SplitVecRes_LOAD(cast<LoadSDNode>(N), Lo, Hi);
1355 break;
1356 case ISD::VP_LOAD:
1357 SplitVecRes_VP_LOAD(cast<VPLoadSDNode>(N), Lo, Hi);
1358 break;
1359 case ISD::VP_LOAD_FF:
1360 SplitVecRes_VP_LOAD_FF(cast<VPLoadFFSDNode>(N), Lo, Hi);
1361 break;
1362 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
1363 SplitVecRes_VP_STRIDED_LOAD(cast<VPStridedLoadSDNode>(N), Lo, Hi);
1364 break;
1365 case ISD::MLOAD:
1366 SplitVecRes_MLOAD(cast<MaskedLoadSDNode>(N), Lo, Hi);
1367 break;
1368 case ISD::MGATHER:
1369 case ISD::VP_GATHER:
1370 SplitVecRes_Gather(cast<MemSDNode>(N), Lo, Hi, /*SplitSETCC*/ true);
1371 break;
1373 SplitVecRes_VECTOR_COMPRESS(N, Lo, Hi);
1374 break;
1375 case ISD::SETCC:
1376 case ISD::VP_SETCC:
1377 SplitVecRes_SETCC(N, Lo, Hi);
1378 break;
1380 SplitVecRes_VECTOR_REVERSE(N, Lo, Hi);
1381 break;
1383 SplitVecRes_VECTOR_SHUFFLE(cast<ShuffleVectorSDNode>(N), Lo, Hi);
1384 break;
1387 SplitVecRes_VECTOR_SPLICE(N, Lo, Hi);
1388 break;
1390 SplitVecRes_VECTOR_DEINTERLEAVE(N);
1391 return;
1393 SplitVecRes_VECTOR_INTERLEAVE(N);
1394 return;
1395 case ISD::VAARG:
1396 SplitVecRes_VAARG(N, Lo, Hi);
1397 break;
1398
1402 SplitVecRes_ExtVecInRegOp(N, Lo, Hi);
1403 break;
1404
1405 case ISD::ABS:
1406 case ISD::VP_ABS:
1407 case ISD::BITREVERSE:
1408 case ISD::VP_BITREVERSE:
1409 case ISD::BSWAP:
1410 case ISD::VP_BSWAP:
1411 case ISD::CTLZ:
1412 case ISD::VP_CTLZ:
1413 case ISD::CTTZ:
1414 case ISD::VP_CTTZ:
1416 case ISD::VP_CTLZ_ZERO_UNDEF:
1418 case ISD::VP_CTTZ_ZERO_UNDEF:
1419 case ISD::CTPOP:
1420 case ISD::VP_CTPOP:
1421 case ISD::FABS: case ISD::VP_FABS:
1422 case ISD::FACOS:
1423 case ISD::FASIN:
1424 case ISD::FATAN:
1425 case ISD::FCEIL:
1426 case ISD::VP_FCEIL:
1427 case ISD::FCOS:
1428 case ISD::FCOSH:
1429 case ISD::FEXP:
1430 case ISD::FEXP2:
1431 case ISD::FEXP10:
1432 case ISD::FFLOOR:
1433 case ISD::VP_FFLOOR:
1434 case ISD::FLOG:
1435 case ISD::FLOG10:
1436 case ISD::FLOG2:
1437 case ISD::FNEARBYINT:
1438 case ISD::VP_FNEARBYINT:
1439 case ISD::FNEG: case ISD::VP_FNEG:
1440 case ISD::FREEZE:
1441 case ISD::ARITH_FENCE:
1442 case ISD::FP_EXTEND:
1443 case ISD::VP_FP_EXTEND:
1444 case ISD::FP_ROUND:
1445 case ISD::VP_FP_ROUND:
1446 case ISD::FP_TO_SINT:
1447 case ISD::VP_FP_TO_SINT:
1448 case ISD::FP_TO_UINT:
1449 case ISD::VP_FP_TO_UINT:
1450 case ISD::FRINT:
1451 case ISD::VP_FRINT:
1452 case ISD::LRINT:
1453 case ISD::VP_LRINT:
1454 case ISD::LLRINT:
1455 case ISD::VP_LLRINT:
1456 case ISD::FROUND:
1457 case ISD::VP_FROUND:
1458 case ISD::FROUNDEVEN:
1459 case ISD::VP_FROUNDEVEN:
1460 case ISD::LROUND:
1461 case ISD::LLROUND:
1462 case ISD::FSIN:
1463 case ISD::FSINH:
1464 case ISD::FSQRT: case ISD::VP_SQRT:
1465 case ISD::FTAN:
1466 case ISD::FTANH:
1467 case ISD::FTRUNC:
1468 case ISD::VP_FROUNDTOZERO:
1469 case ISD::SINT_TO_FP:
1470 case ISD::VP_SINT_TO_FP:
1471 case ISD::TRUNCATE:
1472 case ISD::VP_TRUNCATE:
1473 case ISD::UINT_TO_FP:
1474 case ISD::VP_UINT_TO_FP:
1475 case ISD::FCANONICALIZE:
1478 SplitVecRes_UnaryOp(N, Lo, Hi);
1479 break;
1480 case ISD::ADDRSPACECAST:
1481 SplitVecRes_ADDRSPACECAST(N, Lo, Hi);
1482 break;
1483 case ISD::FMODF:
1484 case ISD::FFREXP:
1485 case ISD::FSINCOS:
1486 case ISD::FSINCOSPI:
1487 SplitVecRes_UnaryOpWithTwoResults(N, ResNo, Lo, Hi);
1488 break;
1489
1490 case ISD::ANY_EXTEND:
1491 case ISD::SIGN_EXTEND:
1492 case ISD::ZERO_EXTEND:
1493 case ISD::VP_SIGN_EXTEND:
1494 case ISD::VP_ZERO_EXTEND:
1495 SplitVecRes_ExtendOp(N, Lo, Hi);
1496 break;
1497
1498 case ISD::ADD: case ISD::VP_ADD:
1499 case ISD::SUB: case ISD::VP_SUB:
1500 case ISD::MUL: case ISD::VP_MUL:
1501 case ISD::CLMUL:
1502 case ISD::CLMULR:
1503 case ISD::CLMULH:
1504 case ISD::MULHS:
1505 case ISD::MULHU:
1506 case ISD::ABDS:
1507 case ISD::ABDU:
1508 case ISD::AVGCEILS:
1509 case ISD::AVGCEILU:
1510 case ISD::AVGFLOORS:
1511 case ISD::AVGFLOORU:
1512 case ISD::FADD: case ISD::VP_FADD:
1513 case ISD::FSUB: case ISD::VP_FSUB:
1514 case ISD::FMUL: case ISD::VP_FMUL:
1515 case ISD::FMINNUM:
1516 case ISD::FMINNUM_IEEE:
1517 case ISD::VP_FMINNUM:
1518 case ISD::FMAXNUM:
1519 case ISD::FMAXNUM_IEEE:
1520 case ISD::VP_FMAXNUM:
1521 case ISD::FMINIMUM:
1522 case ISD::VP_FMINIMUM:
1523 case ISD::FMAXIMUM:
1524 case ISD::VP_FMAXIMUM:
1525 case ISD::FMINIMUMNUM:
1526 case ISD::FMAXIMUMNUM:
1527 case ISD::SDIV: case ISD::VP_SDIV:
1528 case ISD::UDIV: case ISD::VP_UDIV:
1529 case ISD::FDIV: case ISD::VP_FDIV:
1530 case ISD::FPOW:
1531 case ISD::FATAN2:
1532 case ISD::AND: case ISD::VP_AND:
1533 case ISD::OR: case ISD::VP_OR:
1534 case ISD::XOR: case ISD::VP_XOR:
1535 case ISD::SHL: case ISD::VP_SHL:
1536 case ISD::SRA: case ISD::VP_SRA:
1537 case ISD::SRL: case ISD::VP_SRL:
1538 case ISD::UREM: case ISD::VP_UREM:
1539 case ISD::SREM: case ISD::VP_SREM:
1540 case ISD::FREM: case ISD::VP_FREM:
1541 case ISD::SMIN: case ISD::VP_SMIN:
1542 case ISD::SMAX: case ISD::VP_SMAX:
1543 case ISD::UMIN: case ISD::VP_UMIN:
1544 case ISD::UMAX: case ISD::VP_UMAX:
1545 case ISD::SADDSAT: case ISD::VP_SADDSAT:
1546 case ISD::UADDSAT: case ISD::VP_UADDSAT:
1547 case ISD::SSUBSAT: case ISD::VP_SSUBSAT:
1548 case ISD::USUBSAT: case ISD::VP_USUBSAT:
1549 case ISD::SSHLSAT:
1550 case ISD::USHLSAT:
1551 case ISD::ROTL:
1552 case ISD::ROTR:
1553 case ISD::VP_FCOPYSIGN:
1554 SplitVecRes_BinOp(N, Lo, Hi);
1555 break;
1556 case ISD::MASKED_UDIV:
1557 case ISD::MASKED_SDIV:
1558 case ISD::MASKED_UREM:
1559 case ISD::MASKED_SREM:
1560 SplitVecRes_MaskedBinOp(N, Lo, Hi);
1561 break;
1562 case ISD::FMA: case ISD::VP_FMA:
1563 case ISD::FSHL:
1564 case ISD::VP_FSHL:
1565 case ISD::FSHR:
1566 case ISD::VP_FSHR:
1567 SplitVecRes_TernaryOp(N, Lo, Hi);
1568 break;
1569
1570 case ISD::SCMP: case ISD::UCMP:
1571 SplitVecRes_CMP(N, Lo, Hi);
1572 break;
1573
1574#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
1575 case ISD::STRICT_##DAGN:
1576#include "llvm/IR/ConstrainedOps.def"
1577 SplitVecRes_StrictFPOp(N, Lo, Hi);
1578 break;
1579
1582 SplitVecRes_FP_TO_XINT_SAT(N, Lo, Hi);
1583 break;
1584
1585 case ISD::UADDO:
1586 case ISD::SADDO:
1587 case ISD::USUBO:
1588 case ISD::SSUBO:
1589 case ISD::UMULO:
1590 case ISD::SMULO:
1591 SplitVecRes_OverflowOp(N, ResNo, Lo, Hi);
1592 break;
1593 case ISD::SMULFIX:
1594 case ISD::SMULFIXSAT:
1595 case ISD::UMULFIX:
1596 case ISD::UMULFIXSAT:
1597 case ISD::SDIVFIX:
1598 case ISD::SDIVFIXSAT:
1599 case ISD::UDIVFIX:
1600 case ISD::UDIVFIXSAT:
1601 SplitVecRes_FIX(N, Lo, Hi);
1602 break;
1603 case ISD::EXPERIMENTAL_VP_SPLICE:
1604 SplitVecRes_VP_SPLICE(N, Lo, Hi);
1605 break;
1606 case ISD::EXPERIMENTAL_VP_REVERSE:
1607 SplitVecRes_VP_REVERSE(N, Lo, Hi);
1608 break;
1613 SplitVecRes_PARTIAL_REDUCE_MLA(N, Lo, Hi);
1614 break;
1616 SplitVecRes_GET_ACTIVE_LANE_MASK(N, Lo, Hi);
1617 break;
1618 }
1619
1620 // If Lo/Hi is null, the sub-method took care of registering results etc.
1621 if (Lo.getNode())
1622 SetSplitVector(SDValue(N, ResNo), Lo, Hi);
1623}
1624
1625void DAGTypeLegalizer::IncrementPointer(MemSDNode *N, EVT MemVT,
1626 MachinePointerInfo &MPI, SDValue &Ptr,
1627 uint64_t *ScaledOffset) {
1628 SDLoc DL(N);
1629 unsigned IncrementSize = MemVT.getSizeInBits().getKnownMinValue() / 8;
1630
1631 if (MemVT.isScalableVector()) {
1632 SDValue BytesIncrement = DAG.getVScale(
1633 DL, Ptr.getValueType(),
1634 APInt(Ptr.getValueSizeInBits().getFixedValue(), IncrementSize));
1635 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
1636 if (ScaledOffset)
1637 *ScaledOffset += IncrementSize;
1638 Ptr = DAG.getNode(ISD::ADD, DL, Ptr.getValueType(), Ptr, BytesIncrement,
1640 } else {
1641 MPI = N->getPointerInfo().getWithOffset(IncrementSize);
1642 // Increment the pointer to the other half.
1643 Ptr = DAG.getObjectPtrOffset(DL, Ptr, TypeSize::getFixed(IncrementSize));
1644 }
1645}
1646
1647std::pair<SDValue, SDValue> DAGTypeLegalizer::SplitMask(SDValue Mask) {
1648 return SplitMask(Mask, SDLoc(Mask));
1649}
1650
1651std::pair<SDValue, SDValue> DAGTypeLegalizer::SplitMask(SDValue Mask,
1652 const SDLoc &DL) {
1653 SDValue MaskLo, MaskHi;
1654 EVT MaskVT = Mask.getValueType();
1655 if (getTypeAction(MaskVT) == TargetLowering::TypeSplitVector)
1656 GetSplitVector(Mask, MaskLo, MaskHi);
1657 else
1658 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
1659 return std::make_pair(MaskLo, MaskHi);
1660}
1661
1662void DAGTypeLegalizer::SplitVecRes_BinOp(SDNode *N, SDValue &Lo, SDValue &Hi) {
1663 SDValue LHSLo, LHSHi;
1664 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1665 SDValue RHSLo, RHSHi;
1666 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
1667 SDLoc dl(N);
1668
1669 const SDNodeFlags Flags = N->getFlags();
1670 unsigned Opcode = N->getOpcode();
1671 if (N->getNumOperands() == 2) {
1672 Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(), LHSLo, RHSLo, Flags);
1673 Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(), LHSHi, RHSHi, Flags);
1674 return;
1675 }
1676
1677 assert(N->getNumOperands() == 4 && "Unexpected number of operands!");
1678 assert(N->isVPOpcode() && "Expected VP opcode");
1679
1680 SDValue MaskLo, MaskHi;
1681 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(2));
1682
1683 SDValue EVLLo, EVLHi;
1684 std::tie(EVLLo, EVLHi) =
1685 DAG.SplitEVL(N->getOperand(3), N->getValueType(0), dl);
1686
1687 Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(),
1688 {LHSLo, RHSLo, MaskLo, EVLLo}, Flags);
1689 Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(),
1690 {LHSHi, RHSHi, MaskHi, EVLHi}, Flags);
1691}
1692
1693void DAGTypeLegalizer::SplitVecRes_MaskedBinOp(SDNode *N, SDValue &Lo,
1694 SDValue &Hi) {
1695 SDValue LHSLo, LHSHi;
1696 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1697 SDValue RHSLo, RHSHi;
1698 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
1699 auto [MaskLo, MaskHi] = SplitMask(N->getOperand(2));
1700 SDLoc dl(N);
1701
1702 const SDNodeFlags Flags = N->getFlags();
1703 unsigned Opcode = N->getOpcode();
1704 Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(), LHSLo, RHSLo, MaskLo,
1705 Flags);
1706 Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(), LHSHi, RHSHi, MaskHi,
1707 Flags);
1708}
1709
1710void DAGTypeLegalizer::SplitVecRes_TernaryOp(SDNode *N, SDValue &Lo,
1711 SDValue &Hi) {
1712 SDValue Op0Lo, Op0Hi;
1713 GetSplitVector(N->getOperand(0), Op0Lo, Op0Hi);
1714 SDValue Op1Lo, Op1Hi;
1715 GetSplitVector(N->getOperand(1), Op1Lo, Op1Hi);
1716 SDValue Op2Lo, Op2Hi;
1717 GetSplitVector(N->getOperand(2), Op2Lo, Op2Hi);
1718 SDLoc dl(N);
1719
1720 const SDNodeFlags Flags = N->getFlags();
1721 unsigned Opcode = N->getOpcode();
1722 if (N->getNumOperands() == 3) {
1723 Lo = DAG.getNode(Opcode, dl, Op0Lo.getValueType(), Op0Lo, Op1Lo, Op2Lo, Flags);
1724 Hi = DAG.getNode(Opcode, dl, Op0Hi.getValueType(), Op0Hi, Op1Hi, Op2Hi, Flags);
1725 return;
1726 }
1727
1728 assert(N->getNumOperands() == 5 && "Unexpected number of operands!");
1729 assert(N->isVPOpcode() && "Expected VP opcode");
1730
1731 SDValue MaskLo, MaskHi;
1732 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(3));
1733
1734 SDValue EVLLo, EVLHi;
1735 std::tie(EVLLo, EVLHi) =
1736 DAG.SplitEVL(N->getOperand(4), N->getValueType(0), dl);
1737
1738 Lo = DAG.getNode(Opcode, dl, Op0Lo.getValueType(),
1739 {Op0Lo, Op1Lo, Op2Lo, MaskLo, EVLLo}, Flags);
1740 Hi = DAG.getNode(Opcode, dl, Op0Hi.getValueType(),
1741 {Op0Hi, Op1Hi, Op2Hi, MaskHi, EVLHi}, Flags);
1742}
1743
1744void DAGTypeLegalizer::SplitVecRes_CMP(SDNode *N, SDValue &Lo, SDValue &Hi) {
1745 LLVMContext &Ctxt = *DAG.getContext();
1746 SDLoc dl(N);
1747
1748 SDValue LHS = N->getOperand(0);
1749 SDValue RHS = N->getOperand(1);
1750
1751 SDValue LHSLo, LHSHi, RHSLo, RHSHi;
1752 if (getTypeAction(LHS.getValueType()) == TargetLowering::TypeSplitVector) {
1753 GetSplitVector(LHS, LHSLo, LHSHi);
1754 GetSplitVector(RHS, RHSLo, RHSHi);
1755 } else {
1756 std::tie(LHSLo, LHSHi) = DAG.SplitVector(LHS, dl);
1757 std::tie(RHSLo, RHSHi) = DAG.SplitVector(RHS, dl);
1758 }
1759
1760 EVT SplitResVT = N->getValueType(0).getHalfNumVectorElementsVT(Ctxt);
1761 Lo = DAG.getNode(N->getOpcode(), dl, SplitResVT, LHSLo, RHSLo);
1762 Hi = DAG.getNode(N->getOpcode(), dl, SplitResVT, LHSHi, RHSHi);
1763}
1764
1765void DAGTypeLegalizer::SplitVecRes_FIX(SDNode *N, SDValue &Lo, SDValue &Hi) {
1766 SDValue LHSLo, LHSHi;
1767 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1768 SDValue RHSLo, RHSHi;
1769 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
1770 SDLoc dl(N);
1771 SDValue Op2 = N->getOperand(2);
1772
1773 unsigned Opcode = N->getOpcode();
1774 Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(), LHSLo, RHSLo, Op2,
1775 N->getFlags());
1776 Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(), LHSHi, RHSHi, Op2,
1777 N->getFlags());
1778}
1779
1780void DAGTypeLegalizer::SplitVecRes_BITCAST(SDNode *N, SDValue &Lo,
1781 SDValue &Hi) {
1782 // We know the result is a vector. The input may be either a vector or a
1783 // scalar value.
1784 EVT LoVT, HiVT;
1785 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1786 SDLoc dl(N);
1787
1788 SDValue InOp = N->getOperand(0);
1789 EVT InVT = InOp.getValueType();
1790
1791 // Handle some special cases efficiently.
1792 switch (getTypeAction(InVT)) {
1799 break;
1802 // A scalar to vector conversion, where the scalar needs expansion.
1803 // If the vector is being split in two then we can just convert the
1804 // expanded pieces.
1805 if (LoVT == HiVT) {
1806 GetExpandedOp(InOp, Lo, Hi);
1807 if (DAG.getDataLayout().isBigEndian())
1808 std::swap(Lo, Hi);
1809 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
1810 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
1811 return;
1812 }
1813 break;
1815 // If the input is a vector that needs to be split, convert each split
1816 // piece of the input now.
1817 GetSplitVector(InOp, Lo, Hi);
1818 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
1819 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
1820 return;
1822 report_fatal_error("Scalarization of scalable vectors is not supported.");
1823 }
1824
1825 if (LoVT.isScalableVector()) {
1826 auto [InLo, InHi] = DAG.SplitVectorOperand(N, 0);
1827 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, InLo);
1828 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, InHi);
1829 return;
1830 }
1831
1832 // In the general case, convert the input to an integer and split it by hand.
1833 EVT LoIntVT = EVT::getIntegerVT(*DAG.getContext(), LoVT.getSizeInBits());
1834 EVT HiIntVT = EVT::getIntegerVT(*DAG.getContext(), HiVT.getSizeInBits());
1835 if (DAG.getDataLayout().isBigEndian())
1836 std::swap(LoIntVT, HiIntVT);
1837
1838 SplitInteger(BitConvertToInteger(InOp), LoIntVT, HiIntVT, Lo, Hi);
1839
1840 if (DAG.getDataLayout().isBigEndian())
1841 std::swap(Lo, Hi);
1842 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
1843 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
1844}
1845
1846void DAGTypeLegalizer::SplitVecRes_LOOP_DEPENDENCE_MASK(SDNode *N, SDValue &Lo,
1847 SDValue &Hi) {
1848 SDLoc DL(N);
1849 EVT LoVT, HiVT;
1850 SDValue PtrA = N->getOperand(0);
1851 SDValue PtrB = N->getOperand(1);
1852 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1853
1854 // The lane offset for the "Lo" half of the mask is unchanged.
1855 Lo = DAG.getNode(N->getOpcode(), DL, LoVT, PtrA, PtrB,
1856 /*ElementSizeInBytes=*/N->getOperand(2),
1857 /*LaneOffset=*/N->getOperand(3));
1858 // The lane offset for the "Hi" half of the mask is incremented by the number
1859 // of elements in the "Lo" half.
1860 unsigned LaneOffset =
1862 // Note: The lane offset is implicitly scalable for scalable masks.
1863 Hi = DAG.getNode(N->getOpcode(), DL, HiVT, PtrA, PtrB,
1864 /*ElementSizeInBytes=*/N->getOperand(2),
1865 /*LaneOffset=*/DAG.getConstant(LaneOffset, DL, MVT::i64));
1866}
1867
1868void DAGTypeLegalizer::SplitVecRes_BUILD_VECTOR(SDNode *N, SDValue &Lo,
1869 SDValue &Hi) {
1870 EVT LoVT, HiVT;
1871 SDLoc dl(N);
1872 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1873 unsigned LoNumElts = LoVT.getVectorNumElements();
1874 SmallVector<SDValue, 8> LoOps(N->op_begin(), N->op_begin()+LoNumElts);
1875 Lo = DAG.getBuildVector(LoVT, dl, LoOps);
1876
1877 SmallVector<SDValue, 8> HiOps(N->op_begin()+LoNumElts, N->op_end());
1878 Hi = DAG.getBuildVector(HiVT, dl, HiOps);
1879}
1880
1881void DAGTypeLegalizer::SplitVecRes_CONCAT_VECTORS(SDNode *N, SDValue &Lo,
1882 SDValue &Hi) {
1883 assert(!(N->getNumOperands() & 1) && "Unsupported CONCAT_VECTORS");
1884 SDLoc dl(N);
1885 unsigned NumSubvectors = N->getNumOperands() / 2;
1886 if (NumSubvectors == 1) {
1887 Lo = N->getOperand(0);
1888 Hi = N->getOperand(1);
1889 return;
1890 }
1891
1892 EVT LoVT, HiVT;
1893 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1894
1895 SmallVector<SDValue, 8> LoOps(N->op_begin(), N->op_begin()+NumSubvectors);
1896 Lo = DAG.getNode(ISD::CONCAT_VECTORS, dl, LoVT, LoOps);
1897
1898 SmallVector<SDValue, 8> HiOps(N->op_begin()+NumSubvectors, N->op_end());
1899 Hi = DAG.getNode(ISD::CONCAT_VECTORS, dl, HiVT, HiOps);
1900}
1901
1902void DAGTypeLegalizer::SplitVecRes_EXTRACT_SUBVECTOR(SDNode *N, SDValue &Lo,
1903 SDValue &Hi) {
1904 SDValue Vec = N->getOperand(0);
1905 SDValue Idx = N->getOperand(1);
1906 SDLoc dl(N);
1907
1908 EVT LoVT, HiVT;
1909 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1910
1911 Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, LoVT, Vec, Idx);
1912 uint64_t IdxVal = Idx->getAsZExtVal();
1913 Hi = DAG.getNode(
1914 ISD::EXTRACT_SUBVECTOR, dl, HiVT, Vec,
1915 DAG.getVectorIdxConstant(IdxVal + LoVT.getVectorMinNumElements(), dl));
1916}
1917
1918void DAGTypeLegalizer::SplitVecRes_INSERT_SUBVECTOR(SDNode *N, SDValue &Lo,
1919 SDValue &Hi) {
1920 SDValue Vec = N->getOperand(0);
1921 SDValue SubVec = N->getOperand(1);
1922 SDValue Idx = N->getOperand(2);
1923 SDLoc dl(N);
1924 GetSplitVector(Vec, Lo, Hi);
1925
1926 EVT VecVT = Vec.getValueType();
1927 EVT LoVT = Lo.getValueType();
1928 EVT SubVecVT = SubVec.getValueType();
1929 unsigned VecElems = VecVT.getVectorMinNumElements();
1930 unsigned SubElems = SubVecVT.getVectorMinNumElements();
1931 unsigned LoElems = LoVT.getVectorMinNumElements();
1932
1933 // If we know the index is in the first half, and we know the subvector
1934 // doesn't cross the boundary between the halves, we can avoid spilling the
1935 // vector, and insert into the lower half of the split vector directly.
1936 unsigned IdxVal = Idx->getAsZExtVal();
1937 if (IdxVal + SubElems <= LoElems) {
1938 Lo = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, LoVT, Lo, SubVec, Idx);
1939 return;
1940 }
1941 // Similarly if the subvector is fully in the high half, but mind that we
1942 // can't tell whether a fixed-length subvector is fully within the high half
1943 // of a scalable vector.
1944 if (VecVT.isScalableVector() == SubVecVT.isScalableVector() &&
1945 IdxVal >= LoElems && IdxVal + SubElems <= VecElems) {
1946 Hi = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, Hi.getValueType(), Hi, SubVec,
1947 DAG.getVectorIdxConstant(IdxVal - LoElems, dl));
1948 return;
1949 }
1950
1951 if (getTypeAction(SubVecVT) == TargetLowering::TypeWidenVector &&
1952 Vec.isUndef() && SubVecVT.getVectorElementType() == MVT::i1) {
1953 SDValue WideSubVec = GetWidenedVector(SubVec);
1954 if (WideSubVec.getValueType() == VecVT) {
1955 std::tie(Lo, Hi) = DAG.SplitVector(WideSubVec, SDLoc(WideSubVec));
1956 return;
1957 }
1958 }
1959
1960 // Spill the vector to the stack.
1961 // In cases where the vector is illegal it will be broken down into parts
1962 // and stored in parts - we should use the alignment for the smallest part.
1963 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
1965 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
1966 auto &MF = DAG.getMachineFunction();
1967 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
1968 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
1969
1970 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
1971 SmallestAlign);
1972
1973 // Store the new subvector into the specified index.
1974 SDValue SubVecPtr =
1975 TLI.getVectorSubVecPointer(DAG, StackPtr, VecVT, SubVecVT, Idx);
1976 Store = DAG.getStore(Store, dl, SubVec, SubVecPtr,
1978
1979 // Load the Lo part from the stack slot.
1980 Lo = DAG.getLoad(Lo.getValueType(), dl, Store, StackPtr, PtrInfo,
1981 SmallestAlign);
1982
1983 // Increment the pointer to the other part.
1984 auto *Load = cast<LoadSDNode>(Lo);
1985 MachinePointerInfo MPI = Load->getPointerInfo();
1986 IncrementPointer(Load, LoVT, MPI, StackPtr);
1987
1988 // Load the Hi part from the stack slot.
1989 Hi = DAG.getLoad(Hi.getValueType(), dl, Store, StackPtr, MPI, SmallestAlign);
1990}
1991
1992// Handle splitting an FP where the second operand does not match the first
1993// type. The second operand may be a scalar, or a vector that has exactly as
1994// many elements as the first
1995void DAGTypeLegalizer::SplitVecRes_FPOp_MultiType(SDNode *N, SDValue &Lo,
1996 SDValue &Hi) {
1997 SDValue LHSLo, LHSHi;
1998 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1999 SDLoc DL(N);
2000
2001 SDValue RHSLo, RHSHi;
2002 SDValue RHS = N->getOperand(1);
2003 EVT RHSVT = RHS.getValueType();
2004 if (RHSVT.isVector()) {
2005 if (getTypeAction(RHSVT) == TargetLowering::TypeSplitVector)
2006 GetSplitVector(RHS, RHSLo, RHSHi);
2007 else
2008 std::tie(RHSLo, RHSHi) = DAG.SplitVector(RHS, SDLoc(RHS));
2009
2010 Lo = DAG.getNode(N->getOpcode(), DL, LHSLo.getValueType(), LHSLo, RHSLo);
2011 Hi = DAG.getNode(N->getOpcode(), DL, LHSHi.getValueType(), LHSHi, RHSHi);
2012 } else {
2013 Lo = DAG.getNode(N->getOpcode(), DL, LHSLo.getValueType(), LHSLo, RHS);
2014 Hi = DAG.getNode(N->getOpcode(), DL, LHSHi.getValueType(), LHSHi, RHS);
2015 }
2016}
2017
2018void DAGTypeLegalizer::SplitVecRes_IS_FPCLASS(SDNode *N, SDValue &Lo,
2019 SDValue &Hi) {
2020 SDLoc DL(N);
2021 SDValue ArgLo, ArgHi;
2022 SDValue Test = N->getOperand(1);
2023 SDValue FpValue = N->getOperand(0);
2024 if (getTypeAction(FpValue.getValueType()) == TargetLowering::TypeSplitVector)
2025 GetSplitVector(FpValue, ArgLo, ArgHi);
2026 else
2027 std::tie(ArgLo, ArgHi) = DAG.SplitVector(FpValue, SDLoc(FpValue));
2028 EVT LoVT, HiVT;
2029 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2030
2031 Lo = DAG.getNode(ISD::IS_FPCLASS, DL, LoVT, ArgLo, Test, N->getFlags());
2032 Hi = DAG.getNode(ISD::IS_FPCLASS, DL, HiVT, ArgHi, Test, N->getFlags());
2033}
2034
2035void DAGTypeLegalizer::SplitVecRes_InregOp(SDNode *N, SDValue &Lo,
2036 SDValue &Hi) {
2037 SDValue LHSLo, LHSHi;
2038 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
2039 SDLoc dl(N);
2040
2041 EVT LoVT, HiVT;
2042 std::tie(LoVT, HiVT) =
2043 DAG.GetSplitDestVTs(cast<VTSDNode>(N->getOperand(1))->getVT());
2044
2045 Lo = DAG.getNode(N->getOpcode(), dl, LHSLo.getValueType(), LHSLo,
2046 DAG.getValueType(LoVT));
2047 Hi = DAG.getNode(N->getOpcode(), dl, LHSHi.getValueType(), LHSHi,
2048 DAG.getValueType(HiVT));
2049}
2050
2051void DAGTypeLegalizer::SplitVecRes_ExtVecInRegOp(SDNode *N, SDValue &Lo,
2052 SDValue &Hi) {
2053 unsigned Opcode = N->getOpcode();
2054 SDValue N0 = N->getOperand(0);
2055
2056 SDLoc dl(N);
2057 SDValue InLo, InHi;
2058
2059 if (getTypeAction(N0.getValueType()) == TargetLowering::TypeSplitVector)
2060 GetSplitVector(N0, InLo, InHi);
2061 else
2062 std::tie(InLo, InHi) = DAG.SplitVectorOperand(N, 0);
2063
2064 EVT InLoVT = InLo.getValueType();
2065 unsigned InNumElements = InLoVT.getVectorNumElements();
2066
2067 EVT OutLoVT, OutHiVT;
2068 std::tie(OutLoVT, OutHiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2069 unsigned OutNumElements = OutLoVT.getVectorNumElements();
2070 assert((2 * OutNumElements) <= InNumElements &&
2071 "Illegal extend vector in reg split");
2072
2073 // *_EXTEND_VECTOR_INREG instructions extend the lowest elements of the
2074 // input vector (i.e. we only use InLo):
2075 // OutLo will extend the first OutNumElements from InLo.
2076 // OutHi will extend the next OutNumElements from InLo.
2077
2078 // Shuffle the elements from InLo for OutHi into the bottom elements to
2079 // create a 'fake' InHi.
2080 SmallVector<int, 8> SplitHi(InNumElements, -1);
2081 for (unsigned i = 0; i != OutNumElements; ++i)
2082 SplitHi[i] = i + OutNumElements;
2083 InHi = DAG.getVectorShuffle(InLoVT, dl, InLo, DAG.getPOISON(InLoVT), SplitHi);
2084
2085 Lo = DAG.getNode(Opcode, dl, OutLoVT, InLo);
2086 Hi = DAG.getNode(Opcode, dl, OutHiVT, InHi);
2087}
2088
2089void DAGTypeLegalizer::SplitVecRes_StrictFPOp(SDNode *N, SDValue &Lo,
2090 SDValue &Hi) {
2091 unsigned NumOps = N->getNumOperands();
2092 SDValue Chain = N->getOperand(0);
2093 EVT LoVT, HiVT;
2094 SDLoc dl(N);
2095 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2096
2099
2100 // The Chain is the first operand.
2101 OpsLo[0] = Chain;
2102 OpsHi[0] = Chain;
2103
2104 // Now process the remaining operands.
2105 for (unsigned i = 1; i < NumOps; ++i) {
2106 SDValue Op = N->getOperand(i);
2107 SDValue OpLo = Op;
2108 SDValue OpHi = Op;
2109
2110 EVT InVT = Op.getValueType();
2111 if (InVT.isVector()) {
2112 // If the input also splits, handle it directly for a
2113 // compile time speedup. Otherwise split it by hand.
2114 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
2115 GetSplitVector(Op, OpLo, OpHi);
2116 else
2117 std::tie(OpLo, OpHi) = DAG.SplitVectorOperand(N, i);
2118 }
2119
2120 OpsLo[i] = OpLo;
2121 OpsHi[i] = OpHi;
2122 }
2123
2124 EVT LoValueVTs[] = {LoVT, MVT::Other};
2125 EVT HiValueVTs[] = {HiVT, MVT::Other};
2126 Lo = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(LoValueVTs), OpsLo,
2127 N->getFlags());
2128 Hi = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(HiValueVTs), OpsHi,
2129 N->getFlags());
2130
2131 // Build a factor node to remember that this Op is independent of the
2132 // other one.
2133 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
2134 Lo.getValue(1), Hi.getValue(1));
2135
2136 // Legalize the chain result - switch anything that used the old chain to
2137 // use the new one.
2138 ReplaceValueWith(SDValue(N, 1), Chain);
2139}
2140
2141SDValue DAGTypeLegalizer::UnrollVectorOp_StrictFP(SDNode *N, unsigned ResNE) {
2142 SDValue Chain = N->getOperand(0);
2143 EVT VT = N->getValueType(0);
2144 unsigned NE = VT.getVectorNumElements();
2145 EVT EltVT = VT.getVectorElementType();
2146 SDLoc dl(N);
2147
2149 SmallVector<SDValue, 4> Operands(N->getNumOperands());
2150
2151 // If ResNE is 0, fully unroll the vector op.
2152 if (ResNE == 0)
2153 ResNE = NE;
2154 else if (NE > ResNE)
2155 NE = ResNE;
2156
2157 //The results of each unrolled operation, including the chain.
2158 SDVTList ChainVTs = DAG.getVTList(EltVT, MVT::Other);
2160
2161 unsigned i;
2162 for (i = 0; i != NE; ++i) {
2163 Operands[0] = Chain;
2164 for (unsigned j = 1, e = N->getNumOperands(); j != e; ++j) {
2165 SDValue Operand = N->getOperand(j);
2166 EVT OperandVT = Operand.getValueType();
2167 if (OperandVT.isVector()) {
2168 EVT OperandEltVT = OperandVT.getVectorElementType();
2169 Operands[j] = DAG.getExtractVectorElt(dl, OperandEltVT, Operand, i);
2170 } else {
2171 Operands[j] = Operand;
2172 }
2173 }
2174 SDValue Scalar =
2175 DAG.getNode(N->getOpcode(), dl, ChainVTs, Operands, N->getFlags());
2176
2177 //Add in the scalar as well as its chain value to the
2178 //result vectors.
2179 Scalars.push_back(Scalar);
2180 Chains.push_back(Scalar.getValue(1));
2181 }
2182
2183 for (; i < ResNE; ++i)
2184 Scalars.push_back(DAG.getPOISON(EltVT));
2185
2186 // Build a new factor node to connect the chain back together.
2187 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
2188 ReplaceValueWith(SDValue(N, 1), Chain);
2189
2190 // Create a new BUILD_VECTOR node
2191 EVT VecVT = EVT::getVectorVT(*DAG.getContext(), EltVT, ResNE);
2192 return DAG.getBuildVector(VecVT, dl, Scalars);
2193}
2194
2195void DAGTypeLegalizer::SplitVecRes_OverflowOp(SDNode *N, unsigned ResNo,
2196 SDValue &Lo, SDValue &Hi) {
2197 SDLoc dl(N);
2198 EVT ResVT = N->getValueType(0);
2199 EVT OvVT = N->getValueType(1);
2200 EVT LoResVT, HiResVT, LoOvVT, HiOvVT;
2201 std::tie(LoResVT, HiResVT) = DAG.GetSplitDestVTs(ResVT);
2202 std::tie(LoOvVT, HiOvVT) = DAG.GetSplitDestVTs(OvVT);
2203
2204 SDValue LoLHS, HiLHS, LoRHS, HiRHS;
2205 if (getTypeAction(ResVT) == TargetLowering::TypeSplitVector) {
2206 GetSplitVector(N->getOperand(0), LoLHS, HiLHS);
2207 GetSplitVector(N->getOperand(1), LoRHS, HiRHS);
2208 } else {
2209 std::tie(LoLHS, HiLHS) = DAG.SplitVectorOperand(N, 0);
2210 std::tie(LoRHS, HiRHS) = DAG.SplitVectorOperand(N, 1);
2211 }
2212
2213 unsigned Opcode = N->getOpcode();
2214 SDVTList LoVTs = DAG.getVTList(LoResVT, LoOvVT);
2215 SDVTList HiVTs = DAG.getVTList(HiResVT, HiOvVT);
2216 SDNode *LoNode =
2217 DAG.getNode(Opcode, dl, LoVTs, {LoLHS, LoRHS}, N->getFlags()).getNode();
2218 SDNode *HiNode =
2219 DAG.getNode(Opcode, dl, HiVTs, {HiLHS, HiRHS}, N->getFlags()).getNode();
2220
2221 Lo = SDValue(LoNode, ResNo);
2222 Hi = SDValue(HiNode, ResNo);
2223
2224 // Replace the other vector result not being explicitly split here.
2225 unsigned OtherNo = 1 - ResNo;
2226 EVT OtherVT = N->getValueType(OtherNo);
2227 if (getTypeAction(OtherVT) == TargetLowering::TypeSplitVector) {
2228 SetSplitVector(SDValue(N, OtherNo),
2229 SDValue(LoNode, OtherNo), SDValue(HiNode, OtherNo));
2230 } else {
2231 SDValue OtherVal = DAG.getNode(
2232 ISD::CONCAT_VECTORS, dl, OtherVT,
2233 SDValue(LoNode, OtherNo), SDValue(HiNode, OtherNo));
2234 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
2235 }
2236}
2237
2238void DAGTypeLegalizer::SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo,
2239 SDValue &Hi) {
2240 SDValue Vec = N->getOperand(0);
2241 SDValue Elt = N->getOperand(1);
2242 SDValue Idx = N->getOperand(2);
2243 SDLoc dl(N);
2244 GetSplitVector(Vec, Lo, Hi);
2245
2246 if (ConstantSDNode *CIdx = dyn_cast<ConstantSDNode>(Idx)) {
2247 unsigned IdxVal = CIdx->getZExtValue();
2248 unsigned LoNumElts = Lo.getValueType().getVectorMinNumElements();
2249 if (IdxVal < LoNumElts) {
2250 Lo = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl,
2251 Lo.getValueType(), Lo, Elt, Idx);
2252 return;
2253 } else if (!Vec.getValueType().isScalableVector()) {
2254 Hi = DAG.getInsertVectorElt(dl, Hi, Elt, IdxVal - LoNumElts);
2255 return;
2256 }
2257 }
2258
2259 // Make the vector elements byte-addressable if they aren't already.
2260 EVT VecVT = Vec.getValueType();
2261 EVT EltVT = VecVT.getVectorElementType();
2262 if (!EltVT.isByteSized()) {
2263 EltVT = EltVT.changeTypeToInteger().getRoundIntegerType(*DAG.getContext());
2264 VecVT = VecVT.changeElementType(*DAG.getContext(), EltVT);
2265 Vec = DAG.getNode(ISD::ANY_EXTEND, dl, VecVT, Vec);
2266 // Extend the element type to match if needed.
2267 if (EltVT.bitsGT(Elt.getValueType()))
2268 Elt = DAG.getNode(ISD::ANY_EXTEND, dl, EltVT, Elt);
2269 }
2270
2271 // Spill the vector to the stack.
2272 // In cases where the vector is illegal it will be broken down into parts
2273 // and stored in parts - we should use the alignment for the smallest part.
2274 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
2276 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
2277 auto &MF = DAG.getMachineFunction();
2278 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
2279 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
2280
2281 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
2282 SmallestAlign);
2283
2284 // Store the new element. This may be larger than the vector element type,
2285 // so use a truncating store.
2286 SDValue EltPtr = TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Idx);
2287 Store = DAG.getTruncStore(
2288 Store, dl, Elt, EltPtr, MachinePointerInfo::getUnknownStack(MF), EltVT,
2289 commonAlignment(SmallestAlign,
2290 EltVT.getFixedSizeInBits() / 8));
2291
2292 EVT LoVT, HiVT;
2293 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(VecVT);
2294
2295 // Load the Lo part from the stack slot.
2296 Lo = DAG.getLoad(LoVT, dl, Store, StackPtr, PtrInfo, SmallestAlign);
2297
2298 // Increment the pointer to the other part.
2299 auto Load = cast<LoadSDNode>(Lo);
2300 MachinePointerInfo MPI = Load->getPointerInfo();
2301 IncrementPointer(Load, LoVT, MPI, StackPtr);
2302
2303 Hi = DAG.getLoad(HiVT, dl, Store, StackPtr, MPI, SmallestAlign);
2304
2305 // If we adjusted the original type, we need to truncate the results.
2306 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2307 if (LoVT != Lo.getValueType())
2308 Lo = DAG.getNode(ISD::TRUNCATE, dl, LoVT, Lo);
2309 if (HiVT != Hi.getValueType())
2310 Hi = DAG.getNode(ISD::TRUNCATE, dl, HiVT, Hi);
2311}
2312
2313void DAGTypeLegalizer::SplitVecRes_STEP_VECTOR(SDNode *N, SDValue &Lo,
2314 SDValue &Hi) {
2315 EVT LoVT, HiVT;
2316 SDLoc dl(N);
2317 assert(N->getValueType(0).isScalableVector() &&
2318 "Only scalable vectors are supported for STEP_VECTOR");
2319 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2320 SDValue Step = N->getOperand(0);
2321
2322 Lo = DAG.getNode(ISD::STEP_VECTOR, dl, LoVT, Step);
2323
2324 // Hi = Lo + (EltCnt * Step)
2325 EVT EltVT = Step.getValueType();
2326 APInt StepVal = Step->getAsAPIntVal();
2327 SDValue StartOfHi =
2328 DAG.getVScale(dl, EltVT, StepVal * LoVT.getVectorMinNumElements());
2329 StartOfHi = DAG.getSExtOrTrunc(StartOfHi, dl, HiVT.getVectorElementType());
2330 StartOfHi = DAG.getNode(ISD::SPLAT_VECTOR, dl, HiVT, StartOfHi);
2331
2332 Hi = DAG.getNode(ISD::STEP_VECTOR, dl, HiVT, Step);
2333 Hi = DAG.getNode(ISD::ADD, dl, HiVT, Hi, StartOfHi);
2334}
2335
2336void DAGTypeLegalizer::SplitVecRes_ScalarOp(SDNode *N, SDValue &Lo,
2337 SDValue &Hi) {
2338 EVT LoVT, HiVT;
2339 SDLoc dl(N);
2340 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2341 Lo = DAG.getNode(N->getOpcode(), dl, LoVT, N->getOperand(0));
2342 if (N->getOpcode() == ISD::SCALAR_TO_VECTOR) {
2343 Hi = DAG.getPOISON(HiVT);
2344 } else {
2345 assert(N->getOpcode() == ISD::SPLAT_VECTOR && "Unexpected opcode");
2346 Hi = Lo;
2347 }
2348}
2349
2350void DAGTypeLegalizer::SplitVecRes_LOAD(LoadSDNode *LD, SDValue &Lo,
2351 SDValue &Hi) {
2352 assert(ISD::isUNINDEXEDLoad(LD) && "Indexed load during type legalization!");
2353 EVT LoVT, HiVT;
2354 SDLoc dl(LD);
2355 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(LD->getValueType(0));
2356
2357 ISD::LoadExtType ExtType = LD->getExtensionType();
2358 SDValue Ch = LD->getChain();
2359 SDValue Ptr = LD->getBasePtr();
2360 SDValue Offset = DAG.getUNDEF(Ptr.getValueType());
2361 EVT MemoryVT = LD->getMemoryVT();
2362 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
2363 AAMDNodes AAInfo = LD->getAAInfo();
2364
2365 EVT LoMemVT, HiMemVT;
2366 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
2367
2368 if (!LoMemVT.isByteSized() || !HiMemVT.isByteSized()) {
2369 SDValue Value, NewChain;
2370 std::tie(Value, NewChain) = TLI.scalarizeVectorLoad(LD, DAG);
2371 std::tie(Lo, Hi) = DAG.SplitVector(Value, dl);
2372 ReplaceValueWith(SDValue(LD, 1), NewChain);
2373 return;
2374 }
2375
2376 Lo = DAG.getLoad(ISD::UNINDEXED, ExtType, LoVT, dl, Ch, Ptr, Offset,
2377 LD->getPointerInfo(), LoMemVT, LD->getBaseAlign(), MMOFlags,
2378 AAInfo);
2379
2380 MachinePointerInfo MPI;
2381 IncrementPointer(LD, LoMemVT, MPI, Ptr);
2382
2383 Hi = DAG.getLoad(ISD::UNINDEXED, ExtType, HiVT, dl, Ch, Ptr, Offset, MPI,
2384 HiMemVT, LD->getBaseAlign(), MMOFlags, AAInfo);
2385
2386 // Build a factor node to remember that this load is independent of the
2387 // other one.
2388 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2389 Hi.getValue(1));
2390
2391 // Legalize the chain result - switch anything that used the old chain to
2392 // use the new one.
2393 ReplaceValueWith(SDValue(LD, 1), Ch);
2394}
2395
2396void DAGTypeLegalizer::SplitVecRes_VP_LOAD(VPLoadSDNode *LD, SDValue &Lo,
2397 SDValue &Hi) {
2398 assert(LD->isUnindexed() && "Indexed VP load during type legalization!");
2399 EVT LoVT, HiVT;
2400 SDLoc dl(LD);
2401 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(LD->getValueType(0));
2402
2403 ISD::LoadExtType ExtType = LD->getExtensionType();
2404 SDValue Ch = LD->getChain();
2405 SDValue Ptr = LD->getBasePtr();
2406 SDValue Offset = LD->getOffset();
2407 assert(Offset.isUndef() && "Unexpected indexed variable-length load offset");
2408 Align Alignment = LD->getBaseAlign();
2409 SDValue Mask = LD->getMask();
2410 SDValue EVL = LD->getVectorLength();
2411 EVT MemoryVT = LD->getMemoryVT();
2412
2413 EVT LoMemVT, HiMemVT;
2414 bool HiIsEmpty = false;
2415 std::tie(LoMemVT, HiMemVT) =
2416 DAG.GetDependentSplitDestVTs(MemoryVT, LoVT, &HiIsEmpty);
2417
2418 // Split Mask operand
2419 SDValue MaskLo, MaskHi;
2420 if (Mask.getOpcode() == ISD::SETCC) {
2421 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
2422 } else {
2423 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
2424 GetSplitVector(Mask, MaskLo, MaskHi);
2425 else
2426 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, dl);
2427 }
2428
2429 // Split EVL operand
2430 SDValue EVLLo, EVLHi;
2431 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(EVL, LD->getValueType(0), dl);
2432
2433 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
2434 LD->getPointerInfo(), MachineMemOperand::MOLoad,
2435 LocationSize::beforeOrAfterPointer(), Alignment, LD->getAAInfo(),
2436 LD->getRanges());
2437
2438 Lo =
2439 DAG.getLoadVP(LD->getAddressingMode(), ExtType, LoVT, dl, Ch, Ptr, Offset,
2440 MaskLo, EVLLo, LoMemVT, MMO, LD->isExpandingLoad());
2441
2442 if (HiIsEmpty) {
2443 // The hi vp_load has zero storage size. We therefore simply set it to
2444 // the low vp_load and rely on subsequent removal from the chain.
2445 Hi = Lo;
2446 } else {
2447 // Generate hi vp_load.
2448 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, dl, LoMemVT, DAG,
2449 LD->isExpandingLoad());
2450
2451 MachinePointerInfo MPI;
2452 if (LoMemVT.isScalableVector())
2453 MPI = MachinePointerInfo(LD->getPointerInfo().getAddrSpace());
2454 else
2455 MPI = LD->getPointerInfo().getWithOffset(
2456 LoMemVT.getStoreSize().getFixedValue());
2457
2458 MMO = DAG.getMachineFunction().getMachineMemOperand(
2460 Alignment, LD->getAAInfo(), LD->getRanges());
2461
2462 Hi = DAG.getLoadVP(LD->getAddressingMode(), ExtType, HiVT, dl, Ch, Ptr,
2463 Offset, MaskHi, EVLHi, HiMemVT, MMO,
2464 LD->isExpandingLoad());
2465 }
2466
2467 // Build a factor node to remember that this load is independent of the
2468 // other one.
2469 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2470 Hi.getValue(1));
2471
2472 // Legalize the chain result - switch anything that used the old chain to
2473 // use the new one.
2474 ReplaceValueWith(SDValue(LD, 1), Ch);
2475}
2476
2477void DAGTypeLegalizer::SplitVecRes_VP_LOAD_FF(VPLoadFFSDNode *LD, SDValue &Lo,
2478 SDValue &Hi) {
2479 SDLoc dl(LD);
2480 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(LD->getValueType(0));
2481
2482 SDValue Ch = LD->getChain();
2483 SDValue Ptr = LD->getBasePtr();
2484 Align Alignment = LD->getBaseAlign();
2485 SDValue Mask = LD->getMask();
2486 SDValue EVL = LD->getVectorLength();
2487
2488 // Split Mask operand
2489 SDValue MaskLo, MaskHi;
2490 if (Mask.getOpcode() == ISD::SETCC) {
2491 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
2492 } else {
2493 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
2494 GetSplitVector(Mask, MaskLo, MaskHi);
2495 else
2496 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, dl);
2497 }
2498
2499 // Split EVL operand
2500 auto [EVLLo, EVLHi] = DAG.SplitEVL(EVL, LD->getValueType(0), dl);
2501
2502 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
2503 LD->getPointerInfo(), MachineMemOperand::MOLoad,
2504 LocationSize::beforeOrAfterPointer(), Alignment, LD->getAAInfo(),
2505 LD->getRanges());
2506
2507 Lo = DAG.getLoadFFVP(LoVT, dl, Ch, Ptr, MaskLo, EVLLo, MMO);
2508
2509 // Fill the upper half with poison.
2510 Hi = DAG.getPOISON(HiVT);
2511
2512 ReplaceValueWith(SDValue(LD, 1), Lo.getValue(1));
2513 ReplaceValueWith(SDValue(LD, 2), Lo.getValue(2));
2514}
2515
2516void DAGTypeLegalizer::SplitVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode *SLD,
2517 SDValue &Lo, SDValue &Hi) {
2518 assert(SLD->isUnindexed() &&
2519 "Indexed VP strided load during type legalization!");
2520 assert(SLD->getOffset().isUndef() &&
2521 "Unexpected indexed variable-length load offset");
2522
2523 SDLoc DL(SLD);
2524
2525 EVT LoVT, HiVT;
2526 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(SLD->getValueType(0));
2527
2528 EVT LoMemVT, HiMemVT;
2529 bool HiIsEmpty = false;
2530 std::tie(LoMemVT, HiMemVT) =
2531 DAG.GetDependentSplitDestVTs(SLD->getMemoryVT(), LoVT, &HiIsEmpty);
2532
2533 SDValue Mask = SLD->getMask();
2534 SDValue LoMask, HiMask;
2535 if (Mask.getOpcode() == ISD::SETCC) {
2536 SplitVecRes_SETCC(Mask.getNode(), LoMask, HiMask);
2537 } else {
2538 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
2539 GetSplitVector(Mask, LoMask, HiMask);
2540 else
2541 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
2542 }
2543
2544 SDValue LoEVL, HiEVL;
2545 std::tie(LoEVL, HiEVL) =
2546 DAG.SplitEVL(SLD->getVectorLength(), SLD->getValueType(0), DL);
2547
2548 // Generate the low vp_strided_load
2549 Lo = DAG.getStridedLoadVP(
2550 SLD->getAddressingMode(), SLD->getExtensionType(), LoVT, DL,
2551 SLD->getChain(), SLD->getBasePtr(), SLD->getOffset(), SLD->getStride(),
2552 LoMask, LoEVL, LoMemVT, SLD->getMemOperand(), SLD->isExpandingLoad());
2553
2554 if (HiIsEmpty) {
2555 // The high vp_strided_load has zero storage size. We therefore simply set
2556 // it to the low vp_strided_load and rely on subsequent removal from the
2557 // chain.
2558 Hi = Lo;
2559 } else {
2560 // Generate the high vp_strided_load.
2561 // To calculate the high base address, we need to sum to the low base
2562 // address stride number of bytes for each element already loaded by low,
2563 // that is: Ptr = Ptr + (LoEVL * Stride)
2564 EVT PtrVT = SLD->getBasePtr().getValueType();
2566 DAG.getNode(ISD::MUL, DL, PtrVT, LoEVL,
2567 DAG.getSExtOrTrunc(SLD->getStride(), DL, PtrVT));
2568 SDValue Ptr =
2569 DAG.getNode(ISD::ADD, DL, PtrVT, SLD->getBasePtr(), Increment);
2570
2571 Align Alignment = SLD->getBaseAlign();
2572 if (LoMemVT.isScalableVector())
2573 Alignment = commonAlignment(
2574 Alignment, LoMemVT.getSizeInBits().getKnownMinValue() / 8);
2575
2576 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
2577 MachinePointerInfo(SLD->getPointerInfo().getAddrSpace()),
2579 Alignment, SLD->getAAInfo(), SLD->getRanges());
2580
2581 Hi = DAG.getStridedLoadVP(SLD->getAddressingMode(), SLD->getExtensionType(),
2582 HiVT, DL, SLD->getChain(), Ptr, SLD->getOffset(),
2583 SLD->getStride(), HiMask, HiEVL, HiMemVT, MMO,
2584 SLD->isExpandingLoad());
2585 }
2586
2587 // Build a factor node to remember that this load is independent of the
2588 // other one.
2589 SDValue Ch = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo.getValue(1),
2590 Hi.getValue(1));
2591
2592 // Legalize the chain result - switch anything that used the old chain to
2593 // use the new one.
2594 ReplaceValueWith(SDValue(SLD, 1), Ch);
2595}
2596
2597void DAGTypeLegalizer::SplitVecRes_MLOAD(MaskedLoadSDNode *MLD,
2598 SDValue &Lo, SDValue &Hi) {
2599 assert(MLD->isUnindexed() && "Indexed masked load during type legalization!");
2600 EVT LoVT, HiVT;
2601 SDLoc dl(MLD);
2602 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(MLD->getValueType(0));
2603
2604 SDValue Ch = MLD->getChain();
2605 SDValue Ptr = MLD->getBasePtr();
2606 SDValue Offset = MLD->getOffset();
2607 assert(Offset.isUndef() && "Unexpected indexed masked load offset");
2608 SDValue Mask = MLD->getMask();
2609 SDValue PassThru = MLD->getPassThru();
2610 Align Alignment = MLD->getBaseAlign();
2611 ISD::LoadExtType ExtType = MLD->getExtensionType();
2612 MachineMemOperand::Flags MMOFlags = MLD->getMemOperand()->getFlags();
2613
2614 // Split Mask operand
2615 SDValue MaskLo, MaskHi;
2616 if (Mask.getOpcode() == ISD::SETCC) {
2617 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
2618 } else {
2619 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
2620 GetSplitVector(Mask, MaskLo, MaskHi);
2621 else
2622 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, dl);
2623 }
2624
2625 EVT MemoryVT = MLD->getMemoryVT();
2626 EVT LoMemVT, HiMemVT;
2627 bool HiIsEmpty = false;
2628 std::tie(LoMemVT, HiMemVT) =
2629 DAG.GetDependentSplitDestVTs(MemoryVT, LoVT, &HiIsEmpty);
2630
2631 SDValue PassThruLo, PassThruHi;
2632 if (getTypeAction(PassThru.getValueType()) == TargetLowering::TypeSplitVector)
2633 GetSplitVector(PassThru, PassThruLo, PassThruHi);
2634 else
2635 std::tie(PassThruLo, PassThruHi) = DAG.SplitVector(PassThru, dl);
2636
2637 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
2639 Alignment, MLD->getAAInfo(), MLD->getRanges());
2640
2641 Lo = DAG.getMaskedLoad(LoVT, dl, Ch, Ptr, Offset, MaskLo, PassThruLo, LoMemVT,
2642 MMO, MLD->getAddressingMode(), ExtType,
2643 MLD->isExpandingLoad());
2644
2645 if (HiIsEmpty) {
2646 // The hi masked load has zero storage size. We therefore simply set it to
2647 // the low masked load and rely on subsequent removal from the chain.
2648 Hi = Lo;
2649 } else {
2650 // Generate hi masked load.
2651 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, dl, LoMemVT, DAG,
2652 MLD->isExpandingLoad());
2653
2654 MachinePointerInfo MPI;
2655 if (LoMemVT.isScalableVector())
2656 MPI = MachinePointerInfo(MLD->getPointerInfo().getAddrSpace());
2657 else
2658 MPI = MLD->getPointerInfo().getWithOffset(
2659 LoMemVT.getStoreSize().getFixedValue());
2660
2661 MMO = DAG.getMachineFunction().getMachineMemOperand(
2662 MPI, MMOFlags, LocationSize::beforeOrAfterPointer(), Alignment,
2663 MLD->getAAInfo(), MLD->getRanges());
2664
2665 Hi = DAG.getMaskedLoad(HiVT, dl, Ch, Ptr, Offset, MaskHi, PassThruHi,
2666 HiMemVT, MMO, MLD->getAddressingMode(), ExtType,
2667 MLD->isExpandingLoad());
2668 }
2669
2670 // Build a factor node to remember that this load is independent of the
2671 // other one.
2672 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2673 Hi.getValue(1));
2674
2675 // Legalize the chain result - switch anything that used the old chain to
2676 // use the new one.
2677 ReplaceValueWith(SDValue(MLD, 1), Ch);
2678
2679}
2680
2681void DAGTypeLegalizer::SplitVecRes_Gather(MemSDNode *N, SDValue &Lo,
2682 SDValue &Hi, bool SplitSETCC) {
2683 EVT LoVT, HiVT;
2684 SDLoc dl(N);
2685 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2686
2687 SDValue Ch = N->getChain();
2688 SDValue Ptr = N->getBasePtr();
2689 struct Operands {
2690 SDValue Mask;
2691 SDValue Index;
2692 SDValue Scale;
2693 } Ops = [&]() -> Operands {
2694 if (auto *MSC = dyn_cast<MaskedGatherSDNode>(N)) {
2695 return {MSC->getMask(), MSC->getIndex(), MSC->getScale()};
2696 }
2697 auto *VPSC = cast<VPGatherSDNode>(N);
2698 return {VPSC->getMask(), VPSC->getIndex(), VPSC->getScale()};
2699 }();
2700
2701 EVT MemoryVT = N->getMemoryVT();
2702 Align Alignment = N->getBaseAlign();
2703
2704 // Split Mask operand
2705 SDValue MaskLo, MaskHi;
2706 if (SplitSETCC && Ops.Mask.getOpcode() == ISD::SETCC) {
2707 SplitVecRes_SETCC(Ops.Mask.getNode(), MaskLo, MaskHi);
2708 } else {
2709 std::tie(MaskLo, MaskHi) = SplitMask(Ops.Mask, dl);
2710 }
2711
2712 EVT LoMemVT, HiMemVT;
2713 // Split MemoryVT
2714 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
2715
2716 SDValue IndexHi, IndexLo;
2717 if (getTypeAction(Ops.Index.getValueType()) ==
2719 GetSplitVector(Ops.Index, IndexLo, IndexHi);
2720 else
2721 std::tie(IndexLo, IndexHi) = DAG.SplitVector(Ops.Index, dl);
2722
2723 MachineMemOperand::Flags MMOFlags = N->getMemOperand()->getFlags();
2724 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
2725 N->getPointerInfo(), MMOFlags, LocationSize::beforeOrAfterPointer(),
2726 Alignment, N->getAAInfo(), N->getRanges());
2727
2728 if (auto *MGT = dyn_cast<MaskedGatherSDNode>(N)) {
2729 SDValue PassThru = MGT->getPassThru();
2730 SDValue PassThruLo, PassThruHi;
2731 if (getTypeAction(PassThru.getValueType()) ==
2733 GetSplitVector(PassThru, PassThruLo, PassThruHi);
2734 else
2735 std::tie(PassThruLo, PassThruHi) = DAG.SplitVector(PassThru, dl);
2736
2737 ISD::LoadExtType ExtType = MGT->getExtensionType();
2738 ISD::MemIndexType IndexTy = MGT->getIndexType();
2739
2740 SDValue OpsLo[] = {Ch, PassThruLo, MaskLo, Ptr, IndexLo, Ops.Scale};
2741 Lo = DAG.getMaskedGather(DAG.getVTList(LoVT, MVT::Other), LoMemVT, dl,
2742 OpsLo, MMO, IndexTy, ExtType);
2743
2744 SDValue OpsHi[] = {Ch, PassThruHi, MaskHi, Ptr, IndexHi, Ops.Scale};
2745 Hi = DAG.getMaskedGather(DAG.getVTList(HiVT, MVT::Other), HiMemVT, dl,
2746 OpsHi, MMO, IndexTy, ExtType);
2747 } else {
2748 auto *VPGT = cast<VPGatherSDNode>(N);
2749 SDValue EVLLo, EVLHi;
2750 std::tie(EVLLo, EVLHi) =
2751 DAG.SplitEVL(VPGT->getVectorLength(), MemoryVT, dl);
2752
2753 SDValue OpsLo[] = {Ch, Ptr, IndexLo, Ops.Scale, MaskLo, EVLLo};
2754 Lo = DAG.getGatherVP(DAG.getVTList(LoVT, MVT::Other), LoMemVT, dl, OpsLo,
2755 MMO, VPGT->getIndexType());
2756
2757 SDValue OpsHi[] = {Ch, Ptr, IndexHi, Ops.Scale, MaskHi, EVLHi};
2758 Hi = DAG.getGatherVP(DAG.getVTList(HiVT, MVT::Other), HiMemVT, dl, OpsHi,
2759 MMO, VPGT->getIndexType());
2760 }
2761
2762 // Build a factor node to remember that this load is independent of the
2763 // other one.
2764 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2765 Hi.getValue(1));
2766
2767 // Legalize the chain result - switch anything that used the old chain to
2768 // use the new one.
2769 ReplaceValueWith(SDValue(N, 1), Ch);
2770}
2771
2772void DAGTypeLegalizer::SplitVecRes_VECTOR_COMPRESS(SDNode *N, SDValue &Lo,
2773 SDValue &Hi) {
2774 // This is not "trivial", as there is a dependency between the two subvectors.
2775 // Depending on the number of 1s in the mask, the elements from the Hi vector
2776 // need to be moved to the Lo vector. Passthru values make this even harder.
2777 // We try to use VECTOR_COMPRESS if the target has custom lowering with
2778 // smaller types and passthru is undef, as it is most likely faster than the
2779 // fully expand path. Otherwise, just do the full expansion as one "big"
2780 // operation and then extract the Lo and Hi vectors from that. This gets
2781 // rid of VECTOR_COMPRESS and all other operands can be legalized later.
2782 SDLoc DL(N);
2783 EVT VecVT = N->getValueType(0);
2784
2785 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(VecVT);
2786 bool HasCustomLowering = false;
2787 EVT CheckVT = LoVT;
2788 while (CheckVT.getVectorMinNumElements() > 1) {
2789 // TLI.isOperationLegalOrCustom requires a legal type, but we could have a
2790 // custom lowering for illegal types. So we do the checks separately.
2791 if (TLI.isOperationLegal(ISD::VECTOR_COMPRESS, CheckVT) ||
2792 TLI.isOperationCustom(ISD::VECTOR_COMPRESS, CheckVT)) {
2793 HasCustomLowering = true;
2794 break;
2795 }
2796 CheckVT = CheckVT.getHalfNumVectorElementsVT(*DAG.getContext());
2797 }
2798
2799 SDValue Passthru = N->getOperand(2);
2800 if (!HasCustomLowering) {
2801 SDValue Compressed = TLI.expandVECTOR_COMPRESS(N, DAG);
2802 std::tie(Lo, Hi) = DAG.SplitVector(Compressed, DL, LoVT, HiVT);
2803 return;
2804 }
2805
2806 // Try to VECTOR_COMPRESS smaller vectors and combine via a stack store+load.
2807 SDValue Mask = N->getOperand(1);
2808 SDValue LoMask, HiMask;
2809 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
2810 std::tie(LoMask, HiMask) = SplitMask(Mask);
2811
2812 SDValue UndefPassthru = DAG.getPOISON(LoVT);
2813 Lo = DAG.getNode(ISD::VECTOR_COMPRESS, DL, LoVT, Lo, LoMask, UndefPassthru);
2814 Hi = DAG.getNode(ISD::VECTOR_COMPRESS, DL, HiVT, Hi, HiMask, UndefPassthru);
2815
2816 SDValue StackPtr = DAG.CreateStackTemporary(
2817 VecVT.getStoreSize(), DAG.getReducedAlign(VecVT, /*UseABI=*/false));
2818 MachineFunction &MF = DAG.getMachineFunction();
2819 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(
2820 MF, cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex());
2821
2822 EVT MaskVT = LoMask.getValueType();
2823 assert(MaskVT.getScalarType() == MVT::i1 && "Expected vector of i1s");
2824
2825 // We store LoVec and then insert HiVec starting at offset=|1s| in LoMask.
2826 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i32,
2827 MaskVT.getVectorElementCount());
2828 SDValue WideMask = DAG.getNode(ISD::ZERO_EXTEND, DL, WideMaskVT, LoMask);
2829 SDValue Offset = DAG.getNode(ISD::VECREDUCE_ADD, DL, MVT::i32, WideMask);
2830 Offset = TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Offset);
2831
2832 SDValue Chain = DAG.getEntryNode();
2833 Chain = DAG.getStore(Chain, DL, Lo, StackPtr, PtrInfo);
2834 Chain = DAG.getStore(Chain, DL, Hi, Offset,
2836
2837 SDValue Compressed = DAG.getLoad(VecVT, DL, Chain, StackPtr, PtrInfo);
2838 if (!Passthru.isUndef()) {
2839 Compressed =
2840 DAG.getNode(ISD::VSELECT, DL, VecVT, Mask, Compressed, Passthru);
2841 }
2842 std::tie(Lo, Hi) = DAG.SplitVector(Compressed, DL);
2843}
2844
2845void DAGTypeLegalizer::SplitVecRes_SETCC(SDNode *N, SDValue &Lo, SDValue &Hi) {
2846 assert(N->getValueType(0).isVector() &&
2847 N->getOperand(0).getValueType().isVector() &&
2848 "Operand types must be vectors");
2849
2850 EVT LoVT, HiVT;
2851 SDLoc DL(N);
2852 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2853
2854 // If the input also splits, handle it directly. Otherwise split it by hand.
2855 SDValue LL, LH, RL, RH;
2856 if (getTypeAction(N->getOperand(0).getValueType()) ==
2858 GetSplitVector(N->getOperand(0), LL, LH);
2859 else
2860 std::tie(LL, LH) = DAG.SplitVectorOperand(N, 0);
2861
2862 if (getTypeAction(N->getOperand(1).getValueType()) ==
2864 GetSplitVector(N->getOperand(1), RL, RH);
2865 else
2866 std::tie(RL, RH) = DAG.SplitVectorOperand(N, 1);
2867
2868 if (N->getOpcode() == ISD::SETCC) {
2869 Lo = DAG.getNode(N->getOpcode(), DL, LoVT, LL, RL, N->getOperand(2));
2870 Hi = DAG.getNode(N->getOpcode(), DL, HiVT, LH, RH, N->getOperand(2));
2871 } else {
2872 assert(N->getOpcode() == ISD::VP_SETCC && "Expected VP_SETCC opcode");
2873 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
2874 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(3));
2875 std::tie(EVLLo, EVLHi) =
2876 DAG.SplitEVL(N->getOperand(4), N->getValueType(0), DL);
2877 Lo = DAG.getNode(N->getOpcode(), DL, LoVT, LL, RL, N->getOperand(2), MaskLo,
2878 EVLLo);
2879 Hi = DAG.getNode(N->getOpcode(), DL, HiVT, LH, RH, N->getOperand(2), MaskHi,
2880 EVLHi);
2881 }
2882}
2883
2884void DAGTypeLegalizer::SplitVecRes_UnaryOp(SDNode *N, SDValue &Lo,
2885 SDValue &Hi) {
2886 // Get the dest types - they may not match the input types, e.g. int_to_fp.
2887 EVT LoVT, HiVT;
2888 SDLoc dl(N);
2889 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2890
2891 // If the input also splits, handle it directly for a compile time speedup.
2892 // Otherwise split it by hand.
2893 EVT InVT = N->getOperand(0).getValueType();
2894 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
2895 GetSplitVector(N->getOperand(0), Lo, Hi);
2896 else
2897 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
2898
2899 const SDNodeFlags Flags = N->getFlags();
2900 unsigned Opcode = N->getOpcode();
2901 if (N->getNumOperands() <= 2) {
2902 if (Opcode == ISD::FP_ROUND || Opcode == ISD::AssertNoFPClass ||
2904 Lo = DAG.getNode(Opcode, dl, LoVT, Lo, N->getOperand(1), Flags);
2905 Hi = DAG.getNode(Opcode, dl, HiVT, Hi, N->getOperand(1), Flags);
2906 } else {
2907 Lo = DAG.getNode(Opcode, dl, LoVT, Lo, Flags);
2908 Hi = DAG.getNode(Opcode, dl, HiVT, Hi, Flags);
2909 }
2910 return;
2911 }
2912
2913 assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
2914 assert(N->isVPOpcode() && "Expected VP opcode");
2915
2916 SDValue MaskLo, MaskHi;
2917 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
2918
2919 SDValue EVLLo, EVLHi;
2920 std::tie(EVLLo, EVLHi) =
2921 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), dl);
2922
2923 Lo = DAG.getNode(Opcode, dl, LoVT, {Lo, MaskLo, EVLLo}, Flags);
2924 Hi = DAG.getNode(Opcode, dl, HiVT, {Hi, MaskHi, EVLHi}, Flags);
2925}
2926
2927void DAGTypeLegalizer::SplitVecRes_ADDRSPACECAST(SDNode *N, SDValue &Lo,
2928 SDValue &Hi) {
2929 SDLoc dl(N);
2930 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(N->getValueType(0));
2931
2932 // If the input also splits, handle it directly for a compile time speedup.
2933 // Otherwise split it by hand.
2934 EVT InVT = N->getOperand(0).getValueType();
2935 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
2936 GetSplitVector(N->getOperand(0), Lo, Hi);
2937 else
2938 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
2939
2940 auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
2941 unsigned SrcAS = AddrSpaceCastN->getSrcAddressSpace();
2942 unsigned DestAS = AddrSpaceCastN->getDestAddressSpace();
2943 Lo = DAG.getAddrSpaceCast(dl, LoVT, Lo, SrcAS, DestAS);
2944 Hi = DAG.getAddrSpaceCast(dl, HiVT, Hi, SrcAS, DestAS);
2945}
2946
2947void DAGTypeLegalizer::SplitVecRes_UnaryOpWithTwoResults(SDNode *N,
2948 unsigned ResNo,
2949 SDValue &Lo,
2950 SDValue &Hi) {
2951 SDLoc dl(N);
2952 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(N->getValueType(0));
2953 auto [LoVT1, HiVT1] = DAG.GetSplitDestVTs(N->getValueType(1));
2954
2955 // If the input also splits, handle it directly for a compile time speedup.
2956 // Otherwise split it by hand.
2957 EVT InVT = N->getOperand(0).getValueType();
2958 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
2959 GetSplitVector(N->getOperand(0), Lo, Hi);
2960 else
2961 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
2962
2963 Lo = DAG.getNode(N->getOpcode(), dl, {LoVT, LoVT1}, Lo, N->getFlags());
2964 Hi = DAG.getNode(N->getOpcode(), dl, {HiVT, HiVT1}, Hi, N->getFlags());
2965
2966 SDNode *HiNode = Hi.getNode();
2967 SDNode *LoNode = Lo.getNode();
2968
2969 // Replace the other vector result not being explicitly split here.
2970 unsigned OtherNo = 1 - ResNo;
2971 EVT OtherVT = N->getValueType(OtherNo);
2972 if (getTypeAction(OtherVT) == TargetLowering::TypeSplitVector) {
2973 SetSplitVector(SDValue(N, OtherNo), SDValue(LoNode, OtherNo),
2974 SDValue(HiNode, OtherNo));
2975 } else {
2976 SDValue OtherVal =
2977 DAG.getNode(ISD::CONCAT_VECTORS, dl, OtherVT, SDValue(LoNode, OtherNo),
2978 SDValue(HiNode, OtherNo));
2979 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
2980 }
2981}
2982
2983void DAGTypeLegalizer::SplitVecRes_ExtendOp(SDNode *N, SDValue &Lo,
2984 SDValue &Hi) {
2985 SDLoc dl(N);
2986 EVT SrcVT = N->getOperand(0).getValueType();
2987 EVT DestVT = N->getValueType(0);
2988 EVT LoVT, HiVT;
2989 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(DestVT);
2990
2991 // We can do better than a generic split operation if the extend is doing
2992 // more than just doubling the width of the elements and the following are
2993 // true:
2994 // - The number of vector elements is even,
2995 // - the source type is legal,
2996 // - the type of a split source is illegal,
2997 // - the type of an extended (by doubling element size) source is legal, and
2998 // - the type of that extended source when split is legal.
2999 //
3000 // This won't necessarily completely legalize the operation, but it will
3001 // more effectively move in the right direction and prevent falling down
3002 // to scalarization in many cases due to the input vector being split too
3003 // far.
3004 if (SrcVT.getVectorElementCount().isKnownEven() &&
3005 SrcVT.getScalarSizeInBits() * 2 < DestVT.getScalarSizeInBits()) {
3006 LLVMContext &Ctx = *DAG.getContext();
3007 EVT NewSrcVT = SrcVT.widenIntegerVectorElementType(Ctx);
3008 EVT SplitSrcVT = SrcVT.getHalfNumVectorElementsVT(Ctx);
3009
3010 EVT SplitLoVT, SplitHiVT;
3011 std::tie(SplitLoVT, SplitHiVT) = DAG.GetSplitDestVTs(NewSrcVT);
3012 if (TLI.isTypeLegal(SrcVT) && !TLI.isTypeLegal(SplitSrcVT) &&
3013 TLI.isTypeLegal(NewSrcVT) && TLI.isTypeLegal(SplitLoVT)) {
3014 LLVM_DEBUG(dbgs() << "Split vector extend via incremental extend:";
3015 N->dump(&DAG); dbgs() << "\n");
3016 if (!N->isVPOpcode()) {
3017 // Extend the source vector by one step.
3018 SDValue NewSrc =
3019 DAG.getNode(N->getOpcode(), dl, NewSrcVT, N->getOperand(0));
3020 // Get the low and high halves of the new, extended one step, vector.
3021 std::tie(Lo, Hi) = DAG.SplitVector(NewSrc, dl);
3022 // Extend those vector halves the rest of the way.
3023 Lo = DAG.getNode(N->getOpcode(), dl, LoVT, Lo);
3024 Hi = DAG.getNode(N->getOpcode(), dl, HiVT, Hi);
3025 return;
3026 }
3027
3028 // Extend the source vector by one step.
3029 SDValue NewSrc =
3030 DAG.getNode(N->getOpcode(), dl, NewSrcVT, N->getOperand(0),
3031 N->getOperand(1), N->getOperand(2));
3032 // Get the low and high halves of the new, extended one step, vector.
3033 std::tie(Lo, Hi) = DAG.SplitVector(NewSrc, dl);
3034
3035 SDValue MaskLo, MaskHi;
3036 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
3037
3038 SDValue EVLLo, EVLHi;
3039 std::tie(EVLLo, EVLHi) =
3040 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), dl);
3041 // Extend those vector halves the rest of the way.
3042 Lo = DAG.getNode(N->getOpcode(), dl, LoVT, {Lo, MaskLo, EVLLo});
3043 Hi = DAG.getNode(N->getOpcode(), dl, HiVT, {Hi, MaskHi, EVLHi});
3044 return;
3045 }
3046 }
3047 // Fall back to the generic unary operator splitting otherwise.
3048 SplitVecRes_UnaryOp(N, Lo, Hi);
3049}
3050
3051void DAGTypeLegalizer::SplitVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N,
3052 SDValue &Lo, SDValue &Hi) {
3053 // The low and high parts of the original input give four input vectors.
3054 SDValue Inputs[4];
3055 SDLoc DL(N);
3056 GetSplitVector(N->getOperand(0), Inputs[0], Inputs[1]);
3057 GetSplitVector(N->getOperand(1), Inputs[2], Inputs[3]);
3058 EVT NewVT = Inputs[0].getValueType();
3059 unsigned NewElts = NewVT.getVectorNumElements();
3060
3061 auto &&IsConstant = [](const SDValue &N) {
3062 APInt SplatValue;
3063 return N.getResNo() == 0 &&
3064 (ISD::isConstantSplatVector(N.getNode(), SplatValue) ||
3066 };
3067 auto &&BuildVector = [NewElts, &DAG = DAG, NewVT, &DL](SDValue &Input1,
3068 SDValue &Input2,
3069 ArrayRef<int> Mask) {
3070 assert(Input1->getOpcode() == ISD::BUILD_VECTOR &&
3071 Input2->getOpcode() == ISD::BUILD_VECTOR &&
3072 "Expected build vector node.");
3073 EVT EltVT = NewVT.getVectorElementType();
3074 SmallVector<SDValue> Ops(NewElts, DAG.getPOISON(EltVT));
3075 for (unsigned I = 0; I < NewElts; ++I) {
3076 if (Mask[I] == PoisonMaskElem)
3077 continue;
3078 unsigned Idx = Mask[I];
3079 if (Idx >= NewElts)
3080 Ops[I] = Input2.getOperand(Idx - NewElts);
3081 else
3082 Ops[I] = Input1.getOperand(Idx);
3083 // Make the type of all elements the same as the element type.
3084 if (Ops[I].getValueType().bitsGT(EltVT))
3085 Ops[I] = DAG.getNode(ISD::TRUNCATE, DL, EltVT, Ops[I]);
3086 }
3087 return DAG.getBuildVector(NewVT, DL, Ops);
3088 };
3089
3090 // If Lo or Hi uses elements from at most two of the four input vectors, then
3091 // express it as a vector shuffle of those two inputs. Otherwise extract the
3092 // input elements by hand and construct the Lo/Hi output using a BUILD_VECTOR.
3093 SmallVector<int> OrigMask(N->getMask());
3094 // Try to pack incoming shuffles/inputs.
3095 auto &&TryPeekThroughShufflesInputs = [&Inputs, &NewVT, this, NewElts,
3096 &DL](SmallVectorImpl<int> &Mask) {
3097 // Check if all inputs are shuffles of the same operands or non-shuffles.
3098 MapVector<std::pair<SDValue, SDValue>, SmallVector<unsigned>> ShufflesIdxs;
3099 for (unsigned Idx = 0; Idx < std::size(Inputs); ++Idx) {
3100 SDValue Input = Inputs[Idx];
3101 auto *Shuffle = dyn_cast<ShuffleVectorSDNode>(Input.getNode());
3102 if (!Shuffle ||
3103 Input.getOperand(0).getValueType() != Input.getValueType())
3104 continue;
3105 ShufflesIdxs[std::make_pair(Input.getOperand(0), Input.getOperand(1))]
3106 .push_back(Idx);
3107 ShufflesIdxs[std::make_pair(Input.getOperand(1), Input.getOperand(0))]
3108 .push_back(Idx);
3109 }
3110 for (auto &P : ShufflesIdxs) {
3111 if (P.second.size() < 2)
3112 continue;
3113 // Use shuffles operands instead of shuffles themselves.
3114 // 1. Adjust mask.
3115 for (int &Idx : Mask) {
3116 if (Idx == PoisonMaskElem)
3117 continue;
3118 unsigned SrcRegIdx = Idx / NewElts;
3119 if (Inputs[SrcRegIdx].isUndef()) {
3120 Idx = PoisonMaskElem;
3121 continue;
3122 }
3123 auto *Shuffle =
3124 dyn_cast<ShuffleVectorSDNode>(Inputs[SrcRegIdx].getNode());
3125 if (!Shuffle || !is_contained(P.second, SrcRegIdx))
3126 continue;
3127 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
3128 if (MaskElt == PoisonMaskElem) {
3129 Idx = PoisonMaskElem;
3130 continue;
3131 }
3132 Idx = MaskElt % NewElts +
3133 P.second[Shuffle->getOperand(MaskElt / NewElts) == P.first.first
3134 ? 0
3135 : 1] *
3136 NewElts;
3137 }
3138 // 2. Update inputs.
3139 Inputs[P.second[0]] = P.first.first;
3140 Inputs[P.second[1]] = P.first.second;
3141 // Clear the pair data.
3142 P.second.clear();
3143 ShufflesIdxs[std::make_pair(P.first.second, P.first.first)].clear();
3144 }
3145 // Check if any concat_vectors can be simplified.
3146 SmallBitVector UsedSubVector(2 * std::size(Inputs));
3147 for (int &Idx : Mask) {
3148 if (Idx == PoisonMaskElem)
3149 continue;
3150 unsigned SrcRegIdx = Idx / NewElts;
3151 if (Inputs[SrcRegIdx].isUndef()) {
3152 Idx = PoisonMaskElem;
3153 continue;
3154 }
3156 getTypeAction(Inputs[SrcRegIdx].getValueType());
3157 if (Inputs[SrcRegIdx].getOpcode() == ISD::CONCAT_VECTORS &&
3158 Inputs[SrcRegIdx].getNumOperands() == 2 &&
3159 !Inputs[SrcRegIdx].getOperand(1).isUndef() &&
3160 (TypeAction == TargetLowering::TypeLegal ||
3161 TypeAction == TargetLowering::TypeWidenVector))
3162 UsedSubVector.set(2 * SrcRegIdx + (Idx % NewElts) / (NewElts / 2));
3163 }
3164 if (UsedSubVector.count() > 1) {
3166 for (unsigned I = 0; I < std::size(Inputs); ++I) {
3167 if (UsedSubVector.test(2 * I) == UsedSubVector.test(2 * I + 1))
3168 continue;
3169 if (Pairs.empty() || Pairs.back().size() == 2)
3170 Pairs.emplace_back();
3171 if (UsedSubVector.test(2 * I)) {
3172 Pairs.back().emplace_back(I, 0);
3173 } else {
3174 assert(UsedSubVector.test(2 * I + 1) &&
3175 "Expected to be used one of the subvectors.");
3176 Pairs.back().emplace_back(I, 1);
3177 }
3178 }
3179 if (!Pairs.empty() && Pairs.front().size() > 1) {
3180 // Adjust mask.
3181 for (int &Idx : Mask) {
3182 if (Idx == PoisonMaskElem)
3183 continue;
3184 unsigned SrcRegIdx = Idx / NewElts;
3185 auto *It = find_if(
3186 Pairs, [SrcRegIdx](ArrayRef<std::pair<unsigned, int>> Idxs) {
3187 return Idxs.front().first == SrcRegIdx ||
3188 Idxs.back().first == SrcRegIdx;
3189 });
3190 if (It == Pairs.end())
3191 continue;
3192 Idx = It->front().first * NewElts + (Idx % NewElts) % (NewElts / 2) +
3193 (SrcRegIdx == It->front().first ? 0 : (NewElts / 2));
3194 }
3195 // Adjust inputs.
3196 for (ArrayRef<std::pair<unsigned, int>> Idxs : Pairs) {
3197 Inputs[Idxs.front().first] = DAG.getNode(
3199 Inputs[Idxs.front().first].getValueType(),
3200 Inputs[Idxs.front().first].getOperand(Idxs.front().second),
3201 Inputs[Idxs.back().first].getOperand(Idxs.back().second));
3202 }
3203 }
3204 }
3205 bool Changed;
3206 do {
3207 // Try to remove extra shuffles (except broadcasts) and shuffles with the
3208 // reused operands.
3209 Changed = false;
3210 for (unsigned I = 0; I < std::size(Inputs); ++I) {
3211 auto *Shuffle = dyn_cast<ShuffleVectorSDNode>(Inputs[I].getNode());
3212 if (!Shuffle)
3213 continue;
3214 if (Shuffle->getOperand(0).getValueType() != NewVT)
3215 continue;
3216 int Op = -1;
3217 if (!Inputs[I].hasOneUse() && Shuffle->getOperand(1).isUndef() &&
3218 !Shuffle->isSplat()) {
3219 Op = 0;
3220 } else if (!Inputs[I].hasOneUse() &&
3221 !Shuffle->getOperand(1).isUndef()) {
3222 // Find the only used operand, if possible.
3223 for (int &Idx : Mask) {
3224 if (Idx == PoisonMaskElem)
3225 continue;
3226 unsigned SrcRegIdx = Idx / NewElts;
3227 if (SrcRegIdx != I)
3228 continue;
3229 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
3230 if (MaskElt == PoisonMaskElem) {
3231 Idx = PoisonMaskElem;
3232 continue;
3233 }
3234 int OpIdx = MaskElt / NewElts;
3235 if (Op == -1) {
3236 Op = OpIdx;
3237 continue;
3238 }
3239 if (Op != OpIdx) {
3240 Op = -1;
3241 break;
3242 }
3243 }
3244 }
3245 if (Op < 0) {
3246 // Try to check if one of the shuffle operands is used already.
3247 for (int OpIdx = 0; OpIdx < 2; ++OpIdx) {
3248 if (Shuffle->getOperand(OpIdx).isUndef())
3249 continue;
3250 auto *It = find(Inputs, Shuffle->getOperand(OpIdx));
3251 if (It == std::end(Inputs))
3252 continue;
3253 int FoundOp = std::distance(std::begin(Inputs), It);
3254 // Found that operand is used already.
3255 // 1. Fix the mask for the reused operand.
3256 for (int &Idx : Mask) {
3257 if (Idx == PoisonMaskElem)
3258 continue;
3259 unsigned SrcRegIdx = Idx / NewElts;
3260 if (SrcRegIdx != I)
3261 continue;
3262 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
3263 if (MaskElt == PoisonMaskElem) {
3264 Idx = PoisonMaskElem;
3265 continue;
3266 }
3267 int MaskIdx = MaskElt / NewElts;
3268 if (OpIdx == MaskIdx)
3269 Idx = MaskElt % NewElts + FoundOp * NewElts;
3270 }
3271 // 2. Set Op to the unused OpIdx.
3272 Op = (OpIdx + 1) % 2;
3273 break;
3274 }
3275 }
3276 if (Op >= 0) {
3277 Changed = true;
3278 Inputs[I] = Shuffle->getOperand(Op);
3279 // Adjust mask.
3280 for (int &Idx : Mask) {
3281 if (Idx == PoisonMaskElem)
3282 continue;
3283 unsigned SrcRegIdx = Idx / NewElts;
3284 if (SrcRegIdx != I)
3285 continue;
3286 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
3287 int OpIdx = MaskElt / NewElts;
3288 if (OpIdx != Op)
3289 continue;
3290 Idx = MaskElt % NewElts + SrcRegIdx * NewElts;
3291 }
3292 }
3293 }
3294 } while (Changed);
3295 };
3296 TryPeekThroughShufflesInputs(OrigMask);
3297 // Proces unique inputs.
3298 auto &&MakeUniqueInputs = [&Inputs, &IsConstant,
3299 NewElts](SmallVectorImpl<int> &Mask) {
3300 SetVector<SDValue> UniqueInputs;
3301 SetVector<SDValue> UniqueConstantInputs;
3302 for (const auto &I : Inputs) {
3303 if (IsConstant(I))
3304 UniqueConstantInputs.insert(I);
3305 else if (!I.isUndef())
3306 UniqueInputs.insert(I);
3307 }
3308 // Adjust mask in case of reused inputs. Also, need to insert constant
3309 // inputs at first, otherwise it affects the final outcome.
3310 if (UniqueInputs.size() != std::size(Inputs)) {
3311 auto &&UniqueVec = UniqueInputs.takeVector();
3312 auto &&UniqueConstantVec = UniqueConstantInputs.takeVector();
3313 unsigned ConstNum = UniqueConstantVec.size();
3314 for (int &Idx : Mask) {
3315 if (Idx == PoisonMaskElem)
3316 continue;
3317 unsigned SrcRegIdx = Idx / NewElts;
3318 if (Inputs[SrcRegIdx].isUndef()) {
3319 Idx = PoisonMaskElem;
3320 continue;
3321 }
3322 const auto It = find(UniqueConstantVec, Inputs[SrcRegIdx]);
3323 if (It != UniqueConstantVec.end()) {
3324 Idx = (Idx % NewElts) +
3325 NewElts * std::distance(UniqueConstantVec.begin(), It);
3326 assert(Idx >= 0 && "Expected defined mask idx.");
3327 continue;
3328 }
3329 const auto RegIt = find(UniqueVec, Inputs[SrcRegIdx]);
3330 assert(RegIt != UniqueVec.end() && "Cannot find non-const value.");
3331 Idx = (Idx % NewElts) +
3332 NewElts * (std::distance(UniqueVec.begin(), RegIt) + ConstNum);
3333 assert(Idx >= 0 && "Expected defined mask idx.");
3334 }
3335 copy(UniqueConstantVec, std::begin(Inputs));
3336 copy(UniqueVec, std::next(std::begin(Inputs), ConstNum));
3337 }
3338 };
3339 MakeUniqueInputs(OrigMask);
3340 SDValue OrigInputs[4];
3341 copy(Inputs, std::begin(OrigInputs));
3342 for (unsigned High = 0; High < 2; ++High) {
3343 SDValue &Output = High ? Hi : Lo;
3344
3345 // Build a shuffle mask for the output, discovering on the fly which
3346 // input vectors to use as shuffle operands.
3347 unsigned FirstMaskIdx = High * NewElts;
3348 SmallVector<int> Mask(NewElts * std::size(Inputs), PoisonMaskElem);
3349 copy(ArrayRef(OrigMask).slice(FirstMaskIdx, NewElts), Mask.begin());
3350 assert(!Output && "Expected default initialized initial value.");
3351 TryPeekThroughShufflesInputs(Mask);
3352 MakeUniqueInputs(Mask);
3353 SDValue TmpInputs[4];
3354 copy(Inputs, std::begin(TmpInputs));
3355 // Track changes in the output registers.
3356 int UsedIdx = -1;
3357 bool SecondIteration = false;
3358 auto &&AccumulateResults = [&UsedIdx, &SecondIteration](unsigned Idx) {
3359 if (UsedIdx < 0) {
3360 UsedIdx = Idx;
3361 return false;
3362 }
3363 if (UsedIdx >= 0 && static_cast<unsigned>(UsedIdx) == Idx)
3364 SecondIteration = true;
3365 return SecondIteration;
3366 };
3368 Mask, std::size(Inputs), std::size(Inputs),
3369 /*NumOfUsedRegs=*/1,
3370 [&Output, &DAG = DAG, NewVT]() { Output = DAG.getPOISON(NewVT); },
3371 [&Output, &DAG = DAG, NewVT, &DL, &Inputs,
3372 &BuildVector](ArrayRef<int> Mask, unsigned Idx, unsigned /*Unused*/) {
3373 if (Inputs[Idx]->getOpcode() == ISD::BUILD_VECTOR)
3374 Output = BuildVector(Inputs[Idx], Inputs[Idx], Mask);
3375 else
3376 Output = DAG.getVectorShuffle(NewVT, DL, Inputs[Idx],
3377 DAG.getPOISON(NewVT), Mask);
3378 Inputs[Idx] = Output;
3379 },
3380 [&AccumulateResults, &Output, &DAG = DAG, NewVT, &DL, &Inputs,
3381 &TmpInputs, &BuildVector](ArrayRef<int> Mask, unsigned Idx1,
3382 unsigned Idx2, bool /*Unused*/) {
3383 if (AccumulateResults(Idx1)) {
3384 if (Inputs[Idx1]->getOpcode() == ISD::BUILD_VECTOR &&
3385 Inputs[Idx2]->getOpcode() == ISD::BUILD_VECTOR)
3386 Output = BuildVector(Inputs[Idx1], Inputs[Idx2], Mask);
3387 else
3388 Output = DAG.getVectorShuffle(NewVT, DL, Inputs[Idx1],
3389 Inputs[Idx2], Mask);
3390 } else {
3391 if (TmpInputs[Idx1]->getOpcode() == ISD::BUILD_VECTOR &&
3392 TmpInputs[Idx2]->getOpcode() == ISD::BUILD_VECTOR)
3393 Output = BuildVector(TmpInputs[Idx1], TmpInputs[Idx2], Mask);
3394 else
3395 Output = DAG.getVectorShuffle(NewVT, DL, TmpInputs[Idx1],
3396 TmpInputs[Idx2], Mask);
3397 }
3398 Inputs[Idx1] = Output;
3399 });
3400 copy(OrigInputs, std::begin(Inputs));
3401 }
3402}
3403
3404void DAGTypeLegalizer::SplitVecRes_VAARG(SDNode *N, SDValue &Lo, SDValue &Hi) {
3405 EVT OVT = N->getValueType(0);
3406 EVT NVT = OVT.getHalfNumVectorElementsVT(*DAG.getContext());
3407 SDValue Chain = N->getOperand(0);
3408 SDValue Ptr = N->getOperand(1);
3409 SDValue SV = N->getOperand(2);
3410 SDLoc dl(N);
3411
3412 const Align Alignment =
3413 DAG.getDataLayout().getABITypeAlign(NVT.getTypeForEVT(*DAG.getContext()));
3414
3415 Lo = DAG.getVAArg(NVT, dl, Chain, Ptr, SV, Alignment.value());
3416 Hi = DAG.getVAArg(NVT, dl, Lo.getValue(1), Ptr, SV, Alignment.value());
3417 Chain = Hi.getValue(1);
3418
3419 // Modified the chain - switch anything that used the old chain to use
3420 // the new one.
3421 ReplaceValueWith(SDValue(N, 1), Chain);
3422}
3423
3424void DAGTypeLegalizer::SplitVecRes_FP_TO_XINT_SAT(SDNode *N, SDValue &Lo,
3425 SDValue &Hi) {
3426 EVT DstVTLo, DstVTHi;
3427 std::tie(DstVTLo, DstVTHi) = DAG.GetSplitDestVTs(N->getValueType(0));
3428 SDLoc dl(N);
3429
3430 SDValue SrcLo, SrcHi;
3431 EVT SrcVT = N->getOperand(0).getValueType();
3432 if (getTypeAction(SrcVT) == TargetLowering::TypeSplitVector)
3433 GetSplitVector(N->getOperand(0), SrcLo, SrcHi);
3434 else
3435 std::tie(SrcLo, SrcHi) = DAG.SplitVectorOperand(N, 0);
3436
3437 Lo = DAG.getNode(N->getOpcode(), dl, DstVTLo, SrcLo, N->getOperand(1));
3438 Hi = DAG.getNode(N->getOpcode(), dl, DstVTHi, SrcHi, N->getOperand(1));
3439}
3440
3441void DAGTypeLegalizer::SplitVecRes_VECTOR_REVERSE(SDNode *N, SDValue &Lo,
3442 SDValue &Hi) {
3443 SDValue InLo, InHi;
3444 GetSplitVector(N->getOperand(0), InLo, InHi);
3445 SDLoc DL(N);
3446
3447 Lo = DAG.getNode(ISD::VECTOR_REVERSE, DL, InHi.getValueType(), InHi);
3448 Hi = DAG.getNode(ISD::VECTOR_REVERSE, DL, InLo.getValueType(), InLo);
3449}
3450
3451void DAGTypeLegalizer::SplitVecRes_VECTOR_SPLICE(SDNode *N, SDValue &Lo,
3452 SDValue &Hi) {
3453 SDLoc DL(N);
3454
3455 SDValue Expanded = TLI.expandVectorSplice(N, DAG);
3456 std::tie(Lo, Hi) = DAG.SplitVector(Expanded, DL);
3457}
3458
3459void DAGTypeLegalizer::SplitVecRes_VP_REVERSE(SDNode *N, SDValue &Lo,
3460 SDValue &Hi) {
3461 EVT VT = N->getValueType(0);
3462 SDValue Val = N->getOperand(0);
3463 SDValue Mask = N->getOperand(1);
3464 SDValue EVL = N->getOperand(2);
3465 SDLoc DL(N);
3466
3467 // Fallback to VP_STRIDED_STORE to stack followed by VP_LOAD.
3468 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
3469
3470 EVT MemVT = EVT::getVectorVT(*DAG.getContext(), VT.getVectorElementType(),
3472 SDValue StackPtr = DAG.CreateStackTemporary(MemVT.getStoreSize(), Alignment);
3473 EVT PtrVT = StackPtr.getValueType();
3474 auto &MF = DAG.getMachineFunction();
3475 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
3476 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
3477
3478 MachineMemOperand *StoreMMO = DAG.getMachineFunction().getMachineMemOperand(
3480 Alignment);
3481 MachineMemOperand *LoadMMO = DAG.getMachineFunction().getMachineMemOperand(
3483 Alignment);
3484
3485 unsigned EltWidth = VT.getScalarSizeInBits() / 8;
3486 SDValue NumElemMinus1 =
3487 DAG.getNode(ISD::SUB, DL, PtrVT, DAG.getZExtOrTrunc(EVL, DL, PtrVT),
3488 DAG.getConstant(1, DL, PtrVT));
3489 SDValue StartOffset = DAG.getNode(ISD::MUL, DL, PtrVT, NumElemMinus1,
3490 DAG.getConstant(EltWidth, DL, PtrVT));
3491 SDValue StorePtr = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, StartOffset);
3492 SDValue Stride = DAG.getConstant(-(int64_t)EltWidth, DL, PtrVT);
3493
3494 SDValue TrueMask = DAG.getBoolConstant(true, DL, Mask.getValueType(), VT);
3495 SDValue Store = DAG.getStridedStoreVP(DAG.getEntryNode(), DL, Val, StorePtr,
3496 DAG.getPOISON(PtrVT), Stride, TrueMask,
3497 EVL, MemVT, StoreMMO, ISD::UNINDEXED);
3498
3499 SDValue Load = DAG.getLoadVP(VT, DL, Store, StackPtr, Mask, EVL, LoadMMO);
3500
3501 std::tie(Lo, Hi) = DAG.SplitVector(Load, DL);
3502}
3503
3504void DAGTypeLegalizer::SplitVecRes_VP_SPLICE(SDNode *N, SDValue &Lo,
3505 SDValue &Hi) {
3506 EVT VT = N->getValueType(0);
3507 SDValue V1 = N->getOperand(0);
3508 SDValue V2 = N->getOperand(1);
3509 int64_t Imm = cast<ConstantSDNode>(N->getOperand(2))->getSExtValue();
3510 SDValue Mask = N->getOperand(3);
3511 SDValue EVL1 = N->getOperand(4);
3512 SDValue EVL2 = N->getOperand(5);
3513 SDLoc DL(N);
3514
3515 // Since EVL2 is considered the real VL it gets promoted during
3516 // SelectionDAGBuilder. Promote EVL1 here if needed.
3517 if (getTypeAction(EVL1.getValueType()) == TargetLowering::TypePromoteInteger)
3518 EVL1 = ZExtPromotedInteger(EVL1);
3519
3520 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
3521
3522 EVT MemVT = EVT::getVectorVT(*DAG.getContext(), VT.getVectorElementType(),
3523 VT.getVectorElementCount() * 2);
3524 SDValue StackPtr = DAG.CreateStackTemporary(MemVT.getStoreSize(), Alignment);
3525 EVT PtrVT = StackPtr.getValueType();
3526 auto &MF = DAG.getMachineFunction();
3527 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
3528 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
3529
3530 MachineMemOperand *StoreMMO = DAG.getMachineFunction().getMachineMemOperand(
3532 Alignment);
3533 MachineMemOperand *LoadMMO = DAG.getMachineFunction().getMachineMemOperand(
3535 Alignment);
3536
3537 SDValue StackPtr2 = TLI.getVectorElementPointer(DAG, StackPtr, VT, EVL1);
3538 SDValue PoisonPtr = DAG.getPOISON(PtrVT);
3539
3540 SDValue TrueMask = DAG.getBoolConstant(true, DL, Mask.getValueType(), VT);
3541 SDValue StoreV1 =
3542 DAG.getStoreVP(DAG.getEntryNode(), DL, V1, StackPtr, PoisonPtr, TrueMask,
3543 EVL1, V1.getValueType(), StoreMMO, ISD::UNINDEXED);
3544
3546 DAG.getStoreVP(StoreV1, DL, V2, StackPtr2, PoisonPtr, TrueMask, EVL2,
3547 V2.getValueType(), StoreMMO, ISD::UNINDEXED);
3548
3549 SDValue Load;
3550 if (Imm >= 0) {
3551 StackPtr = TLI.getVectorElementPointer(DAG, StackPtr, VT, N->getOperand(2));
3552 Load = DAG.getLoadVP(VT, DL, StoreV2, StackPtr, Mask, EVL2, LoadMMO);
3553 } else {
3554 uint64_t TrailingElts = -Imm;
3555 unsigned EltWidth = VT.getScalarSizeInBits() / 8;
3556 SDValue TrailingBytes = DAG.getConstant(TrailingElts * EltWidth, DL, PtrVT);
3557
3558 // Make sure TrailingBytes doesn't exceed the size of vec1.
3559 SDValue OffsetToV2 = DAG.getNode(ISD::SUB, DL, PtrVT, StackPtr2, StackPtr);
3560 TrailingBytes =
3561 DAG.getNode(ISD::UMIN, DL, PtrVT, TrailingBytes, OffsetToV2);
3562
3563 // Calculate the start address of the spliced result.
3564 StackPtr2 = DAG.getNode(ISD::SUB, DL, PtrVT, StackPtr2, TrailingBytes);
3565 Load = DAG.getLoadVP(VT, DL, StoreV2, StackPtr2, Mask, EVL2, LoadMMO);
3566 }
3567
3568 EVT LoVT, HiVT;
3569 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(VT);
3570 Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, LoVT, Load,
3571 DAG.getVectorIdxConstant(0, DL));
3572 Hi =
3573 DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, HiVT, Load,
3574 DAG.getVectorIdxConstant(LoVT.getVectorMinNumElements(), DL));
3575}
3576
3577void DAGTypeLegalizer::SplitVecRes_PARTIAL_REDUCE_MLA(SDNode *N, SDValue &Lo,
3578 SDValue &Hi) {
3579 SDLoc DL(N);
3580 SDValue Acc = N->getOperand(0);
3581 SDValue Input1 = N->getOperand(1);
3582 SDValue Input2 = N->getOperand(2);
3583
3584 SDValue AccLo, AccHi;
3585 GetSplitVector(Acc, AccLo, AccHi);
3586 unsigned Opcode = N->getOpcode();
3587
3588 // If the input types don't need splitting, just accumulate into the
3589 // low part of the accumulator.
3590 if (getTypeAction(Input1.getValueType()) != TargetLowering::TypeSplitVector) {
3591 Lo = DAG.getNode(Opcode, DL, AccLo.getValueType(), AccLo, Input1, Input2);
3592 Hi = AccHi;
3593 return;
3594 }
3595
3596 SDValue Input1Lo, Input1Hi;
3597 SDValue Input2Lo, Input2Hi;
3598 GetSplitVector(Input1, Input1Lo, Input1Hi);
3599 GetSplitVector(Input2, Input2Lo, Input2Hi);
3600 EVT ResultVT = AccLo.getValueType();
3601
3602 Lo = DAG.getNode(Opcode, DL, ResultVT, AccLo, Input1Lo, Input2Lo);
3603 Hi = DAG.getNode(Opcode, DL, ResultVT, AccHi, Input1Hi, Input2Hi);
3604}
3605
3606void DAGTypeLegalizer::SplitVecRes_GET_ACTIVE_LANE_MASK(SDNode *N, SDValue &Lo,
3607 SDValue &Hi) {
3608 SDLoc DL(N);
3609 SDValue Op0 = N->getOperand(0);
3610 SDValue Op1 = N->getOperand(1);
3611 EVT OpVT = Op0.getValueType();
3612
3613 EVT LoVT, HiVT;
3614 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
3615
3616 Lo = DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, DL, LoVT, Op0, Op1);
3617 SDValue LoElts = DAG.getElementCount(DL, OpVT, LoVT.getVectorElementCount());
3618 SDValue HiStartVal = DAG.getNode(ISD::UADDSAT, DL, OpVT, Op0, LoElts);
3619 Hi = DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, DL, HiVT, HiStartVal, Op1);
3620}
3621
3622void DAGTypeLegalizer::SplitVecRes_VECTOR_DEINTERLEAVE(SDNode *N) {
3623 unsigned Factor = N->getNumOperands();
3624
3625 SmallVector<SDValue, 8> Ops(Factor * 2);
3626 for (unsigned i = 0; i != Factor; ++i) {
3627 SDValue OpLo, OpHi;
3628 GetSplitVector(N->getOperand(i), OpLo, OpHi);
3629 Ops[i * 2] = OpLo;
3630 Ops[i * 2 + 1] = OpHi;
3631 }
3632
3633 SmallVector<EVT, 8> VTs(Factor, Ops[0].getValueType());
3634
3635 SDLoc DL(N);
3636 SDValue ResLo = DAG.getNode(ISD::VECTOR_DEINTERLEAVE, DL, VTs,
3637 ArrayRef(Ops).slice(0, Factor));
3638 SDValue ResHi = DAG.getNode(ISD::VECTOR_DEINTERLEAVE, DL, VTs,
3639 ArrayRef(Ops).slice(Factor, Factor));
3640
3641 for (unsigned i = 0; i != Factor; ++i)
3642 SetSplitVector(SDValue(N, i), ResLo.getValue(i), ResHi.getValue(i));
3643}
3644
3645void DAGTypeLegalizer::SplitVecRes_VECTOR_INTERLEAVE(SDNode *N) {
3646 unsigned Factor = N->getNumOperands();
3647
3648 SmallVector<SDValue, 8> Ops(Factor * 2);
3649 for (unsigned i = 0; i != Factor; ++i) {
3650 SDValue OpLo, OpHi;
3651 GetSplitVector(N->getOperand(i), OpLo, OpHi);
3652 Ops[i] = OpLo;
3653 Ops[i + Factor] = OpHi;
3654 }
3655
3656 SmallVector<EVT, 8> VTs(Factor, Ops[0].getValueType());
3657
3658 SDLoc DL(N);
3659 SDValue Res[] = {DAG.getNode(ISD::VECTOR_INTERLEAVE, DL, VTs,
3660 ArrayRef(Ops).slice(0, Factor)),
3661 DAG.getNode(ISD::VECTOR_INTERLEAVE, DL, VTs,
3662 ArrayRef(Ops).slice(Factor, Factor))};
3663
3664 for (unsigned i = 0; i != Factor; ++i) {
3665 unsigned IdxLo = 2 * i;
3666 unsigned IdxHi = 2 * i + 1;
3667 SetSplitVector(SDValue(N, i), Res[IdxLo / Factor].getValue(IdxLo % Factor),
3668 Res[IdxHi / Factor].getValue(IdxHi % Factor));
3669 }
3670}
3671
3672//===----------------------------------------------------------------------===//
3673// Operand Vector Splitting
3674//===----------------------------------------------------------------------===//
3675
3676/// This method is called when the specified operand of the specified node is
3677/// found to need vector splitting. At this point, all of the result types of
3678/// the node are known to be legal, but other operands of the node may need
3679/// legalization as well as the specified one.
3680bool DAGTypeLegalizer::SplitVectorOperand(SDNode *N, unsigned OpNo) {
3681 LLVM_DEBUG(dbgs() << "Split node operand: "; N->dump(&DAG));
3682 SDValue Res = SDValue();
3683
3684 // See if the target wants to custom split this node.
3685 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
3686 return false;
3687
3688 switch (N->getOpcode()) {
3689 default:
3690#ifndef NDEBUG
3691 dbgs() << "SplitVectorOperand Op #" << OpNo << ": ";
3692 N->dump(&DAG);
3693 dbgs() << "\n";
3694#endif
3695 report_fatal_error("Do not know how to split this operator's "
3696 "operand!\n");
3697
3698 case ISD::VP_SETCC:
3699 case ISD::STRICT_FSETCC:
3701 case ISD::SETCC: Res = SplitVecOp_VSETCC(N); break;
3702 case ISD::BITCAST: Res = SplitVecOp_BITCAST(N); break;
3703 case ISD::EXTRACT_SUBVECTOR: Res = SplitVecOp_EXTRACT_SUBVECTOR(N); break;
3704 case ISD::INSERT_SUBVECTOR: Res = SplitVecOp_INSERT_SUBVECTOR(N, OpNo); break;
3705 case ISD::EXTRACT_VECTOR_ELT:Res = SplitVecOp_EXTRACT_VECTOR_ELT(N); break;
3706 case ISD::CONCAT_VECTORS: Res = SplitVecOp_CONCAT_VECTORS(N); break;
3708 Res = SplitVecOp_VECTOR_FIND_LAST_ACTIVE(N);
3709 break;
3710 case ISD::VP_TRUNCATE:
3711 case ISD::TRUNCATE:
3712 Res = SplitVecOp_TruncateHelper(N);
3713 break;
3715 case ISD::VP_FP_ROUND:
3716 case ISD::FP_ROUND:
3718 Res = SplitVecOp_FP_ROUND(N);
3719 break;
3720 case ISD::FCOPYSIGN: Res = SplitVecOp_FPOpDifferentTypes(N); break;
3721 case ISD::STORE:
3722 Res = SplitVecOp_STORE(cast<StoreSDNode>(N), OpNo);
3723 break;
3724 case ISD::VP_STORE:
3725 Res = SplitVecOp_VP_STORE(cast<VPStoreSDNode>(N), OpNo);
3726 break;
3727 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
3728 Res = SplitVecOp_VP_STRIDED_STORE(cast<VPStridedStoreSDNode>(N), OpNo);
3729 break;
3730 case ISD::MSTORE:
3731 Res = SplitVecOp_MSTORE(cast<MaskedStoreSDNode>(N), OpNo);
3732 break;
3733 case ISD::MSCATTER:
3734 case ISD::VP_SCATTER:
3735 Res = SplitVecOp_Scatter(cast<MemSDNode>(N), OpNo);
3736 break;
3737 case ISD::MGATHER:
3738 case ISD::VP_GATHER:
3739 Res = SplitVecOp_Gather(cast<MemSDNode>(N), OpNo);
3740 break;
3741 case ISD::VSELECT:
3742 Res = SplitVecOp_VSELECT(N, OpNo);
3743 break;
3745 Res = SplitVecOp_VECTOR_COMPRESS(N, OpNo);
3746 break;
3749 case ISD::SINT_TO_FP:
3750 case ISD::UINT_TO_FP:
3751 case ISD::VP_SINT_TO_FP:
3752 case ISD::VP_UINT_TO_FP:
3753 if (N->getValueType(0).bitsLT(
3754 N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType()))
3755 Res = SplitVecOp_TruncateHelper(N);
3756 else
3757 Res = SplitVecOp_UnaryOp(N);
3758 break;
3761 Res = SplitVecOp_FP_TO_XINT_SAT(N);
3762 break;
3763 case ISD::FP_TO_SINT:
3764 case ISD::FP_TO_UINT:
3765 case ISD::VP_FP_TO_SINT:
3766 case ISD::VP_FP_TO_UINT:
3770 case ISD::FP_EXTEND:
3771 case ISD::SIGN_EXTEND:
3772 case ISD::ZERO_EXTEND:
3773 case ISD::ANY_EXTEND:
3774 case ISD::FTRUNC:
3775 case ISD::LROUND:
3776 case ISD::LLROUND:
3777 case ISD::LRINT:
3778 case ISD::LLRINT:
3779 Res = SplitVecOp_UnaryOp(N);
3780 break;
3781 case ISD::FLDEXP:
3782 Res = SplitVecOp_FPOpDifferentTypes(N);
3783 break;
3784
3785 case ISD::SCMP:
3786 case ISD::UCMP:
3787 Res = SplitVecOp_CMP(N);
3788 break;
3789
3790 case ISD::FAKE_USE:
3791 Res = SplitVecOp_FAKE_USE(N);
3792 break;
3796 Res = SplitVecOp_ExtVecInRegOp(N);
3797 break;
3798
3801 case ISD::VECREDUCE_ADD:
3802 case ISD::VECREDUCE_MUL:
3803 case ISD::VECREDUCE_AND:
3804 case ISD::VECREDUCE_OR:
3805 case ISD::VECREDUCE_XOR:
3814 Res = SplitVecOp_VECREDUCE(N, OpNo);
3815 break;
3818 Res = SplitVecOp_VECREDUCE_SEQ(N);
3819 break;
3820 case ISD::VP_REDUCE_FADD:
3821 case ISD::VP_REDUCE_SEQ_FADD:
3822 case ISD::VP_REDUCE_FMUL:
3823 case ISD::VP_REDUCE_SEQ_FMUL:
3824 case ISD::VP_REDUCE_ADD:
3825 case ISD::VP_REDUCE_MUL:
3826 case ISD::VP_REDUCE_AND:
3827 case ISD::VP_REDUCE_OR:
3828 case ISD::VP_REDUCE_XOR:
3829 case ISD::VP_REDUCE_SMAX:
3830 case ISD::VP_REDUCE_SMIN:
3831 case ISD::VP_REDUCE_UMAX:
3832 case ISD::VP_REDUCE_UMIN:
3833 case ISD::VP_REDUCE_FMAX:
3834 case ISD::VP_REDUCE_FMIN:
3835 case ISD::VP_REDUCE_FMAXIMUM:
3836 case ISD::VP_REDUCE_FMINIMUM:
3837 Res = SplitVecOp_VP_REDUCE(N, OpNo);
3838 break;
3839 case ISD::CTTZ_ELTS:
3841 Res = SplitVecOp_CttzElts(N);
3842 break;
3843 case ISD::VP_CTTZ_ELTS:
3844 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
3845 Res = SplitVecOp_VP_CttzElements(N);
3846 break;
3848 Res = SplitVecOp_VECTOR_HISTOGRAM(N);
3849 break;
3854 Res = SplitVecOp_PARTIAL_REDUCE_MLA(N);
3855 break;
3856 }
3857
3858 // If the result is null, the sub-method took care of registering results etc.
3859 if (!Res.getNode()) return false;
3860
3861 // If the result is N, the sub-method updated N in place. Tell the legalizer
3862 // core about this.
3863 if (Res.getNode() == N)
3864 return true;
3865
3866 if (N->isStrictFPOpcode())
3867 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
3868 "Invalid operand expansion");
3869 else
3870 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
3871 "Invalid operand expansion");
3872
3873 ReplaceValueWith(SDValue(N, 0), Res);
3874 return false;
3875}
3876
3877SDValue DAGTypeLegalizer::SplitVecOp_VECTOR_FIND_LAST_ACTIVE(SDNode *N) {
3878 SDLoc DL(N);
3879
3880 SDValue LoMask, HiMask;
3881 GetSplitVector(N->getOperand(0), LoMask, HiMask);
3882
3883 EVT VT = N->getValueType(0);
3884 EVT SplitVT = LoMask.getValueType();
3885 ElementCount SplitEC = SplitVT.getVectorElementCount();
3886
3887 // Find the last active in both the low and the high masks.
3888 SDValue LoFind = DAG.getNode(ISD::VECTOR_FIND_LAST_ACTIVE, DL, VT, LoMask);
3889 SDValue HiFind = DAG.getNode(ISD::VECTOR_FIND_LAST_ACTIVE, DL, VT, HiMask);
3890
3891 // Check if any lane is active in the high mask.
3892 // FIXME: This would not be necessary if VECTOR_FIND_LAST_ACTIVE returned a
3893 // sentinel value for "none active".
3894 SDValue AnyHiActive = DAG.getNode(ISD::VECREDUCE_OR, DL, MVT::i1, HiMask);
3895 SDValue Cond = DAG.getBoolExtOrTrunc(AnyHiActive, DL,
3896 getSetCCResultType(MVT::i1), MVT::i1);
3897
3898 // Return: AnyHiActive ? (HiFind + SplitEC) : LoFind;
3899 return DAG.getNode(ISD::SELECT, DL, VT, Cond,
3900 DAG.getNode(ISD::ADD, DL, VT, HiFind,
3901 DAG.getElementCount(DL, VT, SplitEC)),
3902 LoFind);
3903}
3904
3905SDValue DAGTypeLegalizer::SplitVecOp_VSELECT(SDNode *N, unsigned OpNo) {
3906 // The only possibility for an illegal operand is the mask, since result type
3907 // legalization would have handled this node already otherwise.
3908 assert(OpNo == 0 && "Illegal operand must be mask");
3909
3910 SDValue Mask = N->getOperand(0);
3911 SDValue Src0 = N->getOperand(1);
3912 SDValue Src1 = N->getOperand(2);
3913 EVT Src0VT = Src0.getValueType();
3914 SDLoc DL(N);
3915 assert(Mask.getValueType().isVector() && "VSELECT without a vector mask?");
3916
3917 SDValue Lo, Hi;
3918 GetSplitVector(N->getOperand(0), Lo, Hi);
3919 assert(Lo.getValueType() == Hi.getValueType() &&
3920 "Lo and Hi have differing types");
3921
3922 EVT LoOpVT, HiOpVT;
3923 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(Src0VT);
3924 assert(LoOpVT == HiOpVT && "Asymmetric vector split?");
3925
3926 SDValue LoOp0, HiOp0, LoOp1, HiOp1, LoMask, HiMask;
3927 std::tie(LoOp0, HiOp0) = DAG.SplitVector(Src0, DL);
3928 std::tie(LoOp1, HiOp1) = DAG.SplitVector(Src1, DL);
3929 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
3930
3931 SDValue LoSelect =
3932 DAG.getNode(ISD::VSELECT, DL, LoOpVT, LoMask, LoOp0, LoOp1);
3933 SDValue HiSelect =
3934 DAG.getNode(ISD::VSELECT, DL, HiOpVT, HiMask, HiOp0, HiOp1);
3935
3936 return DAG.getNode(ISD::CONCAT_VECTORS, DL, Src0VT, LoSelect, HiSelect);
3937}
3938
3939SDValue DAGTypeLegalizer::SplitVecOp_VECTOR_COMPRESS(SDNode *N, unsigned OpNo) {
3940 // The only possibility for an illegal operand is the mask, since result type
3941 // legalization would have handled this node already otherwise.
3942 assert(OpNo == 1 && "Illegal operand must be mask");
3943
3944 // To split the mask, we need to split the result type too, so we can just
3945 // reuse that logic here.
3946 SDValue Lo, Hi;
3947 SplitVecRes_VECTOR_COMPRESS(N, Lo, Hi);
3948
3949 EVT VecVT = N->getValueType(0);
3950 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), VecVT, Lo, Hi);
3951}
3952
3953SDValue DAGTypeLegalizer::SplitVecOp_VECREDUCE(SDNode *N, unsigned OpNo) {
3954 EVT ResVT = N->getValueType(0);
3955 SDValue Lo, Hi;
3956 SDLoc dl(N);
3957
3958 SDValue VecOp = N->getOperand(OpNo);
3959 EVT VecVT = VecOp.getValueType();
3960 assert(VecVT.isVector() && "Can only split reduce vector operand");
3961 GetSplitVector(VecOp, Lo, Hi);
3962 EVT LoOpVT, HiOpVT;
3963 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(VecVT);
3964
3965 // Use the appropriate scalar instruction on the split subvectors before
3966 // reducing the now partially reduced smaller vector.
3967 unsigned CombineOpc = ISD::getVecReduceBaseOpcode(N->getOpcode());
3968 SDValue Partial = DAG.getNode(CombineOpc, dl, LoOpVT, Lo, Hi, N->getFlags());
3969 return DAG.getNode(N->getOpcode(), dl, ResVT, Partial, N->getFlags());
3970}
3971
3972SDValue DAGTypeLegalizer::SplitVecOp_VECREDUCE_SEQ(SDNode *N) {
3973 EVT ResVT = N->getValueType(0);
3974 SDValue Lo, Hi;
3975 SDLoc dl(N);
3976
3977 SDValue AccOp = N->getOperand(0);
3978 SDValue VecOp = N->getOperand(1);
3979 SDNodeFlags Flags = N->getFlags();
3980
3981 EVT VecVT = VecOp.getValueType();
3982 assert(VecVT.isVector() && "Can only split reduce vector operand");
3983 GetSplitVector(VecOp, Lo, Hi);
3984 EVT LoOpVT, HiOpVT;
3985 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(VecVT);
3986
3987 // Reduce low half.
3988 SDValue Partial = DAG.getNode(N->getOpcode(), dl, ResVT, AccOp, Lo, Flags);
3989
3990 // Reduce high half, using low half result as initial value.
3991 return DAG.getNode(N->getOpcode(), dl, ResVT, Partial, Hi, Flags);
3992}
3993
3994SDValue DAGTypeLegalizer::SplitVecOp_VP_REDUCE(SDNode *N, unsigned OpNo) {
3995 assert(N->isVPOpcode() && "Expected VP opcode");
3996 assert(OpNo == 1 && "Can only split reduce vector operand");
3997
3998 unsigned Opc = N->getOpcode();
3999 EVT ResVT = N->getValueType(0);
4000 SDValue Lo, Hi;
4001 SDLoc dl(N);
4002
4003 SDValue VecOp = N->getOperand(OpNo);
4004 EVT VecVT = VecOp.getValueType();
4005 assert(VecVT.isVector() && "Can only split reduce vector operand");
4006 GetSplitVector(VecOp, Lo, Hi);
4007
4008 SDValue MaskLo, MaskHi;
4009 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(2));
4010
4011 SDValue EVLLo, EVLHi;
4012 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(N->getOperand(3), VecVT, dl);
4013
4014 const SDNodeFlags Flags = N->getFlags();
4015
4016 SDValue ResLo =
4017 DAG.getNode(Opc, dl, ResVT, {N->getOperand(0), Lo, MaskLo, EVLLo}, Flags);
4018 return DAG.getNode(Opc, dl, ResVT, {ResLo, Hi, MaskHi, EVLHi}, Flags);
4019}
4020
4021SDValue DAGTypeLegalizer::SplitVecOp_UnaryOp(SDNode *N) {
4022 // The result has a legal vector type, but the input needs splitting.
4023 EVT ResVT = N->getValueType(0);
4024 SDValue Lo, Hi;
4025 SDLoc dl(N);
4026 GetSplitVector(N->getOperand(N->isStrictFPOpcode() ? 1 : 0), Lo, Hi);
4027 EVT InVT = Lo.getValueType();
4028
4029 EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
4030 InVT.getVectorElementCount());
4031
4032 if (N->isStrictFPOpcode()) {
4033 Lo = DAG.getNode(N->getOpcode(), dl, {OutVT, MVT::Other},
4034 {N->getOperand(0), Lo});
4035 Hi = DAG.getNode(N->getOpcode(), dl, {OutVT, MVT::Other},
4036 {N->getOperand(0), Hi});
4037
4038 // Build a factor node to remember that this operation is independent
4039 // of the other one.
4040 SDValue Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
4041 Hi.getValue(1));
4042
4043 // Legalize the chain result - switch anything that used the old chain to
4044 // use the new one.
4045 ReplaceValueWith(SDValue(N, 1), Ch);
4046 } else if (N->getNumOperands() == 3) {
4047 assert(N->isVPOpcode() && "Expected VP opcode");
4048 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
4049 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
4050 std::tie(EVLLo, EVLHi) =
4051 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), dl);
4052 Lo = DAG.getNode(N->getOpcode(), dl, OutVT, Lo, MaskLo, EVLLo);
4053 Hi = DAG.getNode(N->getOpcode(), dl, OutVT, Hi, MaskHi, EVLHi);
4054 } else {
4055 Lo = DAG.getNode(N->getOpcode(), dl, OutVT, Lo);
4056 Hi = DAG.getNode(N->getOpcode(), dl, OutVT, Hi);
4057 }
4058
4059 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
4060}
4061
4062// Split a FAKE_USE use of a vector into FAKE_USEs of hi and lo part.
4063SDValue DAGTypeLegalizer::SplitVecOp_FAKE_USE(SDNode *N) {
4064 SDValue Lo, Hi;
4065 GetSplitVector(N->getOperand(1), Lo, Hi);
4066 SDValue Chain =
4067 DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, N->getOperand(0), Lo);
4068 return DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, Chain, Hi);
4069}
4070
4071SDValue DAGTypeLegalizer::SplitVecOp_BITCAST(SDNode *N) {
4072 // For example, i64 = BITCAST v4i16 on alpha. Typically the vector will
4073 // end up being split all the way down to individual components. Convert the
4074 // split pieces into integers and reassemble.
4075 EVT ResVT = N->getValueType(0);
4076 SDValue Lo, Hi;
4077 GetSplitVector(N->getOperand(0), Lo, Hi);
4078 SDLoc dl(N);
4079
4080 if (ResVT.isScalableVector()) {
4081 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(ResVT);
4082 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
4083 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
4084 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
4085 }
4086
4087 Lo = BitConvertToInteger(Lo);
4088 Hi = BitConvertToInteger(Hi);
4089
4090 if (DAG.getDataLayout().isBigEndian())
4091 std::swap(Lo, Hi);
4092
4093 return DAG.getNode(ISD::BITCAST, dl, ResVT, JoinIntegers(Lo, Hi));
4094}
4095
4096SDValue DAGTypeLegalizer::SplitVecOp_INSERT_SUBVECTOR(SDNode *N,
4097 unsigned OpNo) {
4098 assert(OpNo == 1 && "Invalid OpNo; can only split SubVec.");
4099 // We know that the result type is legal.
4100 EVT ResVT = N->getValueType(0);
4101
4102 SDValue Vec = N->getOperand(0);
4103 SDValue SubVec = N->getOperand(1);
4104 SDValue Idx = N->getOperand(2);
4105 SDLoc dl(N);
4106
4107 SDValue Lo, Hi;
4108 GetSplitVector(SubVec, Lo, Hi);
4109
4110 uint64_t IdxVal = Idx->getAsZExtVal();
4111 uint64_t LoElts = Lo.getValueType().getVectorMinNumElements();
4112
4113 SDValue FirstInsertion =
4114 DAG.getNode(ISD::INSERT_SUBVECTOR, dl, ResVT, Vec, Lo, Idx);
4115 SDValue SecondInsertion =
4116 DAG.getNode(ISD::INSERT_SUBVECTOR, dl, ResVT, FirstInsertion, Hi,
4117 DAG.getVectorIdxConstant(IdxVal + LoElts, dl));
4118
4119 return SecondInsertion;
4120}
4121
4122SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
4123 // We know that the extracted result type is legal.
4124 EVT SubVT = N->getValueType(0);
4125 SDValue Idx = N->getOperand(1);
4126 SDLoc dl(N);
4127 SDValue Lo, Hi;
4128
4129 GetSplitVector(N->getOperand(0), Lo, Hi);
4130
4131 ElementCount LoElts = Lo.getValueType().getVectorElementCount();
4132 // Note: For scalable vectors, the index is scaled by vscale.
4133 ElementCount IdxVal =
4135 uint64_t IdxValMin = IdxVal.getKnownMinValue();
4136
4137 EVT SrcVT = N->getOperand(0).getValueType();
4138 ElementCount NumResultElts = SubVT.getVectorElementCount();
4139
4140 // If the extracted elements are all in the low half, do a simple extract.
4141 if (ElementCount::isKnownLE(IdxVal + NumResultElts, LoElts))
4142 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, SubVT, Lo, Idx);
4143
4144 unsigned LoEltsMin = LoElts.getKnownMinValue();
4145 if (IdxValMin < LoEltsMin && SubVT.isFixedLengthVector() &&
4146 SrcVT.isFixedLengthVector()) {
4147 // Extracted subvector crosses vector split, so we need to blend the two
4148 // halves.
4149 // TODO: May be able to emit partial extract_subvector.
4151 Elts.reserve(NumResultElts.getFixedValue());
4152
4153 // This is not valid for scalable vectors. If SubVT is scalable, this is the
4154 // same as unrolling a scalable dimension (invalid). If ScrVT is scalable,
4155 // `Lo[LoEltsMin]` may not be the last element of `Lo`.
4156 DAG.ExtractVectorElements(Lo, Elts, /*Start=*/IdxValMin,
4157 /*Count=*/LoEltsMin - IdxValMin);
4158 DAG.ExtractVectorElements(Hi, Elts, /*Start=*/0,
4159 /*Count=*/SubVT.getVectorNumElements() -
4160 Elts.size());
4161 return DAG.getBuildVector(SubVT, dl, Elts);
4162 }
4163
4164 if (SubVT.isScalableVector() == SrcVT.isScalableVector()) {
4165 ElementCount ExtractIdx = IdxVal - LoElts;
4166 if (ExtractIdx.isKnownMultipleOf(NumResultElts))
4167 return DAG.getExtractSubvector(dl, SubVT, Hi,
4168 ExtractIdx.getKnownMinValue());
4169
4170 EVT HiVT = Hi.getValueType();
4171 assert(HiVT.isFixedLengthVector() &&
4172 "Only fixed-vector extracts are supported in this case");
4173
4174 // We cannot create an extract_subvector that isn't a multiple of the
4175 // result size, which may go out of bounds for the last elements. Shuffle
4176 // the desired elements down to 0 and do a simple 0 extract.
4177 SmallVector<int, 8> Mask(HiVT.getVectorNumElements(), -1);
4178 for (int I = 0; I != int(NumResultElts.getFixedValue()); ++I)
4179 Mask[I] = int(ExtractIdx.getFixedValue()) + I;
4180
4181 SDValue Shuffle =
4182 DAG.getVectorShuffle(HiVT, dl, Hi, DAG.getPOISON(HiVT), Mask);
4183 return DAG.getExtractSubvector(dl, SubVT, Shuffle, 0);
4184 }
4185
4186 // After this point the DAG node only permits extracting fixed-width
4187 // subvectors from scalable vectors.
4188 assert(SubVT.isFixedLengthVector() &&
4189 "Extracting scalable subvector from fixed-width unsupported");
4190
4191 // If the element type is i1 and we're not promoting the result, then we may
4192 // end up loading the wrong data since the bits are packed tightly into
4193 // bytes. For example, if we extract a v4i1 (legal) from a nxv4i1 (legal)
4194 // type at index 4, then we will load a byte starting at index 0.
4195 if (SubVT.getScalarType() == MVT::i1)
4196 report_fatal_error("Don't know how to extract fixed-width predicate "
4197 "subvector from a scalable predicate vector");
4198
4199 // Spill the vector to the stack. We should use the alignment for
4200 // the smallest part.
4201 SDValue Vec = N->getOperand(0);
4202 EVT VecVT = Vec.getValueType();
4203 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
4205 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
4206 auto &MF = DAG.getMachineFunction();
4207 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
4208 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
4209
4210 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
4211 SmallestAlign);
4212
4213 // Extract the subvector by loading the correct part.
4214 StackPtr = TLI.getVectorSubVecPointer(DAG, StackPtr, VecVT, SubVT, Idx);
4215
4216 return DAG.getLoad(
4217 SubVT, dl, Store, StackPtr,
4218 MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()));
4219}
4220
4221SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
4222 SDValue Vec = N->getOperand(0);
4223 SDValue Idx = N->getOperand(1);
4224 EVT VecVT = Vec.getValueType();
4225
4226 if (const ConstantSDNode *Index = dyn_cast<ConstantSDNode>(Idx)) {
4227 uint64_t IdxVal = Index->getZExtValue();
4228
4229 SDValue Lo, Hi;
4230 GetSplitVector(Vec, Lo, Hi);
4231
4232 uint64_t LoElts = Lo.getValueType().getVectorMinNumElements();
4233
4234 if (IdxVal < LoElts)
4235 return SDValue(DAG.UpdateNodeOperands(N, Lo, Idx), 0);
4236 else if (!Vec.getValueType().isScalableVector())
4237 return SDValue(DAG.UpdateNodeOperands(N, Hi,
4238 DAG.getConstant(IdxVal - LoElts, SDLoc(N),
4239 Idx.getValueType())), 0);
4240 }
4241
4242 // See if the target wants to custom expand this node.
4243 if (CustomLowerNode(N, N->getValueType(0), true))
4244 return SDValue();
4245
4246 // Make the vector elements byte-addressable if they aren't already.
4247 SDLoc dl(N);
4248 EVT EltVT = VecVT.getVectorElementType();
4249 if (!EltVT.isByteSized()) {
4250 EltVT = EltVT.changeTypeToInteger().getRoundIntegerType(*DAG.getContext());
4251 VecVT = VecVT.changeElementType(*DAG.getContext(), EltVT);
4252 Vec = DAG.getNode(ISD::ANY_EXTEND, dl, VecVT, Vec);
4253 SDValue NewExtract =
4254 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, Vec, Idx);
4255 return DAG.getAnyExtOrTrunc(NewExtract, dl, N->getValueType(0));
4256 }
4257
4258 // Store the vector to the stack.
4259 // In cases where the vector is illegal it will be broken down into parts
4260 // and stored in parts - we should use the alignment for the smallest part.
4261 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
4263 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
4264 auto &MF = DAG.getMachineFunction();
4265 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
4266 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
4267 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
4268 SmallestAlign);
4269
4270 // Load back the required element.
4271 StackPtr = TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Idx);
4272
4273 // EXTRACT_VECTOR_ELT can extend the element type to the width of the return
4274 // type, leaving the high bits undefined. But it can't truncate.
4275 assert(N->getValueType(0).bitsGE(EltVT) && "Illegal EXTRACT_VECTOR_ELT.");
4276
4277 return DAG.getExtLoad(
4278 ISD::EXTLOAD, dl, N->getValueType(0), Store, StackPtr,
4279 MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()), EltVT,
4280 commonAlignment(SmallestAlign, EltVT.getFixedSizeInBits() / 8));
4281}
4282
4283SDValue DAGTypeLegalizer::SplitVecOp_ExtVecInRegOp(SDNode *N) {
4284 SDValue Lo, Hi;
4285
4286 // *_EXTEND_VECTOR_INREG only reference the lower half of the input, so
4287 // splitting the result has the same effect as splitting the input operand.
4288 SplitVecRes_ExtVecInRegOp(N, Lo, Hi);
4289
4290 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), N->getValueType(0), Lo, Hi);
4291}
4292
4293SDValue DAGTypeLegalizer::SplitVecOp_Gather(MemSDNode *N, unsigned OpNo) {
4294 (void)OpNo;
4295 SDValue Lo, Hi;
4296 SplitVecRes_Gather(N, Lo, Hi);
4297
4298 SDValue Res = DAG.getNode(ISD::CONCAT_VECTORS, N, N->getValueType(0), Lo, Hi);
4299 ReplaceValueWith(SDValue(N, 0), Res);
4300 return SDValue();
4301}
4302
4303SDValue DAGTypeLegalizer::SplitVecOp_VP_STORE(VPStoreSDNode *N, unsigned OpNo) {
4304 assert(N->isUnindexed() && "Indexed vp_store of vector?");
4305 SDValue Ch = N->getChain();
4306 SDValue Ptr = N->getBasePtr();
4307 SDValue Offset = N->getOffset();
4308 assert(Offset.isUndef() && "Unexpected VP store offset");
4309 SDValue Mask = N->getMask();
4310 SDValue EVL = N->getVectorLength();
4311 SDValue Data = N->getValue();
4312 Align Alignment = N->getBaseAlign();
4313 SDLoc DL(N);
4314
4315 SDValue DataLo, DataHi;
4316 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
4317 // Split Data operand
4318 GetSplitVector(Data, DataLo, DataHi);
4319 else
4320 std::tie(DataLo, DataHi) = DAG.SplitVector(Data, DL);
4321
4322 // Split Mask operand
4323 SDValue MaskLo, MaskHi;
4324 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC) {
4325 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
4326 } else {
4327 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
4328 GetSplitVector(Mask, MaskLo, MaskHi);
4329 else
4330 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
4331 }
4332
4333 EVT MemoryVT = N->getMemoryVT();
4334 EVT LoMemVT, HiMemVT;
4335 bool HiIsEmpty = false;
4336 std::tie(LoMemVT, HiMemVT) =
4337 DAG.GetDependentSplitDestVTs(MemoryVT, DataLo.getValueType(), &HiIsEmpty);
4338
4339 // Split EVL
4340 SDValue EVLLo, EVLHi;
4341 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(EVL, Data.getValueType(), DL);
4342
4343 SDValue Lo, Hi;
4344 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
4345 N->getPointerInfo(), MachineMemOperand::MOStore,
4346 LocationSize::beforeOrAfterPointer(), Alignment, N->getAAInfo(),
4347 N->getRanges());
4348
4349 Lo = DAG.getStoreVP(Ch, DL, DataLo, Ptr, Offset, MaskLo, EVLLo, LoMemVT, MMO,
4350 N->getAddressingMode(), N->isTruncatingStore(),
4351 N->isCompressingStore());
4352
4353 // If the hi vp_store has zero storage size, only the lo vp_store is needed.
4354 if (HiIsEmpty)
4355 return Lo;
4356
4357 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, DL, LoMemVT, DAG,
4358 N->isCompressingStore());
4359
4360 MachinePointerInfo MPI;
4361 if (LoMemVT.isScalableVector()) {
4362 Alignment = commonAlignment(Alignment,
4363 LoMemVT.getSizeInBits().getKnownMinValue() / 8);
4364 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
4365 } else
4366 MPI = N->getPointerInfo().getWithOffset(
4367 LoMemVT.getStoreSize().getFixedValue());
4368
4369 MMO = DAG.getMachineFunction().getMachineMemOperand(
4371 Alignment, N->getAAInfo(), N->getRanges());
4372
4373 Hi = DAG.getStoreVP(Ch, DL, DataHi, Ptr, Offset, MaskHi, EVLHi, HiMemVT, MMO,
4374 N->getAddressingMode(), N->isTruncatingStore(),
4375 N->isCompressingStore());
4376
4377 // Build a factor node to remember that this store is independent of the
4378 // other one.
4379 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4380}
4381
4382SDValue DAGTypeLegalizer::SplitVecOp_VP_STRIDED_STORE(VPStridedStoreSDNode *N,
4383 unsigned OpNo) {
4384 assert(N->isUnindexed() && "Indexed vp_strided_store of a vector?");
4385 assert(N->getOffset().isUndef() && "Unexpected VP strided store offset");
4386
4387 SDLoc DL(N);
4388
4389 SDValue Data = N->getValue();
4390 SDValue LoData, HiData;
4391 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
4392 GetSplitVector(Data, LoData, HiData);
4393 else
4394 std::tie(LoData, HiData) = DAG.SplitVector(Data, DL);
4395
4396 EVT LoMemVT, HiMemVT;
4397 bool HiIsEmpty = false;
4398 std::tie(LoMemVT, HiMemVT) = DAG.GetDependentSplitDestVTs(
4399 N->getMemoryVT(), LoData.getValueType(), &HiIsEmpty);
4400
4401 SDValue Mask = N->getMask();
4402 SDValue LoMask, HiMask;
4403 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC)
4404 SplitVecRes_SETCC(Mask.getNode(), LoMask, HiMask);
4405 else if (getTypeAction(Mask.getValueType()) ==
4407 GetSplitVector(Mask, LoMask, HiMask);
4408 else
4409 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
4410
4411 SDValue LoEVL, HiEVL;
4412 std::tie(LoEVL, HiEVL) =
4413 DAG.SplitEVL(N->getVectorLength(), Data.getValueType(), DL);
4414
4415 // Generate the low vp_strided_store
4416 SDValue Lo = DAG.getStridedStoreVP(
4417 N->getChain(), DL, LoData, N->getBasePtr(), N->getOffset(),
4418 N->getStride(), LoMask, LoEVL, LoMemVT, N->getMemOperand(),
4419 N->getAddressingMode(), N->isTruncatingStore(), N->isCompressingStore());
4420
4421 // If the high vp_strided_store has zero storage size, only the low
4422 // vp_strided_store is needed.
4423 if (HiIsEmpty)
4424 return Lo;
4425
4426 // Generate the high vp_strided_store.
4427 // To calculate the high base address, we need to sum to the low base
4428 // address stride number of bytes for each element already stored by low,
4429 // that is: Ptr = Ptr + (LoEVL * Stride)
4430 EVT PtrVT = N->getBasePtr().getValueType();
4432 DAG.getNode(ISD::MUL, DL, PtrVT, LoEVL,
4433 DAG.getSExtOrTrunc(N->getStride(), DL, PtrVT));
4434 SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, N->getBasePtr(), Increment);
4435
4436 Align Alignment = N->getBaseAlign();
4437 if (LoMemVT.isScalableVector())
4438 Alignment = commonAlignment(Alignment,
4439 LoMemVT.getSizeInBits().getKnownMinValue() / 8);
4440
4441 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
4442 MachinePointerInfo(N->getPointerInfo().getAddrSpace()),
4444 Alignment, N->getAAInfo(), N->getRanges());
4445
4446 SDValue Hi = DAG.getStridedStoreVP(
4447 N->getChain(), DL, HiData, Ptr, N->getOffset(), N->getStride(), HiMask,
4448 HiEVL, HiMemVT, MMO, N->getAddressingMode(), N->isTruncatingStore(),
4449 N->isCompressingStore());
4450
4451 // Build a factor node to remember that this store is independent of the
4452 // other one.
4453 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4454}
4455
4456SDValue DAGTypeLegalizer::SplitVecOp_MSTORE(MaskedStoreSDNode *N,
4457 unsigned OpNo) {
4458 assert(N->isUnindexed() && "Indexed masked store of vector?");
4459 SDValue Ch = N->getChain();
4460 SDValue Ptr = N->getBasePtr();
4461 SDValue Offset = N->getOffset();
4462 assert(Offset.isUndef() && "Unexpected indexed masked store offset");
4463 SDValue Mask = N->getMask();
4464 SDValue Data = N->getValue();
4465 Align Alignment = N->getBaseAlign();
4466 SDLoc DL(N);
4467
4468 SDValue DataLo, DataHi;
4469 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
4470 // Split Data operand
4471 GetSplitVector(Data, DataLo, DataHi);
4472 else
4473 std::tie(DataLo, DataHi) = DAG.SplitVector(Data, DL);
4474
4475 // Split Mask operand
4476 SDValue MaskLo, MaskHi;
4477 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC) {
4478 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
4479 } else {
4480 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
4481 GetSplitVector(Mask, MaskLo, MaskHi);
4482 else
4483 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
4484 }
4485
4486 EVT MemoryVT = N->getMemoryVT();
4487 EVT LoMemVT, HiMemVT;
4488 bool HiIsEmpty = false;
4489 std::tie(LoMemVT, HiMemVT) =
4490 DAG.GetDependentSplitDestVTs(MemoryVT, DataLo.getValueType(), &HiIsEmpty);
4491
4492 SDValue Lo, Hi, Res;
4493 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
4494 N->getPointerInfo(), MachineMemOperand::MOStore,
4495 LocationSize::beforeOrAfterPointer(), Alignment, N->getAAInfo(),
4496 N->getRanges());
4497
4498 Lo = DAG.getMaskedStore(Ch, DL, DataLo, Ptr, Offset, MaskLo, LoMemVT, MMO,
4499 N->getAddressingMode(), N->isTruncatingStore(),
4500 N->isCompressingStore());
4501
4502 if (HiIsEmpty) {
4503 // The hi masked store has zero storage size.
4504 // Only the lo masked store is needed.
4505 Res = Lo;
4506 } else {
4507
4508 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, DL, LoMemVT, DAG,
4509 N->isCompressingStore());
4510
4511 MachinePointerInfo MPI;
4512 if (LoMemVT.isScalableVector()) {
4513 Alignment = commonAlignment(
4514 Alignment, LoMemVT.getSizeInBits().getKnownMinValue() / 8);
4515 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
4516 } else
4517 MPI = N->getPointerInfo().getWithOffset(
4518 LoMemVT.getStoreSize().getFixedValue());
4519
4520 MMO = DAG.getMachineFunction().getMachineMemOperand(
4522 Alignment, N->getAAInfo(), N->getRanges());
4523
4524 Hi = DAG.getMaskedStore(Ch, DL, DataHi, Ptr, Offset, MaskHi, HiMemVT, MMO,
4525 N->getAddressingMode(), N->isTruncatingStore(),
4526 N->isCompressingStore());
4527
4528 // Build a factor node to remember that this store is independent of the
4529 // other one.
4530 Res = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4531 }
4532
4533 return Res;
4534}
4535
4536SDValue DAGTypeLegalizer::SplitVecOp_Scatter(MemSDNode *N, unsigned OpNo) {
4537 SDValue Ch = N->getChain();
4538 SDValue Ptr = N->getBasePtr();
4539 EVT MemoryVT = N->getMemoryVT();
4540 Align Alignment = N->getBaseAlign();
4541 SDLoc DL(N);
4542 struct Operands {
4543 SDValue Mask;
4544 SDValue Index;
4545 SDValue Scale;
4546 SDValue Data;
4547 } Ops = [&]() -> Operands {
4548 if (auto *MSC = dyn_cast<MaskedScatterSDNode>(N)) {
4549 return {MSC->getMask(), MSC->getIndex(), MSC->getScale(),
4550 MSC->getValue()};
4551 }
4552 auto *VPSC = cast<VPScatterSDNode>(N);
4553 return {VPSC->getMask(), VPSC->getIndex(), VPSC->getScale(),
4554 VPSC->getValue()};
4555 }();
4556 // Split all operands
4557
4558 EVT LoMemVT, HiMemVT;
4559 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
4560
4561 SDValue DataLo, DataHi;
4562 if (getTypeAction(Ops.Data.getValueType()) == TargetLowering::TypeSplitVector)
4563 // Split Data operand
4564 GetSplitVector(Ops.Data, DataLo, DataHi);
4565 else
4566 std::tie(DataLo, DataHi) = DAG.SplitVector(Ops.Data, DL);
4567
4568 // Split Mask operand
4569 SDValue MaskLo, MaskHi;
4570 if (OpNo == 1 && Ops.Mask.getOpcode() == ISD::SETCC) {
4571 SplitVecRes_SETCC(Ops.Mask.getNode(), MaskLo, MaskHi);
4572 } else {
4573 std::tie(MaskLo, MaskHi) = SplitMask(Ops.Mask, DL);
4574 }
4575
4576 SDValue IndexHi, IndexLo;
4577 if (getTypeAction(Ops.Index.getValueType()) ==
4579 GetSplitVector(Ops.Index, IndexLo, IndexHi);
4580 else
4581 std::tie(IndexLo, IndexHi) = DAG.SplitVector(Ops.Index, DL);
4582
4583 SDValue Lo;
4584 MachineMemOperand::Flags MMOFlags = N->getMemOperand()->getFlags();
4585 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
4586 N->getPointerInfo(), MMOFlags, LocationSize::beforeOrAfterPointer(),
4587 Alignment, N->getAAInfo(), N->getRanges());
4588
4589 if (auto *MSC = dyn_cast<MaskedScatterSDNode>(N)) {
4590 SDValue OpsLo[] = {Ch, DataLo, MaskLo, Ptr, IndexLo, Ops.Scale};
4591 Lo =
4592 DAG.getMaskedScatter(DAG.getVTList(MVT::Other), LoMemVT, DL, OpsLo, MMO,
4593 MSC->getIndexType(), MSC->isTruncatingStore());
4594
4595 // The order of the Scatter operation after split is well defined. The "Hi"
4596 // part comes after the "Lo". So these two operations should be chained one
4597 // after another.
4598 SDValue OpsHi[] = {Lo, DataHi, MaskHi, Ptr, IndexHi, Ops.Scale};
4599 return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), HiMemVT, DL, OpsHi,
4600 MMO, MSC->getIndexType(),
4601 MSC->isTruncatingStore());
4602 }
4603 auto *VPSC = cast<VPScatterSDNode>(N);
4604 SDValue EVLLo, EVLHi;
4605 std::tie(EVLLo, EVLHi) =
4606 DAG.SplitEVL(VPSC->getVectorLength(), Ops.Data.getValueType(), DL);
4607
4608 SDValue OpsLo[] = {Ch, DataLo, Ptr, IndexLo, Ops.Scale, MaskLo, EVLLo};
4609 Lo = DAG.getScatterVP(DAG.getVTList(MVT::Other), LoMemVT, DL, OpsLo, MMO,
4610 VPSC->getIndexType());
4611
4612 // The order of the Scatter operation after split is well defined. The "Hi"
4613 // part comes after the "Lo". So these two operations should be chained one
4614 // after another.
4615 SDValue OpsHi[] = {Lo, DataHi, Ptr, IndexHi, Ops.Scale, MaskHi, EVLHi};
4616 return DAG.getScatterVP(DAG.getVTList(MVT::Other), HiMemVT, DL, OpsHi, MMO,
4617 VPSC->getIndexType());
4618}
4619
4620SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) {
4621 assert(N->isUnindexed() && "Indexed store of vector?");
4622 assert(OpNo == 1 && "Can only split the stored value");
4623 SDLoc DL(N);
4624
4625 bool isTruncating = N->isTruncatingStore();
4626 SDValue Ch = N->getChain();
4627 SDValue Ptr = N->getBasePtr();
4628 EVT MemoryVT = N->getMemoryVT();
4629 Align Alignment = N->getBaseAlign();
4630 MachineMemOperand::Flags MMOFlags = N->getMemOperand()->getFlags();
4631 AAMDNodes AAInfo = N->getAAInfo();
4632 SDValue Lo, Hi;
4633 GetSplitVector(N->getOperand(1), Lo, Hi);
4634
4635 EVT LoMemVT, HiMemVT;
4636 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
4637
4638 // Scalarize if the split halves are not byte-sized.
4639 if (!LoMemVT.isByteSized() || !HiMemVT.isByteSized())
4640 return TLI.scalarizeVectorStore(N, DAG);
4641
4642 if (isTruncating)
4643 Lo = DAG.getTruncStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), LoMemVT,
4644 Alignment, MMOFlags, AAInfo);
4645 else
4646 Lo = DAG.getStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), Alignment, MMOFlags,
4647 AAInfo);
4648
4649 MachinePointerInfo MPI;
4650 IncrementPointer(N, LoMemVT, MPI, Ptr);
4651
4652 if (isTruncating)
4653 Hi = DAG.getTruncStore(Ch, DL, Hi, Ptr, MPI,
4654 HiMemVT, Alignment, MMOFlags, AAInfo);
4655 else
4656 Hi = DAG.getStore(Ch, DL, Hi, Ptr, MPI, Alignment, MMOFlags, AAInfo);
4657
4658 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4659}
4660
4661SDValue DAGTypeLegalizer::SplitVecOp_CONCAT_VECTORS(SDNode *N) {
4662 SDLoc DL(N);
4663
4664 // The input operands all must have the same type, and we know the result
4665 // type is valid. Convert this to a buildvector which extracts all the
4666 // input elements.
4667 // TODO: If the input elements are power-two vectors, we could convert this to
4668 // a new CONCAT_VECTORS node with elements that are half-wide.
4670 EVT EltVT = N->getValueType(0).getVectorElementType();
4671 for (const SDValue &Op : N->op_values()) {
4672 for (unsigned i = 0, e = Op.getValueType().getVectorNumElements();
4673 i != e; ++i) {
4674 Elts.push_back(DAG.getExtractVectorElt(DL, EltVT, Op, i));
4675 }
4676 }
4677
4678 return DAG.getBuildVector(N->getValueType(0), DL, Elts);
4679}
4680
4681SDValue DAGTypeLegalizer::SplitVecOp_TruncateHelper(SDNode *N) {
4682 // The result type is legal, but the input type is illegal. If splitting
4683 // ends up with the result type of each half still being legal, just
4684 // do that. If, however, that would result in an illegal result type,
4685 // we can try to get more clever with power-two vectors. Specifically,
4686 // split the input type, but also widen the result element size, then
4687 // concatenate the halves and truncate again. For example, consider a target
4688 // where v8i8 is legal and v8i32 is not (ARM, which doesn't have 256-bit
4689 // vectors). To perform a "%res = v8i8 trunc v8i32 %in" we do:
4690 // %inlo = v4i32 extract_subvector %in, 0
4691 // %inhi = v4i32 extract_subvector %in, 4
4692 // %lo16 = v4i16 trunc v4i32 %inlo
4693 // %hi16 = v4i16 trunc v4i32 %inhi
4694 // %in16 = v8i16 concat_vectors v4i16 %lo16, v4i16 %hi16
4695 // %res = v8i8 trunc v8i16 %in16
4696 //
4697 // Without this transform, the original truncate would end up being
4698 // scalarized, which is pretty much always a last resort.
4699 unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
4700 SDValue InVec = N->getOperand(OpNo);
4701 EVT InVT = InVec->getValueType(0);
4702 EVT OutVT = N->getValueType(0);
4703 ElementCount NumElements = OutVT.getVectorElementCount();
4704 bool IsFloat = OutVT.isFloatingPoint();
4705
4706 unsigned InElementSize = InVT.getScalarSizeInBits();
4707 unsigned OutElementSize = OutVT.getScalarSizeInBits();
4708
4709 // Determine the split output VT. If its legal we can just split dirctly.
4710 EVT LoOutVT, HiOutVT;
4711 std::tie(LoOutVT, HiOutVT) = DAG.GetSplitDestVTs(OutVT);
4712 assert(LoOutVT == HiOutVT && "Unequal split?");
4713
4714 // If the input elements are only 1/2 the width of the result elements,
4715 // just use the normal splitting. Our trick only work if there's room
4716 // to split more than once.
4717 if (isTypeLegal(LoOutVT) || InElementSize <= OutElementSize * 2 ||
4718 (IsFloat && !isPowerOf2_32(InElementSize)))
4719 return SplitVecOp_UnaryOp(N);
4720 SDLoc DL(N);
4721
4722 // Don't touch if this will be scalarized.
4723 EVT FinalVT = InVT;
4724 while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
4725 FinalVT = FinalVT.getHalfNumVectorElementsVT(*DAG.getContext());
4726
4727 if (getTypeAction(FinalVT) == TargetLowering::TypeScalarizeVector)
4728 return SplitVecOp_UnaryOp(N);
4729
4730 // Get the split input vector.
4731 SDValue InLoVec, InHiVec;
4732 GetSplitVector(InVec, InLoVec, InHiVec);
4733
4734 // Truncate them to 1/2 the element size.
4735 //
4736 // This assumes the number of elements is a power of two; any vector that
4737 // isn't should be widened, not split.
4738 EVT HalfElementVT = IsFloat ?
4739 EVT::getFloatingPointVT(InElementSize/2) :
4740 EVT::getIntegerVT(*DAG.getContext(), InElementSize/2);
4741 EVT HalfVT = EVT::getVectorVT(*DAG.getContext(), HalfElementVT,
4742 NumElements.divideCoefficientBy(2));
4743
4744 SDValue HalfLo;
4745 SDValue HalfHi;
4746 SDValue Chain;
4747 if (N->isStrictFPOpcode()) {
4748 HalfLo = DAG.getNode(N->getOpcode(), DL, {HalfVT, MVT::Other},
4749 {N->getOperand(0), InLoVec});
4750 HalfHi = DAG.getNode(N->getOpcode(), DL, {HalfVT, MVT::Other},
4751 {N->getOperand(0), InHiVec});
4752 // Legalize the chain result - switch anything that used the old chain to
4753 // use the new one.
4754 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, HalfLo.getValue(1),
4755 HalfHi.getValue(1));
4756 } else {
4757 HalfLo = DAG.getNode(N->getOpcode(), DL, HalfVT, InLoVec);
4758 HalfHi = DAG.getNode(N->getOpcode(), DL, HalfVT, InHiVec);
4759 }
4760
4761 // Concatenate them to get the full intermediate truncation result.
4762 EVT InterVT = EVT::getVectorVT(*DAG.getContext(), HalfElementVT, NumElements);
4763 SDValue InterVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InterVT, HalfLo,
4764 HalfHi);
4765 // Now finish up by truncating all the way down to the original result
4766 // type. This should normally be something that ends up being legal directly,
4767 // but in theory if a target has very wide vectors and an annoyingly
4768 // restricted set of legal types, this split can chain to build things up.
4769
4770 if (N->isStrictFPOpcode()) {
4771 SDValue Res = DAG.getNode(
4772 ISD::STRICT_FP_ROUND, DL, {OutVT, MVT::Other},
4773 {Chain, InterVec,
4774 DAG.getTargetConstant(0, DL, TLI.getPointerTy(DAG.getDataLayout()))});
4775 // Relink the chain
4776 ReplaceValueWith(SDValue(N, 1), SDValue(Res.getNode(), 1));
4777 return Res;
4778 }
4779
4780 return IsFloat
4781 ? DAG.getNode(ISD::FP_ROUND, DL, OutVT, InterVec,
4782 DAG.getTargetConstant(
4783 0, DL, TLI.getPointerTy(DAG.getDataLayout())))
4784 : DAG.getNode(ISD::TRUNCATE, DL, OutVT, InterVec);
4785}
4786
4787SDValue DAGTypeLegalizer::SplitVecOp_VSETCC(SDNode *N) {
4788 unsigned Opc = N->getOpcode();
4789 bool isStrict = Opc == ISD::STRICT_FSETCC || Opc == ISD::STRICT_FSETCCS;
4790 assert(N->getValueType(0).isVector() &&
4791 N->getOperand(isStrict ? 1 : 0).getValueType().isVector() &&
4792 "Operand types must be vectors");
4793 // The result has a legal vector type, but the input needs splitting.
4794 SDValue Lo0, Hi0, Lo1, Hi1, LoRes, HiRes;
4795 SDLoc DL(N);
4796 GetSplitVector(N->getOperand(isStrict ? 1 : 0), Lo0, Hi0);
4797 GetSplitVector(N->getOperand(isStrict ? 2 : 1), Lo1, Hi1);
4798
4799 EVT VT = N->getValueType(0);
4800 EVT PartResVT = getSetCCResultType(Lo0.getValueType());
4801
4802 if (Opc == ISD::SETCC) {
4803 LoRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Lo0, Lo1, N->getOperand(2));
4804 HiRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Hi0, Hi1, N->getOperand(2));
4805 } else if (isStrict) {
4806 LoRes = DAG.getNode(Opc, DL, DAG.getVTList(PartResVT, N->getValueType(1)),
4807 N->getOperand(0), Lo0, Lo1, N->getOperand(3));
4808 HiRes = DAG.getNode(Opc, DL, DAG.getVTList(PartResVT, N->getValueType(1)),
4809 N->getOperand(0), Hi0, Hi1, N->getOperand(3));
4810 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
4811 LoRes.getValue(1), HiRes.getValue(1));
4812 ReplaceValueWith(SDValue(N, 1), NewChain);
4813 } else {
4814 assert(Opc == ISD::VP_SETCC && "Expected VP_SETCC opcode");
4815 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
4816 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(3));
4817 std::tie(EVLLo, EVLHi) =
4818 DAG.SplitEVL(N->getOperand(4), N->getValueType(0), DL);
4819 LoRes = DAG.getNode(ISD::VP_SETCC, DL, PartResVT, Lo0, Lo1,
4820 N->getOperand(2), MaskLo, EVLLo);
4821 HiRes = DAG.getNode(ISD::VP_SETCC, DL, PartResVT, Hi0, Hi1,
4822 N->getOperand(2), MaskHi, EVLHi);
4823 }
4824
4825 EVT ConcatVT = PartResVT.getDoubleNumVectorElementsVT(*DAG.getContext());
4826 SDValue Con = DAG.getNode(ISD::CONCAT_VECTORS, DL, ConcatVT, LoRes, HiRes);
4827 if (VT == ConcatVT)
4828 return Con;
4829
4830 EVT OpVT = N->getOperand(0).getValueType();
4831 ISD::NodeType ExtendCode =
4832 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
4833 return DAG.getExtOrTrunc(Con, DL, VT, ExtendCode);
4834}
4835
4836
4837SDValue DAGTypeLegalizer::SplitVecOp_FP_ROUND(SDNode *N) {
4838 // The result has a legal vector type, but the input needs splitting.
4839 EVT ResVT = N->getValueType(0);
4840 SDValue Lo, Hi;
4841 SDLoc DL(N);
4842 GetSplitVector(N->getOperand(N->isStrictFPOpcode() ? 1 : 0), Lo, Hi);
4843 EVT InVT = Lo.getValueType();
4844
4845 EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
4846 InVT.getVectorElementCount());
4847
4848 if (N->isStrictFPOpcode()) {
4849 Lo = DAG.getNode(N->getOpcode(), DL, {OutVT, MVT::Other},
4850 {N->getOperand(0), Lo, N->getOperand(2)});
4851 Hi = DAG.getNode(N->getOpcode(), DL, {OutVT, MVT::Other},
4852 {N->getOperand(0), Hi, N->getOperand(2)});
4853 // Legalize the chain result - switch anything that used the old chain to
4854 // use the new one.
4855 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
4856 Lo.getValue(1), Hi.getValue(1));
4857 ReplaceValueWith(SDValue(N, 1), NewChain);
4858 } else if (N->getOpcode() == ISD::VP_FP_ROUND) {
4859 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
4860 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
4861 std::tie(EVLLo, EVLHi) =
4862 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), DL);
4863 Lo = DAG.getNode(ISD::VP_FP_ROUND, DL, OutVT, Lo, MaskLo, EVLLo);
4864 Hi = DAG.getNode(ISD::VP_FP_ROUND, DL, OutVT, Hi, MaskHi, EVLHi);
4865 } else {
4866 Lo = DAG.getNode(N->getOpcode(), DL, OutVT, Lo, N->getOperand(1));
4867 Hi = DAG.getNode(N->getOpcode(), DL, OutVT, Hi, N->getOperand(1));
4868 }
4869
4870 return DAG.getNode(ISD::CONCAT_VECTORS, DL, ResVT, Lo, Hi);
4871}
4872
4873// Split a vector type in an FP binary operation where the second operand has a
4874// different type from the first.
4875//
4876// The result (and the first input) has a legal vector type, but the second
4877// input needs splitting.
4878SDValue DAGTypeLegalizer::SplitVecOp_FPOpDifferentTypes(SDNode *N) {
4879 SDLoc DL(N);
4880
4881 EVT LHSLoVT, LHSHiVT;
4882 std::tie(LHSLoVT, LHSHiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
4883
4884 if (!isTypeLegal(LHSLoVT) || !isTypeLegal(LHSHiVT))
4885 return DAG.UnrollVectorOp(N, N->getValueType(0).getVectorNumElements());
4886
4887 SDValue LHSLo, LHSHi;
4888 std::tie(LHSLo, LHSHi) =
4889 DAG.SplitVector(N->getOperand(0), DL, LHSLoVT, LHSHiVT);
4890
4891 SDValue RHSLo, RHSHi;
4892 std::tie(RHSLo, RHSHi) = DAG.SplitVector(N->getOperand(1), DL);
4893
4894 SDValue Lo = DAG.getNode(N->getOpcode(), DL, LHSLoVT, LHSLo, RHSLo);
4895 SDValue Hi = DAG.getNode(N->getOpcode(), DL, LHSHiVT, LHSHi, RHSHi);
4896
4897 return DAG.getNode(ISD::CONCAT_VECTORS, DL, N->getValueType(0), Lo, Hi);
4898}
4899
4900SDValue DAGTypeLegalizer::SplitVecOp_CMP(SDNode *N) {
4901 LLVMContext &Ctxt = *DAG.getContext();
4902 SDLoc dl(N);
4903
4904 SDValue LHSLo, LHSHi, RHSLo, RHSHi;
4905 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
4906 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
4907
4908 EVT ResVT = N->getValueType(0);
4909 ElementCount SplitOpEC = LHSLo.getValueType().getVectorElementCount();
4910 EVT NewResVT =
4911 EVT::getVectorVT(Ctxt, ResVT.getVectorElementType(), SplitOpEC);
4912
4913 SDValue Lo = DAG.getNode(N->getOpcode(), dl, NewResVT, LHSLo, RHSLo);
4914 SDValue Hi = DAG.getNode(N->getOpcode(), dl, NewResVT, LHSHi, RHSHi);
4915
4916 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
4917}
4918
4919SDValue DAGTypeLegalizer::SplitVecOp_FP_TO_XINT_SAT(SDNode *N) {
4920 EVT ResVT = N->getValueType(0);
4921 SDValue Lo, Hi;
4922 SDLoc dl(N);
4923 GetSplitVector(N->getOperand(0), Lo, Hi);
4924 EVT InVT = Lo.getValueType();
4925
4926 EVT NewResVT =
4927 EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
4928 InVT.getVectorElementCount());
4929
4930 Lo = DAG.getNode(N->getOpcode(), dl, NewResVT, Lo, N->getOperand(1));
4931 Hi = DAG.getNode(N->getOpcode(), dl, NewResVT, Hi, N->getOperand(1));
4932
4933 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
4934}
4935
4936SDValue DAGTypeLegalizer::SplitVecOp_CttzElts(SDNode *N) {
4937 SDLoc DL(N);
4938 EVT ResVT = N->getValueType(0);
4939
4940 SDValue Lo, Hi;
4941 SDValue VecOp = N->getOperand(0);
4942 GetSplitVector(VecOp, Lo, Hi);
4943
4944 // if CTTZ_ELTS(Lo) != VL => CTTZ_ELTS(Lo).
4945 // else => VL + (CTTZ_ELTS(Hi) or CTTZ_ELTS_ZERO_POISON(Hi)).
4946 SDValue ResLo = DAG.getNode(ISD::CTTZ_ELTS, DL, ResVT, Lo);
4947 SDValue VL =
4948 DAG.getElementCount(DL, ResVT, Lo.getValueType().getVectorElementCount());
4949 SDValue ResLoNotVL =
4950 DAG.getSetCC(DL, getSetCCResultType(ResVT), ResLo, VL, ISD::SETNE);
4951 SDValue ResHi = DAG.getNode(N->getOpcode(), DL, ResVT, Hi);
4952 return DAG.getSelect(DL, ResVT, ResLoNotVL, ResLo,
4953 DAG.getNode(ISD::ADD, DL, ResVT, VL, ResHi));
4954}
4955
4956SDValue DAGTypeLegalizer::SplitVecOp_VP_CttzElements(SDNode *N) {
4957 SDLoc DL(N);
4958 EVT ResVT = N->getValueType(0);
4959
4960 SDValue Lo, Hi;
4961 SDValue VecOp = N->getOperand(0);
4962 GetSplitVector(VecOp, Lo, Hi);
4963
4964 auto [MaskLo, MaskHi] = SplitMask(N->getOperand(1));
4965 auto [EVLLo, EVLHi] =
4966 DAG.SplitEVL(N->getOperand(2), VecOp.getValueType(), DL);
4967 SDValue VLo = DAG.getZExtOrTrunc(EVLLo, DL, ResVT);
4968
4969 // if VP_CTTZ_ELTS(Lo) != EVLLo => VP_CTTZ_ELTS(Lo).
4970 // else => EVLLo + (VP_CTTZ_ELTS(Hi) or VP_CTTZ_ELTS_ZERO_UNDEF(Hi)).
4971 SDValue ResLo = DAG.getNode(ISD::VP_CTTZ_ELTS, DL, ResVT, Lo, MaskLo, EVLLo);
4972 SDValue ResLoNotEVL =
4973 DAG.getSetCC(DL, getSetCCResultType(ResVT), ResLo, VLo, ISD::SETNE);
4974 SDValue ResHi = DAG.getNode(N->getOpcode(), DL, ResVT, Hi, MaskHi, EVLHi);
4975 return DAG.getSelect(DL, ResVT, ResLoNotEVL, ResLo,
4976 DAG.getNode(ISD::ADD, DL, ResVT, VLo, ResHi));
4977}
4978
4979SDValue DAGTypeLegalizer::SplitVecOp_VECTOR_HISTOGRAM(SDNode *N) {
4980 MaskedHistogramSDNode *HG = cast<MaskedHistogramSDNode>(N);
4981 SDLoc DL(HG);
4982 SDValue Inc = HG->getInc();
4983 SDValue Ptr = HG->getBasePtr();
4984 SDValue Scale = HG->getScale();
4985 SDValue IntID = HG->getIntID();
4986 EVT MemVT = HG->getMemoryVT();
4987 MachineMemOperand *MMO = HG->getMemOperand();
4988 ISD::MemIndexType IndexType = HG->getIndexType();
4989
4990 SDValue IndexLo, IndexHi, MaskLo, MaskHi;
4991 std::tie(IndexLo, IndexHi) = DAG.SplitVector(HG->getIndex(), DL);
4992 std::tie(MaskLo, MaskHi) = DAG.SplitVector(HG->getMask(), DL);
4993 SDValue OpsLo[] = {HG->getChain(), Inc, MaskLo, Ptr, IndexLo, Scale, IntID};
4994 SDValue Lo = DAG.getMaskedHistogram(DAG.getVTList(MVT::Other), MemVT, DL,
4995 OpsLo, MMO, IndexType);
4996 SDValue OpsHi[] = {Lo, Inc, MaskHi, Ptr, IndexHi, Scale, IntID};
4997 return DAG.getMaskedHistogram(DAG.getVTList(MVT::Other), MemVT, DL, OpsHi,
4998 MMO, IndexType);
4999}
5000
5001SDValue DAGTypeLegalizer::SplitVecOp_PARTIAL_REDUCE_MLA(SDNode *N) {
5002 SDValue Acc = N->getOperand(0);
5003 assert(getTypeAction(Acc.getValueType()) != TargetLowering::TypeSplitVector &&
5004 "Accumulator should already be a legal type, and shouldn't need "
5005 "further splitting");
5006
5007 SDLoc DL(N);
5008 SDValue Input1Lo, Input1Hi, Input2Lo, Input2Hi;
5009 GetSplitVector(N->getOperand(1), Input1Lo, Input1Hi);
5010 GetSplitVector(N->getOperand(2), Input2Lo, Input2Hi);
5011 unsigned Opcode = N->getOpcode();
5012 EVT ResultVT = Acc.getValueType();
5013
5014 SDValue Lo = DAG.getNode(Opcode, DL, ResultVT, Acc, Input1Lo, Input2Lo);
5015 return DAG.getNode(Opcode, DL, ResultVT, Lo, Input1Hi, Input2Hi);
5016}
5017
5018//===----------------------------------------------------------------------===//
5019// Result Vector Widening
5020//===----------------------------------------------------------------------===//
5021
5022void DAGTypeLegalizer::ReplaceOtherWidenResults(SDNode *N, SDNode *WidenNode,
5023 unsigned WidenResNo) {
5024 unsigned NumResults = N->getNumValues();
5025 for (unsigned ResNo = 0; ResNo < NumResults; ResNo++) {
5026 if (ResNo == WidenResNo)
5027 continue;
5028 EVT ResVT = N->getValueType(ResNo);
5029 if (getTypeAction(ResVT) == TargetLowering::TypeWidenVector) {
5030 SetWidenedVector(SDValue(N, ResNo), SDValue(WidenNode, ResNo));
5031 } else {
5032 SDLoc DL(N);
5033 SDValue ResVal =
5034 DAG.getExtractSubvector(DL, ResVT, SDValue(WidenNode, ResNo), 0);
5035 ReplaceValueWith(SDValue(N, ResNo), ResVal);
5036 }
5037 }
5038}
5039
5040void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
5041 LLVM_DEBUG(dbgs() << "Widen node result " << ResNo << ": "; N->dump(&DAG));
5042
5043 // See if the target wants to custom widen this node.
5044 if (CustomWidenLowerNode(N, N->getValueType(ResNo)))
5045 return;
5046
5047 SDValue Res = SDValue();
5048
5049 auto unrollExpandedOp = [&]() {
5050 // We're going to widen this vector op to a legal type by padding with undef
5051 // elements. If the wide vector op is eventually going to be expanded to
5052 // scalar libcalls, then unroll into scalar ops now to avoid unnecessary
5053 // libcalls on the undef elements.
5054 EVT VT = N->getValueType(0);
5055 EVT WideVecVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
5056 if (!TLI.isOperationLegalOrCustomOrPromote(N->getOpcode(), WideVecVT) &&
5057 TLI.isOperationExpandOrLibCall(N->getOpcode(), VT.getScalarType())) {
5058 Res = DAG.UnrollVectorOp(N, WideVecVT.getVectorNumElements());
5059 if (N->getNumValues() > 1)
5060 ReplaceOtherWidenResults(N, Res.getNode(), ResNo);
5061 return true;
5062 }
5063 return false;
5064 };
5065
5066 switch (N->getOpcode()) {
5067 default:
5068#ifndef NDEBUG
5069 dbgs() << "WidenVectorResult #" << ResNo << ": ";
5070 N->dump(&DAG);
5071 dbgs() << "\n";
5072#endif
5073 report_fatal_error("Do not know how to widen the result of this operator!");
5074
5077 Res = WidenVecRes_LOOP_DEPENDENCE_MASK(N);
5078 break;
5079 case ISD::MERGE_VALUES: Res = WidenVecRes_MERGE_VALUES(N, ResNo); break;
5080 case ISD::ADDRSPACECAST:
5081 Res = WidenVecRes_ADDRSPACECAST(N);
5082 break;
5083 case ISD::AssertZext: Res = WidenVecRes_AssertZext(N); break;
5084 case ISD::BITCAST: Res = WidenVecRes_BITCAST(N); break;
5085 case ISD::BUILD_VECTOR: Res = WidenVecRes_BUILD_VECTOR(N); break;
5086 case ISD::CONCAT_VECTORS: Res = WidenVecRes_CONCAT_VECTORS(N); break;
5088 Res = WidenVecRes_INSERT_SUBVECTOR(N);
5089 break;
5090 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecRes_EXTRACT_SUBVECTOR(N); break;
5091 case ISD::INSERT_VECTOR_ELT: Res = WidenVecRes_INSERT_VECTOR_ELT(N); break;
5092 case ISD::ATOMIC_LOAD:
5093 Res = WidenVecRes_ATOMIC_LOAD(cast<AtomicSDNode>(N));
5094 break;
5095 case ISD::LOAD: Res = WidenVecRes_LOAD(N); break;
5096 case ISD::STEP_VECTOR:
5097 case ISD::SPLAT_VECTOR:
5099 Res = WidenVecRes_ScalarOp(N);
5100 break;
5101 case ISD::SIGN_EXTEND_INREG: Res = WidenVecRes_InregOp(N); break;
5102 case ISD::VSELECT:
5103 case ISD::SELECT:
5104 case ISD::VP_SELECT:
5105 case ISD::VP_MERGE:
5106 Res = WidenVecRes_Select(N);
5107 break;
5108 case ISD::SELECT_CC: Res = WidenVecRes_SELECT_CC(N); break;
5109 case ISD::VP_SETCC:
5110 case ISD::SETCC: Res = WidenVecRes_SETCC(N); break;
5111 case ISD::POISON:
5112 case ISD::UNDEF: Res = WidenVecRes_UNDEF(N); break;
5114 Res = WidenVecRes_VECTOR_SHUFFLE(cast<ShuffleVectorSDNode>(N));
5115 break;
5116 case ISD::VP_LOAD:
5117 Res = WidenVecRes_VP_LOAD(cast<VPLoadSDNode>(N));
5118 break;
5119 case ISD::VP_LOAD_FF:
5120 Res = WidenVecRes_VP_LOAD_FF(cast<VPLoadFFSDNode>(N));
5121 break;
5122 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
5123 Res = WidenVecRes_VP_STRIDED_LOAD(cast<VPStridedLoadSDNode>(N));
5124 break;
5126 Res = WidenVecRes_VECTOR_COMPRESS(N);
5127 break;
5128 case ISD::MLOAD:
5129 Res = WidenVecRes_MLOAD(cast<MaskedLoadSDNode>(N));
5130 break;
5131 case ISD::MGATHER:
5132 Res = WidenVecRes_MGATHER(cast<MaskedGatherSDNode>(N));
5133 break;
5134 case ISD::VP_GATHER:
5135 Res = WidenVecRes_VP_GATHER(cast<VPGatherSDNode>(N));
5136 break;
5138 Res = WidenVecRes_VECTOR_REVERSE(N);
5139 break;
5141 Res = WidenVecRes_GET_ACTIVE_LANE_MASK(N);
5142 break;
5143
5144 case ISD::ADD: case ISD::VP_ADD:
5145 case ISD::AND: case ISD::VP_AND:
5146 case ISD::MUL: case ISD::VP_MUL:
5147 case ISD::MULHS:
5148 case ISD::MULHU:
5149 case ISD::ABDS:
5150 case ISD::ABDU:
5151 case ISD::OR: case ISD::VP_OR:
5152 case ISD::SUB: case ISD::VP_SUB:
5153 case ISD::XOR: case ISD::VP_XOR:
5154 case ISD::SHL: case ISD::VP_SHL:
5155 case ISD::SRA: case ISD::VP_SRA:
5156 case ISD::SRL: case ISD::VP_SRL:
5157 case ISD::CLMUL:
5158 case ISD::CLMULR:
5159 case ISD::CLMULH:
5160 case ISD::FMINNUM:
5161 case ISD::FMINNUM_IEEE:
5162 case ISD::VP_FMINNUM:
5163 case ISD::FMAXNUM:
5164 case ISD::FMAXNUM_IEEE:
5165 case ISD::VP_FMAXNUM:
5166 case ISD::FMINIMUM:
5167 case ISD::VP_FMINIMUM:
5168 case ISD::FMAXIMUM:
5169 case ISD::VP_FMAXIMUM:
5170 case ISD::FMINIMUMNUM:
5171 case ISD::FMAXIMUMNUM:
5172 case ISD::SMIN: case ISD::VP_SMIN:
5173 case ISD::SMAX: case ISD::VP_SMAX:
5174 case ISD::UMIN: case ISD::VP_UMIN:
5175 case ISD::UMAX: case ISD::VP_UMAX:
5176 case ISD::UADDSAT: case ISD::VP_UADDSAT:
5177 case ISD::SADDSAT: case ISD::VP_SADDSAT:
5178 case ISD::USUBSAT: case ISD::VP_USUBSAT:
5179 case ISD::SSUBSAT: case ISD::VP_SSUBSAT:
5180 case ISD::SSHLSAT:
5181 case ISD::USHLSAT:
5182 case ISD::ROTL:
5183 case ISD::ROTR:
5184 case ISD::AVGFLOORS:
5185 case ISD::AVGFLOORU:
5186 case ISD::AVGCEILS:
5187 case ISD::AVGCEILU:
5188 // Vector-predicated binary op widening. Note that -- unlike the
5189 // unpredicated versions -- we don't have to worry about trapping on
5190 // operations like UDIV, FADD, etc., as we pass on the original vector
5191 // length parameter. This means the widened elements containing garbage
5192 // aren't active.
5193 case ISD::VP_SDIV:
5194 case ISD::VP_UDIV:
5195 case ISD::VP_SREM:
5196 case ISD::VP_UREM:
5197 case ISD::VP_FADD:
5198 case ISD::VP_FSUB:
5199 case ISD::VP_FMUL:
5200 case ISD::VP_FDIV:
5201 case ISD::VP_FREM:
5202 case ISD::VP_FCOPYSIGN:
5203 Res = WidenVecRes_Binary(N);
5204 break;
5205
5206 case ISD::MASKED_UDIV:
5207 case ISD::MASKED_SDIV:
5208 case ISD::MASKED_UREM:
5209 case ISD::MASKED_SREM:
5210 Res = WidenVecRes_MaskedBinary(N);
5211 break;
5212
5213 case ISD::SCMP:
5214 case ISD::UCMP:
5215 Res = WidenVecRes_CMP(N);
5216 break;
5217
5218 case ISD::FPOW:
5219 case ISD::FATAN2:
5220 case ISD::FREM:
5221 if (unrollExpandedOp())
5222 break;
5223 // If the target has custom/legal support for the scalar FP intrinsic ops
5224 // (they are probably not destined to become libcalls), then widen those
5225 // like any other binary ops.
5226 [[fallthrough]];
5227
5228 case ISD::FADD:
5229 case ISD::FMUL:
5230 case ISD::FSUB:
5231 case ISD::FDIV:
5232 case ISD::SDIV:
5233 case ISD::UDIV:
5234 case ISD::SREM:
5235 case ISD::UREM:
5236 Res = WidenVecRes_BinaryCanTrap(N);
5237 break;
5238
5239 case ISD::SMULFIX:
5240 case ISD::SMULFIXSAT:
5241 case ISD::UMULFIX:
5242 case ISD::UMULFIXSAT:
5243 // These are binary operations, but with an extra operand that shouldn't
5244 // be widened (the scale).
5245 Res = WidenVecRes_BinaryWithExtraScalarOp(N);
5246 break;
5247
5248#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
5249 case ISD::STRICT_##DAGN:
5250#include "llvm/IR/ConstrainedOps.def"
5251 Res = WidenVecRes_StrictFP(N);
5252 break;
5253
5254 case ISD::UADDO:
5255 case ISD::SADDO:
5256 case ISD::USUBO:
5257 case ISD::SSUBO:
5258 case ISD::UMULO:
5259 case ISD::SMULO:
5260 Res = WidenVecRes_OverflowOp(N, ResNo);
5261 break;
5262
5263 case ISD::FCOPYSIGN:
5264 Res = WidenVecRes_FCOPYSIGN(N);
5265 break;
5266
5267 case ISD::IS_FPCLASS:
5268 case ISD::FPTRUNC_ROUND:
5269 Res = WidenVecRes_UnarySameEltsWithScalarArg(N);
5270 break;
5271
5272 case ISD::FLDEXP:
5273 case ISD::FPOWI:
5274 if (!unrollExpandedOp())
5275 Res = WidenVecRes_ExpOp(N);
5276 break;
5277
5281 Res = WidenVecRes_EXTEND_VECTOR_INREG(N);
5282 break;
5283
5284 case ISD::ANY_EXTEND:
5285 case ISD::FP_EXTEND:
5286 case ISD::VP_FP_EXTEND:
5287 case ISD::FP_ROUND:
5288 case ISD::VP_FP_ROUND:
5289 case ISD::FP_TO_SINT:
5290 case ISD::VP_FP_TO_SINT:
5291 case ISD::FP_TO_UINT:
5292 case ISD::VP_FP_TO_UINT:
5293 case ISD::SIGN_EXTEND:
5294 case ISD::VP_SIGN_EXTEND:
5295 case ISD::SINT_TO_FP:
5296 case ISD::VP_SINT_TO_FP:
5297 case ISD::VP_TRUNCATE:
5298 case ISD::TRUNCATE:
5299 case ISD::UINT_TO_FP:
5300 case ISD::VP_UINT_TO_FP:
5301 case ISD::ZERO_EXTEND:
5302 case ISD::VP_ZERO_EXTEND:
5304 Res = WidenVecRes_Convert(N);
5305 break;
5306
5309 Res = WidenVecRes_FP_TO_XINT_SAT(N);
5310 break;
5311
5312 case ISD::LRINT:
5313 case ISD::LLRINT:
5314 case ISD::VP_LRINT:
5315 case ISD::VP_LLRINT:
5316 case ISD::LROUND:
5317 case ISD::LLROUND:
5318 Res = WidenVecRes_XROUND(N);
5319 break;
5320
5321 case ISD::FACOS:
5322 case ISD::FASIN:
5323 case ISD::FATAN:
5324 case ISD::FCEIL:
5325 case ISD::FCOS:
5326 case ISD::FCOSH:
5327 case ISD::FEXP:
5328 case ISD::FEXP2:
5329 case ISD::FEXP10:
5330 case ISD::FFLOOR:
5331 case ISD::FLOG:
5332 case ISD::FLOG10:
5333 case ISD::FLOG2:
5334 case ISD::FNEARBYINT:
5335 case ISD::FRINT:
5336 case ISD::FROUND:
5337 case ISD::FROUNDEVEN:
5338 case ISD::FSIN:
5339 case ISD::FSINH:
5340 case ISD::FSQRT:
5341 case ISD::FTAN:
5342 case ISD::FTANH:
5343 case ISD::FTRUNC:
5344 if (unrollExpandedOp())
5345 break;
5346 // If the target has custom/legal support for the scalar FP intrinsic ops
5347 // (they are probably not destined to become libcalls), then widen those
5348 // like any other unary ops.
5349 [[fallthrough]];
5350
5351 case ISD::ABS:
5352 case ISD::VP_ABS:
5353 case ISD::BITREVERSE:
5354 case ISD::VP_BITREVERSE:
5355 case ISD::BSWAP:
5356 case ISD::VP_BSWAP:
5357 case ISD::CTLZ:
5358 case ISD::VP_CTLZ:
5360 case ISD::VP_CTLZ_ZERO_UNDEF:
5361 case ISD::CTPOP:
5362 case ISD::VP_CTPOP:
5363 case ISD::CTTZ:
5364 case ISD::VP_CTTZ:
5366 case ISD::VP_CTTZ_ZERO_UNDEF:
5367 case ISD::FNEG: case ISD::VP_FNEG:
5368 case ISD::FABS: case ISD::VP_FABS:
5369 case ISD::VP_SQRT:
5370 case ISD::VP_FCEIL:
5371 case ISD::VP_FFLOOR:
5372 case ISD::VP_FRINT:
5373 case ISD::VP_FNEARBYINT:
5374 case ISD::VP_FROUND:
5375 case ISD::VP_FROUNDEVEN:
5376 case ISD::VP_FROUNDTOZERO:
5377 case ISD::FREEZE:
5378 case ISD::ARITH_FENCE:
5379 case ISD::FCANONICALIZE:
5381 Res = WidenVecRes_Unary(N);
5382 break;
5383 case ISD::FMA: case ISD::VP_FMA:
5384 case ISD::FSHL:
5385 case ISD::VP_FSHL:
5386 case ISD::FSHR:
5387 case ISD::VP_FSHR:
5388 Res = WidenVecRes_Ternary(N);
5389 break;
5390 case ISD::FMODF:
5391 case ISD::FFREXP:
5392 case ISD::FSINCOS:
5393 case ISD::FSINCOSPI: {
5394 if (!unrollExpandedOp())
5395 Res = WidenVecRes_UnaryOpWithTwoResults(N, ResNo);
5396 break;
5397 }
5398 }
5399
5400 // If Res is null, the sub-method took care of registering the result.
5401 if (Res.getNode())
5402 SetWidenedVector(SDValue(N, ResNo), Res);
5403}
5404
5405SDValue DAGTypeLegalizer::WidenVecRes_Ternary(SDNode *N) {
5406 // Ternary op widening.
5407 SDLoc dl(N);
5408 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5409 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5410 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5411 SDValue InOp3 = GetWidenedVector(N->getOperand(2));
5412 if (N->getNumOperands() == 3)
5413 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3);
5414
5415 assert(N->getNumOperands() == 5 && "Unexpected number of operands!");
5416 assert(N->isVPOpcode() && "Expected VP opcode");
5417
5418 SDValue Mask =
5419 GetWidenedMask(N->getOperand(3), WidenVT.getVectorElementCount());
5420 return DAG.getNode(N->getOpcode(), dl, WidenVT,
5421 {InOp1, InOp2, InOp3, Mask, N->getOperand(4)});
5422}
5423
5424SDValue DAGTypeLegalizer::WidenVecRes_Binary(SDNode *N) {
5425 // Binary op widening.
5426 SDLoc dl(N);
5427 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5428 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5429 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5430 if (N->getNumOperands() == 2)
5431 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2,
5432 N->getFlags());
5433
5434 assert(N->getNumOperands() == 4 && "Unexpected number of operands!");
5435 assert(N->isVPOpcode() && "Expected VP opcode");
5436
5437 SDValue Mask =
5438 GetWidenedMask(N->getOperand(2), WidenVT.getVectorElementCount());
5439 return DAG.getNode(N->getOpcode(), dl, WidenVT,
5440 {InOp1, InOp2, Mask, N->getOperand(3)}, N->getFlags());
5441}
5442
5443SDValue DAGTypeLegalizer::WidenVecRes_MaskedBinary(SDNode *N) {
5444 SDLoc dl(N);
5445 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5446 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5447 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5448 SDValue Mask = N->getOperand(2);
5449 EVT WideMaskVT = WidenVT.changeVectorElementType(
5450 *DAG.getContext(), Mask.getValueType().getVectorElementType());
5451 Mask = ModifyToType(Mask, WideMaskVT, /*FillWithZeros=*/true);
5452 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, Mask,
5453 N->getFlags());
5454}
5455
5456SDValue DAGTypeLegalizer::WidenVecRes_CMP(SDNode *N) {
5457 LLVMContext &Ctxt = *DAG.getContext();
5458 SDLoc dl(N);
5459
5460 SDValue LHS = N->getOperand(0);
5461 SDValue RHS = N->getOperand(1);
5462 EVT OpVT = LHS.getValueType();
5463 if (getTypeAction(OpVT) == TargetLowering::TypeWidenVector) {
5464 LHS = GetWidenedVector(LHS);
5465 RHS = GetWidenedVector(RHS);
5466 OpVT = LHS.getValueType();
5467 }
5468
5469 EVT WidenResVT = TLI.getTypeToTransformTo(Ctxt, N->getValueType(0));
5470 ElementCount WidenResEC = WidenResVT.getVectorElementCount();
5471 if (WidenResEC == OpVT.getVectorElementCount()) {
5472 return DAG.getNode(N->getOpcode(), dl, WidenResVT, LHS, RHS);
5473 }
5474
5475 return DAG.UnrollVectorOp(N, WidenResVT.getVectorNumElements());
5476}
5477
5478SDValue DAGTypeLegalizer::WidenVecRes_BinaryWithExtraScalarOp(SDNode *N) {
5479 // Binary op widening, but with an extra operand that shouldn't be widened.
5480 SDLoc dl(N);
5481 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5482 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5483 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5484 SDValue InOp3 = N->getOperand(2);
5485 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3,
5486 N->getFlags());
5487}
5488
5489// Given a vector of operations that have been broken up to widen, see
5490// if we can collect them together into the next widest legal VT. This
5491// implementation is trap-safe.
5493 SmallVectorImpl<SDValue> &ConcatOps,
5494 unsigned ConcatEnd, EVT VT, EVT MaxVT,
5495 EVT WidenVT) {
5496 // Check to see if we have a single operation with the widen type.
5497 if (ConcatEnd == 1) {
5498 VT = ConcatOps[0].getValueType();
5499 if (VT == WidenVT)
5500 return ConcatOps[0];
5501 }
5502
5503 SDLoc dl(ConcatOps[0]);
5504 EVT WidenEltVT = WidenVT.getVectorElementType();
5505
5506 // while (Some element of ConcatOps is not of type MaxVT) {
5507 // From the end of ConcatOps, collect elements of the same type and put
5508 // them into an op of the next larger supported type
5509 // }
5510 while (ConcatOps[ConcatEnd-1].getValueType() != MaxVT) {
5511 int Idx = ConcatEnd - 1;
5512 VT = ConcatOps[Idx--].getValueType();
5513 while (Idx >= 0 && ConcatOps[Idx].getValueType() == VT)
5514 Idx--;
5515
5516 int NextSize = VT.isVector() ? VT.getVectorNumElements() : 1;
5517 EVT NextVT;
5518 do {
5519 NextSize *= 2;
5520 NextVT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NextSize);
5521 } while (!TLI.isTypeLegal(NextVT));
5522
5523 if (!VT.isVector()) {
5524 // Scalar type, create an INSERT_VECTOR_ELEMENT of type NextVT
5525 SDValue VecOp = DAG.getPOISON(NextVT);
5526 unsigned NumToInsert = ConcatEnd - Idx - 1;
5527 for (unsigned i = 0, OpIdx = Idx + 1; i < NumToInsert; i++, OpIdx++)
5528 VecOp = DAG.getInsertVectorElt(dl, VecOp, ConcatOps[OpIdx], i);
5529 ConcatOps[Idx+1] = VecOp;
5530 ConcatEnd = Idx + 2;
5531 } else {
5532 // Vector type, create a CONCAT_VECTORS of type NextVT
5533 SDValue undefVec = DAG.getPOISON(VT);
5534 unsigned OpsToConcat = NextSize/VT.getVectorNumElements();
5535 SmallVector<SDValue, 16> SubConcatOps(OpsToConcat);
5536 unsigned RealVals = ConcatEnd - Idx - 1;
5537 unsigned SubConcatEnd = 0;
5538 unsigned SubConcatIdx = Idx + 1;
5539 while (SubConcatEnd < RealVals)
5540 SubConcatOps[SubConcatEnd++] = ConcatOps[++Idx];
5541 while (SubConcatEnd < OpsToConcat)
5542 SubConcatOps[SubConcatEnd++] = undefVec;
5543 ConcatOps[SubConcatIdx] = DAG.getNode(ISD::CONCAT_VECTORS, dl,
5544 NextVT, SubConcatOps);
5545 ConcatEnd = SubConcatIdx + 1;
5546 }
5547 }
5548
5549 // Check to see if we have a single operation with the widen type.
5550 if (ConcatEnd == 1) {
5551 VT = ConcatOps[0].getValueType();
5552 if (VT == WidenVT)
5553 return ConcatOps[0];
5554 }
5555
5556 // add undefs of size MaxVT until ConcatOps grows to length of WidenVT
5557 unsigned NumOps = WidenVT.getVectorNumElements()/MaxVT.getVectorNumElements();
5558 if (NumOps != ConcatEnd ) {
5559 SDValue UndefVal = DAG.getPOISON(MaxVT);
5560 for (unsigned j = ConcatEnd; j < NumOps; ++j)
5561 ConcatOps[j] = UndefVal;
5562 }
5563 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
5564 ArrayRef(ConcatOps.data(), NumOps));
5565}
5566
5567SDValue DAGTypeLegalizer::WidenVecRes_BinaryCanTrap(SDNode *N) {
5568 // Binary op widening for operations that can trap.
5569 unsigned Opcode = N->getOpcode();
5570 SDLoc dl(N);
5571 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5572 EVT WidenEltVT = WidenVT.getVectorElementType();
5573 EVT VT = WidenVT;
5574 unsigned NumElts = VT.getVectorMinNumElements();
5575 const SDNodeFlags Flags = N->getFlags();
5576 while (!TLI.isTypeLegal(VT) && NumElts != 1) {
5577 NumElts = NumElts / 2;
5578 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5579 }
5580
5581 if (NumElts != 1 && !TLI.canOpTrap(N->getOpcode(), VT)) {
5582 // Operation doesn't trap so just widen as normal.
5583 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5584 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5585 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, Flags);
5586 }
5587
5588 // Generate a vp.op if it is custom/legal for the target. This avoids need
5589 // to split and tile the subvectors (below), because the inactive lanes can
5590 // simply be disabled. To avoid possible recursion, only do this if the
5591 // widened mask type is legal.
5592 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opcode);
5593 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WidenVT)) {
5594 if (EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
5595 WidenVT.getVectorElementCount());
5596 TLI.isTypeLegal(WideMaskVT)) {
5597 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5598 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5599 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
5600 SDValue EVL =
5601 DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
5602 N->getValueType(0).getVectorElementCount());
5603 return DAG.getNode(*VPOpcode, dl, WidenVT, InOp1, InOp2, Mask, EVL,
5604 Flags);
5605 }
5606 }
5607
5608 // FIXME: Improve support for scalable vectors.
5609 assert(!VT.isScalableVector() && "Scalable vectors not handled yet.");
5610
5611 // No legal vector version so unroll the vector operation and then widen.
5612 if (NumElts == 1)
5613 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
5614
5615 // Since the operation can trap, apply operation on the original vector.
5616 EVT MaxVT = VT;
5617 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5618 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5619 unsigned CurNumElts = N->getValueType(0).getVectorNumElements();
5620
5621 SmallVector<SDValue, 16> ConcatOps(CurNumElts);
5622 unsigned ConcatEnd = 0; // Current ConcatOps index.
5623 int Idx = 0; // Current Idx into input vectors.
5624
5625 // NumElts := greatest legal vector size (at most WidenVT)
5626 // while (orig. vector has unhandled elements) {
5627 // take munches of size NumElts from the beginning and add to ConcatOps
5628 // NumElts := next smaller supported vector size or 1
5629 // }
5630 while (CurNumElts != 0) {
5631 while (CurNumElts >= NumElts) {
5632 SDValue EOp1 = DAG.getExtractSubvector(dl, VT, InOp1, Idx);
5633 SDValue EOp2 = DAG.getExtractSubvector(dl, VT, InOp2, Idx);
5634 ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, VT, EOp1, EOp2, Flags);
5635 Idx += NumElts;
5636 CurNumElts -= NumElts;
5637 }
5638 do {
5639 NumElts = NumElts / 2;
5640 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5641 } while (!TLI.isTypeLegal(VT) && NumElts != 1);
5642
5643 if (NumElts == 1) {
5644 for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
5645 SDValue EOp1 = DAG.getExtractVectorElt(dl, WidenEltVT, InOp1, Idx);
5646 SDValue EOp2 = DAG.getExtractVectorElt(dl, WidenEltVT, InOp2, Idx);
5647 ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, WidenEltVT,
5648 EOp1, EOp2, Flags);
5649 }
5650 CurNumElts = 0;
5651 }
5652 }
5653
5654 return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
5655}
5656
5657SDValue DAGTypeLegalizer::WidenVecRes_StrictFP(SDNode *N) {
5658 switch (N->getOpcode()) {
5659 case ISD::STRICT_FSETCC:
5661 return WidenVecRes_STRICT_FSETCC(N);
5668 return WidenVecRes_Convert_StrictFP(N);
5669 default:
5670 break;
5671 }
5672
5673 // StrictFP op widening for operations that can trap.
5674 unsigned NumOpers = N->getNumOperands();
5675 unsigned Opcode = N->getOpcode();
5676 SDLoc dl(N);
5677 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5678 EVT WidenEltVT = WidenVT.getVectorElementType();
5679 EVT VT = WidenVT;
5680 unsigned NumElts = VT.getVectorNumElements();
5681 while (!TLI.isTypeLegal(VT) && NumElts != 1) {
5682 NumElts = NumElts / 2;
5683 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5684 }
5685
5686 // No legal vector version so unroll the vector operation and then widen.
5687 if (NumElts == 1)
5688 return UnrollVectorOp_StrictFP(N, WidenVT.getVectorNumElements());
5689
5690 // Since the operation can trap, apply operation on the original vector.
5691 EVT MaxVT = VT;
5693 unsigned CurNumElts = N->getValueType(0).getVectorNumElements();
5694
5695 SmallVector<SDValue, 16> ConcatOps(CurNumElts);
5697 unsigned ConcatEnd = 0; // Current ConcatOps index.
5698 int Idx = 0; // Current Idx into input vectors.
5699
5700 // The Chain is the first operand.
5701 InOps.push_back(N->getOperand(0));
5702
5703 // Now process the remaining operands.
5704 for (unsigned i = 1; i < NumOpers; ++i) {
5705 SDValue Oper = N->getOperand(i);
5706
5707 EVT OpVT = Oper.getValueType();
5708 if (OpVT.isVector()) {
5709 if (getTypeAction(OpVT) == TargetLowering::TypeWidenVector)
5710 Oper = GetWidenedVector(Oper);
5711 else {
5712 EVT WideOpVT =
5713 EVT::getVectorVT(*DAG.getContext(), OpVT.getVectorElementType(),
5714 WidenVT.getVectorElementCount());
5715 Oper = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WideOpVT,
5716 DAG.getPOISON(WideOpVT), Oper,
5717 DAG.getVectorIdxConstant(0, dl));
5718 }
5719 }
5720
5721 InOps.push_back(Oper);
5722 }
5723
5724 // NumElts := greatest legal vector size (at most WidenVT)
5725 // while (orig. vector has unhandled elements) {
5726 // take munches of size NumElts from the beginning and add to ConcatOps
5727 // NumElts := next smaller supported vector size or 1
5728 // }
5729 while (CurNumElts != 0) {
5730 while (CurNumElts >= NumElts) {
5732
5733 for (unsigned i = 0; i < NumOpers; ++i) {
5734 SDValue Op = InOps[i];
5735
5736 EVT OpVT = Op.getValueType();
5737 if (OpVT.isVector()) {
5738 EVT OpExtractVT =
5739 EVT::getVectorVT(*DAG.getContext(), OpVT.getVectorElementType(),
5741 Op = DAG.getExtractSubvector(dl, OpExtractVT, Op, Idx);
5742 }
5743
5744 EOps.push_back(Op);
5745 }
5746
5747 EVT OperVT[] = {VT, MVT::Other};
5748 SDValue Oper = DAG.getNode(Opcode, dl, OperVT, EOps);
5749 ConcatOps[ConcatEnd++] = Oper;
5750 Chains.push_back(Oper.getValue(1));
5751 Idx += NumElts;
5752 CurNumElts -= NumElts;
5753 }
5754 do {
5755 NumElts = NumElts / 2;
5756 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5757 } while (!TLI.isTypeLegal(VT) && NumElts != 1);
5758
5759 if (NumElts == 1) {
5760 for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
5762
5763 for (unsigned i = 0; i < NumOpers; ++i) {
5764 SDValue Op = InOps[i];
5765
5766 EVT OpVT = Op.getValueType();
5767 if (OpVT.isVector())
5768 Op = DAG.getExtractVectorElt(dl, OpVT.getVectorElementType(), Op,
5769 Idx);
5770
5771 EOps.push_back(Op);
5772 }
5773
5774 EVT WidenVT[] = {WidenEltVT, MVT::Other};
5775 SDValue Oper = DAG.getNode(Opcode, dl, WidenVT, EOps);
5776 ConcatOps[ConcatEnd++] = Oper;
5777 Chains.push_back(Oper.getValue(1));
5778 }
5779 CurNumElts = 0;
5780 }
5781 }
5782
5783 // Build a factor node to remember all the Ops that have been created.
5784 SDValue NewChain;
5785 if (Chains.size() == 1)
5786 NewChain = Chains[0];
5787 else
5788 NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
5789 ReplaceValueWith(SDValue(N, 1), NewChain);
5790
5791 return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
5792}
5793
5794SDValue DAGTypeLegalizer::WidenVecRes_OverflowOp(SDNode *N, unsigned ResNo) {
5795 SDLoc DL(N);
5796 EVT ResVT = N->getValueType(0);
5797 EVT OvVT = N->getValueType(1);
5798 EVT WideResVT, WideOvVT;
5799 SDValue WideLHS, WideRHS;
5800
5801 // TODO: This might result in a widen/split loop.
5802 if (ResNo == 0) {
5803 WideResVT = TLI.getTypeToTransformTo(*DAG.getContext(), ResVT);
5804 WideOvVT = EVT::getVectorVT(
5805 *DAG.getContext(), OvVT.getVectorElementType(),
5806 WideResVT.getVectorNumElements());
5807
5808 WideLHS = GetWidenedVector(N->getOperand(0));
5809 WideRHS = GetWidenedVector(N->getOperand(1));
5810 } else {
5811 WideOvVT = TLI.getTypeToTransformTo(*DAG.getContext(), OvVT);
5812 WideResVT = EVT::getVectorVT(
5813 *DAG.getContext(), ResVT.getVectorElementType(),
5814 WideOvVT.getVectorNumElements());
5815
5816 SDValue Zero = DAG.getVectorIdxConstant(0, DL);
5817 SDValue Poison = DAG.getPOISON(WideResVT);
5818
5819 WideLHS = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideResVT, Poison,
5820 N->getOperand(0), Zero);
5821 WideRHS = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideResVT, Poison,
5822 N->getOperand(1), Zero);
5823 }
5824
5825 SDVTList WideVTs = DAG.getVTList(WideResVT, WideOvVT);
5826 SDNode *WideNode = DAG.getNode(
5827 N->getOpcode(), DL, WideVTs, WideLHS, WideRHS).getNode();
5828
5829 // Replace the other vector result not being explicitly widened here.
5830 unsigned OtherNo = 1 - ResNo;
5831 EVT OtherVT = N->getValueType(OtherNo);
5832 if (getTypeAction(OtherVT) == TargetLowering::TypeWidenVector) {
5833 SetWidenedVector(SDValue(N, OtherNo), SDValue(WideNode, OtherNo));
5834 } else {
5835 SDValue Zero = DAG.getVectorIdxConstant(0, DL);
5836 SDValue OtherVal = DAG.getNode(
5837 ISD::EXTRACT_SUBVECTOR, DL, OtherVT, SDValue(WideNode, OtherNo), Zero);
5838 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
5839 }
5840
5841 return SDValue(WideNode, ResNo);
5842}
5843
5844SDValue DAGTypeLegalizer::WidenVecRes_Convert(SDNode *N) {
5845 LLVMContext &Ctx = *DAG.getContext();
5846 SDValue InOp = N->getOperand(0);
5847 SDLoc DL(N);
5848
5849 EVT WidenVT = TLI.getTypeToTransformTo(Ctx, N->getValueType(0));
5850 ElementCount WidenEC = WidenVT.getVectorElementCount();
5851
5852 EVT InVT = InOp.getValueType();
5853
5854 unsigned Opcode = N->getOpcode();
5855 const SDNodeFlags Flags = N->getFlags();
5856
5857 // Handle the case of ZERO_EXTEND where the promoted InVT element size does
5858 // not equal that of WidenVT.
5859 if (N->getOpcode() == ISD::ZERO_EXTEND &&
5860 getTypeAction(InVT) == TargetLowering::TypePromoteInteger &&
5861 TLI.getTypeToTransformTo(Ctx, InVT).getScalarSizeInBits() !=
5862 WidenVT.getScalarSizeInBits()) {
5863 InOp = ZExtPromotedInteger(InOp);
5864 InVT = InOp.getValueType();
5865 if (WidenVT.getScalarSizeInBits() < InVT.getScalarSizeInBits())
5866 Opcode = ISD::TRUNCATE;
5867 }
5868
5869 EVT InEltVT = InVT.getVectorElementType();
5870 EVT InWidenVT = EVT::getVectorVT(Ctx, InEltVT, WidenEC);
5871 ElementCount InVTEC = InVT.getVectorElementCount();
5872
5873 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
5874 InOp = GetWidenedVector(N->getOperand(0));
5875 InVT = InOp.getValueType();
5876 InVTEC = InVT.getVectorElementCount();
5877 if (InVTEC == WidenEC) {
5878 if (N->getNumOperands() == 1)
5879 return DAG.getNode(Opcode, DL, WidenVT, InOp, Flags);
5880 if (N->getNumOperands() == 3) {
5881 assert(N->isVPOpcode() && "Expected VP opcode");
5882 SDValue Mask =
5883 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
5884 return DAG.getNode(Opcode, DL, WidenVT, InOp, Mask, N->getOperand(2));
5885 }
5886 return DAG.getNode(Opcode, DL, WidenVT, InOp, N->getOperand(1), Flags);
5887 }
5888 if (WidenVT.getSizeInBits() == InVT.getSizeInBits()) {
5889 // If both input and result vector types are of same width, extend
5890 // operations should be done with SIGN/ZERO_EXTEND_VECTOR_INREG, which
5891 // accepts fewer elements in the result than in the input.
5892 if (Opcode == ISD::ANY_EXTEND)
5893 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
5894 if (Opcode == ISD::SIGN_EXTEND)
5895 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
5896 if (Opcode == ISD::ZERO_EXTEND)
5897 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
5898 }
5899
5900 // For TRUNCATE, try to widen using the legal EC of the input type instead
5901 // if the legalisation action for that intermediate type is not widening.
5902 // E.g. for trunc nxv1i64 -> nxv1i8 where
5903 // - nxv1i64 input gets widened to nxv2i64
5904 // - nxv1i8 output gets widened to nxv16i8
5905 // Then one can try widening the result to nxv2i8 (instead of going all the
5906 // way to nxv16i8) if this later allows type promotion.
5907 EVT MidResVT =
5908 EVT::getVectorVT(Ctx, WidenVT.getVectorElementType(), InVTEC);
5909 if (N->getOpcode() == ISD::TRUNCATE &&
5910 getTypeAction(MidResVT) == TargetLowering::TypePromoteInteger) {
5911 SDValue MidRes = DAG.getNode(ISD::TRUNCATE, DL, MidResVT, InOp, Flags);
5912 return DAG.getInsertSubvector(DL, DAG.getPOISON(WidenVT), MidRes, 0);
5913 }
5914 }
5915
5916 if (TLI.isTypeLegal(InWidenVT)) {
5917 // Because the result and the input are different vector types, widening
5918 // the result could create a legal type but widening the input might make
5919 // it an illegal type that might lead to repeatedly splitting the input
5920 // and then widening it. To avoid this, we widen the input only if
5921 // it results in a legal type.
5922 if (WidenEC.isKnownMultipleOf(InVTEC.getKnownMinValue())) {
5923 // Widen the input and call convert on the widened input vector.
5924 unsigned NumConcat =
5925 WidenEC.getKnownMinValue() / InVTEC.getKnownMinValue();
5926 SmallVector<SDValue, 16> Ops(NumConcat, DAG.getPOISON(InVT));
5927 Ops[0] = InOp;
5928 SDValue InVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InWidenVT, Ops);
5929 if (N->getNumOperands() == 1)
5930 return DAG.getNode(Opcode, DL, WidenVT, InVec, Flags);
5931 return DAG.getNode(Opcode, DL, WidenVT, InVec, N->getOperand(1), Flags);
5932 }
5933
5934 if (InVTEC.isKnownMultipleOf(WidenEC.getKnownMinValue())) {
5935 SDValue InVal = DAG.getExtractSubvector(DL, InWidenVT, InOp, 0);
5936 // Extract the input and convert the shorten input vector.
5937 if (N->getNumOperands() == 1)
5938 return DAG.getNode(Opcode, DL, WidenVT, InVal, Flags);
5939 return DAG.getNode(Opcode, DL, WidenVT, InVal, N->getOperand(1), Flags);
5940 }
5941 }
5942
5943 // Otherwise unroll into some nasty scalar code and rebuild the vector.
5944 EVT EltVT = WidenVT.getVectorElementType();
5945 SmallVector<SDValue, 16> Ops(WidenEC.getFixedValue(), DAG.getPOISON(EltVT));
5946 // Use the original element count so we don't do more scalar opts than
5947 // necessary.
5948 unsigned MinElts = N->getValueType(0).getVectorNumElements();
5949 for (unsigned i=0; i < MinElts; ++i) {
5950 SDValue Val = DAG.getExtractVectorElt(DL, InEltVT, InOp, i);
5951 if (N->getNumOperands() == 1)
5952 Ops[i] = DAG.getNode(Opcode, DL, EltVT, Val, Flags);
5953 else
5954 Ops[i] = DAG.getNode(Opcode, DL, EltVT, Val, N->getOperand(1), Flags);
5955 }
5956
5957 return DAG.getBuildVector(WidenVT, DL, Ops);
5958}
5959
5960SDValue DAGTypeLegalizer::WidenVecRes_FP_TO_XINT_SAT(SDNode *N) {
5961 SDLoc dl(N);
5962 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5963 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
5964
5965 SDValue Src = N->getOperand(0);
5966 EVT SrcVT = Src.getValueType();
5967
5968 // Also widen the input.
5969 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
5970 Src = GetWidenedVector(Src);
5971 SrcVT = Src.getValueType();
5972 }
5973
5974 // Input and output not widened to the same size, give up.
5975 if (WidenNumElts != SrcVT.getVectorElementCount())
5976 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
5977
5978 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src, N->getOperand(1));
5979}
5980
5981SDValue DAGTypeLegalizer::WidenVecRes_XROUND(SDNode *N) {
5982 SDLoc dl(N);
5983 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5984 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
5985
5986 SDValue Src = N->getOperand(0);
5987 EVT SrcVT = Src.getValueType();
5988
5989 // Also widen the input.
5990 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
5991 Src = GetWidenedVector(Src);
5992 SrcVT = Src.getValueType();
5993 }
5994
5995 // Input and output not widened to the same size, give up.
5996 if (WidenNumElts != SrcVT.getVectorElementCount())
5997 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
5998
5999 if (N->getNumOperands() == 1)
6000 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src);
6001
6002 assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
6003 assert(N->isVPOpcode() && "Expected VP opcode");
6004
6005 SDValue Mask =
6006 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
6007 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src, Mask, N->getOperand(2));
6008}
6009
6010SDValue DAGTypeLegalizer::WidenVecRes_Convert_StrictFP(SDNode *N) {
6011 SDValue InOp = N->getOperand(1);
6012 SDLoc DL(N);
6013 SmallVector<SDValue, 4> NewOps(N->ops());
6014
6015 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6016 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6017
6018 EVT InVT = InOp.getValueType();
6019 EVT InEltVT = InVT.getVectorElementType();
6020
6021 unsigned Opcode = N->getOpcode();
6022
6023 // FIXME: Optimizations need to be implemented here.
6024
6025 // Otherwise unroll into some nasty scalar code and rebuild the vector.
6026 EVT EltVT = WidenVT.getVectorElementType();
6027 std::array<EVT, 2> EltVTs = {{EltVT, MVT::Other}};
6028 SmallVector<SDValue, 16> Ops(WidenNumElts, DAG.getPOISON(EltVT));
6029 SmallVector<SDValue, 32> OpChains;
6030 // Use the original element count so we don't do more scalar opts than
6031 // necessary.
6032 unsigned MinElts = N->getValueType(0).getVectorNumElements();
6033 for (unsigned i=0; i < MinElts; ++i) {
6034 NewOps[1] = DAG.getExtractVectorElt(DL, InEltVT, InOp, i);
6035 Ops[i] = DAG.getNode(Opcode, DL, EltVTs, NewOps);
6036 OpChains.push_back(Ops[i].getValue(1));
6037 }
6038 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OpChains);
6039 ReplaceValueWith(SDValue(N, 1), NewChain);
6040
6041 return DAG.getBuildVector(WidenVT, DL, Ops);
6042}
6043
6044SDValue DAGTypeLegalizer::WidenVecRes_EXTEND_VECTOR_INREG(SDNode *N) {
6045 unsigned Opcode = N->getOpcode();
6046 SDValue InOp = N->getOperand(0);
6047 SDLoc DL(N);
6048
6049 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6050 EVT WidenSVT = WidenVT.getVectorElementType();
6051 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6052
6053 EVT InVT = InOp.getValueType();
6054 EVT InSVT = InVT.getVectorElementType();
6055 unsigned InVTNumElts = InVT.getVectorNumElements();
6056
6057 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
6058 InOp = GetWidenedVector(InOp);
6059 InVT = InOp.getValueType();
6060 if (InVT.getSizeInBits() == WidenVT.getSizeInBits()) {
6061 switch (Opcode) {
6065 return DAG.getNode(Opcode, DL, WidenVT, InOp);
6066 }
6067 }
6068 }
6069
6070 // Unroll, extend the scalars and rebuild the vector.
6072 for (unsigned i = 0, e = std::min(InVTNumElts, WidenNumElts); i != e; ++i) {
6073 SDValue Val = DAG.getExtractVectorElt(DL, InSVT, InOp, i);
6074 switch (Opcode) {
6076 Val = DAG.getNode(ISD::ANY_EXTEND, DL, WidenSVT, Val);
6077 break;
6079 Val = DAG.getNode(ISD::SIGN_EXTEND, DL, WidenSVT, Val);
6080 break;
6082 Val = DAG.getNode(ISD::ZERO_EXTEND, DL, WidenSVT, Val);
6083 break;
6084 default:
6085 llvm_unreachable("A *_EXTEND_VECTOR_INREG node was expected");
6086 }
6087 Ops.push_back(Val);
6088 }
6089
6090 while (Ops.size() != WidenNumElts)
6091 Ops.push_back(DAG.getPOISON(WidenSVT));
6092
6093 return DAG.getBuildVector(WidenVT, DL, Ops);
6094}
6095
6096SDValue DAGTypeLegalizer::WidenVecRes_FCOPYSIGN(SDNode *N) {
6097 // If this is an FCOPYSIGN with same input types, we can treat it as a
6098 // normal (can trap) binary op.
6099 if (N->getOperand(0).getValueType() == N->getOperand(1).getValueType())
6100 return WidenVecRes_BinaryCanTrap(N);
6101
6102 // If the types are different, fall back to unrolling.
6103 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6104 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
6105}
6106
6107/// Result and first source operand are different scalar types, but must have
6108/// the same number of elements. There is an additional control argument which
6109/// should be passed through unchanged.
6110SDValue DAGTypeLegalizer::WidenVecRes_UnarySameEltsWithScalarArg(SDNode *N) {
6111 SDValue FpValue = N->getOperand(0);
6112 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6113 if (getTypeAction(FpValue.getValueType()) != TargetLowering::TypeWidenVector)
6114 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
6115 SDValue Arg = GetWidenedVector(FpValue);
6116 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, {Arg, N->getOperand(1)},
6117 N->getFlags());
6118}
6119
6120SDValue DAGTypeLegalizer::WidenVecRes_ExpOp(SDNode *N) {
6121 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6122 SDValue InOp = GetWidenedVector(N->getOperand(0));
6123 SDValue RHS = N->getOperand(1);
6124 EVT ExpVT = RHS.getValueType();
6125 SDValue ExpOp = RHS;
6126 if (ExpVT.isVector()) {
6127 EVT WideExpVT = WidenVT.changeVectorElementType(
6128 *DAG.getContext(), ExpVT.getVectorElementType());
6129 ExpOp = ModifyToType(RHS, WideExpVT);
6130 }
6131
6132 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, ExpOp);
6133}
6134
6135SDValue DAGTypeLegalizer::WidenVecRes_Unary(SDNode *N) {
6136 // Unary op widening.
6137 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6138 SDValue InOp = GetWidenedVector(N->getOperand(0));
6139 if (N->getNumOperands() == 1)
6140 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, N->getFlags());
6141 if (N->getOpcode() == ISD::AssertNoFPClass)
6142 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp,
6143 N->getOperand(1), N->getFlags());
6144
6145 assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
6146 assert(N->isVPOpcode() && "Expected VP opcode");
6147
6148 SDValue Mask =
6149 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
6150 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT,
6151 {InOp, Mask, N->getOperand(2)});
6152}
6153
6154SDValue DAGTypeLegalizer::WidenVecRes_InregOp(SDNode *N) {
6155 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6156 EVT ExtVT = EVT::getVectorVT(
6157 *DAG.getContext(),
6158 cast<VTSDNode>(N->getOperand(1))->getVT().getVectorElementType(),
6159 WidenVT.getVectorElementCount());
6160 SDValue WidenLHS = GetWidenedVector(N->getOperand(0));
6161 return DAG.getNode(N->getOpcode(), SDLoc(N),
6162 WidenVT, WidenLHS, DAG.getValueType(ExtVT));
6163}
6164
6165SDValue DAGTypeLegalizer::WidenVecRes_UnaryOpWithTwoResults(SDNode *N,
6166 unsigned ResNo) {
6167 EVT VT0 = N->getValueType(0);
6168 EVT VT1 = N->getValueType(1);
6169
6170 assert(VT0.isVector() && VT1.isVector() &&
6172 "expected both results to be vectors of matching element count");
6173
6174 LLVMContext &Ctx = *DAG.getContext();
6175 SDValue InOp = GetWidenedVector(N->getOperand(0));
6176
6177 EVT WidenVT = TLI.getTypeToTransformTo(Ctx, N->getValueType(ResNo));
6178 ElementCount WidenEC = WidenVT.getVectorElementCount();
6179
6180 EVT WidenVT0 = EVT::getVectorVT(Ctx, VT0.getVectorElementType(), WidenEC);
6181 EVT WidenVT1 = EVT::getVectorVT(Ctx, VT1.getVectorElementType(), WidenEC);
6182
6183 SDNode *WidenNode =
6184 DAG.getNode(N->getOpcode(), SDLoc(N), {WidenVT0, WidenVT1}, InOp)
6185 .getNode();
6186
6187 ReplaceOtherWidenResults(N, WidenNode, ResNo);
6188 return SDValue(WidenNode, ResNo);
6189}
6190
6191SDValue DAGTypeLegalizer::WidenVecRes_MERGE_VALUES(SDNode *N, unsigned ResNo) {
6192 SDValue WidenVec = DisintegrateMERGE_VALUES(N, ResNo);
6193 return GetWidenedVector(WidenVec);
6194}
6195
6196SDValue DAGTypeLegalizer::WidenVecRes_ADDRSPACECAST(SDNode *N) {
6197 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6198 SDValue InOp = GetWidenedVector(N->getOperand(0));
6199 auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
6200
6201 return DAG.getAddrSpaceCast(SDLoc(N), WidenVT, InOp,
6202 AddrSpaceCastN->getSrcAddressSpace(),
6203 AddrSpaceCastN->getDestAddressSpace());
6204}
6205
6206SDValue DAGTypeLegalizer::WidenVecRes_BITCAST(SDNode *N) {
6207 SDValue InOp = N->getOperand(0);
6208 EVT InVT = InOp.getValueType();
6209 EVT VT = N->getValueType(0);
6210 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6211 SDLoc dl(N);
6212
6213 switch (getTypeAction(InVT)) {
6215 break;
6217 report_fatal_error("Scalarization of scalable vectors is not supported.");
6219 // If the incoming type is a vector that is being promoted, then
6220 // we know that the elements are arranged differently and that we
6221 // must perform the conversion using a stack slot.
6222 if (InVT.isVector())
6223 break;
6224
6225 // If the InOp is promoted to the same size, convert it. Otherwise,
6226 // fall out of the switch and widen the promoted input.
6227 SDValue NInOp = GetPromotedInteger(InOp);
6228 EVT NInVT = NInOp.getValueType();
6229 if (WidenVT.bitsEq(NInVT)) {
6230 // For big endian targets we need to shift the input integer or the
6231 // interesting bits will end up at the wrong place.
6232 if (DAG.getDataLayout().isBigEndian()) {
6233 unsigned ShiftAmt = NInVT.getSizeInBits() - InVT.getSizeInBits();
6234 NInOp = DAG.getNode(ISD::SHL, dl, NInVT, NInOp,
6235 DAG.getShiftAmountConstant(ShiftAmt, NInVT, dl));
6236 }
6237 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NInOp);
6238 }
6239 InOp = NInOp;
6240 InVT = NInVT;
6241 break;
6242 }
6249 break;
6251 // If the InOp is widened to the same size, convert it. Otherwise, fall
6252 // out of the switch and widen the widened input.
6253 InOp = GetWidenedVector(InOp);
6254 InVT = InOp.getValueType();
6255 if (WidenVT.bitsEq(InVT))
6256 // The input widens to the same size. Convert to the widen value.
6257 return DAG.getNode(ISD::BITCAST, dl, WidenVT, InOp);
6258 break;
6259 }
6260
6261 unsigned WidenSize = WidenVT.getSizeInBits();
6262 unsigned InSize = InVT.getSizeInBits();
6263 unsigned InScalarSize = InVT.getScalarSizeInBits();
6264 // x86mmx is not an acceptable vector element type, so don't try.
6265 if (WidenSize % InScalarSize == 0 && InVT != MVT::x86mmx) {
6266 // Determine new input vector type. The new input vector type will use
6267 // the same element type (if its a vector) or use the input type as a
6268 // vector. It is the same size as the type to widen to.
6269 EVT NewInVT;
6270 unsigned NewNumParts = WidenSize / InSize;
6271 if (InVT.isVector()) {
6272 EVT InEltVT = InVT.getVectorElementType();
6273 NewInVT = EVT::getVectorVT(*DAG.getContext(), InEltVT,
6274 WidenSize / InEltVT.getSizeInBits());
6275 } else {
6276 // For big endian systems, using the promoted input scalar type
6277 // to produce the scalar_to_vector would put the desired bits into
6278 // the least significant byte(s) of the wider element zero. This
6279 // will mean that the users of the result vector are using incorrect
6280 // bits. Use the original input type instead. Although either input
6281 // type can be used on little endian systems, for consistency we
6282 // use the original type there as well.
6283 EVT OrigInVT = N->getOperand(0).getValueType();
6284 NewNumParts = WidenSize / OrigInVT.getSizeInBits();
6285 NewInVT = EVT::getVectorVT(*DAG.getContext(), OrigInVT, NewNumParts);
6286 }
6287
6288 if (TLI.isTypeLegal(NewInVT)) {
6289 SDValue NewVec;
6290 if (InVT.isVector()) {
6291 // Because the result and the input are different vector types, widening
6292 // the result could create a legal type but widening the input might
6293 // make it an illegal type that might lead to repeatedly splitting the
6294 // input and then widening it. To avoid this, we widen the input only if
6295 // it results in a legal type.
6296 if (WidenSize % InSize == 0) {
6297 SmallVector<SDValue, 16> Ops(NewNumParts, DAG.getPOISON(InVT));
6298 Ops[0] = InOp;
6299
6300 NewVec = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewInVT, Ops);
6301 } else {
6303 DAG.ExtractVectorElements(InOp, Ops);
6304 Ops.append(WidenSize / InScalarSize - Ops.size(),
6305 DAG.getPOISON(InVT.getVectorElementType()));
6306
6307 NewVec = DAG.getNode(ISD::BUILD_VECTOR, dl, NewInVT, Ops);
6308 }
6309 } else {
6310 NewVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewInVT, InOp);
6311 }
6312 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NewVec);
6313 }
6314 }
6315
6316 return CreateStackStoreLoad(InOp, WidenVT);
6317}
6318
6319SDValue DAGTypeLegalizer::WidenVecRes_LOOP_DEPENDENCE_MASK(SDNode *N) {
6320 return DAG.getNode(
6321 N->getOpcode(), SDLoc(N),
6322 TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)),
6323 N->getOperand(0), N->getOperand(1), N->getOperand(2), N->getOperand(3));
6324}
6325
6326SDValue DAGTypeLegalizer::WidenVecRes_BUILD_VECTOR(SDNode *N) {
6327 SDLoc dl(N);
6328 // Build a vector with poison for the new nodes.
6329 EVT VT = N->getValueType(0);
6330
6331 // Integer BUILD_VECTOR operands may be larger than the node's vector element
6332 // type. The POISONs need to have the same type as the existing operands.
6333 EVT EltVT = N->getOperand(0).getValueType();
6334 unsigned NumElts = VT.getVectorNumElements();
6335
6336 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6337 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6338
6339 SmallVector<SDValue, 16> NewOps(N->ops());
6340 assert(WidenNumElts >= NumElts && "Shrinking vector instead of widening!");
6341 NewOps.append(WidenNumElts - NumElts, DAG.getPOISON(EltVT));
6342
6343 return DAG.getBuildVector(WidenVT, dl, NewOps);
6344}
6345
6346SDValue DAGTypeLegalizer::WidenVecRes_CONCAT_VECTORS(SDNode *N) {
6347 EVT InVT = N->getOperand(0).getValueType();
6348 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6349 SDLoc dl(N);
6350 unsigned NumOperands = N->getNumOperands();
6351
6352 bool InputWidened = false; // Indicates we need to widen the input.
6353 if (getTypeAction(InVT) != TargetLowering::TypeWidenVector) {
6354 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6355 unsigned NumInElts = InVT.getVectorMinNumElements();
6356 if (WidenNumElts % NumInElts == 0) {
6357 // Add undef vectors to widen to correct length.
6358 unsigned NumConcat = WidenNumElts / NumInElts;
6359 SDValue UndefVal = DAG.getPOISON(InVT);
6360 SmallVector<SDValue, 16> Ops(NumConcat);
6361 for (unsigned i=0; i < NumOperands; ++i)
6362 Ops[i] = N->getOperand(i);
6363 for (unsigned i = NumOperands; i != NumConcat; ++i)
6364 Ops[i] = UndefVal;
6365 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Ops);
6366 }
6367 } else {
6368 InputWidened = true;
6369 if (WidenVT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
6370 // The inputs and the result are widen to the same value.
6371 unsigned i;
6372 for (i=1; i < NumOperands; ++i)
6373 if (!N->getOperand(i).isUndef())
6374 break;
6375
6376 if (i == NumOperands)
6377 // Everything but the first operand is an UNDEF so just return the
6378 // widened first operand.
6379 return GetWidenedVector(N->getOperand(0));
6380
6381 if (NumOperands == 2) {
6382 assert(!WidenVT.isScalableVector() &&
6383 "Cannot use vector shuffles to widen CONCAT_VECTOR result");
6384 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6385 unsigned NumInElts = InVT.getVectorNumElements();
6386
6387 // Replace concat of two operands with a shuffle.
6388 SmallVector<int, 16> MaskOps(WidenNumElts, -1);
6389 for (unsigned i = 0; i < NumInElts; ++i) {
6390 MaskOps[i] = i;
6391 MaskOps[i + NumInElts] = i + WidenNumElts;
6392 }
6393 return DAG.getVectorShuffle(WidenVT, dl,
6394 GetWidenedVector(N->getOperand(0)),
6395 GetWidenedVector(N->getOperand(1)),
6396 MaskOps);
6397 }
6398 }
6399 }
6400
6401 assert(!WidenVT.isScalableVector() &&
6402 "Cannot use build vectors to widen CONCAT_VECTOR result");
6403 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6404 unsigned NumInElts = InVT.getVectorNumElements();
6405
6406 // Fall back to use extracts and build vector.
6407 EVT EltVT = WidenVT.getVectorElementType();
6408 SmallVector<SDValue, 16> Ops(WidenNumElts);
6409 unsigned Idx = 0;
6410 for (unsigned i=0; i < NumOperands; ++i) {
6411 SDValue InOp = N->getOperand(i);
6412 if (InputWidened)
6413 InOp = GetWidenedVector(InOp);
6414 for (unsigned j = 0; j < NumInElts; ++j)
6415 Ops[Idx++] = DAG.getExtractVectorElt(dl, EltVT, InOp, j);
6416 }
6417 SDValue UndefVal = DAG.getPOISON(EltVT);
6418 for (; Idx < WidenNumElts; ++Idx)
6419 Ops[Idx] = UndefVal;
6420 return DAG.getBuildVector(WidenVT, dl, Ops);
6421}
6422
6423SDValue DAGTypeLegalizer::WidenVecRes_INSERT_SUBVECTOR(SDNode *N) {
6424 EVT VT = N->getValueType(0);
6425 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6426 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
6427 SDValue InOp2 = N->getOperand(1);
6428 SDValue Idx = N->getOperand(2);
6429 SDLoc dl(N);
6430 return DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WidenVT, InOp1, InOp2, Idx);
6431}
6432
6433SDValue DAGTypeLegalizer::WidenVecRes_EXTRACT_SUBVECTOR(SDNode *N) {
6434 EVT VT = N->getValueType(0);
6435 EVT EltVT = VT.getVectorElementType();
6436 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6437 SDValue InOp = N->getOperand(0);
6438 SDValue Idx = N->getOperand(1);
6439 SDLoc dl(N);
6440
6441 auto InOpTypeAction = getTypeAction(InOp.getValueType());
6442 if (InOpTypeAction == TargetLowering::TypeWidenVector)
6443 InOp = GetWidenedVector(InOp);
6444
6445 EVT InVT = InOp.getValueType();
6446
6447 // Check if we can just return the input vector after widening.
6448 uint64_t IdxVal = Idx->getAsZExtVal();
6449 if (IdxVal == 0 && InVT == WidenVT)
6450 return InOp;
6451
6452 // Check if we can extract from the vector.
6453 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6454 unsigned InNumElts = InVT.getVectorMinNumElements();
6455 unsigned VTNumElts = VT.getVectorMinNumElements();
6456 assert(IdxVal % VTNumElts == 0 &&
6457 "Expected Idx to be a multiple of subvector minimum vector length");
6458 if (IdxVal % WidenNumElts == 0 && IdxVal + WidenNumElts < InNumElts)
6459 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, WidenVT, InOp, Idx);
6460
6461 if (VT.isScalableVector()) {
6462 // Try to split the operation up into smaller extracts and concat the
6463 // results together, e.g.
6464 // nxv6i64 extract_subvector(nxv12i64, 6)
6465 // <->
6466 // nxv8i64 concat(
6467 // nxv2i64 extract_subvector(nxv16i64, 6)
6468 // nxv2i64 extract_subvector(nxv16i64, 8)
6469 // nxv2i64 extract_subvector(nxv16i64, 10)
6470 // undef)
6471 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
6472 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
6473 "down type's element count");
6474 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
6476 // Avoid recursion around e.g. nxv1i8.
6477 if (getTypeAction(PartVT) != TargetLowering::TypeWidenVector) {
6479 unsigned I = 0;
6480 for (; I < VTNumElts / GCD; ++I)
6481 Parts.push_back(
6482 DAG.getExtractSubvector(dl, PartVT, InOp, IdxVal + I * GCD));
6483 for (; I < WidenNumElts / GCD; ++I)
6484 Parts.push_back(DAG.getPOISON(PartVT));
6485
6486 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
6487 }
6488
6489 // Fallback to extracting through memory.
6490
6491 Align Alignment = DAG.getReducedAlign(InVT, /*UseABI=*/false);
6492 SDValue StackPtr = DAG.CreateStackTemporary(InVT.getStoreSize(), Alignment);
6493 MachineFunction &MF = DAG.getMachineFunction();
6494 int FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
6495 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
6496
6497 MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
6500 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
6503
6504 // Write out the input vector.
6505 SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, InOp, StackPtr, StoreMMO);
6506
6507 // Build a mask to match the length of the non-widened result.
6508 SDValue Mask =
6509 DAG.getMaskFromElementCount(dl, WidenVT, VT.getVectorElementCount());
6510
6511 // Read back the sub-vector setting the remaining lanes to poison.
6512 StackPtr = TLI.getVectorSubVecPointer(DAG, StackPtr, InVT, VT, Idx);
6513 return DAG.getMaskedLoad(
6514 WidenVT, dl, Ch, StackPtr, DAG.getPOISON(StackPtr.getValueType()), Mask,
6515 DAG.getPOISON(WidenVT), VT, LoadMMO, ISD::UNINDEXED, ISD::NON_EXTLOAD);
6516 }
6517
6518 // We could try widening the input to the right length but for now, extract
6519 // the original elements, fill the rest with undefs and build a vector.
6520 SmallVector<SDValue, 16> Ops(WidenNumElts);
6521 unsigned i;
6522 for (i = 0; i < VTNumElts; ++i)
6523 Ops[i] = DAG.getExtractVectorElt(dl, EltVT, InOp, IdxVal + i);
6524
6525 SDValue UndefVal = DAG.getPOISON(EltVT);
6526 for (; i < WidenNumElts; ++i)
6527 Ops[i] = UndefVal;
6528 return DAG.getBuildVector(WidenVT, dl, Ops);
6529}
6530
6531SDValue DAGTypeLegalizer::WidenVecRes_AssertZext(SDNode *N) {
6532 SDValue InOp = ModifyToType(
6533 N->getOperand(0),
6534 TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)), true);
6535 return DAG.getNode(ISD::AssertZext, SDLoc(N), InOp.getValueType(), InOp,
6536 N->getOperand(1));
6537}
6538
6539SDValue DAGTypeLegalizer::WidenVecRes_INSERT_VECTOR_ELT(SDNode *N) {
6540 SDValue InOp = GetWidenedVector(N->getOperand(0));
6541 return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(N),
6542 InOp.getValueType(), InOp,
6543 N->getOperand(1), N->getOperand(2));
6544}
6545
6546/// Either return the same load or provide appropriate casts
6547/// from the load and return that.
6548static SDValue coerceLoadedValue(SDValue LdOp, EVT FirstVT, EVT WidenVT,
6549 TypeSize LdWidth, TypeSize FirstVTWidth,
6550 SDLoc dl, SelectionDAG &DAG) {
6551 assert(TypeSize::isKnownLE(LdWidth, FirstVTWidth) &&
6552 "Load width must be less than or equal to first value type width");
6553 TypeSize WidenWidth = WidenVT.getSizeInBits();
6554 if (!FirstVT.isVector()) {
6555 unsigned NumElts =
6556 WidenWidth.getFixedValue() / FirstVTWidth.getFixedValue();
6557 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), FirstVT, NumElts);
6558 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT, LdOp);
6559 return DAG.getNode(ISD::BITCAST, dl, WidenVT, VecOp);
6560 }
6561 assert(FirstVT == WidenVT && "First value type must equal widen value type");
6562 return LdOp;
6563}
6564
6565static std::optional<EVT> findMemType(SelectionDAG &DAG,
6566 const TargetLowering &TLI, unsigned Width,
6567 EVT WidenVT, unsigned Align,
6568 unsigned WidenEx);
6569
6570SDValue DAGTypeLegalizer::WidenVecRes_ATOMIC_LOAD(AtomicSDNode *LD) {
6571 EVT WidenVT =
6572 TLI.getTypeToTransformTo(*DAG.getContext(), LD->getValueType(0));
6573 EVT LdVT = LD->getMemoryVT();
6574 SDLoc dl(LD);
6575 assert(LdVT.isVector() && WidenVT.isVector() && "Expected vectors");
6576 assert(LdVT.isScalableVector() == WidenVT.isScalableVector() &&
6577 "Must be scalable");
6578 assert(LdVT.getVectorElementType() == WidenVT.getVectorElementType() &&
6579 "Expected equivalent element types");
6580
6581 // Load information
6582 SDValue Chain = LD->getChain();
6583 SDValue BasePtr = LD->getBasePtr();
6584
6585 TypeSize LdWidth = LdVT.getSizeInBits();
6586 TypeSize WidenWidth = WidenVT.getSizeInBits();
6587 TypeSize WidthDiff = WidenWidth - LdWidth;
6588
6589 // Find the vector type that can load from.
6590 std::optional<EVT> FirstVT =
6591 findMemType(DAG, TLI, LdWidth.getKnownMinValue(), WidenVT, /*LdAlign=*/0,
6592 WidthDiff.getKnownMinValue());
6593
6594 if (!FirstVT)
6595 return SDValue();
6596
6597 SmallVector<EVT, 8> MemVTs;
6598 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
6599
6600 SDValue LdOp = DAG.getAtomicLoad(ISD::NON_EXTLOAD, dl, *FirstVT, *FirstVT,
6601 Chain, BasePtr, LD->getMemOperand());
6602
6603 // Load the element with one instruction.
6604 SDValue Result = coerceLoadedValue(LdOp, *FirstVT, WidenVT, LdWidth,
6605 FirstVTWidth, dl, DAG);
6606
6607 // Modified the chain - switch anything that used the old chain to use
6608 // the new one.
6609 ReplaceValueWith(SDValue(LD, 1), LdOp.getValue(1));
6610 return Result;
6611}
6612
6613SDValue DAGTypeLegalizer::WidenVecRes_LOAD(SDNode *N) {
6614 LoadSDNode *LD = cast<LoadSDNode>(N);
6615 ISD::LoadExtType ExtType = LD->getExtensionType();
6616
6617 // A vector must always be stored in memory as-is, i.e. without any padding
6618 // between the elements, since various code depend on it, e.g. in the
6619 // handling of a bitcast of a vector type to int, which may be done with a
6620 // vector store followed by an integer load. A vector that does not have
6621 // elements that are byte-sized must therefore be stored as an integer
6622 // built out of the extracted vector elements.
6623 if (!LD->getMemoryVT().isByteSized()) {
6624 SDValue Value, NewChain;
6625 std::tie(Value, NewChain) = TLI.scalarizeVectorLoad(LD, DAG);
6626 ReplaceValueWith(SDValue(LD, 0), Value);
6627 ReplaceValueWith(SDValue(LD, 1), NewChain);
6628 return SDValue();
6629 }
6630
6631 // Generate a vector-predicated load if it is custom/legal on the target. To
6632 // avoid possible recursion, only do this if the widened mask type is legal.
6633 // FIXME: Not all targets may support EVL in VP_LOAD. These will have been
6634 // removed from the IR by the ExpandVectorPredication pass but we're
6635 // reintroducing them here.
6636 EVT VT = LD->getValueType(0);
6637 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6638 EVT WideMaskVT = getSetCCResultType(WideVT);
6639
6640 if (ExtType == ISD::NON_EXTLOAD &&
6641 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WideVT) &&
6642 TLI.isTypeLegal(WideMaskVT)) {
6643 SDLoc DL(N);
6644 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
6645 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
6647 SDValue NewLoad =
6648 DAG.getLoadVP(LD->getAddressingMode(), ISD::NON_EXTLOAD, WideVT, DL,
6649 LD->getChain(), LD->getBasePtr(), LD->getOffset(), Mask,
6650 EVL, LD->getMemoryVT(), LD->getMemOperand());
6651
6652 // Modified the chain - switch anything that used the old chain to use
6653 // the new one.
6654 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6655
6656 return NewLoad;
6657 }
6658
6660 SmallVector<SDValue, 16> LdChain; // Chain for the series of load
6661 if (ExtType != ISD::NON_EXTLOAD)
6662 Result = GenWidenVectorExtLoads(LdChain, LD, ExtType);
6663 else
6664 Result = GenWidenVectorLoads(LdChain, LD);
6665
6666 if (Result) {
6667 // If we generate a single load, we can use that for the chain. Otherwise,
6668 // build a factor node to remember the multiple loads are independent and
6669 // chain to that.
6670 SDValue NewChain;
6671 if (LdChain.size() == 1)
6672 NewChain = LdChain[0];
6673 else
6674 NewChain = DAG.getNode(ISD::TokenFactor, SDLoc(LD), MVT::Other, LdChain);
6675
6676 // Modified the chain - switch anything that used the old chain to use
6677 // the new one.
6678 ReplaceValueWith(SDValue(N, 1), NewChain);
6679
6680 return Result;
6681 }
6682
6683 if (VT.isVector()) {
6684 // If all else fails replace the load with a wide masked load.
6685 SDLoc DL(N);
6686 SDValue Mask =
6687 DAG.getMaskFromElementCount(DL, WideVT, VT.getVectorElementCount());
6688
6689 SDValue NewLoad = DAG.getMaskedLoad(
6690 WideVT, DL, LD->getChain(), LD->getBasePtr(), LD->getOffset(), Mask,
6691 DAG.getPOISON(WideVT), LD->getMemoryVT(), LD->getMemOperand(),
6692 LD->getAddressingMode(), LD->getExtensionType());
6693
6694 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6695 return NewLoad;
6696 }
6697
6698 report_fatal_error("Unable to widen vector load");
6699}
6700
6701SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD(VPLoadSDNode *N) {
6702 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6703 SDValue Mask = N->getMask();
6704 SDValue EVL = N->getVectorLength();
6705 ISD::LoadExtType ExtType = N->getExtensionType();
6706 SDLoc dl(N);
6707
6708 // The mask should be widened as well
6709 assert(getTypeAction(Mask.getValueType()) ==
6711 "Unable to widen binary VP op");
6712 Mask = GetWidenedVector(Mask);
6713 assert(Mask.getValueType().getVectorElementCount() ==
6714 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
6715 .getVectorElementCount() &&
6716 "Unable to widen vector load");
6717
6718 SDValue Res =
6719 DAG.getLoadVP(N->getAddressingMode(), ExtType, WidenVT, dl, N->getChain(),
6720 N->getBasePtr(), N->getOffset(), Mask, EVL,
6721 N->getMemoryVT(), N->getMemOperand(), N->isExpandingLoad());
6722 // Legalize the chain result - switch anything that used the old chain to
6723 // use the new one.
6724 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6725 return Res;
6726}
6727
6728SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD_FF(VPLoadFFSDNode *N) {
6729 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6730 SDValue Mask = N->getMask();
6731 SDValue EVL = N->getVectorLength();
6732 SDLoc dl(N);
6733
6734 // The mask should be widened as well
6735 assert(getTypeAction(Mask.getValueType()) ==
6737 "Unable to widen binary VP op");
6738 Mask = GetWidenedVector(Mask);
6739 assert(Mask.getValueType().getVectorElementCount() ==
6740 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
6741 .getVectorElementCount() &&
6742 "Unable to widen vector load");
6743
6744 SDValue Res = DAG.getLoadFFVP(WidenVT, dl, N->getChain(), N->getBasePtr(),
6745 Mask, EVL, N->getMemOperand());
6746 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6747 ReplaceValueWith(SDValue(N, 2), Res.getValue(2));
6748 return Res;
6749}
6750
6751SDValue DAGTypeLegalizer::WidenVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode *N) {
6752 SDLoc DL(N);
6753
6754 // The mask should be widened as well
6755 SDValue Mask = N->getMask();
6756 assert(getTypeAction(Mask.getValueType()) ==
6758 "Unable to widen VP strided load");
6759 Mask = GetWidenedVector(Mask);
6760
6761 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6762 assert(Mask.getValueType().getVectorElementCount() ==
6763 WidenVT.getVectorElementCount() &&
6764 "Data and mask vectors should have the same number of elements");
6765
6766 SDValue Res = DAG.getStridedLoadVP(
6767 N->getAddressingMode(), N->getExtensionType(), WidenVT, DL, N->getChain(),
6768 N->getBasePtr(), N->getOffset(), N->getStride(), Mask,
6769 N->getVectorLength(), N->getMemoryVT(), N->getMemOperand(),
6770 N->isExpandingLoad());
6771
6772 // Legalize the chain result - switch anything that used the old chain to
6773 // use the new one.
6774 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6775 return Res;
6776}
6777
6778SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_COMPRESS(SDNode *N) {
6779 SDValue Vec = N->getOperand(0);
6780 SDValue Mask = N->getOperand(1);
6781 SDValue Passthru = N->getOperand(2);
6782 EVT WideVecVT =
6783 TLI.getTypeToTransformTo(*DAG.getContext(), Vec.getValueType());
6784 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
6785 Mask.getValueType().getVectorElementType(),
6786 WideVecVT.getVectorElementCount());
6787
6788 SDValue WideVec = ModifyToType(Vec, WideVecVT);
6789 SDValue WideMask = ModifyToType(Mask, WideMaskVT, /*FillWithZeroes=*/true);
6790 SDValue WidePassthru = ModifyToType(Passthru, WideVecVT);
6791 return DAG.getNode(ISD::VECTOR_COMPRESS, SDLoc(N), WideVecVT, WideVec,
6792 WideMask, WidePassthru);
6793}
6794
6795SDValue DAGTypeLegalizer::WidenVecRes_MLOAD(MaskedLoadSDNode *N) {
6796 EVT VT = N->getValueType(0);
6797 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6798 SDValue Mask = N->getMask();
6799 EVT MaskVT = Mask.getValueType();
6800 SDValue PassThru = GetWidenedVector(N->getPassThru());
6801 ISD::LoadExtType ExtType = N->getExtensionType();
6802 SDLoc dl(N);
6803
6804 EVT WideMaskVT =
6805 EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(),
6806 WidenVT.getVectorElementCount());
6807
6808 if (ExtType == ISD::NON_EXTLOAD && !N->isExpandingLoad() &&
6809 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WidenVT) &&
6810 TLI.isTypeLegal(WideMaskVT) &&
6811 // If there is a passthru, we shouldn't use vp.load. However,
6812 // type legalizer will struggle on masked.load with
6813 // scalable vectors, so for scalable vectors, we still use vp.load
6814 // but manually merge the load result with the passthru using vp.select.
6815 (N->getPassThru()->isUndef() || VT.isScalableVector())) {
6816 Mask = DAG.getInsertSubvector(dl, DAG.getPOISON(WideMaskVT), Mask, 0);
6817 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
6819 SDValue NewLoad =
6820 DAG.getLoadVP(N->getAddressingMode(), ISD::NON_EXTLOAD, WidenVT, dl,
6821 N->getChain(), N->getBasePtr(), N->getOffset(), Mask, EVL,
6822 N->getMemoryVT(), N->getMemOperand());
6823 SDValue NewVal = NewLoad;
6824
6825 // Manually merge with vselect
6826 if (!N->getPassThru()->isUndef()) {
6827 assert(WidenVT.isScalableVector());
6828 NewVal = DAG.getNode(ISD::VSELECT, dl, WidenVT, Mask, NewVal, PassThru);
6829 // The lanes past EVL are poison.
6830 NewVal = DAG.getNode(ISD::VP_MERGE, dl, WidenVT,
6831 DAG.getAllOnesConstant(dl, WideMaskVT), NewVal,
6832 DAG.getPOISON(WidenVT), EVL);
6833 }
6834
6835 // Modified the chain - switch anything that used the old chain to use
6836 // the new one.
6837 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6838
6839 return NewVal;
6840 }
6841
6842 // The mask should be widened as well
6843 Mask = ModifyToType(Mask, WideMaskVT, true);
6844
6845 SDValue Res = DAG.getMaskedLoad(
6846 WidenVT, dl, N->getChain(), N->getBasePtr(), N->getOffset(), Mask,
6847 PassThru, N->getMemoryVT(), N->getMemOperand(), N->getAddressingMode(),
6848 ExtType, N->isExpandingLoad());
6849 // Legalize the chain result - switch anything that used the old chain to
6850 // use the new one.
6851 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6852 return Res;
6853}
6854
6855SDValue DAGTypeLegalizer::WidenVecRes_MGATHER(MaskedGatherSDNode *N) {
6856
6857 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6858 SDValue Mask = N->getMask();
6859 EVT MaskVT = Mask.getValueType();
6860 SDValue PassThru = GetWidenedVector(N->getPassThru());
6861 SDValue Scale = N->getScale();
6862 unsigned NumElts = WideVT.getVectorNumElements();
6863 SDLoc dl(N);
6864
6865 // The mask should be widened as well
6866 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
6867 MaskVT.getVectorElementType(),
6868 WideVT.getVectorNumElements());
6869 Mask = ModifyToType(Mask, WideMaskVT, true);
6870
6871 // Widen the Index operand
6872 SDValue Index = N->getIndex();
6873 EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
6874 Index.getValueType().getScalarType(),
6875 NumElts);
6876 Index = ModifyToType(Index, WideIndexVT);
6877 SDValue Ops[] = { N->getChain(), PassThru, Mask, N->getBasePtr(), Index,
6878 Scale };
6879
6880 // Widen the MemoryType
6881 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
6882 N->getMemoryVT().getScalarType(), NumElts);
6883 SDValue Res = DAG.getMaskedGather(DAG.getVTList(WideVT, MVT::Other),
6884 WideMemVT, dl, Ops, N->getMemOperand(),
6885 N->getIndexType(), N->getExtensionType());
6886
6887 // Legalize the chain result - switch anything that used the old chain to
6888 // use the new one.
6889 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6890 return Res;
6891}
6892
6893SDValue DAGTypeLegalizer::WidenVecRes_VP_GATHER(VPGatherSDNode *N) {
6894 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6895 SDValue Mask = N->getMask();
6896 SDValue Scale = N->getScale();
6897 ElementCount WideEC = WideVT.getVectorElementCount();
6898 SDLoc dl(N);
6899
6900 SDValue Index = GetWidenedVector(N->getIndex());
6901 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
6902 N->getMemoryVT().getScalarType(), WideEC);
6903 Mask = GetWidenedMask(Mask, WideEC);
6904
6905 SDValue Ops[] = {N->getChain(), N->getBasePtr(), Index, Scale,
6906 Mask, N->getVectorLength()};
6907 SDValue Res = DAG.getGatherVP(DAG.getVTList(WideVT, MVT::Other), WideMemVT,
6908 dl, Ops, N->getMemOperand(), N->getIndexType());
6909
6910 // Legalize the chain result - switch anything that used the old chain to
6911 // use the new one.
6912 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6913 return Res;
6914}
6915
6916SDValue DAGTypeLegalizer::WidenVecRes_ScalarOp(SDNode *N) {
6917 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6918 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, N->getOperand(0));
6919}
6920
6921// Return true is this is a SETCC node or a strict version of it.
6922static inline bool isSETCCOp(unsigned Opcode) {
6923 switch (Opcode) {
6924 case ISD::SETCC:
6925 case ISD::STRICT_FSETCC:
6927 return true;
6928 }
6929 return false;
6930}
6931
6932// Return true if this is a node that could have two SETCCs as operands.
6933static inline bool isLogicalMaskOp(unsigned Opcode) {
6934 switch (Opcode) {
6935 case ISD::AND:
6936 case ISD::OR:
6937 case ISD::XOR:
6938 return true;
6939 }
6940 return false;
6941}
6942
6943// If N is a SETCC or a strict variant of it, return the type
6944// of the compare operands.
6946 unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
6947 return N->getOperand(OpNo).getValueType();
6948}
6949
6950// This is used just for the assert in convertMask(). Check that this either
6951// a SETCC or a previously handled SETCC by convertMask().
6952#ifndef NDEBUG
6953static inline bool isSETCCorConvertedSETCC(SDValue N) {
6954 if (N.getOpcode() == ISD::EXTRACT_SUBVECTOR)
6955 N = N.getOperand(0);
6956 else if (N.getOpcode() == ISD::CONCAT_VECTORS) {
6957 for (unsigned i = 1; i < N->getNumOperands(); ++i)
6958 if (!N->getOperand(i)->isUndef())
6959 return false;
6960 N = N.getOperand(0);
6961 }
6962
6963 if (N.getOpcode() == ISD::TRUNCATE)
6964 N = N.getOperand(0);
6965 else if (N.getOpcode() == ISD::SIGN_EXTEND)
6966 N = N.getOperand(0);
6967
6968 if (isLogicalMaskOp(N.getOpcode()))
6969 return isSETCCorConvertedSETCC(N.getOperand(0)) &&
6970 isSETCCorConvertedSETCC(N.getOperand(1));
6971
6972 return (isSETCCOp(N.getOpcode()) ||
6974}
6975#endif
6976
6977// Return a mask of vector type MaskVT to replace InMask. Also adjust MaskVT
6978// to ToMaskVT if needed with vector extension or truncation.
6979SDValue DAGTypeLegalizer::convertMask(SDValue InMask, EVT MaskVT,
6980 EVT ToMaskVT) {
6981 // Currently a SETCC or a AND/OR/XOR with two SETCCs are handled.
6982 // FIXME: This code seems to be too restrictive, we might consider
6983 // generalizing it or dropping it.
6984 assert(isSETCCorConvertedSETCC(InMask) && "Unexpected mask argument.");
6985
6986 // Make a new Mask node, with a legal result VT.
6987 SDValue Mask;
6989 for (unsigned i = 0, e = InMask->getNumOperands(); i < e; ++i)
6990 Ops.push_back(InMask->getOperand(i));
6991 if (InMask->isStrictFPOpcode()) {
6992 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask),
6993 { MaskVT, MVT::Other }, Ops);
6994 ReplaceValueWith(InMask.getValue(1), Mask.getValue(1));
6995 }
6996 else
6997 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask), MaskVT, Ops,
6998 InMask->getFlags());
6999
7000 // If MaskVT has smaller or bigger elements than ToMaskVT, a vector sign
7001 // extend or truncate is needed.
7002 LLVMContext &Ctx = *DAG.getContext();
7003 unsigned MaskScalarBits = MaskVT.getScalarSizeInBits();
7004 unsigned ToMaskScalBits = ToMaskVT.getScalarSizeInBits();
7005 if (MaskScalarBits < ToMaskScalBits) {
7006 EVT ExtVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
7007 MaskVT.getVectorNumElements());
7008 Mask = DAG.getNode(ISD::SIGN_EXTEND, SDLoc(Mask), ExtVT, Mask);
7009 } else if (MaskScalarBits > ToMaskScalBits) {
7010 EVT TruncVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
7011 MaskVT.getVectorNumElements());
7012 Mask = DAG.getNode(ISD::TRUNCATE, SDLoc(Mask), TruncVT, Mask);
7013 }
7014
7015 assert(Mask->getValueType(0).getScalarSizeInBits() ==
7016 ToMaskVT.getScalarSizeInBits() &&
7017 "Mask should have the right element size by now.");
7018
7019 // Adjust Mask to the right number of elements.
7020 unsigned CurrMaskNumEls = Mask->getValueType(0).getVectorNumElements();
7021 if (CurrMaskNumEls > ToMaskVT.getVectorNumElements()) {
7022 Mask = DAG.getExtractSubvector(SDLoc(Mask), ToMaskVT, Mask, 0);
7023 } else if (CurrMaskNumEls < ToMaskVT.getVectorNumElements()) {
7024 unsigned NumSubVecs = (ToMaskVT.getVectorNumElements() / CurrMaskNumEls);
7025 EVT SubVT = Mask->getValueType(0);
7026 SmallVector<SDValue, 16> SubOps(NumSubVecs, DAG.getPOISON(SubVT));
7027 SubOps[0] = Mask;
7028 Mask = DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Mask), ToMaskVT, SubOps);
7029 }
7030
7031 assert((Mask->getValueType(0) == ToMaskVT) &&
7032 "A mask of ToMaskVT should have been produced by now.");
7033
7034 return Mask;
7035}
7036
7037// This method tries to handle some special cases for the vselect mask
7038// and if needed adjusting the mask vector type to match that of the VSELECT.
7039// Without it, many cases end up with scalarization of the SETCC, with many
7040// unnecessary instructions.
7041SDValue DAGTypeLegalizer::WidenVSELECTMask(SDNode *N) {
7042 LLVMContext &Ctx = *DAG.getContext();
7043 SDValue Cond = N->getOperand(0);
7044
7045 if (N->getOpcode() != ISD::VSELECT)
7046 return SDValue();
7047
7048 if (!isSETCCOp(Cond->getOpcode()) && !isLogicalMaskOp(Cond->getOpcode()))
7049 return SDValue();
7050
7051 // If this is a splitted VSELECT that was previously already handled, do
7052 // nothing.
7053 EVT CondVT = Cond->getValueType(0);
7054 if (CondVT.getScalarSizeInBits() != 1)
7055 return SDValue();
7056
7057 EVT VSelVT = N->getValueType(0);
7058
7059 // This method can't handle scalable vector types.
7060 // FIXME: This support could be added in the future.
7061 if (VSelVT.isScalableVector())
7062 return SDValue();
7063
7064 // Only handle vector types which are a power of 2.
7065 if (!isPowerOf2_64(VSelVT.getSizeInBits()))
7066 return SDValue();
7067
7068 // Don't touch if this will be scalarized.
7069 EVT FinalVT = VSelVT;
7070 while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
7071 FinalVT = FinalVT.getHalfNumVectorElementsVT(Ctx);
7072
7073 if (FinalVT.getVectorNumElements() == 1)
7074 return SDValue();
7075
7076 // If there is support for an i1 vector mask, don't touch.
7077 if (isSETCCOp(Cond.getOpcode())) {
7078 EVT SetCCOpVT = getSETCCOperandType(Cond);
7079 while (TLI.getTypeAction(Ctx, SetCCOpVT) != TargetLowering::TypeLegal)
7080 SetCCOpVT = TLI.getTypeToTransformTo(Ctx, SetCCOpVT);
7081 EVT SetCCResVT = getSetCCResultType(SetCCOpVT);
7082 if (SetCCResVT.getScalarSizeInBits() == 1)
7083 return SDValue();
7084 } else if (CondVT.getScalarType() == MVT::i1) {
7085 // If there is support for an i1 vector mask (or only scalar i1 conditions),
7086 // don't touch.
7087 while (TLI.getTypeAction(Ctx, CondVT) != TargetLowering::TypeLegal)
7088 CondVT = TLI.getTypeToTransformTo(Ctx, CondVT);
7089
7090 if (CondVT.getScalarType() == MVT::i1)
7091 return SDValue();
7092 }
7093
7094 // Widen the vselect result type if needed.
7095 if (getTypeAction(VSelVT) == TargetLowering::TypeWidenVector)
7096 VSelVT = TLI.getTypeToTransformTo(Ctx, VSelVT);
7097
7098 // The mask of the VSELECT should have integer elements.
7099 EVT ToMaskVT = VSelVT;
7100 if (!ToMaskVT.getScalarType().isInteger())
7101 ToMaskVT = ToMaskVT.changeVectorElementTypeToInteger();
7102
7103 SDValue Mask;
7104 if (isSETCCOp(Cond->getOpcode())) {
7105 EVT MaskVT = getSetCCResultType(getSETCCOperandType(Cond));
7106 Mask = convertMask(Cond, MaskVT, ToMaskVT);
7107 } else if (isLogicalMaskOp(Cond->getOpcode()) &&
7108 isSETCCOp(Cond->getOperand(0).getOpcode()) &&
7109 isSETCCOp(Cond->getOperand(1).getOpcode())) {
7110 // Cond is (AND/OR/XOR (SETCC, SETCC))
7111 SDValue SETCC0 = Cond->getOperand(0);
7112 SDValue SETCC1 = Cond->getOperand(1);
7113 EVT VT0 = getSetCCResultType(getSETCCOperandType(SETCC0));
7114 EVT VT1 = getSetCCResultType(getSETCCOperandType(SETCC1));
7115 unsigned ScalarBits0 = VT0.getScalarSizeInBits();
7116 unsigned ScalarBits1 = VT1.getScalarSizeInBits();
7117 unsigned ScalarBits_ToMask = ToMaskVT.getScalarSizeInBits();
7118 EVT MaskVT;
7119 // If the two SETCCs have different VTs, either extend/truncate one of
7120 // them to the other "towards" ToMaskVT, or truncate one and extend the
7121 // other to ToMaskVT.
7122 if (ScalarBits0 != ScalarBits1) {
7123 EVT NarrowVT = ((ScalarBits0 < ScalarBits1) ? VT0 : VT1);
7124 EVT WideVT = ((NarrowVT == VT0) ? VT1 : VT0);
7125 if (ScalarBits_ToMask >= WideVT.getScalarSizeInBits())
7126 MaskVT = WideVT;
7127 else if (ScalarBits_ToMask <= NarrowVT.getScalarSizeInBits())
7128 MaskVT = NarrowVT;
7129 else
7130 MaskVT = ToMaskVT;
7131 } else
7132 // If the two SETCCs have the same VT, don't change it.
7133 MaskVT = VT0;
7134
7135 // Make new SETCCs and logical nodes.
7136 SETCC0 = convertMask(SETCC0, VT0, MaskVT);
7137 SETCC1 = convertMask(SETCC1, VT1, MaskVT);
7138 Cond = DAG.getNode(Cond->getOpcode(), SDLoc(Cond), MaskVT, SETCC0, SETCC1);
7139
7140 // Convert the logical op for VSELECT if needed.
7141 Mask = convertMask(Cond, MaskVT, ToMaskVT);
7142 } else
7143 return SDValue();
7144
7145 return Mask;
7146}
7147
7148SDValue DAGTypeLegalizer::WidenVecRes_Select(SDNode *N) {
7149 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7150 ElementCount WidenEC = WidenVT.getVectorElementCount();
7151
7152 SDValue Cond1 = N->getOperand(0);
7153 EVT CondVT = Cond1.getValueType();
7154 unsigned Opcode = N->getOpcode();
7155 if (CondVT.isVector()) {
7156 if (SDValue WideCond = WidenVSELECTMask(N)) {
7157 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
7158 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
7159 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
7160 return DAG.getNode(Opcode, SDLoc(N), WidenVT, WideCond, InOp1, InOp2);
7161 }
7162
7163 EVT CondEltVT = CondVT.getVectorElementType();
7164 EVT CondWidenVT = EVT::getVectorVT(*DAG.getContext(), CondEltVT, WidenEC);
7165 if (getTypeAction(CondVT) == TargetLowering::TypeWidenVector)
7166 Cond1 = GetWidenedVector(Cond1);
7167
7168 // If we have to split the condition there is no point in widening the
7169 // select. This would result in an cycle of widening the select ->
7170 // widening the condition operand -> splitting the condition operand ->
7171 // splitting the select -> widening the select. Instead split this select
7172 // further and widen the resulting type.
7173 if (getTypeAction(CondVT) == TargetLowering::TypeSplitVector) {
7174 SDValue SplitSelect = SplitVecOp_VSELECT(N, 0);
7175 SDValue Res = ModifyToType(SplitSelect, WidenVT);
7176 return Res;
7177 }
7178
7179 if (Cond1.getValueType() != CondWidenVT)
7180 Cond1 = ModifyToType(Cond1, CondWidenVT);
7181 }
7182
7183 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
7184 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
7185 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
7186 if (Opcode == ISD::VP_SELECT || Opcode == ISD::VP_MERGE)
7187 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2,
7188 N->getOperand(3));
7189 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2);
7190}
7191
7192SDValue DAGTypeLegalizer::WidenVecRes_SELECT_CC(SDNode *N) {
7193 SDValue InOp1 = GetWidenedVector(N->getOperand(2));
7194 SDValue InOp2 = GetWidenedVector(N->getOperand(3));
7195 return DAG.getNode(ISD::SELECT_CC, SDLoc(N),
7196 InOp1.getValueType(), N->getOperand(0),
7197 N->getOperand(1), InOp1, InOp2, N->getOperand(4));
7198}
7199
7200SDValue DAGTypeLegalizer::WidenVecRes_UNDEF(SDNode *N) {
7201 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7202 return DAG.getUNDEF(WidenVT);
7203}
7204
7205SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N) {
7206 EVT VT = N->getValueType(0);
7207 SDLoc dl(N);
7208
7209 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7210 unsigned NumElts = VT.getVectorNumElements();
7211 unsigned WidenNumElts = WidenVT.getVectorNumElements();
7212
7213 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
7214 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
7215
7216 // Adjust mask based on new input vector length.
7217 SmallVector<int, 16> NewMask(WidenNumElts, -1);
7218 for (unsigned i = 0; i != NumElts; ++i) {
7219 int Idx = N->getMaskElt(i);
7220 if (Idx < (int)NumElts)
7221 NewMask[i] = Idx;
7222 else
7223 NewMask[i] = Idx - NumElts + WidenNumElts;
7224 }
7225 return DAG.getVectorShuffle(WidenVT, dl, InOp1, InOp2, NewMask);
7226}
7227
7228SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_REVERSE(SDNode *N) {
7229 EVT VT = N->getValueType(0);
7230 EVT EltVT = VT.getVectorElementType();
7231 SDLoc dl(N);
7232
7233 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7234 SDValue OpValue = GetWidenedVector(N->getOperand(0));
7235 assert(WidenVT == OpValue.getValueType() && "Unexpected widened vector type");
7236
7237 SDValue ReverseVal = DAG.getNode(ISD::VECTOR_REVERSE, dl, WidenVT, OpValue);
7238 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
7239 unsigned VTNumElts = VT.getVectorMinNumElements();
7240 unsigned IdxVal = WidenNumElts - VTNumElts;
7241
7242 if (VT.isScalableVector()) {
7243 // Try to split the 'Widen ReverseVal' into smaller extracts and concat the
7244 // results together, e.g.(nxv6i64 -> nxv8i64)
7245 // nxv8i64 vector_reverse
7246 // <->
7247 // nxv8i64 concat(
7248 // nxv2i64 extract_subvector(nxv8i64, 2)
7249 // nxv2i64 extract_subvector(nxv8i64, 4)
7250 // nxv2i64 extract_subvector(nxv8i64, 6)
7251 // nxv2i64 undef)
7252
7253 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
7254 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
7256 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
7257 "down type's element count");
7259 unsigned i = 0;
7260 for (; i < VTNumElts / GCD; ++i)
7261 Parts.push_back(
7262 DAG.getExtractSubvector(dl, PartVT, ReverseVal, IdxVal + i * GCD));
7263 for (; i < WidenNumElts / GCD; ++i)
7264 Parts.push_back(DAG.getPOISON(PartVT));
7265
7266 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
7267 }
7268
7269 // Use VECTOR_SHUFFLE to combine new vector from 'ReverseVal' for
7270 // fixed-vectors.
7271 SmallVector<int, 16> Mask(WidenNumElts, -1);
7272 std::iota(Mask.begin(), Mask.begin() + VTNumElts, IdxVal);
7273
7274 return DAG.getVectorShuffle(WidenVT, dl, ReverseVal, DAG.getPOISON(WidenVT),
7275 Mask);
7276}
7277
7278SDValue DAGTypeLegalizer::WidenVecRes_GET_ACTIVE_LANE_MASK(SDNode *N) {
7279 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7280 return DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, SDLoc(N), NVT, N->ops());
7281}
7282
7283SDValue DAGTypeLegalizer::WidenVecRes_SETCC(SDNode *N) {
7284 assert(N->getValueType(0).isVector() &&
7285 N->getOperand(0).getValueType().isVector() &&
7286 "Operands must be vectors");
7287 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7288 ElementCount WidenEC = WidenVT.getVectorElementCount();
7289
7290 SDValue InOp1 = N->getOperand(0);
7291 EVT InVT = InOp1.getValueType();
7292 assert(InVT.isVector() && "can not widen non-vector type");
7293 EVT WidenInVT =
7294 EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), WidenEC);
7295
7296 // The input and output types often differ here, and it could be that while
7297 // we'd prefer to widen the result type, the input operands have been split.
7298 // In this case, we also need to split the result of this node as well.
7299 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector) {
7300 SDValue SplitVSetCC = SplitVecOp_VSETCC(N);
7301 SDValue Res = ModifyToType(SplitVSetCC, WidenVT);
7302 return Res;
7303 }
7304
7305 // If the inputs also widen, handle them directly. Otherwise widen by hand.
7306 SDValue InOp2 = N->getOperand(1);
7307 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
7308 InOp1 = GetWidenedVector(InOp1);
7309 InOp2 = GetWidenedVector(InOp2);
7310 } else {
7311 SDValue Poison = DAG.getPOISON(WidenInVT);
7312 SDValue ZeroIdx = DAG.getVectorIdxConstant(0, SDLoc(N));
7313 InOp1 = DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), WidenInVT, Poison,
7314 InOp1, ZeroIdx);
7315 InOp2 = DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), WidenInVT, Poison,
7316 InOp2, ZeroIdx);
7317 }
7318
7319 // Assume that the input and output will be widen appropriately. If not,
7320 // we will have to unroll it at some point.
7321 assert(InOp1.getValueType() == WidenInVT &&
7322 InOp2.getValueType() == WidenInVT &&
7323 "Input not widened to expected type!");
7324 (void)WidenInVT;
7325 if (N->getOpcode() == ISD::VP_SETCC) {
7326 SDValue Mask =
7327 GetWidenedMask(N->getOperand(3), WidenVT.getVectorElementCount());
7328 return DAG.getNode(ISD::VP_SETCC, SDLoc(N), WidenVT, InOp1, InOp2,
7329 N->getOperand(2), Mask, N->getOperand(4));
7330 }
7331 return DAG.getNode(ISD::SETCC, SDLoc(N), WidenVT, InOp1, InOp2,
7332 N->getOperand(2));
7333}
7334
7335SDValue DAGTypeLegalizer::WidenVecRes_STRICT_FSETCC(SDNode *N) {
7336 assert(N->getValueType(0).isVector() &&
7337 N->getOperand(1).getValueType().isVector() &&
7338 "Operands must be vectors");
7339 EVT VT = N->getValueType(0);
7340 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7341 unsigned WidenNumElts = WidenVT.getVectorNumElements();
7342 unsigned NumElts = VT.getVectorNumElements();
7343 EVT EltVT = VT.getVectorElementType();
7344
7345 SDLoc dl(N);
7346 SDValue Chain = N->getOperand(0);
7347 SDValue LHS = N->getOperand(1);
7348 SDValue RHS = N->getOperand(2);
7349 SDValue CC = N->getOperand(3);
7350 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
7351
7352 // Fully unroll and reassemble.
7353 SmallVector<SDValue, 8> Scalars(WidenNumElts, DAG.getPOISON(EltVT));
7354 SmallVector<SDValue, 8> Chains(NumElts);
7355 for (unsigned i = 0; i != NumElts; ++i) {
7356 SDValue LHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, LHS, i);
7357 SDValue RHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, RHS, i);
7358
7359 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
7360 {Chain, LHSElem, RHSElem, CC});
7361 Chains[i] = Scalars[i].getValue(1);
7362 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
7363 DAG.getBoolConstant(true, dl, EltVT, VT),
7364 DAG.getBoolConstant(false, dl, EltVT, VT));
7365 }
7366
7367 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
7368 ReplaceValueWith(SDValue(N, 1), NewChain);
7369
7370 return DAG.getBuildVector(WidenVT, dl, Scalars);
7371}
7372
7373//===----------------------------------------------------------------------===//
7374// Widen Vector Operand
7375//===----------------------------------------------------------------------===//
7376bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned OpNo) {
7377 LLVM_DEBUG(dbgs() << "Widen node operand " << OpNo << ": "; N->dump(&DAG));
7378 SDValue Res = SDValue();
7379
7380 // See if the target wants to custom widen this node.
7381 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
7382 return false;
7383
7384 switch (N->getOpcode()) {
7385 default:
7386#ifndef NDEBUG
7387 dbgs() << "WidenVectorOperand op #" << OpNo << ": ";
7388 N->dump(&DAG);
7389 dbgs() << "\n";
7390#endif
7391 report_fatal_error("Do not know how to widen this operator's operand!");
7392
7393 case ISD::BITCAST: Res = WidenVecOp_BITCAST(N); break;
7394 case ISD::FAKE_USE:
7395 Res = WidenVecOp_FAKE_USE(N);
7396 break;
7397 case ISD::CONCAT_VECTORS: Res = WidenVecOp_CONCAT_VECTORS(N); break;
7398 case ISD::INSERT_SUBVECTOR: Res = WidenVecOp_INSERT_SUBVECTOR(N); break;
7399 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecOp_EXTRACT_SUBVECTOR(N); break;
7400 case ISD::EXTRACT_VECTOR_ELT: Res = WidenVecOp_EXTRACT_VECTOR_ELT(N); break;
7401 case ISD::STORE: Res = WidenVecOp_STORE(N); break;
7402 case ISD::VP_STORE: Res = WidenVecOp_VP_STORE(N, OpNo); break;
7403 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
7404 Res = WidenVecOp_VP_STRIDED_STORE(N, OpNo);
7405 break;
7409 Res = WidenVecOp_EXTEND_VECTOR_INREG(N);
7410 break;
7411 case ISD::MSTORE: Res = WidenVecOp_MSTORE(N, OpNo); break;
7412 case ISD::MGATHER: Res = WidenVecOp_MGATHER(N, OpNo); break;
7413 case ISD::MSCATTER: Res = WidenVecOp_MSCATTER(N, OpNo); break;
7414 case ISD::VP_SCATTER: Res = WidenVecOp_VP_SCATTER(N, OpNo); break;
7415 case ISD::SETCC: Res = WidenVecOp_SETCC(N); break;
7416 case ISD::STRICT_FSETCC:
7417 case ISD::STRICT_FSETCCS: Res = WidenVecOp_STRICT_FSETCC(N); break;
7418 case ISD::VSELECT: Res = WidenVecOp_VSELECT(N); break;
7419 case ISD::FLDEXP:
7420 case ISD::FCOPYSIGN:
7421 case ISD::LROUND:
7422 case ISD::LLROUND:
7423 case ISD::LRINT:
7424 case ISD::LLRINT:
7425 Res = WidenVecOp_UnrollVectorOp(N);
7426 break;
7427 case ISD::IS_FPCLASS: Res = WidenVecOp_IS_FPCLASS(N); break;
7428
7429 case ISD::ANY_EXTEND:
7430 case ISD::SIGN_EXTEND:
7431 case ISD::ZERO_EXTEND:
7432 Res = WidenVecOp_EXTEND(N);
7433 break;
7434
7435 case ISD::SCMP:
7436 case ISD::UCMP:
7437 Res = WidenVecOp_CMP(N);
7438 break;
7439
7440 case ISD::FP_EXTEND:
7442 case ISD::FP_ROUND:
7444 case ISD::FP_TO_SINT:
7446 case ISD::FP_TO_UINT:
7448 case ISD::SINT_TO_FP:
7450 case ISD::UINT_TO_FP:
7452 case ISD::TRUNCATE:
7454 Res = WidenVecOp_Convert(N);
7455 break;
7456
7459 Res = WidenVecOp_FP_TO_XINT_SAT(N);
7460 break;
7461
7464 case ISD::VECREDUCE_ADD:
7465 case ISD::VECREDUCE_MUL:
7466 case ISD::VECREDUCE_AND:
7467 case ISD::VECREDUCE_OR:
7468 case ISD::VECREDUCE_XOR:
7477 Res = WidenVecOp_VECREDUCE(N);
7478 break;
7481 Res = WidenVecOp_VECREDUCE_SEQ(N);
7482 break;
7483 case ISD::VP_REDUCE_FADD:
7484 case ISD::VP_REDUCE_SEQ_FADD:
7485 case ISD::VP_REDUCE_FMUL:
7486 case ISD::VP_REDUCE_SEQ_FMUL:
7487 case ISD::VP_REDUCE_ADD:
7488 case ISD::VP_REDUCE_MUL:
7489 case ISD::VP_REDUCE_AND:
7490 case ISD::VP_REDUCE_OR:
7491 case ISD::VP_REDUCE_XOR:
7492 case ISD::VP_REDUCE_SMAX:
7493 case ISD::VP_REDUCE_SMIN:
7494 case ISD::VP_REDUCE_UMAX:
7495 case ISD::VP_REDUCE_UMIN:
7496 case ISD::VP_REDUCE_FMAX:
7497 case ISD::VP_REDUCE_FMIN:
7498 case ISD::VP_REDUCE_FMAXIMUM:
7499 case ISD::VP_REDUCE_FMINIMUM:
7500 Res = WidenVecOp_VP_REDUCE(N);
7501 break;
7502 case ISD::VP_CTTZ_ELTS:
7503 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
7504 Res = WidenVecOp_VP_CttzElements(N);
7505 break;
7507 Res = WidenVecOp_VECTOR_FIND_LAST_ACTIVE(N);
7508 break;
7509 }
7510
7511 // If Res is null, the sub-method took care of registering the result.
7512 if (!Res.getNode()) return false;
7513
7514 // If the result is N, the sub-method updated N in place. Tell the legalizer
7515 // core about this.
7516 if (Res.getNode() == N)
7517 return true;
7518
7519
7520 if (N->isStrictFPOpcode())
7521 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
7522 "Invalid operand expansion");
7523 else
7524 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
7525 "Invalid operand expansion");
7526
7527 ReplaceValueWith(SDValue(N, 0), Res);
7528 return false;
7529}
7530
7531SDValue DAGTypeLegalizer::WidenVecOp_EXTEND(SDNode *N) {
7532 SDLoc DL(N);
7533 EVT VT = N->getValueType(0);
7534
7535 SDValue InOp = N->getOperand(0);
7536 assert(getTypeAction(InOp.getValueType()) ==
7538 "Unexpected type action");
7539 InOp = GetWidenedVector(InOp);
7542 "Input wasn't widened!");
7543
7544 // We may need to further widen the operand until it has the same total
7545 // vector size as the result.
7546 EVT InVT = InOp.getValueType();
7547 if (InVT.getSizeInBits() != VT.getSizeInBits()) {
7548 EVT InEltVT = InVT.getVectorElementType();
7549 for (EVT FixedVT : MVT::vector_valuetypes()) {
7550 EVT FixedEltVT = FixedVT.getVectorElementType();
7551 if (TLI.isTypeLegal(FixedVT) &&
7552 FixedVT.getSizeInBits() == VT.getSizeInBits() &&
7553 FixedEltVT == InEltVT) {
7554 assert(FixedVT.getVectorNumElements() >= VT.getVectorNumElements() &&
7555 "Not enough elements in the fixed type for the operand!");
7556 assert(FixedVT.getVectorNumElements() != InVT.getVectorNumElements() &&
7557 "We can't have the same type as we started with!");
7558 if (FixedVT.getVectorNumElements() > InVT.getVectorNumElements())
7559 InOp = DAG.getInsertSubvector(DL, DAG.getPOISON(FixedVT), InOp, 0);
7560 else
7561 InOp = DAG.getExtractSubvector(DL, FixedVT, InOp, 0);
7562 break;
7563 }
7564 }
7565 InVT = InOp.getValueType();
7566 if (InVT.getSizeInBits() != VT.getSizeInBits())
7567 // We couldn't find a legal vector type that was a widening of the input
7568 // and could be extended in-register to the result type, so we have to
7569 // scalarize.
7570 return WidenVecOp_Convert(N);
7571 }
7572
7573 // Use special DAG nodes to represent the operation of extending the
7574 // low lanes.
7575 switch (N->getOpcode()) {
7576 default:
7577 llvm_unreachable("Extend legalization on extend operation!");
7578 case ISD::ANY_EXTEND:
7579 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, VT, InOp);
7580 case ISD::SIGN_EXTEND:
7581 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, VT, InOp);
7582 case ISD::ZERO_EXTEND:
7583 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, VT, InOp);
7584 }
7585}
7586
7587SDValue DAGTypeLegalizer::WidenVecOp_CMP(SDNode *N) {
7588 SDLoc dl(N);
7589
7590 EVT OpVT = N->getOperand(0).getValueType();
7591 EVT ResVT = N->getValueType(0);
7592 SDValue LHS = GetWidenedVector(N->getOperand(0));
7593 SDValue RHS = GetWidenedVector(N->getOperand(1));
7594
7595 // 1. EXTRACT_SUBVECTOR
7596 // 2. SIGN_EXTEND/ZERO_EXTEND
7597 // 3. CMP
7598 LHS = DAG.getExtractSubvector(dl, OpVT, LHS, 0);
7599 RHS = DAG.getExtractSubvector(dl, OpVT, RHS, 0);
7600
7601 // At this point the result type is guaranteed to be valid, so we can use it
7602 // as the operand type by extending it appropriately
7603 ISD::NodeType ExtendOpcode =
7604 N->getOpcode() == ISD::SCMP ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
7605 LHS = DAG.getNode(ExtendOpcode, dl, ResVT, LHS);
7606 RHS = DAG.getNode(ExtendOpcode, dl, ResVT, RHS);
7607
7608 return DAG.getNode(N->getOpcode(), dl, ResVT, LHS, RHS);
7609}
7610
7611SDValue DAGTypeLegalizer::WidenVecOp_UnrollVectorOp(SDNode *N) {
7612 // The result (and first input) is legal, but the second input is illegal.
7613 // We can't do much to fix that, so just unroll and let the extracts off of
7614 // the second input be widened as needed later.
7615 return DAG.UnrollVectorOp(N);
7616}
7617
7618SDValue DAGTypeLegalizer::WidenVecOp_IS_FPCLASS(SDNode *N) {
7619 SDLoc DL(N);
7620 EVT ResultVT = N->getValueType(0);
7621 SDValue Test = N->getOperand(1);
7622 SDValue WideArg = GetWidenedVector(N->getOperand(0));
7623
7624 // Process this node similarly to SETCC.
7625 EVT WideResultVT = getSetCCResultType(WideArg.getValueType());
7626 if (ResultVT.getScalarType() == MVT::i1)
7627 WideResultVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
7628 WideResultVT.getVectorNumElements());
7629
7630 SDValue WideNode = DAG.getNode(ISD::IS_FPCLASS, DL, WideResultVT,
7631 {WideArg, Test}, N->getFlags());
7632
7633 // Extract the needed results from the result vector.
7634 EVT ResVT =
7635 EVT::getVectorVT(*DAG.getContext(), WideResultVT.getVectorElementType(),
7636 ResultVT.getVectorNumElements());
7637 SDValue CC = DAG.getExtractSubvector(DL, ResVT, WideNode, 0);
7638
7639 EVT OpVT = N->getOperand(0).getValueType();
7640 ISD::NodeType ExtendCode =
7641 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
7642 return DAG.getNode(ExtendCode, DL, ResultVT, CC);
7643}
7644
7645SDValue DAGTypeLegalizer::WidenVecOp_Convert(SDNode *N) {
7646 // Since the result is legal and the input is illegal.
7647 EVT VT = N->getValueType(0);
7648 EVT EltVT = VT.getVectorElementType();
7649 SDLoc dl(N);
7650 SDValue InOp = N->getOperand(N->isStrictFPOpcode() ? 1 : 0);
7651 assert(getTypeAction(InOp.getValueType()) ==
7653 "Unexpected type action");
7654 InOp = GetWidenedVector(InOp);
7655 EVT InVT = InOp.getValueType();
7656 unsigned Opcode = N->getOpcode();
7657
7658 // See if a widened result type would be legal, if so widen the node.
7659 // FIXME: This isn't safe for StrictFP. Other optimization here is needed.
7660 EVT WideVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
7661 InVT.getVectorElementCount());
7662 if (TLI.isTypeLegal(WideVT) && !N->isStrictFPOpcode()) {
7663 SDValue Res;
7664 if (N->isStrictFPOpcode()) {
7665 if (Opcode == ISD::STRICT_FP_ROUND)
7666 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
7667 { N->getOperand(0), InOp, N->getOperand(2) });
7668 else
7669 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
7670 { N->getOperand(0), InOp });
7671 // Legalize the chain result - switch anything that used the old chain to
7672 // use the new one.
7673 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7674 } else {
7675 if (Opcode == ISD::FP_ROUND || Opcode == ISD::CONVERT_FROM_ARBITRARY_FP)
7676 Res = DAG.getNode(Opcode, dl, WideVT, InOp, N->getOperand(1));
7677 else
7678 Res = DAG.getNode(Opcode, dl, WideVT, InOp);
7679 }
7680 return DAG.getExtractSubvector(dl, VT, Res, 0);
7681 }
7682
7683 EVT InEltVT = InVT.getVectorElementType();
7684
7685 // Unroll the convert into some scalar code and create a nasty build vector.
7686 unsigned NumElts = VT.getVectorNumElements();
7688 if (N->isStrictFPOpcode()) {
7689 SmallVector<SDValue, 4> NewOps(N->ops());
7690 SmallVector<SDValue, 32> OpChains;
7691 for (unsigned i=0; i < NumElts; ++i) {
7692 NewOps[1] = DAG.getExtractVectorElt(dl, InEltVT, InOp, i);
7693 Ops[i] = DAG.getNode(Opcode, dl, { EltVT, MVT::Other }, NewOps);
7694 OpChains.push_back(Ops[i].getValue(1));
7695 }
7696 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OpChains);
7697 ReplaceValueWith(SDValue(N, 1), NewChain);
7698 } else {
7699 for (unsigned i = 0; i < NumElts; ++i) {
7700 SDValue Elt = DAG.getExtractVectorElt(dl, InEltVT, InOp, i);
7701 if (Opcode == ISD::FP_ROUND || Opcode == ISD::CONVERT_FROM_ARBITRARY_FP)
7702 Ops[i] = DAG.getNode(Opcode, dl, EltVT, Elt, N->getOperand(1));
7703 else
7704 Ops[i] = DAG.getNode(Opcode, dl, EltVT, Elt);
7705 }
7706 }
7707
7708 return DAG.getBuildVector(VT, dl, Ops);
7709}
7710
7711SDValue DAGTypeLegalizer::WidenVecOp_FP_TO_XINT_SAT(SDNode *N) {
7712 EVT DstVT = N->getValueType(0);
7713 SDValue Src = GetWidenedVector(N->getOperand(0));
7714 EVT SrcVT = Src.getValueType();
7715 ElementCount WideNumElts = SrcVT.getVectorElementCount();
7716 SDLoc dl(N);
7717
7718 // See if a widened result type would be legal, if so widen the node.
7719 EVT WideDstVT = EVT::getVectorVT(*DAG.getContext(),
7720 DstVT.getVectorElementType(), WideNumElts);
7721 if (TLI.isTypeLegal(WideDstVT)) {
7722 SDValue Res =
7723 DAG.getNode(N->getOpcode(), dl, WideDstVT, Src, N->getOperand(1));
7724 return DAG.getNode(
7725 ISD::EXTRACT_SUBVECTOR, dl, DstVT, Res,
7726 DAG.getConstant(0, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
7727 }
7728
7729 // Give up and unroll.
7730 return DAG.UnrollVectorOp(N);
7731}
7732
7733SDValue DAGTypeLegalizer::WidenVecOp_BITCAST(SDNode *N) {
7734 EVT VT = N->getValueType(0);
7735 SDValue InOp = GetWidenedVector(N->getOperand(0));
7736 EVT InWidenVT = InOp.getValueType();
7737 SDLoc dl(N);
7738
7739 // Check if we can convert between two legal vector types and extract.
7740 TypeSize InWidenSize = InWidenVT.getSizeInBits();
7741 TypeSize Size = VT.getSizeInBits();
7742 // x86mmx is not an acceptable vector element type, so don't try.
7743 if (!VT.isVector() && VT != MVT::x86mmx &&
7744 InWidenSize.hasKnownScalarFactor(Size)) {
7745 unsigned NewNumElts = InWidenSize.getKnownScalarFactor(Size);
7746 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), VT, NewNumElts);
7747 if (TLI.isTypeLegal(NewVT)) {
7748 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
7749 return DAG.getExtractVectorElt(dl, VT, BitOp, 0);
7750 }
7751 }
7752
7753 // Handle a case like bitcast v12i8 -> v3i32. Normally that would get widened
7754 // to v16i8 -> v4i32, but for a target where v3i32 is legal but v12i8 is not,
7755 // we end up here. Handling the case here with EXTRACT_SUBVECTOR avoids
7756 // having to copy via memory.
7757 if (VT.isVector()) {
7758 EVT EltVT = VT.getVectorElementType();
7759 unsigned EltSize = EltVT.getFixedSizeInBits();
7760 if (InWidenSize.isKnownMultipleOf(EltSize)) {
7761 ElementCount NewNumElts =
7762 (InWidenVT.getVectorElementCount() * InWidenVT.getScalarSizeInBits())
7763 .divideCoefficientBy(EltSize);
7764 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NewNumElts);
7765 if (TLI.isTypeLegal(NewVT)) {
7766 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
7767 return DAG.getExtractSubvector(dl, VT, BitOp, 0);
7768 }
7769 }
7770 }
7771
7772 return CreateStackStoreLoad(InOp, VT);
7773}
7774
7775// Vectors with sizes that are not powers of 2 need to be widened to the
7776// next largest power of 2. For example, we may get a vector of 3 32-bit
7777// integers or of 6 16-bit integers, both of which have to be widened to a
7778// 128-bit vector.
7779SDValue DAGTypeLegalizer::WidenVecOp_FAKE_USE(SDNode *N) {
7780 SDValue WidenedOp = GetWidenedVector(N->getOperand(1));
7781 return DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, N->getOperand(0),
7782 WidenedOp);
7783}
7784
7785SDValue DAGTypeLegalizer::WidenVecOp_CONCAT_VECTORS(SDNode *N) {
7786 EVT VT = N->getValueType(0);
7787 EVT EltVT = VT.getVectorElementType();
7788 EVT InVT = N->getOperand(0).getValueType();
7789 SDLoc dl(N);
7790
7791 // If the widen width for this operand is the same as the width of the concat
7792 // and all but the first operand is undef, just use the widened operand.
7793 unsigned NumOperands = N->getNumOperands();
7794 if (VT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
7795 unsigned i;
7796 for (i = 1; i < NumOperands; ++i)
7797 if (!N->getOperand(i).isUndef())
7798 break;
7799
7800 if (i == NumOperands)
7801 return GetWidenedVector(N->getOperand(0));
7802 }
7803
7804 // Otherwise, fall back to a nasty build vector.
7805 unsigned NumElts = VT.getVectorNumElements();
7807
7808 unsigned NumInElts = InVT.getVectorNumElements();
7809
7810 unsigned Idx = 0;
7811 for (unsigned i=0; i < NumOperands; ++i) {
7812 SDValue InOp = N->getOperand(i);
7813 assert(getTypeAction(InOp.getValueType()) ==
7815 "Unexpected type action");
7816 InOp = GetWidenedVector(InOp);
7817 for (unsigned j = 0; j < NumInElts; ++j)
7818 Ops[Idx++] = DAG.getExtractVectorElt(dl, EltVT, InOp, j);
7819 }
7820 return DAG.getBuildVector(VT, dl, Ops);
7821}
7822
7823SDValue DAGTypeLegalizer::WidenVecOp_INSERT_SUBVECTOR(SDNode *N) {
7824 EVT VT = N->getValueType(0);
7825 SDValue SubVec = N->getOperand(1);
7826 SDValue InVec = N->getOperand(0);
7827
7828 EVT OrigVT = SubVec.getValueType();
7829 SubVec = GetWidenedVector(SubVec);
7830 EVT SubVT = SubVec.getValueType();
7831
7832 // Whether or not all the elements of the widened SubVec will be inserted into
7833 // valid indices of VT.
7834 bool IndicesValid = false;
7835 // If we statically know that VT can fit SubVT, the indices are valid.
7836 if (VT.knownBitsGE(SubVT))
7837 IndicesValid = true;
7838 else if (VT.isScalableVector() && SubVT.isFixedLengthVector()) {
7839 // Otherwise, if we're inserting a fixed vector into a scalable vector and
7840 // we know the minimum vscale we can work out if it's valid ourselves.
7841 Attribute Attr = DAG.getMachineFunction().getFunction().getFnAttribute(
7842 Attribute::VScaleRange);
7843 if (Attr.isValid()) {
7844 unsigned VScaleMin = Attr.getVScaleRangeMin();
7845 if (VT.getSizeInBits().getKnownMinValue() * VScaleMin >=
7846 SubVT.getFixedSizeInBits())
7847 IndicesValid = true;
7848 }
7849 }
7850
7851 if (!IndicesValid)
7853 "Don't know how to widen the operands for INSERT_SUBVECTOR");
7854
7855 SDLoc DL(N);
7856
7857 // We need to make sure that the indices are still valid, otherwise we might
7858 // widen what was previously well-defined to something undefined.
7859 if (InVec.isUndef() && N->getConstantOperandVal(2) == 0)
7860 return DAG.getNode(ISD::INSERT_SUBVECTOR, DL, VT, InVec, SubVec,
7861 N->getOperand(2));
7862
7863 if (OrigVT.isScalableVector()) {
7864 // When the widened types match, overwriting the start of a vector is
7865 // effectively a merge operation that can be implement as a vselect.
7866 if (SubVT == VT && N->getConstantOperandVal(2) == 0) {
7867 SDValue Mask =
7868 DAG.getMaskFromElementCount(DL, VT, OrigVT.getVectorElementCount());
7869 return DAG.getNode(ISD::VSELECT, DL, VT, Mask, SubVec, InVec);
7870 }
7871
7872 // Fallback to inserting through memory.
7873 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
7874 SDValue StackPtr = DAG.CreateStackTemporary(VT.getStoreSize(), Alignment);
7875 MachineFunction &MF = DAG.getMachineFunction();
7876 int FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
7877 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
7878
7879 MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
7882 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
7885
7886 // Write out the vector being inserting into.
7887 SDValue Ch =
7888 DAG.getStore(DAG.getEntryNode(), DL, InVec, StackPtr, StoreMMO);
7889
7890 // Build a mask to match the length of the sub-vector.
7891 SDValue Mask =
7892 DAG.getMaskFromElementCount(DL, SubVT, OrigVT.getVectorElementCount());
7893
7894 // Overwrite the sub-vector at the required offset.
7895 SDValue SubVecPtr =
7896 TLI.getVectorSubVecPointer(DAG, StackPtr, VT, OrigVT, N->getOperand(2));
7897 Ch = DAG.getMaskedStore(Ch, DL, SubVec, SubVecPtr,
7898 DAG.getPOISON(SubVecPtr.getValueType()), Mask, VT,
7899 StoreMMO, ISD::UNINDEXED, ISD::NON_EXTLOAD);
7900
7901 // Read back the result.
7902 return DAG.getLoad(VT, DL, Ch, StackPtr, LoadMMO);
7903 }
7904
7905 // If the operands can't be widened legally, just replace the INSERT_SUBVECTOR
7906 // with a series of INSERT_VECTOR_ELT
7907 unsigned Idx = N->getConstantOperandVal(2);
7908
7909 SDValue InsertElt = InVec;
7910 for (unsigned I = 0, E = OrigVT.getVectorNumElements(); I != E; ++I) {
7911 SDValue ExtractElt =
7912 DAG.getExtractVectorElt(DL, VT.getVectorElementType(), SubVec, I);
7913 InsertElt = DAG.getInsertVectorElt(DL, InsertElt, ExtractElt, I + Idx);
7914 }
7915
7916 return InsertElt;
7917}
7918
7919SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
7920 SDValue InOp = GetWidenedVector(N->getOperand(0));
7921 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SDLoc(N),
7922 N->getValueType(0), InOp, N->getOperand(1));
7923}
7924
7925SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
7926 SDValue InOp = GetWidenedVector(N->getOperand(0));
7927 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
7928 N->getValueType(0), InOp, N->getOperand(1));
7929}
7930
7931SDValue DAGTypeLegalizer::WidenVecOp_EXTEND_VECTOR_INREG(SDNode *N) {
7932 SDLoc DL(N);
7933 EVT ResVT = N->getValueType(0);
7934
7935 // Widen the input as requested by the legalizer.
7936 SDValue WideInOp = GetWidenedVector(N->getOperand(0));
7937 EVT WideInVT = WideInOp.getValueType();
7938
7939 // Simple case: if widened input is still smaller than or equal to result,
7940 // just use it directly.
7941 if (WideInVT.getSizeInBits() <= ResVT.getSizeInBits())
7942 return DAG.getNode(N->getOpcode(), DL, ResVT, WideInOp);
7943
7944 // EXTEND_VECTOR_INREG requires input bits <= result bits.
7945 // If widening makes the input larger than the original result, widen the
7946 // result to match, then extract back down.
7947 EVT ResEltVT = ResVT.getVectorElementType();
7948 unsigned EltBits = ResEltVT.getSizeInBits();
7949 assert((WideInVT.getSizeInBits() % EltBits) == 0 &&
7950 "Widened input size must be a multiple of result element size");
7951
7952 unsigned WideNumElts = WideInVT.getSizeInBits() / EltBits;
7953 EVT WideResVT = EVT::getVectorVT(*DAG.getContext(), ResEltVT, WideNumElts);
7954
7955 SDValue WideRes = DAG.getNode(N->getOpcode(), DL, WideResVT, WideInOp);
7956 return DAG.getExtractSubvector(DL, ResVT, WideRes, 0);
7957}
7958
7959SDValue DAGTypeLegalizer::WidenVecOp_STORE(SDNode *N) {
7960 // We have to widen the value, but we want only to store the original
7961 // vector type.
7962 StoreSDNode *ST = cast<StoreSDNode>(N);
7963
7964 if (!ST->getMemoryVT().getScalarType().isByteSized())
7965 return TLI.scalarizeVectorStore(ST, DAG);
7966
7967 if (ST->isTruncatingStore())
7968 return TLI.scalarizeVectorStore(ST, DAG);
7969
7970 // Generate a vector-predicated store if it is custom/legal on the target.
7971 // To avoid possible recursion, only do this if the widened mask type is
7972 // legal.
7973 // FIXME: Not all targets may support EVL in VP_STORE. These will have been
7974 // removed from the IR by the ExpandVectorPredication pass but we're
7975 // reintroducing them here.
7976 SDValue StVal = ST->getValue();
7977 EVT StVT = StVal.getValueType();
7978 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), StVT);
7979 EVT WideMaskVT = getSetCCResultType(WideVT);
7980
7981 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
7982 TLI.isTypeLegal(WideMaskVT)) {
7983 // Widen the value.
7984 SDLoc DL(N);
7985 StVal = GetWidenedVector(StVal);
7986 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
7987 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
7988 StVT.getVectorElementCount());
7989 return DAG.getStoreVP(ST->getChain(), DL, StVal, ST->getBasePtr(),
7990 ST->getOffset(), Mask, EVL, StVT, ST->getMemOperand(),
7991 ST->getAddressingMode());
7992 }
7993
7995 if (GenWidenVectorStores(StChain, ST)) {
7996 if (StChain.size() == 1)
7997 return StChain[0];
7998
7999 return DAG.getNode(ISD::TokenFactor, SDLoc(ST), MVT::Other, StChain);
8000 }
8001
8002 if (StVT.isVector()) {
8003 // If all else fails replace the store with a wide masked store.
8004 SDLoc DL(N);
8005 SDValue WideStVal = GetWidenedVector(StVal);
8006 SDValue Mask =
8007 DAG.getMaskFromElementCount(DL, WideVT, StVT.getVectorElementCount());
8008
8009 return DAG.getMaskedStore(ST->getChain(), DL, WideStVal, ST->getBasePtr(),
8010 ST->getOffset(), Mask, ST->getMemoryVT(),
8011 ST->getMemOperand(), ST->getAddressingMode(),
8012 ST->isTruncatingStore());
8013 }
8014
8015 report_fatal_error("Unable to widen vector store");
8016}
8017
8018SDValue DAGTypeLegalizer::WidenVecOp_VP_STORE(SDNode *N, unsigned OpNo) {
8019 assert((OpNo == 1 || OpNo == 3) &&
8020 "Can widen only data or mask operand of vp_store");
8021 VPStoreSDNode *ST = cast<VPStoreSDNode>(N);
8022 SDValue Mask = ST->getMask();
8023 SDValue StVal = ST->getValue();
8024 SDLoc dl(N);
8025
8026 if (OpNo == 1) {
8027 // Widen the value.
8028 StVal = GetWidenedVector(StVal);
8029
8030 // We only handle the case where the mask needs widening to an
8031 // identically-sized type as the vector inputs.
8032 assert(getTypeAction(Mask.getValueType()) ==
8034 "Unable to widen VP store");
8035 Mask = GetWidenedVector(Mask);
8036 } else {
8037 Mask = GetWidenedVector(Mask);
8038
8039 // We only handle the case where the stored value needs widening to an
8040 // identically-sized type as the mask.
8041 assert(getTypeAction(StVal.getValueType()) ==
8043 "Unable to widen VP store");
8044 StVal = GetWidenedVector(StVal);
8045 }
8046
8047 assert(Mask.getValueType().getVectorElementCount() ==
8049 "Mask and data vectors should have the same number of elements");
8050 return DAG.getStoreVP(ST->getChain(), dl, StVal, ST->getBasePtr(),
8051 ST->getOffset(), Mask, ST->getVectorLength(),
8052 ST->getMemoryVT(), ST->getMemOperand(),
8053 ST->getAddressingMode(), ST->isTruncatingStore(),
8054 ST->isCompressingStore());
8055}
8056
8057SDValue DAGTypeLegalizer::WidenVecOp_VP_STRIDED_STORE(SDNode *N,
8058 unsigned OpNo) {
8059 assert((OpNo == 1 || OpNo == 4) &&
8060 "Can widen only data or mask operand of vp_strided_store");
8061 VPStridedStoreSDNode *SST = cast<VPStridedStoreSDNode>(N);
8062 SDValue Mask = SST->getMask();
8063 SDValue StVal = SST->getValue();
8064 SDLoc DL(N);
8065
8066 if (OpNo == 1)
8067 assert(getTypeAction(Mask.getValueType()) ==
8069 "Unable to widen VP strided store");
8070 else
8071 assert(getTypeAction(StVal.getValueType()) ==
8073 "Unable to widen VP strided store");
8074
8075 StVal = GetWidenedVector(StVal);
8076 Mask = GetWidenedVector(Mask);
8077
8079 Mask.getValueType().getVectorElementCount() &&
8080 "Data and mask vectors should have the same number of elements");
8081
8082 return DAG.getStridedStoreVP(
8083 SST->getChain(), DL, StVal, SST->getBasePtr(), SST->getOffset(),
8084 SST->getStride(), Mask, SST->getVectorLength(), SST->getMemoryVT(),
8085 SST->getMemOperand(), SST->getAddressingMode(), SST->isTruncatingStore(),
8086 SST->isCompressingStore());
8087}
8088
8089SDValue DAGTypeLegalizer::WidenVecOp_MSTORE(SDNode *N, unsigned OpNo) {
8090 assert((OpNo == 1 || OpNo == 4) &&
8091 "Can widen only data or mask operand of mstore");
8092 MaskedStoreSDNode *MST = cast<MaskedStoreSDNode>(N);
8093 SDValue Mask = MST->getMask();
8094 EVT MaskVT = Mask.getValueType();
8095 SDValue StVal = MST->getValue();
8096 EVT VT = StVal.getValueType();
8097 SDLoc dl(N);
8098
8099 EVT WideVT, WideMaskVT;
8100 if (OpNo == 1) {
8101 // Widen the value.
8102 StVal = GetWidenedVector(StVal);
8103
8104 WideVT = StVal.getValueType();
8105 WideMaskVT =
8106 EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(),
8107 WideVT.getVectorElementCount());
8108 } else {
8109 WideMaskVT = TLI.getTypeToTransformTo(*DAG.getContext(), MaskVT);
8110
8111 EVT ValueVT = StVal.getValueType();
8112 WideVT = EVT::getVectorVT(*DAG.getContext(), ValueVT.getVectorElementType(),
8113 WideMaskVT.getVectorElementCount());
8114 }
8115
8116 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
8117 TLI.isTypeLegal(WideMaskVT) && !MST->isCompressingStore()) {
8118 Mask = DAG.getInsertSubvector(dl, DAG.getPOISON(WideMaskVT), Mask, 0);
8119 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8121 return DAG.getStoreVP(MST->getChain(), dl, StVal, MST->getBasePtr(),
8122 MST->getOffset(), Mask, EVL, MST->getMemoryVT(),
8123 MST->getMemOperand(), MST->getAddressingMode());
8124 }
8125
8126 if (OpNo == 1) {
8127 // The mask should be widened as well.
8128 Mask = ModifyToType(Mask, WideMaskVT, true);
8129 } else {
8130 // Widen the mask.
8131 Mask = ModifyToType(Mask, WideMaskVT, true);
8132
8133 StVal = ModifyToType(StVal, WideVT);
8134 }
8135
8136 assert(Mask.getValueType().getVectorElementCount() ==
8138 "Mask and data vectors should have the same number of elements");
8139 return DAG.getMaskedStore(MST->getChain(), dl, StVal, MST->getBasePtr(),
8140 MST->getOffset(), Mask, MST->getMemoryVT(),
8141 MST->getMemOperand(), MST->getAddressingMode(),
8142 false, MST->isCompressingStore());
8143}
8144
8145SDValue DAGTypeLegalizer::WidenVecOp_MGATHER(SDNode *N, unsigned OpNo) {
8146 assert(OpNo == 4 && "Can widen only the index of mgather");
8147 auto *MG = cast<MaskedGatherSDNode>(N);
8148 SDValue DataOp = MG->getPassThru();
8149 SDValue Mask = MG->getMask();
8150 SDValue Scale = MG->getScale();
8151
8152 // Just widen the index. It's allowed to have extra elements.
8153 SDValue Index = GetWidenedVector(MG->getIndex());
8154
8155 SDLoc dl(N);
8156 SDValue Ops[] = {MG->getChain(), DataOp, Mask, MG->getBasePtr(), Index,
8157 Scale};
8158 SDValue Res = DAG.getMaskedGather(MG->getVTList(), MG->getMemoryVT(), dl, Ops,
8159 MG->getMemOperand(), MG->getIndexType(),
8160 MG->getExtensionType());
8161 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
8162 ReplaceValueWith(SDValue(N, 0), Res.getValue(0));
8163 return SDValue();
8164}
8165
8166SDValue DAGTypeLegalizer::WidenVecOp_MSCATTER(SDNode *N, unsigned OpNo) {
8167 MaskedScatterSDNode *MSC = cast<MaskedScatterSDNode>(N);
8168 SDValue DataOp = MSC->getValue();
8169 SDValue Mask = MSC->getMask();
8170 SDValue Index = MSC->getIndex();
8171 SDValue Scale = MSC->getScale();
8172 EVT WideMemVT = MSC->getMemoryVT();
8173
8174 if (OpNo == 1) {
8175 DataOp = GetWidenedVector(DataOp);
8176 unsigned NumElts = DataOp.getValueType().getVectorNumElements();
8177
8178 // Widen index.
8179 EVT IndexVT = Index.getValueType();
8180 EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
8181 IndexVT.getVectorElementType(), NumElts);
8182 Index = ModifyToType(Index, WideIndexVT);
8183
8184 // The mask should be widened as well.
8185 EVT MaskVT = Mask.getValueType();
8186 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
8187 MaskVT.getVectorElementType(), NumElts);
8188 Mask = ModifyToType(Mask, WideMaskVT, true);
8189
8190 // Widen the MemoryType
8191 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
8192 MSC->getMemoryVT().getScalarType(), NumElts);
8193 } else if (OpNo == 4) {
8194 // Just widen the index. It's allowed to have extra elements.
8195 Index = GetWidenedVector(Index);
8196 } else
8197 llvm_unreachable("Can't widen this operand of mscatter");
8198
8199 SDValue Ops[] = {MSC->getChain(), DataOp, Mask, MSC->getBasePtr(), Index,
8200 Scale};
8201 return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N),
8202 Ops, MSC->getMemOperand(), MSC->getIndexType(),
8203 MSC->isTruncatingStore());
8204}
8205
8206SDValue DAGTypeLegalizer::WidenVecOp_VP_SCATTER(SDNode *N, unsigned OpNo) {
8207 VPScatterSDNode *VPSC = cast<VPScatterSDNode>(N);
8208 SDValue DataOp = VPSC->getValue();
8209 SDValue Mask = VPSC->getMask();
8210 SDValue Index = VPSC->getIndex();
8211 SDValue Scale = VPSC->getScale();
8212 EVT WideMemVT = VPSC->getMemoryVT();
8213
8214 if (OpNo == 1) {
8215 DataOp = GetWidenedVector(DataOp);
8216 Index = GetWidenedVector(Index);
8217 const auto WideEC = DataOp.getValueType().getVectorElementCount();
8218 Mask = GetWidenedMask(Mask, WideEC);
8219 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
8220 VPSC->getMemoryVT().getScalarType(), WideEC);
8221 } else if (OpNo == 3) {
8222 // Just widen the index. It's allowed to have extra elements.
8223 Index = GetWidenedVector(Index);
8224 } else
8225 llvm_unreachable("Can't widen this operand of VP_SCATTER");
8226
8227 SDValue Ops[] = {
8228 VPSC->getChain(), DataOp, VPSC->getBasePtr(), Index, Scale, Mask,
8229 VPSC->getVectorLength()};
8230 return DAG.getScatterVP(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N), Ops,
8231 VPSC->getMemOperand(), VPSC->getIndexType());
8232}
8233
8234SDValue DAGTypeLegalizer::WidenVecOp_SETCC(SDNode *N) {
8235 SDValue InOp0 = GetWidenedVector(N->getOperand(0));
8236 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
8237 SDLoc dl(N);
8238 EVT VT = N->getValueType(0);
8239
8240 // WARNING: In this code we widen the compare instruction with garbage.
8241 // This garbage may contain denormal floats which may be slow. Is this a real
8242 // concern ? Should we zero the unused lanes if this is a float compare ?
8243
8244 // Get a new SETCC node to compare the newly widened operands.
8245 // Only some of the compared elements are legal.
8246 EVT SVT = getSetCCResultType(InOp0.getValueType());
8247 // The result type is legal, if its vXi1, keep vXi1 for the new SETCC.
8248 if (VT.getScalarType() == MVT::i1)
8249 SVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8250 SVT.getVectorElementCount());
8251
8252 SDValue WideSETCC = DAG.getNode(ISD::SETCC, SDLoc(N),
8253 SVT, InOp0, InOp1, N->getOperand(2));
8254
8255 // Extract the needed results from the result vector.
8256 EVT ResVT = EVT::getVectorVT(*DAG.getContext(),
8259 SDValue CC = DAG.getExtractSubvector(dl, ResVT, WideSETCC, 0);
8260
8261 EVT OpVT = N->getOperand(0).getValueType();
8262 ISD::NodeType ExtendCode =
8263 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
8264 return DAG.getNode(ExtendCode, dl, VT, CC);
8265}
8266
8267SDValue DAGTypeLegalizer::WidenVecOp_STRICT_FSETCC(SDNode *N) {
8268 SDValue Chain = N->getOperand(0);
8269 SDValue LHS = GetWidenedVector(N->getOperand(1));
8270 SDValue RHS = GetWidenedVector(N->getOperand(2));
8271 SDValue CC = N->getOperand(3);
8272 SDLoc dl(N);
8273
8274 EVT VT = N->getValueType(0);
8275 EVT EltVT = VT.getVectorElementType();
8276 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
8277 unsigned NumElts = VT.getVectorNumElements();
8278
8279 // Unroll into a build vector.
8280 SmallVector<SDValue, 8> Scalars(NumElts);
8281 SmallVector<SDValue, 8> Chains(NumElts);
8282
8283 for (unsigned i = 0; i != NumElts; ++i) {
8284 SDValue LHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, LHS, i);
8285 SDValue RHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, RHS, i);
8286
8287 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
8288 {Chain, LHSElem, RHSElem, CC});
8289 Chains[i] = Scalars[i].getValue(1);
8290 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
8291 DAG.getBoolConstant(true, dl, EltVT, VT),
8292 DAG.getBoolConstant(false, dl, EltVT, VT));
8293 }
8294
8295 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
8296 ReplaceValueWith(SDValue(N, 1), NewChain);
8297
8298 return DAG.getBuildVector(VT, dl, Scalars);
8299}
8300
8301static unsigned getExtendForIntVecReduction(unsigned Opc) {
8302 switch (Opc) {
8303 default:
8304 llvm_unreachable("Expected integer vector reduction");
8305 case ISD::VECREDUCE_ADD:
8306 case ISD::VECREDUCE_MUL:
8307 case ISD::VECREDUCE_AND:
8308 case ISD::VECREDUCE_OR:
8309 case ISD::VECREDUCE_XOR:
8310 return ISD::ANY_EXTEND;
8313 return ISD::SIGN_EXTEND;
8316 return ISD::ZERO_EXTEND;
8317 }
8318}
8319
8320SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE(SDNode *N) {
8321 SDLoc dl(N);
8322 SDValue Op = GetWidenedVector(N->getOperand(0));
8323 EVT VT = N->getValueType(0);
8324 EVT OrigVT = N->getOperand(0).getValueType();
8325 EVT WideVT = Op.getValueType();
8326 EVT ElemVT = OrigVT.getVectorElementType();
8327 SDNodeFlags Flags = N->getFlags();
8328
8329 unsigned Opc = N->getOpcode();
8330 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
8331 SDValue NeutralElem = DAG.getNeutralElement(BaseOpc, dl, ElemVT, Flags);
8332 assert(NeutralElem && "Neutral element must exist");
8333
8334 // Pad the vector with the neutral element.
8335 unsigned OrigElts = OrigVT.getVectorMinNumElements();
8336 unsigned WideElts = WideVT.getVectorMinNumElements();
8337
8338 // Generate a vp.reduce_op if it is custom/legal for the target. This avoids
8339 // needing to pad the source vector, because the inactive lanes can simply be
8340 // disabled and not contribute to the result.
8341 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opc);
8342 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WideVT)) {
8343 SDValue Start = NeutralElem;
8344 if (VT.isInteger())
8345 Start = DAG.getNode(getExtendForIntVecReduction(Opc), dl, VT, Start);
8346 assert(Start.getValueType() == VT);
8347 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8348 WideVT.getVectorElementCount());
8349 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
8350 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8351 OrigVT.getVectorElementCount());
8352 return DAG.getNode(*VPOpcode, dl, VT, {Start, Op, Mask, EVL}, Flags);
8353 }
8354
8355 if (WideVT.isScalableVector()) {
8356 unsigned GCD = std::gcd(OrigElts, WideElts);
8357 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
8359 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
8360 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
8361 Op = DAG.getInsertSubvector(dl, Op, SplatNeutral, Idx);
8362 return DAG.getNode(Opc, dl, VT, Op, Flags);
8363 }
8364
8365 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
8366 Op = DAG.getInsertVectorElt(dl, Op, NeutralElem, Idx);
8367
8368 return DAG.getNode(Opc, dl, VT, Op, Flags);
8369}
8370
8371SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE_SEQ(SDNode *N) {
8372 SDLoc dl(N);
8373 SDValue AccOp = N->getOperand(0);
8374 SDValue VecOp = N->getOperand(1);
8375 SDValue Op = GetWidenedVector(VecOp);
8376
8377 EVT VT = N->getValueType(0);
8378 EVT OrigVT = VecOp.getValueType();
8379 EVT WideVT = Op.getValueType();
8380 EVT ElemVT = OrigVT.getVectorElementType();
8381 SDNodeFlags Flags = N->getFlags();
8382
8383 unsigned Opc = N->getOpcode();
8384 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
8385 SDValue NeutralElem = DAG.getNeutralElement(BaseOpc, dl, ElemVT, Flags);
8386
8387 // Pad the vector with the neutral element.
8388 unsigned OrigElts = OrigVT.getVectorMinNumElements();
8389 unsigned WideElts = WideVT.getVectorMinNumElements();
8390
8391 // Generate a vp.reduce_op if it is custom/legal for the target. This avoids
8392 // needing to pad the source vector, because the inactive lanes can simply be
8393 // disabled and not contribute to the result.
8394 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opc);
8395 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WideVT)) {
8396 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8397 WideVT.getVectorElementCount());
8398 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
8399 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8400 OrigVT.getVectorElementCount());
8401 return DAG.getNode(*VPOpcode, dl, VT, {AccOp, Op, Mask, EVL}, Flags);
8402 }
8403
8404 if (WideVT.isScalableVector()) {
8405 unsigned GCD = std::gcd(OrigElts, WideElts);
8406 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
8408 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
8409 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
8410 Op = DAG.getInsertSubvector(dl, Op, SplatNeutral, Idx);
8411 return DAG.getNode(Opc, dl, VT, AccOp, Op, Flags);
8412 }
8413
8414 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
8415 Op = DAG.getInsertVectorElt(dl, Op, NeutralElem, Idx);
8416
8417 return DAG.getNode(Opc, dl, VT, AccOp, Op, Flags);
8418}
8419
8420SDValue DAGTypeLegalizer::WidenVecOp_VP_REDUCE(SDNode *N) {
8421 assert(N->isVPOpcode() && "Expected VP opcode");
8422
8423 SDLoc dl(N);
8424 SDValue Op = GetWidenedVector(N->getOperand(1));
8425 SDValue Mask = GetWidenedMask(N->getOperand(2),
8426 Op.getValueType().getVectorElementCount());
8427
8428 return DAG.getNode(N->getOpcode(), dl, N->getValueType(0),
8429 {N->getOperand(0), Op, Mask, N->getOperand(3)},
8430 N->getFlags());
8431}
8432
8433SDValue DAGTypeLegalizer::WidenVecOp_VSELECT(SDNode *N) {
8434 // This only gets called in the case that the left and right inputs and
8435 // result are of a legal odd vector type, and the condition is illegal i1 of
8436 // the same odd width that needs widening.
8437 EVT VT = N->getValueType(0);
8438 assert(VT.isVector() && !VT.isPow2VectorType() && isTypeLegal(VT));
8439
8440 SDValue Cond = GetWidenedVector(N->getOperand(0));
8441 SDValue LeftIn = DAG.WidenVector(N->getOperand(1), SDLoc(N));
8442 SDValue RightIn = DAG.WidenVector(N->getOperand(2), SDLoc(N));
8443 SDLoc DL(N);
8444
8445 SDValue Select = DAG.getNode(N->getOpcode(), DL, LeftIn.getValueType(), Cond,
8446 LeftIn, RightIn);
8447 return DAG.getExtractSubvector(DL, VT, Select, 0);
8448}
8449
8450SDValue DAGTypeLegalizer::WidenVecOp_VP_CttzElements(SDNode *N) {
8451 SDLoc DL(N);
8452 SDValue Source = GetWidenedVector(N->getOperand(0));
8453 EVT SrcVT = Source.getValueType();
8454 SDValue Mask =
8455 GetWidenedMask(N->getOperand(1), SrcVT.getVectorElementCount());
8456
8457 return DAG.getNode(N->getOpcode(), DL, N->getValueType(0),
8458 {Source, Mask, N->getOperand(2)}, N->getFlags());
8459}
8460
8461SDValue DAGTypeLegalizer::WidenVecOp_VECTOR_FIND_LAST_ACTIVE(SDNode *N) {
8462 SDLoc DL(N);
8463 SDValue Mask = N->getOperand(0);
8464 EVT OrigMaskVT = Mask.getValueType();
8465 SDValue WideMask = GetWidenedVector(Mask);
8466 EVT WideMaskVT = WideMask.getValueType();
8467
8468 // Pad the mask with zeros to ensure inactive lanes don't affect the result.
8469 unsigned OrigElts = OrigMaskVT.getVectorNumElements();
8470 unsigned WideElts = WideMaskVT.getVectorNumElements();
8471 if (OrigElts != WideElts) {
8472 SDValue ZeroMask = DAG.getConstant(0, DL, WideMaskVT);
8473 WideMask = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideMaskVT, ZeroMask,
8474 Mask, DAG.getVectorIdxConstant(0, DL));
8475 }
8476
8477 return DAG.getNode(ISD::VECTOR_FIND_LAST_ACTIVE, DL, N->getValueType(0),
8478 WideMask);
8479}
8480
8481//===----------------------------------------------------------------------===//
8482// Vector Widening Utilities
8483//===----------------------------------------------------------------------===//
8484
8485// Utility function to find the type to chop up a widen vector for load/store
8486// TLI: Target lowering used to determine legal types.
8487// Width: Width left need to load/store.
8488// WidenVT: The widen vector type to load to/store from
8489// Align: If 0, don't allow use of a wider type
8490// WidenEx: If Align is not 0, the amount additional we can load/store from.
8491
8492static std::optional<EVT> findMemType(SelectionDAG &DAG,
8493 const TargetLowering &TLI, unsigned Width,
8494 EVT WidenVT, unsigned Align = 0,
8495 unsigned WidenEx = 0) {
8496 EVT WidenEltVT = WidenVT.getVectorElementType();
8497 const bool Scalable = WidenVT.isScalableVector();
8498 unsigned WidenWidth = WidenVT.getSizeInBits().getKnownMinValue();
8499 unsigned WidenEltWidth = WidenEltVT.getSizeInBits();
8500 unsigned AlignInBits = Align*8;
8501
8502 EVT RetVT = WidenEltVT;
8503 // Don't bother looking for an integer type if the vector is scalable, skip
8504 // to vector types.
8505 if (!Scalable) {
8506 // If we have one element to load/store, return it.
8507 if (Width == WidenEltWidth)
8508 return RetVT;
8509
8510 // See if there is larger legal integer than the element type to load/store.
8511 for (EVT MemVT : reverse(MVT::integer_valuetypes())) {
8512 unsigned MemVTWidth = MemVT.getSizeInBits();
8513 if (MemVT.getSizeInBits() <= WidenEltWidth)
8514 break;
8515 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
8516 if ((Action == TargetLowering::TypeLegal ||
8518 (WidenWidth % MemVTWidth) == 0 &&
8519 isPowerOf2_32(WidenWidth / MemVTWidth) &&
8520 (MemVTWidth <= Width ||
8521 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
8522 if (MemVTWidth == WidenWidth)
8523 return MemVT;
8524 RetVT = MemVT;
8525 break;
8526 }
8527 }
8528 }
8529
8530 // See if there is a larger vector type to load/store that has the same vector
8531 // element type and is evenly divisible with the WidenVT.
8532 for (EVT MemVT : reverse(MVT::vector_valuetypes())) {
8533 // Skip vector MVTs which don't match the scalable property of WidenVT.
8534 if (Scalable != MemVT.isScalableVector())
8535 continue;
8536 unsigned MemVTWidth = MemVT.getSizeInBits().getKnownMinValue();
8537 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
8538 if ((Action == TargetLowering::TypeLegal ||
8540 WidenEltVT == MemVT.getVectorElementType() &&
8541 (WidenWidth % MemVTWidth) == 0 &&
8542 isPowerOf2_32(WidenWidth / MemVTWidth) &&
8543 (MemVTWidth <= Width ||
8544 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
8545 if (RetVT.getFixedSizeInBits() < MemVTWidth || MemVT == WidenVT)
8546 return MemVT;
8547 }
8548 }
8549
8550 // Using element-wise loads and stores for widening operations is not
8551 // supported for scalable vectors
8552 if (Scalable)
8553 return std::nullopt;
8554
8555 return RetVT;
8556}
8557
8558// Builds a vector type from scalar loads
8559// VecTy: Resulting Vector type
8560// LDOps: Load operators to build a vector type
8561// [Start,End) the list of loads to use.
8564 unsigned Start, unsigned End) {
8565 SDLoc dl(LdOps[Start]);
8566 EVT LdTy = LdOps[Start].getValueType();
8567 unsigned Width = VecTy.getSizeInBits();
8568 unsigned NumElts = Width / LdTy.getSizeInBits();
8569 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), LdTy, NumElts);
8570
8571 unsigned Idx = 1;
8572 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT,LdOps[Start]);
8573
8574 for (unsigned i = Start + 1; i != End; ++i) {
8575 EVT NewLdTy = LdOps[i].getValueType();
8576 if (NewLdTy != LdTy) {
8577 NumElts = Width / NewLdTy.getSizeInBits();
8578 NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewLdTy, NumElts);
8579 VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, VecOp);
8580 // Readjust position and vector position based on new load type.
8581 Idx = Idx * LdTy.getSizeInBits() / NewLdTy.getSizeInBits();
8582 LdTy = NewLdTy;
8583 }
8584 VecOp = DAG.getInsertVectorElt(dl, VecOp, LdOps[i], Idx++);
8585 }
8586 return DAG.getNode(ISD::BITCAST, dl, VecTy, VecOp);
8587}
8588
8589SDValue DAGTypeLegalizer::GenWidenVectorLoads(SmallVectorImpl<SDValue> &LdChain,
8590 LoadSDNode *LD) {
8591 // The strategy assumes that we can efficiently load power-of-two widths.
8592 // The routine chops the vector into the largest vector loads with the same
8593 // element type or scalar loads and then recombines it to the widen vector
8594 // type.
8595 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
8596 EVT LdVT = LD->getMemoryVT();
8597 SDLoc dl(LD);
8598 assert(LdVT.isVector() && WidenVT.isVector());
8599 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
8601
8602 // Load information
8603 SDValue Chain = LD->getChain();
8604 SDValue BasePtr = LD->getBasePtr();
8605 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
8606 AAMDNodes AAInfo = LD->getAAInfo();
8607
8608 TypeSize LdWidth = LdVT.getSizeInBits();
8609 TypeSize WidenWidth = WidenVT.getSizeInBits();
8610 TypeSize WidthDiff = WidenWidth - LdWidth;
8611 // Allow wider loads if they are sufficiently aligned to avoid memory faults
8612 // and if the original load is simple.
8613 unsigned LdAlign =
8614 (!LD->isSimple() || LdVT.isScalableVector()) ? 0 : LD->getAlign().value();
8615
8616 // Find the vector type that can load from.
8617 std::optional<EVT> FirstVT =
8618 findMemType(DAG, TLI, LdWidth.getKnownMinValue(), WidenVT, LdAlign,
8619 WidthDiff.getKnownMinValue());
8620
8621 if (!FirstVT)
8622 return SDValue();
8623
8624 SmallVector<EVT, 8> MemVTs;
8625 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
8626
8627 // Unless we're able to load in one instruction we must work out how to load
8628 // the remainder.
8629 if (!TypeSize::isKnownLE(LdWidth, FirstVTWidth)) {
8630 std::optional<EVT> NewVT = FirstVT;
8631 TypeSize RemainingWidth = LdWidth;
8632 TypeSize NewVTWidth = FirstVTWidth;
8633 do {
8634 RemainingWidth -= NewVTWidth;
8635 if (TypeSize::isKnownLT(RemainingWidth, NewVTWidth)) {
8636 // The current type we are using is too large. Find a better size.
8637 NewVT = findMemType(DAG, TLI, RemainingWidth.getKnownMinValue(),
8638 WidenVT, LdAlign, WidthDiff.getKnownMinValue());
8639 if (!NewVT)
8640 return SDValue();
8641 NewVTWidth = NewVT->getSizeInBits();
8642 }
8643 MemVTs.push_back(*NewVT);
8644 } while (TypeSize::isKnownGT(RemainingWidth, NewVTWidth));
8645 }
8646
8647 SDValue LdOp = DAG.getLoad(*FirstVT, dl, Chain, BasePtr, LD->getPointerInfo(),
8648 LD->getBaseAlign(), MMOFlags, AAInfo);
8649 LdChain.push_back(LdOp.getValue(1));
8650
8651 // Check if we can load the element with one instruction.
8652 if (MemVTs.empty())
8653 return coerceLoadedValue(LdOp, *FirstVT, WidenVT, LdWidth, FirstVTWidth, dl,
8654 DAG);
8655
8656 // Load vector by using multiple loads from largest vector to scalar.
8658 LdOps.push_back(LdOp);
8659
8660 uint64_t ScaledOffset = 0;
8661 MachinePointerInfo MPI = LD->getPointerInfo();
8662
8663 // First incremement past the first load.
8664 IncrementPointer(cast<LoadSDNode>(LdOp), *FirstVT, MPI, BasePtr,
8665 &ScaledOffset);
8666
8667 for (EVT MemVT : MemVTs) {
8668 Align NewAlign = ScaledOffset == 0
8669 ? LD->getBaseAlign()
8670 : commonAlignment(LD->getAlign(), ScaledOffset);
8671 SDValue L =
8672 DAG.getLoad(MemVT, dl, Chain, BasePtr, MPI, NewAlign, MMOFlags, AAInfo);
8673
8674 LdOps.push_back(L);
8675 LdChain.push_back(L.getValue(1));
8676 IncrementPointer(cast<LoadSDNode>(L), MemVT, MPI, BasePtr, &ScaledOffset);
8677 }
8678
8679 // Build the vector from the load operations.
8680 unsigned End = LdOps.size();
8681 if (!LdOps[0].getValueType().isVector())
8682 // All the loads are scalar loads.
8683 return BuildVectorFromScalar(DAG, WidenVT, LdOps, 0, End);
8684
8685 // If the load contains vectors, build the vector using concat vector.
8686 // All of the vectors used to load are power-of-2, and the scalar loads can be
8687 // combined to make a power-of-2 vector.
8688 SmallVector<SDValue, 16> ConcatOps(End);
8689 int i = End - 1;
8690 int Idx = End;
8691 EVT LdTy = LdOps[i].getValueType();
8692 // First, combine the scalar loads to a vector.
8693 if (!LdTy.isVector()) {
8694 for (--i; i >= 0; --i) {
8695 LdTy = LdOps[i].getValueType();
8696 if (LdTy.isVector())
8697 break;
8698 }
8699 ConcatOps[--Idx] = BuildVectorFromScalar(DAG, LdTy, LdOps, i + 1, End);
8700 }
8701
8702 ConcatOps[--Idx] = LdOps[i];
8703 for (--i; i >= 0; --i) {
8704 EVT NewLdTy = LdOps[i].getValueType();
8705 if (NewLdTy != LdTy) {
8706 // Create a larger vector.
8707 TypeSize LdTySize = LdTy.getSizeInBits();
8708 TypeSize NewLdTySize = NewLdTy.getSizeInBits();
8709 assert(NewLdTySize.isScalable() == LdTySize.isScalable() &&
8710 NewLdTySize.isKnownMultipleOf(LdTySize.getKnownMinValue()));
8711 unsigned NumOps =
8712 NewLdTySize.getKnownMinValue() / LdTySize.getKnownMinValue();
8714 unsigned j = 0;
8715 for (; j != End-Idx; ++j)
8716 WidenOps[j] = ConcatOps[Idx+j];
8717 for (; j != NumOps; ++j)
8718 WidenOps[j] = DAG.getPOISON(LdTy);
8719
8720 ConcatOps[End-1] = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewLdTy,
8721 WidenOps);
8722 Idx = End - 1;
8723 LdTy = NewLdTy;
8724 }
8725 ConcatOps[--Idx] = LdOps[i];
8726 }
8727
8728 if (WidenWidth == LdTy.getSizeInBits() * (End - Idx))
8729 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
8730 ArrayRef(&ConcatOps[Idx], End - Idx));
8731
8732 // We need to fill the rest with undefs to build the vector.
8733 unsigned NumOps =
8734 WidenWidth.getKnownMinValue() / LdTy.getSizeInBits().getKnownMinValue();
8736 SDValue UndefVal = DAG.getPOISON(LdTy);
8737 {
8738 unsigned i = 0;
8739 for (; i != End-Idx; ++i)
8740 WidenOps[i] = ConcatOps[Idx+i];
8741 for (; i != NumOps; ++i)
8742 WidenOps[i] = UndefVal;
8743 }
8744 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, WidenOps);
8745}
8746
8747SDValue
8748DAGTypeLegalizer::GenWidenVectorExtLoads(SmallVectorImpl<SDValue> &LdChain,
8749 LoadSDNode *LD,
8750 ISD::LoadExtType ExtType) {
8751 // For extension loads, it may not be more efficient to chop up the vector
8752 // and then extend it. Instead, we unroll the load and build a new vector.
8753 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
8754 EVT LdVT = LD->getMemoryVT();
8755 SDLoc dl(LD);
8756 assert(LdVT.isVector() && WidenVT.isVector());
8757 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
8758
8759 // Load information
8760 SDValue Chain = LD->getChain();
8761 SDValue BasePtr = LD->getBasePtr();
8762 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
8763 AAMDNodes AAInfo = LD->getAAInfo();
8764
8765 if (LdVT.isScalableVector())
8766 return SDValue();
8767
8768 EVT EltVT = WidenVT.getVectorElementType();
8769 EVT LdEltVT = LdVT.getVectorElementType();
8770 unsigned NumElts = LdVT.getVectorNumElements();
8771
8772 // Load each element and widen.
8773 unsigned WidenNumElts = WidenVT.getVectorNumElements();
8774 SmallVector<SDValue, 16> Ops(WidenNumElts);
8775 unsigned Increment = LdEltVT.getSizeInBits() / 8;
8776 Ops[0] =
8777 DAG.getExtLoad(ExtType, dl, EltVT, Chain, BasePtr, LD->getPointerInfo(),
8778 LdEltVT, LD->getBaseAlign(), MMOFlags, AAInfo);
8779 LdChain.push_back(Ops[0].getValue(1));
8780 unsigned i = 0, Offset = Increment;
8781 for (i=1; i < NumElts; ++i, Offset += Increment) {
8782 SDValue NewBasePtr =
8783 DAG.getObjectPtrOffset(dl, BasePtr, TypeSize::getFixed(Offset));
8784 Ops[i] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, NewBasePtr,
8785 LD->getPointerInfo().getWithOffset(Offset), LdEltVT,
8786 LD->getBaseAlign(), MMOFlags, AAInfo);
8787 LdChain.push_back(Ops[i].getValue(1));
8788 }
8789
8790 // Fill the rest with undefs.
8791 SDValue UndefVal = DAG.getPOISON(EltVT);
8792 for (; i != WidenNumElts; ++i)
8793 Ops[i] = UndefVal;
8794
8795 return DAG.getBuildVector(WidenVT, dl, Ops);
8796}
8797
8798bool DAGTypeLegalizer::GenWidenVectorStores(SmallVectorImpl<SDValue> &StChain,
8799 StoreSDNode *ST) {
8800 // The strategy assumes that we can efficiently store power-of-two widths.
8801 // The routine chops the vector into the largest vector stores with the same
8802 // element type or scalar stores.
8803 SDValue Chain = ST->getChain();
8804 SDValue BasePtr = ST->getBasePtr();
8805 MachineMemOperand::Flags MMOFlags = ST->getMemOperand()->getFlags();
8806 AAMDNodes AAInfo = ST->getAAInfo();
8807 SDValue ValOp = GetWidenedVector(ST->getValue());
8808 SDLoc dl(ST);
8809
8810 EVT StVT = ST->getMemoryVT();
8811 TypeSize StWidth = StVT.getSizeInBits();
8812 EVT ValVT = ValOp.getValueType();
8813 TypeSize ValWidth = ValVT.getSizeInBits();
8814 EVT ValEltVT = ValVT.getVectorElementType();
8815 unsigned ValEltWidth = ValEltVT.getFixedSizeInBits();
8816 assert(StVT.getVectorElementType() == ValEltVT);
8817 assert(StVT.isScalableVector() == ValVT.isScalableVector() &&
8818 "Mismatch between store and value types");
8819
8820 int Idx = 0; // current index to store
8821
8822 MachinePointerInfo MPI = ST->getPointerInfo();
8823 uint64_t ScaledOffset = 0;
8824
8825 // A breakdown of how to widen this vector store. Each element of the vector
8826 // is a memory VT combined with the number of times it is to be stored to,
8827 // e,g., v5i32 -> {{v2i32,2},{i32,1}}
8829
8830 while (StWidth.isNonZero()) {
8831 // Find the largest vector type we can store with.
8832 std::optional<EVT> NewVT =
8833 findMemType(DAG, TLI, StWidth.getKnownMinValue(), ValVT);
8834 if (!NewVT)
8835 return false;
8836 MemVTs.push_back({*NewVT, 0});
8837 TypeSize NewVTWidth = NewVT->getSizeInBits();
8838
8839 do {
8840 StWidth -= NewVTWidth;
8841 MemVTs.back().second++;
8842 } while (StWidth.isNonZero() && TypeSize::isKnownGE(StWidth, NewVTWidth));
8843 }
8844
8845 for (const auto &Pair : MemVTs) {
8846 EVT NewVT = Pair.first;
8847 unsigned Count = Pair.second;
8848 TypeSize NewVTWidth = NewVT.getSizeInBits();
8849
8850 if (NewVT.isVector()) {
8851 unsigned NumVTElts = NewVT.getVectorMinNumElements();
8852 do {
8853 Align NewAlign = ScaledOffset == 0
8854 ? ST->getBaseAlign()
8855 : commonAlignment(ST->getAlign(), ScaledOffset);
8856 SDValue EOp = DAG.getExtractSubvector(dl, NewVT, ValOp, Idx);
8857 SDValue PartStore = DAG.getStore(Chain, dl, EOp, BasePtr, MPI, NewAlign,
8858 MMOFlags, AAInfo);
8859 StChain.push_back(PartStore);
8860
8861 Idx += NumVTElts;
8862 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr,
8863 &ScaledOffset);
8864 } while (--Count);
8865 } else {
8866 // Cast the vector to the scalar type we can store.
8867 unsigned NumElts = ValWidth.getFixedValue() / NewVTWidth.getFixedValue();
8868 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewVT, NumElts);
8869 SDValue VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, ValOp);
8870 // Readjust index position based on new vector type.
8871 Idx = Idx * ValEltWidth / NewVTWidth.getFixedValue();
8872 do {
8873 SDValue EOp = DAG.getExtractVectorElt(dl, NewVT, VecOp, Idx++);
8874 SDValue PartStore = DAG.getStore(Chain, dl, EOp, BasePtr, MPI,
8875 ST->getBaseAlign(), MMOFlags, AAInfo);
8876 StChain.push_back(PartStore);
8877
8878 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr);
8879 } while (--Count);
8880 // Restore index back to be relative to the original widen element type.
8881 Idx = Idx * NewVTWidth.getFixedValue() / ValEltWidth;
8882 }
8883 }
8884
8885 return true;
8886}
8887
8888/// Modifies a vector input (widen or narrows) to a vector of NVT. The
8889/// input vector must have the same element type as NVT.
8890/// FillWithZeroes specifies that the vector should be widened with zeroes.
8891SDValue DAGTypeLegalizer::ModifyToType(SDValue InOp, EVT NVT,
8892 bool FillWithZeroes) {
8893 // Note that InOp might have been widened so it might already have
8894 // the right width or it might need be narrowed.
8895 EVT InVT = InOp.getValueType();
8897 "input and widen element type must match");
8898 assert(InVT.isScalableVector() == NVT.isScalableVector() &&
8899 "cannot modify scalable vectors in this way");
8900 SDLoc dl(InOp);
8901
8902 // Check if InOp already has the right width.
8903 if (InVT == NVT)
8904 return InOp;
8905
8906 ElementCount InEC = InVT.getVectorElementCount();
8907 ElementCount WidenEC = NVT.getVectorElementCount();
8908 if (WidenEC.hasKnownScalarFactor(InEC)) {
8909 unsigned NumConcat = WidenEC.getKnownScalarFactor(InEC);
8910 SmallVector<SDValue, 16> Ops(NumConcat);
8911 SDValue FillVal =
8912 FillWithZeroes ? DAG.getConstant(0, dl, InVT) : DAG.getPOISON(InVT);
8913 Ops[0] = InOp;
8914 for (unsigned i = 1; i != NumConcat; ++i)
8915 Ops[i] = FillVal;
8916
8917 return DAG.getNode(ISD::CONCAT_VECTORS, dl, NVT, Ops);
8918 }
8919
8920 if (InEC.hasKnownScalarFactor(WidenEC))
8921 return DAG.getExtractSubvector(dl, NVT, InOp, 0);
8922
8923 assert(!InVT.isScalableVector() && !NVT.isScalableVector() &&
8924 "Scalable vectors should have been handled already.");
8925
8926 unsigned InNumElts = InEC.getFixedValue();
8927 unsigned WidenNumElts = WidenEC.getFixedValue();
8928
8929 // Fall back to extract and build (+ mask, if padding with zeros).
8930 SmallVector<SDValue, 16> Ops(WidenNumElts);
8931 EVT EltVT = NVT.getVectorElementType();
8932 unsigned MinNumElts = std::min(WidenNumElts, InNumElts);
8933 unsigned Idx;
8934 for (Idx = 0; Idx < MinNumElts; ++Idx)
8935 Ops[Idx] = DAG.getExtractVectorElt(dl, EltVT, InOp, Idx);
8936
8937 SDValue UndefVal = DAG.getPOISON(EltVT);
8938 for (; Idx < WidenNumElts; ++Idx)
8939 Ops[Idx] = UndefVal;
8940
8941 SDValue Widened = DAG.getBuildVector(NVT, dl, Ops);
8942 if (!FillWithZeroes)
8943 return Widened;
8944
8945 assert(NVT.isInteger() &&
8946 "We expect to never want to FillWithZeroes for non-integral types.");
8947
8949 MaskOps.append(MinNumElts, DAG.getAllOnesConstant(dl, EltVT));
8950 MaskOps.append(WidenNumElts - MinNumElts, DAG.getConstant(0, dl, EltVT));
8951
8952 return DAG.getNode(ISD::AND, dl, NVT, Widened,
8953 DAG.getBuildVector(NVT, dl, MaskOps));
8954}
return SDValue()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static unsigned getExtendForIntVecReduction(SDNode *N)
static SDValue BuildVectorFromScalar(SelectionDAG &DAG, EVT VecTy, SmallVectorImpl< SDValue > &LdOps, unsigned Start, unsigned End)
static std::optional< EVT > findMemType(SelectionDAG &DAG, const TargetLowering &TLI, unsigned Width, EVT WidenVT, unsigned Align, unsigned WidenEx)
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 SDValue coerceLoadedValue(SDValue LdOp, EVT FirstVT, EVT WidenVT, TypeSize LdWidth, TypeSize FirstVTWidth, SDLoc dl, SelectionDAG &DAG)
Either return the same load or provide appropriate casts from the load and return that.
#define I(x, y, z)
Definition MD5.cpp:57
static bool isUndef(const MachineInstr &MI)
This file provides utility analysis objects describing memory locations.
MachineInstr unsigned OpIdx
uint64_t High
#define P(N)
const SmallVectorImpl< MachineOperand > & Cond
static Type * getValueType(Value *V, bool LookThroughCmp=false)
Returns the "element type" of the given value/instruction V.
This file implements the SmallBitVector class.
#define LLVM_DEBUG(...)
Definition Debug.h:114
static std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
Definition VPlanSLP.cpp:247
Value * RHS
Value * LHS
This is an SDNode representing atomic operations.
LLVM_ABI unsigned getVScaleRangeMin() const
Returns the minimum value for the vscale_range attribute.
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition Attributes.h:261
static constexpr ElementCount getScalable(ScalarTy MinVal)
Definition TypeSize.h:312
static constexpr ElementCount get(ScalarTy MinVal, bool Scalable)
Definition TypeSize.h:315
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.
Flags
Flags values. These may be or'd together.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
This class is used to represent an MGATHER node.
const SDValue & getBasePtr() const
ISD::MemIndexType getIndexType() const
How is Index applied to BasePtr when computing addresses.
const SDValue & getInc() const
const SDValue & getScale() const
const SDValue & getMask() const
const SDValue & getIntID() const
const SDValue & getIndex() const
const SDValue & getBasePtr() const
ISD::MemIndexType getIndexType() const
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,...
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.
Align getBaseAlign() const
Returns alignment and volatility of the memory access.
const MDNode * getRanges() const
Returns the Ranges that describes the dereference.
AAMDNodes getAAInfo() const
Returns the AA info that describes the dereference.
MachineMemOperand * getMemOperand() const
Return the unique 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.
SDNodeFlags getFlags() const
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
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.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
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...
SDValue getInsertVectorElt(const SDLoc &DL, SDValue Vec, SDValue Elt, unsigned Idx)
Insert Elt into Vec at offset Idx.
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getPOISON(EVT VT)
Return a POISON node. POISON does not have a useful SDLoc.
LLVMContext * getContext() const
size_type size() const
Determine the number of elements in the SetVector.
Definition SetVector.h:103
Vector takeVector()
Clear the SetVector and return the underlying vector.
Definition SetVector.h:94
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:151
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
pointer data()
Return a pointer to the vector's buffer, even if empty().
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
BooleanContent
Enum that describes how the target represents true/false values.
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 ...
static ISD::NodeType getExtendForContent(BooleanContent Content)
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:343
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.
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.
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:269
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:200
static constexpr bool isKnownLE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:230
constexpr bool isNonZero() const
Definition TypeSize.h:155
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:277
static constexpr bool isKnownLT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:216
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:168
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:165
static constexpr bool isKnownGT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:223
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:252
static constexpr bool isKnownGE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:237
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
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.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
Definition ISDOpcodes.h:41
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
Definition ISDOpcodes.h:819
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
Definition ISDOpcodes.h:261
@ CTLZ_ZERO_UNDEF
Definition ISDOpcodes.h:788
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
Definition ISDOpcodes.h:511
@ POISON
POISON - A poison node.
Definition ISDOpcodes.h:236
@ PARTIAL_REDUCE_SMLA
PARTIAL_REDUCE_[U|S]MLA(Accumulator, Input1, Input2) The partial reduction nodes sign or zero extend ...
@ LOOP_DEPENDENCE_RAW_MASK
@ VECREDUCE_SEQ_FADD
Generic reduction nodes.
@ MLOAD
Masked load and store - consecutive vector load and store operations with additional mask operand tha...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
Definition ISDOpcodes.h:600
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:779
@ SMULFIX
RESULT = [US]MULFIX(LHS, RHS, SCALE) - Perform fixed point multiplication on 2 integers with the same...
Definition ISDOpcodes.h:394
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:264
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ SMULFIXSAT
Same as the corresponding unsaturated fixed point instructions, but the result is clamped between the...
Definition ISDOpcodes.h:400
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition ISDOpcodes.h:853
@ CTTZ_ELTS
Returns the number of number of trailing (least significant) zero elements in a vector.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
Definition ISDOpcodes.h:518
@ VECTOR_FIND_LAST_ACTIVE
Finds the index of the last active mask element Operands: Mask.
@ FMODF
FMODF - Decomposes the operand into integral and fractional parts, each having the same type and sign...
@ FATAN2
FATAN2 - atan2, inspired by libm.
@ FSINCOSPI
FSINCOSPI - Compute both the sine and cosine times pi more accurately than FSINCOS(pi*x),...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Definition ISDOpcodes.h:880
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
Definition ISDOpcodes.h:584
@ VECREDUCE_FMAX
FMIN/FMAX nodes can have flags, for NaN/NoNaN variants.
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:417
@ VECREDUCE_FMAXIMUM
FMINIMUM/FMAXIMUM nodes propatate NaNs and signed zeroes using the llvm.minimum and llvm....
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
Definition ISDOpcodes.h:747
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
Definition ISDOpcodes.h:910
@ FPTRUNC_ROUND
FPTRUNC_ROUND - This corresponds to the fptrunc_round intrinsic.
Definition ISDOpcodes.h:515
@ FAKE_USE
FAKE_USE represents a use of the operand but does not do anything.
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
Definition ISDOpcodes.h:993
@ CLMUL
Carry-less multiplication operations.
Definition ISDOpcodes.h:774
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ SDIVFIX
RESULT = [US]DIVFIX(LHS, RHS, SCALE) - Perform fixed point division on 2 integers with the same width...
Definition ISDOpcodes.h:407
@ CONVERT_FROM_ARBITRARY_FP
CONVERT_FROM_ARBITRARY_FP - This operator converts from an arbitrary floating-point represented as an...
@ PARTIAL_REDUCE_UMLA
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:844
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
Definition ISDOpcodes.h:715
@ STRICT_UINT_TO_FP
Definition ISDOpcodes.h:485
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
Definition ISDOpcodes.h:665
@ VECREDUCE_FADD
These reductions have relaxed evaluation order semantics, and have a single vector operand.
@ CTTZ_ZERO_UNDEF
Bit counting operators with an undefined result for zero inputs.
Definition ISDOpcodes.h:787
@ PARTIAL_REDUCE_FMLA
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ SSUBO
Same for subtraction.
Definition ISDOpcodes.h:352
@ VECTOR_INTERLEAVE
VECTOR_INTERLEAVE(VEC1, VEC2, ...) - Returns N vectors from N input vectors, where N is the factor to...
Definition ISDOpcodes.h:635
@ STEP_VECTOR
STEP_VECTOR(IMM) - Returns a scalable vector whose lanes are comprised of a linear sequence of unsign...
Definition ISDOpcodes.h:691
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
Definition ISDOpcodes.h:541
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
Definition ISDOpcodes.h:548
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
Definition ISDOpcodes.h:374
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:796
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
Definition ISDOpcodes.h:233
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
Definition ISDOpcodes.h:672
@ GET_ACTIVE_LANE_MASK
GET_ACTIVE_LANE_MASK - this corrosponds to the llvm.get.active.lane.mask intrinsic.
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
Definition ISDOpcodes.h:348
@ ARITH_FENCE
ARITH_FENCE - This corresponds to a arithmetic fence intrinsic.
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition ISDOpcodes.h:704
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:765
@ AssertNoFPClass
AssertNoFPClass - These nodes record if a register contains a float value that is known to be not som...
Definition ISDOpcodes.h:78
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition ISDOpcodes.h:649
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition ISDOpcodes.h:614
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimumNumber or maximumNumber on two values,...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:576
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:850
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:811
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ SSHLSAT
RESULT = [US]SHLSAT(LHS, RHS) - Perform saturation left shift.
Definition ISDOpcodes.h:386
@ SMULO
Same for multiplication.
Definition ISDOpcodes.h:356
@ VECTOR_SPLICE_LEFT
VECTOR_SPLICE_LEFT(VEC1, VEC2, OFFSET) - Shifts CONCAT_VECTORS(VEC1, VEC2) left by OFFSET elements an...
Definition ISDOpcodes.h:653
@ ANY_EXTEND_VECTOR_INREG
ANY_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register any-extension of the low la...
Definition ISDOpcodes.h:899
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition ISDOpcodes.h:888
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:727
@ MASKED_UDIV
Masked vector arithmetic that returns poison on disabled lanes.
@ VECTOR_REVERSE
VECTOR_REVERSE(VECTOR) - Returns a vector, of the same type as VECTOR, whose elements are shuffled us...
Definition ISDOpcodes.h:640
@ SDIVFIXSAT
Same as the corresponding unsaturated fixed point instructions, but the result is clamped between the...
Definition ISDOpcodes.h:413
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:978
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition ISDOpcodes.h:805
@ STRICT_SINT_TO_FP
STRICT_[US]INT_TO_FP - Convert a signed or unsigned integer to a floating point value.
Definition ISDOpcodes.h:484
@ MGATHER
Masked gather and scatter - load and store operations for a vector of random addresses with additiona...
@ STRICT_FP_TO_UINT
Definition ISDOpcodes.h:478
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
Definition ISDOpcodes.h:500
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:477
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:926
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:505
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:739
@ SCMP
[US]CMP - 3-way comparison of signed or unsigned integers.
Definition ISDOpcodes.h:735
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
Definition ISDOpcodes.h:710
@ VECTOR_SPLICE_RIGHT
VECTOR_SPLICE_RIGHT(VEC1, VEC2, OFFSET) - Shifts CONCAT_VECTORS(VEC1,VEC2) right by OFFSET elements a...
Definition ISDOpcodes.h:657
@ FREEZE
FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or is evaluated to UNDEF),...
Definition ISDOpcodes.h:241
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
Definition ISDOpcodes.h:565
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition ISDOpcodes.h:53
@ FFREXP
FFREXP - frexp, extract fractional and exponent component of a floating-point value.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
Definition ISDOpcodes.h:959
@ VECTOR_COMPRESS
VECTOR_COMPRESS(Vec, Mask, Passthru) consecutively place vector elements based on mask e....
Definition ISDOpcodes.h:699
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
Definition ISDOpcodes.h:921
@ ADDRSPACECAST
ADDRSPACECAST - This operator converts between pointers of different address spaces.
Definition ISDOpcodes.h:997
@ EXPERIMENTAL_VECTOR_HISTOGRAM
Experimental vector histogram intrinsic Operands: Input Chain, Inc, Mask, Base, Index,...
@ 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:945
@ VECREDUCE_FMINIMUM
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:856
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ VECREDUCE_SEQ_FMUL
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
Definition ISDOpcodes.h:62
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
Definition ISDOpcodes.h:534
@ PARTIAL_REDUCE_SUMLA
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
Definition ISDOpcodes.h:365
@ VECTOR_DEINTERLEAVE
VECTOR_DEINTERLEAVE(VEC1, VEC2, ...) - Returns N vectors from N input vectors, where N is the factor ...
Definition ISDOpcodes.h:624
@ CTTZ_ELTS_ZERO_POISON
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - minimumnum/maximumnum that is same with FMINNUM_IEEE and FMAXNUM_IEEE besid...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
Definition ISDOpcodes.h:722
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition ISDOpcodes.h:556
@ LOOP_DEPENDENCE_WAR_MASK
The llvm.loop.dependence.
LLVM_ABI bool isBuildVectorOfConstantSDNodes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR node of all ConstantSDNode or undef.
LLVM_ABI NodeType getUnmaskedBinOpOpcode(unsigned MaskedOpc)
Given a MaskedOpc of ISD::MASKED_(U|S)(DIV|REM), returns the unmasked ISD::(U|S)(DIV|REM).
bool isUNINDEXEDLoad(const SDNode *N)
Returns true if the specified node is an unindexed load.
LLVM_ABI std::optional< unsigned > getVPForBaseOpcode(unsigned Opcode)
Translate this non-VP Opcode to its corresponding VP Opcode.
MemIndexType
MemIndexType enum - This enum defines how to interpret MGATHER/SCATTER's index parameter when calcula...
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
LLVM_ABI 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).
LLVM_ABI LegalityPredicate isVector(unsigned TypeIdx)
True iff the specified type index is a vector.
constexpr double e
Context & getContext() const
Definition BasicBlock.h:99
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:532
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
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:1765
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:284
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:279
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr int PoisonMaskElem
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:221
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
Definition STLExtras.h:1885
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
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:1772
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Definition Alignment.h:201
LLVM_ABI 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, bool)> ManyInputsAction)
Splits and processes shuffle mask depending on the number of input and output registers.
@ Increment
Incrementally increasing token ID.
Definition AllocToken.h:26
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:872
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77
Extended Value Type.
Definition ValueTypes.h:35
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
Definition ValueTypes.h:90
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
Definition ValueTypes.h:403
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:70
EVT changeTypeToInteger() const
Return the type converted to an equivalently sized integer or vector with integer element type.
Definition ValueTypes.h:129
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
Definition ValueTypes.h:292
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
Definition ValueTypes.h:155
ElementCount getVectorElementCount() const
Definition ValueTypes.h:358
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
Definition ValueTypes.h:479
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:381
bool isByteSized() const
Return true if the bit size is a multiple of 8.
Definition ValueTypes.h:251
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
Definition ValueTypes.h:367
uint64_t getScalarSizeInBits() const
Definition ValueTypes.h:393
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
Definition ValueTypes.h:486
EVT changeVectorElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
Definition ValueTypes.h:98
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
Definition ValueTypes.h:61
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
Definition ValueTypes.h:389
EVT widenIntegerVectorElementType(LLVMContext &Context) const
Return a VT for an integer vector type with the size of the elements doubled.
Definition ValueTypes.h:460
bool isFixedLengthVector() const
Definition ValueTypes.h:189
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
Definition ValueTypes.h:55
EVT getRoundIntegerType(LLVMContext &Context) const
Rounds the bit-width of the given integer EVT up to the nearest power of two (and at least to eight),...
Definition ValueTypes.h:427
bool isVector() const
Return true if this is a vector value type.
Definition ValueTypes.h:176
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
Definition ValueTypes.h:331
bool bitsEq(EVT VT) const
Return true if this has the same number of bits as VT.
Definition ValueTypes.h:264
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
Definition ValueTypes.h:182
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:276
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition ValueTypes.h:336
EVT changeElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a type whose attributes match ourselves with the exception of the element type that i...
Definition ValueTypes.h:121
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Definition ValueTypes.h:344
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
Definition ValueTypes.h:469
bool isInteger() const
Return true if this is an integer or a vector integer type.
Definition ValueTypes.h:160
This class contains a discriminated union of information about pointers in memory operands,...
LLVM_ABI unsigned getAddrSpace() const
Return the LLVM IR address space number that this pointer points into.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getUnknownStack(MachineFunction &MF)
Stack memory without other information.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.