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) ||
4718 InElementSize <= OutElementSize * 2)
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 = Lo0.getValueType().changeElementType(*DAG.getContext(),
4801 VT.getScalarType());
4802
4803 if (Opc == ISD::SETCC) {
4804 LoRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Lo0, Lo1, N->getOperand(2));
4805 HiRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Hi0, Hi1, N->getOperand(2));
4806 } else if (isStrict) {
4807 LoRes = DAG.getNode(Opc, DL, DAG.getVTList(PartResVT, N->getValueType(1)),
4808 N->getOperand(0), Lo0, Lo1, N->getOperand(3));
4809 HiRes = DAG.getNode(Opc, DL, DAG.getVTList(PartResVT, N->getValueType(1)),
4810 N->getOperand(0), Hi0, Hi1, N->getOperand(3));
4811 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
4812 LoRes.getValue(1), HiRes.getValue(1));
4813 ReplaceValueWith(SDValue(N, 1), NewChain);
4814 } else {
4815 assert(Opc == ISD::VP_SETCC && "Expected VP_SETCC opcode");
4816 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
4817 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(3));
4818 std::tie(EVLLo, EVLHi) =
4819 DAG.SplitEVL(N->getOperand(4), N->getValueType(0), DL);
4820 LoRes = DAG.getNode(ISD::VP_SETCC, DL, PartResVT, Lo0, Lo1,
4821 N->getOperand(2), MaskLo, EVLLo);
4822 HiRes = DAG.getNode(ISD::VP_SETCC, DL, PartResVT, Hi0, Hi1,
4823 N->getOperand(2), MaskHi, EVLHi);
4824 }
4825
4826 return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, LoRes, HiRes);
4827}
4828
4829
4830SDValue DAGTypeLegalizer::SplitVecOp_FP_ROUND(SDNode *N) {
4831 // The result has a legal vector type, but the input needs splitting.
4832 EVT ResVT = N->getValueType(0);
4833 SDValue Lo, Hi;
4834 SDLoc DL(N);
4835 GetSplitVector(N->getOperand(N->isStrictFPOpcode() ? 1 : 0), Lo, Hi);
4836 EVT InVT = Lo.getValueType();
4837
4838 EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
4839 InVT.getVectorElementCount());
4840
4841 if (N->isStrictFPOpcode()) {
4842 Lo = DAG.getNode(N->getOpcode(), DL, {OutVT, MVT::Other},
4843 {N->getOperand(0), Lo, N->getOperand(2)});
4844 Hi = DAG.getNode(N->getOpcode(), DL, {OutVT, MVT::Other},
4845 {N->getOperand(0), Hi, N->getOperand(2)});
4846 // Legalize the chain result - switch anything that used the old chain to
4847 // use the new one.
4848 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
4849 Lo.getValue(1), Hi.getValue(1));
4850 ReplaceValueWith(SDValue(N, 1), NewChain);
4851 } else if (N->getOpcode() == ISD::VP_FP_ROUND) {
4852 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
4853 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
4854 std::tie(EVLLo, EVLHi) =
4855 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), DL);
4856 Lo = DAG.getNode(ISD::VP_FP_ROUND, DL, OutVT, Lo, MaskLo, EVLLo);
4857 Hi = DAG.getNode(ISD::VP_FP_ROUND, DL, OutVT, Hi, MaskHi, EVLHi);
4858 } else {
4859 Lo = DAG.getNode(N->getOpcode(), DL, OutVT, Lo, N->getOperand(1));
4860 Hi = DAG.getNode(N->getOpcode(), DL, OutVT, Hi, N->getOperand(1));
4861 }
4862
4863 return DAG.getNode(ISD::CONCAT_VECTORS, DL, ResVT, Lo, Hi);
4864}
4865
4866// Split a vector type in an FP binary operation where the second operand has a
4867// different type from the first.
4868//
4869// The result (and the first input) has a legal vector type, but the second
4870// input needs splitting.
4871SDValue DAGTypeLegalizer::SplitVecOp_FPOpDifferentTypes(SDNode *N) {
4872 SDLoc DL(N);
4873
4874 EVT LHSLoVT, LHSHiVT;
4875 std::tie(LHSLoVT, LHSHiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
4876
4877 if (!isTypeLegal(LHSLoVT) || !isTypeLegal(LHSHiVT))
4878 return DAG.UnrollVectorOp(N, N->getValueType(0).getVectorNumElements());
4879
4880 SDValue LHSLo, LHSHi;
4881 std::tie(LHSLo, LHSHi) =
4882 DAG.SplitVector(N->getOperand(0), DL, LHSLoVT, LHSHiVT);
4883
4884 SDValue RHSLo, RHSHi;
4885 std::tie(RHSLo, RHSHi) = DAG.SplitVector(N->getOperand(1), DL);
4886
4887 SDValue Lo = DAG.getNode(N->getOpcode(), DL, LHSLoVT, LHSLo, RHSLo);
4888 SDValue Hi = DAG.getNode(N->getOpcode(), DL, LHSHiVT, LHSHi, RHSHi);
4889
4890 return DAG.getNode(ISD::CONCAT_VECTORS, DL, N->getValueType(0), Lo, Hi);
4891}
4892
4893SDValue DAGTypeLegalizer::SplitVecOp_CMP(SDNode *N) {
4894 LLVMContext &Ctxt = *DAG.getContext();
4895 SDLoc dl(N);
4896
4897 SDValue LHSLo, LHSHi, RHSLo, RHSHi;
4898 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
4899 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
4900
4901 EVT ResVT = N->getValueType(0);
4902 ElementCount SplitOpEC = LHSLo.getValueType().getVectorElementCount();
4903 EVT NewResVT =
4904 EVT::getVectorVT(Ctxt, ResVT.getVectorElementType(), SplitOpEC);
4905
4906 SDValue Lo = DAG.getNode(N->getOpcode(), dl, NewResVT, LHSLo, RHSLo);
4907 SDValue Hi = DAG.getNode(N->getOpcode(), dl, NewResVT, LHSHi, RHSHi);
4908
4909 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
4910}
4911
4912SDValue DAGTypeLegalizer::SplitVecOp_FP_TO_XINT_SAT(SDNode *N) {
4913 EVT ResVT = N->getValueType(0);
4914 SDValue Lo, Hi;
4915 SDLoc dl(N);
4916 GetSplitVector(N->getOperand(0), Lo, Hi);
4917 EVT InVT = Lo.getValueType();
4918
4919 EVT NewResVT =
4920 EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
4921 InVT.getVectorElementCount());
4922
4923 Lo = DAG.getNode(N->getOpcode(), dl, NewResVT, Lo, N->getOperand(1));
4924 Hi = DAG.getNode(N->getOpcode(), dl, NewResVT, Hi, N->getOperand(1));
4925
4926 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
4927}
4928
4929SDValue DAGTypeLegalizer::SplitVecOp_CttzElts(SDNode *N) {
4930 SDLoc DL(N);
4931 EVT ResVT = N->getValueType(0);
4932
4933 SDValue Lo, Hi;
4934 SDValue VecOp = N->getOperand(0);
4935 GetSplitVector(VecOp, Lo, Hi);
4936
4937 // if CTTZ_ELTS(Lo) != VL => CTTZ_ELTS(Lo).
4938 // else => VL + (CTTZ_ELTS(Hi) or CTTZ_ELTS_ZERO_POISON(Hi)).
4939 SDValue ResLo = DAG.getNode(ISD::CTTZ_ELTS, DL, ResVT, Lo);
4940 SDValue VL =
4941 DAG.getElementCount(DL, ResVT, Lo.getValueType().getVectorElementCount());
4942 SDValue ResLoNotVL =
4943 DAG.getSetCC(DL, getSetCCResultType(ResVT), ResLo, VL, ISD::SETNE);
4944 SDValue ResHi = DAG.getNode(N->getOpcode(), DL, ResVT, Hi);
4945 return DAG.getSelect(DL, ResVT, ResLoNotVL, ResLo,
4946 DAG.getNode(ISD::ADD, DL, ResVT, VL, ResHi));
4947}
4948
4949SDValue DAGTypeLegalizer::SplitVecOp_VP_CttzElements(SDNode *N) {
4950 SDLoc DL(N);
4951 EVT ResVT = N->getValueType(0);
4952
4953 SDValue Lo, Hi;
4954 SDValue VecOp = N->getOperand(0);
4955 GetSplitVector(VecOp, Lo, Hi);
4956
4957 auto [MaskLo, MaskHi] = SplitMask(N->getOperand(1));
4958 auto [EVLLo, EVLHi] =
4959 DAG.SplitEVL(N->getOperand(2), VecOp.getValueType(), DL);
4960 SDValue VLo = DAG.getZExtOrTrunc(EVLLo, DL, ResVT);
4961
4962 // if VP_CTTZ_ELTS(Lo) != EVLLo => VP_CTTZ_ELTS(Lo).
4963 // else => EVLLo + (VP_CTTZ_ELTS(Hi) or VP_CTTZ_ELTS_ZERO_UNDEF(Hi)).
4964 SDValue ResLo = DAG.getNode(ISD::VP_CTTZ_ELTS, DL, ResVT, Lo, MaskLo, EVLLo);
4965 SDValue ResLoNotEVL =
4966 DAG.getSetCC(DL, getSetCCResultType(ResVT), ResLo, VLo, ISD::SETNE);
4967 SDValue ResHi = DAG.getNode(N->getOpcode(), DL, ResVT, Hi, MaskHi, EVLHi);
4968 return DAG.getSelect(DL, ResVT, ResLoNotEVL, ResLo,
4969 DAG.getNode(ISD::ADD, DL, ResVT, VLo, ResHi));
4970}
4971
4972SDValue DAGTypeLegalizer::SplitVecOp_VECTOR_HISTOGRAM(SDNode *N) {
4973 MaskedHistogramSDNode *HG = cast<MaskedHistogramSDNode>(N);
4974 SDLoc DL(HG);
4975 SDValue Inc = HG->getInc();
4976 SDValue Ptr = HG->getBasePtr();
4977 SDValue Scale = HG->getScale();
4978 SDValue IntID = HG->getIntID();
4979 EVT MemVT = HG->getMemoryVT();
4980 MachineMemOperand *MMO = HG->getMemOperand();
4981 ISD::MemIndexType IndexType = HG->getIndexType();
4982
4983 SDValue IndexLo, IndexHi, MaskLo, MaskHi;
4984 std::tie(IndexLo, IndexHi) = DAG.SplitVector(HG->getIndex(), DL);
4985 std::tie(MaskLo, MaskHi) = DAG.SplitVector(HG->getMask(), DL);
4986 SDValue OpsLo[] = {HG->getChain(), Inc, MaskLo, Ptr, IndexLo, Scale, IntID};
4987 SDValue Lo = DAG.getMaskedHistogram(DAG.getVTList(MVT::Other), MemVT, DL,
4988 OpsLo, MMO, IndexType);
4989 SDValue OpsHi[] = {Lo, Inc, MaskHi, Ptr, IndexHi, Scale, IntID};
4990 return DAG.getMaskedHistogram(DAG.getVTList(MVT::Other), MemVT, DL, OpsHi,
4991 MMO, IndexType);
4992}
4993
4994SDValue DAGTypeLegalizer::SplitVecOp_PARTIAL_REDUCE_MLA(SDNode *N) {
4995 SDValue Acc = N->getOperand(0);
4996 assert(getTypeAction(Acc.getValueType()) != TargetLowering::TypeSplitVector &&
4997 "Accumulator should already be a legal type, and shouldn't need "
4998 "further splitting");
4999
5000 SDLoc DL(N);
5001 SDValue Input1Lo, Input1Hi, Input2Lo, Input2Hi;
5002 GetSplitVector(N->getOperand(1), Input1Lo, Input1Hi);
5003 GetSplitVector(N->getOperand(2), Input2Lo, Input2Hi);
5004 unsigned Opcode = N->getOpcode();
5005 EVT ResultVT = Acc.getValueType();
5006
5007 SDValue Lo = DAG.getNode(Opcode, DL, ResultVT, Acc, Input1Lo, Input2Lo);
5008 return DAG.getNode(Opcode, DL, ResultVT, Lo, Input1Hi, Input2Hi);
5009}
5010
5011//===----------------------------------------------------------------------===//
5012// Result Vector Widening
5013//===----------------------------------------------------------------------===//
5014
5015void DAGTypeLegalizer::ReplaceOtherWidenResults(SDNode *N, SDNode *WidenNode,
5016 unsigned WidenResNo) {
5017 unsigned NumResults = N->getNumValues();
5018 for (unsigned ResNo = 0; ResNo < NumResults; ResNo++) {
5019 if (ResNo == WidenResNo)
5020 continue;
5021 EVT ResVT = N->getValueType(ResNo);
5022 if (getTypeAction(ResVT) == TargetLowering::TypeWidenVector) {
5023 SetWidenedVector(SDValue(N, ResNo), SDValue(WidenNode, ResNo));
5024 } else {
5025 SDLoc DL(N);
5026 SDValue ResVal =
5027 DAG.getExtractSubvector(DL, ResVT, SDValue(WidenNode, ResNo), 0);
5028 ReplaceValueWith(SDValue(N, ResNo), ResVal);
5029 }
5030 }
5031}
5032
5033void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
5034 LLVM_DEBUG(dbgs() << "Widen node result " << ResNo << ": "; N->dump(&DAG));
5035
5036 // See if the target wants to custom widen this node.
5037 if (CustomWidenLowerNode(N, N->getValueType(ResNo)))
5038 return;
5039
5040 SDValue Res = SDValue();
5041
5042 auto unrollExpandedOp = [&]() {
5043 // We're going to widen this vector op to a legal type by padding with undef
5044 // elements. If the wide vector op is eventually going to be expanded to
5045 // scalar libcalls, then unroll into scalar ops now to avoid unnecessary
5046 // libcalls on the undef elements.
5047 EVT VT = N->getValueType(0);
5048 EVT WideVecVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
5049 if (!TLI.isOperationLegalOrCustomOrPromote(N->getOpcode(), WideVecVT) &&
5050 TLI.isOperationExpandOrLibCall(N->getOpcode(), VT.getScalarType())) {
5051 Res = DAG.UnrollVectorOp(N, WideVecVT.getVectorNumElements());
5052 if (N->getNumValues() > 1)
5053 ReplaceOtherWidenResults(N, Res.getNode(), ResNo);
5054 return true;
5055 }
5056 return false;
5057 };
5058
5059 switch (N->getOpcode()) {
5060 default:
5061#ifndef NDEBUG
5062 dbgs() << "WidenVectorResult #" << ResNo << ": ";
5063 N->dump(&DAG);
5064 dbgs() << "\n";
5065#endif
5066 report_fatal_error("Do not know how to widen the result of this operator!");
5067
5070 Res = WidenVecRes_LOOP_DEPENDENCE_MASK(N);
5071 break;
5072 case ISD::MERGE_VALUES: Res = WidenVecRes_MERGE_VALUES(N, ResNo); break;
5073 case ISD::ADDRSPACECAST:
5074 Res = WidenVecRes_ADDRSPACECAST(N);
5075 break;
5076 case ISD::AssertZext: Res = WidenVecRes_AssertZext(N); break;
5077 case ISD::BITCAST: Res = WidenVecRes_BITCAST(N); break;
5078 case ISD::BUILD_VECTOR: Res = WidenVecRes_BUILD_VECTOR(N); break;
5079 case ISD::CONCAT_VECTORS: Res = WidenVecRes_CONCAT_VECTORS(N); break;
5081 Res = WidenVecRes_INSERT_SUBVECTOR(N);
5082 break;
5083 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecRes_EXTRACT_SUBVECTOR(N); break;
5084 case ISD::INSERT_VECTOR_ELT: Res = WidenVecRes_INSERT_VECTOR_ELT(N); break;
5085 case ISD::ATOMIC_LOAD:
5086 Res = WidenVecRes_ATOMIC_LOAD(cast<AtomicSDNode>(N));
5087 break;
5088 case ISD::LOAD: Res = WidenVecRes_LOAD(N); break;
5089 case ISD::STEP_VECTOR:
5090 case ISD::SPLAT_VECTOR:
5092 Res = WidenVecRes_ScalarOp(N);
5093 break;
5094 case ISD::SIGN_EXTEND_INREG: Res = WidenVecRes_InregOp(N); break;
5095 case ISD::VSELECT:
5096 case ISD::SELECT:
5097 case ISD::VP_SELECT:
5098 case ISD::VP_MERGE:
5099 Res = WidenVecRes_Select(N);
5100 break;
5101 case ISD::SELECT_CC: Res = WidenVecRes_SELECT_CC(N); break;
5102 case ISD::VP_SETCC:
5103 case ISD::SETCC: Res = WidenVecRes_SETCC(N); break;
5104 case ISD::POISON:
5105 case ISD::UNDEF: Res = WidenVecRes_UNDEF(N); break;
5107 Res = WidenVecRes_VECTOR_SHUFFLE(cast<ShuffleVectorSDNode>(N));
5108 break;
5109 case ISD::VP_LOAD:
5110 Res = WidenVecRes_VP_LOAD(cast<VPLoadSDNode>(N));
5111 break;
5112 case ISD::VP_LOAD_FF:
5113 Res = WidenVecRes_VP_LOAD_FF(cast<VPLoadFFSDNode>(N));
5114 break;
5115 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
5116 Res = WidenVecRes_VP_STRIDED_LOAD(cast<VPStridedLoadSDNode>(N));
5117 break;
5119 Res = WidenVecRes_VECTOR_COMPRESS(N);
5120 break;
5121 case ISD::MLOAD:
5122 Res = WidenVecRes_MLOAD(cast<MaskedLoadSDNode>(N));
5123 break;
5124 case ISD::MGATHER:
5125 Res = WidenVecRes_MGATHER(cast<MaskedGatherSDNode>(N));
5126 break;
5127 case ISD::VP_GATHER:
5128 Res = WidenVecRes_VP_GATHER(cast<VPGatherSDNode>(N));
5129 break;
5131 Res = WidenVecRes_VECTOR_REVERSE(N);
5132 break;
5134 Res = WidenVecRes_GET_ACTIVE_LANE_MASK(N);
5135 break;
5136
5137 case ISD::ADD: case ISD::VP_ADD:
5138 case ISD::AND: case ISD::VP_AND:
5139 case ISD::MUL: case ISD::VP_MUL:
5140 case ISD::MULHS:
5141 case ISD::MULHU:
5142 case ISD::ABDS:
5143 case ISD::ABDU:
5144 case ISD::OR: case ISD::VP_OR:
5145 case ISD::SUB: case ISD::VP_SUB:
5146 case ISD::XOR: case ISD::VP_XOR:
5147 case ISD::SHL: case ISD::VP_SHL:
5148 case ISD::SRA: case ISD::VP_SRA:
5149 case ISD::SRL: case ISD::VP_SRL:
5150 case ISD::CLMUL:
5151 case ISD::CLMULR:
5152 case ISD::CLMULH:
5153 case ISD::FMINNUM:
5154 case ISD::FMINNUM_IEEE:
5155 case ISD::VP_FMINNUM:
5156 case ISD::FMAXNUM:
5157 case ISD::FMAXNUM_IEEE:
5158 case ISD::VP_FMAXNUM:
5159 case ISD::FMINIMUM:
5160 case ISD::VP_FMINIMUM:
5161 case ISD::FMAXIMUM:
5162 case ISD::VP_FMAXIMUM:
5163 case ISD::FMINIMUMNUM:
5164 case ISD::FMAXIMUMNUM:
5165 case ISD::SMIN: case ISD::VP_SMIN:
5166 case ISD::SMAX: case ISD::VP_SMAX:
5167 case ISD::UMIN: case ISD::VP_UMIN:
5168 case ISD::UMAX: case ISD::VP_UMAX:
5169 case ISD::UADDSAT: case ISD::VP_UADDSAT:
5170 case ISD::SADDSAT: case ISD::VP_SADDSAT:
5171 case ISD::USUBSAT: case ISD::VP_USUBSAT:
5172 case ISD::SSUBSAT: case ISD::VP_SSUBSAT:
5173 case ISD::SSHLSAT:
5174 case ISD::USHLSAT:
5175 case ISD::ROTL:
5176 case ISD::ROTR:
5177 case ISD::AVGFLOORS:
5178 case ISD::AVGFLOORU:
5179 case ISD::AVGCEILS:
5180 case ISD::AVGCEILU:
5181 // Vector-predicated binary op widening. Note that -- unlike the
5182 // unpredicated versions -- we don't have to worry about trapping on
5183 // operations like UDIV, FADD, etc., as we pass on the original vector
5184 // length parameter. This means the widened elements containing garbage
5185 // aren't active.
5186 case ISD::VP_SDIV:
5187 case ISD::VP_UDIV:
5188 case ISD::VP_SREM:
5189 case ISD::VP_UREM:
5190 case ISD::VP_FADD:
5191 case ISD::VP_FSUB:
5192 case ISD::VP_FMUL:
5193 case ISD::VP_FDIV:
5194 case ISD::VP_FREM:
5195 case ISD::VP_FCOPYSIGN:
5196 Res = WidenVecRes_Binary(N);
5197 break;
5198
5199 case ISD::MASKED_UDIV:
5200 case ISD::MASKED_SDIV:
5201 case ISD::MASKED_UREM:
5202 case ISD::MASKED_SREM:
5203 Res = WidenVecRes_MaskedBinary(N);
5204 break;
5205
5206 case ISD::SCMP:
5207 case ISD::UCMP:
5208 Res = WidenVecRes_CMP(N);
5209 break;
5210
5211 case ISD::FPOW:
5212 case ISD::FATAN2:
5213 case ISD::FREM:
5214 if (unrollExpandedOp())
5215 break;
5216 // If the target has custom/legal support for the scalar FP intrinsic ops
5217 // (they are probably not destined to become libcalls), then widen those
5218 // like any other binary ops.
5219 [[fallthrough]];
5220
5221 case ISD::FADD:
5222 case ISD::FMUL:
5223 case ISD::FSUB:
5224 case ISD::FDIV:
5225 case ISD::SDIV:
5226 case ISD::UDIV:
5227 case ISD::SREM:
5228 case ISD::UREM:
5229 Res = WidenVecRes_BinaryCanTrap(N);
5230 break;
5231
5232 case ISD::SMULFIX:
5233 case ISD::SMULFIXSAT:
5234 case ISD::UMULFIX:
5235 case ISD::UMULFIXSAT:
5236 // These are binary operations, but with an extra operand that shouldn't
5237 // be widened (the scale).
5238 Res = WidenVecRes_BinaryWithExtraScalarOp(N);
5239 break;
5240
5241#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
5242 case ISD::STRICT_##DAGN:
5243#include "llvm/IR/ConstrainedOps.def"
5244 Res = WidenVecRes_StrictFP(N);
5245 break;
5246
5247 case ISD::UADDO:
5248 case ISD::SADDO:
5249 case ISD::USUBO:
5250 case ISD::SSUBO:
5251 case ISD::UMULO:
5252 case ISD::SMULO:
5253 Res = WidenVecRes_OverflowOp(N, ResNo);
5254 break;
5255
5256 case ISD::FCOPYSIGN:
5257 Res = WidenVecRes_FCOPYSIGN(N);
5258 break;
5259
5260 case ISD::IS_FPCLASS:
5261 case ISD::FPTRUNC_ROUND:
5262 Res = WidenVecRes_UnarySameEltsWithScalarArg(N);
5263 break;
5264
5265 case ISD::FLDEXP:
5266 case ISD::FPOWI:
5267 if (!unrollExpandedOp())
5268 Res = WidenVecRes_ExpOp(N);
5269 break;
5270
5274 Res = WidenVecRes_EXTEND_VECTOR_INREG(N);
5275 break;
5276
5277 case ISD::ANY_EXTEND:
5278 case ISD::FP_EXTEND:
5279 case ISD::VP_FP_EXTEND:
5280 case ISD::FP_ROUND:
5281 case ISD::VP_FP_ROUND:
5282 case ISD::FP_TO_SINT:
5283 case ISD::VP_FP_TO_SINT:
5284 case ISD::FP_TO_UINT:
5285 case ISD::VP_FP_TO_UINT:
5286 case ISD::SIGN_EXTEND:
5287 case ISD::VP_SIGN_EXTEND:
5288 case ISD::SINT_TO_FP:
5289 case ISD::VP_SINT_TO_FP:
5290 case ISD::VP_TRUNCATE:
5291 case ISD::TRUNCATE:
5292 case ISD::UINT_TO_FP:
5293 case ISD::VP_UINT_TO_FP:
5294 case ISD::ZERO_EXTEND:
5295 case ISD::VP_ZERO_EXTEND:
5297 Res = WidenVecRes_Convert(N);
5298 break;
5299
5302 Res = WidenVecRes_FP_TO_XINT_SAT(N);
5303 break;
5304
5305 case ISD::LRINT:
5306 case ISD::LLRINT:
5307 case ISD::VP_LRINT:
5308 case ISD::VP_LLRINT:
5309 case ISD::LROUND:
5310 case ISD::LLROUND:
5311 Res = WidenVecRes_XROUND(N);
5312 break;
5313
5314 case ISD::FACOS:
5315 case ISD::FASIN:
5316 case ISD::FATAN:
5317 case ISD::FCEIL:
5318 case ISD::FCOS:
5319 case ISD::FCOSH:
5320 case ISD::FEXP:
5321 case ISD::FEXP2:
5322 case ISD::FEXP10:
5323 case ISD::FFLOOR:
5324 case ISD::FLOG:
5325 case ISD::FLOG10:
5326 case ISD::FLOG2:
5327 case ISD::FNEARBYINT:
5328 case ISD::FRINT:
5329 case ISD::FROUND:
5330 case ISD::FROUNDEVEN:
5331 case ISD::FSIN:
5332 case ISD::FSINH:
5333 case ISD::FSQRT:
5334 case ISD::FTAN:
5335 case ISD::FTANH:
5336 case ISD::FTRUNC:
5337 if (unrollExpandedOp())
5338 break;
5339 // If the target has custom/legal support for the scalar FP intrinsic ops
5340 // (they are probably not destined to become libcalls), then widen those
5341 // like any other unary ops.
5342 [[fallthrough]];
5343
5344 case ISD::ABS:
5345 case ISD::VP_ABS:
5346 case ISD::BITREVERSE:
5347 case ISD::VP_BITREVERSE:
5348 case ISD::BSWAP:
5349 case ISD::VP_BSWAP:
5350 case ISD::CTLZ:
5351 case ISD::VP_CTLZ:
5353 case ISD::VP_CTLZ_ZERO_UNDEF:
5354 case ISD::CTPOP:
5355 case ISD::VP_CTPOP:
5356 case ISD::CTTZ:
5357 case ISD::VP_CTTZ:
5359 case ISD::VP_CTTZ_ZERO_UNDEF:
5360 case ISD::FNEG: case ISD::VP_FNEG:
5361 case ISD::FABS: case ISD::VP_FABS:
5362 case ISD::VP_SQRT:
5363 case ISD::VP_FCEIL:
5364 case ISD::VP_FFLOOR:
5365 case ISD::VP_FRINT:
5366 case ISD::VP_FNEARBYINT:
5367 case ISD::VP_FROUND:
5368 case ISD::VP_FROUNDEVEN:
5369 case ISD::VP_FROUNDTOZERO:
5370 case ISD::FREEZE:
5371 case ISD::ARITH_FENCE:
5372 case ISD::FCANONICALIZE:
5374 Res = WidenVecRes_Unary(N);
5375 break;
5376 case ISD::FMA: case ISD::VP_FMA:
5377 case ISD::FSHL:
5378 case ISD::VP_FSHL:
5379 case ISD::FSHR:
5380 case ISD::VP_FSHR:
5381 Res = WidenVecRes_Ternary(N);
5382 break;
5383 case ISD::FMODF:
5384 case ISD::FFREXP:
5385 case ISD::FSINCOS:
5386 case ISD::FSINCOSPI: {
5387 if (!unrollExpandedOp())
5388 Res = WidenVecRes_UnaryOpWithTwoResults(N, ResNo);
5389 break;
5390 }
5391 }
5392
5393 // If Res is null, the sub-method took care of registering the result.
5394 if (Res.getNode())
5395 SetWidenedVector(SDValue(N, ResNo), Res);
5396}
5397
5398SDValue DAGTypeLegalizer::WidenVecRes_Ternary(SDNode *N) {
5399 // Ternary op widening.
5400 SDLoc dl(N);
5401 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5402 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5403 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5404 SDValue InOp3 = GetWidenedVector(N->getOperand(2));
5405 if (N->getNumOperands() == 3)
5406 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3);
5407
5408 assert(N->getNumOperands() == 5 && "Unexpected number of operands!");
5409 assert(N->isVPOpcode() && "Expected VP opcode");
5410
5411 SDValue Mask =
5412 GetWidenedMask(N->getOperand(3), WidenVT.getVectorElementCount());
5413 return DAG.getNode(N->getOpcode(), dl, WidenVT,
5414 {InOp1, InOp2, InOp3, Mask, N->getOperand(4)});
5415}
5416
5417SDValue DAGTypeLegalizer::WidenVecRes_Binary(SDNode *N) {
5418 // Binary op widening.
5419 SDLoc dl(N);
5420 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5421 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5422 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5423 if (N->getNumOperands() == 2)
5424 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2,
5425 N->getFlags());
5426
5427 assert(N->getNumOperands() == 4 && "Unexpected number of operands!");
5428 assert(N->isVPOpcode() && "Expected VP opcode");
5429
5430 SDValue Mask =
5431 GetWidenedMask(N->getOperand(2), WidenVT.getVectorElementCount());
5432 return DAG.getNode(N->getOpcode(), dl, WidenVT,
5433 {InOp1, InOp2, Mask, N->getOperand(3)}, N->getFlags());
5434}
5435
5436SDValue DAGTypeLegalizer::WidenVecRes_MaskedBinary(SDNode *N) {
5437 SDLoc dl(N);
5438 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5439 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5440 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5441 SDValue Mask = N->getOperand(2);
5442 EVT WideMaskVT = WidenVT.changeVectorElementType(
5443 *DAG.getContext(), Mask.getValueType().getVectorElementType());
5444 Mask = ModifyToType(Mask, WideMaskVT, /*FillWithZeros=*/true);
5445 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, Mask,
5446 N->getFlags());
5447}
5448
5449SDValue DAGTypeLegalizer::WidenVecRes_CMP(SDNode *N) {
5450 LLVMContext &Ctxt = *DAG.getContext();
5451 SDLoc dl(N);
5452
5453 SDValue LHS = N->getOperand(0);
5454 SDValue RHS = N->getOperand(1);
5455 EVT OpVT = LHS.getValueType();
5456 if (getTypeAction(OpVT) == TargetLowering::TypeWidenVector) {
5457 LHS = GetWidenedVector(LHS);
5458 RHS = GetWidenedVector(RHS);
5459 OpVT = LHS.getValueType();
5460 }
5461
5462 EVT WidenResVT = TLI.getTypeToTransformTo(Ctxt, N->getValueType(0));
5463 ElementCount WidenResEC = WidenResVT.getVectorElementCount();
5464 if (WidenResEC == OpVT.getVectorElementCount()) {
5465 return DAG.getNode(N->getOpcode(), dl, WidenResVT, LHS, RHS);
5466 }
5467
5468 return DAG.UnrollVectorOp(N, WidenResVT.getVectorNumElements());
5469}
5470
5471SDValue DAGTypeLegalizer::WidenVecRes_BinaryWithExtraScalarOp(SDNode *N) {
5472 // Binary op widening, but with an extra operand that shouldn't be widened.
5473 SDLoc dl(N);
5474 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5475 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5476 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5477 SDValue InOp3 = N->getOperand(2);
5478 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3,
5479 N->getFlags());
5480}
5481
5482// Given a vector of operations that have been broken up to widen, see
5483// if we can collect them together into the next widest legal VT. This
5484// implementation is trap-safe.
5486 SmallVectorImpl<SDValue> &ConcatOps,
5487 unsigned ConcatEnd, EVT VT, EVT MaxVT,
5488 EVT WidenVT) {
5489 // Check to see if we have a single operation with the widen type.
5490 if (ConcatEnd == 1) {
5491 VT = ConcatOps[0].getValueType();
5492 if (VT == WidenVT)
5493 return ConcatOps[0];
5494 }
5495
5496 SDLoc dl(ConcatOps[0]);
5497 EVT WidenEltVT = WidenVT.getVectorElementType();
5498
5499 // while (Some element of ConcatOps is not of type MaxVT) {
5500 // From the end of ConcatOps, collect elements of the same type and put
5501 // them into an op of the next larger supported type
5502 // }
5503 while (ConcatOps[ConcatEnd-1].getValueType() != MaxVT) {
5504 int Idx = ConcatEnd - 1;
5505 VT = ConcatOps[Idx--].getValueType();
5506 while (Idx >= 0 && ConcatOps[Idx].getValueType() == VT)
5507 Idx--;
5508
5509 int NextSize = VT.isVector() ? VT.getVectorNumElements() : 1;
5510 EVT NextVT;
5511 do {
5512 NextSize *= 2;
5513 NextVT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NextSize);
5514 } while (!TLI.isTypeLegal(NextVT));
5515
5516 if (!VT.isVector()) {
5517 // Scalar type, create an INSERT_VECTOR_ELEMENT of type NextVT
5518 SDValue VecOp = DAG.getPOISON(NextVT);
5519 unsigned NumToInsert = ConcatEnd - Idx - 1;
5520 for (unsigned i = 0, OpIdx = Idx + 1; i < NumToInsert; i++, OpIdx++)
5521 VecOp = DAG.getInsertVectorElt(dl, VecOp, ConcatOps[OpIdx], i);
5522 ConcatOps[Idx+1] = VecOp;
5523 ConcatEnd = Idx + 2;
5524 } else {
5525 // Vector type, create a CONCAT_VECTORS of type NextVT
5526 SDValue undefVec = DAG.getPOISON(VT);
5527 unsigned OpsToConcat = NextSize/VT.getVectorNumElements();
5528 SmallVector<SDValue, 16> SubConcatOps(OpsToConcat);
5529 unsigned RealVals = ConcatEnd - Idx - 1;
5530 unsigned SubConcatEnd = 0;
5531 unsigned SubConcatIdx = Idx + 1;
5532 while (SubConcatEnd < RealVals)
5533 SubConcatOps[SubConcatEnd++] = ConcatOps[++Idx];
5534 while (SubConcatEnd < OpsToConcat)
5535 SubConcatOps[SubConcatEnd++] = undefVec;
5536 ConcatOps[SubConcatIdx] = DAG.getNode(ISD::CONCAT_VECTORS, dl,
5537 NextVT, SubConcatOps);
5538 ConcatEnd = SubConcatIdx + 1;
5539 }
5540 }
5541
5542 // Check to see if we have a single operation with the widen type.
5543 if (ConcatEnd == 1) {
5544 VT = ConcatOps[0].getValueType();
5545 if (VT == WidenVT)
5546 return ConcatOps[0];
5547 }
5548
5549 // add undefs of size MaxVT until ConcatOps grows to length of WidenVT
5550 unsigned NumOps = WidenVT.getVectorNumElements()/MaxVT.getVectorNumElements();
5551 if (NumOps != ConcatEnd ) {
5552 SDValue UndefVal = DAG.getPOISON(MaxVT);
5553 for (unsigned j = ConcatEnd; j < NumOps; ++j)
5554 ConcatOps[j] = UndefVal;
5555 }
5556 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
5557 ArrayRef(ConcatOps.data(), NumOps));
5558}
5559
5560SDValue DAGTypeLegalizer::WidenVecRes_BinaryCanTrap(SDNode *N) {
5561 // Binary op widening for operations that can trap.
5562 unsigned Opcode = N->getOpcode();
5563 SDLoc dl(N);
5564 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5565 EVT WidenEltVT = WidenVT.getVectorElementType();
5566 EVT VT = WidenVT;
5567 unsigned NumElts = VT.getVectorMinNumElements();
5568 const SDNodeFlags Flags = N->getFlags();
5569 while (!TLI.isTypeLegal(VT) && NumElts != 1) {
5570 NumElts = NumElts / 2;
5571 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5572 }
5573
5574 if (NumElts != 1 && !TLI.canOpTrap(N->getOpcode(), VT)) {
5575 // Operation doesn't trap so just widen as normal.
5576 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5577 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5578 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, Flags);
5579 }
5580
5581 // Generate a vp.op if it is custom/legal for the target. This avoids need
5582 // to split and tile the subvectors (below), because the inactive lanes can
5583 // simply be disabled. To avoid possible recursion, only do this if the
5584 // widened mask type is legal.
5585 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opcode);
5586 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WidenVT)) {
5587 if (EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
5588 WidenVT.getVectorElementCount());
5589 TLI.isTypeLegal(WideMaskVT)) {
5590 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5591 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5592 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
5593 SDValue EVL =
5594 DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
5595 N->getValueType(0).getVectorElementCount());
5596 return DAG.getNode(*VPOpcode, dl, WidenVT, InOp1, InOp2, Mask, EVL,
5597 Flags);
5598 }
5599 }
5600
5601 // FIXME: Improve support for scalable vectors.
5602 assert(!VT.isScalableVector() && "Scalable vectors not handled yet.");
5603
5604 // No legal vector version so unroll the vector operation and then widen.
5605 if (NumElts == 1)
5606 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
5607
5608 // Since the operation can trap, apply operation on the original vector.
5609 EVT MaxVT = VT;
5610 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5611 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5612 unsigned CurNumElts = N->getValueType(0).getVectorNumElements();
5613
5614 SmallVector<SDValue, 16> ConcatOps(CurNumElts);
5615 unsigned ConcatEnd = 0; // Current ConcatOps index.
5616 int Idx = 0; // Current Idx into input vectors.
5617
5618 // NumElts := greatest legal vector size (at most WidenVT)
5619 // while (orig. vector has unhandled elements) {
5620 // take munches of size NumElts from the beginning and add to ConcatOps
5621 // NumElts := next smaller supported vector size or 1
5622 // }
5623 while (CurNumElts != 0) {
5624 while (CurNumElts >= NumElts) {
5625 SDValue EOp1 = DAG.getExtractSubvector(dl, VT, InOp1, Idx);
5626 SDValue EOp2 = DAG.getExtractSubvector(dl, VT, InOp2, Idx);
5627 ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, VT, EOp1, EOp2, Flags);
5628 Idx += NumElts;
5629 CurNumElts -= NumElts;
5630 }
5631 do {
5632 NumElts = NumElts / 2;
5633 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5634 } while (!TLI.isTypeLegal(VT) && NumElts != 1);
5635
5636 if (NumElts == 1) {
5637 for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
5638 SDValue EOp1 = DAG.getExtractVectorElt(dl, WidenEltVT, InOp1, Idx);
5639 SDValue EOp2 = DAG.getExtractVectorElt(dl, WidenEltVT, InOp2, Idx);
5640 ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, WidenEltVT,
5641 EOp1, EOp2, Flags);
5642 }
5643 CurNumElts = 0;
5644 }
5645 }
5646
5647 return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
5648}
5649
5650SDValue DAGTypeLegalizer::WidenVecRes_StrictFP(SDNode *N) {
5651 switch (N->getOpcode()) {
5652 case ISD::STRICT_FSETCC:
5654 return WidenVecRes_STRICT_FSETCC(N);
5661 return WidenVecRes_Convert_StrictFP(N);
5662 default:
5663 break;
5664 }
5665
5666 // StrictFP op widening for operations that can trap.
5667 unsigned NumOpers = N->getNumOperands();
5668 unsigned Opcode = N->getOpcode();
5669 SDLoc dl(N);
5670 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5671 EVT WidenEltVT = WidenVT.getVectorElementType();
5672 EVT VT = WidenVT;
5673 unsigned NumElts = VT.getVectorNumElements();
5674 while (!TLI.isTypeLegal(VT) && NumElts != 1) {
5675 NumElts = NumElts / 2;
5676 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5677 }
5678
5679 // No legal vector version so unroll the vector operation and then widen.
5680 if (NumElts == 1)
5681 return UnrollVectorOp_StrictFP(N, WidenVT.getVectorNumElements());
5682
5683 // Since the operation can trap, apply operation on the original vector.
5684 EVT MaxVT = VT;
5686 unsigned CurNumElts = N->getValueType(0).getVectorNumElements();
5687
5688 SmallVector<SDValue, 16> ConcatOps(CurNumElts);
5690 unsigned ConcatEnd = 0; // Current ConcatOps index.
5691 int Idx = 0; // Current Idx into input vectors.
5692
5693 // The Chain is the first operand.
5694 InOps.push_back(N->getOperand(0));
5695
5696 // Now process the remaining operands.
5697 for (unsigned i = 1; i < NumOpers; ++i) {
5698 SDValue Oper = N->getOperand(i);
5699
5700 EVT OpVT = Oper.getValueType();
5701 if (OpVT.isVector()) {
5702 if (getTypeAction(OpVT) == TargetLowering::TypeWidenVector)
5703 Oper = GetWidenedVector(Oper);
5704 else {
5705 EVT WideOpVT =
5706 EVT::getVectorVT(*DAG.getContext(), OpVT.getVectorElementType(),
5707 WidenVT.getVectorElementCount());
5708 Oper = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WideOpVT,
5709 DAG.getPOISON(WideOpVT), Oper,
5710 DAG.getVectorIdxConstant(0, dl));
5711 }
5712 }
5713
5714 InOps.push_back(Oper);
5715 }
5716
5717 // NumElts := greatest legal vector size (at most WidenVT)
5718 // while (orig. vector has unhandled elements) {
5719 // take munches of size NumElts from the beginning and add to ConcatOps
5720 // NumElts := next smaller supported vector size or 1
5721 // }
5722 while (CurNumElts != 0) {
5723 while (CurNumElts >= NumElts) {
5725
5726 for (unsigned i = 0; i < NumOpers; ++i) {
5727 SDValue Op = InOps[i];
5728
5729 EVT OpVT = Op.getValueType();
5730 if (OpVT.isVector()) {
5731 EVT OpExtractVT =
5732 EVT::getVectorVT(*DAG.getContext(), OpVT.getVectorElementType(),
5734 Op = DAG.getExtractSubvector(dl, OpExtractVT, Op, Idx);
5735 }
5736
5737 EOps.push_back(Op);
5738 }
5739
5740 EVT OperVT[] = {VT, MVT::Other};
5741 SDValue Oper = DAG.getNode(Opcode, dl, OperVT, EOps);
5742 ConcatOps[ConcatEnd++] = Oper;
5743 Chains.push_back(Oper.getValue(1));
5744 Idx += NumElts;
5745 CurNumElts -= NumElts;
5746 }
5747 do {
5748 NumElts = NumElts / 2;
5749 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5750 } while (!TLI.isTypeLegal(VT) && NumElts != 1);
5751
5752 if (NumElts == 1) {
5753 for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
5755
5756 for (unsigned i = 0; i < NumOpers; ++i) {
5757 SDValue Op = InOps[i];
5758
5759 EVT OpVT = Op.getValueType();
5760 if (OpVT.isVector())
5761 Op = DAG.getExtractVectorElt(dl, OpVT.getVectorElementType(), Op,
5762 Idx);
5763
5764 EOps.push_back(Op);
5765 }
5766
5767 EVT WidenVT[] = {WidenEltVT, MVT::Other};
5768 SDValue Oper = DAG.getNode(Opcode, dl, WidenVT, EOps);
5769 ConcatOps[ConcatEnd++] = Oper;
5770 Chains.push_back(Oper.getValue(1));
5771 }
5772 CurNumElts = 0;
5773 }
5774 }
5775
5776 // Build a factor node to remember all the Ops that have been created.
5777 SDValue NewChain;
5778 if (Chains.size() == 1)
5779 NewChain = Chains[0];
5780 else
5781 NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
5782 ReplaceValueWith(SDValue(N, 1), NewChain);
5783
5784 return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
5785}
5786
5787SDValue DAGTypeLegalizer::WidenVecRes_OverflowOp(SDNode *N, unsigned ResNo) {
5788 SDLoc DL(N);
5789 EVT ResVT = N->getValueType(0);
5790 EVT OvVT = N->getValueType(1);
5791 EVT WideResVT, WideOvVT;
5792 SDValue WideLHS, WideRHS;
5793
5794 // TODO: This might result in a widen/split loop.
5795 if (ResNo == 0) {
5796 WideResVT = TLI.getTypeToTransformTo(*DAG.getContext(), ResVT);
5797 WideOvVT = EVT::getVectorVT(
5798 *DAG.getContext(), OvVT.getVectorElementType(),
5799 WideResVT.getVectorNumElements());
5800
5801 WideLHS = GetWidenedVector(N->getOperand(0));
5802 WideRHS = GetWidenedVector(N->getOperand(1));
5803 } else {
5804 WideOvVT = TLI.getTypeToTransformTo(*DAG.getContext(), OvVT);
5805 WideResVT = EVT::getVectorVT(
5806 *DAG.getContext(), ResVT.getVectorElementType(),
5807 WideOvVT.getVectorNumElements());
5808
5809 SDValue Zero = DAG.getVectorIdxConstant(0, DL);
5810 SDValue Poison = DAG.getPOISON(WideResVT);
5811
5812 WideLHS = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideResVT, Poison,
5813 N->getOperand(0), Zero);
5814 WideRHS = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideResVT, Poison,
5815 N->getOperand(1), Zero);
5816 }
5817
5818 SDVTList WideVTs = DAG.getVTList(WideResVT, WideOvVT);
5819 SDNode *WideNode = DAG.getNode(
5820 N->getOpcode(), DL, WideVTs, WideLHS, WideRHS).getNode();
5821
5822 // Replace the other vector result not being explicitly widened here.
5823 unsigned OtherNo = 1 - ResNo;
5824 EVT OtherVT = N->getValueType(OtherNo);
5825 if (getTypeAction(OtherVT) == TargetLowering::TypeWidenVector) {
5826 SetWidenedVector(SDValue(N, OtherNo), SDValue(WideNode, OtherNo));
5827 } else {
5828 SDValue Zero = DAG.getVectorIdxConstant(0, DL);
5829 SDValue OtherVal = DAG.getNode(
5830 ISD::EXTRACT_SUBVECTOR, DL, OtherVT, SDValue(WideNode, OtherNo), Zero);
5831 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
5832 }
5833
5834 return SDValue(WideNode, ResNo);
5835}
5836
5837SDValue DAGTypeLegalizer::WidenVecRes_Convert(SDNode *N) {
5838 LLVMContext &Ctx = *DAG.getContext();
5839 SDValue InOp = N->getOperand(0);
5840 SDLoc DL(N);
5841
5842 EVT WidenVT = TLI.getTypeToTransformTo(Ctx, N->getValueType(0));
5843 ElementCount WidenEC = WidenVT.getVectorElementCount();
5844
5845 EVT InVT = InOp.getValueType();
5846
5847 unsigned Opcode = N->getOpcode();
5848 const SDNodeFlags Flags = N->getFlags();
5849
5850 // Handle the case of ZERO_EXTEND where the promoted InVT element size does
5851 // not equal that of WidenVT.
5852 if (N->getOpcode() == ISD::ZERO_EXTEND &&
5853 getTypeAction(InVT) == TargetLowering::TypePromoteInteger &&
5854 TLI.getTypeToTransformTo(Ctx, InVT).getScalarSizeInBits() !=
5855 WidenVT.getScalarSizeInBits()) {
5856 InOp = ZExtPromotedInteger(InOp);
5857 InVT = InOp.getValueType();
5858 if (WidenVT.getScalarSizeInBits() < InVT.getScalarSizeInBits())
5859 Opcode = ISD::TRUNCATE;
5860 }
5861
5862 EVT InEltVT = InVT.getVectorElementType();
5863 EVT InWidenVT = EVT::getVectorVT(Ctx, InEltVT, WidenEC);
5864 ElementCount InVTEC = InVT.getVectorElementCount();
5865
5866 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
5867 InOp = GetWidenedVector(N->getOperand(0));
5868 InVT = InOp.getValueType();
5869 InVTEC = InVT.getVectorElementCount();
5870 if (InVTEC == WidenEC) {
5871 if (N->getNumOperands() == 1)
5872 return DAG.getNode(Opcode, DL, WidenVT, InOp, Flags);
5873 if (N->getNumOperands() == 3) {
5874 assert(N->isVPOpcode() && "Expected VP opcode");
5875 SDValue Mask =
5876 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
5877 return DAG.getNode(Opcode, DL, WidenVT, InOp, Mask, N->getOperand(2));
5878 }
5879 return DAG.getNode(Opcode, DL, WidenVT, InOp, N->getOperand(1), Flags);
5880 }
5881 if (WidenVT.getSizeInBits() == InVT.getSizeInBits()) {
5882 // If both input and result vector types are of same width, extend
5883 // operations should be done with SIGN/ZERO_EXTEND_VECTOR_INREG, which
5884 // accepts fewer elements in the result than in the input.
5885 if (Opcode == ISD::ANY_EXTEND)
5886 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
5887 if (Opcode == ISD::SIGN_EXTEND)
5888 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
5889 if (Opcode == ISD::ZERO_EXTEND)
5890 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
5891 }
5892
5893 // For TRUNCATE, try to widen using the legal EC of the input type instead
5894 // if the legalisation action for that intermediate type is not widening.
5895 // E.g. for trunc nxv1i64 -> nxv1i8 where
5896 // - nxv1i64 input gets widened to nxv2i64
5897 // - nxv1i8 output gets widened to nxv16i8
5898 // Then one can try widening the result to nxv2i8 (instead of going all the
5899 // way to nxv16i8) if this later allows type promotion.
5900 EVT MidResVT =
5901 EVT::getVectorVT(Ctx, WidenVT.getVectorElementType(), InVTEC);
5902 if (N->getOpcode() == ISD::TRUNCATE &&
5903 getTypeAction(MidResVT) == TargetLowering::TypePromoteInteger) {
5904 SDValue MidRes = DAG.getNode(ISD::TRUNCATE, DL, MidResVT, InOp, Flags);
5905 return DAG.getInsertSubvector(DL, DAG.getPOISON(WidenVT), MidRes, 0);
5906 }
5907 }
5908
5909 if (TLI.isTypeLegal(InWidenVT)) {
5910 // Because the result and the input are different vector types, widening
5911 // the result could create a legal type but widening the input might make
5912 // it an illegal type that might lead to repeatedly splitting the input
5913 // and then widening it. To avoid this, we widen the input only if
5914 // it results in a legal type.
5915 if (WidenEC.isKnownMultipleOf(InVTEC.getKnownMinValue())) {
5916 // Widen the input and call convert on the widened input vector.
5917 unsigned NumConcat =
5918 WidenEC.getKnownMinValue() / InVTEC.getKnownMinValue();
5919 SmallVector<SDValue, 16> Ops(NumConcat, DAG.getPOISON(InVT));
5920 Ops[0] = InOp;
5921 SDValue InVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InWidenVT, Ops);
5922 if (N->getNumOperands() == 1)
5923 return DAG.getNode(Opcode, DL, WidenVT, InVec, Flags);
5924 return DAG.getNode(Opcode, DL, WidenVT, InVec, N->getOperand(1), Flags);
5925 }
5926
5927 if (InVTEC.isKnownMultipleOf(WidenEC.getKnownMinValue())) {
5928 SDValue InVal = DAG.getExtractSubvector(DL, InWidenVT, InOp, 0);
5929 // Extract the input and convert the shorten input vector.
5930 if (N->getNumOperands() == 1)
5931 return DAG.getNode(Opcode, DL, WidenVT, InVal, Flags);
5932 return DAG.getNode(Opcode, DL, WidenVT, InVal, N->getOperand(1), Flags);
5933 }
5934 }
5935
5936 // Otherwise unroll into some nasty scalar code and rebuild the vector.
5937 EVT EltVT = WidenVT.getVectorElementType();
5938 SmallVector<SDValue, 16> Ops(WidenEC.getFixedValue(), DAG.getPOISON(EltVT));
5939 // Use the original element count so we don't do more scalar opts than
5940 // necessary.
5941 unsigned MinElts = N->getValueType(0).getVectorNumElements();
5942 for (unsigned i=0; i < MinElts; ++i) {
5943 SDValue Val = DAG.getExtractVectorElt(DL, InEltVT, InOp, i);
5944 if (N->getNumOperands() == 1)
5945 Ops[i] = DAG.getNode(Opcode, DL, EltVT, Val, Flags);
5946 else
5947 Ops[i] = DAG.getNode(Opcode, DL, EltVT, Val, N->getOperand(1), Flags);
5948 }
5949
5950 return DAG.getBuildVector(WidenVT, DL, Ops);
5951}
5952
5953SDValue DAGTypeLegalizer::WidenVecRes_FP_TO_XINT_SAT(SDNode *N) {
5954 SDLoc dl(N);
5955 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5956 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
5957
5958 SDValue Src = N->getOperand(0);
5959 EVT SrcVT = Src.getValueType();
5960
5961 // Also widen the input.
5962 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
5963 Src = GetWidenedVector(Src);
5964 SrcVT = Src.getValueType();
5965 }
5966
5967 // Input and output not widened to the same size, give up.
5968 if (WidenNumElts != SrcVT.getVectorElementCount())
5969 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
5970
5971 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src, N->getOperand(1));
5972}
5973
5974SDValue DAGTypeLegalizer::WidenVecRes_XROUND(SDNode *N) {
5975 SDLoc dl(N);
5976 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5977 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
5978
5979 SDValue Src = N->getOperand(0);
5980 EVT SrcVT = Src.getValueType();
5981
5982 // Also widen the input.
5983 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
5984 Src = GetWidenedVector(Src);
5985 SrcVT = Src.getValueType();
5986 }
5987
5988 // Input and output not widened to the same size, give up.
5989 if (WidenNumElts != SrcVT.getVectorElementCount())
5990 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
5991
5992 if (N->getNumOperands() == 1)
5993 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src);
5994
5995 assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
5996 assert(N->isVPOpcode() && "Expected VP opcode");
5997
5998 SDValue Mask =
5999 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
6000 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src, Mask, N->getOperand(2));
6001}
6002
6003SDValue DAGTypeLegalizer::WidenVecRes_Convert_StrictFP(SDNode *N) {
6004 SDValue InOp = N->getOperand(1);
6005 SDLoc DL(N);
6006 SmallVector<SDValue, 4> NewOps(N->ops());
6007
6008 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6009 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6010
6011 EVT InVT = InOp.getValueType();
6012 EVT InEltVT = InVT.getVectorElementType();
6013
6014 unsigned Opcode = N->getOpcode();
6015
6016 // FIXME: Optimizations need to be implemented here.
6017
6018 // Otherwise unroll into some nasty scalar code and rebuild the vector.
6019 EVT EltVT = WidenVT.getVectorElementType();
6020 std::array<EVT, 2> EltVTs = {{EltVT, MVT::Other}};
6021 SmallVector<SDValue, 16> Ops(WidenNumElts, DAG.getPOISON(EltVT));
6022 SmallVector<SDValue, 32> OpChains;
6023 // Use the original element count so we don't do more scalar opts than
6024 // necessary.
6025 unsigned MinElts = N->getValueType(0).getVectorNumElements();
6026 for (unsigned i=0; i < MinElts; ++i) {
6027 NewOps[1] = DAG.getExtractVectorElt(DL, InEltVT, InOp, i);
6028 Ops[i] = DAG.getNode(Opcode, DL, EltVTs, NewOps);
6029 OpChains.push_back(Ops[i].getValue(1));
6030 }
6031 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OpChains);
6032 ReplaceValueWith(SDValue(N, 1), NewChain);
6033
6034 return DAG.getBuildVector(WidenVT, DL, Ops);
6035}
6036
6037SDValue DAGTypeLegalizer::WidenVecRes_EXTEND_VECTOR_INREG(SDNode *N) {
6038 unsigned Opcode = N->getOpcode();
6039 SDValue InOp = N->getOperand(0);
6040 SDLoc DL(N);
6041
6042 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6043 EVT WidenSVT = WidenVT.getVectorElementType();
6044 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6045
6046 EVT InVT = InOp.getValueType();
6047 EVT InSVT = InVT.getVectorElementType();
6048 unsigned InVTNumElts = InVT.getVectorNumElements();
6049
6050 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
6051 InOp = GetWidenedVector(InOp);
6052 InVT = InOp.getValueType();
6053 if (InVT.getSizeInBits() == WidenVT.getSizeInBits()) {
6054 switch (Opcode) {
6058 return DAG.getNode(Opcode, DL, WidenVT, InOp);
6059 }
6060 }
6061 }
6062
6063 // Unroll, extend the scalars and rebuild the vector.
6065 for (unsigned i = 0, e = std::min(InVTNumElts, WidenNumElts); i != e; ++i) {
6066 SDValue Val = DAG.getExtractVectorElt(DL, InSVT, InOp, i);
6067 switch (Opcode) {
6069 Val = DAG.getNode(ISD::ANY_EXTEND, DL, WidenSVT, Val);
6070 break;
6072 Val = DAG.getNode(ISD::SIGN_EXTEND, DL, WidenSVT, Val);
6073 break;
6075 Val = DAG.getNode(ISD::ZERO_EXTEND, DL, WidenSVT, Val);
6076 break;
6077 default:
6078 llvm_unreachable("A *_EXTEND_VECTOR_INREG node was expected");
6079 }
6080 Ops.push_back(Val);
6081 }
6082
6083 while (Ops.size() != WidenNumElts)
6084 Ops.push_back(DAG.getPOISON(WidenSVT));
6085
6086 return DAG.getBuildVector(WidenVT, DL, Ops);
6087}
6088
6089SDValue DAGTypeLegalizer::WidenVecRes_FCOPYSIGN(SDNode *N) {
6090 // If this is an FCOPYSIGN with same input types, we can treat it as a
6091 // normal (can trap) binary op.
6092 if (N->getOperand(0).getValueType() == N->getOperand(1).getValueType())
6093 return WidenVecRes_BinaryCanTrap(N);
6094
6095 // If the types are different, fall back to unrolling.
6096 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6097 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
6098}
6099
6100/// Result and first source operand are different scalar types, but must have
6101/// the same number of elements. There is an additional control argument which
6102/// should be passed through unchanged.
6103SDValue DAGTypeLegalizer::WidenVecRes_UnarySameEltsWithScalarArg(SDNode *N) {
6104 SDValue FpValue = N->getOperand(0);
6105 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6106 if (getTypeAction(FpValue.getValueType()) != TargetLowering::TypeWidenVector)
6107 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
6108 SDValue Arg = GetWidenedVector(FpValue);
6109 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, {Arg, N->getOperand(1)},
6110 N->getFlags());
6111}
6112
6113SDValue DAGTypeLegalizer::WidenVecRes_ExpOp(SDNode *N) {
6114 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6115 SDValue InOp = GetWidenedVector(N->getOperand(0));
6116 SDValue RHS = N->getOperand(1);
6117 EVT ExpVT = RHS.getValueType();
6118 SDValue ExpOp = RHS;
6119 if (ExpVT.isVector()) {
6120 EVT WideExpVT = WidenVT.changeVectorElementType(
6121 *DAG.getContext(), ExpVT.getVectorElementType());
6122 ExpOp = ModifyToType(RHS, WideExpVT);
6123 }
6124
6125 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, ExpOp);
6126}
6127
6128SDValue DAGTypeLegalizer::WidenVecRes_Unary(SDNode *N) {
6129 // Unary op widening.
6130 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6131 SDValue InOp = GetWidenedVector(N->getOperand(0));
6132 if (N->getNumOperands() == 1)
6133 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, N->getFlags());
6134 if (N->getOpcode() == ISD::AssertNoFPClass)
6135 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp,
6136 N->getOperand(1), N->getFlags());
6137
6138 assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
6139 assert(N->isVPOpcode() && "Expected VP opcode");
6140
6141 SDValue Mask =
6142 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
6143 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT,
6144 {InOp, Mask, N->getOperand(2)});
6145}
6146
6147SDValue DAGTypeLegalizer::WidenVecRes_InregOp(SDNode *N) {
6148 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6149 EVT ExtVT = EVT::getVectorVT(*DAG.getContext(),
6150 cast<VTSDNode>(N->getOperand(1))->getVT()
6151 .getVectorElementType(),
6152 WidenVT.getVectorNumElements());
6153 SDValue WidenLHS = GetWidenedVector(N->getOperand(0));
6154 return DAG.getNode(N->getOpcode(), SDLoc(N),
6155 WidenVT, WidenLHS, DAG.getValueType(ExtVT));
6156}
6157
6158SDValue DAGTypeLegalizer::WidenVecRes_UnaryOpWithTwoResults(SDNode *N,
6159 unsigned ResNo) {
6160 EVT VT0 = N->getValueType(0);
6161 EVT VT1 = N->getValueType(1);
6162
6163 assert(VT0.isVector() && VT1.isVector() &&
6165 "expected both results to be vectors of matching element count");
6166
6167 LLVMContext &Ctx = *DAG.getContext();
6168 SDValue InOp = GetWidenedVector(N->getOperand(0));
6169
6170 EVT WidenVT = TLI.getTypeToTransformTo(Ctx, N->getValueType(ResNo));
6171 ElementCount WidenEC = WidenVT.getVectorElementCount();
6172
6173 EVT WidenVT0 = EVT::getVectorVT(Ctx, VT0.getVectorElementType(), WidenEC);
6174 EVT WidenVT1 = EVT::getVectorVT(Ctx, VT1.getVectorElementType(), WidenEC);
6175
6176 SDNode *WidenNode =
6177 DAG.getNode(N->getOpcode(), SDLoc(N), {WidenVT0, WidenVT1}, InOp)
6178 .getNode();
6179
6180 ReplaceOtherWidenResults(N, WidenNode, ResNo);
6181 return SDValue(WidenNode, ResNo);
6182}
6183
6184SDValue DAGTypeLegalizer::WidenVecRes_MERGE_VALUES(SDNode *N, unsigned ResNo) {
6185 SDValue WidenVec = DisintegrateMERGE_VALUES(N, ResNo);
6186 return GetWidenedVector(WidenVec);
6187}
6188
6189SDValue DAGTypeLegalizer::WidenVecRes_ADDRSPACECAST(SDNode *N) {
6190 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6191 SDValue InOp = GetWidenedVector(N->getOperand(0));
6192 auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
6193
6194 return DAG.getAddrSpaceCast(SDLoc(N), WidenVT, InOp,
6195 AddrSpaceCastN->getSrcAddressSpace(),
6196 AddrSpaceCastN->getDestAddressSpace());
6197}
6198
6199SDValue DAGTypeLegalizer::WidenVecRes_BITCAST(SDNode *N) {
6200 SDValue InOp = N->getOperand(0);
6201 EVT InVT = InOp.getValueType();
6202 EVT VT = N->getValueType(0);
6203 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6204 SDLoc dl(N);
6205
6206 switch (getTypeAction(InVT)) {
6208 break;
6210 report_fatal_error("Scalarization of scalable vectors is not supported.");
6212 // If the incoming type is a vector that is being promoted, then
6213 // we know that the elements are arranged differently and that we
6214 // must perform the conversion using a stack slot.
6215 if (InVT.isVector())
6216 break;
6217
6218 // If the InOp is promoted to the same size, convert it. Otherwise,
6219 // fall out of the switch and widen the promoted input.
6220 SDValue NInOp = GetPromotedInteger(InOp);
6221 EVT NInVT = NInOp.getValueType();
6222 if (WidenVT.bitsEq(NInVT)) {
6223 // For big endian targets we need to shift the input integer or the
6224 // interesting bits will end up at the wrong place.
6225 if (DAG.getDataLayout().isBigEndian()) {
6226 unsigned ShiftAmt = NInVT.getSizeInBits() - InVT.getSizeInBits();
6227 NInOp = DAG.getNode(ISD::SHL, dl, NInVT, NInOp,
6228 DAG.getShiftAmountConstant(ShiftAmt, NInVT, dl));
6229 }
6230 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NInOp);
6231 }
6232 InOp = NInOp;
6233 InVT = NInVT;
6234 break;
6235 }
6242 break;
6244 // If the InOp is widened to the same size, convert it. Otherwise, fall
6245 // out of the switch and widen the widened input.
6246 InOp = GetWidenedVector(InOp);
6247 InVT = InOp.getValueType();
6248 if (WidenVT.bitsEq(InVT))
6249 // The input widens to the same size. Convert to the widen value.
6250 return DAG.getNode(ISD::BITCAST, dl, WidenVT, InOp);
6251 break;
6252 }
6253
6254 unsigned WidenSize = WidenVT.getSizeInBits();
6255 unsigned InSize = InVT.getSizeInBits();
6256 unsigned InScalarSize = InVT.getScalarSizeInBits();
6257 // x86mmx is not an acceptable vector element type, so don't try.
6258 if (WidenSize % InScalarSize == 0 && InVT != MVT::x86mmx) {
6259 // Determine new input vector type. The new input vector type will use
6260 // the same element type (if its a vector) or use the input type as a
6261 // vector. It is the same size as the type to widen to.
6262 EVT NewInVT;
6263 unsigned NewNumParts = WidenSize / InSize;
6264 if (InVT.isVector()) {
6265 EVT InEltVT = InVT.getVectorElementType();
6266 NewInVT = EVT::getVectorVT(*DAG.getContext(), InEltVT,
6267 WidenSize / InEltVT.getSizeInBits());
6268 } else {
6269 // For big endian systems, using the promoted input scalar type
6270 // to produce the scalar_to_vector would put the desired bits into
6271 // the least significant byte(s) of the wider element zero. This
6272 // will mean that the users of the result vector are using incorrect
6273 // bits. Use the original input type instead. Although either input
6274 // type can be used on little endian systems, for consistency we
6275 // use the original type there as well.
6276 EVT OrigInVT = N->getOperand(0).getValueType();
6277 NewNumParts = WidenSize / OrigInVT.getSizeInBits();
6278 NewInVT = EVT::getVectorVT(*DAG.getContext(), OrigInVT, NewNumParts);
6279 }
6280
6281 if (TLI.isTypeLegal(NewInVT)) {
6282 SDValue NewVec;
6283 if (InVT.isVector()) {
6284 // Because the result and the input are different vector types, widening
6285 // the result could create a legal type but widening the input might
6286 // make it an illegal type that might lead to repeatedly splitting the
6287 // input and then widening it. To avoid this, we widen the input only if
6288 // it results in a legal type.
6289 if (WidenSize % InSize == 0) {
6290 SmallVector<SDValue, 16> Ops(NewNumParts, DAG.getPOISON(InVT));
6291 Ops[0] = InOp;
6292
6293 NewVec = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewInVT, Ops);
6294 } else {
6296 DAG.ExtractVectorElements(InOp, Ops);
6297 Ops.append(WidenSize / InScalarSize - Ops.size(),
6298 DAG.getPOISON(InVT.getVectorElementType()));
6299
6300 NewVec = DAG.getNode(ISD::BUILD_VECTOR, dl, NewInVT, Ops);
6301 }
6302 } else {
6303 NewVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewInVT, InOp);
6304 }
6305 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NewVec);
6306 }
6307 }
6308
6309 return CreateStackStoreLoad(InOp, WidenVT);
6310}
6311
6312SDValue DAGTypeLegalizer::WidenVecRes_LOOP_DEPENDENCE_MASK(SDNode *N) {
6313 return DAG.getNode(
6314 N->getOpcode(), SDLoc(N),
6315 TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)),
6316 N->getOperand(0), N->getOperand(1), N->getOperand(2), N->getOperand(3));
6317}
6318
6319SDValue DAGTypeLegalizer::WidenVecRes_BUILD_VECTOR(SDNode *N) {
6320 SDLoc dl(N);
6321 // Build a vector with poison for the new nodes.
6322 EVT VT = N->getValueType(0);
6323
6324 // Integer BUILD_VECTOR operands may be larger than the node's vector element
6325 // type. The POISONs need to have the same type as the existing operands.
6326 EVT EltVT = N->getOperand(0).getValueType();
6327 unsigned NumElts = VT.getVectorNumElements();
6328
6329 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6330 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6331
6332 SmallVector<SDValue, 16> NewOps(N->ops());
6333 assert(WidenNumElts >= NumElts && "Shrinking vector instead of widening!");
6334 NewOps.append(WidenNumElts - NumElts, DAG.getPOISON(EltVT));
6335
6336 return DAG.getBuildVector(WidenVT, dl, NewOps);
6337}
6338
6339SDValue DAGTypeLegalizer::WidenVecRes_CONCAT_VECTORS(SDNode *N) {
6340 EVT InVT = N->getOperand(0).getValueType();
6341 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6342 SDLoc dl(N);
6343 unsigned NumOperands = N->getNumOperands();
6344
6345 bool InputWidened = false; // Indicates we need to widen the input.
6346 if (getTypeAction(InVT) != TargetLowering::TypeWidenVector) {
6347 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6348 unsigned NumInElts = InVT.getVectorMinNumElements();
6349 if (WidenNumElts % NumInElts == 0) {
6350 // Add undef vectors to widen to correct length.
6351 unsigned NumConcat = WidenNumElts / NumInElts;
6352 SDValue UndefVal = DAG.getPOISON(InVT);
6353 SmallVector<SDValue, 16> Ops(NumConcat);
6354 for (unsigned i=0; i < NumOperands; ++i)
6355 Ops[i] = N->getOperand(i);
6356 for (unsigned i = NumOperands; i != NumConcat; ++i)
6357 Ops[i] = UndefVal;
6358 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Ops);
6359 }
6360 } else {
6361 InputWidened = true;
6362 if (WidenVT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
6363 // The inputs and the result are widen to the same value.
6364 unsigned i;
6365 for (i=1; i < NumOperands; ++i)
6366 if (!N->getOperand(i).isUndef())
6367 break;
6368
6369 if (i == NumOperands)
6370 // Everything but the first operand is an UNDEF so just return the
6371 // widened first operand.
6372 return GetWidenedVector(N->getOperand(0));
6373
6374 if (NumOperands == 2) {
6375 assert(!WidenVT.isScalableVector() &&
6376 "Cannot use vector shuffles to widen CONCAT_VECTOR result");
6377 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6378 unsigned NumInElts = InVT.getVectorNumElements();
6379
6380 // Replace concat of two operands with a shuffle.
6381 SmallVector<int, 16> MaskOps(WidenNumElts, -1);
6382 for (unsigned i = 0; i < NumInElts; ++i) {
6383 MaskOps[i] = i;
6384 MaskOps[i + NumInElts] = i + WidenNumElts;
6385 }
6386 return DAG.getVectorShuffle(WidenVT, dl,
6387 GetWidenedVector(N->getOperand(0)),
6388 GetWidenedVector(N->getOperand(1)),
6389 MaskOps);
6390 }
6391 }
6392 }
6393
6394 assert(!WidenVT.isScalableVector() &&
6395 "Cannot use build vectors to widen CONCAT_VECTOR result");
6396 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6397 unsigned NumInElts = InVT.getVectorNumElements();
6398
6399 // Fall back to use extracts and build vector.
6400 EVT EltVT = WidenVT.getVectorElementType();
6401 SmallVector<SDValue, 16> Ops(WidenNumElts);
6402 unsigned Idx = 0;
6403 for (unsigned i=0; i < NumOperands; ++i) {
6404 SDValue InOp = N->getOperand(i);
6405 if (InputWidened)
6406 InOp = GetWidenedVector(InOp);
6407 for (unsigned j = 0; j < NumInElts; ++j)
6408 Ops[Idx++] = DAG.getExtractVectorElt(dl, EltVT, InOp, j);
6409 }
6410 SDValue UndefVal = DAG.getPOISON(EltVT);
6411 for (; Idx < WidenNumElts; ++Idx)
6412 Ops[Idx] = UndefVal;
6413 return DAG.getBuildVector(WidenVT, dl, Ops);
6414}
6415
6416SDValue DAGTypeLegalizer::WidenVecRes_INSERT_SUBVECTOR(SDNode *N) {
6417 EVT VT = N->getValueType(0);
6418 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6419 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
6420 SDValue InOp2 = N->getOperand(1);
6421 SDValue Idx = N->getOperand(2);
6422 SDLoc dl(N);
6423 return DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WidenVT, InOp1, InOp2, Idx);
6424}
6425
6426SDValue DAGTypeLegalizer::WidenVecRes_EXTRACT_SUBVECTOR(SDNode *N) {
6427 EVT VT = N->getValueType(0);
6428 EVT EltVT = VT.getVectorElementType();
6429 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6430 SDValue InOp = N->getOperand(0);
6431 SDValue Idx = N->getOperand(1);
6432 SDLoc dl(N);
6433
6434 auto InOpTypeAction = getTypeAction(InOp.getValueType());
6435 if (InOpTypeAction == TargetLowering::TypeWidenVector)
6436 InOp = GetWidenedVector(InOp);
6437
6438 EVT InVT = InOp.getValueType();
6439
6440 // Check if we can just return the input vector after widening.
6441 uint64_t IdxVal = Idx->getAsZExtVal();
6442 if (IdxVal == 0 && InVT == WidenVT)
6443 return InOp;
6444
6445 // Check if we can extract from the vector.
6446 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6447 unsigned InNumElts = InVT.getVectorMinNumElements();
6448 unsigned VTNumElts = VT.getVectorMinNumElements();
6449 assert(IdxVal % VTNumElts == 0 &&
6450 "Expected Idx to be a multiple of subvector minimum vector length");
6451 if (IdxVal % WidenNumElts == 0 && IdxVal + WidenNumElts < InNumElts)
6452 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, WidenVT, InOp, Idx);
6453
6454 if (VT.isScalableVector()) {
6455 // Try to split the operation up into smaller extracts and concat the
6456 // results together, e.g.
6457 // nxv6i64 extract_subvector(nxv12i64, 6)
6458 // <->
6459 // nxv8i64 concat(
6460 // nxv2i64 extract_subvector(nxv16i64, 6)
6461 // nxv2i64 extract_subvector(nxv16i64, 8)
6462 // nxv2i64 extract_subvector(nxv16i64, 10)
6463 // undef)
6464 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
6465 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
6466 "down type's element count");
6467 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
6469 // Avoid recursion around e.g. nxv1i8.
6470 if (getTypeAction(PartVT) != TargetLowering::TypeWidenVector) {
6472 unsigned I = 0;
6473 for (; I < VTNumElts / GCD; ++I)
6474 Parts.push_back(
6475 DAG.getExtractSubvector(dl, PartVT, InOp, IdxVal + I * GCD));
6476 for (; I < WidenNumElts / GCD; ++I)
6477 Parts.push_back(DAG.getPOISON(PartVT));
6478
6479 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
6480 }
6481
6482 // Fallback to extracting through memory.
6483
6484 Align Alignment = DAG.getReducedAlign(InVT, /*UseABI=*/false);
6485 SDValue StackPtr = DAG.CreateStackTemporary(InVT.getStoreSize(), Alignment);
6486 MachineFunction &MF = DAG.getMachineFunction();
6487 int FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
6488 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
6489
6490 MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
6493 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
6496
6497 // Write out the input vector.
6498 SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, InOp, StackPtr, StoreMMO);
6499
6500 // Build a mask to match the length of the non-widened result.
6501 SDValue Mask =
6502 DAG.getMaskFromElementCount(dl, WidenVT, VT.getVectorElementCount());
6503
6504 // Read back the sub-vector setting the remaining lanes to poison.
6505 StackPtr = TLI.getVectorSubVecPointer(DAG, StackPtr, InVT, VT, Idx);
6506 return DAG.getMaskedLoad(
6507 WidenVT, dl, Ch, StackPtr, DAG.getPOISON(StackPtr.getValueType()), Mask,
6508 DAG.getPOISON(WidenVT), VT, LoadMMO, ISD::UNINDEXED, ISD::NON_EXTLOAD);
6509 }
6510
6511 // We could try widening the input to the right length but for now, extract
6512 // the original elements, fill the rest with undefs and build a vector.
6513 SmallVector<SDValue, 16> Ops(WidenNumElts);
6514 unsigned i;
6515 for (i = 0; i < VTNumElts; ++i)
6516 Ops[i] = DAG.getExtractVectorElt(dl, EltVT, InOp, IdxVal + i);
6517
6518 SDValue UndefVal = DAG.getPOISON(EltVT);
6519 for (; i < WidenNumElts; ++i)
6520 Ops[i] = UndefVal;
6521 return DAG.getBuildVector(WidenVT, dl, Ops);
6522}
6523
6524SDValue DAGTypeLegalizer::WidenVecRes_AssertZext(SDNode *N) {
6525 SDValue InOp = ModifyToType(
6526 N->getOperand(0),
6527 TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)), true);
6528 return DAG.getNode(ISD::AssertZext, SDLoc(N), InOp.getValueType(), InOp,
6529 N->getOperand(1));
6530}
6531
6532SDValue DAGTypeLegalizer::WidenVecRes_INSERT_VECTOR_ELT(SDNode *N) {
6533 SDValue InOp = GetWidenedVector(N->getOperand(0));
6534 return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(N),
6535 InOp.getValueType(), InOp,
6536 N->getOperand(1), N->getOperand(2));
6537}
6538
6539/// Either return the same load or provide appropriate casts
6540/// from the load and return that.
6541static SDValue coerceLoadedValue(SDValue LdOp, EVT FirstVT, EVT WidenVT,
6542 TypeSize LdWidth, TypeSize FirstVTWidth,
6543 SDLoc dl, SelectionDAG &DAG) {
6544 assert(TypeSize::isKnownLE(LdWidth, FirstVTWidth) &&
6545 "Load width must be less than or equal to first value type width");
6546 TypeSize WidenWidth = WidenVT.getSizeInBits();
6547 if (!FirstVT.isVector()) {
6548 unsigned NumElts =
6549 WidenWidth.getFixedValue() / FirstVTWidth.getFixedValue();
6550 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), FirstVT, NumElts);
6551 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT, LdOp);
6552 return DAG.getNode(ISD::BITCAST, dl, WidenVT, VecOp);
6553 }
6554 assert(FirstVT == WidenVT && "First value type must equal widen value type");
6555 return LdOp;
6556}
6557
6558static std::optional<EVT> findMemType(SelectionDAG &DAG,
6559 const TargetLowering &TLI, unsigned Width,
6560 EVT WidenVT, unsigned Align,
6561 unsigned WidenEx);
6562
6563SDValue DAGTypeLegalizer::WidenVecRes_ATOMIC_LOAD(AtomicSDNode *LD) {
6564 EVT WidenVT =
6565 TLI.getTypeToTransformTo(*DAG.getContext(), LD->getValueType(0));
6566 EVT LdVT = LD->getMemoryVT();
6567 SDLoc dl(LD);
6568 assert(LdVT.isVector() && WidenVT.isVector() && "Expected vectors");
6569 assert(LdVT.isScalableVector() == WidenVT.isScalableVector() &&
6570 "Must be scalable");
6571 assert(LdVT.getVectorElementType() == WidenVT.getVectorElementType() &&
6572 "Expected equivalent element types");
6573
6574 // Load information
6575 SDValue Chain = LD->getChain();
6576 SDValue BasePtr = LD->getBasePtr();
6577
6578 TypeSize LdWidth = LdVT.getSizeInBits();
6579 TypeSize WidenWidth = WidenVT.getSizeInBits();
6580 TypeSize WidthDiff = WidenWidth - LdWidth;
6581
6582 // Find the vector type that can load from.
6583 std::optional<EVT> FirstVT =
6584 findMemType(DAG, TLI, LdWidth.getKnownMinValue(), WidenVT, /*LdAlign=*/0,
6585 WidthDiff.getKnownMinValue());
6586
6587 if (!FirstVT)
6588 return SDValue();
6589
6590 SmallVector<EVT, 8> MemVTs;
6591 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
6592
6593 SDValue LdOp = DAG.getAtomicLoad(ISD::NON_EXTLOAD, dl, *FirstVT, *FirstVT,
6594 Chain, BasePtr, LD->getMemOperand());
6595
6596 // Load the element with one instruction.
6597 SDValue Result = coerceLoadedValue(LdOp, *FirstVT, WidenVT, LdWidth,
6598 FirstVTWidth, dl, DAG);
6599
6600 // Modified the chain - switch anything that used the old chain to use
6601 // the new one.
6602 ReplaceValueWith(SDValue(LD, 1), LdOp.getValue(1));
6603 return Result;
6604}
6605
6606SDValue DAGTypeLegalizer::WidenVecRes_LOAD(SDNode *N) {
6607 LoadSDNode *LD = cast<LoadSDNode>(N);
6608 ISD::LoadExtType ExtType = LD->getExtensionType();
6609
6610 // A vector must always be stored in memory as-is, i.e. without any padding
6611 // between the elements, since various code depend on it, e.g. in the
6612 // handling of a bitcast of a vector type to int, which may be done with a
6613 // vector store followed by an integer load. A vector that does not have
6614 // elements that are byte-sized must therefore be stored as an integer
6615 // built out of the extracted vector elements.
6616 if (!LD->getMemoryVT().isByteSized()) {
6617 SDValue Value, NewChain;
6618 std::tie(Value, NewChain) = TLI.scalarizeVectorLoad(LD, DAG);
6619 ReplaceValueWith(SDValue(LD, 0), Value);
6620 ReplaceValueWith(SDValue(LD, 1), NewChain);
6621 return SDValue();
6622 }
6623
6624 // Generate a vector-predicated load if it is custom/legal on the target. To
6625 // avoid possible recursion, only do this if the widened mask type is legal.
6626 // FIXME: Not all targets may support EVL in VP_LOAD. These will have been
6627 // removed from the IR by the ExpandVectorPredication pass but we're
6628 // reintroducing them here.
6629 EVT VT = LD->getValueType(0);
6630 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6631 EVT WideMaskVT = getSetCCResultType(WideVT);
6632
6633 if (ExtType == ISD::NON_EXTLOAD &&
6634 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WideVT) &&
6635 TLI.isTypeLegal(WideMaskVT)) {
6636 SDLoc DL(N);
6637 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
6638 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
6640 SDValue NewLoad =
6641 DAG.getLoadVP(LD->getAddressingMode(), ISD::NON_EXTLOAD, WideVT, DL,
6642 LD->getChain(), LD->getBasePtr(), LD->getOffset(), Mask,
6643 EVL, LD->getMemoryVT(), LD->getMemOperand());
6644
6645 // Modified the chain - switch anything that used the old chain to use
6646 // the new one.
6647 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6648
6649 return NewLoad;
6650 }
6651
6653 SmallVector<SDValue, 16> LdChain; // Chain for the series of load
6654 if (ExtType != ISD::NON_EXTLOAD)
6655 Result = GenWidenVectorExtLoads(LdChain, LD, ExtType);
6656 else
6657 Result = GenWidenVectorLoads(LdChain, LD);
6658
6659 if (Result) {
6660 // If we generate a single load, we can use that for the chain. Otherwise,
6661 // build a factor node to remember the multiple loads are independent and
6662 // chain to that.
6663 SDValue NewChain;
6664 if (LdChain.size() == 1)
6665 NewChain = LdChain[0];
6666 else
6667 NewChain = DAG.getNode(ISD::TokenFactor, SDLoc(LD), MVT::Other, LdChain);
6668
6669 // Modified the chain - switch anything that used the old chain to use
6670 // the new one.
6671 ReplaceValueWith(SDValue(N, 1), NewChain);
6672
6673 return Result;
6674 }
6675
6676 if (VT.isVector()) {
6677 // If all else fails replace the load with a wide masked load.
6678 SDLoc DL(N);
6679 SDValue Mask =
6680 DAG.getMaskFromElementCount(DL, WideVT, VT.getVectorElementCount());
6681
6682 SDValue NewLoad = DAG.getMaskedLoad(
6683 WideVT, DL, LD->getChain(), LD->getBasePtr(), LD->getOffset(), Mask,
6684 DAG.getPOISON(WideVT), LD->getMemoryVT(), LD->getMemOperand(),
6685 LD->getAddressingMode(), LD->getExtensionType());
6686
6687 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6688 return NewLoad;
6689 }
6690
6691 report_fatal_error("Unable to widen vector load");
6692}
6693
6694SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD(VPLoadSDNode *N) {
6695 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6696 SDValue Mask = N->getMask();
6697 SDValue EVL = N->getVectorLength();
6698 ISD::LoadExtType ExtType = N->getExtensionType();
6699 SDLoc dl(N);
6700
6701 // The mask should be widened as well
6702 assert(getTypeAction(Mask.getValueType()) ==
6704 "Unable to widen binary VP op");
6705 Mask = GetWidenedVector(Mask);
6706 assert(Mask.getValueType().getVectorElementCount() ==
6707 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
6708 .getVectorElementCount() &&
6709 "Unable to widen vector load");
6710
6711 SDValue Res =
6712 DAG.getLoadVP(N->getAddressingMode(), ExtType, WidenVT, dl, N->getChain(),
6713 N->getBasePtr(), N->getOffset(), Mask, EVL,
6714 N->getMemoryVT(), N->getMemOperand(), N->isExpandingLoad());
6715 // Legalize the chain result - switch anything that used the old chain to
6716 // use the new one.
6717 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6718 return Res;
6719}
6720
6721SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD_FF(VPLoadFFSDNode *N) {
6722 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6723 SDValue Mask = N->getMask();
6724 SDValue EVL = N->getVectorLength();
6725 SDLoc dl(N);
6726
6727 // The mask should be widened as well
6728 assert(getTypeAction(Mask.getValueType()) ==
6730 "Unable to widen binary VP op");
6731 Mask = GetWidenedVector(Mask);
6732 assert(Mask.getValueType().getVectorElementCount() ==
6733 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
6734 .getVectorElementCount() &&
6735 "Unable to widen vector load");
6736
6737 SDValue Res = DAG.getLoadFFVP(WidenVT, dl, N->getChain(), N->getBasePtr(),
6738 Mask, EVL, N->getMemOperand());
6739 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6740 ReplaceValueWith(SDValue(N, 2), Res.getValue(2));
6741 return Res;
6742}
6743
6744SDValue DAGTypeLegalizer::WidenVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode *N) {
6745 SDLoc DL(N);
6746
6747 // The mask should be widened as well
6748 SDValue Mask = N->getMask();
6749 assert(getTypeAction(Mask.getValueType()) ==
6751 "Unable to widen VP strided load");
6752 Mask = GetWidenedVector(Mask);
6753
6754 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6755 assert(Mask.getValueType().getVectorElementCount() ==
6756 WidenVT.getVectorElementCount() &&
6757 "Data and mask vectors should have the same number of elements");
6758
6759 SDValue Res = DAG.getStridedLoadVP(
6760 N->getAddressingMode(), N->getExtensionType(), WidenVT, DL, N->getChain(),
6761 N->getBasePtr(), N->getOffset(), N->getStride(), Mask,
6762 N->getVectorLength(), N->getMemoryVT(), N->getMemOperand(),
6763 N->isExpandingLoad());
6764
6765 // Legalize the chain result - switch anything that used the old chain to
6766 // use the new one.
6767 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6768 return Res;
6769}
6770
6771SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_COMPRESS(SDNode *N) {
6772 SDValue Vec = N->getOperand(0);
6773 SDValue Mask = N->getOperand(1);
6774 SDValue Passthru = N->getOperand(2);
6775 EVT WideVecVT =
6776 TLI.getTypeToTransformTo(*DAG.getContext(), Vec.getValueType());
6777 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
6778 Mask.getValueType().getVectorElementType(),
6779 WideVecVT.getVectorElementCount());
6780
6781 SDValue WideVec = ModifyToType(Vec, WideVecVT);
6782 SDValue WideMask = ModifyToType(Mask, WideMaskVT, /*FillWithZeroes=*/true);
6783 SDValue WidePassthru = ModifyToType(Passthru, WideVecVT);
6784 return DAG.getNode(ISD::VECTOR_COMPRESS, SDLoc(N), WideVecVT, WideVec,
6785 WideMask, WidePassthru);
6786}
6787
6788SDValue DAGTypeLegalizer::WidenVecRes_MLOAD(MaskedLoadSDNode *N) {
6789 EVT VT = N->getValueType(0);
6790 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6791 SDValue Mask = N->getMask();
6792 EVT MaskVT = Mask.getValueType();
6793 SDValue PassThru = GetWidenedVector(N->getPassThru());
6794 ISD::LoadExtType ExtType = N->getExtensionType();
6795 SDLoc dl(N);
6796
6797 EVT WideMaskVT =
6798 EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(),
6799 WidenVT.getVectorElementCount());
6800
6801 if (ExtType == ISD::NON_EXTLOAD &&
6802 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WidenVT) &&
6803 TLI.isTypeLegal(WideMaskVT) &&
6804 // If there is a passthru, we shouldn't use vp.load. However,
6805 // type legalizer will struggle on masked.load with
6806 // scalable vectors, so for scalable vectors, we still use vp.load
6807 // but manually merge the load result with the passthru using vp.select.
6808 (N->getPassThru()->isUndef() || VT.isScalableVector())) {
6809 Mask = DAG.getInsertSubvector(dl, DAG.getPOISON(WideMaskVT), Mask, 0);
6810 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
6812 SDValue NewLoad =
6813 DAG.getLoadVP(N->getAddressingMode(), ISD::NON_EXTLOAD, WidenVT, dl,
6814 N->getChain(), N->getBasePtr(), N->getOffset(), Mask, EVL,
6815 N->getMemoryVT(), N->getMemOperand());
6816 SDValue NewVal = NewLoad;
6817
6818 // Manually merge with vselect
6819 if (!N->getPassThru()->isUndef()) {
6820 assert(WidenVT.isScalableVector());
6821 NewVal = DAG.getNode(ISD::VSELECT, dl, WidenVT, Mask, NewVal, PassThru);
6822 // The lanes past EVL are poison.
6823 NewVal = DAG.getNode(ISD::VP_MERGE, dl, WidenVT,
6824 DAG.getAllOnesConstant(dl, WideMaskVT), NewVal,
6825 DAG.getPOISON(WidenVT), EVL);
6826 }
6827
6828 // Modified the chain - switch anything that used the old chain to use
6829 // the new one.
6830 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6831
6832 return NewVal;
6833 }
6834
6835 // The mask should be widened as well
6836 Mask = ModifyToType(Mask, WideMaskVT, true);
6837
6838 SDValue Res = DAG.getMaskedLoad(
6839 WidenVT, dl, N->getChain(), N->getBasePtr(), N->getOffset(), Mask,
6840 PassThru, N->getMemoryVT(), N->getMemOperand(), N->getAddressingMode(),
6841 ExtType, N->isExpandingLoad());
6842 // Legalize the chain result - switch anything that used the old chain to
6843 // use the new one.
6844 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6845 return Res;
6846}
6847
6848SDValue DAGTypeLegalizer::WidenVecRes_MGATHER(MaskedGatherSDNode *N) {
6849
6850 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6851 SDValue Mask = N->getMask();
6852 EVT MaskVT = Mask.getValueType();
6853 SDValue PassThru = GetWidenedVector(N->getPassThru());
6854 SDValue Scale = N->getScale();
6855 unsigned NumElts = WideVT.getVectorNumElements();
6856 SDLoc dl(N);
6857
6858 // The mask should be widened as well
6859 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
6860 MaskVT.getVectorElementType(),
6861 WideVT.getVectorNumElements());
6862 Mask = ModifyToType(Mask, WideMaskVT, true);
6863
6864 // Widen the Index operand
6865 SDValue Index = N->getIndex();
6866 EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
6867 Index.getValueType().getScalarType(),
6868 NumElts);
6869 Index = ModifyToType(Index, WideIndexVT);
6870 SDValue Ops[] = { N->getChain(), PassThru, Mask, N->getBasePtr(), Index,
6871 Scale };
6872
6873 // Widen the MemoryType
6874 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
6875 N->getMemoryVT().getScalarType(), NumElts);
6876 SDValue Res = DAG.getMaskedGather(DAG.getVTList(WideVT, MVT::Other),
6877 WideMemVT, dl, Ops, N->getMemOperand(),
6878 N->getIndexType(), N->getExtensionType());
6879
6880 // Legalize the chain result - switch anything that used the old chain to
6881 // use the new one.
6882 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6883 return Res;
6884}
6885
6886SDValue DAGTypeLegalizer::WidenVecRes_VP_GATHER(VPGatherSDNode *N) {
6887 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6888 SDValue Mask = N->getMask();
6889 SDValue Scale = N->getScale();
6890 ElementCount WideEC = WideVT.getVectorElementCount();
6891 SDLoc dl(N);
6892
6893 SDValue Index = GetWidenedVector(N->getIndex());
6894 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
6895 N->getMemoryVT().getScalarType(), WideEC);
6896 Mask = GetWidenedMask(Mask, WideEC);
6897
6898 SDValue Ops[] = {N->getChain(), N->getBasePtr(), Index, Scale,
6899 Mask, N->getVectorLength()};
6900 SDValue Res = DAG.getGatherVP(DAG.getVTList(WideVT, MVT::Other), WideMemVT,
6901 dl, Ops, N->getMemOperand(), N->getIndexType());
6902
6903 // Legalize the chain result - switch anything that used the old chain to
6904 // use the new one.
6905 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6906 return Res;
6907}
6908
6909SDValue DAGTypeLegalizer::WidenVecRes_ScalarOp(SDNode *N) {
6910 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6911 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, N->getOperand(0));
6912}
6913
6914// Return true is this is a SETCC node or a strict version of it.
6915static inline bool isSETCCOp(unsigned Opcode) {
6916 switch (Opcode) {
6917 case ISD::SETCC:
6918 case ISD::STRICT_FSETCC:
6920 return true;
6921 }
6922 return false;
6923}
6924
6925// Return true if this is a node that could have two SETCCs as operands.
6926static inline bool isLogicalMaskOp(unsigned Opcode) {
6927 switch (Opcode) {
6928 case ISD::AND:
6929 case ISD::OR:
6930 case ISD::XOR:
6931 return true;
6932 }
6933 return false;
6934}
6935
6936// If N is a SETCC or a strict variant of it, return the type
6937// of the compare operands.
6939 unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
6940 return N->getOperand(OpNo).getValueType();
6941}
6942
6943// This is used just for the assert in convertMask(). Check that this either
6944// a SETCC or a previously handled SETCC by convertMask().
6945#ifndef NDEBUG
6946static inline bool isSETCCorConvertedSETCC(SDValue N) {
6947 if (N.getOpcode() == ISD::EXTRACT_SUBVECTOR)
6948 N = N.getOperand(0);
6949 else if (N.getOpcode() == ISD::CONCAT_VECTORS) {
6950 for (unsigned i = 1; i < N->getNumOperands(); ++i)
6951 if (!N->getOperand(i)->isUndef())
6952 return false;
6953 N = N.getOperand(0);
6954 }
6955
6956 if (N.getOpcode() == ISD::TRUNCATE)
6957 N = N.getOperand(0);
6958 else if (N.getOpcode() == ISD::SIGN_EXTEND)
6959 N = N.getOperand(0);
6960
6961 if (isLogicalMaskOp(N.getOpcode()))
6962 return isSETCCorConvertedSETCC(N.getOperand(0)) &&
6963 isSETCCorConvertedSETCC(N.getOperand(1));
6964
6965 return (isSETCCOp(N.getOpcode()) ||
6967}
6968#endif
6969
6970// Return a mask of vector type MaskVT to replace InMask. Also adjust MaskVT
6971// to ToMaskVT if needed with vector extension or truncation.
6972SDValue DAGTypeLegalizer::convertMask(SDValue InMask, EVT MaskVT,
6973 EVT ToMaskVT) {
6974 // Currently a SETCC or a AND/OR/XOR with two SETCCs are handled.
6975 // FIXME: This code seems to be too restrictive, we might consider
6976 // generalizing it or dropping it.
6977 assert(isSETCCorConvertedSETCC(InMask) && "Unexpected mask argument.");
6978
6979 // Make a new Mask node, with a legal result VT.
6980 SDValue Mask;
6982 for (unsigned i = 0, e = InMask->getNumOperands(); i < e; ++i)
6983 Ops.push_back(InMask->getOperand(i));
6984 if (InMask->isStrictFPOpcode()) {
6985 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask),
6986 { MaskVT, MVT::Other }, Ops);
6987 ReplaceValueWith(InMask.getValue(1), Mask.getValue(1));
6988 }
6989 else
6990 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask), MaskVT, Ops,
6991 InMask->getFlags());
6992
6993 // If MaskVT has smaller or bigger elements than ToMaskVT, a vector sign
6994 // extend or truncate is needed.
6995 LLVMContext &Ctx = *DAG.getContext();
6996 unsigned MaskScalarBits = MaskVT.getScalarSizeInBits();
6997 unsigned ToMaskScalBits = ToMaskVT.getScalarSizeInBits();
6998 if (MaskScalarBits < ToMaskScalBits) {
6999 EVT ExtVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
7000 MaskVT.getVectorNumElements());
7001 Mask = DAG.getNode(ISD::SIGN_EXTEND, SDLoc(Mask), ExtVT, Mask);
7002 } else if (MaskScalarBits > ToMaskScalBits) {
7003 EVT TruncVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
7004 MaskVT.getVectorNumElements());
7005 Mask = DAG.getNode(ISD::TRUNCATE, SDLoc(Mask), TruncVT, Mask);
7006 }
7007
7008 assert(Mask->getValueType(0).getScalarSizeInBits() ==
7009 ToMaskVT.getScalarSizeInBits() &&
7010 "Mask should have the right element size by now.");
7011
7012 // Adjust Mask to the right number of elements.
7013 unsigned CurrMaskNumEls = Mask->getValueType(0).getVectorNumElements();
7014 if (CurrMaskNumEls > ToMaskVT.getVectorNumElements()) {
7015 Mask = DAG.getExtractSubvector(SDLoc(Mask), ToMaskVT, Mask, 0);
7016 } else if (CurrMaskNumEls < ToMaskVT.getVectorNumElements()) {
7017 unsigned NumSubVecs = (ToMaskVT.getVectorNumElements() / CurrMaskNumEls);
7018 EVT SubVT = Mask->getValueType(0);
7019 SmallVector<SDValue, 16> SubOps(NumSubVecs, DAG.getPOISON(SubVT));
7020 SubOps[0] = Mask;
7021 Mask = DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Mask), ToMaskVT, SubOps);
7022 }
7023
7024 assert((Mask->getValueType(0) == ToMaskVT) &&
7025 "A mask of ToMaskVT should have been produced by now.");
7026
7027 return Mask;
7028}
7029
7030// This method tries to handle some special cases for the vselect mask
7031// and if needed adjusting the mask vector type to match that of the VSELECT.
7032// Without it, many cases end up with scalarization of the SETCC, with many
7033// unnecessary instructions.
7034SDValue DAGTypeLegalizer::WidenVSELECTMask(SDNode *N) {
7035 LLVMContext &Ctx = *DAG.getContext();
7036 SDValue Cond = N->getOperand(0);
7037
7038 if (N->getOpcode() != ISD::VSELECT)
7039 return SDValue();
7040
7041 if (!isSETCCOp(Cond->getOpcode()) && !isLogicalMaskOp(Cond->getOpcode()))
7042 return SDValue();
7043
7044 // If this is a splitted VSELECT that was previously already handled, do
7045 // nothing.
7046 EVT CondVT = Cond->getValueType(0);
7047 if (CondVT.getScalarSizeInBits() != 1)
7048 return SDValue();
7049
7050 EVT VSelVT = N->getValueType(0);
7051
7052 // This method can't handle scalable vector types.
7053 // FIXME: This support could be added in the future.
7054 if (VSelVT.isScalableVector())
7055 return SDValue();
7056
7057 // Only handle vector types which are a power of 2.
7058 if (!isPowerOf2_64(VSelVT.getSizeInBits()))
7059 return SDValue();
7060
7061 // Don't touch if this will be scalarized.
7062 EVT FinalVT = VSelVT;
7063 while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
7064 FinalVT = FinalVT.getHalfNumVectorElementsVT(Ctx);
7065
7066 if (FinalVT.getVectorNumElements() == 1)
7067 return SDValue();
7068
7069 // If there is support for an i1 vector mask, don't touch.
7070 if (isSETCCOp(Cond.getOpcode())) {
7071 EVT SetCCOpVT = getSETCCOperandType(Cond);
7072 while (TLI.getTypeAction(Ctx, SetCCOpVT) != TargetLowering::TypeLegal)
7073 SetCCOpVT = TLI.getTypeToTransformTo(Ctx, SetCCOpVT);
7074 EVT SetCCResVT = getSetCCResultType(SetCCOpVT);
7075 if (SetCCResVT.getScalarSizeInBits() == 1)
7076 return SDValue();
7077 } else if (CondVT.getScalarType() == MVT::i1) {
7078 // If there is support for an i1 vector mask (or only scalar i1 conditions),
7079 // don't touch.
7080 while (TLI.getTypeAction(Ctx, CondVT) != TargetLowering::TypeLegal)
7081 CondVT = TLI.getTypeToTransformTo(Ctx, CondVT);
7082
7083 if (CondVT.getScalarType() == MVT::i1)
7084 return SDValue();
7085 }
7086
7087 // Widen the vselect result type if needed.
7088 if (getTypeAction(VSelVT) == TargetLowering::TypeWidenVector)
7089 VSelVT = TLI.getTypeToTransformTo(Ctx, VSelVT);
7090
7091 // The mask of the VSELECT should have integer elements.
7092 EVT ToMaskVT = VSelVT;
7093 if (!ToMaskVT.getScalarType().isInteger())
7094 ToMaskVT = ToMaskVT.changeVectorElementTypeToInteger();
7095
7096 SDValue Mask;
7097 if (isSETCCOp(Cond->getOpcode())) {
7098 EVT MaskVT = getSetCCResultType(getSETCCOperandType(Cond));
7099 Mask = convertMask(Cond, MaskVT, ToMaskVT);
7100 } else if (isLogicalMaskOp(Cond->getOpcode()) &&
7101 isSETCCOp(Cond->getOperand(0).getOpcode()) &&
7102 isSETCCOp(Cond->getOperand(1).getOpcode())) {
7103 // Cond is (AND/OR/XOR (SETCC, SETCC))
7104 SDValue SETCC0 = Cond->getOperand(0);
7105 SDValue SETCC1 = Cond->getOperand(1);
7106 EVT VT0 = getSetCCResultType(getSETCCOperandType(SETCC0));
7107 EVT VT1 = getSetCCResultType(getSETCCOperandType(SETCC1));
7108 unsigned ScalarBits0 = VT0.getScalarSizeInBits();
7109 unsigned ScalarBits1 = VT1.getScalarSizeInBits();
7110 unsigned ScalarBits_ToMask = ToMaskVT.getScalarSizeInBits();
7111 EVT MaskVT;
7112 // If the two SETCCs have different VTs, either extend/truncate one of
7113 // them to the other "towards" ToMaskVT, or truncate one and extend the
7114 // other to ToMaskVT.
7115 if (ScalarBits0 != ScalarBits1) {
7116 EVT NarrowVT = ((ScalarBits0 < ScalarBits1) ? VT0 : VT1);
7117 EVT WideVT = ((NarrowVT == VT0) ? VT1 : VT0);
7118 if (ScalarBits_ToMask >= WideVT.getScalarSizeInBits())
7119 MaskVT = WideVT;
7120 else if (ScalarBits_ToMask <= NarrowVT.getScalarSizeInBits())
7121 MaskVT = NarrowVT;
7122 else
7123 MaskVT = ToMaskVT;
7124 } else
7125 // If the two SETCCs have the same VT, don't change it.
7126 MaskVT = VT0;
7127
7128 // Make new SETCCs and logical nodes.
7129 SETCC0 = convertMask(SETCC0, VT0, MaskVT);
7130 SETCC1 = convertMask(SETCC1, VT1, MaskVT);
7131 Cond = DAG.getNode(Cond->getOpcode(), SDLoc(Cond), MaskVT, SETCC0, SETCC1);
7132
7133 // Convert the logical op for VSELECT if needed.
7134 Mask = convertMask(Cond, MaskVT, ToMaskVT);
7135 } else
7136 return SDValue();
7137
7138 return Mask;
7139}
7140
7141SDValue DAGTypeLegalizer::WidenVecRes_Select(SDNode *N) {
7142 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7143 ElementCount WidenEC = WidenVT.getVectorElementCount();
7144
7145 SDValue Cond1 = N->getOperand(0);
7146 EVT CondVT = Cond1.getValueType();
7147 unsigned Opcode = N->getOpcode();
7148 if (CondVT.isVector()) {
7149 if (SDValue WideCond = WidenVSELECTMask(N)) {
7150 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
7151 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
7152 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
7153 return DAG.getNode(Opcode, SDLoc(N), WidenVT, WideCond, InOp1, InOp2);
7154 }
7155
7156 EVT CondEltVT = CondVT.getVectorElementType();
7157 EVT CondWidenVT = EVT::getVectorVT(*DAG.getContext(), CondEltVT, WidenEC);
7158 if (getTypeAction(CondVT) == TargetLowering::TypeWidenVector)
7159 Cond1 = GetWidenedVector(Cond1);
7160
7161 // If we have to split the condition there is no point in widening the
7162 // select. This would result in an cycle of widening the select ->
7163 // widening the condition operand -> splitting the condition operand ->
7164 // splitting the select -> widening the select. Instead split this select
7165 // further and widen the resulting type.
7166 if (getTypeAction(CondVT) == TargetLowering::TypeSplitVector) {
7167 SDValue SplitSelect = SplitVecOp_VSELECT(N, 0);
7168 SDValue Res = ModifyToType(SplitSelect, WidenVT);
7169 return Res;
7170 }
7171
7172 if (Cond1.getValueType() != CondWidenVT)
7173 Cond1 = ModifyToType(Cond1, CondWidenVT);
7174 }
7175
7176 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
7177 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
7178 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
7179 if (Opcode == ISD::VP_SELECT || Opcode == ISD::VP_MERGE)
7180 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2,
7181 N->getOperand(3));
7182 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2);
7183}
7184
7185SDValue DAGTypeLegalizer::WidenVecRes_SELECT_CC(SDNode *N) {
7186 SDValue InOp1 = GetWidenedVector(N->getOperand(2));
7187 SDValue InOp2 = GetWidenedVector(N->getOperand(3));
7188 return DAG.getNode(ISD::SELECT_CC, SDLoc(N),
7189 InOp1.getValueType(), N->getOperand(0),
7190 N->getOperand(1), InOp1, InOp2, N->getOperand(4));
7191}
7192
7193SDValue DAGTypeLegalizer::WidenVecRes_UNDEF(SDNode *N) {
7194 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7195 return DAG.getUNDEF(WidenVT);
7196}
7197
7198SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N) {
7199 EVT VT = N->getValueType(0);
7200 SDLoc dl(N);
7201
7202 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7203 unsigned NumElts = VT.getVectorNumElements();
7204 unsigned WidenNumElts = WidenVT.getVectorNumElements();
7205
7206 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
7207 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
7208
7209 // Adjust mask based on new input vector length.
7210 SmallVector<int, 16> NewMask(WidenNumElts, -1);
7211 for (unsigned i = 0; i != NumElts; ++i) {
7212 int Idx = N->getMaskElt(i);
7213 if (Idx < (int)NumElts)
7214 NewMask[i] = Idx;
7215 else
7216 NewMask[i] = Idx - NumElts + WidenNumElts;
7217 }
7218 return DAG.getVectorShuffle(WidenVT, dl, InOp1, InOp2, NewMask);
7219}
7220
7221SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_REVERSE(SDNode *N) {
7222 EVT VT = N->getValueType(0);
7223 EVT EltVT = VT.getVectorElementType();
7224 SDLoc dl(N);
7225
7226 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7227 SDValue OpValue = GetWidenedVector(N->getOperand(0));
7228 assert(WidenVT == OpValue.getValueType() && "Unexpected widened vector type");
7229
7230 SDValue ReverseVal = DAG.getNode(ISD::VECTOR_REVERSE, dl, WidenVT, OpValue);
7231 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
7232 unsigned VTNumElts = VT.getVectorMinNumElements();
7233 unsigned IdxVal = WidenNumElts - VTNumElts;
7234
7235 if (VT.isScalableVector()) {
7236 // Try to split the 'Widen ReverseVal' into smaller extracts and concat the
7237 // results together, e.g.(nxv6i64 -> nxv8i64)
7238 // nxv8i64 vector_reverse
7239 // <->
7240 // nxv8i64 concat(
7241 // nxv2i64 extract_subvector(nxv8i64, 2)
7242 // nxv2i64 extract_subvector(nxv8i64, 4)
7243 // nxv2i64 extract_subvector(nxv8i64, 6)
7244 // nxv2i64 undef)
7245
7246 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
7247 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
7249 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
7250 "down type's element count");
7252 unsigned i = 0;
7253 for (; i < VTNumElts / GCD; ++i)
7254 Parts.push_back(
7255 DAG.getExtractSubvector(dl, PartVT, ReverseVal, IdxVal + i * GCD));
7256 for (; i < WidenNumElts / GCD; ++i)
7257 Parts.push_back(DAG.getPOISON(PartVT));
7258
7259 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
7260 }
7261
7262 // Use VECTOR_SHUFFLE to combine new vector from 'ReverseVal' for
7263 // fixed-vectors.
7264 SmallVector<int, 16> Mask(WidenNumElts, -1);
7265 std::iota(Mask.begin(), Mask.begin() + VTNumElts, IdxVal);
7266
7267 return DAG.getVectorShuffle(WidenVT, dl, ReverseVal, DAG.getPOISON(WidenVT),
7268 Mask);
7269}
7270
7271SDValue DAGTypeLegalizer::WidenVecRes_GET_ACTIVE_LANE_MASK(SDNode *N) {
7272 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7273 return DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, SDLoc(N), NVT, N->ops());
7274}
7275
7276SDValue DAGTypeLegalizer::WidenVecRes_SETCC(SDNode *N) {
7277 assert(N->getValueType(0).isVector() &&
7278 N->getOperand(0).getValueType().isVector() &&
7279 "Operands must be vectors");
7280 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7281 ElementCount WidenEC = WidenVT.getVectorElementCount();
7282
7283 SDValue InOp1 = N->getOperand(0);
7284 EVT InVT = InOp1.getValueType();
7285 assert(InVT.isVector() && "can not widen non-vector type");
7286 EVT WidenInVT =
7287 EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), WidenEC);
7288
7289 // The input and output types often differ here, and it could be that while
7290 // we'd prefer to widen the result type, the input operands have been split.
7291 // In this case, we also need to split the result of this node as well.
7292 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector) {
7293 SDValue SplitVSetCC = SplitVecOp_VSETCC(N);
7294 SDValue Res = ModifyToType(SplitVSetCC, WidenVT);
7295 return Res;
7296 }
7297
7298 // If the inputs also widen, handle them directly. Otherwise widen by hand.
7299 SDValue InOp2 = N->getOperand(1);
7300 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
7301 InOp1 = GetWidenedVector(InOp1);
7302 InOp2 = GetWidenedVector(InOp2);
7303 } else {
7304 SDValue Poison = DAG.getPOISON(WidenInVT);
7305 SDValue ZeroIdx = DAG.getVectorIdxConstant(0, SDLoc(N));
7306 InOp1 = DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), WidenInVT, Poison,
7307 InOp1, ZeroIdx);
7308 InOp2 = DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), WidenInVT, Poison,
7309 InOp2, ZeroIdx);
7310 }
7311
7312 // Assume that the input and output will be widen appropriately. If not,
7313 // we will have to unroll it at some point.
7314 assert(InOp1.getValueType() == WidenInVT &&
7315 InOp2.getValueType() == WidenInVT &&
7316 "Input not widened to expected type!");
7317 (void)WidenInVT;
7318 if (N->getOpcode() == ISD::VP_SETCC) {
7319 SDValue Mask =
7320 GetWidenedMask(N->getOperand(3), WidenVT.getVectorElementCount());
7321 return DAG.getNode(ISD::VP_SETCC, SDLoc(N), WidenVT, InOp1, InOp2,
7322 N->getOperand(2), Mask, N->getOperand(4));
7323 }
7324 return DAG.getNode(ISD::SETCC, SDLoc(N), WidenVT, InOp1, InOp2,
7325 N->getOperand(2));
7326}
7327
7328SDValue DAGTypeLegalizer::WidenVecRes_STRICT_FSETCC(SDNode *N) {
7329 assert(N->getValueType(0).isVector() &&
7330 N->getOperand(1).getValueType().isVector() &&
7331 "Operands must be vectors");
7332 EVT VT = N->getValueType(0);
7333 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7334 unsigned WidenNumElts = WidenVT.getVectorNumElements();
7335 unsigned NumElts = VT.getVectorNumElements();
7336 EVT EltVT = VT.getVectorElementType();
7337
7338 SDLoc dl(N);
7339 SDValue Chain = N->getOperand(0);
7340 SDValue LHS = N->getOperand(1);
7341 SDValue RHS = N->getOperand(2);
7342 SDValue CC = N->getOperand(3);
7343 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
7344
7345 // Fully unroll and reassemble.
7346 SmallVector<SDValue, 8> Scalars(WidenNumElts, DAG.getPOISON(EltVT));
7347 SmallVector<SDValue, 8> Chains(NumElts);
7348 for (unsigned i = 0; i != NumElts; ++i) {
7349 SDValue LHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, LHS, i);
7350 SDValue RHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, RHS, i);
7351
7352 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
7353 {Chain, LHSElem, RHSElem, CC});
7354 Chains[i] = Scalars[i].getValue(1);
7355 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
7356 DAG.getBoolConstant(true, dl, EltVT, VT),
7357 DAG.getBoolConstant(false, dl, EltVT, VT));
7358 }
7359
7360 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
7361 ReplaceValueWith(SDValue(N, 1), NewChain);
7362
7363 return DAG.getBuildVector(WidenVT, dl, Scalars);
7364}
7365
7366//===----------------------------------------------------------------------===//
7367// Widen Vector Operand
7368//===----------------------------------------------------------------------===//
7369bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned OpNo) {
7370 LLVM_DEBUG(dbgs() << "Widen node operand " << OpNo << ": "; N->dump(&DAG));
7371 SDValue Res = SDValue();
7372
7373 // See if the target wants to custom widen this node.
7374 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
7375 return false;
7376
7377 switch (N->getOpcode()) {
7378 default:
7379#ifndef NDEBUG
7380 dbgs() << "WidenVectorOperand op #" << OpNo << ": ";
7381 N->dump(&DAG);
7382 dbgs() << "\n";
7383#endif
7384 report_fatal_error("Do not know how to widen this operator's operand!");
7385
7386 case ISD::BITCAST: Res = WidenVecOp_BITCAST(N); break;
7387 case ISD::FAKE_USE:
7388 Res = WidenVecOp_FAKE_USE(N);
7389 break;
7390 case ISD::CONCAT_VECTORS: Res = WidenVecOp_CONCAT_VECTORS(N); break;
7391 case ISD::INSERT_SUBVECTOR: Res = WidenVecOp_INSERT_SUBVECTOR(N); break;
7392 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecOp_EXTRACT_SUBVECTOR(N); break;
7393 case ISD::EXTRACT_VECTOR_ELT: Res = WidenVecOp_EXTRACT_VECTOR_ELT(N); break;
7394 case ISD::STORE: Res = WidenVecOp_STORE(N); break;
7395 case ISD::VP_STORE: Res = WidenVecOp_VP_STORE(N, OpNo); break;
7396 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
7397 Res = WidenVecOp_VP_STRIDED_STORE(N, OpNo);
7398 break;
7402 Res = WidenVecOp_EXTEND_VECTOR_INREG(N);
7403 break;
7404 case ISD::MSTORE: Res = WidenVecOp_MSTORE(N, OpNo); break;
7405 case ISD::MGATHER: Res = WidenVecOp_MGATHER(N, OpNo); break;
7406 case ISD::MSCATTER: Res = WidenVecOp_MSCATTER(N, OpNo); break;
7407 case ISD::VP_SCATTER: Res = WidenVecOp_VP_SCATTER(N, OpNo); break;
7408 case ISD::SETCC: Res = WidenVecOp_SETCC(N); break;
7409 case ISD::STRICT_FSETCC:
7410 case ISD::STRICT_FSETCCS: Res = WidenVecOp_STRICT_FSETCC(N); break;
7411 case ISD::VSELECT: Res = WidenVecOp_VSELECT(N); break;
7412 case ISD::FLDEXP:
7413 case ISD::FCOPYSIGN:
7414 case ISD::LROUND:
7415 case ISD::LLROUND:
7416 case ISD::LRINT:
7417 case ISD::LLRINT:
7418 Res = WidenVecOp_UnrollVectorOp(N);
7419 break;
7420 case ISD::IS_FPCLASS: Res = WidenVecOp_IS_FPCLASS(N); break;
7421
7422 case ISD::ANY_EXTEND:
7423 case ISD::SIGN_EXTEND:
7424 case ISD::ZERO_EXTEND:
7425 Res = WidenVecOp_EXTEND(N);
7426 break;
7427
7428 case ISD::SCMP:
7429 case ISD::UCMP:
7430 Res = WidenVecOp_CMP(N);
7431 break;
7432
7433 case ISD::FP_EXTEND:
7435 case ISD::FP_ROUND:
7437 case ISD::FP_TO_SINT:
7439 case ISD::FP_TO_UINT:
7441 case ISD::SINT_TO_FP:
7443 case ISD::UINT_TO_FP:
7445 case ISD::TRUNCATE:
7447 Res = WidenVecOp_Convert(N);
7448 break;
7449
7452 Res = WidenVecOp_FP_TO_XINT_SAT(N);
7453 break;
7454
7457 case ISD::VECREDUCE_ADD:
7458 case ISD::VECREDUCE_MUL:
7459 case ISD::VECREDUCE_AND:
7460 case ISD::VECREDUCE_OR:
7461 case ISD::VECREDUCE_XOR:
7470 Res = WidenVecOp_VECREDUCE(N);
7471 break;
7474 Res = WidenVecOp_VECREDUCE_SEQ(N);
7475 break;
7476 case ISD::VP_REDUCE_FADD:
7477 case ISD::VP_REDUCE_SEQ_FADD:
7478 case ISD::VP_REDUCE_FMUL:
7479 case ISD::VP_REDUCE_SEQ_FMUL:
7480 case ISD::VP_REDUCE_ADD:
7481 case ISD::VP_REDUCE_MUL:
7482 case ISD::VP_REDUCE_AND:
7483 case ISD::VP_REDUCE_OR:
7484 case ISD::VP_REDUCE_XOR:
7485 case ISD::VP_REDUCE_SMAX:
7486 case ISD::VP_REDUCE_SMIN:
7487 case ISD::VP_REDUCE_UMAX:
7488 case ISD::VP_REDUCE_UMIN:
7489 case ISD::VP_REDUCE_FMAX:
7490 case ISD::VP_REDUCE_FMIN:
7491 case ISD::VP_REDUCE_FMAXIMUM:
7492 case ISD::VP_REDUCE_FMINIMUM:
7493 Res = WidenVecOp_VP_REDUCE(N);
7494 break;
7495 case ISD::VP_CTTZ_ELTS:
7496 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
7497 Res = WidenVecOp_VP_CttzElements(N);
7498 break;
7500 Res = WidenVecOp_VECTOR_FIND_LAST_ACTIVE(N);
7501 break;
7502 }
7503
7504 // If Res is null, the sub-method took care of registering the result.
7505 if (!Res.getNode()) return false;
7506
7507 // If the result is N, the sub-method updated N in place. Tell the legalizer
7508 // core about this.
7509 if (Res.getNode() == N)
7510 return true;
7511
7512
7513 if (N->isStrictFPOpcode())
7514 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
7515 "Invalid operand expansion");
7516 else
7517 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
7518 "Invalid operand expansion");
7519
7520 ReplaceValueWith(SDValue(N, 0), Res);
7521 return false;
7522}
7523
7524SDValue DAGTypeLegalizer::WidenVecOp_EXTEND(SDNode *N) {
7525 SDLoc DL(N);
7526 EVT VT = N->getValueType(0);
7527
7528 SDValue InOp = N->getOperand(0);
7529 assert(getTypeAction(InOp.getValueType()) ==
7531 "Unexpected type action");
7532 InOp = GetWidenedVector(InOp);
7535 "Input wasn't widened!");
7536
7537 // We may need to further widen the operand until it has the same total
7538 // vector size as the result.
7539 EVT InVT = InOp.getValueType();
7540 if (InVT.getSizeInBits() != VT.getSizeInBits()) {
7541 EVT InEltVT = InVT.getVectorElementType();
7542 for (EVT FixedVT : MVT::vector_valuetypes()) {
7543 EVT FixedEltVT = FixedVT.getVectorElementType();
7544 if (TLI.isTypeLegal(FixedVT) &&
7545 FixedVT.getSizeInBits() == VT.getSizeInBits() &&
7546 FixedEltVT == InEltVT) {
7547 assert(FixedVT.getVectorNumElements() >= VT.getVectorNumElements() &&
7548 "Not enough elements in the fixed type for the operand!");
7549 assert(FixedVT.getVectorNumElements() != InVT.getVectorNumElements() &&
7550 "We can't have the same type as we started with!");
7551 if (FixedVT.getVectorNumElements() > InVT.getVectorNumElements())
7552 InOp = DAG.getInsertSubvector(DL, DAG.getPOISON(FixedVT), InOp, 0);
7553 else
7554 InOp = DAG.getExtractSubvector(DL, FixedVT, InOp, 0);
7555 break;
7556 }
7557 }
7558 InVT = InOp.getValueType();
7559 if (InVT.getSizeInBits() != VT.getSizeInBits())
7560 // We couldn't find a legal vector type that was a widening of the input
7561 // and could be extended in-register to the result type, so we have to
7562 // scalarize.
7563 return WidenVecOp_Convert(N);
7564 }
7565
7566 // Use special DAG nodes to represent the operation of extending the
7567 // low lanes.
7568 switch (N->getOpcode()) {
7569 default:
7570 llvm_unreachable("Extend legalization on extend operation!");
7571 case ISD::ANY_EXTEND:
7572 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, VT, InOp);
7573 case ISD::SIGN_EXTEND:
7574 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, VT, InOp);
7575 case ISD::ZERO_EXTEND:
7576 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, VT, InOp);
7577 }
7578}
7579
7580SDValue DAGTypeLegalizer::WidenVecOp_CMP(SDNode *N) {
7581 SDLoc dl(N);
7582
7583 EVT OpVT = N->getOperand(0).getValueType();
7584 EVT ResVT = N->getValueType(0);
7585 SDValue LHS = GetWidenedVector(N->getOperand(0));
7586 SDValue RHS = GetWidenedVector(N->getOperand(1));
7587
7588 // 1. EXTRACT_SUBVECTOR
7589 // 2. SIGN_EXTEND/ZERO_EXTEND
7590 // 3. CMP
7591 LHS = DAG.getExtractSubvector(dl, OpVT, LHS, 0);
7592 RHS = DAG.getExtractSubvector(dl, OpVT, RHS, 0);
7593
7594 // At this point the result type is guaranteed to be valid, so we can use it
7595 // as the operand type by extending it appropriately
7596 ISD::NodeType ExtendOpcode =
7597 N->getOpcode() == ISD::SCMP ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
7598 LHS = DAG.getNode(ExtendOpcode, dl, ResVT, LHS);
7599 RHS = DAG.getNode(ExtendOpcode, dl, ResVT, RHS);
7600
7601 return DAG.getNode(N->getOpcode(), dl, ResVT, LHS, RHS);
7602}
7603
7604SDValue DAGTypeLegalizer::WidenVecOp_UnrollVectorOp(SDNode *N) {
7605 // The result (and first input) is legal, but the second input is illegal.
7606 // We can't do much to fix that, so just unroll and let the extracts off of
7607 // the second input be widened as needed later.
7608 return DAG.UnrollVectorOp(N);
7609}
7610
7611SDValue DAGTypeLegalizer::WidenVecOp_IS_FPCLASS(SDNode *N) {
7612 SDLoc DL(N);
7613 EVT ResultVT = N->getValueType(0);
7614 SDValue Test = N->getOperand(1);
7615 SDValue WideArg = GetWidenedVector(N->getOperand(0));
7616
7617 // Process this node similarly to SETCC.
7618 EVT WideResultVT = getSetCCResultType(WideArg.getValueType());
7619 if (ResultVT.getScalarType() == MVT::i1)
7620 WideResultVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
7621 WideResultVT.getVectorNumElements());
7622
7623 SDValue WideNode = DAG.getNode(ISD::IS_FPCLASS, DL, WideResultVT,
7624 {WideArg, Test}, N->getFlags());
7625
7626 // Extract the needed results from the result vector.
7627 EVT ResVT =
7628 EVT::getVectorVT(*DAG.getContext(), WideResultVT.getVectorElementType(),
7629 ResultVT.getVectorNumElements());
7630 SDValue CC = DAG.getExtractSubvector(DL, ResVT, WideNode, 0);
7631
7632 EVT OpVT = N->getOperand(0).getValueType();
7633 ISD::NodeType ExtendCode =
7634 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
7635 return DAG.getNode(ExtendCode, DL, ResultVT, CC);
7636}
7637
7638SDValue DAGTypeLegalizer::WidenVecOp_Convert(SDNode *N) {
7639 // Since the result is legal and the input is illegal.
7640 EVT VT = N->getValueType(0);
7641 EVT EltVT = VT.getVectorElementType();
7642 SDLoc dl(N);
7643 SDValue InOp = N->getOperand(N->isStrictFPOpcode() ? 1 : 0);
7644 assert(getTypeAction(InOp.getValueType()) ==
7646 "Unexpected type action");
7647 InOp = GetWidenedVector(InOp);
7648 EVT InVT = InOp.getValueType();
7649 unsigned Opcode = N->getOpcode();
7650
7651 // See if a widened result type would be legal, if so widen the node.
7652 // FIXME: This isn't safe for StrictFP. Other optimization here is needed.
7653 EVT WideVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
7654 InVT.getVectorElementCount());
7655 if (TLI.isTypeLegal(WideVT) && !N->isStrictFPOpcode()) {
7656 SDValue Res;
7657 if (N->isStrictFPOpcode()) {
7658 if (Opcode == ISD::STRICT_FP_ROUND)
7659 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
7660 { N->getOperand(0), InOp, N->getOperand(2) });
7661 else
7662 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
7663 { N->getOperand(0), InOp });
7664 // Legalize the chain result - switch anything that used the old chain to
7665 // use the new one.
7666 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7667 } else {
7668 if (Opcode == ISD::FP_ROUND || Opcode == ISD::CONVERT_FROM_ARBITRARY_FP)
7669 Res = DAG.getNode(Opcode, dl, WideVT, InOp, N->getOperand(1));
7670 else
7671 Res = DAG.getNode(Opcode, dl, WideVT, InOp);
7672 }
7673 return DAG.getExtractSubvector(dl, VT, Res, 0);
7674 }
7675
7676 EVT InEltVT = InVT.getVectorElementType();
7677
7678 // Unroll the convert into some scalar code and create a nasty build vector.
7679 unsigned NumElts = VT.getVectorNumElements();
7681 if (N->isStrictFPOpcode()) {
7682 SmallVector<SDValue, 4> NewOps(N->ops());
7683 SmallVector<SDValue, 32> OpChains;
7684 for (unsigned i=0; i < NumElts; ++i) {
7685 NewOps[1] = DAG.getExtractVectorElt(dl, InEltVT, InOp, i);
7686 Ops[i] = DAG.getNode(Opcode, dl, { EltVT, MVT::Other }, NewOps);
7687 OpChains.push_back(Ops[i].getValue(1));
7688 }
7689 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OpChains);
7690 ReplaceValueWith(SDValue(N, 1), NewChain);
7691 } else {
7692 for (unsigned i = 0; i < NumElts; ++i) {
7693 SDValue Elt = DAG.getExtractVectorElt(dl, InEltVT, InOp, i);
7694 if (Opcode == ISD::FP_ROUND || Opcode == ISD::CONVERT_FROM_ARBITRARY_FP)
7695 Ops[i] = DAG.getNode(Opcode, dl, EltVT, Elt, N->getOperand(1));
7696 else
7697 Ops[i] = DAG.getNode(Opcode, dl, EltVT, Elt);
7698 }
7699 }
7700
7701 return DAG.getBuildVector(VT, dl, Ops);
7702}
7703
7704SDValue DAGTypeLegalizer::WidenVecOp_FP_TO_XINT_SAT(SDNode *N) {
7705 EVT DstVT = N->getValueType(0);
7706 SDValue Src = GetWidenedVector(N->getOperand(0));
7707 EVT SrcVT = Src.getValueType();
7708 ElementCount WideNumElts = SrcVT.getVectorElementCount();
7709 SDLoc dl(N);
7710
7711 // See if a widened result type would be legal, if so widen the node.
7712 EVT WideDstVT = EVT::getVectorVT(*DAG.getContext(),
7713 DstVT.getVectorElementType(), WideNumElts);
7714 if (TLI.isTypeLegal(WideDstVT)) {
7715 SDValue Res =
7716 DAG.getNode(N->getOpcode(), dl, WideDstVT, Src, N->getOperand(1));
7717 return DAG.getNode(
7718 ISD::EXTRACT_SUBVECTOR, dl, DstVT, Res,
7719 DAG.getConstant(0, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
7720 }
7721
7722 // Give up and unroll.
7723 return DAG.UnrollVectorOp(N);
7724}
7725
7726SDValue DAGTypeLegalizer::WidenVecOp_BITCAST(SDNode *N) {
7727 EVT VT = N->getValueType(0);
7728 SDValue InOp = GetWidenedVector(N->getOperand(0));
7729 EVT InWidenVT = InOp.getValueType();
7730 SDLoc dl(N);
7731
7732 // Check if we can convert between two legal vector types and extract.
7733 TypeSize InWidenSize = InWidenVT.getSizeInBits();
7734 TypeSize Size = VT.getSizeInBits();
7735 // x86mmx is not an acceptable vector element type, so don't try.
7736 if (!VT.isVector() && VT != MVT::x86mmx &&
7737 InWidenSize.hasKnownScalarFactor(Size)) {
7738 unsigned NewNumElts = InWidenSize.getKnownScalarFactor(Size);
7739 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), VT, NewNumElts);
7740 if (TLI.isTypeLegal(NewVT)) {
7741 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
7742 return DAG.getExtractVectorElt(dl, VT, BitOp, 0);
7743 }
7744 }
7745
7746 // Handle a case like bitcast v12i8 -> v3i32. Normally that would get widened
7747 // to v16i8 -> v4i32, but for a target where v3i32 is legal but v12i8 is not,
7748 // we end up here. Handling the case here with EXTRACT_SUBVECTOR avoids
7749 // having to copy via memory.
7750 if (VT.isVector()) {
7751 EVT EltVT = VT.getVectorElementType();
7752 unsigned EltSize = EltVT.getFixedSizeInBits();
7753 if (InWidenSize.isKnownMultipleOf(EltSize)) {
7754 ElementCount NewNumElts =
7755 (InWidenVT.getVectorElementCount() * InWidenVT.getScalarSizeInBits())
7756 .divideCoefficientBy(EltSize);
7757 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NewNumElts);
7758 if (TLI.isTypeLegal(NewVT)) {
7759 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
7760 return DAG.getExtractSubvector(dl, VT, BitOp, 0);
7761 }
7762 }
7763 }
7764
7765 return CreateStackStoreLoad(InOp, VT);
7766}
7767
7768// Vectors with sizes that are not powers of 2 need to be widened to the
7769// next largest power of 2. For example, we may get a vector of 3 32-bit
7770// integers or of 6 16-bit integers, both of which have to be widened to a
7771// 128-bit vector.
7772SDValue DAGTypeLegalizer::WidenVecOp_FAKE_USE(SDNode *N) {
7773 SDValue WidenedOp = GetWidenedVector(N->getOperand(1));
7774 return DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, N->getOperand(0),
7775 WidenedOp);
7776}
7777
7778SDValue DAGTypeLegalizer::WidenVecOp_CONCAT_VECTORS(SDNode *N) {
7779 EVT VT = N->getValueType(0);
7780 EVT EltVT = VT.getVectorElementType();
7781 EVT InVT = N->getOperand(0).getValueType();
7782 SDLoc dl(N);
7783
7784 // If the widen width for this operand is the same as the width of the concat
7785 // and all but the first operand is undef, just use the widened operand.
7786 unsigned NumOperands = N->getNumOperands();
7787 if (VT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
7788 unsigned i;
7789 for (i = 1; i < NumOperands; ++i)
7790 if (!N->getOperand(i).isUndef())
7791 break;
7792
7793 if (i == NumOperands)
7794 return GetWidenedVector(N->getOperand(0));
7795 }
7796
7797 // Otherwise, fall back to a nasty build vector.
7798 unsigned NumElts = VT.getVectorNumElements();
7800
7801 unsigned NumInElts = InVT.getVectorNumElements();
7802
7803 unsigned Idx = 0;
7804 for (unsigned i=0; i < NumOperands; ++i) {
7805 SDValue InOp = N->getOperand(i);
7806 assert(getTypeAction(InOp.getValueType()) ==
7808 "Unexpected type action");
7809 InOp = GetWidenedVector(InOp);
7810 for (unsigned j = 0; j < NumInElts; ++j)
7811 Ops[Idx++] = DAG.getExtractVectorElt(dl, EltVT, InOp, j);
7812 }
7813 return DAG.getBuildVector(VT, dl, Ops);
7814}
7815
7816SDValue DAGTypeLegalizer::WidenVecOp_INSERT_SUBVECTOR(SDNode *N) {
7817 EVT VT = N->getValueType(0);
7818 SDValue SubVec = N->getOperand(1);
7819 SDValue InVec = N->getOperand(0);
7820
7821 EVT OrigVT = SubVec.getValueType();
7822 SubVec = GetWidenedVector(SubVec);
7823 EVT SubVT = SubVec.getValueType();
7824
7825 // Whether or not all the elements of the widened SubVec will be inserted into
7826 // valid indices of VT.
7827 bool IndicesValid = false;
7828 // If we statically know that VT can fit SubVT, the indices are valid.
7829 if (VT.knownBitsGE(SubVT))
7830 IndicesValid = true;
7831 else if (VT.isScalableVector() && SubVT.isFixedLengthVector()) {
7832 // Otherwise, if we're inserting a fixed vector into a scalable vector and
7833 // we know the minimum vscale we can work out if it's valid ourselves.
7834 Attribute Attr = DAG.getMachineFunction().getFunction().getFnAttribute(
7835 Attribute::VScaleRange);
7836 if (Attr.isValid()) {
7837 unsigned VScaleMin = Attr.getVScaleRangeMin();
7838 if (VT.getSizeInBits().getKnownMinValue() * VScaleMin >=
7839 SubVT.getFixedSizeInBits())
7840 IndicesValid = true;
7841 }
7842 }
7843
7844 if (!IndicesValid)
7846 "Don't know how to widen the operands for INSERT_SUBVECTOR");
7847
7848 SDLoc DL(N);
7849
7850 // We need to make sure that the indices are still valid, otherwise we might
7851 // widen what was previously well-defined to something undefined.
7852 if (InVec.isUndef() && N->getConstantOperandVal(2) == 0)
7853 return DAG.getNode(ISD::INSERT_SUBVECTOR, DL, VT, InVec, SubVec,
7854 N->getOperand(2));
7855
7856 if (OrigVT.isScalableVector()) {
7857 // When the widened types match, overwriting the start of a vector is
7858 // effectively a merge operation that can be implement as a vselect.
7859 if (SubVT == VT && N->getConstantOperandVal(2) == 0) {
7860 SDValue Mask =
7861 DAG.getMaskFromElementCount(DL, VT, OrigVT.getVectorElementCount());
7862 return DAG.getNode(ISD::VSELECT, DL, VT, Mask, SubVec, InVec);
7863 }
7864
7865 // Fallback to inserting through memory.
7866 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
7867 SDValue StackPtr = DAG.CreateStackTemporary(VT.getStoreSize(), Alignment);
7868 MachineFunction &MF = DAG.getMachineFunction();
7869 int FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
7870 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
7871
7872 MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
7875 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
7878
7879 // Write out the vector being inserting into.
7880 SDValue Ch =
7881 DAG.getStore(DAG.getEntryNode(), DL, InVec, StackPtr, StoreMMO);
7882
7883 // Build a mask to match the length of the sub-vector.
7884 SDValue Mask =
7885 DAG.getMaskFromElementCount(DL, SubVT, OrigVT.getVectorElementCount());
7886
7887 // Overwrite the sub-vector at the required offset.
7888 SDValue SubVecPtr =
7889 TLI.getVectorSubVecPointer(DAG, StackPtr, VT, OrigVT, N->getOperand(2));
7890 Ch = DAG.getMaskedStore(Ch, DL, SubVec, SubVecPtr,
7891 DAG.getPOISON(SubVecPtr.getValueType()), Mask, VT,
7892 StoreMMO, ISD::UNINDEXED, ISD::NON_EXTLOAD);
7893
7894 // Read back the result.
7895 return DAG.getLoad(VT, DL, Ch, StackPtr, LoadMMO);
7896 }
7897
7898 // If the operands can't be widened legally, just replace the INSERT_SUBVECTOR
7899 // with a series of INSERT_VECTOR_ELT
7900 unsigned Idx = N->getConstantOperandVal(2);
7901
7902 SDValue InsertElt = InVec;
7903 for (unsigned I = 0, E = OrigVT.getVectorNumElements(); I != E; ++I) {
7904 SDValue ExtractElt =
7905 DAG.getExtractVectorElt(DL, VT.getVectorElementType(), SubVec, I);
7906 InsertElt = DAG.getInsertVectorElt(DL, InsertElt, ExtractElt, I + Idx);
7907 }
7908
7909 return InsertElt;
7910}
7911
7912SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
7913 SDValue InOp = GetWidenedVector(N->getOperand(0));
7914 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SDLoc(N),
7915 N->getValueType(0), InOp, N->getOperand(1));
7916}
7917
7918SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
7919 SDValue InOp = GetWidenedVector(N->getOperand(0));
7920 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
7921 N->getValueType(0), InOp, N->getOperand(1));
7922}
7923
7924SDValue DAGTypeLegalizer::WidenVecOp_EXTEND_VECTOR_INREG(SDNode *N) {
7925 SDLoc DL(N);
7926 EVT ResVT = N->getValueType(0);
7927
7928 // Widen the input as requested by the legalizer.
7929 SDValue WideInOp = GetWidenedVector(N->getOperand(0));
7930 EVT WideInVT = WideInOp.getValueType();
7931
7932 // Simple case: if widened input is still smaller than or equal to result,
7933 // just use it directly.
7934 if (WideInVT.getSizeInBits() <= ResVT.getSizeInBits())
7935 return DAG.getNode(N->getOpcode(), DL, ResVT, WideInOp);
7936
7937 // EXTEND_VECTOR_INREG requires input bits <= result bits.
7938 // If widening makes the input larger than the original result, widen the
7939 // result to match, then extract back down.
7940 EVT ResEltVT = ResVT.getVectorElementType();
7941 unsigned EltBits = ResEltVT.getSizeInBits();
7942 assert((WideInVT.getSizeInBits() % EltBits) == 0 &&
7943 "Widened input size must be a multiple of result element size");
7944
7945 unsigned WideNumElts = WideInVT.getSizeInBits() / EltBits;
7946 EVT WideResVT = EVT::getVectorVT(*DAG.getContext(), ResEltVT, WideNumElts);
7947
7948 SDValue WideRes = DAG.getNode(N->getOpcode(), DL, WideResVT, WideInOp);
7949 return DAG.getExtractSubvector(DL, ResVT, WideRes, 0);
7950}
7951
7952SDValue DAGTypeLegalizer::WidenVecOp_STORE(SDNode *N) {
7953 // We have to widen the value, but we want only to store the original
7954 // vector type.
7955 StoreSDNode *ST = cast<StoreSDNode>(N);
7956
7957 if (!ST->getMemoryVT().getScalarType().isByteSized())
7958 return TLI.scalarizeVectorStore(ST, DAG);
7959
7960 if (ST->isTruncatingStore())
7961 return TLI.scalarizeVectorStore(ST, DAG);
7962
7963 // Generate a vector-predicated store if it is custom/legal on the target.
7964 // To avoid possible recursion, only do this if the widened mask type is
7965 // legal.
7966 // FIXME: Not all targets may support EVL in VP_STORE. These will have been
7967 // removed from the IR by the ExpandVectorPredication pass but we're
7968 // reintroducing them here.
7969 SDValue StVal = ST->getValue();
7970 EVT StVT = StVal.getValueType();
7971 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), StVT);
7972 EVT WideMaskVT = getSetCCResultType(WideVT);
7973
7974 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
7975 TLI.isTypeLegal(WideMaskVT)) {
7976 // Widen the value.
7977 SDLoc DL(N);
7978 StVal = GetWidenedVector(StVal);
7979 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
7980 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
7981 StVT.getVectorElementCount());
7982 return DAG.getStoreVP(ST->getChain(), DL, StVal, ST->getBasePtr(),
7983 ST->getOffset(), Mask, EVL, StVT, ST->getMemOperand(),
7984 ST->getAddressingMode());
7985 }
7986
7988 if (GenWidenVectorStores(StChain, ST)) {
7989 if (StChain.size() == 1)
7990 return StChain[0];
7991
7992 return DAG.getNode(ISD::TokenFactor, SDLoc(ST), MVT::Other, StChain);
7993 }
7994
7995 if (StVT.isVector()) {
7996 // If all else fails replace the store with a wide masked store.
7997 SDLoc DL(N);
7998 SDValue WideStVal = GetWidenedVector(StVal);
7999 SDValue Mask =
8000 DAG.getMaskFromElementCount(DL, WideVT, StVT.getVectorElementCount());
8001
8002 return DAG.getMaskedStore(ST->getChain(), DL, WideStVal, ST->getBasePtr(),
8003 ST->getOffset(), Mask, ST->getMemoryVT(),
8004 ST->getMemOperand(), ST->getAddressingMode(),
8005 ST->isTruncatingStore());
8006 }
8007
8008 report_fatal_error("Unable to widen vector store");
8009}
8010
8011SDValue DAGTypeLegalizer::WidenVecOp_VP_STORE(SDNode *N, unsigned OpNo) {
8012 assert((OpNo == 1 || OpNo == 3) &&
8013 "Can widen only data or mask operand of vp_store");
8014 VPStoreSDNode *ST = cast<VPStoreSDNode>(N);
8015 SDValue Mask = ST->getMask();
8016 SDValue StVal = ST->getValue();
8017 SDLoc dl(N);
8018
8019 if (OpNo == 1) {
8020 // Widen the value.
8021 StVal = GetWidenedVector(StVal);
8022
8023 // We only handle the case where the mask needs widening to an
8024 // identically-sized type as the vector inputs.
8025 assert(getTypeAction(Mask.getValueType()) ==
8027 "Unable to widen VP store");
8028 Mask = GetWidenedVector(Mask);
8029 } else {
8030 Mask = GetWidenedVector(Mask);
8031
8032 // We only handle the case where the stored value needs widening to an
8033 // identically-sized type as the mask.
8034 assert(getTypeAction(StVal.getValueType()) ==
8036 "Unable to widen VP store");
8037 StVal = GetWidenedVector(StVal);
8038 }
8039
8040 assert(Mask.getValueType().getVectorElementCount() ==
8042 "Mask and data vectors should have the same number of elements");
8043 return DAG.getStoreVP(ST->getChain(), dl, StVal, ST->getBasePtr(),
8044 ST->getOffset(), Mask, ST->getVectorLength(),
8045 ST->getMemoryVT(), ST->getMemOperand(),
8046 ST->getAddressingMode(), ST->isTruncatingStore(),
8047 ST->isCompressingStore());
8048}
8049
8050SDValue DAGTypeLegalizer::WidenVecOp_VP_STRIDED_STORE(SDNode *N,
8051 unsigned OpNo) {
8052 assert((OpNo == 1 || OpNo == 4) &&
8053 "Can widen only data or mask operand of vp_strided_store");
8054 VPStridedStoreSDNode *SST = cast<VPStridedStoreSDNode>(N);
8055 SDValue Mask = SST->getMask();
8056 SDValue StVal = SST->getValue();
8057 SDLoc DL(N);
8058
8059 if (OpNo == 1)
8060 assert(getTypeAction(Mask.getValueType()) ==
8062 "Unable to widen VP strided store");
8063 else
8064 assert(getTypeAction(StVal.getValueType()) ==
8066 "Unable to widen VP strided store");
8067
8068 StVal = GetWidenedVector(StVal);
8069 Mask = GetWidenedVector(Mask);
8070
8072 Mask.getValueType().getVectorElementCount() &&
8073 "Data and mask vectors should have the same number of elements");
8074
8075 return DAG.getStridedStoreVP(
8076 SST->getChain(), DL, StVal, SST->getBasePtr(), SST->getOffset(),
8077 SST->getStride(), Mask, SST->getVectorLength(), SST->getMemoryVT(),
8078 SST->getMemOperand(), SST->getAddressingMode(), SST->isTruncatingStore(),
8079 SST->isCompressingStore());
8080}
8081
8082SDValue DAGTypeLegalizer::WidenVecOp_MSTORE(SDNode *N, unsigned OpNo) {
8083 assert((OpNo == 1 || OpNo == 4) &&
8084 "Can widen only data or mask operand of mstore");
8085 MaskedStoreSDNode *MST = cast<MaskedStoreSDNode>(N);
8086 SDValue Mask = MST->getMask();
8087 EVT MaskVT = Mask.getValueType();
8088 SDValue StVal = MST->getValue();
8089 EVT VT = StVal.getValueType();
8090 SDLoc dl(N);
8091
8092 EVT WideVT, WideMaskVT;
8093 if (OpNo == 1) {
8094 // Widen the value.
8095 StVal = GetWidenedVector(StVal);
8096
8097 WideVT = StVal.getValueType();
8098 WideMaskVT =
8099 EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(),
8100 WideVT.getVectorElementCount());
8101 } else {
8102 WideMaskVT = TLI.getTypeToTransformTo(*DAG.getContext(), MaskVT);
8103
8104 EVT ValueVT = StVal.getValueType();
8105 WideVT = EVT::getVectorVT(*DAG.getContext(), ValueVT.getVectorElementType(),
8106 WideMaskVT.getVectorElementCount());
8107 }
8108
8109 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
8110 TLI.isTypeLegal(WideMaskVT)) {
8111 Mask = DAG.getInsertSubvector(dl, DAG.getPOISON(WideMaskVT), Mask, 0);
8112 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8114 return DAG.getStoreVP(MST->getChain(), dl, StVal, MST->getBasePtr(),
8115 MST->getOffset(), Mask, EVL, MST->getMemoryVT(),
8116 MST->getMemOperand(), MST->getAddressingMode());
8117 }
8118
8119 if (OpNo == 1) {
8120 // The mask should be widened as well.
8121 Mask = ModifyToType(Mask, WideMaskVT, true);
8122 } else {
8123 // Widen the mask.
8124 Mask = ModifyToType(Mask, WideMaskVT, true);
8125
8126 StVal = ModifyToType(StVal, WideVT);
8127 }
8128
8129 assert(Mask.getValueType().getVectorElementCount() ==
8131 "Mask and data vectors should have the same number of elements");
8132 return DAG.getMaskedStore(MST->getChain(), dl, StVal, MST->getBasePtr(),
8133 MST->getOffset(), Mask, MST->getMemoryVT(),
8134 MST->getMemOperand(), MST->getAddressingMode(),
8135 false, MST->isCompressingStore());
8136}
8137
8138SDValue DAGTypeLegalizer::WidenVecOp_MGATHER(SDNode *N, unsigned OpNo) {
8139 assert(OpNo == 4 && "Can widen only the index of mgather");
8140 auto *MG = cast<MaskedGatherSDNode>(N);
8141 SDValue DataOp = MG->getPassThru();
8142 SDValue Mask = MG->getMask();
8143 SDValue Scale = MG->getScale();
8144
8145 // Just widen the index. It's allowed to have extra elements.
8146 SDValue Index = GetWidenedVector(MG->getIndex());
8147
8148 SDLoc dl(N);
8149 SDValue Ops[] = {MG->getChain(), DataOp, Mask, MG->getBasePtr(), Index,
8150 Scale};
8151 SDValue Res = DAG.getMaskedGather(MG->getVTList(), MG->getMemoryVT(), dl, Ops,
8152 MG->getMemOperand(), MG->getIndexType(),
8153 MG->getExtensionType());
8154 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
8155 ReplaceValueWith(SDValue(N, 0), Res.getValue(0));
8156 return SDValue();
8157}
8158
8159SDValue DAGTypeLegalizer::WidenVecOp_MSCATTER(SDNode *N, unsigned OpNo) {
8160 MaskedScatterSDNode *MSC = cast<MaskedScatterSDNode>(N);
8161 SDValue DataOp = MSC->getValue();
8162 SDValue Mask = MSC->getMask();
8163 SDValue Index = MSC->getIndex();
8164 SDValue Scale = MSC->getScale();
8165 EVT WideMemVT = MSC->getMemoryVT();
8166
8167 if (OpNo == 1) {
8168 DataOp = GetWidenedVector(DataOp);
8169 unsigned NumElts = DataOp.getValueType().getVectorNumElements();
8170
8171 // Widen index.
8172 EVT IndexVT = Index.getValueType();
8173 EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
8174 IndexVT.getVectorElementType(), NumElts);
8175 Index = ModifyToType(Index, WideIndexVT);
8176
8177 // The mask should be widened as well.
8178 EVT MaskVT = Mask.getValueType();
8179 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
8180 MaskVT.getVectorElementType(), NumElts);
8181 Mask = ModifyToType(Mask, WideMaskVT, true);
8182
8183 // Widen the MemoryType
8184 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
8185 MSC->getMemoryVT().getScalarType(), NumElts);
8186 } else if (OpNo == 4) {
8187 // Just widen the index. It's allowed to have extra elements.
8188 Index = GetWidenedVector(Index);
8189 } else
8190 llvm_unreachable("Can't widen this operand of mscatter");
8191
8192 SDValue Ops[] = {MSC->getChain(), DataOp, Mask, MSC->getBasePtr(), Index,
8193 Scale};
8194 return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N),
8195 Ops, MSC->getMemOperand(), MSC->getIndexType(),
8196 MSC->isTruncatingStore());
8197}
8198
8199SDValue DAGTypeLegalizer::WidenVecOp_VP_SCATTER(SDNode *N, unsigned OpNo) {
8200 VPScatterSDNode *VPSC = cast<VPScatterSDNode>(N);
8201 SDValue DataOp = VPSC->getValue();
8202 SDValue Mask = VPSC->getMask();
8203 SDValue Index = VPSC->getIndex();
8204 SDValue Scale = VPSC->getScale();
8205 EVT WideMemVT = VPSC->getMemoryVT();
8206
8207 if (OpNo == 1) {
8208 DataOp = GetWidenedVector(DataOp);
8209 Index = GetWidenedVector(Index);
8210 const auto WideEC = DataOp.getValueType().getVectorElementCount();
8211 Mask = GetWidenedMask(Mask, WideEC);
8212 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
8213 VPSC->getMemoryVT().getScalarType(), WideEC);
8214 } else if (OpNo == 3) {
8215 // Just widen the index. It's allowed to have extra elements.
8216 Index = GetWidenedVector(Index);
8217 } else
8218 llvm_unreachable("Can't widen this operand of VP_SCATTER");
8219
8220 SDValue Ops[] = {
8221 VPSC->getChain(), DataOp, VPSC->getBasePtr(), Index, Scale, Mask,
8222 VPSC->getVectorLength()};
8223 return DAG.getScatterVP(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N), Ops,
8224 VPSC->getMemOperand(), VPSC->getIndexType());
8225}
8226
8227SDValue DAGTypeLegalizer::WidenVecOp_SETCC(SDNode *N) {
8228 SDValue InOp0 = GetWidenedVector(N->getOperand(0));
8229 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
8230 SDLoc dl(N);
8231 EVT VT = N->getValueType(0);
8232
8233 // WARNING: In this code we widen the compare instruction with garbage.
8234 // This garbage may contain denormal floats which may be slow. Is this a real
8235 // concern ? Should we zero the unused lanes if this is a float compare ?
8236
8237 // Get a new SETCC node to compare the newly widened operands.
8238 // Only some of the compared elements are legal.
8239 EVT SVT = getSetCCResultType(InOp0.getValueType());
8240 // The result type is legal, if its vXi1, keep vXi1 for the new SETCC.
8241 if (VT.getScalarType() == MVT::i1)
8242 SVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8243 SVT.getVectorElementCount());
8244
8245 SDValue WideSETCC = DAG.getNode(ISD::SETCC, SDLoc(N),
8246 SVT, InOp0, InOp1, N->getOperand(2));
8247
8248 // Extract the needed results from the result vector.
8249 EVT ResVT = EVT::getVectorVT(*DAG.getContext(),
8252 SDValue CC = DAG.getExtractSubvector(dl, ResVT, WideSETCC, 0);
8253
8254 EVT OpVT = N->getOperand(0).getValueType();
8255 ISD::NodeType ExtendCode =
8256 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
8257 return DAG.getNode(ExtendCode, dl, VT, CC);
8258}
8259
8260SDValue DAGTypeLegalizer::WidenVecOp_STRICT_FSETCC(SDNode *N) {
8261 SDValue Chain = N->getOperand(0);
8262 SDValue LHS = GetWidenedVector(N->getOperand(1));
8263 SDValue RHS = GetWidenedVector(N->getOperand(2));
8264 SDValue CC = N->getOperand(3);
8265 SDLoc dl(N);
8266
8267 EVT VT = N->getValueType(0);
8268 EVT EltVT = VT.getVectorElementType();
8269 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
8270 unsigned NumElts = VT.getVectorNumElements();
8271
8272 // Unroll into a build vector.
8273 SmallVector<SDValue, 8> Scalars(NumElts);
8274 SmallVector<SDValue, 8> Chains(NumElts);
8275
8276 for (unsigned i = 0; i != NumElts; ++i) {
8277 SDValue LHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, LHS, i);
8278 SDValue RHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, RHS, i);
8279
8280 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
8281 {Chain, LHSElem, RHSElem, CC});
8282 Chains[i] = Scalars[i].getValue(1);
8283 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
8284 DAG.getBoolConstant(true, dl, EltVT, VT),
8285 DAG.getBoolConstant(false, dl, EltVT, VT));
8286 }
8287
8288 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
8289 ReplaceValueWith(SDValue(N, 1), NewChain);
8290
8291 return DAG.getBuildVector(VT, dl, Scalars);
8292}
8293
8294static unsigned getExtendForIntVecReduction(unsigned Opc) {
8295 switch (Opc) {
8296 default:
8297 llvm_unreachable("Expected integer vector reduction");
8298 case ISD::VECREDUCE_ADD:
8299 case ISD::VECREDUCE_MUL:
8300 case ISD::VECREDUCE_AND:
8301 case ISD::VECREDUCE_OR:
8302 case ISD::VECREDUCE_XOR:
8303 return ISD::ANY_EXTEND;
8306 return ISD::SIGN_EXTEND;
8309 return ISD::ZERO_EXTEND;
8310 }
8311}
8312
8313SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE(SDNode *N) {
8314 SDLoc dl(N);
8315 SDValue Op = GetWidenedVector(N->getOperand(0));
8316 EVT VT = N->getValueType(0);
8317 EVT OrigVT = N->getOperand(0).getValueType();
8318 EVT WideVT = Op.getValueType();
8319 EVT ElemVT = OrigVT.getVectorElementType();
8320 SDNodeFlags Flags = N->getFlags();
8321
8322 unsigned Opc = N->getOpcode();
8323 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
8324 SDValue NeutralElem = DAG.getNeutralElement(BaseOpc, dl, ElemVT, Flags);
8325 assert(NeutralElem && "Neutral element must exist");
8326
8327 // Pad the vector with the neutral element.
8328 unsigned OrigElts = OrigVT.getVectorMinNumElements();
8329 unsigned WideElts = WideVT.getVectorMinNumElements();
8330
8331 // Generate a vp.reduce_op if it is custom/legal for the target. This avoids
8332 // needing to pad the source vector, because the inactive lanes can simply be
8333 // disabled and not contribute to the result.
8334 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opc);
8335 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WideVT)) {
8336 SDValue Start = NeutralElem;
8337 if (VT.isInteger())
8338 Start = DAG.getNode(getExtendForIntVecReduction(Opc), dl, VT, Start);
8339 assert(Start.getValueType() == VT);
8340 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8341 WideVT.getVectorElementCount());
8342 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
8343 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8344 OrigVT.getVectorElementCount());
8345 return DAG.getNode(*VPOpcode, dl, VT, {Start, Op, Mask, EVL}, Flags);
8346 }
8347
8348 if (WideVT.isScalableVector()) {
8349 unsigned GCD = std::gcd(OrigElts, WideElts);
8350 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
8352 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
8353 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
8354 Op = DAG.getInsertSubvector(dl, Op, SplatNeutral, Idx);
8355 return DAG.getNode(Opc, dl, VT, Op, Flags);
8356 }
8357
8358 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
8359 Op = DAG.getInsertVectorElt(dl, Op, NeutralElem, Idx);
8360
8361 return DAG.getNode(Opc, dl, VT, Op, Flags);
8362}
8363
8364SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE_SEQ(SDNode *N) {
8365 SDLoc dl(N);
8366 SDValue AccOp = N->getOperand(0);
8367 SDValue VecOp = N->getOperand(1);
8368 SDValue Op = GetWidenedVector(VecOp);
8369
8370 EVT VT = N->getValueType(0);
8371 EVT OrigVT = VecOp.getValueType();
8372 EVT WideVT = Op.getValueType();
8373 EVT ElemVT = OrigVT.getVectorElementType();
8374 SDNodeFlags Flags = N->getFlags();
8375
8376 unsigned Opc = N->getOpcode();
8377 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
8378 SDValue NeutralElem = DAG.getNeutralElement(BaseOpc, dl, ElemVT, Flags);
8379
8380 // Pad the vector with the neutral element.
8381 unsigned OrigElts = OrigVT.getVectorMinNumElements();
8382 unsigned WideElts = WideVT.getVectorMinNumElements();
8383
8384 // Generate a vp.reduce_op if it is custom/legal for the target. This avoids
8385 // needing to pad the source vector, because the inactive lanes can simply be
8386 // disabled and not contribute to the result.
8387 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opc);
8388 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WideVT)) {
8389 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8390 WideVT.getVectorElementCount());
8391 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
8392 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8393 OrigVT.getVectorElementCount());
8394 return DAG.getNode(*VPOpcode, dl, VT, {AccOp, Op, Mask, EVL}, Flags);
8395 }
8396
8397 if (WideVT.isScalableVector()) {
8398 unsigned GCD = std::gcd(OrigElts, WideElts);
8399 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
8401 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
8402 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
8403 Op = DAG.getInsertSubvector(dl, Op, SplatNeutral, Idx);
8404 return DAG.getNode(Opc, dl, VT, AccOp, Op, Flags);
8405 }
8406
8407 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
8408 Op = DAG.getInsertVectorElt(dl, Op, NeutralElem, Idx);
8409
8410 return DAG.getNode(Opc, dl, VT, AccOp, Op, Flags);
8411}
8412
8413SDValue DAGTypeLegalizer::WidenVecOp_VP_REDUCE(SDNode *N) {
8414 assert(N->isVPOpcode() && "Expected VP opcode");
8415
8416 SDLoc dl(N);
8417 SDValue Op = GetWidenedVector(N->getOperand(1));
8418 SDValue Mask = GetWidenedMask(N->getOperand(2),
8419 Op.getValueType().getVectorElementCount());
8420
8421 return DAG.getNode(N->getOpcode(), dl, N->getValueType(0),
8422 {N->getOperand(0), Op, Mask, N->getOperand(3)},
8423 N->getFlags());
8424}
8425
8426SDValue DAGTypeLegalizer::WidenVecOp_VSELECT(SDNode *N) {
8427 // This only gets called in the case that the left and right inputs and
8428 // result are of a legal odd vector type, and the condition is illegal i1 of
8429 // the same odd width that needs widening.
8430 EVT VT = N->getValueType(0);
8431 assert(VT.isVector() && !VT.isPow2VectorType() && isTypeLegal(VT));
8432
8433 SDValue Cond = GetWidenedVector(N->getOperand(0));
8434 SDValue LeftIn = DAG.WidenVector(N->getOperand(1), SDLoc(N));
8435 SDValue RightIn = DAG.WidenVector(N->getOperand(2), SDLoc(N));
8436 SDLoc DL(N);
8437
8438 SDValue Select = DAG.getNode(N->getOpcode(), DL, LeftIn.getValueType(), Cond,
8439 LeftIn, RightIn);
8440 return DAG.getExtractSubvector(DL, VT, Select, 0);
8441}
8442
8443SDValue DAGTypeLegalizer::WidenVecOp_VP_CttzElements(SDNode *N) {
8444 SDLoc DL(N);
8445 SDValue Source = GetWidenedVector(N->getOperand(0));
8446 EVT SrcVT = Source.getValueType();
8447 SDValue Mask =
8448 GetWidenedMask(N->getOperand(1), SrcVT.getVectorElementCount());
8449
8450 return DAG.getNode(N->getOpcode(), DL, N->getValueType(0),
8451 {Source, Mask, N->getOperand(2)}, N->getFlags());
8452}
8453
8454SDValue DAGTypeLegalizer::WidenVecOp_VECTOR_FIND_LAST_ACTIVE(SDNode *N) {
8455 SDLoc DL(N);
8456 SDValue Mask = N->getOperand(0);
8457 EVT OrigMaskVT = Mask.getValueType();
8458 SDValue WideMask = GetWidenedVector(Mask);
8459 EVT WideMaskVT = WideMask.getValueType();
8460
8461 // Pad the mask with zeros to ensure inactive lanes don't affect the result.
8462 unsigned OrigElts = OrigMaskVT.getVectorNumElements();
8463 unsigned WideElts = WideMaskVT.getVectorNumElements();
8464 if (OrigElts != WideElts) {
8465 SDValue ZeroMask = DAG.getConstant(0, DL, WideMaskVT);
8466 WideMask = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideMaskVT, ZeroMask,
8467 Mask, DAG.getVectorIdxConstant(0, DL));
8468 }
8469
8470 return DAG.getNode(ISD::VECTOR_FIND_LAST_ACTIVE, DL, N->getValueType(0),
8471 WideMask);
8472}
8473
8474//===----------------------------------------------------------------------===//
8475// Vector Widening Utilities
8476//===----------------------------------------------------------------------===//
8477
8478// Utility function to find the type to chop up a widen vector for load/store
8479// TLI: Target lowering used to determine legal types.
8480// Width: Width left need to load/store.
8481// WidenVT: The widen vector type to load to/store from
8482// Align: If 0, don't allow use of a wider type
8483// WidenEx: If Align is not 0, the amount additional we can load/store from.
8484
8485static std::optional<EVT> findMemType(SelectionDAG &DAG,
8486 const TargetLowering &TLI, unsigned Width,
8487 EVT WidenVT, unsigned Align = 0,
8488 unsigned WidenEx = 0) {
8489 EVT WidenEltVT = WidenVT.getVectorElementType();
8490 const bool Scalable = WidenVT.isScalableVector();
8491 unsigned WidenWidth = WidenVT.getSizeInBits().getKnownMinValue();
8492 unsigned WidenEltWidth = WidenEltVT.getSizeInBits();
8493 unsigned AlignInBits = Align*8;
8494
8495 EVT RetVT = WidenEltVT;
8496 // Don't bother looking for an integer type if the vector is scalable, skip
8497 // to vector types.
8498 if (!Scalable) {
8499 // If we have one element to load/store, return it.
8500 if (Width == WidenEltWidth)
8501 return RetVT;
8502
8503 // See if there is larger legal integer than the element type to load/store.
8504 for (EVT MemVT : reverse(MVT::integer_valuetypes())) {
8505 unsigned MemVTWidth = MemVT.getSizeInBits();
8506 if (MemVT.getSizeInBits() <= WidenEltWidth)
8507 break;
8508 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
8509 if ((Action == TargetLowering::TypeLegal ||
8511 (WidenWidth % MemVTWidth) == 0 &&
8512 isPowerOf2_32(WidenWidth / MemVTWidth) &&
8513 (MemVTWidth <= Width ||
8514 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
8515 if (MemVTWidth == WidenWidth)
8516 return MemVT;
8517 RetVT = MemVT;
8518 break;
8519 }
8520 }
8521 }
8522
8523 // See if there is a larger vector type to load/store that has the same vector
8524 // element type and is evenly divisible with the WidenVT.
8525 for (EVT MemVT : reverse(MVT::vector_valuetypes())) {
8526 // Skip vector MVTs which don't match the scalable property of WidenVT.
8527 if (Scalable != MemVT.isScalableVector())
8528 continue;
8529 unsigned MemVTWidth = MemVT.getSizeInBits().getKnownMinValue();
8530 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
8531 if ((Action == TargetLowering::TypeLegal ||
8533 WidenEltVT == MemVT.getVectorElementType() &&
8534 (WidenWidth % MemVTWidth) == 0 &&
8535 isPowerOf2_32(WidenWidth / MemVTWidth) &&
8536 (MemVTWidth <= Width ||
8537 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
8538 if (RetVT.getFixedSizeInBits() < MemVTWidth || MemVT == WidenVT)
8539 return MemVT;
8540 }
8541 }
8542
8543 // Using element-wise loads and stores for widening operations is not
8544 // supported for scalable vectors
8545 if (Scalable)
8546 return std::nullopt;
8547
8548 return RetVT;
8549}
8550
8551// Builds a vector type from scalar loads
8552// VecTy: Resulting Vector type
8553// LDOps: Load operators to build a vector type
8554// [Start,End) the list of loads to use.
8557 unsigned Start, unsigned End) {
8558 SDLoc dl(LdOps[Start]);
8559 EVT LdTy = LdOps[Start].getValueType();
8560 unsigned Width = VecTy.getSizeInBits();
8561 unsigned NumElts = Width / LdTy.getSizeInBits();
8562 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), LdTy, NumElts);
8563
8564 unsigned Idx = 1;
8565 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT,LdOps[Start]);
8566
8567 for (unsigned i = Start + 1; i != End; ++i) {
8568 EVT NewLdTy = LdOps[i].getValueType();
8569 if (NewLdTy != LdTy) {
8570 NumElts = Width / NewLdTy.getSizeInBits();
8571 NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewLdTy, NumElts);
8572 VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, VecOp);
8573 // Readjust position and vector position based on new load type.
8574 Idx = Idx * LdTy.getSizeInBits() / NewLdTy.getSizeInBits();
8575 LdTy = NewLdTy;
8576 }
8577 VecOp = DAG.getInsertVectorElt(dl, VecOp, LdOps[i], Idx++);
8578 }
8579 return DAG.getNode(ISD::BITCAST, dl, VecTy, VecOp);
8580}
8581
8582SDValue DAGTypeLegalizer::GenWidenVectorLoads(SmallVectorImpl<SDValue> &LdChain,
8583 LoadSDNode *LD) {
8584 // The strategy assumes that we can efficiently load power-of-two widths.
8585 // The routine chops the vector into the largest vector loads with the same
8586 // element type or scalar loads and then recombines it to the widen vector
8587 // type.
8588 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
8589 EVT LdVT = LD->getMemoryVT();
8590 SDLoc dl(LD);
8591 assert(LdVT.isVector() && WidenVT.isVector());
8592 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
8594
8595 // Load information
8596 SDValue Chain = LD->getChain();
8597 SDValue BasePtr = LD->getBasePtr();
8598 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
8599 AAMDNodes AAInfo = LD->getAAInfo();
8600
8601 TypeSize LdWidth = LdVT.getSizeInBits();
8602 TypeSize WidenWidth = WidenVT.getSizeInBits();
8603 TypeSize WidthDiff = WidenWidth - LdWidth;
8604 // Allow wider loads if they are sufficiently aligned to avoid memory faults
8605 // and if the original load is simple.
8606 unsigned LdAlign =
8607 (!LD->isSimple() || LdVT.isScalableVector()) ? 0 : LD->getAlign().value();
8608
8609 // Find the vector type that can load from.
8610 std::optional<EVT> FirstVT =
8611 findMemType(DAG, TLI, LdWidth.getKnownMinValue(), WidenVT, LdAlign,
8612 WidthDiff.getKnownMinValue());
8613
8614 if (!FirstVT)
8615 return SDValue();
8616
8617 SmallVector<EVT, 8> MemVTs;
8618 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
8619
8620 // Unless we're able to load in one instruction we must work out how to load
8621 // the remainder.
8622 if (!TypeSize::isKnownLE(LdWidth, FirstVTWidth)) {
8623 std::optional<EVT> NewVT = FirstVT;
8624 TypeSize RemainingWidth = LdWidth;
8625 TypeSize NewVTWidth = FirstVTWidth;
8626 do {
8627 RemainingWidth -= NewVTWidth;
8628 if (TypeSize::isKnownLT(RemainingWidth, NewVTWidth)) {
8629 // The current type we are using is too large. Find a better size.
8630 NewVT = findMemType(DAG, TLI, RemainingWidth.getKnownMinValue(),
8631 WidenVT, LdAlign, WidthDiff.getKnownMinValue());
8632 if (!NewVT)
8633 return SDValue();
8634 NewVTWidth = NewVT->getSizeInBits();
8635 }
8636 MemVTs.push_back(*NewVT);
8637 } while (TypeSize::isKnownGT(RemainingWidth, NewVTWidth));
8638 }
8639
8640 SDValue LdOp = DAG.getLoad(*FirstVT, dl, Chain, BasePtr, LD->getPointerInfo(),
8641 LD->getBaseAlign(), MMOFlags, AAInfo);
8642 LdChain.push_back(LdOp.getValue(1));
8643
8644 // Check if we can load the element with one instruction.
8645 if (MemVTs.empty())
8646 return coerceLoadedValue(LdOp, *FirstVT, WidenVT, LdWidth, FirstVTWidth, dl,
8647 DAG);
8648
8649 // Load vector by using multiple loads from largest vector to scalar.
8651 LdOps.push_back(LdOp);
8652
8653 uint64_t ScaledOffset = 0;
8654 MachinePointerInfo MPI = LD->getPointerInfo();
8655
8656 // First incremement past the first load.
8657 IncrementPointer(cast<LoadSDNode>(LdOp), *FirstVT, MPI, BasePtr,
8658 &ScaledOffset);
8659
8660 for (EVT MemVT : MemVTs) {
8661 Align NewAlign = ScaledOffset == 0
8662 ? LD->getBaseAlign()
8663 : commonAlignment(LD->getAlign(), ScaledOffset);
8664 SDValue L =
8665 DAG.getLoad(MemVT, dl, Chain, BasePtr, MPI, NewAlign, MMOFlags, AAInfo);
8666
8667 LdOps.push_back(L);
8668 LdChain.push_back(L.getValue(1));
8669 IncrementPointer(cast<LoadSDNode>(L), MemVT, MPI, BasePtr, &ScaledOffset);
8670 }
8671
8672 // Build the vector from the load operations.
8673 unsigned End = LdOps.size();
8674 if (!LdOps[0].getValueType().isVector())
8675 // All the loads are scalar loads.
8676 return BuildVectorFromScalar(DAG, WidenVT, LdOps, 0, End);
8677
8678 // If the load contains vectors, build the vector using concat vector.
8679 // All of the vectors used to load are power-of-2, and the scalar loads can be
8680 // combined to make a power-of-2 vector.
8681 SmallVector<SDValue, 16> ConcatOps(End);
8682 int i = End - 1;
8683 int Idx = End;
8684 EVT LdTy = LdOps[i].getValueType();
8685 // First, combine the scalar loads to a vector.
8686 if (!LdTy.isVector()) {
8687 for (--i; i >= 0; --i) {
8688 LdTy = LdOps[i].getValueType();
8689 if (LdTy.isVector())
8690 break;
8691 }
8692 ConcatOps[--Idx] = BuildVectorFromScalar(DAG, LdTy, LdOps, i + 1, End);
8693 }
8694
8695 ConcatOps[--Idx] = LdOps[i];
8696 for (--i; i >= 0; --i) {
8697 EVT NewLdTy = LdOps[i].getValueType();
8698 if (NewLdTy != LdTy) {
8699 // Create a larger vector.
8700 TypeSize LdTySize = LdTy.getSizeInBits();
8701 TypeSize NewLdTySize = NewLdTy.getSizeInBits();
8702 assert(NewLdTySize.isScalable() == LdTySize.isScalable() &&
8703 NewLdTySize.isKnownMultipleOf(LdTySize.getKnownMinValue()));
8704 unsigned NumOps =
8705 NewLdTySize.getKnownMinValue() / LdTySize.getKnownMinValue();
8707 unsigned j = 0;
8708 for (; j != End-Idx; ++j)
8709 WidenOps[j] = ConcatOps[Idx+j];
8710 for (; j != NumOps; ++j)
8711 WidenOps[j] = DAG.getPOISON(LdTy);
8712
8713 ConcatOps[End-1] = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewLdTy,
8714 WidenOps);
8715 Idx = End - 1;
8716 LdTy = NewLdTy;
8717 }
8718 ConcatOps[--Idx] = LdOps[i];
8719 }
8720
8721 if (WidenWidth == LdTy.getSizeInBits() * (End - Idx))
8722 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
8723 ArrayRef(&ConcatOps[Idx], End - Idx));
8724
8725 // We need to fill the rest with undefs to build the vector.
8726 unsigned NumOps =
8727 WidenWidth.getKnownMinValue() / LdTy.getSizeInBits().getKnownMinValue();
8729 SDValue UndefVal = DAG.getPOISON(LdTy);
8730 {
8731 unsigned i = 0;
8732 for (; i != End-Idx; ++i)
8733 WidenOps[i] = ConcatOps[Idx+i];
8734 for (; i != NumOps; ++i)
8735 WidenOps[i] = UndefVal;
8736 }
8737 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, WidenOps);
8738}
8739
8740SDValue
8741DAGTypeLegalizer::GenWidenVectorExtLoads(SmallVectorImpl<SDValue> &LdChain,
8742 LoadSDNode *LD,
8743 ISD::LoadExtType ExtType) {
8744 // For extension loads, it may not be more efficient to chop up the vector
8745 // and then extend it. Instead, we unroll the load and build a new vector.
8746 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
8747 EVT LdVT = LD->getMemoryVT();
8748 SDLoc dl(LD);
8749 assert(LdVT.isVector() && WidenVT.isVector());
8750 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
8751
8752 // Load information
8753 SDValue Chain = LD->getChain();
8754 SDValue BasePtr = LD->getBasePtr();
8755 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
8756 AAMDNodes AAInfo = LD->getAAInfo();
8757
8758 if (LdVT.isScalableVector())
8759 return SDValue();
8760
8761 EVT EltVT = WidenVT.getVectorElementType();
8762 EVT LdEltVT = LdVT.getVectorElementType();
8763 unsigned NumElts = LdVT.getVectorNumElements();
8764
8765 // Load each element and widen.
8766 unsigned WidenNumElts = WidenVT.getVectorNumElements();
8767 SmallVector<SDValue, 16> Ops(WidenNumElts);
8768 unsigned Increment = LdEltVT.getSizeInBits() / 8;
8769 Ops[0] =
8770 DAG.getExtLoad(ExtType, dl, EltVT, Chain, BasePtr, LD->getPointerInfo(),
8771 LdEltVT, LD->getBaseAlign(), MMOFlags, AAInfo);
8772 LdChain.push_back(Ops[0].getValue(1));
8773 unsigned i = 0, Offset = Increment;
8774 for (i=1; i < NumElts; ++i, Offset += Increment) {
8775 SDValue NewBasePtr =
8776 DAG.getObjectPtrOffset(dl, BasePtr, TypeSize::getFixed(Offset));
8777 Ops[i] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, NewBasePtr,
8778 LD->getPointerInfo().getWithOffset(Offset), LdEltVT,
8779 LD->getBaseAlign(), MMOFlags, AAInfo);
8780 LdChain.push_back(Ops[i].getValue(1));
8781 }
8782
8783 // Fill the rest with undefs.
8784 SDValue UndefVal = DAG.getPOISON(EltVT);
8785 for (; i != WidenNumElts; ++i)
8786 Ops[i] = UndefVal;
8787
8788 return DAG.getBuildVector(WidenVT, dl, Ops);
8789}
8790
8791bool DAGTypeLegalizer::GenWidenVectorStores(SmallVectorImpl<SDValue> &StChain,
8792 StoreSDNode *ST) {
8793 // The strategy assumes that we can efficiently store power-of-two widths.
8794 // The routine chops the vector into the largest vector stores with the same
8795 // element type or scalar stores.
8796 SDValue Chain = ST->getChain();
8797 SDValue BasePtr = ST->getBasePtr();
8798 MachineMemOperand::Flags MMOFlags = ST->getMemOperand()->getFlags();
8799 AAMDNodes AAInfo = ST->getAAInfo();
8800 SDValue ValOp = GetWidenedVector(ST->getValue());
8801 SDLoc dl(ST);
8802
8803 EVT StVT = ST->getMemoryVT();
8804 TypeSize StWidth = StVT.getSizeInBits();
8805 EVT ValVT = ValOp.getValueType();
8806 TypeSize ValWidth = ValVT.getSizeInBits();
8807 EVT ValEltVT = ValVT.getVectorElementType();
8808 unsigned ValEltWidth = ValEltVT.getFixedSizeInBits();
8809 assert(StVT.getVectorElementType() == ValEltVT);
8810 assert(StVT.isScalableVector() == ValVT.isScalableVector() &&
8811 "Mismatch between store and value types");
8812
8813 int Idx = 0; // current index to store
8814
8815 MachinePointerInfo MPI = ST->getPointerInfo();
8816 uint64_t ScaledOffset = 0;
8817
8818 // A breakdown of how to widen this vector store. Each element of the vector
8819 // is a memory VT combined with the number of times it is to be stored to,
8820 // e,g., v5i32 -> {{v2i32,2},{i32,1}}
8822
8823 while (StWidth.isNonZero()) {
8824 // Find the largest vector type we can store with.
8825 std::optional<EVT> NewVT =
8826 findMemType(DAG, TLI, StWidth.getKnownMinValue(), ValVT);
8827 if (!NewVT)
8828 return false;
8829 MemVTs.push_back({*NewVT, 0});
8830 TypeSize NewVTWidth = NewVT->getSizeInBits();
8831
8832 do {
8833 StWidth -= NewVTWidth;
8834 MemVTs.back().second++;
8835 } while (StWidth.isNonZero() && TypeSize::isKnownGE(StWidth, NewVTWidth));
8836 }
8837
8838 for (const auto &Pair : MemVTs) {
8839 EVT NewVT = Pair.first;
8840 unsigned Count = Pair.second;
8841 TypeSize NewVTWidth = NewVT.getSizeInBits();
8842
8843 if (NewVT.isVector()) {
8844 unsigned NumVTElts = NewVT.getVectorMinNumElements();
8845 do {
8846 Align NewAlign = ScaledOffset == 0
8847 ? ST->getBaseAlign()
8848 : commonAlignment(ST->getAlign(), ScaledOffset);
8849 SDValue EOp = DAG.getExtractSubvector(dl, NewVT, ValOp, Idx);
8850 SDValue PartStore = DAG.getStore(Chain, dl, EOp, BasePtr, MPI, NewAlign,
8851 MMOFlags, AAInfo);
8852 StChain.push_back(PartStore);
8853
8854 Idx += NumVTElts;
8855 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr,
8856 &ScaledOffset);
8857 } while (--Count);
8858 } else {
8859 // Cast the vector to the scalar type we can store.
8860 unsigned NumElts = ValWidth.getFixedValue() / NewVTWidth.getFixedValue();
8861 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewVT, NumElts);
8862 SDValue VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, ValOp);
8863 // Readjust index position based on new vector type.
8864 Idx = Idx * ValEltWidth / NewVTWidth.getFixedValue();
8865 do {
8866 SDValue EOp = DAG.getExtractVectorElt(dl, NewVT, VecOp, Idx++);
8867 SDValue PartStore = DAG.getStore(Chain, dl, EOp, BasePtr, MPI,
8868 ST->getBaseAlign(), MMOFlags, AAInfo);
8869 StChain.push_back(PartStore);
8870
8871 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr);
8872 } while (--Count);
8873 // Restore index back to be relative to the original widen element type.
8874 Idx = Idx * NewVTWidth.getFixedValue() / ValEltWidth;
8875 }
8876 }
8877
8878 return true;
8879}
8880
8881/// Modifies a vector input (widen or narrows) to a vector of NVT. The
8882/// input vector must have the same element type as NVT.
8883/// FillWithZeroes specifies that the vector should be widened with zeroes.
8884SDValue DAGTypeLegalizer::ModifyToType(SDValue InOp, EVT NVT,
8885 bool FillWithZeroes) {
8886 // Note that InOp might have been widened so it might already have
8887 // the right width or it might need be narrowed.
8888 EVT InVT = InOp.getValueType();
8890 "input and widen element type must match");
8891 assert(InVT.isScalableVector() == NVT.isScalableVector() &&
8892 "cannot modify scalable vectors in this way");
8893 SDLoc dl(InOp);
8894
8895 // Check if InOp already has the right width.
8896 if (InVT == NVT)
8897 return InOp;
8898
8899 ElementCount InEC = InVT.getVectorElementCount();
8900 ElementCount WidenEC = NVT.getVectorElementCount();
8901 if (WidenEC.hasKnownScalarFactor(InEC)) {
8902 unsigned NumConcat = WidenEC.getKnownScalarFactor(InEC);
8903 SmallVector<SDValue, 16> Ops(NumConcat);
8904 SDValue FillVal =
8905 FillWithZeroes ? DAG.getConstant(0, dl, InVT) : DAG.getPOISON(InVT);
8906 Ops[0] = InOp;
8907 for (unsigned i = 1; i != NumConcat; ++i)
8908 Ops[i] = FillVal;
8909
8910 return DAG.getNode(ISD::CONCAT_VECTORS, dl, NVT, Ops);
8911 }
8912
8913 if (InEC.hasKnownScalarFactor(WidenEC))
8914 return DAG.getExtractSubvector(dl, NVT, InOp, 0);
8915
8916 assert(!InVT.isScalableVector() && !NVT.isScalableVector() &&
8917 "Scalable vectors should have been handled already.");
8918
8919 unsigned InNumElts = InEC.getFixedValue();
8920 unsigned WidenNumElts = WidenEC.getFixedValue();
8921
8922 // Fall back to extract and build (+ mask, if padding with zeros).
8923 SmallVector<SDValue, 16> Ops(WidenNumElts);
8924 EVT EltVT = NVT.getVectorElementType();
8925 unsigned MinNumElts = std::min(WidenNumElts, InNumElts);
8926 unsigned Idx;
8927 for (Idx = 0; Idx < MinNumElts; ++Idx)
8928 Ops[Idx] = DAG.getExtractVectorElt(dl, EltVT, InOp, Idx);
8929
8930 SDValue UndefVal = DAG.getPOISON(EltVT);
8931 for (; Idx < WidenNumElts; ++Idx)
8932 Ops[Idx] = UndefVal;
8933
8934 SDValue Widened = DAG.getBuildVector(NVT, dl, Ops);
8935 if (!FillWithZeroes)
8936 return Widened;
8937
8938 assert(NVT.isInteger() &&
8939 "We expect to never want to FillWithZeroes for non-integral types.");
8940
8942 MaskOps.append(MinNumElts, DAG.getAllOnesConstant(dl, EltVT));
8943 MaskOps.append(WidenNumElts - MinNumElts, DAG.getConstant(0, dl, EltVT));
8944
8945 return DAG.getNode(ISD::AND, dl, NVT, Widened,
8946 DAG.getBuildVector(NVT, dl, MaskOps));
8947}
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
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.