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);
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);
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();
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
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);
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);
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();
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 }
5554 Res = WidenVecRes_PARTIAL_REDUCE_MLA(N);
5555 break;
5556 }
5557
5558 // If Res is null, the sub-method took care of registering the result.
5559 if (Res.getNode())
5560 SetWidenedVector(SDValue(N, ResNo), Res);
5561}
5562
5563SDValue DAGTypeLegalizer::WidenVecRes_Ternary(SDNode *N) {
5564 // Ternary op widening.
5565 SDLoc dl(N);
5566 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5567 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5568 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5569 SDValue InOp3 = GetWidenedVector(N->getOperand(2));
5570 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3);
5571}
5572
5573SDValue DAGTypeLegalizer::WidenVecRes_Binary(SDNode *N) {
5574 // Binary op widening.
5575 SDLoc dl(N);
5576 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5577 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5578 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5579 if (N->getNumOperands() == 2)
5580 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2,
5581 N->getFlags());
5582
5583 assert(N->getNumOperands() == 4 && "Unexpected number of operands!");
5584 assert((N->getOpcode() == ISD::VP_UDIV || N->getOpcode() == ISD::VP_SDIV ||
5585 N->getOpcode() == ISD::VP_UREM || N->getOpcode() == ISD::VP_SREM) &&
5586 "Expected VP opcode");
5587
5588 SDValue Mask =
5589 GetWidenedMask(N->getOperand(2), WidenVT.getVectorElementCount());
5590 return DAG.getNode(N->getOpcode(), dl, WidenVT,
5591 {InOp1, InOp2, Mask, N->getOperand(3)}, N->getFlags());
5592}
5593
5594SDValue DAGTypeLegalizer::WidenVecRes_MaskedBinary(SDNode *N) {
5595 SDLoc dl(N);
5596 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5597 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5598 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5599 SDValue Mask = N->getOperand(2);
5600 EVT WideMaskVT = WidenVT.changeVectorElementType(
5601 *DAG.getContext(), Mask.getValueType().getVectorElementType());
5602 Mask = ModifyToType(Mask, WideMaskVT, /*FillWithZeros=*/true);
5603 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, Mask,
5604 N->getFlags());
5605}
5606
5607SDValue DAGTypeLegalizer::WidenVecRes_CMP(SDNode *N) {
5608 LLVMContext &Ctxt = *DAG.getContext();
5609 SDLoc dl(N);
5610
5611 SDValue LHS = N->getOperand(0);
5612 SDValue RHS = N->getOperand(1);
5613 EVT OpVT = LHS.getValueType();
5614 if (getTypeAction(OpVT) == TargetLowering::TypeWidenVector) {
5615 LHS = GetWidenedVector(LHS);
5616 RHS = GetWidenedVector(RHS);
5617 OpVT = LHS.getValueType();
5618 }
5619
5620 EVT WidenResVT = TLI.getTypeToTransformTo(Ctxt, N->getValueType(0));
5621 ElementCount WidenResEC = WidenResVT.getVectorElementCount();
5622 if (WidenResEC == OpVT.getVectorElementCount()) {
5623 return DAG.getNode(N->getOpcode(), dl, WidenResVT, LHS, RHS);
5624 }
5625
5626 return DAG.UnrollVectorOp(N, WidenResVT.getVectorNumElements());
5627}
5628
5629SDValue DAGTypeLegalizer::WidenVecRes_BinaryWithExtraScalarOp(SDNode *N) {
5630 // Binary op widening, but with an extra operand that shouldn't be widened.
5631 SDLoc dl(N);
5632 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5633 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5634 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5635 SDValue InOp3 = N->getOperand(2);
5636 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3,
5637 N->getFlags());
5638}
5639
5640// Given a vector of operations that have been broken up to widen, see
5641// if we can collect them together into the next widest legal VT. This
5642// implementation is trap-safe.
5644 SmallVectorImpl<SDValue> &ConcatOps,
5645 unsigned ConcatEnd, EVT VT, EVT MaxVT,
5646 EVT WidenVT) {
5647 // Check to see if we have a single operation with the widen type.
5648 if (ConcatEnd == 1) {
5649 VT = ConcatOps[0].getValueType();
5650 if (VT == WidenVT)
5651 return ConcatOps[0];
5652 }
5653
5654 SDLoc dl(ConcatOps[0]);
5655 EVT WidenEltVT = WidenVT.getVectorElementType();
5656
5657 // while (Some element of ConcatOps is not of type MaxVT) {
5658 // From the end of ConcatOps, collect elements of the same type and put
5659 // them into an op of the next larger supported type
5660 // }
5661 while (ConcatOps[ConcatEnd-1].getValueType() != MaxVT) {
5662 int Idx = ConcatEnd - 1;
5663 VT = ConcatOps[Idx--].getValueType();
5664 while (Idx >= 0 && ConcatOps[Idx].getValueType() == VT)
5665 Idx--;
5666
5667 int NextSize = VT.isVector() ? VT.getVectorNumElements() : 1;
5668 EVT NextVT;
5669 do {
5670 NextSize *= 2;
5671 NextVT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NextSize);
5672 } while (!TLI.isTypeLegal(NextVT));
5673
5674 if (!VT.isVector()) {
5675 // Scalar type, create an INSERT_VECTOR_ELEMENT of type NextVT
5676 SDValue VecOp = DAG.getPOISON(NextVT);
5677 unsigned NumToInsert = ConcatEnd - Idx - 1;
5678 for (unsigned i = 0, OpIdx = Idx + 1; i < NumToInsert; i++, OpIdx++)
5679 VecOp = DAG.getInsertVectorElt(dl, VecOp, ConcatOps[OpIdx], i);
5680 ConcatOps[Idx+1] = VecOp;
5681 ConcatEnd = Idx + 2;
5682 } else {
5683 // Vector type, create a CONCAT_VECTORS of type NextVT
5684 SDValue undefVec = DAG.getPOISON(VT);
5685 unsigned OpsToConcat = NextSize/VT.getVectorNumElements();
5686 SmallVector<SDValue, 16> SubConcatOps(OpsToConcat);
5687 unsigned RealVals = ConcatEnd - Idx - 1;
5688 unsigned SubConcatEnd = 0;
5689 unsigned SubConcatIdx = Idx + 1;
5690 while (SubConcatEnd < RealVals)
5691 SubConcatOps[SubConcatEnd++] = ConcatOps[++Idx];
5692 while (SubConcatEnd < OpsToConcat)
5693 SubConcatOps[SubConcatEnd++] = undefVec;
5694 ConcatOps[SubConcatIdx] = DAG.getNode(ISD::CONCAT_VECTORS, dl,
5695 NextVT, SubConcatOps);
5696 ConcatEnd = SubConcatIdx + 1;
5697 }
5698 }
5699
5700 // Check to see if we have a single operation with the widen type.
5701 if (ConcatEnd == 1) {
5702 VT = ConcatOps[0].getValueType();
5703 if (VT == WidenVT)
5704 return ConcatOps[0];
5705 }
5706
5707 // add undefs of size MaxVT until ConcatOps grows to length of WidenVT
5708 unsigned NumOps = WidenVT.getVectorNumElements()/MaxVT.getVectorNumElements();
5709 if (NumOps != ConcatEnd ) {
5710 SDValue UndefVal = DAG.getPOISON(MaxVT);
5711 for (unsigned j = ConcatEnd; j < NumOps; ++j)
5712 ConcatOps[j] = UndefVal;
5713 }
5714 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
5715 ArrayRef(ConcatOps.data(), NumOps));
5716}
5717
5718SDValue DAGTypeLegalizer::WidenVecRes_BinaryCanTrap(SDNode *N) {
5719 // Binary op widening for operations that can trap.
5720 unsigned Opcode = N->getOpcode();
5721 SDLoc dl(N);
5722 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5723 EVT WidenEltVT = WidenVT.getVectorElementType();
5724 EVT VT = WidenVT;
5725 unsigned NumElts = VT.getVectorMinNumElements();
5726 const SDNodeFlags Flags = N->getFlags();
5727 while (!TLI.isTypeLegal(VT) && NumElts != 1) {
5728 NumElts = NumElts / 2;
5729 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5730 }
5731
5732 if (NumElts != 1 && !TLI.canOpTrap(N->getOpcode(), VT)) {
5733 // Operation doesn't trap so just widen as normal.
5734 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5735 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5736 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, Flags);
5737 }
5738
5739 // Generate a vp.op if it is custom/legal for the target. This avoids need
5740 // to split and tile the subvectors (below), because the inactive lanes can
5741 // simply be disabled. To avoid possible recursion, only do this if the
5742 // widened mask type is legal.
5743 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opcode);
5744 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WidenVT)) {
5745 if (EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
5746 WidenVT.getVectorElementCount());
5747 TLI.isTypeLegal(WideMaskVT)) {
5748 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5749 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5750 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
5751 SDValue EVL =
5752 DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
5753 N->getValueType(0).getVectorElementCount());
5754 return DAG.getNode(*VPOpcode, dl, WidenVT, InOp1, InOp2, Mask, EVL,
5755 Flags);
5756 }
5757 }
5758
5759 // FIXME: Improve support for scalable vectors.
5760 assert(!VT.isScalableVector() && "Scalable vectors not handled yet.");
5761
5762 // No legal vector version so unroll the vector operation and then widen.
5763 if (NumElts == 1)
5764 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
5765
5766 // Since the operation can trap, apply operation on the original vector.
5767 EVT MaxVT = VT;
5768 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5769 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5770 unsigned CurNumElts = N->getValueType(0).getVectorNumElements();
5771
5772 SmallVector<SDValue, 16> ConcatOps(CurNumElts);
5773 unsigned ConcatEnd = 0; // Current ConcatOps index.
5774 int Idx = 0; // Current Idx into input vectors.
5775
5776 // NumElts := greatest legal vector size (at most WidenVT)
5777 // while (orig. vector has unhandled elements) {
5778 // take munches of size NumElts from the beginning and add to ConcatOps
5779 // NumElts := next smaller supported vector size or 1
5780 // }
5781 while (CurNumElts != 0) {
5782 while (CurNumElts >= NumElts) {
5783 SDValue EOp1 = DAG.getExtractSubvector(dl, VT, InOp1, Idx);
5784 SDValue EOp2 = DAG.getExtractSubvector(dl, VT, InOp2, Idx);
5785 ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, VT, EOp1, EOp2, Flags);
5786 Idx += NumElts;
5787 CurNumElts -= NumElts;
5788 }
5789 do {
5790 NumElts = NumElts / 2;
5791 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5792 } while (!TLI.isTypeLegal(VT) && NumElts != 1);
5793
5794 if (NumElts == 1) {
5795 for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
5796 SDValue EOp1 = DAG.getExtractVectorElt(dl, WidenEltVT, InOp1, Idx);
5797 SDValue EOp2 = DAG.getExtractVectorElt(dl, WidenEltVT, InOp2, Idx);
5798 ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, WidenEltVT,
5799 EOp1, EOp2, Flags);
5800 }
5801 CurNumElts = 0;
5802 }
5803 }
5804
5805 return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
5806}
5807
5808SDValue DAGTypeLegalizer::WidenVecRes_StrictFP(SDNode *N) {
5809 switch (N->getOpcode()) {
5810 case ISD::STRICT_FSETCC:
5812 return WidenVecRes_STRICT_FSETCC(N);
5819 return WidenVecRes_Convert_StrictFP(N);
5820 default:
5821 break;
5822 }
5823
5824 // StrictFP op widening for operations that can trap.
5825 unsigned NumOpers = N->getNumOperands();
5826 unsigned Opcode = N->getOpcode();
5827 SDLoc dl(N);
5828 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5829 EVT WidenEltVT = WidenVT.getVectorElementType();
5830 EVT VT = WidenVT;
5831 unsigned NumElts = VT.getVectorNumElements();
5832 while (!TLI.isTypeLegal(VT) && NumElts != 1) {
5833 NumElts = NumElts / 2;
5834 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5835 }
5836
5837 // No legal vector version so unroll the vector operation and then widen.
5838 if (NumElts == 1)
5839 return UnrollVectorOp_StrictFP(N, WidenVT.getVectorNumElements());
5840
5841 // Since the operation can trap, apply operation on the original vector.
5842 EVT MaxVT = VT;
5844 unsigned CurNumElts = N->getValueType(0).getVectorNumElements();
5845
5846 SmallVector<SDValue, 16> ConcatOps(CurNumElts);
5848 unsigned ConcatEnd = 0; // Current ConcatOps index.
5849 int Idx = 0; // Current Idx into input vectors.
5850
5851 // The Chain is the first operand.
5852 InOps.push_back(N->getOperand(0));
5853
5854 // Now process the remaining operands.
5855 for (unsigned i = 1; i < NumOpers; ++i) {
5856 SDValue Oper = N->getOperand(i);
5857
5858 EVT OpVT = Oper.getValueType();
5859 if (OpVT.isVector()) {
5860 if (getTypeAction(OpVT) == TargetLowering::TypeWidenVector)
5861 Oper = GetWidenedVector(Oper);
5862 else {
5863 EVT WideOpVT =
5864 EVT::getVectorVT(*DAG.getContext(), OpVT.getVectorElementType(),
5865 WidenVT.getVectorElementCount());
5866 Oper = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WideOpVT,
5867 DAG.getPOISON(WideOpVT), Oper,
5868 DAG.getVectorIdxConstant(0, dl));
5869 }
5870 }
5871
5872 InOps.push_back(Oper);
5873 }
5874
5875 // NumElts := greatest legal vector size (at most WidenVT)
5876 // while (orig. vector has unhandled elements) {
5877 // take munches of size NumElts from the beginning and add to ConcatOps
5878 // NumElts := next smaller supported vector size or 1
5879 // }
5880 while (CurNumElts != 0) {
5881 while (CurNumElts >= NumElts) {
5883
5884 for (unsigned i = 0; i < NumOpers; ++i) {
5885 SDValue Op = InOps[i];
5886
5887 EVT OpVT = Op.getValueType();
5888 if (OpVT.isVector()) {
5889 EVT OpExtractVT =
5890 EVT::getVectorVT(*DAG.getContext(), OpVT.getVectorElementType(),
5892 Op = DAG.getExtractSubvector(dl, OpExtractVT, Op, Idx);
5893 }
5894
5895 EOps.push_back(Op);
5896 }
5897
5898 EVT OperVT[] = {VT, MVT::Other};
5899 SDValue Oper = DAG.getNode(Opcode, dl, OperVT, EOps);
5900 ConcatOps[ConcatEnd++] = Oper;
5901 Chains.push_back(Oper.getValue(1));
5902 Idx += NumElts;
5903 CurNumElts -= NumElts;
5904 }
5905 do {
5906 NumElts = NumElts / 2;
5907 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5908 } while (!TLI.isTypeLegal(VT) && NumElts != 1);
5909
5910 if (NumElts == 1) {
5911 for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
5913
5914 for (unsigned i = 0; i < NumOpers; ++i) {
5915 SDValue Op = InOps[i];
5916
5917 EVT OpVT = Op.getValueType();
5918 if (OpVT.isVector())
5919 Op = DAG.getExtractVectorElt(dl, OpVT.getVectorElementType(), Op,
5920 Idx);
5921
5922 EOps.push_back(Op);
5923 }
5924
5925 EVT WidenVT[] = {WidenEltVT, MVT::Other};
5926 SDValue Oper = DAG.getNode(Opcode, dl, WidenVT, EOps);
5927 ConcatOps[ConcatEnd++] = Oper;
5928 Chains.push_back(Oper.getValue(1));
5929 }
5930 CurNumElts = 0;
5931 }
5932 }
5933
5934 // Build a factor node to remember all the Ops that have been created.
5935 SDValue NewChain;
5936 if (Chains.size() == 1)
5937 NewChain = Chains[0];
5938 else
5939 NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
5940 ReplaceValueWith(SDValue(N, 1), NewChain);
5941
5942 return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
5943}
5944
5945SDValue DAGTypeLegalizer::WidenVecRes_OverflowOp(SDNode *N, unsigned ResNo) {
5946 SDLoc DL(N);
5947 EVT ResVT = N->getValueType(0);
5948 EVT OvVT = N->getValueType(1);
5949 EVT WideResVT, WideOvVT;
5950 SDValue WideLHS, WideRHS;
5951
5952 // TODO: This might result in a widen/split loop.
5953 if (ResNo == 0) {
5954 WideResVT = TLI.getTypeToTransformTo(*DAG.getContext(), ResVT);
5955 WideOvVT = EVT::getVectorVT(
5956 *DAG.getContext(), OvVT.getVectorElementType(),
5957 WideResVT.getVectorNumElements());
5958
5959 WideLHS = GetWidenedVector(N->getOperand(0));
5960 WideRHS = GetWidenedVector(N->getOperand(1));
5961 } else {
5962 WideOvVT = TLI.getTypeToTransformTo(*DAG.getContext(), OvVT);
5963 WideResVT = EVT::getVectorVT(
5964 *DAG.getContext(), ResVT.getVectorElementType(),
5965 WideOvVT.getVectorNumElements());
5966
5967 SDValue Zero = DAG.getVectorIdxConstant(0, DL);
5968 SDValue Poison = DAG.getPOISON(WideResVT);
5969
5970 WideLHS = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideResVT, Poison,
5971 N->getOperand(0), Zero);
5972 WideRHS = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideResVT, Poison,
5973 N->getOperand(1), Zero);
5974 }
5975
5976 SDVTList WideVTs = DAG.getVTList(WideResVT, WideOvVT);
5977 SDNode *WideNode = DAG.getNode(
5978 N->getOpcode(), DL, WideVTs, WideLHS, WideRHS).getNode();
5979
5980 // Replace the other vector result not being explicitly widened here.
5981 unsigned OtherNo = 1 - ResNo;
5982 EVT OtherVT = N->getValueType(OtherNo);
5983 if (getTypeAction(OtherVT) == TargetLowering::TypeWidenVector) {
5984 SetWidenedVector(SDValue(N, OtherNo), SDValue(WideNode, OtherNo));
5985 } else {
5986 SDValue Zero = DAG.getVectorIdxConstant(0, DL);
5987 SDValue OtherVal = DAG.getNode(
5988 ISD::EXTRACT_SUBVECTOR, DL, OtherVT, SDValue(WideNode, OtherNo), Zero);
5989 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
5990 }
5991
5992 return SDValue(WideNode, ResNo);
5993}
5994
5995SDValue DAGTypeLegalizer::WidenVecRes_Convert(SDNode *N) {
5996 LLVMContext &Ctx = *DAG.getContext();
5997 SDValue InOp = N->getOperand(0);
5998 SDLoc DL(N);
5999
6000 EVT WidenVT = TLI.getTypeToTransformTo(Ctx, N->getValueType(0));
6001 ElementCount WidenEC = WidenVT.getVectorElementCount();
6002
6003 EVT InVT = InOp.getValueType();
6004
6005 unsigned Opcode = N->getOpcode();
6006 const SDNodeFlags Flags = N->getFlags();
6007
6008 // Handle the case of ZERO_EXTEND where the promoted InVT element size does
6009 // not equal that of WidenVT.
6010 if (N->getOpcode() == ISD::ZERO_EXTEND &&
6011 getTypeAction(InVT) == TargetLowering::TypePromoteInteger &&
6012 TLI.getTypeToTransformTo(Ctx, InVT).getScalarSizeInBits() !=
6013 WidenVT.getScalarSizeInBits()) {
6014 InOp = ZExtPromotedInteger(InOp);
6015 InVT = InOp.getValueType();
6016 if (WidenVT.getScalarSizeInBits() < InVT.getScalarSizeInBits())
6017 Opcode = ISD::TRUNCATE;
6018 }
6019
6020 EVT InEltVT = InVT.getVectorElementType();
6021 EVT InWidenVT = EVT::getVectorVT(Ctx, InEltVT, WidenEC);
6022 ElementCount InVTEC = InVT.getVectorElementCount();
6023
6024 // Helper to build node with all scalar trailing operands.
6025 auto MakeConvertNode = [&](EVT VT, SDValue Op) -> SDValue {
6026 if (N->getNumOperands() == 1)
6027 return DAG.getNode(Opcode, DL, VT, Op, Flags);
6028 if (Opcode == ISD::CONVERT_TO_ARBITRARY_FP)
6029 return DAG.getNode(Opcode, DL, VT, Op, N->getOperand(1), N->getOperand(2),
6030 N->getOperand(3), Flags);
6031 return DAG.getNode(Opcode, DL, VT, Op, N->getOperand(1), Flags);
6032 };
6033
6034 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
6035 InOp = GetWidenedVector(N->getOperand(0));
6036 InVT = InOp.getValueType();
6037 InVTEC = InVT.getVectorElementCount();
6038 if (InVTEC == WidenEC)
6039 return MakeConvertNode(WidenVT, InOp);
6040 if (WidenVT.getSizeInBits() == InVT.getSizeInBits()) {
6041 // If both input and result vector types are of same width, extend
6042 // operations should be done with SIGN/ZERO_EXTEND_VECTOR_INREG, which
6043 // accepts fewer elements in the result than in the input.
6044 if (Opcode == ISD::ANY_EXTEND)
6045 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
6046 if (Opcode == ISD::SIGN_EXTEND)
6047 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
6048 if (Opcode == ISD::ZERO_EXTEND)
6049 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
6050 }
6051
6052 // For TRUNCATE, try to widen using the legal EC of the input type instead
6053 // if the legalisation action for that intermediate type is not widening.
6054 // E.g. for trunc nxv1i64 -> nxv1i8 where
6055 // - nxv1i64 input gets widened to nxv2i64
6056 // - nxv1i8 output gets widened to nxv16i8
6057 // Then one can try widening the result to nxv2i8 (instead of going all the
6058 // way to nxv16i8) if this later allows type promotion.
6059 EVT MidResVT =
6060 EVT::getVectorVT(Ctx, WidenVT.getVectorElementType(), InVTEC);
6061 if (N->getOpcode() == ISD::TRUNCATE &&
6062 getTypeAction(MidResVT) == TargetLowering::TypePromoteInteger) {
6063 SDValue MidRes = DAG.getNode(ISD::TRUNCATE, DL, MidResVT, InOp, Flags);
6064 return DAG.getInsertSubvector(DL, DAG.getPOISON(WidenVT), MidRes, 0);
6065 }
6066 }
6067
6068 if (TLI.isTypeLegal(InWidenVT)) {
6069 // Because the result and the input are different vector types, widening
6070 // the result could create a legal type but widening the input might make
6071 // it an illegal type that might lead to repeatedly splitting the input
6072 // and then widening it. To avoid this, we widen the input only if
6073 // it results in a legal type.
6074 if (WidenEC.isKnownMultipleOf(InVTEC.getKnownMinValue())) {
6075 // Widen the input and call convert on the widened input vector.
6076 unsigned NumConcat =
6077 WidenEC.getKnownMinValue() / InVTEC.getKnownMinValue();
6078 SmallVector<SDValue, 16> Ops(NumConcat, DAG.getPOISON(InVT));
6079 Ops[0] = InOp;
6080 SDValue InVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InWidenVT, Ops);
6081 return MakeConvertNode(WidenVT, InVec);
6082 }
6083
6084 if (InVTEC.isKnownMultipleOf(WidenEC.getKnownMinValue())) {
6085 SDValue InVal = DAG.getExtractSubvector(DL, InWidenVT, InOp, 0);
6086 // Extract the input and convert the shorten input vector.
6087 return MakeConvertNode(WidenVT, InVal);
6088 }
6089 }
6090
6091 // Otherwise unroll into some nasty scalar code and rebuild the vector.
6092 EVT EltVT = WidenVT.getVectorElementType();
6093 SmallVector<SDValue, 16> Ops(WidenEC.getFixedValue(), DAG.getPOISON(EltVT));
6094 // Use the original element count so we don't do more scalar opts than
6095 // necessary.
6096 unsigned MinElts = N->getValueType(0).getVectorNumElements();
6097 for (unsigned i=0; i < MinElts; ++i) {
6098 SDValue Val = DAG.getExtractVectorElt(DL, InEltVT, InOp, i);
6099 Ops[i] = MakeConvertNode(EltVT, Val);
6100 }
6101
6102 return DAG.getBuildVector(WidenVT, DL, Ops);
6103}
6104
6105SDValue DAGTypeLegalizer::WidenVecRes_FP_TO_XINT_SAT(SDNode *N) {
6106 SDLoc dl(N);
6107 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6108 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
6109
6110 SDValue Src = N->getOperand(0);
6111 EVT SrcVT = Src.getValueType();
6112
6113 // Also widen the input.
6114 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
6115 Src = GetWidenedVector(Src);
6116 SrcVT = Src.getValueType();
6117 }
6118
6119 // Input and output not widened to the same size, give up.
6120 if (WidenNumElts != SrcVT.getVectorElementCount())
6121 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
6122
6123 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src, N->getOperand(1));
6124}
6125
6126SDValue DAGTypeLegalizer::WidenVecRes_XROUND(SDNode *N) {
6127 SDLoc dl(N);
6128 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6129 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
6130
6131 SDValue Src = N->getOperand(0);
6132 EVT SrcVT = Src.getValueType();
6133
6134 // Also widen the input.
6135 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
6136 Src = GetWidenedVector(Src);
6137 SrcVT = Src.getValueType();
6138 }
6139
6140 // Input and output not widened to the same size, give up.
6141 if (WidenNumElts != SrcVT.getVectorElementCount())
6142 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
6143
6144 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src);
6145}
6146
6147SDValue DAGTypeLegalizer::WidenVecRes_Convert_StrictFP(SDNode *N) {
6148 SDValue InOp = N->getOperand(1);
6149 SDLoc DL(N);
6150 SmallVector<SDValue, 4> NewOps(N->ops());
6151
6152 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6153 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6154
6155 EVT InVT = InOp.getValueType();
6156 EVT InEltVT = InVT.getVectorElementType();
6157
6158 unsigned Opcode = N->getOpcode();
6159
6160 // FIXME: Optimizations need to be implemented here.
6161
6162 // Otherwise unroll into some nasty scalar code and rebuild the vector.
6163 EVT EltVT = WidenVT.getVectorElementType();
6164 std::array<EVT, 2> EltVTs = {{EltVT, MVT::Other}};
6165 SmallVector<SDValue, 16> Ops(WidenNumElts, DAG.getPOISON(EltVT));
6166 SmallVector<SDValue, 32> OpChains;
6167 // Use the original element count so we don't do more scalar opts than
6168 // necessary.
6169 unsigned MinElts = N->getValueType(0).getVectorNumElements();
6170 for (unsigned i=0; i < MinElts; ++i) {
6171 NewOps[1] = DAG.getExtractVectorElt(DL, InEltVT, InOp, i);
6172 Ops[i] = DAG.getNode(Opcode, DL, EltVTs, NewOps);
6173 OpChains.push_back(Ops[i].getValue(1));
6174 }
6175 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OpChains);
6176 ReplaceValueWith(SDValue(N, 1), NewChain);
6177
6178 return DAG.getBuildVector(WidenVT, DL, Ops);
6179}
6180
6181SDValue DAGTypeLegalizer::WidenVecRes_EXTEND_VECTOR_INREG(SDNode *N) {
6182 unsigned Opcode = N->getOpcode();
6183 SDValue InOp = N->getOperand(0);
6184 SDLoc DL(N);
6185
6186 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6187 EVT WidenSVT = WidenVT.getVectorElementType();
6188 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6189
6190 EVT InVT = InOp.getValueType();
6191 EVT InSVT = InVT.getVectorElementType();
6192 unsigned InVTNumElts = InVT.getVectorNumElements();
6193
6194 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
6195 InOp = GetWidenedVector(InOp);
6196 InVT = InOp.getValueType();
6197 if (InVT.getSizeInBits() == WidenVT.getSizeInBits()) {
6198 switch (Opcode) {
6202 return DAG.getNode(Opcode, DL, WidenVT, InOp);
6203 }
6204 }
6205 }
6206
6207 // Unroll, extend the scalars and rebuild the vector.
6209 for (unsigned i = 0, e = std::min(InVTNumElts, WidenNumElts); i != e; ++i) {
6210 SDValue Val = DAG.getExtractVectorElt(DL, InSVT, InOp, i);
6211 switch (Opcode) {
6213 Val = DAG.getNode(ISD::ANY_EXTEND, DL, WidenSVT, Val);
6214 break;
6216 Val = DAG.getNode(ISD::SIGN_EXTEND, DL, WidenSVT, Val);
6217 break;
6219 Val = DAG.getNode(ISD::ZERO_EXTEND, DL, WidenSVT, Val);
6220 break;
6221 default:
6222 llvm_unreachable("A *_EXTEND_VECTOR_INREG node was expected");
6223 }
6224 Ops.push_back(Val);
6225 }
6226
6227 while (Ops.size() != WidenNumElts)
6228 Ops.push_back(DAG.getPOISON(WidenSVT));
6229
6230 return DAG.getBuildVector(WidenVT, DL, Ops);
6231}
6232
6233SDValue DAGTypeLegalizer::WidenVecRes_FCOPYSIGN(SDNode *N) {
6234 // If this is an FCOPYSIGN with same input types, we can treat it as a
6235 // normal (can trap) binary op.
6236 if (N->getOperand(0).getValueType() == N->getOperand(1).getValueType())
6237 return WidenVecRes_BinaryCanTrap(N);
6238
6239 // If the types are different, fall back to unrolling.
6240 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6241 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
6242}
6243
6244/// Result and first source operand are different scalar types, but must have
6245/// the same number of elements. There is an additional control argument which
6246/// should be passed through unchanged.
6247SDValue DAGTypeLegalizer::WidenVecRes_UnarySameEltsWithScalarArg(SDNode *N) {
6248 SDValue FpValue = N->getOperand(0);
6249 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6250 if (getTypeAction(FpValue.getValueType()) != TargetLowering::TypeWidenVector)
6251 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
6252 SDValue Arg = GetWidenedVector(FpValue);
6253 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, {Arg, N->getOperand(1)},
6254 N->getFlags());
6255}
6256
6257SDValue DAGTypeLegalizer::WidenVecRes_ExpOp(SDNode *N) {
6258 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6259 SDValue InOp = GetWidenedVector(N->getOperand(0));
6260 SDValue RHS = N->getOperand(1);
6261 EVT ExpVT = RHS.getValueType();
6262 SDValue ExpOp = RHS;
6263 if (ExpVT.isVector()) {
6264 EVT WideExpVT = WidenVT.changeVectorElementType(
6265 *DAG.getContext(), ExpVT.getVectorElementType());
6266 ExpOp = ModifyToType(RHS, WideExpVT);
6267 }
6268
6269 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, ExpOp);
6270}
6271
6272SDValue DAGTypeLegalizer::WidenVecRes_Unary(SDNode *N) {
6273 // Unary op widening.
6274 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6275 SDValue InOp = GetWidenedVector(N->getOperand(0));
6276 if (N->getNumOperands() == 1)
6277 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, N->getFlags());
6278 assert(N->getOpcode() == ISD::AssertNoFPClass && "unexpected opcode");
6279 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, N->getOperand(1),
6280 N->getFlags());
6281}
6282
6283SDValue DAGTypeLegalizer::WidenVecRes_InregOp(SDNode *N) {
6284 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6285 EVT ExtVT = EVT::getVectorVT(
6286 *DAG.getContext(),
6287 cast<VTSDNode>(N->getOperand(1))->getVT().getVectorElementType(),
6288 WidenVT.getVectorElementCount());
6289 SDValue WidenLHS = GetWidenedVector(N->getOperand(0));
6290 return DAG.getNode(N->getOpcode(), SDLoc(N),
6291 WidenVT, WidenLHS, DAG.getValueType(ExtVT));
6292}
6293
6294SDValue DAGTypeLegalizer::WidenVecRes_UnaryOpWithTwoResults(SDNode *N,
6295 unsigned ResNo) {
6296 EVT VT0 = N->getValueType(0);
6297 EVT VT1 = N->getValueType(1);
6298
6299 assert(VT0.isVector() && VT1.isVector() &&
6301 "expected both results to be vectors of matching element count");
6302
6303 LLVMContext &Ctx = *DAG.getContext();
6304 SDValue InOp = GetWidenedVector(N->getOperand(0));
6305
6306 EVT WidenVT = TLI.getTypeToTransformTo(Ctx, N->getValueType(ResNo));
6307 ElementCount WidenEC = WidenVT.getVectorElementCount();
6308
6309 EVT WidenVT0 = EVT::getVectorVT(Ctx, VT0.getVectorElementType(), WidenEC);
6310 EVT WidenVT1 = EVT::getVectorVT(Ctx, VT1.getVectorElementType(), WidenEC);
6311
6312 SDNode *WidenNode =
6313 DAG.getNode(N->getOpcode(), SDLoc(N), {WidenVT0, WidenVT1}, InOp)
6314 .getNode();
6315
6316 ReplaceOtherWidenResults(N, WidenNode, ResNo);
6317 return SDValue(WidenNode, ResNo);
6318}
6319
6320SDValue DAGTypeLegalizer::WidenVecRes_MERGE_VALUES(SDNode *N, unsigned ResNo) {
6321 SDValue WidenVec = DisintegrateMERGE_VALUES(N, ResNo);
6322 return GetWidenedVector(WidenVec);
6323}
6324
6325SDValue DAGTypeLegalizer::WidenVecRes_ADDRSPACECAST(SDNode *N) {
6326 SDLoc DL(N);
6327 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6328 ElementCount WidenEC = WidenVT.getVectorElementCount();
6329 auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
6330
6331 // The source has the same number of elements as the result, so widen it to
6332 // match WidenVT. It only lives in the widened-vector map if it is itself
6333 // widened; otherwise pad it up to the widened element count.
6334 SDValue InOp = N->getOperand(0);
6335 EVT InVT = InOp.getValueType();
6336 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
6337 InOp = GetWidenedVector(InOp);
6338 } else {
6339 EVT InWidenVT = EVT::getVectorVT(*DAG.getContext(),
6340 InVT.getVectorElementType(), WidenEC);
6341 InOp = DAG.getInsertSubvector(DL, DAG.getPOISON(InWidenVT), InOp, 0);
6342 }
6343
6344 return DAG.getAddrSpaceCast(
6345 DL, WidenVT, InOp, AddrSpaceCastN->getSrcAddressSpace(),
6346 AddrSpaceCastN->getDestAddressSpace(), AddrSpaceCastN->getFlags());
6347}
6348
6349SDValue DAGTypeLegalizer::WidenVecRes_BITCAST(SDNode *N) {
6350 SDValue InOp = N->getOperand(0);
6351 EVT InVT = InOp.getValueType();
6352 EVT VT = N->getValueType(0);
6353 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6354 SDLoc dl(N);
6355
6356 switch (getTypeAction(InVT)) {
6358 break;
6360 report_fatal_error("Scalarization of scalable vectors is not supported.");
6362 // If the incoming type is a vector that is being promoted, then
6363 // we know that the elements are arranged differently and that we
6364 // must perform the conversion using a stack slot.
6365 if (InVT.isVector())
6366 break;
6367
6368 // If the InOp is promoted to the same size, convert it. Otherwise,
6369 // fall out of the switch and widen the promoted input.
6370 SDValue NInOp = GetPromotedInteger(InOp);
6371 EVT NInVT = NInOp.getValueType();
6372 if (WidenVT.bitsEq(NInVT)) {
6373 // For big endian targets we need to shift the input integer or the
6374 // interesting bits will end up at the wrong place.
6375 if (DAG.getDataLayout().isBigEndian()) {
6376 unsigned ShiftAmt = NInVT.getSizeInBits() - InVT.getSizeInBits();
6377 NInOp = DAG.getNode(ISD::SHL, dl, NInVT, NInOp,
6378 DAG.getShiftAmountConstant(ShiftAmt, NInVT, dl));
6379 }
6380 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NInOp);
6381 }
6382 InOp = NInOp;
6383 InVT = NInVT;
6384 break;
6385 }
6392 break;
6394 // If the InOp is widened to the same size, convert it. Otherwise, fall
6395 // out of the switch and widen the widened input.
6396 InOp = GetWidenedVector(InOp);
6397 InVT = InOp.getValueType();
6398 if (WidenVT.bitsEq(InVT))
6399 // The input widens to the same size. Convert to the widen value.
6400 return DAG.getNode(ISD::BITCAST, dl, WidenVT, InOp);
6401 break;
6402 }
6403
6404 unsigned WidenSize = WidenVT.getSizeInBits();
6405 unsigned InSize = InVT.getSizeInBits();
6406 unsigned InScalarSize = InVT.getScalarSizeInBits();
6407 // x86mmx is not an acceptable vector element type, so don't try.
6408 if (WidenSize % InScalarSize == 0 && InVT != MVT::x86mmx) {
6409 // Determine new input vector type. The new input vector type will use
6410 // the same element type (if its a vector) or use the input type as a
6411 // vector. It is the same size as the type to widen to.
6412 EVT NewInVT;
6413 unsigned NewNumParts = WidenSize / InSize;
6414 if (InVT.isVector()) {
6415 EVT InEltVT = InVT.getVectorElementType();
6416 NewInVT = EVT::getVectorVT(*DAG.getContext(), InEltVT,
6417 WidenSize / InEltVT.getSizeInBits());
6418 } else {
6419 // For big endian systems, using the promoted input scalar type
6420 // to produce the scalar_to_vector would put the desired bits into
6421 // the least significant byte(s) of the wider element zero. This
6422 // will mean that the users of the result vector are using incorrect
6423 // bits. Use the original input type instead. Although either input
6424 // type can be used on little endian systems, for consistency we
6425 // use the original type there as well.
6426 EVT OrigInVT = N->getOperand(0).getValueType();
6427 NewNumParts = WidenSize / OrigInVT.getSizeInBits();
6428 NewInVT = EVT::getVectorVT(*DAG.getContext(), OrigInVT, NewNumParts);
6429 }
6430
6431 if (TLI.isTypeLegal(NewInVT)) {
6432 SDValue NewVec;
6433 if (InVT.isVector()) {
6434 // Because the result and the input are different vector types, widening
6435 // the result could create a legal type but widening the input might
6436 // make it an illegal type that might lead to repeatedly splitting the
6437 // input and then widening it. To avoid this, we widen the input only if
6438 // it results in a legal type.
6439 if (WidenSize % InSize == 0) {
6440 SmallVector<SDValue, 16> Ops(NewNumParts, DAG.getPOISON(InVT));
6441 Ops[0] = InOp;
6442
6443 NewVec = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewInVT, Ops);
6444 } else {
6446 DAG.ExtractVectorElements(InOp, Ops);
6447 Ops.append(WidenSize / InScalarSize - Ops.size(),
6448 DAG.getPOISON(InVT.getVectorElementType()));
6449
6450 NewVec = DAG.getNode(ISD::BUILD_VECTOR, dl, NewInVT, Ops);
6451 }
6452 } else {
6453 NewVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewInVT, InOp);
6454 }
6455 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NewVec);
6456 }
6457 }
6458
6459 return CreateStackStoreLoad(InOp, WidenVT);
6460}
6461
6462SDValue DAGTypeLegalizer::WidenVecRes_LOOP_DEPENDENCE_MASK(SDNode *N) {
6463 return DAG.getNode(
6464 N->getOpcode(), SDLoc(N),
6465 TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)),
6466 N->getOperand(0), N->getOperand(1), N->getOperand(2), N->getOperand(3));
6467}
6468
6469SDValue DAGTypeLegalizer::WidenVecRes_BUILD_VECTOR(SDNode *N) {
6470 SDLoc dl(N);
6471 // Build a vector with poison for the new nodes.
6472 EVT VT = N->getValueType(0);
6473
6474 // Integer BUILD_VECTOR operands may be larger than the node's vector element
6475 // type. The POISONs need to have the same type as the existing operands.
6476 EVT EltVT = N->getOperand(0).getValueType();
6477 unsigned NumElts = VT.getVectorNumElements();
6478
6479 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6480 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6481
6482 SmallVector<SDValue, 16> NewOps(N->ops());
6483 assert(WidenNumElts >= NumElts && "Shrinking vector instead of widening!");
6484 NewOps.append(WidenNumElts - NumElts, DAG.getPOISON(EltVT));
6485
6486 return DAG.getBuildVector(WidenVT, dl, NewOps);
6487}
6488
6489SDValue DAGTypeLegalizer::WidenVecRes_CONCAT_VECTORS(SDNode *N) {
6490 EVT InVT = N->getOperand(0).getValueType();
6491 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6492 SDLoc dl(N);
6493 unsigned NumOperands = N->getNumOperands();
6494
6495 bool InputWidened = false; // Indicates we need to widen the input.
6496 if (getTypeAction(InVT) != TargetLowering::TypeWidenVector) {
6497 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6498 unsigned NumInElts = InVT.getVectorMinNumElements();
6499 if (WidenNumElts % NumInElts == 0) {
6500 // Add undef vectors to widen to correct length.
6501 unsigned NumConcat = WidenNumElts / NumInElts;
6502 SDValue UndefVal = DAG.getPOISON(InVT);
6503 SmallVector<SDValue, 16> Ops(NumConcat);
6504 for (unsigned i=0; i < NumOperands; ++i)
6505 Ops[i] = N->getOperand(i);
6506 for (unsigned i = NumOperands; i != NumConcat; ++i)
6507 Ops[i] = UndefVal;
6508 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Ops);
6509 }
6510 } else {
6511 InputWidened = true;
6512 if (WidenVT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
6513 // The inputs and the result are widen to the same value.
6514 unsigned i;
6515 for (i=1; i < NumOperands; ++i)
6516 if (!N->getOperand(i).isUndef())
6517 break;
6518
6519 if (i == NumOperands)
6520 // Everything but the first operand is an UNDEF so just return the
6521 // widened first operand.
6522 return GetWidenedVector(N->getOperand(0));
6523
6524 if (NumOperands == 2) {
6525 assert(!WidenVT.isScalableVector() &&
6526 "Cannot use vector shuffles to widen CONCAT_VECTOR result");
6527 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6528 unsigned NumInElts = InVT.getVectorNumElements();
6529
6530 // Replace concat of two operands with a shuffle.
6531 SmallVector<int, 16> MaskOps(WidenNumElts, -1);
6532 for (unsigned i = 0; i < NumInElts; ++i) {
6533 MaskOps[i] = i;
6534 MaskOps[i + NumInElts] = i + WidenNumElts;
6535 }
6536 return DAG.getVectorShuffle(WidenVT, dl,
6537 GetWidenedVector(N->getOperand(0)),
6538 GetWidenedVector(N->getOperand(1)),
6539 MaskOps);
6540 }
6541 }
6542 }
6543
6544 if (WidenVT.isScalableVector()) {
6545 SDValue WideVec = DAG.getPOISON(WidenVT);
6546 unsigned NumInElts = InVT.getVectorMinNumElements();
6547 for (unsigned I = 0; I < NumOperands; ++I)
6548 WideVec =
6549 DAG.getInsertSubvector(dl, WideVec, N->getOperand(I), I * NumInElts);
6550 return WideVec;
6551 }
6552
6553 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6554 unsigned NumInElts = InVT.getVectorNumElements();
6555
6556 // Fall back to use extracts and build vector.
6557 EVT EltVT = WidenVT.getVectorElementType();
6558 SmallVector<SDValue, 16> Ops(WidenNumElts);
6559 unsigned Idx = 0;
6560 for (unsigned i=0; i < NumOperands; ++i) {
6561 SDValue InOp = N->getOperand(i);
6562 if (InputWidened)
6563 InOp = GetWidenedVector(InOp);
6564 for (unsigned j = 0; j < NumInElts; ++j)
6565 Ops[Idx++] = DAG.getExtractVectorElt(dl, EltVT, InOp, j);
6566 }
6567 SDValue UndefVal = DAG.getPOISON(EltVT);
6568 for (; Idx < WidenNumElts; ++Idx)
6569 Ops[Idx] = UndefVal;
6570 return DAG.getBuildVector(WidenVT, dl, Ops);
6571}
6572
6573SDValue DAGTypeLegalizer::WidenVecRes_INSERT_SUBVECTOR(SDNode *N) {
6574 EVT VT = N->getValueType(0);
6575 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6576 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
6577 SDValue InOp2 = N->getOperand(1);
6578 SDValue Idx = N->getOperand(2);
6579 SDLoc dl(N);
6580 return DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WidenVT, InOp1, InOp2, Idx);
6581}
6582
6583SDValue DAGTypeLegalizer::WidenVecRes_EXTRACT_SUBVECTOR(SDNode *N) {
6584 EVT VT = N->getValueType(0);
6585 EVT EltVT = VT.getVectorElementType();
6586 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6587 SDValue InOp = N->getOperand(0);
6588 SDValue Idx = N->getOperand(1);
6589 SDLoc dl(N);
6590
6591 auto InOpTypeAction = getTypeAction(InOp.getValueType());
6592 if (InOpTypeAction == TargetLowering::TypeWidenVector)
6593 InOp = GetWidenedVector(InOp);
6594
6595 EVT InVT = InOp.getValueType();
6596
6597 // Check if we can just return the input vector after widening.
6598 uint64_t IdxVal = Idx->getAsZExtVal();
6599 if (IdxVal == 0 && InVT == WidenVT)
6600 return InOp;
6601
6602 // Check if we can extract from the vector.
6603 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6604 unsigned InNumElts = InVT.getVectorMinNumElements();
6605 unsigned VTNumElts = VT.getVectorMinNumElements();
6606 assert(IdxVal % VTNumElts == 0 &&
6607 "Expected Idx to be a multiple of subvector minimum vector length");
6608 if (IdxVal % WidenNumElts == 0 && IdxVal + WidenNumElts < InNumElts)
6609 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, WidenVT, InOp, Idx);
6610
6611 if (VT.isScalableVector()) {
6612 // Try to split the operation up into smaller extracts and concat the
6613 // results together, e.g.
6614 // nxv6i64 extract_subvector(nxv12i64, 6)
6615 // <->
6616 // nxv8i64 concat(
6617 // nxv2i64 extract_subvector(nxv16i64, 6)
6618 // nxv2i64 extract_subvector(nxv16i64, 8)
6619 // nxv2i64 extract_subvector(nxv16i64, 10)
6620 // undef)
6621 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
6622 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
6623 "down type's element count");
6624 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
6626 // Avoid recursion around e.g. nxv1i8.
6627 if (getTypeAction(PartVT) != TargetLowering::TypeWidenVector) {
6629 unsigned I = 0;
6630 for (; I < VTNumElts / GCD; ++I)
6631 Parts.push_back(
6632 DAG.getExtractSubvector(dl, PartVT, InOp, IdxVal + I * GCD));
6633 for (; I < WidenNumElts / GCD; ++I)
6634 Parts.push_back(DAG.getPOISON(PartVT));
6635
6636 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
6637 }
6638
6639 // Fallback to extracting through memory.
6640
6641 Align Alignment = DAG.getReducedAlign(InVT, /*UseABI=*/false);
6642 SDValue StackPtr = DAG.CreateStackTemporary(InVT.getStoreSize(), Alignment);
6643 MachineFunction &MF = DAG.getMachineFunction();
6644 int FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
6645 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
6646
6647 MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
6650 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
6653
6654 // Write out the input vector.
6655 SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, InOp, StackPtr, StoreMMO);
6656
6657 // Build a mask to match the length of the non-widened result.
6658 SDValue Mask =
6659 DAG.getMaskFromElementCount(dl, WidenVT, VT.getVectorElementCount());
6660
6661 // Read back the sub-vector setting the remaining lanes to poison.
6662 StackPtr = TLI.getVectorSubVecPointer(DAG, StackPtr, InVT, VT, Idx);
6663 return DAG.getMaskedLoad(
6664 WidenVT, dl, Ch, StackPtr, DAG.getPOISON(StackPtr.getValueType()), Mask,
6665 DAG.getPOISON(WidenVT), VT, LoadMMO, ISD::UNINDEXED, ISD::NON_EXTLOAD);
6666 }
6667
6668 // We could try widening the input to the right length but for now, extract
6669 // the original elements, fill the rest with undefs and build a vector.
6670 SmallVector<SDValue, 16> Ops(WidenNumElts);
6671 unsigned i;
6672 for (i = 0; i < VTNumElts; ++i)
6673 Ops[i] = DAG.getExtractVectorElt(dl, EltVT, InOp, IdxVal + i);
6674
6675 SDValue UndefVal = DAG.getPOISON(EltVT);
6676 for (; i < WidenNumElts; ++i)
6677 Ops[i] = UndefVal;
6678 return DAG.getBuildVector(WidenVT, dl, Ops);
6679}
6680
6681SDValue DAGTypeLegalizer::WidenVecRes_AssertZext(SDNode *N) {
6682 SDValue InOp = ModifyToType(
6683 N->getOperand(0),
6684 TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)), true);
6685 return DAG.getNode(ISD::AssertZext, SDLoc(N), InOp.getValueType(), InOp,
6686 N->getOperand(1));
6687}
6688
6689SDValue DAGTypeLegalizer::WidenVecRes_INSERT_VECTOR_ELT(SDNode *N) {
6690 SDValue InOp = GetWidenedVector(N->getOperand(0));
6691 return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(N),
6692 InOp.getValueType(), InOp,
6693 N->getOperand(1), N->getOperand(2));
6694}
6695
6696/// Either return the same load or provide appropriate casts
6697/// from the load and return that.
6698static SDValue coerceLoadedValue(SDValue LdOp, EVT FirstVT, EVT WidenVT,
6699 TypeSize LdWidth, TypeSize FirstVTWidth,
6700 SDLoc dl, SelectionDAG &DAG) {
6701 assert(TypeSize::isKnownLE(LdWidth, FirstVTWidth) &&
6702 "Load width must be less than or equal to first value type width");
6703 TypeSize WidenWidth = WidenVT.getSizeInBits();
6704 if (!FirstVT.isVector()) {
6705 unsigned NumElts =
6706 WidenWidth.getFixedValue() / FirstVTWidth.getFixedValue();
6707 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), FirstVT, NumElts);
6708 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT, LdOp);
6709 return DAG.getNode(ISD::BITCAST, dl, WidenVT, VecOp);
6710 }
6711 assert(FirstVT == WidenVT && "First value type must equal widen value type");
6712 return LdOp;
6713}
6714
6715/// Inverse of coerceLoadedValue: pull a FirstVT-sized scalar/vector out of the
6716/// widened value so it can be issued in a single atomic store.
6717static SDValue coerceStoredValue(SDValue StVal, EVT FirstVT, EVT WidenVT,
6718 TypeSize FirstVTWidth, const SDLoc &dl,
6719 SelectionDAG &DAG) {
6720 TypeSize WidenWidth = WidenVT.getSizeInBits();
6721 if (!FirstVT.isVector()) {
6722 unsigned NumElts =
6723 WidenWidth.getFixedValue() / FirstVTWidth.getFixedValue();
6724 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), FirstVT, NumElts);
6725 SDValue VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, StVal);
6726 return DAG.getExtractVectorElt(dl, FirstVT, VecOp, 0);
6727 }
6728 assert(FirstVT == WidenVT && "First value type must equal widen value type");
6729 return StVal;
6730}
6731
6732static std::optional<EVT> findMemType(SelectionDAG &DAG,
6733 const TargetLowering &TLI, unsigned Width,
6734 EVT WidenVT, unsigned Align,
6735 unsigned WidenEx);
6736
6737SDValue DAGTypeLegalizer::WidenVecRes_ATOMIC_LOAD(AtomicSDNode *LD) {
6738 EVT WidenVT =
6739 TLI.getTypeToTransformTo(*DAG.getContext(), LD->getValueType(0));
6740 EVT LdVT = LD->getMemoryVT();
6741 SDLoc dl(LD);
6742
6743 // Load information
6744 SDValue Chain = LD->getChain();
6745 SDValue BasePtr = LD->getBasePtr();
6746
6747 TypeSize LdWidth = LdVT.getSizeInBits();
6748 TypeSize WidenWidth = WidenVT.getSizeInBits();
6749 TypeSize WidthDiff = WidenWidth - LdWidth;
6750
6751 // Find the vector type that can load from.
6752 std::optional<EVT> FirstVT =
6753 findMemType(DAG, TLI, LdWidth.getKnownMinValue(), WidenVT, /*LdAlign=*/0,
6754 WidthDiff.getKnownMinValue());
6755
6756 if (!FirstVT)
6757 return SDValue();
6758
6759 SmallVector<EVT, 8> MemVTs;
6760 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
6761
6762 SDValue LdOp = DAG.getAtomicLoad(ISD::NON_EXTLOAD, dl, *FirstVT, *FirstVT,
6763 Chain, BasePtr, LD->getMemOperand());
6764
6765 // Load the element with one instruction.
6766 SDValue Result = coerceLoadedValue(LdOp, *FirstVT, WidenVT, LdWidth,
6767 FirstVTWidth, dl, DAG);
6768
6769 // Modified the chain - switch anything that used the old chain to use
6770 // the new one.
6771 ReplaceValueWith(SDValue(LD, 1), LdOp.getValue(1));
6772 return Result;
6773}
6774
6775SDValue DAGTypeLegalizer::WidenVecRes_LOAD(SDNode *N) {
6776 LoadSDNode *LD = cast<LoadSDNode>(N);
6777 ISD::LoadExtType ExtType = LD->getExtensionType();
6778
6779 // A vector must always be stored in memory as-is, i.e. without any padding
6780 // between the elements, since various code depend on it, e.g. in the
6781 // handling of a bitcast of a vector type to int, which may be done with a
6782 // vector store followed by an integer load. A vector that does not have
6783 // elements that are byte-sized must therefore be stored as an integer
6784 // built out of the extracted vector elements.
6785 if (!LD->getMemoryVT().isByteSized()) {
6786 SDValue Value, NewChain;
6787 std::tie(Value, NewChain) = TLI.scalarizeVectorLoad(LD, DAG);
6788 ReplaceValueWith(SDValue(LD, 0), Value);
6789 ReplaceValueWith(SDValue(LD, 1), NewChain);
6790 return SDValue();
6791 }
6792
6793 // Generate a vector-predicated load if it is custom/legal on the target. To
6794 // avoid possible recursion, only do this if the widened mask type is legal.
6795 // FIXME: Not all targets may support EVL in VP_LOAD. These will have been
6796 // removed from the IR by the ExpandVectorPredication pass but we're
6797 // reintroducing them here.
6798 EVT VT = LD->getValueType(0);
6799 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6800 EVT WideMaskVT = getSetCCResultType(WideVT);
6801
6802 if (ExtType == ISD::NON_EXTLOAD &&
6803 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WideVT) &&
6804 TLI.isTypeLegal(WideMaskVT)) {
6805 SDLoc DL(N);
6806 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
6807 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
6809 SDValue NewLoad =
6810 DAG.getLoadVP(LD->getAddressingMode(), ISD::NON_EXTLOAD, WideVT, DL,
6811 LD->getChain(), LD->getBasePtr(), LD->getOffset(), Mask,
6812 EVL, LD->getMemoryVT(), LD->getMemOperand());
6813
6814 // Modified the chain - switch anything that used the old chain to use
6815 // the new one.
6816 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6817
6818 return NewLoad;
6819 }
6820
6822 SmallVector<SDValue, 16> LdChain; // Chain for the series of load
6823 if (ExtType != ISD::NON_EXTLOAD)
6824 Result = GenWidenVectorExtLoads(LdChain, LD, ExtType);
6825 else
6826 Result = GenWidenVectorLoads(LdChain, LD);
6827
6828 if (Result) {
6829 // If we generate a single load, we can use that for the chain. Otherwise,
6830 // build a factor node to remember the multiple loads are independent and
6831 // chain to that.
6832 SDValue NewChain;
6833 if (LdChain.size() == 1)
6834 NewChain = LdChain[0];
6835 else
6836 NewChain = DAG.getNode(ISD::TokenFactor, SDLoc(LD), MVT::Other, LdChain);
6837
6838 // Modified the chain - switch anything that used the old chain to use
6839 // the new one.
6840 ReplaceValueWith(SDValue(N, 1), NewChain);
6841
6842 return Result;
6843 }
6844
6845 if (VT.isVector()) {
6846 // If all else fails replace the load with a wide masked load.
6847 SDLoc DL(N);
6848 SDValue Mask =
6849 DAG.getMaskFromElementCount(DL, WideVT, VT.getVectorElementCount());
6850
6851 SDValue NewLoad = DAG.getMaskedLoad(
6852 WideVT, DL, LD->getChain(), LD->getBasePtr(), LD->getOffset(), Mask,
6853 DAG.getPOISON(WideVT), LD->getMemoryVT(), LD->getMemOperand(),
6854 LD->getAddressingMode(), LD->getExtensionType());
6855
6856 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6857 return NewLoad;
6858 }
6859
6860 report_fatal_error("Unable to widen vector load");
6861}
6862
6863SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD(VPLoadSDNode *N) {
6864 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6865 SDValue Mask = N->getMask();
6866 SDValue EVL = N->getVectorLength();
6867 ISD::LoadExtType ExtType = N->getExtensionType();
6868 SDLoc dl(N);
6869
6870 // The mask should be widened as well
6871 assert(getTypeAction(Mask.getValueType()) ==
6873 "Unable to widen binary VP op");
6874 Mask = GetWidenedVector(Mask);
6875 assert(Mask.getValueType().getVectorElementCount() ==
6876 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
6877 .getVectorElementCount() &&
6878 "Unable to widen vector load");
6879
6880 SDValue Res =
6881 DAG.getLoadVP(N->getAddressingMode(), ExtType, WidenVT, dl, N->getChain(),
6882 N->getBasePtr(), N->getOffset(), Mask, EVL,
6883 N->getMemoryVT(), N->getMemOperand(), N->isExpandingLoad());
6884 // Legalize the chain result - switch anything that used the old chain to
6885 // use the new one.
6886 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6887 return Res;
6888}
6889
6890SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD_FF(VPLoadFFSDNode *N) {
6891 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6892 SDValue Mask = N->getMask();
6893 SDValue EVL = N->getVectorLength();
6894 SDLoc dl(N);
6895
6896 // The mask should be widened as well
6897 assert(getTypeAction(Mask.getValueType()) ==
6899 "Unable to widen binary VP op");
6900 Mask = GetWidenedVector(Mask);
6901 assert(Mask.getValueType().getVectorElementCount() ==
6902 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
6903 .getVectorElementCount() &&
6904 "Unable to widen vector load");
6905
6906 SDValue Res = DAG.getLoadFFVP(WidenVT, dl, N->getChain(), N->getBasePtr(),
6907 Mask, EVL, N->getMemOperand());
6908 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6909 ReplaceValueWith(SDValue(N, 2), Res.getValue(2));
6910 return Res;
6911}
6912
6913SDValue DAGTypeLegalizer::WidenVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode *N) {
6914 SDLoc DL(N);
6915
6916 // The mask should be widened as well
6917 SDValue Mask = N->getMask();
6918 assert(getTypeAction(Mask.getValueType()) ==
6920 "Unable to widen VP strided load");
6921 Mask = GetWidenedVector(Mask);
6922
6923 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6924 assert(Mask.getValueType().getVectorElementCount() ==
6925 WidenVT.getVectorElementCount() &&
6926 "Data and mask vectors should have the same number of elements");
6927
6928 SDValue Res = DAG.getStridedLoadVP(
6929 N->getAddressingMode(), N->getExtensionType(), WidenVT, DL, N->getChain(),
6930 N->getBasePtr(), N->getOffset(), N->getStride(), Mask,
6931 N->getVectorLength(), N->getMemoryVT(), N->getMemOperand(),
6932 N->isExpandingLoad());
6933
6934 // Legalize the chain result - switch anything that used the old chain to
6935 // use the new one.
6936 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6937 return Res;
6938}
6939
6940SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_COMPRESS(SDNode *N) {
6941 SDValue Vec = N->getOperand(0);
6942 SDValue Mask = N->getOperand(1);
6943 SDValue Passthru = N->getOperand(2);
6944 EVT WideVecVT =
6945 TLI.getTypeToTransformTo(*DAG.getContext(), Vec.getValueType());
6946 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
6947 Mask.getValueType().getVectorElementType(),
6948 WideVecVT.getVectorElementCount());
6949
6950 SDValue WideVec = ModifyToType(Vec, WideVecVT);
6951 SDValue WideMask = ModifyToType(Mask, WideMaskVT, /*FillWithZeroes=*/true);
6952 SDValue WidePassthru = ModifyToType(Passthru, WideVecVT);
6953 return DAG.getNode(ISD::VECTOR_COMPRESS, SDLoc(N), WideVecVT, WideVec,
6954 WideMask, WidePassthru);
6955}
6956
6957SDValue DAGTypeLegalizer::WidenVecRes_MLOAD(MaskedLoadSDNode *N) {
6958 EVT VT = N->getValueType(0);
6959 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6960 SDValue Mask = N->getMask();
6961 EVT MaskVT = Mask.getValueType();
6962 SDValue PassThru = GetWidenedVector(N->getPassThru());
6963 ISD::LoadExtType ExtType = N->getExtensionType();
6964 SDLoc dl(N);
6965
6966 EVT WideMaskVT =
6967 EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(),
6968 WidenVT.getVectorElementCount());
6969
6970 if (ExtType == ISD::NON_EXTLOAD && !N->isExpandingLoad() &&
6971 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WidenVT) &&
6972 TLI.isTypeLegal(WideMaskVT) &&
6973 // If there is a passthru, we shouldn't use vp.load. However,
6974 // type legalizer will struggle on masked.load with
6975 // scalable vectors, so for scalable vectors, we still use vp.load
6976 // but manually merge the load result with the passthru using vp.select.
6977 (N->getPassThru()->isUndef() || VT.isScalableVector())) {
6978 Mask = DAG.getInsertSubvector(dl, DAG.getPOISON(WideMaskVT), Mask, 0);
6979 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
6981 SDValue NewLoad =
6982 DAG.getLoadVP(N->getAddressingMode(), ISD::NON_EXTLOAD, WidenVT, dl,
6983 N->getChain(), N->getBasePtr(), N->getOffset(), Mask, EVL,
6984 N->getMemoryVT(), N->getMemOperand());
6985 SDValue NewVal = NewLoad;
6986
6987 // Manually merge with vselect
6988 if (!N->getPassThru()->isUndef()) {
6989 assert(WidenVT.isScalableVector());
6990 NewVal = DAG.getNode(ISD::VSELECT, dl, WidenVT, Mask, NewVal, PassThru);
6991 // The lanes past EVL are poison.
6992 NewVal = DAG.getNode(ISD::VP_MERGE, dl, WidenVT,
6993 DAG.getAllOnesConstant(dl, WideMaskVT), NewVal,
6994 DAG.getPOISON(WidenVT), EVL);
6995 }
6996
6997 // Modified the chain - switch anything that used the old chain to use
6998 // the new one.
6999 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
7000
7001 return NewVal;
7002 }
7003
7004 // The mask should be widened as well
7005 Mask = ModifyToType(Mask, WideMaskVT, true);
7006
7007 SDValue Res = DAG.getMaskedLoad(
7008 WidenVT, dl, N->getChain(), N->getBasePtr(), N->getOffset(), Mask,
7009 PassThru, N->getMemoryVT(), N->getMemOperand(), N->getAddressingMode(),
7010 ExtType, N->isExpandingLoad());
7011 // Legalize the chain result - switch anything that used the old chain to
7012 // use the new one.
7013 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7014 return Res;
7015}
7016
7017SDValue DAGTypeLegalizer::WidenVecRes_MGATHER(MaskedGatherSDNode *N) {
7018
7019 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7020 SDValue Mask = N->getMask();
7021 EVT MaskVT = Mask.getValueType();
7022 SDValue PassThru = GetWidenedVector(N->getPassThru());
7023 SDValue Scale = N->getScale();
7024 ElementCount WideEC = WideVT.getVectorElementCount();
7025 SDLoc dl(N);
7026
7027 // The mask should be widened as well
7028 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
7029 MaskVT.getVectorElementType(), WideEC);
7030 Mask = ModifyToType(Mask, WideMaskVT, true);
7031
7032 // Widen the Index operand
7033 SDValue Index = N->getIndex();
7034 EVT WideIndexVT = EVT::getVectorVT(
7035 *DAG.getContext(), Index.getValueType().getScalarType(), WideEC);
7036 Index = ModifyToType(Index, WideIndexVT);
7037 SDValue Ops[] = { N->getChain(), PassThru, Mask, N->getBasePtr(), Index,
7038 Scale };
7039
7040 // Widen the MemoryType
7041 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
7042 N->getMemoryVT().getScalarType(), WideEC);
7043 SDValue Res = DAG.getMaskedGather(DAG.getVTList(WideVT, MVT::Other),
7044 WideMemVT, dl, Ops, N->getMemOperand(),
7045 N->getIndexType(), N->getExtensionType());
7046
7047 // Legalize the chain result - switch anything that used the old chain to
7048 // use the new one.
7049 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7050 return Res;
7051}
7052
7053SDValue DAGTypeLegalizer::WidenVecRes_VP_GATHER(VPGatherSDNode *N) {
7054 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7055 SDValue Mask = N->getMask();
7056 SDValue Scale = N->getScale();
7057 ElementCount WideEC = WideVT.getVectorElementCount();
7058 SDLoc dl(N);
7059
7060 SDValue Index = GetWidenedVector(N->getIndex());
7061 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
7062 N->getMemoryVT().getScalarType(), WideEC);
7063 Mask = GetWidenedMask(Mask, WideEC);
7064
7065 SDValue Ops[] = {N->getChain(), N->getBasePtr(), Index, Scale,
7066 Mask, N->getVectorLength()};
7067 SDValue Res = DAG.getGatherVP(DAG.getVTList(WideVT, MVT::Other), WideMemVT,
7068 dl, Ops, N->getMemOperand(), N->getIndexType());
7069
7070 // Legalize the chain result - switch anything that used the old chain to
7071 // use the new one.
7072 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7073 return Res;
7074}
7075
7076SDValue DAGTypeLegalizer::WidenVecRes_ScalarOp(SDNode *N) {
7077 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7078 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, N->getOperand(0));
7079}
7080
7081// Return true is this is a SETCC node or a strict version of it.
7082static inline bool isSETCCOp(unsigned Opcode) {
7083 switch (Opcode) {
7084 case ISD::SETCC:
7085 case ISD::STRICT_FSETCC:
7087 return true;
7088 }
7089 return false;
7090}
7091
7092// Return true if this is a node that could have two SETCCs as operands.
7093static inline bool isLogicalMaskOp(unsigned Opcode) {
7094 switch (Opcode) {
7095 case ISD::AND:
7096 case ISD::OR:
7097 case ISD::XOR:
7098 return true;
7099 }
7100 return false;
7101}
7102
7103// If N is a SETCC or a strict variant of it, return the type
7104// of the compare operands.
7106 unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
7107 return N->getOperand(OpNo).getValueType();
7108}
7109
7110// This is used just for the assert in convertMask(). Check that this either
7111// a SETCC or a previously handled SETCC by convertMask().
7112#ifndef NDEBUG
7113static inline bool isSETCCorConvertedSETCC(SDValue N) {
7114 if (N.getOpcode() == ISD::EXTRACT_SUBVECTOR)
7115 N = N.getOperand(0);
7116 else if (N.getOpcode() == ISD::CONCAT_VECTORS) {
7117 for (unsigned i = 1; i < N->getNumOperands(); ++i)
7118 if (!N->getOperand(i)->isUndef())
7119 return false;
7120 N = N.getOperand(0);
7121 }
7122
7123 if (N.getOpcode() == ISD::TRUNCATE)
7124 N = N.getOperand(0);
7125 else if (N.getOpcode() == ISD::SIGN_EXTEND)
7126 N = N.getOperand(0);
7127
7128 if (isLogicalMaskOp(N.getOpcode()))
7129 return isSETCCorConvertedSETCC(N.getOperand(0)) &&
7130 isSETCCorConvertedSETCC(N.getOperand(1));
7131
7132 return (isSETCCOp(N.getOpcode()) ||
7134}
7135#endif
7136
7137// Return a mask of vector type MaskVT to replace InMask. Also adjust MaskVT
7138// to ToMaskVT if needed with vector extension or truncation.
7139SDValue DAGTypeLegalizer::convertMask(SDValue InMask, EVT MaskVT,
7140 EVT ToMaskVT) {
7141 // Currently a SETCC or a AND/OR/XOR with two SETCCs are handled.
7142 // FIXME: This code seems to be too restrictive, we might consider
7143 // generalizing it or dropping it.
7144 assert(isSETCCorConvertedSETCC(InMask) && "Unexpected mask argument.");
7145
7146 // Make a new Mask node, with a legal result VT.
7147 SDValue Mask;
7149 for (unsigned i = 0, e = InMask->getNumOperands(); i < e; ++i)
7150 Ops.push_back(InMask->getOperand(i));
7151 if (InMask->isStrictFPOpcode()) {
7152 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask),
7153 { MaskVT, MVT::Other }, Ops);
7154 ReplaceValueWith(InMask.getValue(1), Mask.getValue(1));
7155 }
7156 else
7157 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask), MaskVT, Ops,
7158 InMask->getFlags());
7159
7160 // If MaskVT has smaller or bigger elements than ToMaskVT, a vector sign
7161 // extend or truncate is needed.
7162 LLVMContext &Ctx = *DAG.getContext();
7163 unsigned MaskScalarBits = MaskVT.getScalarSizeInBits();
7164 unsigned ToMaskScalBits = ToMaskVT.getScalarSizeInBits();
7165 if (MaskScalarBits < ToMaskScalBits) {
7166 EVT ExtVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
7167 MaskVT.getVectorNumElements());
7168 Mask = DAG.getNode(ISD::SIGN_EXTEND, SDLoc(Mask), ExtVT, Mask);
7169 } else if (MaskScalarBits > ToMaskScalBits) {
7170 EVT TruncVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
7171 MaskVT.getVectorNumElements());
7172 Mask = DAG.getNode(ISD::TRUNCATE, SDLoc(Mask), TruncVT, Mask);
7173 }
7174
7175 assert(Mask->getValueType(0).getScalarSizeInBits() ==
7176 ToMaskVT.getScalarSizeInBits() &&
7177 "Mask should have the right element size by now.");
7178
7179 // Adjust Mask to the right number of elements.
7180 unsigned CurrMaskNumEls = Mask->getValueType(0).getVectorNumElements();
7181 if (CurrMaskNumEls > ToMaskVT.getVectorNumElements()) {
7182 Mask = DAG.getExtractSubvector(SDLoc(Mask), ToMaskVT, Mask, 0);
7183 } else if (CurrMaskNumEls < ToMaskVT.getVectorNumElements()) {
7184 unsigned NumSubVecs = (ToMaskVT.getVectorNumElements() / CurrMaskNumEls);
7185 EVT SubVT = Mask->getValueType(0);
7186 SmallVector<SDValue, 16> SubOps(NumSubVecs, DAG.getPOISON(SubVT));
7187 SubOps[0] = Mask;
7188 Mask = DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Mask), ToMaskVT, SubOps);
7189 }
7190
7191 assert((Mask->getValueType(0) == ToMaskVT) &&
7192 "A mask of ToMaskVT should have been produced by now.");
7193
7194 return Mask;
7195}
7196
7197// This method tries to handle some special cases for the vselect mask
7198// and if needed adjusting the mask vector type to match that of the VSELECT.
7199// Without it, many cases end up with scalarization of the SETCC, with many
7200// unnecessary instructions.
7201SDValue DAGTypeLegalizer::WidenVSELECTMask(SDNode *N) {
7202 LLVMContext &Ctx = *DAG.getContext();
7203 SDValue Cond = N->getOperand(0);
7204
7205 if (N->getOpcode() != ISD::VSELECT)
7206 return SDValue();
7207
7208 if (!isSETCCOp(Cond->getOpcode()) && !isLogicalMaskOp(Cond->getOpcode()))
7209 return SDValue();
7210
7211 // If this is a splitted VSELECT that was previously already handled, do
7212 // nothing.
7213 EVT CondVT = Cond->getValueType(0);
7214 if (CondVT.getScalarSizeInBits() != 1)
7215 return SDValue();
7216
7217 EVT VSelVT = N->getValueType(0);
7218
7219 // This method can't handle scalable vector types.
7220 // FIXME: This support could be added in the future.
7221 if (VSelVT.isScalableVector())
7222 return SDValue();
7223
7224 // Only handle vector types which are a power of 2.
7225 if (!isPowerOf2_64(VSelVT.getSizeInBits()))
7226 return SDValue();
7227
7228 // Don't touch if this will be scalarized.
7229 EVT FinalVT = VSelVT;
7230 while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
7231 FinalVT = FinalVT.getHalfNumVectorElementsVT(Ctx);
7232
7233 if (FinalVT.getVectorNumElements() == 1)
7234 return SDValue();
7235
7236 // If there is support for an i1 vector mask, don't touch.
7237 if (isSETCCOp(Cond.getOpcode())) {
7238 EVT SetCCOpVT = getSETCCOperandType(Cond);
7239 while (TLI.getTypeAction(Ctx, SetCCOpVT) != TargetLowering::TypeLegal)
7240 SetCCOpVT = TLI.getTypeToTransformTo(Ctx, SetCCOpVT);
7241 EVT SetCCResVT = getSetCCResultType(SetCCOpVT);
7242 if (SetCCResVT.getScalarSizeInBits() == 1)
7243 return SDValue();
7244 } else if (CondVT.getScalarType() == MVT::i1) {
7245 // If there is support for an i1 vector mask (or only scalar i1 conditions),
7246 // don't touch.
7247 while (TLI.getTypeAction(Ctx, CondVT) != TargetLowering::TypeLegal)
7248 CondVT = TLI.getTypeToTransformTo(Ctx, CondVT);
7249
7250 if (CondVT.getScalarType() == MVT::i1)
7251 return SDValue();
7252 }
7253
7254 // Widen the vselect result type if needed.
7255 if (getTypeAction(VSelVT) == TargetLowering::TypeWidenVector)
7256 VSelVT = TLI.getTypeToTransformTo(Ctx, VSelVT);
7257
7258 // The mask of the VSELECT should have integer elements.
7259 EVT ToMaskVT = VSelVT;
7260 if (!ToMaskVT.getScalarType().isInteger())
7261 ToMaskVT = ToMaskVT.changeVectorElementTypeToInteger();
7262
7263 SDValue Mask;
7264 if (isSETCCOp(Cond->getOpcode())) {
7265 EVT MaskVT = getSetCCResultType(getSETCCOperandType(Cond));
7266 Mask = convertMask(Cond, MaskVT, ToMaskVT);
7267 } else if (isLogicalMaskOp(Cond->getOpcode()) &&
7268 isSETCCOp(Cond->getOperand(0).getOpcode()) &&
7269 isSETCCOp(Cond->getOperand(1).getOpcode())) {
7270 // Cond is (AND/OR/XOR (SETCC, SETCC))
7271 SDValue SETCC0 = Cond->getOperand(0);
7272 SDValue SETCC1 = Cond->getOperand(1);
7273 EVT VT0 = getSetCCResultType(getSETCCOperandType(SETCC0));
7274 EVT VT1 = getSetCCResultType(getSETCCOperandType(SETCC1));
7275 unsigned ScalarBits0 = VT0.getScalarSizeInBits();
7276 unsigned ScalarBits1 = VT1.getScalarSizeInBits();
7277 unsigned ScalarBits_ToMask = ToMaskVT.getScalarSizeInBits();
7278 EVT MaskVT;
7279 // If the two SETCCs have different VTs, either extend/truncate one of
7280 // them to the other "towards" ToMaskVT, or truncate one and extend the
7281 // other to ToMaskVT.
7282 if (ScalarBits0 != ScalarBits1) {
7283 EVT NarrowVT = ((ScalarBits0 < ScalarBits1) ? VT0 : VT1);
7284 EVT WideVT = ((NarrowVT == VT0) ? VT1 : VT0);
7285 if (ScalarBits_ToMask >= WideVT.getScalarSizeInBits())
7286 MaskVT = WideVT;
7287 else if (ScalarBits_ToMask <= NarrowVT.getScalarSizeInBits())
7288 MaskVT = NarrowVT;
7289 else
7290 MaskVT = ToMaskVT;
7291 } else
7292 // If the two SETCCs have the same VT, don't change it.
7293 MaskVT = VT0;
7294
7295 // Make new SETCCs and logical nodes.
7296 SETCC0 = convertMask(SETCC0, VT0, MaskVT);
7297 SETCC1 = convertMask(SETCC1, VT1, MaskVT);
7298 Cond = DAG.getNode(Cond->getOpcode(), SDLoc(Cond), MaskVT, SETCC0, SETCC1);
7299
7300 // Convert the logical op for VSELECT if needed.
7301 Mask = convertMask(Cond, MaskVT, ToMaskVT);
7302 } else
7303 return SDValue();
7304
7305 return Mask;
7306}
7307
7308SDValue DAGTypeLegalizer::WidenVecRes_Select(SDNode *N) {
7309 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7310 ElementCount WidenEC = WidenVT.getVectorElementCount();
7311
7312 SDValue Cond1 = N->getOperand(0);
7313 EVT CondVT = Cond1.getValueType();
7314 unsigned Opcode = N->getOpcode();
7315 if (CondVT.isVector()) {
7316 if (SDValue WideCond = WidenVSELECTMask(N)) {
7317 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
7318 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
7319 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
7320 return DAG.getNode(Opcode, SDLoc(N), WidenVT, WideCond, InOp1, InOp2);
7321 }
7322
7323 EVT CondEltVT = CondVT.getVectorElementType();
7324 EVT CondWidenVT = EVT::getVectorVT(*DAG.getContext(), CondEltVT, WidenEC);
7325 if (getTypeAction(CondVT) == TargetLowering::TypeWidenVector)
7326 Cond1 = GetWidenedVector(Cond1);
7327
7328 // If we have to split the condition there is no point in widening the
7329 // select. This would result in an cycle of widening the select ->
7330 // widening the condition operand -> splitting the condition operand ->
7331 // splitting the select -> widening the select. Instead split this select
7332 // further and widen the resulting type.
7333 if (getTypeAction(CondVT) == TargetLowering::TypeSplitVector) {
7334 SDValue SplitSelect = SplitVecOp_VSELECT(N, 0);
7335 SDValue Res = ModifyToType(SplitSelect, WidenVT);
7336 return Res;
7337 }
7338
7339 if (Cond1.getValueType() != CondWidenVT)
7340 Cond1 = ModifyToType(Cond1, CondWidenVT);
7341 }
7342
7343 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
7344 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
7345 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
7346 if (Opcode == ISD::VP_MERGE)
7347 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2,
7348 N->getOperand(3));
7349 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2);
7350}
7351
7352SDValue DAGTypeLegalizer::WidenVecRes_SELECT_CC(SDNode *N) {
7353 SDValue InOp1 = GetWidenedVector(N->getOperand(2));
7354 SDValue InOp2 = GetWidenedVector(N->getOperand(3));
7355 return DAG.getNode(ISD::SELECT_CC, SDLoc(N),
7356 InOp1.getValueType(), N->getOperand(0),
7357 N->getOperand(1), InOp1, InOp2, N->getOperand(4));
7358}
7359
7360SDValue DAGTypeLegalizer::WidenVecRes_UNDEF(SDNode *N) {
7361 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7362 return DAG.getUNDEF(WidenVT);
7363}
7364
7365SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N) {
7366 EVT VT = N->getValueType(0);
7367 SDLoc dl(N);
7368
7369 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7370 unsigned NumElts = VT.getVectorNumElements();
7371 unsigned WidenNumElts = WidenVT.getVectorNumElements();
7372
7373 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
7374 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
7375
7376 // Adjust mask based on new input vector length.
7377 SmallVector<int, 16> NewMask(WidenNumElts, -1);
7378 for (unsigned i = 0; i != NumElts; ++i) {
7379 int Idx = N->getMaskElt(i);
7380 if (Idx < (int)NumElts)
7381 NewMask[i] = Idx;
7382 else
7383 NewMask[i] = Idx - NumElts + WidenNumElts;
7384 }
7385 return DAG.getVectorShuffle(WidenVT, dl, InOp1, InOp2, NewMask);
7386}
7387
7388SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_REVERSE(SDNode *N) {
7389 EVT VT = N->getValueType(0);
7390 EVT EltVT = VT.getVectorElementType();
7391 SDLoc dl(N);
7392
7393 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7394 SDValue OpValue = GetWidenedVector(N->getOperand(0));
7395 assert(WidenVT == OpValue.getValueType() && "Unexpected widened vector type");
7396
7397 SDValue ReverseVal = DAG.getNode(ISD::VECTOR_REVERSE, dl, WidenVT, OpValue);
7398 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
7399 unsigned VTNumElts = VT.getVectorMinNumElements();
7400 unsigned IdxVal = WidenNumElts - VTNumElts;
7401
7402 if (VT.isScalableVector()) {
7403 // Try to split the 'Widen ReverseVal' into smaller extracts and concat the
7404 // results together, e.g.(nxv6i64 -> nxv8i64)
7405 // nxv8i64 vector_reverse
7406 // <->
7407 // nxv8i64 concat(
7408 // nxv2i64 extract_subvector(nxv8i64, 2)
7409 // nxv2i64 extract_subvector(nxv8i64, 4)
7410 // nxv2i64 extract_subvector(nxv8i64, 6)
7411 // nxv2i64 undef)
7412
7413 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
7414 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
7416 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
7417 "down type's element count");
7419 unsigned i = 0;
7420 for (; i < VTNumElts / GCD; ++i)
7421 Parts.push_back(
7422 DAG.getExtractSubvector(dl, PartVT, ReverseVal, IdxVal + i * GCD));
7423 for (; i < WidenNumElts / GCD; ++i)
7424 Parts.push_back(DAG.getPOISON(PartVT));
7425
7426 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
7427 }
7428
7429 // Use VECTOR_SHUFFLE to combine new vector from 'ReverseVal' for
7430 // fixed-vectors.
7431 SmallVector<int, 16> Mask(WidenNumElts, -1);
7432 std::iota(Mask.begin(), Mask.begin() + VTNumElts, IdxVal);
7433
7434 return DAG.getVectorShuffle(WidenVT, dl, ReverseVal, DAG.getPOISON(WidenVT),
7435 Mask);
7436}
7437
7438SDValue DAGTypeLegalizer::WidenVecRes_GET_ACTIVE_LANE_MASK(SDNode *N) {
7439 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7440 return DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, SDLoc(N), NVT, N->ops());
7441}
7442
7443void DAGTypeLegalizer::WidenVecRes_VECTOR_INTERLEAVE(SDNode *N) {
7444 EVT VT = N->getValueType(0);
7445 EVT EltVT = VT.getVectorElementType();
7446 ElementCount OrigEC = VT.getVectorElementCount();
7447 unsigned Factor = N->getNumOperands();
7448 SDLoc DL(N);
7449
7450 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7451 ElementCount WidenEC = WidenVT.getVectorElementCount();
7452
7453 SmallVector<SDValue, 8> WidenOps(Factor);
7454 for (unsigned Idx = 0U; Idx < Factor; ++Idx)
7455 WidenOps[Idx] = GetWidenedVector(N->getOperand(Idx));
7456
7457 SmallVector<EVT, 8> WidenVTs(Factor, WidenVT);
7458 SDValue Interleaved =
7459 DAG.getNode(ISD::VECTOR_INTERLEAVE, DL, WidenVTs, WidenOps);
7460
7461 EVT PackedWidenVT =
7462 EVT::getVectorVT(*DAG.getContext(), EltVT, WidenEC * Factor);
7463 SmallVector<SDValue, 8> Slices(Factor);
7464 for (unsigned Idx = 0; Idx != Factor; ++Idx)
7465 Slices[Idx] = Interleaved.getValue(Idx);
7466
7467 SDValue Packed = DAG.getNode(ISD::CONCAT_VECTORS, DL, PackedWidenVT, Slices);
7468
7469 for (unsigned Idx = 0U; Idx < Factor; ++Idx) {
7470 SDValue Narrow = DAG.getExtractSubvector(DL, VT, Packed,
7471 OrigEC.getKnownMinValue() * Idx);
7472 SDValue Wide =
7473 DAG.getInsertSubvector(DL, DAG.getPOISON(WidenVT), Narrow, /*Idx=*/0U);
7474 SetWidenedVector(SDValue(N, Idx), Wide);
7475 }
7476}
7477
7478SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_MATCH(SDNode *N) {
7479 SDLoc DL(N);
7480 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7481 EVT SourceVT = N->getOperand(0).getValueType();
7482 EVT WideSourceVT =
7483 EVT::getVectorVT(*DAG.getContext(), SourceVT.getVectorElementType(),
7484 WidenVT.getVectorElementCount());
7485
7486 SDValue WideSource = DAG.getInsertSubvector(DL, DAG.getUNDEF(WideSourceVT),
7487 N->getOperand(0), 0);
7488 SDValue WideMask = DAG.getInsertSubvector(DL, DAG.getConstant(0, DL, WidenVT),
7489 N->getOperand(2), 0);
7490 return DAG.getNode(ISD::VECTOR_MATCH, DL, WidenVT, WideSource,
7491 N->getOperand(1), WideMask, N->getFlags());
7492}
7493
7494void DAGTypeLegalizer::WidenVecRes_VECTOR_DEINTERLEAVE(SDNode *N) {
7495 EVT VT = N->getValueType(0);
7496 EVT EltVT = VT.getVectorElementType();
7497 ElementCount OrigEC = VT.getVectorElementCount();
7498 unsigned Factor = N->getNumOperands();
7499 SDLoc DL(N);
7500
7501 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7502 ElementCount WidenEC = WidenVT.getVectorElementCount();
7503 // We cannot just use the widened operands directly: since they might be
7504 // individually widened, using them directly will result in de-interleaving
7505 // the "padded" lanes that sit in the middle of the vector. Instead, we should
7506 // not concat the widened operands but the original ones to effectively
7507 // generate a "packed" concated and widened vector, before extracting new
7508 // operand vectors with the widened type.
7509 EVT PackedWidenVT =
7510 EVT::getVectorVT(*DAG.getContext(), EltVT, WidenEC * Factor);
7511 EVT ConcatVT = EVT::getVectorVT(*DAG.getContext(), EltVT, OrigEC * Factor);
7512 SDValue ConcatOp = DAG.getNode(ISD::CONCAT_VECTORS, DL, ConcatVT, N->ops());
7513 SDValue PackedWidenVec = DAG.getInsertSubvector(
7514 DL, DAG.getUNDEF(PackedWidenVT), ConcatOp, /*Idx=*/0U);
7515
7516 // Extract the new widened operand vectors.
7517 SmallVector<SDValue, 8> NewOps(Factor, SDValue());
7518 for (unsigned Idx = 0U; Idx < Factor; ++Idx) {
7519 NewOps[Idx] = DAG.getExtractSubvector(DL, WidenVT, PackedWidenVec,
7520 WidenEC.getKnownMinValue() * Idx);
7521 }
7522
7523 SmallVector<EVT, 8> NewVTs(Factor, WidenVT);
7524 SDValue NewRes = DAG.getNode(ISD::VECTOR_DEINTERLEAVE, DL, NewVTs, NewOps);
7525 // Set the widened results manually.
7526 for (unsigned Idx = 0U; Idx < Factor; ++Idx)
7527 SetWidenedVector(SDValue(N, Idx), NewRes.getValue(Idx));
7528}
7529
7530SDValue DAGTypeLegalizer::WidenVecRes_SETCC(SDNode *N) {
7531 assert(N->getValueType(0).isVector() &&
7532 N->getOperand(0).getValueType().isVector() &&
7533 "Operands must be vectors");
7534 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7535 ElementCount WidenEC = WidenVT.getVectorElementCount();
7536
7537 SDValue InOp1 = N->getOperand(0);
7538 EVT InVT = InOp1.getValueType();
7539 assert(InVT.isVector() && "can not widen non-vector type");
7540 EVT WidenInVT =
7541 EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), WidenEC);
7542
7543 // The input and output types often differ here, and it could be that while
7544 // we'd prefer to widen the result type, the input operands have been split.
7545 // In this case, we also need to split the result of this node as well.
7546 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector) {
7547 SDValue SplitVSetCC = SplitVecOp_VSETCC(N);
7548 SDValue Res = ModifyToType(SplitVSetCC, WidenVT);
7549 return Res;
7550 }
7551
7552 // If the inputs also widen, handle them directly. Otherwise widen by hand.
7553 SDValue InOp2 = N->getOperand(1);
7554 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
7555 InOp1 = GetWidenedVector(InOp1);
7556 InOp2 = GetWidenedVector(InOp2);
7557 } else {
7558 SDValue Poison = DAG.getPOISON(WidenInVT);
7559 SDValue ZeroIdx = DAG.getVectorIdxConstant(0, SDLoc(N));
7560 InOp1 = DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), WidenInVT, Poison,
7561 InOp1, ZeroIdx);
7562 InOp2 = DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), WidenInVT, Poison,
7563 InOp2, ZeroIdx);
7564 }
7565
7566 // Assume that the input and output will be widen appropriately. If not,
7567 // we will have to unroll it at some point.
7568 assert(InOp1.getValueType() == WidenInVT &&
7569 InOp2.getValueType() == WidenInVT &&
7570 "Input not widened to expected type!");
7571 (void)WidenInVT;
7572 return DAG.getNode(ISD::SETCC, SDLoc(N), WidenVT, InOp1, InOp2,
7573 N->getOperand(2));
7574}
7575
7576SDValue DAGTypeLegalizer::WidenVecRes_STRICT_FSETCC(SDNode *N) {
7577 assert(N->getValueType(0).isVector() &&
7578 N->getOperand(1).getValueType().isVector() &&
7579 "Operands must be vectors");
7580 EVT VT = N->getValueType(0);
7581 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7582 unsigned WidenNumElts = WidenVT.getVectorNumElements();
7583 unsigned NumElts = VT.getVectorNumElements();
7584 EVT EltVT = VT.getVectorElementType();
7585
7586 SDLoc dl(N);
7587 SDValue Chain = N->getOperand(0);
7588 SDValue LHS = N->getOperand(1);
7589 SDValue RHS = N->getOperand(2);
7590 SDValue CC = N->getOperand(3);
7591 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
7592
7593 // Fully unroll and reassemble.
7594 SmallVector<SDValue, 8> Scalars(WidenNumElts, DAG.getPOISON(EltVT));
7595 SmallVector<SDValue, 8> Chains(NumElts);
7596 for (unsigned i = 0; i != NumElts; ++i) {
7597 SDValue LHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, LHS, i);
7598 SDValue RHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, RHS, i);
7599
7600 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
7601 {Chain, LHSElem, RHSElem, CC});
7602 Chains[i] = Scalars[i].getValue(1);
7603 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
7604 DAG.getBoolConstant(true, dl, EltVT, VT),
7605 DAG.getBoolConstant(false, dl, EltVT, VT));
7606 }
7607
7608 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
7609 ReplaceValueWith(SDValue(N, 1), NewChain);
7610
7611 return DAG.getBuildVector(WidenVT, dl, Scalars);
7612}
7613
7614SDValue DAGTypeLegalizer::WidenVecRes_PARTIAL_REDUCE_MLA(SDNode *N) {
7615 SDLoc DL(N);
7616 EVT VT = N->getValueType(0);
7617
7618 // Expand, then widen the result.
7619 SDValue Expanded = TLI.expandPartialReduceMLA(N, DAG);
7620 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7621 return DAG.getInsertSubvector(DL, DAG.getPOISON(WideVT), Expanded, 0);
7622}
7623
7624//===----------------------------------------------------------------------===//
7625// Widen Vector Operand
7626//===----------------------------------------------------------------------===//
7627bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned OpNo) {
7628 LLVM_DEBUG(dbgs() << "Widen node operand " << OpNo << ": "; N->dump(&DAG));
7629 SDValue Res = SDValue();
7630
7631 // See if the target wants to custom widen this node.
7632 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
7633 return false;
7634
7635 switch (N->getOpcode()) {
7636 default:
7637#ifndef NDEBUG
7638 dbgs() << "WidenVectorOperand op #" << OpNo << ": ";
7639 N->dump(&DAG);
7640 dbgs() << "\n";
7641#endif
7642 report_fatal_error("Do not know how to widen this operator's operand!");
7643
7644 case ISD::BITCAST: Res = WidenVecOp_BITCAST(N); break;
7645 case ISD::FAKE_USE:
7646 Res = WidenVecOp_FAKE_USE(N);
7647 break;
7648 case ISD::CONCAT_VECTORS: Res = WidenVecOp_CONCAT_VECTORS(N); break;
7649 case ISD::INSERT_SUBVECTOR: Res = WidenVecOp_INSERT_SUBVECTOR(N); break;
7650 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecOp_EXTRACT_SUBVECTOR(N); break;
7651 case ISD::EXTRACT_VECTOR_ELT: Res = WidenVecOp_EXTRACT_VECTOR_ELT(N); break;
7652 case ISD::STORE: Res = WidenVecOp_STORE(N); break;
7653 case ISD::ATOMIC_STORE:
7654 Res = WidenVecOp_ATOMIC_STORE(cast<AtomicSDNode>(N));
7655 break;
7656 case ISD::VP_STORE: Res = WidenVecOp_VP_STORE(N, OpNo); break;
7657 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
7658 Res = WidenVecOp_VP_STRIDED_STORE(N, OpNo);
7659 break;
7663 Res = WidenVecOp_EXTEND_VECTOR_INREG(N);
7664 break;
7665 case ISD::MSTORE: Res = WidenVecOp_MSTORE(N, OpNo); break;
7666 case ISD::MGATHER: Res = WidenVecOp_MGATHER(N, OpNo); break;
7667 case ISD::MSCATTER: Res = WidenVecOp_MSCATTER(N, OpNo); break;
7668 case ISD::VP_SCATTER: Res = WidenVecOp_VP_SCATTER(N, OpNo); break;
7669 case ISD::SETCC: Res = WidenVecOp_SETCC(N); break;
7670 case ISD::STRICT_FSETCC:
7671 case ISD::STRICT_FSETCCS: Res = WidenVecOp_STRICT_FSETCC(N); break;
7672 case ISD::VSELECT: Res = WidenVecOp_VSELECT(N); break;
7673 case ISD::FLDEXP:
7674 case ISD::FCOPYSIGN:
7675 case ISD::LROUND:
7676 case ISD::LLROUND:
7677 case ISD::LRINT:
7678 case ISD::LLRINT:
7679 Res = WidenVecOp_UnrollVectorOp(N);
7680 break;
7681 case ISD::IS_FPCLASS: Res = WidenVecOp_IS_FPCLASS(N); break;
7682
7683 case ISD::ANY_EXTEND:
7684 case ISD::SIGN_EXTEND:
7685 case ISD::ZERO_EXTEND:
7686 Res = WidenVecOp_EXTEND(N);
7687 break;
7688
7689 case ISD::SCMP:
7690 case ISD::UCMP:
7691 Res = WidenVecOp_CMP(N);
7692 break;
7693
7694 case ISD::FP_EXTEND:
7696 case ISD::FP_ROUND:
7698 case ISD::FP_TO_SINT:
7700 case ISD::FP_TO_UINT:
7702 case ISD::SINT_TO_FP:
7704 case ISD::UINT_TO_FP:
7706 case ISD::TRUNCATE:
7709 Res = WidenVecOp_Convert(N);
7710 break;
7711
7714 Res = WidenVecOp_FP_TO_XINT_SAT(N);
7715 break;
7716
7719 case ISD::VECREDUCE_ADD:
7720 case ISD::VECREDUCE_MUL:
7721 case ISD::VECREDUCE_AND:
7722 case ISD::VECREDUCE_OR:
7723 case ISD::VECREDUCE_XOR:
7734 Res = WidenVecOp_VECREDUCE(N);
7735 break;
7738 Res = WidenVecOp_VECREDUCE_SEQ(N);
7739 break;
7740 case ISD::VP_REDUCE_FADD:
7741 case ISD::VP_REDUCE_SEQ_FADD:
7742 case ISD::VP_REDUCE_FMUL:
7743 case ISD::VP_REDUCE_SEQ_FMUL:
7744 case ISD::VP_REDUCE_ADD:
7745 case ISD::VP_REDUCE_MUL:
7746 case ISD::VP_REDUCE_AND:
7747 case ISD::VP_REDUCE_OR:
7748 case ISD::VP_REDUCE_XOR:
7749 case ISD::VP_REDUCE_SMAX:
7750 case ISD::VP_REDUCE_SMIN:
7751 case ISD::VP_REDUCE_UMAX:
7752 case ISD::VP_REDUCE_UMIN:
7753 case ISD::VP_REDUCE_FMAX:
7754 case ISD::VP_REDUCE_FMIN:
7755 case ISD::VP_REDUCE_FMAXIMUM:
7756 case ISD::VP_REDUCE_FMINIMUM:
7757 Res = WidenVecOp_VP_REDUCE(N);
7758 break;
7759 case ISD::CTTZ_ELTS:
7761 Res = WidenVecOp_CttzElements(N);
7762 break;
7763 case ISD::VP_CTTZ_ELTS:
7764 case ISD::VP_CTTZ_ELTS_ZERO_POISON:
7765 Res = WidenVecOp_VP_CttzElements(N);
7766 break;
7768 Res = WidenVecOp_VECTOR_FIND_LAST_ACTIVE(N);
7769 break;
7770 case ISD::VECTOR_MATCH:
7771 Res = WidenVecOp_VECTOR_MATCH(N, OpNo);
7772 break;
7773 }
7774
7775 // If Res is null, the sub-method took care of registering the result.
7776 if (!Res.getNode()) return false;
7777
7778 // If the result is N, the sub-method updated N in place. Tell the legalizer
7779 // core about this.
7780 if (Res.getNode() == N)
7781 return true;
7782
7783
7784 if (N->isStrictFPOpcode())
7785 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
7786 "Invalid operand expansion");
7787 else
7788 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
7789 "Invalid operand expansion");
7790
7791 ReplaceValueWith(SDValue(N, 0), Res);
7792 return false;
7793}
7794
7795SDValue DAGTypeLegalizer::WidenVecOp_EXTEND(SDNode *N) {
7796 SDLoc DL(N);
7797 EVT VT = N->getValueType(0);
7798
7799 SDValue InOp = N->getOperand(0);
7800 assert(getTypeAction(InOp.getValueType()) ==
7802 "Unexpected type action");
7803 InOp = GetWidenedVector(InOp);
7806 "Input wasn't widened!");
7807
7808 // We may need to further widen the operand until it has the same total
7809 // vector size as the result.
7810 EVT InVT = InOp.getValueType();
7811 if (InVT.getSizeInBits() != VT.getSizeInBits()) {
7812 EVT InEltVT = InVT.getVectorElementType();
7813 for (EVT FixedVT : MVT::vector_valuetypes()) {
7814 EVT FixedEltVT = FixedVT.getVectorElementType();
7815 if (TLI.isTypeLegal(FixedVT) &&
7816 FixedVT.getSizeInBits() == VT.getSizeInBits() &&
7817 FixedEltVT == InEltVT) {
7818 assert(FixedVT.getVectorNumElements() >= VT.getVectorNumElements() &&
7819 "Not enough elements in the fixed type for the operand!");
7820 assert(FixedVT.getVectorNumElements() != InVT.getVectorNumElements() &&
7821 "We can't have the same type as we started with!");
7822 if (FixedVT.getVectorNumElements() > InVT.getVectorNumElements())
7823 InOp = DAG.getInsertSubvector(DL, DAG.getPOISON(FixedVT), InOp, 0);
7824 else
7825 InOp = DAG.getExtractSubvector(DL, FixedVT, InOp, 0);
7826 break;
7827 }
7828 }
7829 InVT = InOp.getValueType();
7830 if (InVT.getSizeInBits() != VT.getSizeInBits())
7831 // We couldn't find a legal vector type that was a widening of the input
7832 // and could be extended in-register to the result type, so we have to
7833 // scalarize.
7834 return WidenVecOp_Convert(N);
7835 }
7836
7837 // Use special DAG nodes to represent the operation of extending the
7838 // low lanes.
7839 switch (N->getOpcode()) {
7840 default:
7841 llvm_unreachable("Extend legalization on extend operation!");
7842 case ISD::ANY_EXTEND:
7843 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, VT, InOp);
7844 case ISD::SIGN_EXTEND:
7845 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, VT, InOp);
7846 case ISD::ZERO_EXTEND:
7847 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, VT, InOp);
7848 }
7849}
7850
7851SDValue DAGTypeLegalizer::WidenVecOp_CMP(SDNode *N) {
7852 SDLoc dl(N);
7853
7854 EVT OpVT = N->getOperand(0).getValueType();
7855 EVT ResVT = N->getValueType(0);
7856 SDValue LHS = GetWidenedVector(N->getOperand(0));
7857 SDValue RHS = GetWidenedVector(N->getOperand(1));
7858
7859 // 1. EXTRACT_SUBVECTOR
7860 // 2. SIGN_EXTEND/ZERO_EXTEND
7861 // 3. CMP
7862 LHS = DAG.getExtractSubvector(dl, OpVT, LHS, 0);
7863 RHS = DAG.getExtractSubvector(dl, OpVT, RHS, 0);
7864
7865 // At this point the result type is guaranteed to be valid, so we can use it
7866 // as the operand type by extending it appropriately
7867 ISD::NodeType ExtendOpcode =
7868 N->getOpcode() == ISD::SCMP ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
7869 LHS = DAG.getNode(ExtendOpcode, dl, ResVT, LHS);
7870 RHS = DAG.getNode(ExtendOpcode, dl, ResVT, RHS);
7871
7872 return DAG.getNode(N->getOpcode(), dl, ResVT, LHS, RHS);
7873}
7874
7875SDValue DAGTypeLegalizer::WidenVecOp_UnrollVectorOp(SDNode *N) {
7876 // The result (and first input) is legal, but the second input is illegal.
7877 // We can't do much to fix that, so just unroll and let the extracts off of
7878 // the second input be widened as needed later.
7879 return DAG.UnrollVectorOp(N);
7880}
7881
7882SDValue DAGTypeLegalizer::WidenVecOp_IS_FPCLASS(SDNode *N) {
7883 SDLoc DL(N);
7884 EVT ResultVT = N->getValueType(0);
7885 SDValue Test = N->getOperand(1);
7886 SDValue WideArg = GetWidenedVector(N->getOperand(0));
7887
7888 // Process this node similarly to SETCC.
7889 EVT WideResultVT = getSetCCResultType(WideArg.getValueType());
7890 if (ResultVT.getScalarType() == MVT::i1)
7891 WideResultVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
7892 WideResultVT.getVectorNumElements());
7893
7894 SDValue WideNode = DAG.getNode(ISD::IS_FPCLASS, DL, WideResultVT,
7895 {WideArg, Test}, N->getFlags());
7896
7897 // Extract the needed results from the result vector.
7898 EVT ResVT =
7899 EVT::getVectorVT(*DAG.getContext(), WideResultVT.getVectorElementType(),
7900 ResultVT.getVectorNumElements());
7901 SDValue CC = DAG.getExtractSubvector(DL, ResVT, WideNode, 0);
7902
7903 EVT OpVT = N->getOperand(0).getValueType();
7904 ISD::NodeType ExtendCode =
7905 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
7906 return DAG.getNode(ExtendCode, DL, ResultVT, CC);
7907}
7908
7909SDValue DAGTypeLegalizer::WidenVecOp_Convert(SDNode *N) {
7910 // Since the result is legal and the input is illegal.
7911 EVT VT = N->getValueType(0);
7912 EVT EltVT = VT.getVectorElementType();
7913 SDLoc dl(N);
7914 SDValue InOp = N->getOperand(N->isStrictFPOpcode() ? 1 : 0);
7915 assert(getTypeAction(InOp.getValueType()) ==
7917 "Unexpected type action");
7918 InOp = GetWidenedVector(InOp);
7919 EVT InVT = InOp.getValueType();
7920 unsigned Opcode = N->getOpcode();
7921
7922 // Helper to build a convert node with all scalar trailing operands.
7923 auto MakeConvertNode = [&](EVT VT, SDValue Op) -> SDValue {
7924 if (Opcode == ISD::CONVERT_TO_ARBITRARY_FP)
7925 return DAG.getNode(Opcode, dl, VT, Op, N->getOperand(1), N->getOperand(2),
7926 N->getOperand(3));
7927 if (Opcode == ISD::FP_ROUND || Opcode == ISD::CONVERT_FROM_ARBITRARY_FP)
7928 return DAG.getNode(Opcode, dl, VT, Op, N->getOperand(1));
7929 return DAG.getNode(Opcode, dl, VT, Op);
7930 };
7931
7932 // See if a widened result type would be legal, if so widen the node.
7933 // FIXME: This isn't safe for StrictFP. Other optimization here is needed.
7934 EVT WideVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
7935 InVT.getVectorElementCount());
7936 if (TLI.isTypeLegal(WideVT) && !N->isStrictFPOpcode()) {
7937 SDValue Res;
7938 if (N->isStrictFPOpcode()) {
7939 if (Opcode == ISD::STRICT_FP_ROUND)
7940 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
7941 { N->getOperand(0), InOp, N->getOperand(2) });
7942 else
7943 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
7944 { N->getOperand(0), InOp });
7945 // Legalize the chain result - switch anything that used the old chain to
7946 // use the new one.
7947 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7948 } else {
7949 Res = MakeConvertNode(WideVT, InOp);
7950 }
7951 return DAG.getExtractSubvector(dl, VT, Res, 0);
7952 }
7953
7954 EVT InEltVT = InVT.getVectorElementType();
7955
7956 // Unroll the convert into some scalar code and create a nasty build vector.
7957 unsigned NumElts = VT.getVectorNumElements();
7959 if (N->isStrictFPOpcode()) {
7960 SmallVector<SDValue, 4> NewOps(N->ops());
7961 SmallVector<SDValue, 32> OpChains;
7962 for (unsigned i=0; i < NumElts; ++i) {
7963 NewOps[1] = DAG.getExtractVectorElt(dl, InEltVT, InOp, i);
7964 Ops[i] = DAG.getNode(Opcode, dl, { EltVT, MVT::Other }, NewOps);
7965 OpChains.push_back(Ops[i].getValue(1));
7966 }
7967 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OpChains);
7968 ReplaceValueWith(SDValue(N, 1), NewChain);
7969 } else {
7970 for (unsigned i = 0; i < NumElts; ++i) {
7971 SDValue Elt = DAG.getExtractVectorElt(dl, InEltVT, InOp, i);
7972 Ops[i] = MakeConvertNode(EltVT, Elt);
7973 }
7974 }
7975
7976 return DAG.getBuildVector(VT, dl, Ops);
7977}
7978
7979SDValue DAGTypeLegalizer::WidenVecOp_FP_TO_XINT_SAT(SDNode *N) {
7980 EVT DstVT = N->getValueType(0);
7981 SDValue Src = GetWidenedVector(N->getOperand(0));
7982 EVT SrcVT = Src.getValueType();
7983 ElementCount WideNumElts = SrcVT.getVectorElementCount();
7984 SDLoc dl(N);
7985
7986 // See if a widened result type would be legal, if so widen the node.
7987 EVT WideDstVT = EVT::getVectorVT(*DAG.getContext(),
7988 DstVT.getVectorElementType(), WideNumElts);
7989 if (TLI.isTypeLegal(WideDstVT)) {
7990 SDValue Res =
7991 DAG.getNode(N->getOpcode(), dl, WideDstVT, Src, N->getOperand(1));
7992 return DAG.getNode(
7993 ISD::EXTRACT_SUBVECTOR, dl, DstVT, Res,
7994 DAG.getConstant(0, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
7995 }
7996
7997 // Give up and unroll.
7998 return DAG.UnrollVectorOp(N);
7999}
8000
8001SDValue DAGTypeLegalizer::WidenVecOp_BITCAST(SDNode *N) {
8002 EVT VT = N->getValueType(0);
8003 SDValue InOp = GetWidenedVector(N->getOperand(0));
8004 EVT InWidenVT = InOp.getValueType();
8005 SDLoc dl(N);
8006
8007 // Check if we can convert between two legal vector types and extract.
8008 TypeSize InWidenSize = InWidenVT.getSizeInBits();
8009 TypeSize Size = VT.getSizeInBits();
8010 // x86mmx is not an acceptable vector element type, so don't try.
8011 if (!VT.isVector() && VT != MVT::x86mmx &&
8012 InWidenSize.hasKnownScalarFactor(Size)) {
8013 unsigned NewNumElts = InWidenSize.getKnownScalarFactor(Size);
8014 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), VT, NewNumElts);
8015 if (TLI.isTypeLegal(NewVT)) {
8016 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
8017 return DAG.getExtractVectorElt(dl, VT, BitOp, 0);
8018 }
8019 }
8020
8021 // Handle a case like bitcast v12i8 -> v3i32. Normally that would get widened
8022 // to v16i8 -> v4i32, but for a target where v3i32 is legal but v12i8 is not,
8023 // we end up here. Handling the case here with EXTRACT_SUBVECTOR avoids
8024 // having to copy via memory.
8025 if (VT.isVector()) {
8026 EVT EltVT = VT.getVectorElementType();
8027 unsigned EltSize = EltVT.getFixedSizeInBits();
8028 if (InWidenSize.isKnownMultipleOf(EltSize)) {
8029 ElementCount NewNumElts =
8030 (InWidenVT.getVectorElementCount() * InWidenVT.getScalarSizeInBits())
8031 .divideCoefficientBy(EltSize);
8032 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NewNumElts);
8033 if (TLI.isTypeLegal(NewVT)) {
8034 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
8035 return DAG.getExtractSubvector(dl, VT, BitOp, 0);
8036 }
8037 }
8038 }
8039
8040 return CreateStackStoreLoad(InOp, VT);
8041}
8042
8043// Vectors with sizes that are not powers of 2 need to be widened to the
8044// next largest power of 2. For example, we may get a vector of 3 32-bit
8045// integers or of 6 16-bit integers, both of which have to be widened to a
8046// 128-bit vector.
8047SDValue DAGTypeLegalizer::WidenVecOp_FAKE_USE(SDNode *N) {
8048 SDValue WidenedOp = GetWidenedVector(N->getOperand(1));
8049 return DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, N->getOperand(0),
8050 WidenedOp);
8051}
8052
8053SDValue DAGTypeLegalizer::WidenVecOp_CONCAT_VECTORS(SDNode *N) {
8054 EVT VT = N->getValueType(0);
8055 EVT EltVT = VT.getVectorElementType();
8056 EVT InVT = N->getOperand(0).getValueType();
8057 SDLoc dl(N);
8058
8059 // If the widen width for this operand is the same as the width of the concat
8060 // and all but the first operand is undef, just use the widened operand.
8061 unsigned NumOperands = N->getNumOperands();
8062 if (VT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
8063 unsigned i;
8064 for (i = 1; i < NumOperands; ++i)
8065 if (!N->getOperand(i).isUndef())
8066 break;
8067
8068 if (i == NumOperands)
8069 return GetWidenedVector(N->getOperand(0));
8070 }
8071
8072 // Otherwise, fall back to a nasty build vector.
8073 unsigned NumElts = VT.getVectorNumElements();
8075
8076 unsigned NumInElts = InVT.getVectorNumElements();
8077
8078 unsigned Idx = 0;
8079 for (unsigned i=0; i < NumOperands; ++i) {
8080 SDValue InOp = N->getOperand(i);
8081 assert(getTypeAction(InOp.getValueType()) ==
8083 "Unexpected type action");
8084 InOp = GetWidenedVector(InOp);
8085 for (unsigned j = 0; j < NumInElts; ++j)
8086 Ops[Idx++] = DAG.getExtractVectorElt(dl, EltVT, InOp, j);
8087 }
8088 return DAG.getBuildVector(VT, dl, Ops);
8089}
8090
8091SDValue DAGTypeLegalizer::WidenVecOp_INSERT_SUBVECTOR(SDNode *N) {
8092 EVT VT = N->getValueType(0);
8093 SDValue SubVec = N->getOperand(1);
8094 SDValue InVec = N->getOperand(0);
8095
8096 EVT OrigVT = SubVec.getValueType();
8097 SubVec = GetWidenedVector(SubVec);
8098 EVT SubVT = SubVec.getValueType();
8099
8100 // Whether or not all the elements of the widened SubVec will be inserted into
8101 // valid indices of VT.
8102 bool IndicesValid = false;
8103 // If we statically know that VT can fit SubVT, the indices are valid.
8104 if (VT.knownBitsGE(SubVT))
8105 IndicesValid = true;
8106 else if (VT.isScalableVector() && SubVT.isFixedLengthVector()) {
8107 // Otherwise, if we're inserting a fixed vector into a scalable vector and
8108 // we know the minimum vscale we can work out if it's valid ourselves.
8109 Attribute Attr = DAG.getMachineFunction().getFunction().getFnAttribute(
8110 Attribute::VScaleRange);
8111 if (Attr.isValid()) {
8112 unsigned VScaleMin = Attr.getVScaleRangeMin();
8113 if (VT.getSizeInBits().getKnownMinValue() * VScaleMin >=
8114 SubVT.getFixedSizeInBits())
8115 IndicesValid = true;
8116 }
8117 }
8118
8119 if (!IndicesValid)
8121 "Don't know how to widen the operands for INSERT_SUBVECTOR");
8122
8123 SDLoc DL(N);
8124
8125 // We need to make sure that the indices are still valid, otherwise we might
8126 // widen what was previously well-defined to something undefined.
8127 if (InVec.isUndef() && N->getConstantOperandVal(2) == 0)
8128 return DAG.getNode(ISD::INSERT_SUBVECTOR, DL, VT, InVec, SubVec,
8129 N->getOperand(2));
8130
8131 if (OrigVT.isScalableVector()) {
8132 // When the widened types match, overwriting the start of a vector is
8133 // effectively a merge operation that can be implement as a vselect.
8134 if (SubVT == VT && N->getConstantOperandVal(2) == 0) {
8135 SDValue Mask =
8136 DAG.getMaskFromElementCount(DL, VT, OrigVT.getVectorElementCount());
8137 return DAG.getNode(ISD::VSELECT, DL, VT, Mask, SubVec, InVec);
8138 }
8139
8140 // Fallback to inserting through memory.
8141 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
8142 SDValue StackPtr = DAG.CreateStackTemporary(VT.getStoreSize(), Alignment);
8143 MachineFunction &MF = DAG.getMachineFunction();
8144 int FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
8145 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
8146
8147 MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
8150 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
8153
8154 // Write out the vector being inserting into.
8155 SDValue Ch =
8156 DAG.getStore(DAG.getEntryNode(), DL, InVec, StackPtr, StoreMMO);
8157
8158 // Build a mask to match the length of the sub-vector.
8159 SDValue Mask =
8160 DAG.getMaskFromElementCount(DL, SubVT, OrigVT.getVectorElementCount());
8161
8162 // Overwrite the sub-vector at the required offset.
8163 SDValue SubVecPtr =
8164 TLI.getVectorSubVecPointer(DAG, StackPtr, VT, OrigVT, N->getOperand(2));
8165 Ch = DAG.getMaskedStore(Ch, DL, SubVec, SubVecPtr,
8166 DAG.getPOISON(SubVecPtr.getValueType()), Mask, VT,
8167 StoreMMO, ISD::UNINDEXED, ISD::NON_EXTLOAD);
8168
8169 // Read back the result.
8170 return DAG.getLoad(VT, DL, Ch, StackPtr, LoadMMO);
8171 }
8172
8173 // If the operands can't be widened legally, just replace the INSERT_SUBVECTOR
8174 // with a series of INSERT_VECTOR_ELT
8175 unsigned Idx = N->getConstantOperandVal(2);
8176
8177 SDValue InsertElt = InVec;
8178 for (unsigned I = 0, E = OrigVT.getVectorNumElements(); I != E; ++I) {
8179 SDValue ExtractElt =
8180 DAG.getExtractVectorElt(DL, VT.getVectorElementType(), SubVec, I);
8181 InsertElt = DAG.getInsertVectorElt(DL, InsertElt, ExtractElt, I + Idx);
8182 }
8183
8184 return InsertElt;
8185}
8186
8187SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
8188 SDValue InOp = GetWidenedVector(N->getOperand(0));
8189 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SDLoc(N),
8190 N->getValueType(0), InOp, N->getOperand(1));
8191}
8192
8193SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
8194 SDValue InOp = GetWidenedVector(N->getOperand(0));
8195 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
8196 N->getValueType(0), InOp, N->getOperand(1));
8197}
8198
8199SDValue DAGTypeLegalizer::WidenVecOp_EXTEND_VECTOR_INREG(SDNode *N) {
8200 SDLoc DL(N);
8201 EVT ResVT = N->getValueType(0);
8202
8203 // Widen the input as requested by the legalizer.
8204 SDValue WideInOp = GetWidenedVector(N->getOperand(0));
8205 EVT WideInVT = WideInOp.getValueType();
8206
8207 // Simple case: if widened input is still smaller than or equal to result,
8208 // just use it directly.
8209 if (WideInVT.getSizeInBits() <= ResVT.getSizeInBits())
8210 return DAG.getNode(N->getOpcode(), DL, ResVT, WideInOp);
8211
8212 // EXTEND_VECTOR_INREG requires input bits <= result bits.
8213 // If widening makes the input larger than the original result, widen the
8214 // result to match, then extract back down.
8215 EVT ResEltVT = ResVT.getVectorElementType();
8216 unsigned EltBits = ResEltVT.getSizeInBits();
8217 assert((WideInVT.getSizeInBits() % EltBits) == 0 &&
8218 "Widened input size must be a multiple of result element size");
8219
8220 unsigned WideNumElts = WideInVT.getSizeInBits() / EltBits;
8221 EVT WideResVT = EVT::getVectorVT(*DAG.getContext(), ResEltVT, WideNumElts);
8222
8223 SDValue WideRes = DAG.getNode(N->getOpcode(), DL, WideResVT, WideInOp);
8224 return DAG.getExtractSubvector(DL, ResVT, WideRes, 0);
8225}
8226
8227SDValue DAGTypeLegalizer::WidenVecOp_STORE(SDNode *N) {
8228 // We have to widen the value, but we want only to store the original
8229 // vector type.
8230 StoreSDNode *ST = cast<StoreSDNode>(N);
8231
8232 if (!ST->getMemoryVT().getScalarType().isByteSized())
8233 return TLI.scalarizeVectorStore(ST, DAG);
8234
8235 if (ST->isTruncatingStore())
8236 return TLI.scalarizeVectorStore(ST, DAG);
8237
8238 // Generate a vector-predicated store if it is custom/legal on the target.
8239 // To avoid possible recursion, only do this if the widened mask type is
8240 // legal.
8241 // FIXME: Not all targets may support EVL in VP_STORE. These will have been
8242 // removed from the IR by the ExpandVectorPredication pass but we're
8243 // reintroducing them here.
8244 SDValue StVal = ST->getValue();
8245 EVT StVT = StVal.getValueType();
8246 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), StVT);
8247 EVT WideMaskVT = getSetCCResultType(WideVT);
8248
8249 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
8250 TLI.isTypeLegal(WideMaskVT)) {
8251 // Widen the value.
8252 SDLoc DL(N);
8253 StVal = GetWidenedVector(StVal);
8254 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
8255 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
8256 StVT.getVectorElementCount());
8257 return DAG.getStoreVP(ST->getChain(), DL, StVal, ST->getBasePtr(),
8258 ST->getOffset(), Mask, EVL, StVT, ST->getMemOperand(),
8259 ST->getAddressingMode());
8260 }
8261
8263 if (GenWidenVectorStores(StChain, ST)) {
8264 if (StChain.size() == 1)
8265 return StChain[0];
8266
8267 return DAG.getNode(ISD::TokenFactor, SDLoc(ST), MVT::Other, StChain);
8268 }
8269
8270 if (StVT.isVector()) {
8271 // If all else fails replace the store with a wide masked store.
8272 SDLoc DL(N);
8273 SDValue WideStVal = GetWidenedVector(StVal);
8274 SDValue Mask =
8275 DAG.getMaskFromElementCount(DL, WideVT, StVT.getVectorElementCount());
8276
8277 return DAG.getMaskedStore(ST->getChain(), DL, WideStVal, ST->getBasePtr(),
8278 ST->getOffset(), Mask, ST->getMemoryVT(),
8279 ST->getMemOperand(), ST->getAddressingMode(),
8280 ST->isTruncatingStore());
8281 }
8282
8283 report_fatal_error("Unable to widen vector store");
8284}
8285
8286SDValue DAGTypeLegalizer::WidenVecOp_ATOMIC_STORE(AtomicSDNode *ST) {
8287 EVT StVT = ST->getMemoryVT();
8288 SDLoc dl(ST);
8289
8290 SDValue StVal = GetWidenedVector(ST->getVal());
8291 EVT WidenVT = StVal.getValueType();
8292
8293 TypeSize StWidth = StVT.getSizeInBits();
8294 TypeSize WidenWidth = WidenVT.getSizeInBits();
8295 TypeSize WidthDiff = WidenWidth - StWidth;
8296
8297 // Find the vector type that can store the original memory width in one
8298 // atomic operation. Pass StAlign=0 (like atomic loads); a real align would
8299 // let findMemType widen the access past the value (e.g. <2 x i8> at align 4
8300 // implies a 4-byte movl, writing undef bytes past its object).
8301 std::optional<EVT> FirstVT =
8302 findMemType(DAG, TLI, StWidth.getKnownMinValue(), WidenVT, /*StAlign=*/0,
8303 WidthDiff.getKnownMinValue());
8304 if (!FirstVT)
8305 return SDValue();
8306
8307 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
8308
8309 SDValue StOp =
8310 coerceStoredValue(StVal, *FirstVT, WidenVT, FirstVTWidth, dl, DAG);
8311
8312 return DAG.getAtomic(ISD::ATOMIC_STORE, dl, *FirstVT, ST->getChain(), StOp,
8313 ST->getBasePtr(), ST->getMemOperand());
8314}
8315
8316SDValue DAGTypeLegalizer::WidenVecOp_VP_STORE(SDNode *N, unsigned OpNo) {
8317 assert((OpNo == 1 || OpNo == 3) &&
8318 "Can widen only data or mask operand of vp_store");
8319 VPStoreSDNode *ST = cast<VPStoreSDNode>(N);
8320 SDValue Mask = ST->getMask();
8321 SDValue StVal = ST->getValue();
8322 SDLoc dl(N);
8323
8324 if (OpNo == 1) {
8325 // Widen the value.
8326 StVal = GetWidenedVector(StVal);
8327
8328 // We only handle the case where the mask needs widening to an
8329 // identically-sized type as the vector inputs.
8330 assert(getTypeAction(Mask.getValueType()) ==
8332 "Unable to widen VP store");
8333 Mask = GetWidenedVector(Mask);
8334 } else {
8335 Mask = GetWidenedVector(Mask);
8336
8337 // We only handle the case where the stored value needs widening to an
8338 // identically-sized type as the mask.
8339 assert(getTypeAction(StVal.getValueType()) ==
8341 "Unable to widen VP store");
8342 StVal = GetWidenedVector(StVal);
8343 }
8344
8345 assert(Mask.getValueType().getVectorElementCount() ==
8347 "Mask and data vectors should have the same number of elements");
8348 return DAG.getStoreVP(ST->getChain(), dl, StVal, ST->getBasePtr(),
8349 ST->getOffset(), Mask, ST->getVectorLength(),
8350 ST->getMemoryVT(), ST->getMemOperand(),
8351 ST->getAddressingMode(), ST->isTruncatingStore(),
8352 ST->isCompressingStore());
8353}
8354
8355SDValue DAGTypeLegalizer::WidenVecOp_VP_STRIDED_STORE(SDNode *N,
8356 unsigned OpNo) {
8357 assert((OpNo == 1 || OpNo == 4) &&
8358 "Can widen only data or mask operand of vp_strided_store");
8359 VPStridedStoreSDNode *SST = cast<VPStridedStoreSDNode>(N);
8360 SDValue Mask = SST->getMask();
8361 SDValue StVal = SST->getValue();
8362 SDLoc DL(N);
8363
8364 if (OpNo == 1)
8365 assert(getTypeAction(Mask.getValueType()) ==
8367 "Unable to widen VP strided store");
8368 else
8369 assert(getTypeAction(StVal.getValueType()) ==
8371 "Unable to widen VP strided store");
8372
8373 StVal = GetWidenedVector(StVal);
8374 Mask = GetWidenedVector(Mask);
8375
8377 Mask.getValueType().getVectorElementCount() &&
8378 "Data and mask vectors should have the same number of elements");
8379
8380 return DAG.getStridedStoreVP(
8381 SST->getChain(), DL, StVal, SST->getBasePtr(), SST->getOffset(),
8382 SST->getStride(), Mask, SST->getVectorLength(), SST->getMemoryVT(),
8383 SST->getMemOperand(), SST->getAddressingMode(), SST->isTruncatingStore(),
8384 SST->isCompressingStore());
8385}
8386
8387SDValue DAGTypeLegalizer::WidenVecOp_MSTORE(SDNode *N, unsigned OpNo) {
8388 assert((OpNo == 1 || OpNo == 4) &&
8389 "Can widen only data or mask operand of mstore");
8390 MaskedStoreSDNode *MST = cast<MaskedStoreSDNode>(N);
8391 SDValue Mask = MST->getMask();
8392 EVT MaskVT = Mask.getValueType();
8393 SDValue StVal = MST->getValue();
8394 EVT VT = StVal.getValueType();
8395 SDLoc dl(N);
8396
8397 EVT WideVT, WideMaskVT;
8398 if (OpNo == 1) {
8399 // Widen the value.
8400 StVal = GetWidenedVector(StVal);
8401
8402 WideVT = StVal.getValueType();
8403 WideMaskVT =
8404 EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(),
8405 WideVT.getVectorElementCount());
8406 } else {
8407 WideMaskVT = TLI.getTypeToTransformTo(*DAG.getContext(), MaskVT);
8408
8409 EVT ValueVT = StVal.getValueType();
8410 WideVT = EVT::getVectorVT(*DAG.getContext(), ValueVT.getVectorElementType(),
8411 WideMaskVT.getVectorElementCount());
8412 }
8413
8414 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
8415 TLI.isTypeLegal(WideMaskVT) && !MST->isCompressingStore()) {
8416 Mask = DAG.getInsertSubvector(dl, DAG.getPOISON(WideMaskVT), Mask, 0);
8417 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8419 return DAG.getStoreVP(MST->getChain(), dl, StVal, MST->getBasePtr(),
8420 MST->getOffset(), Mask, EVL, MST->getMemoryVT(),
8421 MST->getMemOperand(), MST->getAddressingMode());
8422 }
8423
8424 if (OpNo == 1) {
8425 // The mask should be widened as well.
8426 Mask = ModifyToType(Mask, WideMaskVT, true);
8427 } else {
8428 // Widen the mask.
8429 Mask = ModifyToType(Mask, WideMaskVT, true);
8430
8431 StVal = ModifyToType(StVal, WideVT);
8432 }
8433
8434 assert(Mask.getValueType().getVectorElementCount() ==
8436 "Mask and data vectors should have the same number of elements");
8437 return DAG.getMaskedStore(MST->getChain(), dl, StVal, MST->getBasePtr(),
8438 MST->getOffset(), Mask, MST->getMemoryVT(),
8439 MST->getMemOperand(), MST->getAddressingMode(),
8440 false, MST->isCompressingStore());
8441}
8442
8443SDValue DAGTypeLegalizer::WidenVecOp_MGATHER(SDNode *N, unsigned OpNo) {
8444 assert(OpNo == 4 && "Can widen only the index of mgather");
8445 auto *MG = cast<MaskedGatherSDNode>(N);
8446 SDValue DataOp = MG->getPassThru();
8447 SDValue Mask = MG->getMask();
8448 SDValue Scale = MG->getScale();
8449
8450 // Just widen the index. It's allowed to have extra elements.
8451 SDValue Index = GetWidenedVector(MG->getIndex());
8452
8453 SDLoc dl(N);
8454 SDValue Ops[] = {MG->getChain(), DataOp, Mask, MG->getBasePtr(), Index,
8455 Scale};
8456 SDValue Res = DAG.getMaskedGather(MG->getVTList(), MG->getMemoryVT(), dl, Ops,
8457 MG->getMemOperand(), MG->getIndexType(),
8458 MG->getExtensionType());
8459 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
8460 ReplaceValueWith(SDValue(N, 0), Res.getValue(0));
8461 return SDValue();
8462}
8463
8464SDValue DAGTypeLegalizer::WidenVecOp_MSCATTER(SDNode *N, unsigned OpNo) {
8465 MaskedScatterSDNode *MSC = cast<MaskedScatterSDNode>(N);
8466 SDValue DataOp = MSC->getValue();
8467 SDValue Mask = MSC->getMask();
8468 SDValue Index = MSC->getIndex();
8469 SDValue Scale = MSC->getScale();
8470 EVT WideMemVT = MSC->getMemoryVT();
8471
8472 if (OpNo == 1) {
8473 DataOp = GetWidenedVector(DataOp);
8474 ElementCount WideEC = DataOp.getValueType().getVectorElementCount();
8475
8476 // Widen index.
8477 EVT IndexVT = Index.getValueType();
8478 EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
8479 IndexVT.getVectorElementType(), WideEC);
8480 Index = ModifyToType(Index, WideIndexVT);
8481
8482 // The mask should be widened as well.
8483 EVT MaskVT = Mask.getValueType();
8484 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
8485 MaskVT.getVectorElementType(), WideEC);
8486 Mask = ModifyToType(Mask, WideMaskVT, true);
8487
8488 // Widen the MemoryType
8489 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
8490 MSC->getMemoryVT().getScalarType(), WideEC);
8491 } else if (OpNo == 4) {
8492 // Just widen the index. It's allowed to have extra elements.
8493 Index = GetWidenedVector(Index);
8494 } else
8495 llvm_unreachable("Can't widen this operand of mscatter");
8496
8497 SDValue Ops[] = {MSC->getChain(), DataOp, Mask, MSC->getBasePtr(), Index,
8498 Scale};
8499 return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N),
8500 Ops, MSC->getMemOperand(), MSC->getIndexType(),
8501 MSC->isTruncatingStore());
8502}
8503
8504SDValue DAGTypeLegalizer::WidenVecOp_VP_SCATTER(SDNode *N, unsigned OpNo) {
8505 VPScatterSDNode *VPSC = cast<VPScatterSDNode>(N);
8506 SDValue DataOp = VPSC->getValue();
8507 SDValue Mask = VPSC->getMask();
8508 SDValue Index = VPSC->getIndex();
8509 SDValue Scale = VPSC->getScale();
8510 EVT WideMemVT = VPSC->getMemoryVT();
8511
8512 if (OpNo == 1) {
8513 DataOp = GetWidenedVector(DataOp);
8514 Index = GetWidenedVector(Index);
8515 const auto WideEC = DataOp.getValueType().getVectorElementCount();
8516 Mask = GetWidenedMask(Mask, WideEC);
8517 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
8518 VPSC->getMemoryVT().getScalarType(), WideEC);
8519 } else if (OpNo == 3) {
8520 // Just widen the index. It's allowed to have extra elements.
8521 Index = GetWidenedVector(Index);
8522 } else
8523 llvm_unreachable("Can't widen this operand of VP_SCATTER");
8524
8525 SDValue Ops[] = {
8526 VPSC->getChain(), DataOp, VPSC->getBasePtr(), Index, Scale, Mask,
8527 VPSC->getVectorLength()};
8528 return DAG.getScatterVP(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N), Ops,
8529 VPSC->getMemOperand(), VPSC->getIndexType());
8530}
8531
8532SDValue DAGTypeLegalizer::WidenVecOp_SETCC(SDNode *N) {
8533 SDValue InOp0 = GetWidenedVector(N->getOperand(0));
8534 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
8535 SDLoc dl(N);
8536 EVT VT = N->getValueType(0);
8537
8538 // WARNING: In this code we widen the compare instruction with garbage.
8539 // This garbage may contain denormal floats which may be slow. Is this a real
8540 // concern ? Should we zero the unused lanes if this is a float compare ?
8541
8542 // Get a new SETCC node to compare the newly widened operands.
8543 // Only some of the compared elements are legal.
8544 EVT SVT = getSetCCResultType(InOp0.getValueType());
8545 // The result type is legal, if its vXi1, keep vXi1 for the new SETCC.
8546 if (VT.getScalarType() == MVT::i1)
8547 SVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8548 SVT.getVectorElementCount());
8549
8550 SDValue WideSETCC = DAG.getNode(ISD::SETCC, SDLoc(N),
8551 SVT, InOp0, InOp1, N->getOperand(2));
8552
8553 // Extract the needed results from the result vector.
8554 EVT ResVT = EVT::getVectorVT(*DAG.getContext(),
8557 SDValue CC = DAG.getExtractSubvector(dl, ResVT, WideSETCC, 0);
8558
8559 EVT OpVT = N->getOperand(0).getValueType();
8560 ISD::NodeType ExtendCode =
8561 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
8562 return DAG.getNode(ExtendCode, dl, VT, CC);
8563}
8564
8565SDValue DAGTypeLegalizer::WidenVecOp_STRICT_FSETCC(SDNode *N) {
8566 SDValue Chain = N->getOperand(0);
8567 SDValue LHS = GetWidenedVector(N->getOperand(1));
8568 SDValue RHS = GetWidenedVector(N->getOperand(2));
8569 SDValue CC = N->getOperand(3);
8570 SDLoc dl(N);
8571
8572 EVT VT = N->getValueType(0);
8573 EVT EltVT = VT.getVectorElementType();
8574 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
8575 unsigned NumElts = VT.getVectorNumElements();
8576
8577 // Unroll into a build vector.
8578 SmallVector<SDValue, 8> Scalars(NumElts);
8579 SmallVector<SDValue, 8> Chains(NumElts);
8580
8581 for (unsigned i = 0; i != NumElts; ++i) {
8582 SDValue LHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, LHS, i);
8583 SDValue RHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, RHS, i);
8584
8585 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
8586 {Chain, LHSElem, RHSElem, CC});
8587 Chains[i] = Scalars[i].getValue(1);
8588 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
8589 DAG.getBoolConstant(true, dl, EltVT, VT),
8590 DAG.getBoolConstant(false, dl, EltVT, VT));
8591 }
8592
8593 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
8594 ReplaceValueWith(SDValue(N, 1), NewChain);
8595
8596 return DAG.getBuildVector(VT, dl, Scalars);
8597}
8598
8599static unsigned getExtendForIntVecReduction(unsigned Opc) {
8600 switch (Opc) {
8601 default:
8602 llvm_unreachable("Expected integer vector reduction");
8603 case ISD::VECREDUCE_ADD:
8604 case ISD::VECREDUCE_MUL:
8605 case ISD::VECREDUCE_AND:
8606 case ISD::VECREDUCE_OR:
8607 case ISD::VECREDUCE_XOR:
8608 return ISD::ANY_EXTEND;
8611 return ISD::SIGN_EXTEND;
8614 return ISD::ZERO_EXTEND;
8615 }
8616}
8617
8618SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE(SDNode *N) {
8619 SDLoc dl(N);
8620 SDValue Op = GetWidenedVector(N->getOperand(0));
8621 EVT VT = N->getValueType(0);
8622 EVT OrigVT = N->getOperand(0).getValueType();
8623 EVT WideVT = Op.getValueType();
8624 EVT ElemVT = OrigVT.getVectorElementType();
8625 SDNodeFlags Flags = N->getFlags();
8626
8627 unsigned Opc = N->getOpcode();
8628 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
8629 SDValue NeutralElem = DAG.getIdentityElement(BaseOpc, dl, ElemVT, Flags);
8630 assert(NeutralElem && "Neutral element must exist");
8631
8632 // Pad the vector with the neutral element.
8633 unsigned OrigElts = OrigVT.getVectorMinNumElements();
8634 unsigned WideElts = WideVT.getVectorMinNumElements();
8635
8636 // Generate a vp.reduce_op if it is custom/legal for the target. This avoids
8637 // needing to pad the source vector, because the inactive lanes can simply be
8638 // disabled and not contribute to the result.
8639 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opc);
8640 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WideVT)) {
8641 SDValue Start = NeutralElem;
8642 if (VT.isInteger())
8643 Start = DAG.getNode(getExtendForIntVecReduction(Opc), dl, VT, Start);
8644 assert(Start.getValueType() == VT);
8645 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8646 WideVT.getVectorElementCount());
8647 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
8648 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8649 OrigVT.getVectorElementCount());
8650 return DAG.getNode(*VPOpcode, dl, VT, {Start, Op, Mask, EVL}, Flags);
8651 }
8652
8653 if (WideVT.isScalableVector()) {
8654 unsigned GCD = std::gcd(OrigElts, WideElts);
8655 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
8657 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
8658 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
8659 Op = DAG.getInsertSubvector(dl, Op, SplatNeutral, Idx);
8660 return DAG.getNode(Opc, dl, VT, Op, Flags);
8661 }
8662
8663 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
8664 Op = DAG.getInsertVectorElt(dl, Op, NeutralElem, Idx);
8665
8666 return DAG.getNode(Opc, dl, VT, Op, Flags);
8667}
8668
8669SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE_SEQ(SDNode *N) {
8670 SDLoc dl(N);
8671 SDValue AccOp = N->getOperand(0);
8672 SDValue VecOp = N->getOperand(1);
8673 SDValue Op = GetWidenedVector(VecOp);
8674
8675 EVT VT = N->getValueType(0);
8676 EVT OrigVT = VecOp.getValueType();
8677 EVT WideVT = Op.getValueType();
8678 EVT ElemVT = OrigVT.getVectorElementType();
8679 SDNodeFlags Flags = N->getFlags();
8680
8681 unsigned Opc = N->getOpcode();
8682 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
8683 SDValue NeutralElem = DAG.getIdentityElement(BaseOpc, dl, ElemVT, Flags);
8684
8685 // Pad the vector with the neutral element.
8686 unsigned OrigElts = OrigVT.getVectorMinNumElements();
8687 unsigned WideElts = WideVT.getVectorMinNumElements();
8688
8689 // Generate a vp.reduce_op if it is custom/legal for the target. This avoids
8690 // needing to pad the source vector, because the inactive lanes can simply be
8691 // disabled and not contribute to the result.
8692 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opc);
8693 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WideVT)) {
8694 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8695 WideVT.getVectorElementCount());
8696 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
8697 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8698 OrigVT.getVectorElementCount());
8699 return DAG.getNode(*VPOpcode, dl, VT, {AccOp, Op, Mask, EVL}, Flags);
8700 }
8701
8702 if (WideVT.isScalableVector()) {
8703 unsigned GCD = std::gcd(OrigElts, WideElts);
8704 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
8706 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
8707 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
8708 Op = DAG.getInsertSubvector(dl, Op, SplatNeutral, Idx);
8709 return DAG.getNode(Opc, dl, VT, AccOp, Op, Flags);
8710 }
8711
8712 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
8713 Op = DAG.getInsertVectorElt(dl, Op, NeutralElem, Idx);
8714
8715 return DAG.getNode(Opc, dl, VT, AccOp, Op, Flags);
8716}
8717
8718SDValue DAGTypeLegalizer::WidenVecOp_VP_REDUCE(SDNode *N) {
8719 assert(N->isVPOpcode() && "Expected VP opcode");
8720
8721 SDLoc dl(N);
8722 SDValue Op = GetWidenedVector(N->getOperand(1));
8723 SDValue Mask = GetWidenedMask(N->getOperand(2),
8724 Op.getValueType().getVectorElementCount());
8725
8726 return DAG.getNode(N->getOpcode(), dl, N->getValueType(0),
8727 {N->getOperand(0), Op, Mask, N->getOperand(3)},
8728 N->getFlags());
8729}
8730
8731SDValue DAGTypeLegalizer::WidenVecOp_VSELECT(SDNode *N) {
8732 // This only gets called in the case that the left and right inputs and
8733 // result are of a legal odd vector type, and the condition is illegal i1 of
8734 // the same odd width that needs widening.
8735 EVT VT = N->getValueType(0);
8736 assert(VT.isVector() && !VT.isPow2VectorType() && isTypeLegal(VT));
8737
8738 SDValue Cond = GetWidenedVector(N->getOperand(0));
8739 SDValue LeftIn = DAG.WidenVector(N->getOperand(1), SDLoc(N));
8740 SDValue RightIn = DAG.WidenVector(N->getOperand(2), SDLoc(N));
8741 SDLoc DL(N);
8742
8743 SDValue Select = DAG.getNode(N->getOpcode(), DL, LeftIn.getValueType(), Cond,
8744 LeftIn, RightIn);
8745 return DAG.getExtractSubvector(DL, VT, Select, 0);
8746}
8747
8748SDValue DAGTypeLegalizer::WidenVecOp_CttzElements(SDNode *N) {
8749 SDLoc DL(N);
8750 SDValue Source = N->getOperand(0);
8751 EVT SourceVT = Source.getValueType();
8752 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), SourceVT);
8753
8754 SDValue WideSource;
8755 if (N->getOpcode() == ISD::CTTZ_ELTS_ZERO_POISON) {
8756 WideSource = GetWidenedVector(Source);
8757 } else {
8758 // Pad the widened portion with all-ones so the extra lanes appear as
8759 // active (non-zero) elements and do not contribute trailing zeros.
8760 SDValue AllOnes = DAG.getAllOnesConstant(DL, WideVT);
8761 if (WideVT.isFixedLengthVector() &&
8762 getTypeAction(WideVT) == TargetLowering::TypeSplitVector) {
8763 WideSource = GetWidenedVector(Source);
8764 unsigned WideElts = WideVT.getVectorNumElements();
8765 SmallVector<int> Mask(WideElts);
8766 std::iota(Mask.begin(), Mask.end(), 0);
8767 for (unsigned I = SourceVT.getVectorNumElements(); I != WideElts; ++I)
8768 Mask[I] += WideElts;
8769 WideSource = DAG.getVectorShuffle(WideVT, DL, WideSource, AllOnes, Mask);
8770 } else {
8771 WideSource = DAG.getInsertSubvector(DL, AllOnes, Source, 0);
8772 }
8773 }
8774
8775 return DAG.getNode(N->getOpcode(), DL, N->getValueType(0), WideSource,
8776 N->getFlags());
8777}
8778
8779SDValue DAGTypeLegalizer::WidenVecOp_VP_CttzElements(SDNode *N) {
8780 SDLoc DL(N);
8781 SDValue Source = GetWidenedVector(N->getOperand(0));
8782 EVT SrcVT = Source.getValueType();
8783 SDValue Mask =
8784 GetWidenedMask(N->getOperand(1), SrcVT.getVectorElementCount());
8785
8786 return DAG.getNode(N->getOpcode(), DL, N->getValueType(0),
8787 {Source, Mask, N->getOperand(2)}, N->getFlags());
8788}
8789
8790SDValue DAGTypeLegalizer::WidenVecOp_VECTOR_FIND_LAST_ACTIVE(SDNode *N) {
8791 SDLoc DL(N);
8792 SDValue Mask = N->getOperand(0);
8793 EVT OrigMaskVT = Mask.getValueType();
8794 SDValue WideMask = GetWidenedVector(Mask);
8795 EVT WideMaskVT = WideMask.getValueType();
8796
8797 // Pad the mask with zeros to ensure inactive lanes don't affect the result.
8798 unsigned OrigElts = OrigMaskVT.getVectorNumElements();
8799 unsigned WideElts = WideMaskVT.getVectorNumElements();
8800 if (OrigElts != WideElts) {
8801 SDValue ZeroMask = DAG.getConstant(0, DL, WideMaskVT);
8802 WideMask = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideMaskVT, ZeroMask,
8803 Mask, DAG.getVectorIdxConstant(0, DL));
8804 }
8805
8806 return DAG.getNode(ISD::VECTOR_FIND_LAST_ACTIVE, DL, N->getValueType(0),
8807 WideMask);
8808}
8809
8810SDValue DAGTypeLegalizer::WidenVecOp_VECTOR_MATCH(SDNode *N, unsigned OpNo) {
8811 if (OpNo == 0) {
8812 SDLoc DL(N);
8813 EVT ResVT = N->getValueType(0);
8814 EVT SourceVT = N->getOperand(0).getValueType();
8815 EVT WideSourceVT = TLI.getTypeToTransformTo(*DAG.getContext(), SourceVT);
8816 EVT WidenVT =
8817 EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
8818 WideSourceVT.getVectorElementCount());
8819
8820 SDValue WideSource = DAG.getInsertSubvector(DL, DAG.getUNDEF(WideSourceVT),
8821 N->getOperand(0), 0);
8822 SDValue WideMask = DAG.getInsertSubvector(
8823 DL, DAG.getConstant(0, DL, WidenVT), N->getOperand(2), 0);
8824 SDValue WideMatch = DAG.getNode(ISD::VECTOR_MATCH, DL, WidenVT, WideSource,
8825 N->getOperand(1), WideMask, N->getFlags());
8826 return DAG.getExtractSubvector(DL, ResVT, WideMatch, 0);
8827 }
8828
8829 // Note: The Mask (OpNo == 2) should be widened with the result.
8830 assert(OpNo == 1 && "Unexpected VECTOR_MATCH operand");
8831
8832 SDLoc DL(N);
8833 SDValue Needle = N->getOperand(1);
8834 EVT NeedleVT = Needle.getValueType();
8835 if (NeedleVT.getVectorNumElements() == 1)
8836 return TLI.expandVectorMatch(N, DAG);
8837
8838 EVT WidenNeedleVT = TLI.getTypeToTransformTo(*DAG.getContext(), NeedleVT);
8839
8840 SDValue Fill =
8841 DAG.getExtractVectorElt(DL, NeedleVT.getVectorElementType(), Needle, 0);
8842 SDValue WideNeedle = DAG.getSplatVector(WidenNeedleVT, DL, Fill);
8843 WideNeedle = DAG.getInsertSubvector(DL, WideNeedle, Needle, 0);
8844
8845 return DAG.getNode(ISD::VECTOR_MATCH, DL, N->getValueType(0),
8846 N->getOperand(0), WideNeedle, N->getOperand(2),
8847 N->getFlags());
8848}
8849
8850//===----------------------------------------------------------------------===//
8851// Vector Widening Utilities
8852//===----------------------------------------------------------------------===//
8853
8854// Utility function to find the type to chop up a widen vector for load/store
8855// TLI: Target lowering used to determine legal types.
8856// Width: Width left need to load/store.
8857// WidenVT: The widen vector type to load to/store from
8858// Align: If 0, don't allow use of a wider type
8859// WidenEx: If Align is not 0, the amount additional we can load/store from.
8860
8861static std::optional<EVT> findMemType(SelectionDAG &DAG,
8862 const TargetLowering &TLI, unsigned Width,
8863 EVT WidenVT, unsigned Align = 0,
8864 unsigned WidenEx = 0) {
8865 EVT WidenEltVT = WidenVT.getVectorElementType();
8866 const bool Scalable = WidenVT.isScalableVector();
8867 unsigned WidenWidth = WidenVT.getSizeInBits().getKnownMinValue();
8868 unsigned WidenEltWidth = WidenEltVT.getSizeInBits();
8869 unsigned AlignInBits = Align*8;
8870
8871 EVT RetVT = WidenEltVT;
8872 // Don't bother looking for an integer type if the vector is scalable, skip
8873 // to vector types.
8874 if (!Scalable) {
8875 // If we have one element to load/store, return it.
8876 if (Width == WidenEltWidth)
8877 return RetVT;
8878
8879 // See if there is larger legal integer than the element type to load/store.
8880 for (EVT MemVT : reverse(MVT::integer_valuetypes())) {
8881 unsigned MemVTWidth = MemVT.getSizeInBits();
8882 if (MemVT.getSizeInBits() <= WidenEltWidth)
8883 break;
8884 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
8885 if ((Action == TargetLowering::TypeLegal ||
8887 (WidenWidth % MemVTWidth) == 0 &&
8888 isPowerOf2_32(WidenWidth / MemVTWidth) &&
8889 (MemVTWidth <= Width ||
8890 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
8891 if (MemVTWidth == WidenWidth)
8892 return MemVT;
8893 RetVT = MemVT;
8894 break;
8895 }
8896 }
8897 }
8898
8899 // See if there is a larger vector type to load/store that has the same vector
8900 // element type and is evenly divisible with the WidenVT.
8901 for (EVT MemVT : reverse(MVT::vector_valuetypes())) {
8902 // Skip vector MVTs which don't match the scalable property of WidenVT.
8903 if (Scalable != MemVT.isScalableVector())
8904 continue;
8905 unsigned MemVTWidth = MemVT.getSizeInBits().getKnownMinValue();
8906 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
8907 if ((Action == TargetLowering::TypeLegal ||
8909 WidenEltVT == MemVT.getVectorElementType() &&
8910 (WidenWidth % MemVTWidth) == 0 &&
8911 isPowerOf2_32(WidenWidth / MemVTWidth) &&
8912 (MemVTWidth <= Width ||
8913 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
8914 if (RetVT.getFixedSizeInBits() < MemVTWidth || MemVT == WidenVT)
8915 return MemVT;
8916 }
8917 }
8918
8919 // Using element-wise loads and stores for widening operations is not
8920 // supported for scalable vectors
8921 if (Scalable)
8922 return std::nullopt;
8923
8924 return RetVT;
8925}
8926
8927// Builds a vector type from scalar loads
8928// VecTy: Resulting Vector type
8929// LDOps: Load operators to build a vector type
8930// [Start,End) the list of loads to use.
8933 unsigned Start, unsigned End) {
8934 SDLoc dl(LdOps[Start]);
8935 EVT LdTy = LdOps[Start].getValueType();
8936 unsigned Width = VecTy.getSizeInBits();
8937 unsigned NumElts = Width / LdTy.getSizeInBits();
8938 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), LdTy, NumElts);
8939
8940 unsigned Idx = 1;
8941 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT,LdOps[Start]);
8942
8943 for (unsigned i = Start + 1; i != End; ++i) {
8944 EVT NewLdTy = LdOps[i].getValueType();
8945 if (NewLdTy != LdTy) {
8946 NumElts = Width / NewLdTy.getSizeInBits();
8947 NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewLdTy, NumElts);
8948 VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, VecOp);
8949 // Readjust position and vector position based on new load type.
8950 Idx = Idx * LdTy.getSizeInBits() / NewLdTy.getSizeInBits();
8951 LdTy = NewLdTy;
8952 }
8953 VecOp = DAG.getInsertVectorElt(dl, VecOp, LdOps[i], Idx++);
8954 }
8955 return DAG.getNode(ISD::BITCAST, dl, VecTy, VecOp);
8956}
8957
8958SDValue DAGTypeLegalizer::GenWidenVectorLoads(SmallVectorImpl<SDValue> &LdChain,
8959 LoadSDNode *LD) {
8960 // The strategy assumes that we can efficiently load power-of-two widths.
8961 // The routine chops the vector into the largest vector loads with the same
8962 // element type or scalar loads and then recombines it to the widen vector
8963 // type.
8964 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
8965 EVT LdVT = LD->getMemoryVT();
8966 SDLoc dl(LD);
8967 assert(LdVT.isVector() && WidenVT.isVector());
8968 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
8970
8971 // Load information
8972 SDValue Chain = LD->getChain();
8973 SDValue BasePtr = LD->getBasePtr();
8974 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
8975 AAMDNodes AAInfo = LD->getAAInfo();
8976
8977 TypeSize LdWidth = LdVT.getSizeInBits();
8978 TypeSize WidenWidth = WidenVT.getSizeInBits();
8979 TypeSize WidthDiff = WidenWidth - LdWidth;
8980 // Allow wider loads if they are sufficiently aligned to avoid memory faults
8981 // and if the original load is simple.
8982 unsigned LdAlign =
8983 (!LD->isSimple() || LdVT.isScalableVector()) ? 0 : LD->getAlign().value();
8984
8985 // Find the vector type that can load from.
8986 std::optional<EVT> FirstVT =
8987 findMemType(DAG, TLI, LdWidth.getKnownMinValue(), WidenVT, LdAlign,
8988 WidthDiff.getKnownMinValue());
8989
8990 if (!FirstVT)
8991 return SDValue();
8992
8993 SmallVector<EVT, 8> MemVTs;
8994 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
8995
8996 // Unless we're able to load in one instruction we must work out how to load
8997 // the remainder.
8998 if (!TypeSize::isKnownLE(LdWidth, FirstVTWidth)) {
8999 std::optional<EVT> NewVT = FirstVT;
9000 TypeSize RemainingWidth = LdWidth;
9001 TypeSize NewVTWidth = FirstVTWidth;
9002 do {
9003 RemainingWidth -= NewVTWidth;
9004 if (TypeSize::isKnownLT(RemainingWidth, NewVTWidth)) {
9005 // The current type we are using is too large. Find a better size.
9006 NewVT = findMemType(DAG, TLI, RemainingWidth.getKnownMinValue(),
9007 WidenVT, LdAlign, WidthDiff.getKnownMinValue());
9008 if (!NewVT)
9009 return SDValue();
9010 NewVTWidth = NewVT->getSizeInBits();
9011 }
9012 MemVTs.push_back(*NewVT);
9013 } while (TypeSize::isKnownGT(RemainingWidth, NewVTWidth));
9014 }
9015
9016 SDValue LdOp = DAG.getLoad(*FirstVT, dl, Chain, BasePtr, LD->getPointerInfo(),
9017 LD->getBaseAlign(), MMOFlags, AAInfo);
9018 LdChain.push_back(LdOp.getValue(1));
9019
9020 // Check if we can load the element with one instruction.
9021 if (MemVTs.empty())
9022 return coerceLoadedValue(LdOp, *FirstVT, WidenVT, LdWidth, FirstVTWidth, dl,
9023 DAG);
9024
9025 // Load vector by using multiple loads from largest vector to scalar.
9027 LdOps.push_back(LdOp);
9028
9029 uint64_t ScaledOffset = 0;
9030 MachinePointerInfo MPI = LD->getPointerInfo();
9031
9032 // First incremement past the first load.
9033 IncrementPointer(cast<LoadSDNode>(LdOp), *FirstVT, MPI, BasePtr,
9034 &ScaledOffset);
9035
9036 for (EVT MemVT : MemVTs) {
9037 Align NewAlign = ScaledOffset == 0
9038 ? LD->getBaseAlign()
9039 : commonAlignment(LD->getAlign(), ScaledOffset);
9040 SDValue L =
9041 DAG.getLoad(MemVT, dl, Chain, BasePtr, MPI, NewAlign, MMOFlags, AAInfo);
9042
9043 LdOps.push_back(L);
9044 LdChain.push_back(L.getValue(1));
9045 IncrementPointer(cast<LoadSDNode>(L), MemVT, MPI, BasePtr, &ScaledOffset);
9046 }
9047
9048 // Build the vector from the load operations.
9049 unsigned End = LdOps.size();
9050 if (!LdOps[0].getValueType().isVector())
9051 // All the loads are scalar loads.
9052 return BuildVectorFromScalar(DAG, WidenVT, LdOps, 0, End);
9053
9054 // If the load contains vectors, build the vector using concat vector.
9055 // All of the vectors used to load are power-of-2, and the scalar loads can be
9056 // combined to make a power-of-2 vector.
9057 SmallVector<SDValue, 16> ConcatOps(End);
9058 int i = End - 1;
9059 int Idx = End;
9060 EVT LdTy = LdOps[i].getValueType();
9061 // First, combine the scalar loads to a vector.
9062 if (!LdTy.isVector()) {
9063 for (--i; i >= 0; --i) {
9064 LdTy = LdOps[i].getValueType();
9065 if (LdTy.isVector())
9066 break;
9067 }
9068 ConcatOps[--Idx] = BuildVectorFromScalar(DAG, LdTy, LdOps, i + 1, End);
9069 }
9070
9071 ConcatOps[--Idx] = LdOps[i];
9072 for (--i; i >= 0; --i) {
9073 EVT NewLdTy = LdOps[i].getValueType();
9074 if (NewLdTy != LdTy) {
9075 // Create a larger vector.
9076 TypeSize LdTySize = LdTy.getSizeInBits();
9077 TypeSize NewLdTySize = NewLdTy.getSizeInBits();
9078 assert(NewLdTySize.isScalable() == LdTySize.isScalable() &&
9079 NewLdTySize.isKnownMultipleOf(LdTySize.getKnownMinValue()));
9080 unsigned NumOps =
9081 NewLdTySize.getKnownMinValue() / LdTySize.getKnownMinValue();
9083 unsigned j = 0;
9084 for (; j != End-Idx; ++j)
9085 WidenOps[j] = ConcatOps[Idx+j];
9086 for (; j != NumOps; ++j)
9087 WidenOps[j] = DAG.getPOISON(LdTy);
9088
9089 ConcatOps[End-1] = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewLdTy,
9090 WidenOps);
9091 Idx = End - 1;
9092 LdTy = NewLdTy;
9093 }
9094 ConcatOps[--Idx] = LdOps[i];
9095 }
9096
9097 if (WidenWidth == LdTy.getSizeInBits() * (End - Idx))
9098 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
9099 ArrayRef(&ConcatOps[Idx], End - Idx));
9100
9101 // We need to fill the rest with undefs to build the vector.
9102 unsigned NumOps =
9103 WidenWidth.getKnownMinValue() / LdTy.getSizeInBits().getKnownMinValue();
9105 SDValue UndefVal = DAG.getPOISON(LdTy);
9106 {
9107 unsigned i = 0;
9108 for (; i != End-Idx; ++i)
9109 WidenOps[i] = ConcatOps[Idx+i];
9110 for (; i != NumOps; ++i)
9111 WidenOps[i] = UndefVal;
9112 }
9113 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, WidenOps);
9114}
9115
9116SDValue
9117DAGTypeLegalizer::GenWidenVectorExtLoads(SmallVectorImpl<SDValue> &LdChain,
9118 LoadSDNode *LD,
9119 ISD::LoadExtType ExtType) {
9120 // For extension loads, it may not be more efficient to chop up the vector
9121 // and then extend it. Instead, we unroll the load and build a new vector.
9122 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
9123 EVT LdVT = LD->getMemoryVT();
9124 SDLoc dl(LD);
9125 assert(LdVT.isVector() && WidenVT.isVector());
9126 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
9127
9128 // Load information
9129 SDValue Chain = LD->getChain();
9130 SDValue BasePtr = LD->getBasePtr();
9131 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
9132 AAMDNodes AAInfo = LD->getAAInfo();
9133
9134 if (LdVT.isScalableVector())
9135 return SDValue();
9136
9137 EVT EltVT = WidenVT.getVectorElementType();
9138 EVT LdEltVT = LdVT.getVectorElementType();
9139 unsigned NumElts = LdVT.getVectorNumElements();
9140
9141 // Load each element and widen.
9142 unsigned WidenNumElts = WidenVT.getVectorNumElements();
9143 SmallVector<SDValue, 16> Ops(WidenNumElts);
9144 unsigned Increment = LdEltVT.getSizeInBits() / 8;
9145 Ops[0] =
9146 DAG.getExtLoad(ExtType, dl, EltVT, Chain, BasePtr, LD->getPointerInfo(),
9147 LdEltVT, LD->getBaseAlign(), MMOFlags, AAInfo);
9148 LdChain.push_back(Ops[0].getValue(1));
9149 unsigned i = 0, Offset = Increment;
9150 for (i=1; i < NumElts; ++i, Offset += Increment) {
9151 SDValue NewBasePtr =
9152 DAG.getObjectPtrOffset(dl, BasePtr, TypeSize::getFixed(Offset));
9153 Ops[i] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, NewBasePtr,
9154 LD->getPointerInfo().getWithOffset(Offset), LdEltVT,
9155 LD->getBaseAlign(), MMOFlags, AAInfo);
9156 LdChain.push_back(Ops[i].getValue(1));
9157 }
9158
9159 // Fill the rest with undefs.
9160 SDValue UndefVal = DAG.getPOISON(EltVT);
9161 for (; i != WidenNumElts; ++i)
9162 Ops[i] = UndefVal;
9163
9164 return DAG.getBuildVector(WidenVT, dl, Ops);
9165}
9166
9167bool DAGTypeLegalizer::GenWidenVectorStores(SmallVectorImpl<SDValue> &StChain,
9168 StoreSDNode *ST) {
9169 // The strategy assumes that we can efficiently store power-of-two widths.
9170 // The routine chops the vector into the largest vector stores with the same
9171 // element type or scalar stores.
9172 SDValue Chain = ST->getChain();
9173 SDValue BasePtr = ST->getBasePtr();
9174 MachineMemOperand::Flags MMOFlags = ST->getMemOperand()->getFlags();
9175 AAMDNodes AAInfo = ST->getAAInfo();
9176 SDValue ValOp = GetWidenedVector(ST->getValue());
9177 SDLoc dl(ST);
9178
9179 EVT StVT = ST->getMemoryVT();
9180 TypeSize StWidth = StVT.getSizeInBits();
9181 EVT ValVT = ValOp.getValueType();
9182 TypeSize ValWidth = ValVT.getSizeInBits();
9183 EVT ValEltVT = ValVT.getVectorElementType();
9184 unsigned ValEltWidth = ValEltVT.getFixedSizeInBits();
9185 assert(StVT.getVectorElementType() == ValEltVT);
9186 assert(StVT.isScalableVector() == ValVT.isScalableVector() &&
9187 "Mismatch between store and value types");
9188
9189 int Idx = 0; // current index to store
9190
9191 MachinePointerInfo MPI = ST->getPointerInfo();
9192 uint64_t ScaledOffset = 0;
9193
9194 // A breakdown of how to widen this vector store. Each element of the vector
9195 // is a memory VT combined with the number of times it is to be stored to,
9196 // e,g., v5i32 -> {{v2i32,2},{i32,1}}
9198
9199 while (StWidth.isNonZero()) {
9200 // Find the largest vector type we can store with.
9201 std::optional<EVT> NewVT =
9202 findMemType(DAG, TLI, StWidth.getKnownMinValue(), ValVT);
9203 if (!NewVT)
9204 return false;
9205 MemVTs.push_back({*NewVT, 0});
9206 TypeSize NewVTWidth = NewVT->getSizeInBits();
9207
9208 do {
9209 StWidth -= NewVTWidth;
9210 MemVTs.back().second++;
9211 } while (StWidth.isNonZero() && TypeSize::isKnownGE(StWidth, NewVTWidth));
9212 }
9213
9214 for (const auto &Pair : MemVTs) {
9215 EVT NewVT = Pair.first;
9216 unsigned Count = Pair.second;
9217 TypeSize NewVTWidth = NewVT.getSizeInBits();
9218
9219 if (NewVT.isVector()) {
9220 unsigned NumVTElts = NewVT.getVectorMinNumElements();
9221 do {
9222 Align NewAlign = ScaledOffset == 0
9223 ? ST->getBaseAlign()
9224 : commonAlignment(ST->getAlign(), ScaledOffset);
9225 SDValue EOp = DAG.getExtractSubvector(dl, NewVT, ValOp, Idx);
9226 SDValue PartStore = DAG.getStore(Chain, dl, EOp, BasePtr, MPI, NewAlign,
9227 MMOFlags, AAInfo);
9228 StChain.push_back(PartStore);
9229
9230 Idx += NumVTElts;
9231 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr,
9232 &ScaledOffset);
9233 } while (--Count);
9234 } else {
9235 // Cast the vector to the scalar type we can store.
9236 unsigned NumElts = ValWidth.getFixedValue() / NewVTWidth.getFixedValue();
9237 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewVT, NumElts);
9238 SDValue VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, ValOp);
9239 // Readjust index position based on new vector type.
9240 Idx = Idx * ValEltWidth / NewVTWidth.getFixedValue();
9241 do {
9242 SDValue EOp = DAG.getExtractVectorElt(dl, NewVT, VecOp, Idx++);
9243 SDValue PartStore = DAG.getStore(Chain, dl, EOp, BasePtr, MPI,
9244 ST->getBaseAlign(), MMOFlags, AAInfo);
9245 StChain.push_back(PartStore);
9246
9247 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr);
9248 } while (--Count);
9249 // Restore index back to be relative to the original widen element type.
9250 Idx = Idx * NewVTWidth.getFixedValue() / ValEltWidth;
9251 }
9252 }
9253
9254 return true;
9255}
9256
9257/// Modifies a vector input (widen or narrows) to a vector of NVT. The
9258/// input vector must have the same element type as NVT.
9259/// FillWithZeroes specifies that the vector should be widened with zeroes.
9260SDValue DAGTypeLegalizer::ModifyToType(SDValue InOp, EVT NVT,
9261 bool FillWithZeroes) {
9262 // Note that InOp might have been widened so it might already have
9263 // the right width or it might need be narrowed.
9264 EVT InVT = InOp.getValueType();
9266 "input and widen element type must match");
9267 assert(InVT.isScalableVector() == NVT.isScalableVector() &&
9268 "cannot modify scalable vectors in this way");
9269 SDLoc dl(InOp);
9270
9271 // Check if InOp already has the right width.
9272 if (InVT == NVT)
9273 return InOp;
9274
9275 ElementCount InEC = InVT.getVectorElementCount();
9276 ElementCount WidenEC = NVT.getVectorElementCount();
9277 if (WidenEC.hasKnownScalarFactor(InEC)) {
9278 unsigned NumConcat = WidenEC.getKnownScalarFactor(InEC);
9279 SmallVector<SDValue, 16> Ops(NumConcat);
9280 SDValue FillVal =
9281 FillWithZeroes ? DAG.getConstant(0, dl, InVT) : DAG.getPOISON(InVT);
9282 Ops[0] = InOp;
9283 for (unsigned i = 1; i != NumConcat; ++i)
9284 Ops[i] = FillVal;
9285
9286 return DAG.getNode(ISD::CONCAT_VECTORS, dl, NVT, Ops);
9287 }
9288
9289 if (InEC.hasKnownScalarFactor(WidenEC))
9290 return DAG.getExtractSubvector(dl, NVT, InOp, 0);
9291
9292 if (NVT.isScalableVector() && InVT.isScalableVector()) {
9293 // Split the input into the largest equal-sized scalable subvectors.
9294 unsigned InNumElts = InVT.getVectorMinNumElements();
9295 unsigned NewNumElts = NVT.getVectorMinNumElements();
9296 unsigned CommonFactor = std::gcd(InNumElts, NewNumElts);
9297 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), NVT.getVectorElementType(),
9298 ElementCount::getScalable(CommonFactor));
9299
9301 unsigned NumCopiedParts = std::min(InNumElts, NewNumElts) / CommonFactor;
9302 for (unsigned I = 0; I != NumCopiedParts; ++I)
9303 Ops.push_back(
9304 DAG.getExtractSubvector(dl, PartVT, InOp, I * CommonFactor));
9305
9306 unsigned NumResultParts = NewNumElts / CommonFactor;
9307 if (NumResultParts > NumCopiedParts) {
9308 SDValue FillVal = FillWithZeroes ? DAG.getConstant(0, dl, PartVT)
9309 : DAG.getPOISON(PartVT);
9310 Ops.append(NumResultParts - NumCopiedParts, FillVal);
9311 }
9312
9313 return DAG.getNode(ISD::CONCAT_VECTORS, dl, NVT, Ops);
9314 }
9315
9316 assert(!InVT.isScalableVector() && !NVT.isScalableVector() &&
9317 "Scalable vectors should have been handled already.");
9318
9319 unsigned InNumElts = InEC.getFixedValue();
9320 unsigned WidenNumElts = WidenEC.getFixedValue();
9321
9322 // Fall back to extract and build (+ mask, if padding with zeros).
9323 SmallVector<SDValue, 16> Ops(WidenNumElts);
9324 EVT EltVT = NVT.getVectorElementType();
9325 unsigned MinNumElts = std::min(WidenNumElts, InNumElts);
9326 unsigned Idx;
9327 for (Idx = 0; Idx < MinNumElts; ++Idx)
9328 Ops[Idx] = DAG.getExtractVectorElt(dl, EltVT, InOp, Idx);
9329
9330 SDValue UndefVal = DAG.getPOISON(EltVT);
9331 for (; Idx < WidenNumElts; ++Idx)
9332 Ops[Idx] = UndefVal;
9333
9334 SDValue Widened = DAG.getBuildVector(NVT, dl, Ops);
9335 if (!FillWithZeroes)
9336 return Widened;
9337
9338 assert(NVT.isInteger() &&
9339 "We expect to never want to FillWithZeroes for non-integral types.");
9340
9342 MaskOps.append(MinNumElts, DAG.getAllOnesConstant(dl, EltVT));
9343 MaskOps.append(WidenNumElts - MinNumElts, DAG.getConstant(0, dl, EltVT));
9344
9345 return DAG.getNode(ISD::AND, dl, NVT, Widened,
9346 DAG.getBuildVector(NVT, dl, MaskOps));
9347}
return SDValue()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
unsigned Imm
unsigned uint64_t
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static constexpr Value * getValue(Ty &ValueOrUse)
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static unsigned getExtendForIntVecReduction(SDNode *N)
static SDValue BuildVectorFromScalar(SelectionDAG &DAG, EVT VecTy, SmallVectorImpl< SDValue > &LdOps, unsigned Start, unsigned End)
static std::optional< EVT > findMemType(SelectionDAG &DAG, const TargetLowering &TLI, unsigned Width, EVT WidenVT, unsigned Align, unsigned WidenEx)
static EVT getSETCCOperandType(SDValue N)
static bool isSETCCOp(unsigned Opcode)
static bool isLogicalMaskOp(unsigned Opcode)
static bool isSETCCorConvertedSETCC(SDValue N)
static SDValue coerceStoredValue(SDValue StVal, EVT FirstVT, EVT WidenVT, TypeSize FirstVTWidth, const SDLoc &dl, SelectionDAG &DAG)
Inverse of coerceLoadedValue: pull a FirstVT-sized scalar/vector out of the widened value so it can b...
static SDValue CollectOpsToWiden(SelectionDAG &DAG, const TargetLowering &TLI, SmallVectorImpl< SDValue > &ConcatOps, unsigned ConcatEnd, EVT VT, EVT MaxVT, EVT WidenVT)
static SDValue coerceLoadedValue(SDValue LdOp, EVT FirstVT, EVT WidenVT, TypeSize LdWidth, TypeSize FirstVTWidth, SDLoc dl, SelectionDAG &DAG)
Either return the same load or provide appropriate casts from the load and return that.
#define I(x, y, z)
Definition MD5.cpp:57
static bool isUndef(const MachineInstr &MI)
This file provides utility analysis objects describing memory locations.
uint64_t High
#define P(N)
const SmallVectorImpl< MachineOperand > & Cond
SI Fold Operands
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
This file implements the SmallBitVector class.
#define LLVM_DEBUG(...)
Definition Debug.h:119
Value * RHS
Value * LHS
This is an SDNode representing atomic operations.
LLVM_ABI unsigned getVScaleRangeMin() const
Returns the minimum value for the vscale_range attribute.
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition Attributes.h:263
static constexpr ElementCount getScalable(ScalarTy MinVal)
Definition TypeSize.h: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:1765
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr int PoisonMaskElem
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
Definition STLExtras.h:1885
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1772
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Definition Alignment.h:201
LLVM_ABI void processShuffleMasks(ArrayRef< int > Mask, unsigned NumOfSrcRegs, unsigned NumOfDestRegs, unsigned NumOfUsedRegs, function_ref< void()> NoInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned)> SingleInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned, bool)> ManyInputsAction)
Splits and processes shuffle mask depending on the number of input and output registers.
@ Increment
Incrementally increasing token ID.
Definition AllocToken.h:26
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Extended Value Type.
Definition ValueTypes.h:35
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
Definition ValueTypes.h:90
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
Definition ValueTypes.h:418
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
Definition ValueTypes.h:70
EVT changeTypeToInteger() const
Return the type converted to an equivalently sized integer or vector with integer element type.
Definition ValueTypes.h:129
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
Definition ValueTypes.h:307
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
Definition ValueTypes.h:155
ElementCount getVectorElementCount() const
Definition ValueTypes.h:373
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
Definition ValueTypes.h:494
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:396
bool isByteSized() const
Return true if the bit size is a multiple of 8.
Definition ValueTypes.h:266
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
Definition ValueTypes.h:382
uint64_t getScalarSizeInBits() const
Definition ValueTypes.h:408
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
Definition ValueTypes.h:501
EVT changeVectorElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
Definition ValueTypes.h:98
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
Definition ValueTypes.h:61
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
Definition ValueTypes.h:404
EVT widenIntegerVectorElementType(LLVMContext &Context) const
Return a VT for an integer vector type with the size of the elements doubled.
Definition ValueTypes.h:475
bool isFixedLengthVector() const
Definition ValueTypes.h:199
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
Definition ValueTypes.h:55
EVT getRoundIntegerType(LLVMContext &Context) const
Rounds the bit-width of the given integer EVT up to the nearest power of two (and at least to eight),...
Definition ValueTypes.h:442
bool isVector() const
Return true if this is a vector value type.
Definition ValueTypes.h:176
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
Definition ValueTypes.h:346
bool bitsEq(EVT VT) const
Return true if this has the same number of bits as VT.
Definition ValueTypes.h:279
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
Definition ValueTypes.h:187
bool knownBitsGE(EVT VT) const
Return true if we know at compile time this has more than or the same bits as VT.
Definition ValueTypes.h:291
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition ValueTypes.h:351
EVT changeElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a type whose attributes match ourselves with the exception of the element type that i...
Definition ValueTypes.h:121
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Definition ValueTypes.h:359
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
Definition ValueTypes.h:484
bool isInteger() const
Return true if this is an integer or a vector integer type.
Definition ValueTypes.h:160
This class contains a discriminated union of information about pointers in memory operands,...
LLVM_ABI unsigned getAddrSpace() const
Return the LLVM IR address space number that this pointer points into.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getUnknownStack(MachineFunction &MF)
Stack memory without other information.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.