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