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