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