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