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