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