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 assert(LdVT.isVector() && WidenVT.isVector() && "Expected vectors");
6625 assert(LdVT.isScalableVector() == WidenVT.isScalableVector() &&
6626 "Must be scalable");
6627 assert(LdVT.getVectorElementType() == WidenVT.getVectorElementType() &&
6628 "Expected equivalent element types");
6629
6630 // Load information
6631 SDValue Chain = LD->getChain();
6632 SDValue BasePtr = LD->getBasePtr();
6633
6634 TypeSize LdWidth = LdVT.getSizeInBits();
6635 TypeSize WidenWidth = WidenVT.getSizeInBits();
6636 TypeSize WidthDiff = WidenWidth - LdWidth;
6637
6638 // Find the vector type that can load from.
6639 std::optional<EVT> FirstVT =
6640 findMemType(DAG, TLI, LdWidth.getKnownMinValue(), WidenVT, /*LdAlign=*/0,
6641 WidthDiff.getKnownMinValue());
6642
6643 if (!FirstVT)
6644 return SDValue();
6645
6646 SmallVector<EVT, 8> MemVTs;
6647 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
6648
6649 SDValue LdOp = DAG.getAtomicLoad(ISD::NON_EXTLOAD, dl, *FirstVT, *FirstVT,
6650 Chain, BasePtr, LD->getMemOperand());
6651
6652 // Load the element with one instruction.
6653 SDValue Result = coerceLoadedValue(LdOp, *FirstVT, WidenVT, LdWidth,
6654 FirstVTWidth, dl, DAG);
6655
6656 // Modified the chain - switch anything that used the old chain to use
6657 // the new one.
6658 ReplaceValueWith(SDValue(LD, 1), LdOp.getValue(1));
6659 return Result;
6660}
6661
6662SDValue DAGTypeLegalizer::WidenVecRes_LOAD(SDNode *N) {
6663 LoadSDNode *LD = cast<LoadSDNode>(N);
6664 ISD::LoadExtType ExtType = LD->getExtensionType();
6665
6666 // A vector must always be stored in memory as-is, i.e. without any padding
6667 // between the elements, since various code depend on it, e.g. in the
6668 // handling of a bitcast of a vector type to int, which may be done with a
6669 // vector store followed by an integer load. A vector that does not have
6670 // elements that are byte-sized must therefore be stored as an integer
6671 // built out of the extracted vector elements.
6672 if (!LD->getMemoryVT().isByteSized()) {
6673 SDValue Value, NewChain;
6674 std::tie(Value, NewChain) = TLI.scalarizeVectorLoad(LD, DAG);
6675 ReplaceValueWith(SDValue(LD, 0), Value);
6676 ReplaceValueWith(SDValue(LD, 1), NewChain);
6677 return SDValue();
6678 }
6679
6680 // Generate a vector-predicated load if it is custom/legal on the target. To
6681 // avoid possible recursion, only do this if the widened mask type is legal.
6682 // FIXME: Not all targets may support EVL in VP_LOAD. These will have been
6683 // removed from the IR by the ExpandVectorPredication pass but we're
6684 // reintroducing them here.
6685 EVT VT = LD->getValueType(0);
6686 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6687 EVT WideMaskVT = getSetCCResultType(WideVT);
6688
6689 if (ExtType == ISD::NON_EXTLOAD &&
6690 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WideVT) &&
6691 TLI.isTypeLegal(WideMaskVT)) {
6692 SDLoc DL(N);
6693 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
6694 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
6696 SDValue NewLoad =
6697 DAG.getLoadVP(LD->getAddressingMode(), ISD::NON_EXTLOAD, WideVT, DL,
6698 LD->getChain(), LD->getBasePtr(), LD->getOffset(), Mask,
6699 EVL, LD->getMemoryVT(), LD->getMemOperand());
6700
6701 // Modified the chain - switch anything that used the old chain to use
6702 // the new one.
6703 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6704
6705 return NewLoad;
6706 }
6707
6709 SmallVector<SDValue, 16> LdChain; // Chain for the series of load
6710 if (ExtType != ISD::NON_EXTLOAD)
6711 Result = GenWidenVectorExtLoads(LdChain, LD, ExtType);
6712 else
6713 Result = GenWidenVectorLoads(LdChain, LD);
6714
6715 if (Result) {
6716 // If we generate a single load, we can use that for the chain. Otherwise,
6717 // build a factor node to remember the multiple loads are independent and
6718 // chain to that.
6719 SDValue NewChain;
6720 if (LdChain.size() == 1)
6721 NewChain = LdChain[0];
6722 else
6723 NewChain = DAG.getNode(ISD::TokenFactor, SDLoc(LD), MVT::Other, LdChain);
6724
6725 // Modified the chain - switch anything that used the old chain to use
6726 // the new one.
6727 ReplaceValueWith(SDValue(N, 1), NewChain);
6728
6729 return Result;
6730 }
6731
6732 if (VT.isVector()) {
6733 // If all else fails replace the load with a wide masked load.
6734 SDLoc DL(N);
6735 SDValue Mask =
6736 DAG.getMaskFromElementCount(DL, WideVT, VT.getVectorElementCount());
6737
6738 SDValue NewLoad = DAG.getMaskedLoad(
6739 WideVT, DL, LD->getChain(), LD->getBasePtr(), LD->getOffset(), Mask,
6740 DAG.getPOISON(WideVT), LD->getMemoryVT(), LD->getMemOperand(),
6741 LD->getAddressingMode(), LD->getExtensionType());
6742
6743 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6744 return NewLoad;
6745 }
6746
6747 report_fatal_error("Unable to widen vector load");
6748}
6749
6750SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD(VPLoadSDNode *N) {
6751 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6752 SDValue Mask = N->getMask();
6753 SDValue EVL = N->getVectorLength();
6754 ISD::LoadExtType ExtType = N->getExtensionType();
6755 SDLoc dl(N);
6756
6757 // The mask should be widened as well
6758 assert(getTypeAction(Mask.getValueType()) ==
6760 "Unable to widen binary VP op");
6761 Mask = GetWidenedVector(Mask);
6762 assert(Mask.getValueType().getVectorElementCount() ==
6763 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
6764 .getVectorElementCount() &&
6765 "Unable to widen vector load");
6766
6767 SDValue Res =
6768 DAG.getLoadVP(N->getAddressingMode(), ExtType, WidenVT, dl, N->getChain(),
6769 N->getBasePtr(), N->getOffset(), Mask, EVL,
6770 N->getMemoryVT(), N->getMemOperand(), N->isExpandingLoad());
6771 // Legalize the chain result - switch anything that used the old chain to
6772 // use the new one.
6773 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6774 return Res;
6775}
6776
6777SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD_FF(VPLoadFFSDNode *N) {
6778 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6779 SDValue Mask = N->getMask();
6780 SDValue EVL = N->getVectorLength();
6781 SDLoc dl(N);
6782
6783 // The mask should be widened as well
6784 assert(getTypeAction(Mask.getValueType()) ==
6786 "Unable to widen binary VP op");
6787 Mask = GetWidenedVector(Mask);
6788 assert(Mask.getValueType().getVectorElementCount() ==
6789 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
6790 .getVectorElementCount() &&
6791 "Unable to widen vector load");
6792
6793 SDValue Res = DAG.getLoadFFVP(WidenVT, dl, N->getChain(), N->getBasePtr(),
6794 Mask, EVL, N->getMemOperand());
6795 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6796 ReplaceValueWith(SDValue(N, 2), Res.getValue(2));
6797 return Res;
6798}
6799
6800SDValue DAGTypeLegalizer::WidenVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode *N) {
6801 SDLoc DL(N);
6802
6803 // The mask should be widened as well
6804 SDValue Mask = N->getMask();
6805 assert(getTypeAction(Mask.getValueType()) ==
6807 "Unable to widen VP strided load");
6808 Mask = GetWidenedVector(Mask);
6809
6810 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6811 assert(Mask.getValueType().getVectorElementCount() ==
6812 WidenVT.getVectorElementCount() &&
6813 "Data and mask vectors should have the same number of elements");
6814
6815 SDValue Res = DAG.getStridedLoadVP(
6816 N->getAddressingMode(), N->getExtensionType(), WidenVT, DL, N->getChain(),
6817 N->getBasePtr(), N->getOffset(), N->getStride(), Mask,
6818 N->getVectorLength(), N->getMemoryVT(), N->getMemOperand(),
6819 N->isExpandingLoad());
6820
6821 // Legalize the chain result - switch anything that used the old chain to
6822 // use the new one.
6823 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6824 return Res;
6825}
6826
6827SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_COMPRESS(SDNode *N) {
6828 SDValue Vec = N->getOperand(0);
6829 SDValue Mask = N->getOperand(1);
6830 SDValue Passthru = N->getOperand(2);
6831 EVT WideVecVT =
6832 TLI.getTypeToTransformTo(*DAG.getContext(), Vec.getValueType());
6833 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
6834 Mask.getValueType().getVectorElementType(),
6835 WideVecVT.getVectorElementCount());
6836
6837 SDValue WideVec = ModifyToType(Vec, WideVecVT);
6838 SDValue WideMask = ModifyToType(Mask, WideMaskVT, /*FillWithZeroes=*/true);
6839 SDValue WidePassthru = ModifyToType(Passthru, WideVecVT);
6840 return DAG.getNode(ISD::VECTOR_COMPRESS, SDLoc(N), WideVecVT, WideVec,
6841 WideMask, WidePassthru);
6842}
6843
6844SDValue DAGTypeLegalizer::WidenVecRes_MLOAD(MaskedLoadSDNode *N) {
6845 EVT VT = N->getValueType(0);
6846 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6847 SDValue Mask = N->getMask();
6848 EVT MaskVT = Mask.getValueType();
6849 SDValue PassThru = GetWidenedVector(N->getPassThru());
6850 ISD::LoadExtType ExtType = N->getExtensionType();
6851 SDLoc dl(N);
6852
6853 EVT WideMaskVT =
6854 EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(),
6855 WidenVT.getVectorElementCount());
6856
6857 if (ExtType == ISD::NON_EXTLOAD && !N->isExpandingLoad() &&
6858 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WidenVT) &&
6859 TLI.isTypeLegal(WideMaskVT) &&
6860 // If there is a passthru, we shouldn't use vp.load. However,
6861 // type legalizer will struggle on masked.load with
6862 // scalable vectors, so for scalable vectors, we still use vp.load
6863 // but manually merge the load result with the passthru using vp.select.
6864 (N->getPassThru()->isUndef() || VT.isScalableVector())) {
6865 Mask = DAG.getInsertSubvector(dl, DAG.getPOISON(WideMaskVT), Mask, 0);
6866 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
6868 SDValue NewLoad =
6869 DAG.getLoadVP(N->getAddressingMode(), ISD::NON_EXTLOAD, WidenVT, dl,
6870 N->getChain(), N->getBasePtr(), N->getOffset(), Mask, EVL,
6871 N->getMemoryVT(), N->getMemOperand());
6872 SDValue NewVal = NewLoad;
6873
6874 // Manually merge with vselect
6875 if (!N->getPassThru()->isUndef()) {
6876 assert(WidenVT.isScalableVector());
6877 NewVal = DAG.getNode(ISD::VSELECT, dl, WidenVT, Mask, NewVal, PassThru);
6878 // The lanes past EVL are poison.
6879 NewVal = DAG.getNode(ISD::VP_MERGE, dl, WidenVT,
6880 DAG.getAllOnesConstant(dl, WideMaskVT), NewVal,
6881 DAG.getPOISON(WidenVT), EVL);
6882 }
6883
6884 // Modified the chain - switch anything that used the old chain to use
6885 // the new one.
6886 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6887
6888 return NewVal;
6889 }
6890
6891 // The mask should be widened as well
6892 Mask = ModifyToType(Mask, WideMaskVT, true);
6893
6894 SDValue Res = DAG.getMaskedLoad(
6895 WidenVT, dl, N->getChain(), N->getBasePtr(), N->getOffset(), Mask,
6896 PassThru, N->getMemoryVT(), N->getMemOperand(), N->getAddressingMode(),
6897 ExtType, N->isExpandingLoad());
6898 // Legalize the chain result - switch anything that used the old chain to
6899 // use the new one.
6900 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6901 return Res;
6902}
6903
6904SDValue DAGTypeLegalizer::WidenVecRes_MGATHER(MaskedGatherSDNode *N) {
6905
6906 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6907 SDValue Mask = N->getMask();
6908 EVT MaskVT = Mask.getValueType();
6909 SDValue PassThru = GetWidenedVector(N->getPassThru());
6910 SDValue Scale = N->getScale();
6911 unsigned NumElts = WideVT.getVectorNumElements();
6912 SDLoc dl(N);
6913
6914 // The mask should be widened as well
6915 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
6916 MaskVT.getVectorElementType(),
6917 WideVT.getVectorNumElements());
6918 Mask = ModifyToType(Mask, WideMaskVT, true);
6919
6920 // Widen the Index operand
6921 SDValue Index = N->getIndex();
6922 EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
6923 Index.getValueType().getScalarType(),
6924 NumElts);
6925 Index = ModifyToType(Index, WideIndexVT);
6926 SDValue Ops[] = { N->getChain(), PassThru, Mask, N->getBasePtr(), Index,
6927 Scale };
6928
6929 // Widen the MemoryType
6930 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
6931 N->getMemoryVT().getScalarType(), NumElts);
6932 SDValue Res = DAG.getMaskedGather(DAG.getVTList(WideVT, MVT::Other),
6933 WideMemVT, dl, Ops, N->getMemOperand(),
6934 N->getIndexType(), N->getExtensionType());
6935
6936 // Legalize the chain result - switch anything that used the old chain to
6937 // use the new one.
6938 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6939 return Res;
6940}
6941
6942SDValue DAGTypeLegalizer::WidenVecRes_VP_GATHER(VPGatherSDNode *N) {
6943 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6944 SDValue Mask = N->getMask();
6945 SDValue Scale = N->getScale();
6946 ElementCount WideEC = WideVT.getVectorElementCount();
6947 SDLoc dl(N);
6948
6949 SDValue Index = GetWidenedVector(N->getIndex());
6950 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
6951 N->getMemoryVT().getScalarType(), WideEC);
6952 Mask = GetWidenedMask(Mask, WideEC);
6953
6954 SDValue Ops[] = {N->getChain(), N->getBasePtr(), Index, Scale,
6955 Mask, N->getVectorLength()};
6956 SDValue Res = DAG.getGatherVP(DAG.getVTList(WideVT, MVT::Other), WideMemVT,
6957 dl, Ops, N->getMemOperand(), N->getIndexType());
6958
6959 // Legalize the chain result - switch anything that used the old chain to
6960 // use the new one.
6961 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6962 return Res;
6963}
6964
6965SDValue DAGTypeLegalizer::WidenVecRes_ScalarOp(SDNode *N) {
6966 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6967 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, N->getOperand(0));
6968}
6969
6970// Return true is this is a SETCC node or a strict version of it.
6971static inline bool isSETCCOp(unsigned Opcode) {
6972 switch (Opcode) {
6973 case ISD::SETCC:
6974 case ISD::STRICT_FSETCC:
6976 return true;
6977 }
6978 return false;
6979}
6980
6981// Return true if this is a node that could have two SETCCs as operands.
6982static inline bool isLogicalMaskOp(unsigned Opcode) {
6983 switch (Opcode) {
6984 case ISD::AND:
6985 case ISD::OR:
6986 case ISD::XOR:
6987 return true;
6988 }
6989 return false;
6990}
6991
6992// If N is a SETCC or a strict variant of it, return the type
6993// of the compare operands.
6995 unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
6996 return N->getOperand(OpNo).getValueType();
6997}
6998
6999// This is used just for the assert in convertMask(). Check that this either
7000// a SETCC or a previously handled SETCC by convertMask().
7001#ifndef NDEBUG
7002static inline bool isSETCCorConvertedSETCC(SDValue N) {
7003 if (N.getOpcode() == ISD::EXTRACT_SUBVECTOR)
7004 N = N.getOperand(0);
7005 else if (N.getOpcode() == ISD::CONCAT_VECTORS) {
7006 for (unsigned i = 1; i < N->getNumOperands(); ++i)
7007 if (!N->getOperand(i)->isUndef())
7008 return false;
7009 N = N.getOperand(0);
7010 }
7011
7012 if (N.getOpcode() == ISD::TRUNCATE)
7013 N = N.getOperand(0);
7014 else if (N.getOpcode() == ISD::SIGN_EXTEND)
7015 N = N.getOperand(0);
7016
7017 if (isLogicalMaskOp(N.getOpcode()))
7018 return isSETCCorConvertedSETCC(N.getOperand(0)) &&
7019 isSETCCorConvertedSETCC(N.getOperand(1));
7020
7021 return (isSETCCOp(N.getOpcode()) ||
7023}
7024#endif
7025
7026// Return a mask of vector type MaskVT to replace InMask. Also adjust MaskVT
7027// to ToMaskVT if needed with vector extension or truncation.
7028SDValue DAGTypeLegalizer::convertMask(SDValue InMask, EVT MaskVT,
7029 EVT ToMaskVT) {
7030 // Currently a SETCC or a AND/OR/XOR with two SETCCs are handled.
7031 // FIXME: This code seems to be too restrictive, we might consider
7032 // generalizing it or dropping it.
7033 assert(isSETCCorConvertedSETCC(InMask) && "Unexpected mask argument.");
7034
7035 // Make a new Mask node, with a legal result VT.
7036 SDValue Mask;
7038 for (unsigned i = 0, e = InMask->getNumOperands(); i < e; ++i)
7039 Ops.push_back(InMask->getOperand(i));
7040 if (InMask->isStrictFPOpcode()) {
7041 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask),
7042 { MaskVT, MVT::Other }, Ops);
7043 ReplaceValueWith(InMask.getValue(1), Mask.getValue(1));
7044 }
7045 else
7046 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask), MaskVT, Ops,
7047 InMask->getFlags());
7048
7049 // If MaskVT has smaller or bigger elements than ToMaskVT, a vector sign
7050 // extend or truncate is needed.
7051 LLVMContext &Ctx = *DAG.getContext();
7052 unsigned MaskScalarBits = MaskVT.getScalarSizeInBits();
7053 unsigned ToMaskScalBits = ToMaskVT.getScalarSizeInBits();
7054 if (MaskScalarBits < ToMaskScalBits) {
7055 EVT ExtVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
7056 MaskVT.getVectorNumElements());
7057 Mask = DAG.getNode(ISD::SIGN_EXTEND, SDLoc(Mask), ExtVT, Mask);
7058 } else if (MaskScalarBits > ToMaskScalBits) {
7059 EVT TruncVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
7060 MaskVT.getVectorNumElements());
7061 Mask = DAG.getNode(ISD::TRUNCATE, SDLoc(Mask), TruncVT, Mask);
7062 }
7063
7064 assert(Mask->getValueType(0).getScalarSizeInBits() ==
7065 ToMaskVT.getScalarSizeInBits() &&
7066 "Mask should have the right element size by now.");
7067
7068 // Adjust Mask to the right number of elements.
7069 unsigned CurrMaskNumEls = Mask->getValueType(0).getVectorNumElements();
7070 if (CurrMaskNumEls > ToMaskVT.getVectorNumElements()) {
7071 Mask = DAG.getExtractSubvector(SDLoc(Mask), ToMaskVT, Mask, 0);
7072 } else if (CurrMaskNumEls < ToMaskVT.getVectorNumElements()) {
7073 unsigned NumSubVecs = (ToMaskVT.getVectorNumElements() / CurrMaskNumEls);
7074 EVT SubVT = Mask->getValueType(0);
7075 SmallVector<SDValue, 16> SubOps(NumSubVecs, DAG.getPOISON(SubVT));
7076 SubOps[0] = Mask;
7077 Mask = DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Mask), ToMaskVT, SubOps);
7078 }
7079
7080 assert((Mask->getValueType(0) == ToMaskVT) &&
7081 "A mask of ToMaskVT should have been produced by now.");
7082
7083 return Mask;
7084}
7085
7086// This method tries to handle some special cases for the vselect mask
7087// and if needed adjusting the mask vector type to match that of the VSELECT.
7088// Without it, many cases end up with scalarization of the SETCC, with many
7089// unnecessary instructions.
7090SDValue DAGTypeLegalizer::WidenVSELECTMask(SDNode *N) {
7091 LLVMContext &Ctx = *DAG.getContext();
7092 SDValue Cond = N->getOperand(0);
7093
7094 if (N->getOpcode() != ISD::VSELECT)
7095 return SDValue();
7096
7097 if (!isSETCCOp(Cond->getOpcode()) && !isLogicalMaskOp(Cond->getOpcode()))
7098 return SDValue();
7099
7100 // If this is a splitted VSELECT that was previously already handled, do
7101 // nothing.
7102 EVT CondVT = Cond->getValueType(0);
7103 if (CondVT.getScalarSizeInBits() != 1)
7104 return SDValue();
7105
7106 EVT VSelVT = N->getValueType(0);
7107
7108 // This method can't handle scalable vector types.
7109 // FIXME: This support could be added in the future.
7110 if (VSelVT.isScalableVector())
7111 return SDValue();
7112
7113 // Only handle vector types which are a power of 2.
7114 if (!isPowerOf2_64(VSelVT.getSizeInBits()))
7115 return SDValue();
7116
7117 // Don't touch if this will be scalarized.
7118 EVT FinalVT = VSelVT;
7119 while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
7120 FinalVT = FinalVT.getHalfNumVectorElementsVT(Ctx);
7121
7122 if (FinalVT.getVectorNumElements() == 1)
7123 return SDValue();
7124
7125 // If there is support for an i1 vector mask, don't touch.
7126 if (isSETCCOp(Cond.getOpcode())) {
7127 EVT SetCCOpVT = getSETCCOperandType(Cond);
7128 while (TLI.getTypeAction(Ctx, SetCCOpVT) != TargetLowering::TypeLegal)
7129 SetCCOpVT = TLI.getTypeToTransformTo(Ctx, SetCCOpVT);
7130 EVT SetCCResVT = getSetCCResultType(SetCCOpVT);
7131 if (SetCCResVT.getScalarSizeInBits() == 1)
7132 return SDValue();
7133 } else if (CondVT.getScalarType() == MVT::i1) {
7134 // If there is support for an i1 vector mask (or only scalar i1 conditions),
7135 // don't touch.
7136 while (TLI.getTypeAction(Ctx, CondVT) != TargetLowering::TypeLegal)
7137 CondVT = TLI.getTypeToTransformTo(Ctx, CondVT);
7138
7139 if (CondVT.getScalarType() == MVT::i1)
7140 return SDValue();
7141 }
7142
7143 // Widen the vselect result type if needed.
7144 if (getTypeAction(VSelVT) == TargetLowering::TypeWidenVector)
7145 VSelVT = TLI.getTypeToTransformTo(Ctx, VSelVT);
7146
7147 // The mask of the VSELECT should have integer elements.
7148 EVT ToMaskVT = VSelVT;
7149 if (!ToMaskVT.getScalarType().isInteger())
7150 ToMaskVT = ToMaskVT.changeVectorElementTypeToInteger();
7151
7152 SDValue Mask;
7153 if (isSETCCOp(Cond->getOpcode())) {
7154 EVT MaskVT = getSetCCResultType(getSETCCOperandType(Cond));
7155 Mask = convertMask(Cond, MaskVT, ToMaskVT);
7156 } else if (isLogicalMaskOp(Cond->getOpcode()) &&
7157 isSETCCOp(Cond->getOperand(0).getOpcode()) &&
7158 isSETCCOp(Cond->getOperand(1).getOpcode())) {
7159 // Cond is (AND/OR/XOR (SETCC, SETCC))
7160 SDValue SETCC0 = Cond->getOperand(0);
7161 SDValue SETCC1 = Cond->getOperand(1);
7162 EVT VT0 = getSetCCResultType(getSETCCOperandType(SETCC0));
7163 EVT VT1 = getSetCCResultType(getSETCCOperandType(SETCC1));
7164 unsigned ScalarBits0 = VT0.getScalarSizeInBits();
7165 unsigned ScalarBits1 = VT1.getScalarSizeInBits();
7166 unsigned ScalarBits_ToMask = ToMaskVT.getScalarSizeInBits();
7167 EVT MaskVT;
7168 // If the two SETCCs have different VTs, either extend/truncate one of
7169 // them to the other "towards" ToMaskVT, or truncate one and extend the
7170 // other to ToMaskVT.
7171 if (ScalarBits0 != ScalarBits1) {
7172 EVT NarrowVT = ((ScalarBits0 < ScalarBits1) ? VT0 : VT1);
7173 EVT WideVT = ((NarrowVT == VT0) ? VT1 : VT0);
7174 if (ScalarBits_ToMask >= WideVT.getScalarSizeInBits())
7175 MaskVT = WideVT;
7176 else if (ScalarBits_ToMask <= NarrowVT.getScalarSizeInBits())
7177 MaskVT = NarrowVT;
7178 else
7179 MaskVT = ToMaskVT;
7180 } else
7181 // If the two SETCCs have the same VT, don't change it.
7182 MaskVT = VT0;
7183
7184 // Make new SETCCs and logical nodes.
7185 SETCC0 = convertMask(SETCC0, VT0, MaskVT);
7186 SETCC1 = convertMask(SETCC1, VT1, MaskVT);
7187 Cond = DAG.getNode(Cond->getOpcode(), SDLoc(Cond), MaskVT, SETCC0, SETCC1);
7188
7189 // Convert the logical op for VSELECT if needed.
7190 Mask = convertMask(Cond, MaskVT, ToMaskVT);
7191 } else
7192 return SDValue();
7193
7194 return Mask;
7195}
7196
7197SDValue DAGTypeLegalizer::WidenVecRes_Select(SDNode *N) {
7198 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7199 ElementCount WidenEC = WidenVT.getVectorElementCount();
7200
7201 SDValue Cond1 = N->getOperand(0);
7202 EVT CondVT = Cond1.getValueType();
7203 unsigned Opcode = N->getOpcode();
7204 if (CondVT.isVector()) {
7205 if (SDValue WideCond = WidenVSELECTMask(N)) {
7206 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
7207 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
7208 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
7209 return DAG.getNode(Opcode, SDLoc(N), WidenVT, WideCond, InOp1, InOp2);
7210 }
7211
7212 EVT CondEltVT = CondVT.getVectorElementType();
7213 EVT CondWidenVT = EVT::getVectorVT(*DAG.getContext(), CondEltVT, WidenEC);
7214 if (getTypeAction(CondVT) == TargetLowering::TypeWidenVector)
7215 Cond1 = GetWidenedVector(Cond1);
7216
7217 // If we have to split the condition there is no point in widening the
7218 // select. This would result in an cycle of widening the select ->
7219 // widening the condition operand -> splitting the condition operand ->
7220 // splitting the select -> widening the select. Instead split this select
7221 // further and widen the resulting type.
7222 if (getTypeAction(CondVT) == TargetLowering::TypeSplitVector) {
7223 SDValue SplitSelect = SplitVecOp_VSELECT(N, 0);
7224 SDValue Res = ModifyToType(SplitSelect, WidenVT);
7225 return Res;
7226 }
7227
7228 if (Cond1.getValueType() != CondWidenVT)
7229 Cond1 = ModifyToType(Cond1, CondWidenVT);
7230 }
7231
7232 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
7233 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
7234 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
7235 if (Opcode == ISD::VP_SELECT || Opcode == ISD::VP_MERGE)
7236 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2,
7237 N->getOperand(3));
7238 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2);
7239}
7240
7241SDValue DAGTypeLegalizer::WidenVecRes_SELECT_CC(SDNode *N) {
7242 SDValue InOp1 = GetWidenedVector(N->getOperand(2));
7243 SDValue InOp2 = GetWidenedVector(N->getOperand(3));
7244 return DAG.getNode(ISD::SELECT_CC, SDLoc(N),
7245 InOp1.getValueType(), N->getOperand(0),
7246 N->getOperand(1), InOp1, InOp2, N->getOperand(4));
7247}
7248
7249SDValue DAGTypeLegalizer::WidenVecRes_UNDEF(SDNode *N) {
7250 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7251 return DAG.getUNDEF(WidenVT);
7252}
7253
7254SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N) {
7255 EVT VT = N->getValueType(0);
7256 SDLoc dl(N);
7257
7258 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7259 unsigned NumElts = VT.getVectorNumElements();
7260 unsigned WidenNumElts = WidenVT.getVectorNumElements();
7261
7262 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
7263 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
7264
7265 // Adjust mask based on new input vector length.
7266 SmallVector<int, 16> NewMask(WidenNumElts, -1);
7267 for (unsigned i = 0; i != NumElts; ++i) {
7268 int Idx = N->getMaskElt(i);
7269 if (Idx < (int)NumElts)
7270 NewMask[i] = Idx;
7271 else
7272 NewMask[i] = Idx - NumElts + WidenNumElts;
7273 }
7274 return DAG.getVectorShuffle(WidenVT, dl, InOp1, InOp2, NewMask);
7275}
7276
7277SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_REVERSE(SDNode *N) {
7278 EVT VT = N->getValueType(0);
7279 EVT EltVT = VT.getVectorElementType();
7280 SDLoc dl(N);
7281
7282 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7283 SDValue OpValue = GetWidenedVector(N->getOperand(0));
7284 assert(WidenVT == OpValue.getValueType() && "Unexpected widened vector type");
7285
7286 SDValue ReverseVal = DAG.getNode(ISD::VECTOR_REVERSE, dl, WidenVT, OpValue);
7287 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
7288 unsigned VTNumElts = VT.getVectorMinNumElements();
7289 unsigned IdxVal = WidenNumElts - VTNumElts;
7290
7291 if (VT.isScalableVector()) {
7292 // Try to split the 'Widen ReverseVal' into smaller extracts and concat the
7293 // results together, e.g.(nxv6i64 -> nxv8i64)
7294 // nxv8i64 vector_reverse
7295 // <->
7296 // nxv8i64 concat(
7297 // nxv2i64 extract_subvector(nxv8i64, 2)
7298 // nxv2i64 extract_subvector(nxv8i64, 4)
7299 // nxv2i64 extract_subvector(nxv8i64, 6)
7300 // nxv2i64 undef)
7301
7302 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
7303 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
7305 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
7306 "down type's element count");
7308 unsigned i = 0;
7309 for (; i < VTNumElts / GCD; ++i)
7310 Parts.push_back(
7311 DAG.getExtractSubvector(dl, PartVT, ReverseVal, IdxVal + i * GCD));
7312 for (; i < WidenNumElts / GCD; ++i)
7313 Parts.push_back(DAG.getPOISON(PartVT));
7314
7315 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
7316 }
7317
7318 // Use VECTOR_SHUFFLE to combine new vector from 'ReverseVal' for
7319 // fixed-vectors.
7320 SmallVector<int, 16> Mask(WidenNumElts, -1);
7321 std::iota(Mask.begin(), Mask.begin() + VTNumElts, IdxVal);
7322
7323 return DAG.getVectorShuffle(WidenVT, dl, ReverseVal, DAG.getPOISON(WidenVT),
7324 Mask);
7325}
7326
7327SDValue DAGTypeLegalizer::WidenVecRes_GET_ACTIVE_LANE_MASK(SDNode *N) {
7328 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7329 return DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, SDLoc(N), NVT, N->ops());
7330}
7331
7332SDValue DAGTypeLegalizer::WidenVecRes_SETCC(SDNode *N) {
7333 assert(N->getValueType(0).isVector() &&
7334 N->getOperand(0).getValueType().isVector() &&
7335 "Operands must be vectors");
7336 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7337 ElementCount WidenEC = WidenVT.getVectorElementCount();
7338
7339 SDValue InOp1 = N->getOperand(0);
7340 EVT InVT = InOp1.getValueType();
7341 assert(InVT.isVector() && "can not widen non-vector type");
7342 EVT WidenInVT =
7343 EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), WidenEC);
7344
7345 // The input and output types often differ here, and it could be that while
7346 // we'd prefer to widen the result type, the input operands have been split.
7347 // In this case, we also need to split the result of this node as well.
7348 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector) {
7349 SDValue SplitVSetCC = SplitVecOp_VSETCC(N);
7350 SDValue Res = ModifyToType(SplitVSetCC, WidenVT);
7351 return Res;
7352 }
7353
7354 // If the inputs also widen, handle them directly. Otherwise widen by hand.
7355 SDValue InOp2 = N->getOperand(1);
7356 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
7357 InOp1 = GetWidenedVector(InOp1);
7358 InOp2 = GetWidenedVector(InOp2);
7359 } else {
7360 SDValue Poison = DAG.getPOISON(WidenInVT);
7361 SDValue ZeroIdx = DAG.getVectorIdxConstant(0, SDLoc(N));
7362 InOp1 = DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), WidenInVT, Poison,
7363 InOp1, ZeroIdx);
7364 InOp2 = DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), WidenInVT, Poison,
7365 InOp2, ZeroIdx);
7366 }
7367
7368 // Assume that the input and output will be widen appropriately. If not,
7369 // we will have to unroll it at some point.
7370 assert(InOp1.getValueType() == WidenInVT &&
7371 InOp2.getValueType() == WidenInVT &&
7372 "Input not widened to expected type!");
7373 (void)WidenInVT;
7374 if (N->getOpcode() == ISD::VP_SETCC) {
7375 SDValue Mask =
7376 GetWidenedMask(N->getOperand(3), WidenVT.getVectorElementCount());
7377 return DAG.getNode(ISD::VP_SETCC, SDLoc(N), WidenVT, InOp1, InOp2,
7378 N->getOperand(2), Mask, N->getOperand(4));
7379 }
7380 return DAG.getNode(ISD::SETCC, SDLoc(N), WidenVT, InOp1, InOp2,
7381 N->getOperand(2));
7382}
7383
7384SDValue DAGTypeLegalizer::WidenVecRes_STRICT_FSETCC(SDNode *N) {
7385 assert(N->getValueType(0).isVector() &&
7386 N->getOperand(1).getValueType().isVector() &&
7387 "Operands must be vectors");
7388 EVT VT = N->getValueType(0);
7389 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7390 unsigned WidenNumElts = WidenVT.getVectorNumElements();
7391 unsigned NumElts = VT.getVectorNumElements();
7392 EVT EltVT = VT.getVectorElementType();
7393
7394 SDLoc dl(N);
7395 SDValue Chain = N->getOperand(0);
7396 SDValue LHS = N->getOperand(1);
7397 SDValue RHS = N->getOperand(2);
7398 SDValue CC = N->getOperand(3);
7399 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
7400
7401 // Fully unroll and reassemble.
7402 SmallVector<SDValue, 8> Scalars(WidenNumElts, DAG.getPOISON(EltVT));
7403 SmallVector<SDValue, 8> Chains(NumElts);
7404 for (unsigned i = 0; i != NumElts; ++i) {
7405 SDValue LHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, LHS, i);
7406 SDValue RHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, RHS, i);
7407
7408 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
7409 {Chain, LHSElem, RHSElem, CC});
7410 Chains[i] = Scalars[i].getValue(1);
7411 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
7412 DAG.getBoolConstant(true, dl, EltVT, VT),
7413 DAG.getBoolConstant(false, dl, EltVT, VT));
7414 }
7415
7416 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
7417 ReplaceValueWith(SDValue(N, 1), NewChain);
7418
7419 return DAG.getBuildVector(WidenVT, dl, Scalars);
7420}
7421
7422//===----------------------------------------------------------------------===//
7423// Widen Vector Operand
7424//===----------------------------------------------------------------------===//
7425bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned OpNo) {
7426 LLVM_DEBUG(dbgs() << "Widen node operand " << OpNo << ": "; N->dump(&DAG));
7427 SDValue Res = SDValue();
7428
7429 // See if the target wants to custom widen this node.
7430 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
7431 return false;
7432
7433 switch (N->getOpcode()) {
7434 default:
7435#ifndef NDEBUG
7436 dbgs() << "WidenVectorOperand op #" << OpNo << ": ";
7437 N->dump(&DAG);
7438 dbgs() << "\n";
7439#endif
7440 report_fatal_error("Do not know how to widen this operator's operand!");
7441
7442 case ISD::BITCAST: Res = WidenVecOp_BITCAST(N); break;
7443 case ISD::FAKE_USE:
7444 Res = WidenVecOp_FAKE_USE(N);
7445 break;
7446 case ISD::CONCAT_VECTORS: Res = WidenVecOp_CONCAT_VECTORS(N); break;
7447 case ISD::INSERT_SUBVECTOR: Res = WidenVecOp_INSERT_SUBVECTOR(N); break;
7448 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecOp_EXTRACT_SUBVECTOR(N); break;
7449 case ISD::EXTRACT_VECTOR_ELT: Res = WidenVecOp_EXTRACT_VECTOR_ELT(N); break;
7450 case ISD::STORE: Res = WidenVecOp_STORE(N); break;
7451 case ISD::VP_STORE: Res = WidenVecOp_VP_STORE(N, OpNo); break;
7452 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
7453 Res = WidenVecOp_VP_STRIDED_STORE(N, OpNo);
7454 break;
7458 Res = WidenVecOp_EXTEND_VECTOR_INREG(N);
7459 break;
7460 case ISD::MSTORE: Res = WidenVecOp_MSTORE(N, OpNo); break;
7461 case ISD::MGATHER: Res = WidenVecOp_MGATHER(N, OpNo); break;
7462 case ISD::MSCATTER: Res = WidenVecOp_MSCATTER(N, OpNo); break;
7463 case ISD::VP_SCATTER: Res = WidenVecOp_VP_SCATTER(N, OpNo); break;
7464 case ISD::SETCC: Res = WidenVecOp_SETCC(N); break;
7465 case ISD::STRICT_FSETCC:
7466 case ISD::STRICT_FSETCCS: Res = WidenVecOp_STRICT_FSETCC(N); break;
7467 case ISD::VSELECT: Res = WidenVecOp_VSELECT(N); break;
7468 case ISD::FLDEXP:
7469 case ISD::FCOPYSIGN:
7470 case ISD::LROUND:
7471 case ISD::LLROUND:
7472 case ISD::LRINT:
7473 case ISD::LLRINT:
7474 Res = WidenVecOp_UnrollVectorOp(N);
7475 break;
7476 case ISD::IS_FPCLASS: Res = WidenVecOp_IS_FPCLASS(N); break;
7477
7478 case ISD::ANY_EXTEND:
7479 case ISD::SIGN_EXTEND:
7480 case ISD::ZERO_EXTEND:
7481 Res = WidenVecOp_EXTEND(N);
7482 break;
7483
7484 case ISD::SCMP:
7485 case ISD::UCMP:
7486 Res = WidenVecOp_CMP(N);
7487 break;
7488
7489 case ISD::FP_EXTEND:
7491 case ISD::FP_ROUND:
7493 case ISD::FP_TO_SINT:
7495 case ISD::FP_TO_UINT:
7497 case ISD::SINT_TO_FP:
7499 case ISD::UINT_TO_FP:
7501 case ISD::TRUNCATE:
7503 Res = WidenVecOp_Convert(N);
7504 break;
7505
7508 Res = WidenVecOp_FP_TO_XINT_SAT(N);
7509 break;
7510
7513 case ISD::VECREDUCE_ADD:
7514 case ISD::VECREDUCE_MUL:
7515 case ISD::VECREDUCE_AND:
7516 case ISD::VECREDUCE_OR:
7517 case ISD::VECREDUCE_XOR:
7526 Res = WidenVecOp_VECREDUCE(N);
7527 break;
7530 Res = WidenVecOp_VECREDUCE_SEQ(N);
7531 break;
7532 case ISD::VP_REDUCE_FADD:
7533 case ISD::VP_REDUCE_SEQ_FADD:
7534 case ISD::VP_REDUCE_FMUL:
7535 case ISD::VP_REDUCE_SEQ_FMUL:
7536 case ISD::VP_REDUCE_ADD:
7537 case ISD::VP_REDUCE_MUL:
7538 case ISD::VP_REDUCE_AND:
7539 case ISD::VP_REDUCE_OR:
7540 case ISD::VP_REDUCE_XOR:
7541 case ISD::VP_REDUCE_SMAX:
7542 case ISD::VP_REDUCE_SMIN:
7543 case ISD::VP_REDUCE_UMAX:
7544 case ISD::VP_REDUCE_UMIN:
7545 case ISD::VP_REDUCE_FMAX:
7546 case ISD::VP_REDUCE_FMIN:
7547 case ISD::VP_REDUCE_FMAXIMUM:
7548 case ISD::VP_REDUCE_FMINIMUM:
7549 Res = WidenVecOp_VP_REDUCE(N);
7550 break;
7551 case ISD::VP_CTTZ_ELTS:
7552 case ISD::VP_CTTZ_ELTS_ZERO_POISON:
7553 Res = WidenVecOp_VP_CttzElements(N);
7554 break;
7556 Res = WidenVecOp_VECTOR_FIND_LAST_ACTIVE(N);
7557 break;
7558 }
7559
7560 // If Res is null, the sub-method took care of registering the result.
7561 if (!Res.getNode()) return false;
7562
7563 // If the result is N, the sub-method updated N in place. Tell the legalizer
7564 // core about this.
7565 if (Res.getNode() == N)
7566 return true;
7567
7568
7569 if (N->isStrictFPOpcode())
7570 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
7571 "Invalid operand expansion");
7572 else
7573 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
7574 "Invalid operand expansion");
7575
7576 ReplaceValueWith(SDValue(N, 0), Res);
7577 return false;
7578}
7579
7580SDValue DAGTypeLegalizer::WidenVecOp_EXTEND(SDNode *N) {
7581 SDLoc DL(N);
7582 EVT VT = N->getValueType(0);
7583
7584 SDValue InOp = N->getOperand(0);
7585 assert(getTypeAction(InOp.getValueType()) ==
7587 "Unexpected type action");
7588 InOp = GetWidenedVector(InOp);
7591 "Input wasn't widened!");
7592
7593 // We may need to further widen the operand until it has the same total
7594 // vector size as the result.
7595 EVT InVT = InOp.getValueType();
7596 if (InVT.getSizeInBits() != VT.getSizeInBits()) {
7597 EVT InEltVT = InVT.getVectorElementType();
7598 for (EVT FixedVT : MVT::vector_valuetypes()) {
7599 EVT FixedEltVT = FixedVT.getVectorElementType();
7600 if (TLI.isTypeLegal(FixedVT) &&
7601 FixedVT.getSizeInBits() == VT.getSizeInBits() &&
7602 FixedEltVT == InEltVT) {
7603 assert(FixedVT.getVectorNumElements() >= VT.getVectorNumElements() &&
7604 "Not enough elements in the fixed type for the operand!");
7605 assert(FixedVT.getVectorNumElements() != InVT.getVectorNumElements() &&
7606 "We can't have the same type as we started with!");
7607 if (FixedVT.getVectorNumElements() > InVT.getVectorNumElements())
7608 InOp = DAG.getInsertSubvector(DL, DAG.getPOISON(FixedVT), InOp, 0);
7609 else
7610 InOp = DAG.getExtractSubvector(DL, FixedVT, InOp, 0);
7611 break;
7612 }
7613 }
7614 InVT = InOp.getValueType();
7615 if (InVT.getSizeInBits() != VT.getSizeInBits())
7616 // We couldn't find a legal vector type that was a widening of the input
7617 // and could be extended in-register to the result type, so we have to
7618 // scalarize.
7619 return WidenVecOp_Convert(N);
7620 }
7621
7622 // Use special DAG nodes to represent the operation of extending the
7623 // low lanes.
7624 switch (N->getOpcode()) {
7625 default:
7626 llvm_unreachable("Extend legalization on extend operation!");
7627 case ISD::ANY_EXTEND:
7628 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, VT, InOp);
7629 case ISD::SIGN_EXTEND:
7630 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, VT, InOp);
7631 case ISD::ZERO_EXTEND:
7632 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, VT, InOp);
7633 }
7634}
7635
7636SDValue DAGTypeLegalizer::WidenVecOp_CMP(SDNode *N) {
7637 SDLoc dl(N);
7638
7639 EVT OpVT = N->getOperand(0).getValueType();
7640 EVT ResVT = N->getValueType(0);
7641 SDValue LHS = GetWidenedVector(N->getOperand(0));
7642 SDValue RHS = GetWidenedVector(N->getOperand(1));
7643
7644 // 1. EXTRACT_SUBVECTOR
7645 // 2. SIGN_EXTEND/ZERO_EXTEND
7646 // 3. CMP
7647 LHS = DAG.getExtractSubvector(dl, OpVT, LHS, 0);
7648 RHS = DAG.getExtractSubvector(dl, OpVT, RHS, 0);
7649
7650 // At this point the result type is guaranteed to be valid, so we can use it
7651 // as the operand type by extending it appropriately
7652 ISD::NodeType ExtendOpcode =
7653 N->getOpcode() == ISD::SCMP ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
7654 LHS = DAG.getNode(ExtendOpcode, dl, ResVT, LHS);
7655 RHS = DAG.getNode(ExtendOpcode, dl, ResVT, RHS);
7656
7657 return DAG.getNode(N->getOpcode(), dl, ResVT, LHS, RHS);
7658}
7659
7660SDValue DAGTypeLegalizer::WidenVecOp_UnrollVectorOp(SDNode *N) {
7661 // The result (and first input) is legal, but the second input is illegal.
7662 // We can't do much to fix that, so just unroll and let the extracts off of
7663 // the second input be widened as needed later.
7664 return DAG.UnrollVectorOp(N);
7665}
7666
7667SDValue DAGTypeLegalizer::WidenVecOp_IS_FPCLASS(SDNode *N) {
7668 SDLoc DL(N);
7669 EVT ResultVT = N->getValueType(0);
7670 SDValue Test = N->getOperand(1);
7671 SDValue WideArg = GetWidenedVector(N->getOperand(0));
7672
7673 // Process this node similarly to SETCC.
7674 EVT WideResultVT = getSetCCResultType(WideArg.getValueType());
7675 if (ResultVT.getScalarType() == MVT::i1)
7676 WideResultVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
7677 WideResultVT.getVectorNumElements());
7678
7679 SDValue WideNode = DAG.getNode(ISD::IS_FPCLASS, DL, WideResultVT,
7680 {WideArg, Test}, N->getFlags());
7681
7682 // Extract the needed results from the result vector.
7683 EVT ResVT =
7684 EVT::getVectorVT(*DAG.getContext(), WideResultVT.getVectorElementType(),
7685 ResultVT.getVectorNumElements());
7686 SDValue CC = DAG.getExtractSubvector(DL, ResVT, WideNode, 0);
7687
7688 EVT OpVT = N->getOperand(0).getValueType();
7689 ISD::NodeType ExtendCode =
7690 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
7691 return DAG.getNode(ExtendCode, DL, ResultVT, CC);
7692}
7693
7694SDValue DAGTypeLegalizer::WidenVecOp_Convert(SDNode *N) {
7695 // Since the result is legal and the input is illegal.
7696 EVT VT = N->getValueType(0);
7697 EVT EltVT = VT.getVectorElementType();
7698 SDLoc dl(N);
7699 SDValue InOp = N->getOperand(N->isStrictFPOpcode() ? 1 : 0);
7700 assert(getTypeAction(InOp.getValueType()) ==
7702 "Unexpected type action");
7703 InOp = GetWidenedVector(InOp);
7704 EVT InVT = InOp.getValueType();
7705 unsigned Opcode = N->getOpcode();
7706
7707 // See if a widened result type would be legal, if so widen the node.
7708 // FIXME: This isn't safe for StrictFP. Other optimization here is needed.
7709 EVT WideVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
7710 InVT.getVectorElementCount());
7711 if (TLI.isTypeLegal(WideVT) && !N->isStrictFPOpcode()) {
7712 SDValue Res;
7713 if (N->isStrictFPOpcode()) {
7714 if (Opcode == ISD::STRICT_FP_ROUND)
7715 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
7716 { N->getOperand(0), InOp, N->getOperand(2) });
7717 else
7718 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
7719 { N->getOperand(0), InOp });
7720 // Legalize the chain result - switch anything that used the old chain to
7721 // use the new one.
7722 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7723 } else {
7724 if (Opcode == ISD::FP_ROUND || Opcode == ISD::CONVERT_FROM_ARBITRARY_FP)
7725 Res = DAG.getNode(Opcode, dl, WideVT, InOp, N->getOperand(1));
7726 else
7727 Res = DAG.getNode(Opcode, dl, WideVT, InOp);
7728 }
7729 return DAG.getExtractSubvector(dl, VT, Res, 0);
7730 }
7731
7732 EVT InEltVT = InVT.getVectorElementType();
7733
7734 // Unroll the convert into some scalar code and create a nasty build vector.
7735 unsigned NumElts = VT.getVectorNumElements();
7737 if (N->isStrictFPOpcode()) {
7738 SmallVector<SDValue, 4> NewOps(N->ops());
7739 SmallVector<SDValue, 32> OpChains;
7740 for (unsigned i=0; i < NumElts; ++i) {
7741 NewOps[1] = DAG.getExtractVectorElt(dl, InEltVT, InOp, i);
7742 Ops[i] = DAG.getNode(Opcode, dl, { EltVT, MVT::Other }, NewOps);
7743 OpChains.push_back(Ops[i].getValue(1));
7744 }
7745 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OpChains);
7746 ReplaceValueWith(SDValue(N, 1), NewChain);
7747 } else {
7748 for (unsigned i = 0; i < NumElts; ++i) {
7749 SDValue Elt = DAG.getExtractVectorElt(dl, InEltVT, InOp, i);
7750 if (Opcode == ISD::FP_ROUND || Opcode == ISD::CONVERT_FROM_ARBITRARY_FP)
7751 Ops[i] = DAG.getNode(Opcode, dl, EltVT, Elt, N->getOperand(1));
7752 else
7753 Ops[i] = DAG.getNode(Opcode, dl, EltVT, Elt);
7754 }
7755 }
7756
7757 return DAG.getBuildVector(VT, dl, Ops);
7758}
7759
7760SDValue DAGTypeLegalizer::WidenVecOp_FP_TO_XINT_SAT(SDNode *N) {
7761 EVT DstVT = N->getValueType(0);
7762 SDValue Src = GetWidenedVector(N->getOperand(0));
7763 EVT SrcVT = Src.getValueType();
7764 ElementCount WideNumElts = SrcVT.getVectorElementCount();
7765 SDLoc dl(N);
7766
7767 // See if a widened result type would be legal, if so widen the node.
7768 EVT WideDstVT = EVT::getVectorVT(*DAG.getContext(),
7769 DstVT.getVectorElementType(), WideNumElts);
7770 if (TLI.isTypeLegal(WideDstVT)) {
7771 SDValue Res =
7772 DAG.getNode(N->getOpcode(), dl, WideDstVT, Src, N->getOperand(1));
7773 return DAG.getNode(
7774 ISD::EXTRACT_SUBVECTOR, dl, DstVT, Res,
7775 DAG.getConstant(0, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
7776 }
7777
7778 // Give up and unroll.
7779 return DAG.UnrollVectorOp(N);
7780}
7781
7782SDValue DAGTypeLegalizer::WidenVecOp_BITCAST(SDNode *N) {
7783 EVT VT = N->getValueType(0);
7784 SDValue InOp = GetWidenedVector(N->getOperand(0));
7785 EVT InWidenVT = InOp.getValueType();
7786 SDLoc dl(N);
7787
7788 // Check if we can convert between two legal vector types and extract.
7789 TypeSize InWidenSize = InWidenVT.getSizeInBits();
7790 TypeSize Size = VT.getSizeInBits();
7791 // x86mmx is not an acceptable vector element type, so don't try.
7792 if (!VT.isVector() && VT != MVT::x86mmx &&
7793 InWidenSize.hasKnownScalarFactor(Size)) {
7794 unsigned NewNumElts = InWidenSize.getKnownScalarFactor(Size);
7795 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), VT, NewNumElts);
7796 if (TLI.isTypeLegal(NewVT)) {
7797 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
7798 return DAG.getExtractVectorElt(dl, VT, BitOp, 0);
7799 }
7800 }
7801
7802 // Handle a case like bitcast v12i8 -> v3i32. Normally that would get widened
7803 // to v16i8 -> v4i32, but for a target where v3i32 is legal but v12i8 is not,
7804 // we end up here. Handling the case here with EXTRACT_SUBVECTOR avoids
7805 // having to copy via memory.
7806 if (VT.isVector()) {
7807 EVT EltVT = VT.getVectorElementType();
7808 unsigned EltSize = EltVT.getFixedSizeInBits();
7809 if (InWidenSize.isKnownMultipleOf(EltSize)) {
7810 ElementCount NewNumElts =
7811 (InWidenVT.getVectorElementCount() * InWidenVT.getScalarSizeInBits())
7812 .divideCoefficientBy(EltSize);
7813 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NewNumElts);
7814 if (TLI.isTypeLegal(NewVT)) {
7815 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
7816 return DAG.getExtractSubvector(dl, VT, BitOp, 0);
7817 }
7818 }
7819 }
7820
7821 return CreateStackStoreLoad(InOp, VT);
7822}
7823
7824// Vectors with sizes that are not powers of 2 need to be widened to the
7825// next largest power of 2. For example, we may get a vector of 3 32-bit
7826// integers or of 6 16-bit integers, both of which have to be widened to a
7827// 128-bit vector.
7828SDValue DAGTypeLegalizer::WidenVecOp_FAKE_USE(SDNode *N) {
7829 SDValue WidenedOp = GetWidenedVector(N->getOperand(1));
7830 return DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, N->getOperand(0),
7831 WidenedOp);
7832}
7833
7834SDValue DAGTypeLegalizer::WidenVecOp_CONCAT_VECTORS(SDNode *N) {
7835 EVT VT = N->getValueType(0);
7836 EVT EltVT = VT.getVectorElementType();
7837 EVT InVT = N->getOperand(0).getValueType();
7838 SDLoc dl(N);
7839
7840 // If the widen width for this operand is the same as the width of the concat
7841 // and all but the first operand is undef, just use the widened operand.
7842 unsigned NumOperands = N->getNumOperands();
7843 if (VT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
7844 unsigned i;
7845 for (i = 1; i < NumOperands; ++i)
7846 if (!N->getOperand(i).isUndef())
7847 break;
7848
7849 if (i == NumOperands)
7850 return GetWidenedVector(N->getOperand(0));
7851 }
7852
7853 // Otherwise, fall back to a nasty build vector.
7854 unsigned NumElts = VT.getVectorNumElements();
7856
7857 unsigned NumInElts = InVT.getVectorNumElements();
7858
7859 unsigned Idx = 0;
7860 for (unsigned i=0; i < NumOperands; ++i) {
7861 SDValue InOp = N->getOperand(i);
7862 assert(getTypeAction(InOp.getValueType()) ==
7864 "Unexpected type action");
7865 InOp = GetWidenedVector(InOp);
7866 for (unsigned j = 0; j < NumInElts; ++j)
7867 Ops[Idx++] = DAG.getExtractVectorElt(dl, EltVT, InOp, j);
7868 }
7869 return DAG.getBuildVector(VT, dl, Ops);
7870}
7871
7872SDValue DAGTypeLegalizer::WidenVecOp_INSERT_SUBVECTOR(SDNode *N) {
7873 EVT VT = N->getValueType(0);
7874 SDValue SubVec = N->getOperand(1);
7875 SDValue InVec = N->getOperand(0);
7876
7877 EVT OrigVT = SubVec.getValueType();
7878 SubVec = GetWidenedVector(SubVec);
7879 EVT SubVT = SubVec.getValueType();
7880
7881 // Whether or not all the elements of the widened SubVec will be inserted into
7882 // valid indices of VT.
7883 bool IndicesValid = false;
7884 // If we statically know that VT can fit SubVT, the indices are valid.
7885 if (VT.knownBitsGE(SubVT))
7886 IndicesValid = true;
7887 else if (VT.isScalableVector() && SubVT.isFixedLengthVector()) {
7888 // Otherwise, if we're inserting a fixed vector into a scalable vector and
7889 // we know the minimum vscale we can work out if it's valid ourselves.
7890 Attribute Attr = DAG.getMachineFunction().getFunction().getFnAttribute(
7891 Attribute::VScaleRange);
7892 if (Attr.isValid()) {
7893 unsigned VScaleMin = Attr.getVScaleRangeMin();
7894 if (VT.getSizeInBits().getKnownMinValue() * VScaleMin >=
7895 SubVT.getFixedSizeInBits())
7896 IndicesValid = true;
7897 }
7898 }
7899
7900 if (!IndicesValid)
7902 "Don't know how to widen the operands for INSERT_SUBVECTOR");
7903
7904 SDLoc DL(N);
7905
7906 // We need to make sure that the indices are still valid, otherwise we might
7907 // widen what was previously well-defined to something undefined.
7908 if (InVec.isUndef() && N->getConstantOperandVal(2) == 0)
7909 return DAG.getNode(ISD::INSERT_SUBVECTOR, DL, VT, InVec, SubVec,
7910 N->getOperand(2));
7911
7912 if (OrigVT.isScalableVector()) {
7913 // When the widened types match, overwriting the start of a vector is
7914 // effectively a merge operation that can be implement as a vselect.
7915 if (SubVT == VT && N->getConstantOperandVal(2) == 0) {
7916 SDValue Mask =
7917 DAG.getMaskFromElementCount(DL, VT, OrigVT.getVectorElementCount());
7918 return DAG.getNode(ISD::VSELECT, DL, VT, Mask, SubVec, InVec);
7919 }
7920
7921 // Fallback to inserting through memory.
7922 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
7923 SDValue StackPtr = DAG.CreateStackTemporary(VT.getStoreSize(), Alignment);
7924 MachineFunction &MF = DAG.getMachineFunction();
7925 int FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
7926 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
7927
7928 MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
7931 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
7934
7935 // Write out the vector being inserting into.
7936 SDValue Ch =
7937 DAG.getStore(DAG.getEntryNode(), DL, InVec, StackPtr, StoreMMO);
7938
7939 // Build a mask to match the length of the sub-vector.
7940 SDValue Mask =
7941 DAG.getMaskFromElementCount(DL, SubVT, OrigVT.getVectorElementCount());
7942
7943 // Overwrite the sub-vector at the required offset.
7944 SDValue SubVecPtr =
7945 TLI.getVectorSubVecPointer(DAG, StackPtr, VT, OrigVT, N->getOperand(2));
7946 Ch = DAG.getMaskedStore(Ch, DL, SubVec, SubVecPtr,
7947 DAG.getPOISON(SubVecPtr.getValueType()), Mask, VT,
7948 StoreMMO, ISD::UNINDEXED, ISD::NON_EXTLOAD);
7949
7950 // Read back the result.
7951 return DAG.getLoad(VT, DL, Ch, StackPtr, LoadMMO);
7952 }
7953
7954 // If the operands can't be widened legally, just replace the INSERT_SUBVECTOR
7955 // with a series of INSERT_VECTOR_ELT
7956 unsigned Idx = N->getConstantOperandVal(2);
7957
7958 SDValue InsertElt = InVec;
7959 for (unsigned I = 0, E = OrigVT.getVectorNumElements(); I != E; ++I) {
7960 SDValue ExtractElt =
7961 DAG.getExtractVectorElt(DL, VT.getVectorElementType(), SubVec, I);
7962 InsertElt = DAG.getInsertVectorElt(DL, InsertElt, ExtractElt, I + Idx);
7963 }
7964
7965 return InsertElt;
7966}
7967
7968SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
7969 SDValue InOp = GetWidenedVector(N->getOperand(0));
7970 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SDLoc(N),
7971 N->getValueType(0), InOp, N->getOperand(1));
7972}
7973
7974SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
7975 SDValue InOp = GetWidenedVector(N->getOperand(0));
7976 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
7977 N->getValueType(0), InOp, N->getOperand(1));
7978}
7979
7980SDValue DAGTypeLegalizer::WidenVecOp_EXTEND_VECTOR_INREG(SDNode *N) {
7981 SDLoc DL(N);
7982 EVT ResVT = N->getValueType(0);
7983
7984 // Widen the input as requested by the legalizer.
7985 SDValue WideInOp = GetWidenedVector(N->getOperand(0));
7986 EVT WideInVT = WideInOp.getValueType();
7987
7988 // Simple case: if widened input is still smaller than or equal to result,
7989 // just use it directly.
7990 if (WideInVT.getSizeInBits() <= ResVT.getSizeInBits())
7991 return DAG.getNode(N->getOpcode(), DL, ResVT, WideInOp);
7992
7993 // EXTEND_VECTOR_INREG requires input bits <= result bits.
7994 // If widening makes the input larger than the original result, widen the
7995 // result to match, then extract back down.
7996 EVT ResEltVT = ResVT.getVectorElementType();
7997 unsigned EltBits = ResEltVT.getSizeInBits();
7998 assert((WideInVT.getSizeInBits() % EltBits) == 0 &&
7999 "Widened input size must be a multiple of result element size");
8000
8001 unsigned WideNumElts = WideInVT.getSizeInBits() / EltBits;
8002 EVT WideResVT = EVT::getVectorVT(*DAG.getContext(), ResEltVT, WideNumElts);
8003
8004 SDValue WideRes = DAG.getNode(N->getOpcode(), DL, WideResVT, WideInOp);
8005 return DAG.getExtractSubvector(DL, ResVT, WideRes, 0);
8006}
8007
8008SDValue DAGTypeLegalizer::WidenVecOp_STORE(SDNode *N) {
8009 // We have to widen the value, but we want only to store the original
8010 // vector type.
8011 StoreSDNode *ST = cast<StoreSDNode>(N);
8012
8013 if (!ST->getMemoryVT().getScalarType().isByteSized())
8014 return TLI.scalarizeVectorStore(ST, DAG);
8015
8016 if (ST->isTruncatingStore())
8017 return TLI.scalarizeVectorStore(ST, DAG);
8018
8019 // Generate a vector-predicated store if it is custom/legal on the target.
8020 // To avoid possible recursion, only do this if the widened mask type is
8021 // legal.
8022 // FIXME: Not all targets may support EVL in VP_STORE. These will have been
8023 // removed from the IR by the ExpandVectorPredication pass but we're
8024 // reintroducing them here.
8025 SDValue StVal = ST->getValue();
8026 EVT StVT = StVal.getValueType();
8027 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), StVT);
8028 EVT WideMaskVT = getSetCCResultType(WideVT);
8029
8030 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
8031 TLI.isTypeLegal(WideMaskVT)) {
8032 // Widen the value.
8033 SDLoc DL(N);
8034 StVal = GetWidenedVector(StVal);
8035 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
8036 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
8037 StVT.getVectorElementCount());
8038 return DAG.getStoreVP(ST->getChain(), DL, StVal, ST->getBasePtr(),
8039 ST->getOffset(), Mask, EVL, StVT, ST->getMemOperand(),
8040 ST->getAddressingMode());
8041 }
8042
8044 if (GenWidenVectorStores(StChain, ST)) {
8045 if (StChain.size() == 1)
8046 return StChain[0];
8047
8048 return DAG.getNode(ISD::TokenFactor, SDLoc(ST), MVT::Other, StChain);
8049 }
8050
8051 if (StVT.isVector()) {
8052 // If all else fails replace the store with a wide masked store.
8053 SDLoc DL(N);
8054 SDValue WideStVal = GetWidenedVector(StVal);
8055 SDValue Mask =
8056 DAG.getMaskFromElementCount(DL, WideVT, StVT.getVectorElementCount());
8057
8058 return DAG.getMaskedStore(ST->getChain(), DL, WideStVal, ST->getBasePtr(),
8059 ST->getOffset(), Mask, ST->getMemoryVT(),
8060 ST->getMemOperand(), ST->getAddressingMode(),
8061 ST->isTruncatingStore());
8062 }
8063
8064 report_fatal_error("Unable to widen vector store");
8065}
8066
8067SDValue DAGTypeLegalizer::WidenVecOp_VP_STORE(SDNode *N, unsigned OpNo) {
8068 assert((OpNo == 1 || OpNo == 3) &&
8069 "Can widen only data or mask operand of vp_store");
8070 VPStoreSDNode *ST = cast<VPStoreSDNode>(N);
8071 SDValue Mask = ST->getMask();
8072 SDValue StVal = ST->getValue();
8073 SDLoc dl(N);
8074
8075 if (OpNo == 1) {
8076 // Widen the value.
8077 StVal = GetWidenedVector(StVal);
8078
8079 // We only handle the case where the mask needs widening to an
8080 // identically-sized type as the vector inputs.
8081 assert(getTypeAction(Mask.getValueType()) ==
8083 "Unable to widen VP store");
8084 Mask = GetWidenedVector(Mask);
8085 } else {
8086 Mask = GetWidenedVector(Mask);
8087
8088 // We only handle the case where the stored value needs widening to an
8089 // identically-sized type as the mask.
8090 assert(getTypeAction(StVal.getValueType()) ==
8092 "Unable to widen VP store");
8093 StVal = GetWidenedVector(StVal);
8094 }
8095
8096 assert(Mask.getValueType().getVectorElementCount() ==
8098 "Mask and data vectors should have the same number of elements");
8099 return DAG.getStoreVP(ST->getChain(), dl, StVal, ST->getBasePtr(),
8100 ST->getOffset(), Mask, ST->getVectorLength(),
8101 ST->getMemoryVT(), ST->getMemOperand(),
8102 ST->getAddressingMode(), ST->isTruncatingStore(),
8103 ST->isCompressingStore());
8104}
8105
8106SDValue DAGTypeLegalizer::WidenVecOp_VP_STRIDED_STORE(SDNode *N,
8107 unsigned OpNo) {
8108 assert((OpNo == 1 || OpNo == 4) &&
8109 "Can widen only data or mask operand of vp_strided_store");
8110 VPStridedStoreSDNode *SST = cast<VPStridedStoreSDNode>(N);
8111 SDValue Mask = SST->getMask();
8112 SDValue StVal = SST->getValue();
8113 SDLoc DL(N);
8114
8115 if (OpNo == 1)
8116 assert(getTypeAction(Mask.getValueType()) ==
8118 "Unable to widen VP strided store");
8119 else
8120 assert(getTypeAction(StVal.getValueType()) ==
8122 "Unable to widen VP strided store");
8123
8124 StVal = GetWidenedVector(StVal);
8125 Mask = GetWidenedVector(Mask);
8126
8128 Mask.getValueType().getVectorElementCount() &&
8129 "Data and mask vectors should have the same number of elements");
8130
8131 return DAG.getStridedStoreVP(
8132 SST->getChain(), DL, StVal, SST->getBasePtr(), SST->getOffset(),
8133 SST->getStride(), Mask, SST->getVectorLength(), SST->getMemoryVT(),
8134 SST->getMemOperand(), SST->getAddressingMode(), SST->isTruncatingStore(),
8135 SST->isCompressingStore());
8136}
8137
8138SDValue DAGTypeLegalizer::WidenVecOp_MSTORE(SDNode *N, unsigned OpNo) {
8139 assert((OpNo == 1 || OpNo == 4) &&
8140 "Can widen only data or mask operand of mstore");
8141 MaskedStoreSDNode *MST = cast<MaskedStoreSDNode>(N);
8142 SDValue Mask = MST->getMask();
8143 EVT MaskVT = Mask.getValueType();
8144 SDValue StVal = MST->getValue();
8145 EVT VT = StVal.getValueType();
8146 SDLoc dl(N);
8147
8148 EVT WideVT, WideMaskVT;
8149 if (OpNo == 1) {
8150 // Widen the value.
8151 StVal = GetWidenedVector(StVal);
8152
8153 WideVT = StVal.getValueType();
8154 WideMaskVT =
8155 EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(),
8156 WideVT.getVectorElementCount());
8157 } else {
8158 WideMaskVT = TLI.getTypeToTransformTo(*DAG.getContext(), MaskVT);
8159
8160 EVT ValueVT = StVal.getValueType();
8161 WideVT = EVT::getVectorVT(*DAG.getContext(), ValueVT.getVectorElementType(),
8162 WideMaskVT.getVectorElementCount());
8163 }
8164
8165 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
8166 TLI.isTypeLegal(WideMaskVT) && !MST->isCompressingStore()) {
8167 Mask = DAG.getInsertSubvector(dl, DAG.getPOISON(WideMaskVT), Mask, 0);
8168 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8170 return DAG.getStoreVP(MST->getChain(), dl, StVal, MST->getBasePtr(),
8171 MST->getOffset(), Mask, EVL, MST->getMemoryVT(),
8172 MST->getMemOperand(), MST->getAddressingMode());
8173 }
8174
8175 if (OpNo == 1) {
8176 // The mask should be widened as well.
8177 Mask = ModifyToType(Mask, WideMaskVT, true);
8178 } else {
8179 // Widen the mask.
8180 Mask = ModifyToType(Mask, WideMaskVT, true);
8181
8182 StVal = ModifyToType(StVal, WideVT);
8183 }
8184
8185 assert(Mask.getValueType().getVectorElementCount() ==
8187 "Mask and data vectors should have the same number of elements");
8188 return DAG.getMaskedStore(MST->getChain(), dl, StVal, MST->getBasePtr(),
8189 MST->getOffset(), Mask, MST->getMemoryVT(),
8190 MST->getMemOperand(), MST->getAddressingMode(),
8191 false, MST->isCompressingStore());
8192}
8193
8194SDValue DAGTypeLegalizer::WidenVecOp_MGATHER(SDNode *N, unsigned OpNo) {
8195 assert(OpNo == 4 && "Can widen only the index of mgather");
8196 auto *MG = cast<MaskedGatherSDNode>(N);
8197 SDValue DataOp = MG->getPassThru();
8198 SDValue Mask = MG->getMask();
8199 SDValue Scale = MG->getScale();
8200
8201 // Just widen the index. It's allowed to have extra elements.
8202 SDValue Index = GetWidenedVector(MG->getIndex());
8203
8204 SDLoc dl(N);
8205 SDValue Ops[] = {MG->getChain(), DataOp, Mask, MG->getBasePtr(), Index,
8206 Scale};
8207 SDValue Res = DAG.getMaskedGather(MG->getVTList(), MG->getMemoryVT(), dl, Ops,
8208 MG->getMemOperand(), MG->getIndexType(),
8209 MG->getExtensionType());
8210 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
8211 ReplaceValueWith(SDValue(N, 0), Res.getValue(0));
8212 return SDValue();
8213}
8214
8215SDValue DAGTypeLegalizer::WidenVecOp_MSCATTER(SDNode *N, unsigned OpNo) {
8216 MaskedScatterSDNode *MSC = cast<MaskedScatterSDNode>(N);
8217 SDValue DataOp = MSC->getValue();
8218 SDValue Mask = MSC->getMask();
8219 SDValue Index = MSC->getIndex();
8220 SDValue Scale = MSC->getScale();
8221 EVT WideMemVT = MSC->getMemoryVT();
8222
8223 if (OpNo == 1) {
8224 DataOp = GetWidenedVector(DataOp);
8225 unsigned NumElts = DataOp.getValueType().getVectorNumElements();
8226
8227 // Widen index.
8228 EVT IndexVT = Index.getValueType();
8229 EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
8230 IndexVT.getVectorElementType(), NumElts);
8231 Index = ModifyToType(Index, WideIndexVT);
8232
8233 // The mask should be widened as well.
8234 EVT MaskVT = Mask.getValueType();
8235 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
8236 MaskVT.getVectorElementType(), NumElts);
8237 Mask = ModifyToType(Mask, WideMaskVT, true);
8238
8239 // Widen the MemoryType
8240 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
8241 MSC->getMemoryVT().getScalarType(), NumElts);
8242 } else if (OpNo == 4) {
8243 // Just widen the index. It's allowed to have extra elements.
8244 Index = GetWidenedVector(Index);
8245 } else
8246 llvm_unreachable("Can't widen this operand of mscatter");
8247
8248 SDValue Ops[] = {MSC->getChain(), DataOp, Mask, MSC->getBasePtr(), Index,
8249 Scale};
8250 return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N),
8251 Ops, MSC->getMemOperand(), MSC->getIndexType(),
8252 MSC->isTruncatingStore());
8253}
8254
8255SDValue DAGTypeLegalizer::WidenVecOp_VP_SCATTER(SDNode *N, unsigned OpNo) {
8256 VPScatterSDNode *VPSC = cast<VPScatterSDNode>(N);
8257 SDValue DataOp = VPSC->getValue();
8258 SDValue Mask = VPSC->getMask();
8259 SDValue Index = VPSC->getIndex();
8260 SDValue Scale = VPSC->getScale();
8261 EVT WideMemVT = VPSC->getMemoryVT();
8262
8263 if (OpNo == 1) {
8264 DataOp = GetWidenedVector(DataOp);
8265 Index = GetWidenedVector(Index);
8266 const auto WideEC = DataOp.getValueType().getVectorElementCount();
8267 Mask = GetWidenedMask(Mask, WideEC);
8268 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
8269 VPSC->getMemoryVT().getScalarType(), WideEC);
8270 } else if (OpNo == 3) {
8271 // Just widen the index. It's allowed to have extra elements.
8272 Index = GetWidenedVector(Index);
8273 } else
8274 llvm_unreachable("Can't widen this operand of VP_SCATTER");
8275
8276 SDValue Ops[] = {
8277 VPSC->getChain(), DataOp, VPSC->getBasePtr(), Index, Scale, Mask,
8278 VPSC->getVectorLength()};
8279 return DAG.getScatterVP(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N), Ops,
8280 VPSC->getMemOperand(), VPSC->getIndexType());
8281}
8282
8283SDValue DAGTypeLegalizer::WidenVecOp_SETCC(SDNode *N) {
8284 SDValue InOp0 = GetWidenedVector(N->getOperand(0));
8285 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
8286 SDLoc dl(N);
8287 EVT VT = N->getValueType(0);
8288
8289 // WARNING: In this code we widen the compare instruction with garbage.
8290 // This garbage may contain denormal floats which may be slow. Is this a real
8291 // concern ? Should we zero the unused lanes if this is a float compare ?
8292
8293 // Get a new SETCC node to compare the newly widened operands.
8294 // Only some of the compared elements are legal.
8295 EVT SVT = getSetCCResultType(InOp0.getValueType());
8296 // The result type is legal, if its vXi1, keep vXi1 for the new SETCC.
8297 if (VT.getScalarType() == MVT::i1)
8298 SVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8299 SVT.getVectorElementCount());
8300
8301 SDValue WideSETCC = DAG.getNode(ISD::SETCC, SDLoc(N),
8302 SVT, InOp0, InOp1, N->getOperand(2));
8303
8304 // Extract the needed results from the result vector.
8305 EVT ResVT = EVT::getVectorVT(*DAG.getContext(),
8308 SDValue CC = DAG.getExtractSubvector(dl, ResVT, WideSETCC, 0);
8309
8310 EVT OpVT = N->getOperand(0).getValueType();
8311 ISD::NodeType ExtendCode =
8312 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
8313 return DAG.getNode(ExtendCode, dl, VT, CC);
8314}
8315
8316SDValue DAGTypeLegalizer::WidenVecOp_STRICT_FSETCC(SDNode *N) {
8317 SDValue Chain = N->getOperand(0);
8318 SDValue LHS = GetWidenedVector(N->getOperand(1));
8319 SDValue RHS = GetWidenedVector(N->getOperand(2));
8320 SDValue CC = N->getOperand(3);
8321 SDLoc dl(N);
8322
8323 EVT VT = N->getValueType(0);
8324 EVT EltVT = VT.getVectorElementType();
8325 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
8326 unsigned NumElts = VT.getVectorNumElements();
8327
8328 // Unroll into a build vector.
8329 SmallVector<SDValue, 8> Scalars(NumElts);
8330 SmallVector<SDValue, 8> Chains(NumElts);
8331
8332 for (unsigned i = 0; i != NumElts; ++i) {
8333 SDValue LHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, LHS, i);
8334 SDValue RHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, RHS, i);
8335
8336 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
8337 {Chain, LHSElem, RHSElem, CC});
8338 Chains[i] = Scalars[i].getValue(1);
8339 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
8340 DAG.getBoolConstant(true, dl, EltVT, VT),
8341 DAG.getBoolConstant(false, dl, EltVT, VT));
8342 }
8343
8344 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
8345 ReplaceValueWith(SDValue(N, 1), NewChain);
8346
8347 return DAG.getBuildVector(VT, dl, Scalars);
8348}
8349
8350static unsigned getExtendForIntVecReduction(unsigned Opc) {
8351 switch (Opc) {
8352 default:
8353 llvm_unreachable("Expected integer vector reduction");
8354 case ISD::VECREDUCE_ADD:
8355 case ISD::VECREDUCE_MUL:
8356 case ISD::VECREDUCE_AND:
8357 case ISD::VECREDUCE_OR:
8358 case ISD::VECREDUCE_XOR:
8359 return ISD::ANY_EXTEND;
8362 return ISD::SIGN_EXTEND;
8365 return ISD::ZERO_EXTEND;
8366 }
8367}
8368
8369SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE(SDNode *N) {
8370 SDLoc dl(N);
8371 SDValue Op = GetWidenedVector(N->getOperand(0));
8372 EVT VT = N->getValueType(0);
8373 EVT OrigVT = N->getOperand(0).getValueType();
8374 EVT WideVT = Op.getValueType();
8375 EVT ElemVT = OrigVT.getVectorElementType();
8376 SDNodeFlags Flags = N->getFlags();
8377
8378 unsigned Opc = N->getOpcode();
8379 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
8380 SDValue NeutralElem = DAG.getIdentityElement(BaseOpc, dl, ElemVT, Flags);
8381 assert(NeutralElem && "Neutral element must exist");
8382
8383 // Pad the vector with the neutral element.
8384 unsigned OrigElts = OrigVT.getVectorMinNumElements();
8385 unsigned WideElts = WideVT.getVectorMinNumElements();
8386
8387 // Generate a vp.reduce_op if it is custom/legal for the target. This avoids
8388 // needing to pad the source vector, because the inactive lanes can simply be
8389 // disabled and not contribute to the result.
8390 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opc);
8391 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WideVT)) {
8392 SDValue Start = NeutralElem;
8393 if (VT.isInteger())
8394 Start = DAG.getNode(getExtendForIntVecReduction(Opc), dl, VT, Start);
8395 assert(Start.getValueType() == VT);
8396 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8397 WideVT.getVectorElementCount());
8398 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
8399 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8400 OrigVT.getVectorElementCount());
8401 return DAG.getNode(*VPOpcode, dl, VT, {Start, Op, Mask, EVL}, Flags);
8402 }
8403
8404 if (WideVT.isScalableVector()) {
8405 unsigned GCD = std::gcd(OrigElts, WideElts);
8406 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
8408 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
8409 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
8410 Op = DAG.getInsertSubvector(dl, Op, SplatNeutral, Idx);
8411 return DAG.getNode(Opc, dl, VT, Op, Flags);
8412 }
8413
8414 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
8415 Op = DAG.getInsertVectorElt(dl, Op, NeutralElem, Idx);
8416
8417 return DAG.getNode(Opc, dl, VT, Op, Flags);
8418}
8419
8420SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE_SEQ(SDNode *N) {
8421 SDLoc dl(N);
8422 SDValue AccOp = N->getOperand(0);
8423 SDValue VecOp = N->getOperand(1);
8424 SDValue Op = GetWidenedVector(VecOp);
8425
8426 EVT VT = N->getValueType(0);
8427 EVT OrigVT = VecOp.getValueType();
8428 EVT WideVT = Op.getValueType();
8429 EVT ElemVT = OrigVT.getVectorElementType();
8430 SDNodeFlags Flags = N->getFlags();
8431
8432 unsigned Opc = N->getOpcode();
8433 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
8434 SDValue NeutralElem = DAG.getIdentityElement(BaseOpc, dl, ElemVT, Flags);
8435
8436 // Pad the vector with the neutral element.
8437 unsigned OrigElts = OrigVT.getVectorMinNumElements();
8438 unsigned WideElts = WideVT.getVectorMinNumElements();
8439
8440 // Generate a vp.reduce_op if it is custom/legal for the target. This avoids
8441 // needing to pad the source vector, because the inactive lanes can simply be
8442 // disabled and not contribute to the result.
8443 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opc);
8444 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WideVT)) {
8445 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8446 WideVT.getVectorElementCount());
8447 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
8448 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8449 OrigVT.getVectorElementCount());
8450 return DAG.getNode(*VPOpcode, dl, VT, {AccOp, Op, Mask, EVL}, Flags);
8451 }
8452
8453 if (WideVT.isScalableVector()) {
8454 unsigned GCD = std::gcd(OrigElts, WideElts);
8455 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
8457 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
8458 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
8459 Op = DAG.getInsertSubvector(dl, Op, SplatNeutral, Idx);
8460 return DAG.getNode(Opc, dl, VT, AccOp, Op, Flags);
8461 }
8462
8463 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
8464 Op = DAG.getInsertVectorElt(dl, Op, NeutralElem, Idx);
8465
8466 return DAG.getNode(Opc, dl, VT, AccOp, Op, Flags);
8467}
8468
8469SDValue DAGTypeLegalizer::WidenVecOp_VP_REDUCE(SDNode *N) {
8470 assert(N->isVPOpcode() && "Expected VP opcode");
8471
8472 SDLoc dl(N);
8473 SDValue Op = GetWidenedVector(N->getOperand(1));
8474 SDValue Mask = GetWidenedMask(N->getOperand(2),
8475 Op.getValueType().getVectorElementCount());
8476
8477 return DAG.getNode(N->getOpcode(), dl, N->getValueType(0),
8478 {N->getOperand(0), Op, Mask, N->getOperand(3)},
8479 N->getFlags());
8480}
8481
8482SDValue DAGTypeLegalizer::WidenVecOp_VSELECT(SDNode *N) {
8483 // This only gets called in the case that the left and right inputs and
8484 // result are of a legal odd vector type, and the condition is illegal i1 of
8485 // the same odd width that needs widening.
8486 EVT VT = N->getValueType(0);
8487 assert(VT.isVector() && !VT.isPow2VectorType() && isTypeLegal(VT));
8488
8489 SDValue Cond = GetWidenedVector(N->getOperand(0));
8490 SDValue LeftIn = DAG.WidenVector(N->getOperand(1), SDLoc(N));
8491 SDValue RightIn = DAG.WidenVector(N->getOperand(2), SDLoc(N));
8492 SDLoc DL(N);
8493
8494 SDValue Select = DAG.getNode(N->getOpcode(), DL, LeftIn.getValueType(), Cond,
8495 LeftIn, RightIn);
8496 return DAG.getExtractSubvector(DL, VT, Select, 0);
8497}
8498
8499SDValue DAGTypeLegalizer::WidenVecOp_VP_CttzElements(SDNode *N) {
8500 SDLoc DL(N);
8501 SDValue Source = GetWidenedVector(N->getOperand(0));
8502 EVT SrcVT = Source.getValueType();
8503 SDValue Mask =
8504 GetWidenedMask(N->getOperand(1), SrcVT.getVectorElementCount());
8505
8506 return DAG.getNode(N->getOpcode(), DL, N->getValueType(0),
8507 {Source, Mask, N->getOperand(2)}, N->getFlags());
8508}
8509
8510SDValue DAGTypeLegalizer::WidenVecOp_VECTOR_FIND_LAST_ACTIVE(SDNode *N) {
8511 SDLoc DL(N);
8512 SDValue Mask = N->getOperand(0);
8513 EVT OrigMaskVT = Mask.getValueType();
8514 SDValue WideMask = GetWidenedVector(Mask);
8515 EVT WideMaskVT = WideMask.getValueType();
8516
8517 // Pad the mask with zeros to ensure inactive lanes don't affect the result.
8518 unsigned OrigElts = OrigMaskVT.getVectorNumElements();
8519 unsigned WideElts = WideMaskVT.getVectorNumElements();
8520 if (OrigElts != WideElts) {
8521 SDValue ZeroMask = DAG.getConstant(0, DL, WideMaskVT);
8522 WideMask = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideMaskVT, ZeroMask,
8523 Mask, DAG.getVectorIdxConstant(0, DL));
8524 }
8525
8526 return DAG.getNode(ISD::VECTOR_FIND_LAST_ACTIVE, DL, N->getValueType(0),
8527 WideMask);
8528}
8529
8530//===----------------------------------------------------------------------===//
8531// Vector Widening Utilities
8532//===----------------------------------------------------------------------===//
8533
8534// Utility function to find the type to chop up a widen vector for load/store
8535// TLI: Target lowering used to determine legal types.
8536// Width: Width left need to load/store.
8537// WidenVT: The widen vector type to load to/store from
8538// Align: If 0, don't allow use of a wider type
8539// WidenEx: If Align is not 0, the amount additional we can load/store from.
8540
8541static std::optional<EVT> findMemType(SelectionDAG &DAG,
8542 const TargetLowering &TLI, unsigned Width,
8543 EVT WidenVT, unsigned Align = 0,
8544 unsigned WidenEx = 0) {
8545 EVT WidenEltVT = WidenVT.getVectorElementType();
8546 const bool Scalable = WidenVT.isScalableVector();
8547 unsigned WidenWidth = WidenVT.getSizeInBits().getKnownMinValue();
8548 unsigned WidenEltWidth = WidenEltVT.getSizeInBits();
8549 unsigned AlignInBits = Align*8;
8550
8551 EVT RetVT = WidenEltVT;
8552 // Don't bother looking for an integer type if the vector is scalable, skip
8553 // to vector types.
8554 if (!Scalable) {
8555 // If we have one element to load/store, return it.
8556 if (Width == WidenEltWidth)
8557 return RetVT;
8558
8559 // See if there is larger legal integer than the element type to load/store.
8560 for (EVT MemVT : reverse(MVT::integer_valuetypes())) {
8561 unsigned MemVTWidth = MemVT.getSizeInBits();
8562 if (MemVT.getSizeInBits() <= WidenEltWidth)
8563 break;
8564 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
8565 if ((Action == TargetLowering::TypeLegal ||
8567 (WidenWidth % MemVTWidth) == 0 &&
8568 isPowerOf2_32(WidenWidth / MemVTWidth) &&
8569 (MemVTWidth <= Width ||
8570 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
8571 if (MemVTWidth == WidenWidth)
8572 return MemVT;
8573 RetVT = MemVT;
8574 break;
8575 }
8576 }
8577 }
8578
8579 // See if there is a larger vector type to load/store that has the same vector
8580 // element type and is evenly divisible with the WidenVT.
8581 for (EVT MemVT : reverse(MVT::vector_valuetypes())) {
8582 // Skip vector MVTs which don't match the scalable property of WidenVT.
8583 if (Scalable != MemVT.isScalableVector())
8584 continue;
8585 unsigned MemVTWidth = MemVT.getSizeInBits().getKnownMinValue();
8586 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
8587 if ((Action == TargetLowering::TypeLegal ||
8589 WidenEltVT == MemVT.getVectorElementType() &&
8590 (WidenWidth % MemVTWidth) == 0 &&
8591 isPowerOf2_32(WidenWidth / MemVTWidth) &&
8592 (MemVTWidth <= Width ||
8593 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
8594 if (RetVT.getFixedSizeInBits() < MemVTWidth || MemVT == WidenVT)
8595 return MemVT;
8596 }
8597 }
8598
8599 // Using element-wise loads and stores for widening operations is not
8600 // supported for scalable vectors
8601 if (Scalable)
8602 return std::nullopt;
8603
8604 return RetVT;
8605}
8606
8607// Builds a vector type from scalar loads
8608// VecTy: Resulting Vector type
8609// LDOps: Load operators to build a vector type
8610// [Start,End) the list of loads to use.
8613 unsigned Start, unsigned End) {
8614 SDLoc dl(LdOps[Start]);
8615 EVT LdTy = LdOps[Start].getValueType();
8616 unsigned Width = VecTy.getSizeInBits();
8617 unsigned NumElts = Width / LdTy.getSizeInBits();
8618 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), LdTy, NumElts);
8619
8620 unsigned Idx = 1;
8621 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT,LdOps[Start]);
8622
8623 for (unsigned i = Start + 1; i != End; ++i) {
8624 EVT NewLdTy = LdOps[i].getValueType();
8625 if (NewLdTy != LdTy) {
8626 NumElts = Width / NewLdTy.getSizeInBits();
8627 NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewLdTy, NumElts);
8628 VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, VecOp);
8629 // Readjust position and vector position based on new load type.
8630 Idx = Idx * LdTy.getSizeInBits() / NewLdTy.getSizeInBits();
8631 LdTy = NewLdTy;
8632 }
8633 VecOp = DAG.getInsertVectorElt(dl, VecOp, LdOps[i], Idx++);
8634 }
8635 return DAG.getNode(ISD::BITCAST, dl, VecTy, VecOp);
8636}
8637
8638SDValue DAGTypeLegalizer::GenWidenVectorLoads(SmallVectorImpl<SDValue> &LdChain,
8639 LoadSDNode *LD) {
8640 // The strategy assumes that we can efficiently load power-of-two widths.
8641 // The routine chops the vector into the largest vector loads with the same
8642 // element type or scalar loads and then recombines it to the widen vector
8643 // type.
8644 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
8645 EVT LdVT = LD->getMemoryVT();
8646 SDLoc dl(LD);
8647 assert(LdVT.isVector() && WidenVT.isVector());
8648 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
8650
8651 // Load information
8652 SDValue Chain = LD->getChain();
8653 SDValue BasePtr = LD->getBasePtr();
8654 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
8655 AAMDNodes AAInfo = LD->getAAInfo();
8656
8657 TypeSize LdWidth = LdVT.getSizeInBits();
8658 TypeSize WidenWidth = WidenVT.getSizeInBits();
8659 TypeSize WidthDiff = WidenWidth - LdWidth;
8660 // Allow wider loads if they are sufficiently aligned to avoid memory faults
8661 // and if the original load is simple.
8662 unsigned LdAlign =
8663 (!LD->isSimple() || LdVT.isScalableVector()) ? 0 : LD->getAlign().value();
8664
8665 // Find the vector type that can load from.
8666 std::optional<EVT> FirstVT =
8667 findMemType(DAG, TLI, LdWidth.getKnownMinValue(), WidenVT, LdAlign,
8668 WidthDiff.getKnownMinValue());
8669
8670 if (!FirstVT)
8671 return SDValue();
8672
8673 SmallVector<EVT, 8> MemVTs;
8674 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
8675
8676 // Unless we're able to load in one instruction we must work out how to load
8677 // the remainder.
8678 if (!TypeSize::isKnownLE(LdWidth, FirstVTWidth)) {
8679 std::optional<EVT> NewVT = FirstVT;
8680 TypeSize RemainingWidth = LdWidth;
8681 TypeSize NewVTWidth = FirstVTWidth;
8682 do {
8683 RemainingWidth -= NewVTWidth;
8684 if (TypeSize::isKnownLT(RemainingWidth, NewVTWidth)) {
8685 // The current type we are using is too large. Find a better size.
8686 NewVT = findMemType(DAG, TLI, RemainingWidth.getKnownMinValue(),
8687 WidenVT, LdAlign, WidthDiff.getKnownMinValue());
8688 if (!NewVT)
8689 return SDValue();
8690 NewVTWidth = NewVT->getSizeInBits();
8691 }
8692 MemVTs.push_back(*NewVT);
8693 } while (TypeSize::isKnownGT(RemainingWidth, NewVTWidth));
8694 }
8695
8696 SDValue LdOp = DAG.getLoad(*FirstVT, dl, Chain, BasePtr, LD->getPointerInfo(),
8697 LD->getBaseAlign(), MMOFlags, AAInfo);
8698 LdChain.push_back(LdOp.getValue(1));
8699
8700 // Check if we can load the element with one instruction.
8701 if (MemVTs.empty())
8702 return coerceLoadedValue(LdOp, *FirstVT, WidenVT, LdWidth, FirstVTWidth, dl,
8703 DAG);
8704
8705 // Load vector by using multiple loads from largest vector to scalar.
8707 LdOps.push_back(LdOp);
8708
8709 uint64_t ScaledOffset = 0;
8710 MachinePointerInfo MPI = LD->getPointerInfo();
8711
8712 // First incremement past the first load.
8713 IncrementPointer(cast<LoadSDNode>(LdOp), *FirstVT, MPI, BasePtr,
8714 &ScaledOffset);
8715
8716 for (EVT MemVT : MemVTs) {
8717 Align NewAlign = ScaledOffset == 0
8718 ? LD->getBaseAlign()
8719 : commonAlignment(LD->getAlign(), ScaledOffset);
8720 SDValue L =
8721 DAG.getLoad(MemVT, dl, Chain, BasePtr, MPI, NewAlign, MMOFlags, AAInfo);
8722
8723 LdOps.push_back(L);
8724 LdChain.push_back(L.getValue(1));
8725 IncrementPointer(cast<LoadSDNode>(L), MemVT, MPI, BasePtr, &ScaledOffset);
8726 }
8727
8728 // Build the vector from the load operations.
8729 unsigned End = LdOps.size();
8730 if (!LdOps[0].getValueType().isVector())
8731 // All the loads are scalar loads.
8732 return BuildVectorFromScalar(DAG, WidenVT, LdOps, 0, End);
8733
8734 // If the load contains vectors, build the vector using concat vector.
8735 // All of the vectors used to load are power-of-2, and the scalar loads can be
8736 // combined to make a power-of-2 vector.
8737 SmallVector<SDValue, 16> ConcatOps(End);
8738 int i = End - 1;
8739 int Idx = End;
8740 EVT LdTy = LdOps[i].getValueType();
8741 // First, combine the scalar loads to a vector.
8742 if (!LdTy.isVector()) {
8743 for (--i; i >= 0; --i) {
8744 LdTy = LdOps[i].getValueType();
8745 if (LdTy.isVector())
8746 break;
8747 }
8748 ConcatOps[--Idx] = BuildVectorFromScalar(DAG, LdTy, LdOps, i + 1, End);
8749 }
8750
8751 ConcatOps[--Idx] = LdOps[i];
8752 for (--i; i >= 0; --i) {
8753 EVT NewLdTy = LdOps[i].getValueType();
8754 if (NewLdTy != LdTy) {
8755 // Create a larger vector.
8756 TypeSize LdTySize = LdTy.getSizeInBits();
8757 TypeSize NewLdTySize = NewLdTy.getSizeInBits();
8758 assert(NewLdTySize.isScalable() == LdTySize.isScalable() &&
8759 NewLdTySize.isKnownMultipleOf(LdTySize.getKnownMinValue()));
8760 unsigned NumOps =
8761 NewLdTySize.getKnownMinValue() / LdTySize.getKnownMinValue();
8763 unsigned j = 0;
8764 for (; j != End-Idx; ++j)
8765 WidenOps[j] = ConcatOps[Idx+j];
8766 for (; j != NumOps; ++j)
8767 WidenOps[j] = DAG.getPOISON(LdTy);
8768
8769 ConcatOps[End-1] = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewLdTy,
8770 WidenOps);
8771 Idx = End - 1;
8772 LdTy = NewLdTy;
8773 }
8774 ConcatOps[--Idx] = LdOps[i];
8775 }
8776
8777 if (WidenWidth == LdTy.getSizeInBits() * (End - Idx))
8778 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
8779 ArrayRef(&ConcatOps[Idx], End - Idx));
8780
8781 // We need to fill the rest with undefs to build the vector.
8782 unsigned NumOps =
8783 WidenWidth.getKnownMinValue() / LdTy.getSizeInBits().getKnownMinValue();
8785 SDValue UndefVal = DAG.getPOISON(LdTy);
8786 {
8787 unsigned i = 0;
8788 for (; i != End-Idx; ++i)
8789 WidenOps[i] = ConcatOps[Idx+i];
8790 for (; i != NumOps; ++i)
8791 WidenOps[i] = UndefVal;
8792 }
8793 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, WidenOps);
8794}
8795
8796SDValue
8797DAGTypeLegalizer::GenWidenVectorExtLoads(SmallVectorImpl<SDValue> &LdChain,
8798 LoadSDNode *LD,
8799 ISD::LoadExtType ExtType) {
8800 // For extension loads, it may not be more efficient to chop up the vector
8801 // and then extend it. Instead, we unroll the load and build a new vector.
8802 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
8803 EVT LdVT = LD->getMemoryVT();
8804 SDLoc dl(LD);
8805 assert(LdVT.isVector() && WidenVT.isVector());
8806 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
8807
8808 // Load information
8809 SDValue Chain = LD->getChain();
8810 SDValue BasePtr = LD->getBasePtr();
8811 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
8812 AAMDNodes AAInfo = LD->getAAInfo();
8813
8814 if (LdVT.isScalableVector())
8815 return SDValue();
8816
8817 EVT EltVT = WidenVT.getVectorElementType();
8818 EVT LdEltVT = LdVT.getVectorElementType();
8819 unsigned NumElts = LdVT.getVectorNumElements();
8820
8821 // Load each element and widen.
8822 unsigned WidenNumElts = WidenVT.getVectorNumElements();
8823 SmallVector<SDValue, 16> Ops(WidenNumElts);
8824 unsigned Increment = LdEltVT.getSizeInBits() / 8;
8825 Ops[0] =
8826 DAG.getExtLoad(ExtType, dl, EltVT, Chain, BasePtr, LD->getPointerInfo(),
8827 LdEltVT, LD->getBaseAlign(), MMOFlags, AAInfo);
8828 LdChain.push_back(Ops[0].getValue(1));
8829 unsigned i = 0, Offset = Increment;
8830 for (i=1; i < NumElts; ++i, Offset += Increment) {
8831 SDValue NewBasePtr =
8832 DAG.getObjectPtrOffset(dl, BasePtr, TypeSize::getFixed(Offset));
8833 Ops[i] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, NewBasePtr,
8834 LD->getPointerInfo().getWithOffset(Offset), LdEltVT,
8835 LD->getBaseAlign(), MMOFlags, AAInfo);
8836 LdChain.push_back(Ops[i].getValue(1));
8837 }
8838
8839 // Fill the rest with undefs.
8840 SDValue UndefVal = DAG.getPOISON(EltVT);
8841 for (; i != WidenNumElts; ++i)
8842 Ops[i] = UndefVal;
8843
8844 return DAG.getBuildVector(WidenVT, dl, Ops);
8845}
8846
8847bool DAGTypeLegalizer::GenWidenVectorStores(SmallVectorImpl<SDValue> &StChain,
8848 StoreSDNode *ST) {
8849 // The strategy assumes that we can efficiently store power-of-two widths.
8850 // The routine chops the vector into the largest vector stores with the same
8851 // element type or scalar stores.
8852 SDValue Chain = ST->getChain();
8853 SDValue BasePtr = ST->getBasePtr();
8854 MachineMemOperand::Flags MMOFlags = ST->getMemOperand()->getFlags();
8855 AAMDNodes AAInfo = ST->getAAInfo();
8856 SDValue ValOp = GetWidenedVector(ST->getValue());
8857 SDLoc dl(ST);
8858
8859 EVT StVT = ST->getMemoryVT();
8860 TypeSize StWidth = StVT.getSizeInBits();
8861 EVT ValVT = ValOp.getValueType();
8862 TypeSize ValWidth = ValVT.getSizeInBits();
8863 EVT ValEltVT = ValVT.getVectorElementType();
8864 unsigned ValEltWidth = ValEltVT.getFixedSizeInBits();
8865 assert(StVT.getVectorElementType() == ValEltVT);
8866 assert(StVT.isScalableVector() == ValVT.isScalableVector() &&
8867 "Mismatch between store and value types");
8868
8869 int Idx = 0; // current index to store
8870
8871 MachinePointerInfo MPI = ST->getPointerInfo();
8872 uint64_t ScaledOffset = 0;
8873
8874 // A breakdown of how to widen this vector store. Each element of the vector
8875 // is a memory VT combined with the number of times it is to be stored to,
8876 // e,g., v5i32 -> {{v2i32,2},{i32,1}}
8878
8879 while (StWidth.isNonZero()) {
8880 // Find the largest vector type we can store with.
8881 std::optional<EVT> NewVT =
8882 findMemType(DAG, TLI, StWidth.getKnownMinValue(), ValVT);
8883 if (!NewVT)
8884 return false;
8885 MemVTs.push_back({*NewVT, 0});
8886 TypeSize NewVTWidth = NewVT->getSizeInBits();
8887
8888 do {
8889 StWidth -= NewVTWidth;
8890 MemVTs.back().second++;
8891 } while (StWidth.isNonZero() && TypeSize::isKnownGE(StWidth, NewVTWidth));
8892 }
8893
8894 for (const auto &Pair : MemVTs) {
8895 EVT NewVT = Pair.first;
8896 unsigned Count = Pair.second;
8897 TypeSize NewVTWidth = NewVT.getSizeInBits();
8898
8899 if (NewVT.isVector()) {
8900 unsigned NumVTElts = NewVT.getVectorMinNumElements();
8901 do {
8902 Align NewAlign = ScaledOffset == 0
8903 ? ST->getBaseAlign()
8904 : commonAlignment(ST->getAlign(), ScaledOffset);
8905 SDValue EOp = DAG.getExtractSubvector(dl, NewVT, ValOp, Idx);
8906 SDValue PartStore = DAG.getStore(Chain, dl, EOp, BasePtr, MPI, NewAlign,
8907 MMOFlags, AAInfo);
8908 StChain.push_back(PartStore);
8909
8910 Idx += NumVTElts;
8911 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr,
8912 &ScaledOffset);
8913 } while (--Count);
8914 } else {
8915 // Cast the vector to the scalar type we can store.
8916 unsigned NumElts = ValWidth.getFixedValue() / NewVTWidth.getFixedValue();
8917 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewVT, NumElts);
8918 SDValue VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, ValOp);
8919 // Readjust index position based on new vector type.
8920 Idx = Idx * ValEltWidth / NewVTWidth.getFixedValue();
8921 do {
8922 SDValue EOp = DAG.getExtractVectorElt(dl, NewVT, VecOp, Idx++);
8923 SDValue PartStore = DAG.getStore(Chain, dl, EOp, BasePtr, MPI,
8924 ST->getBaseAlign(), MMOFlags, AAInfo);
8925 StChain.push_back(PartStore);
8926
8927 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr);
8928 } while (--Count);
8929 // Restore index back to be relative to the original widen element type.
8930 Idx = Idx * NewVTWidth.getFixedValue() / ValEltWidth;
8931 }
8932 }
8933
8934 return true;
8935}
8936
8937/// Modifies a vector input (widen or narrows) to a vector of NVT. The
8938/// input vector must have the same element type as NVT.
8939/// FillWithZeroes specifies that the vector should be widened with zeroes.
8940SDValue DAGTypeLegalizer::ModifyToType(SDValue InOp, EVT NVT,
8941 bool FillWithZeroes) {
8942 // Note that InOp might have been widened so it might already have
8943 // the right width or it might need be narrowed.
8944 EVT InVT = InOp.getValueType();
8946 "input and widen element type must match");
8947 assert(InVT.isScalableVector() == NVT.isScalableVector() &&
8948 "cannot modify scalable vectors in this way");
8949 SDLoc dl(InOp);
8950
8951 // Check if InOp already has the right width.
8952 if (InVT == NVT)
8953 return InOp;
8954
8955 ElementCount InEC = InVT.getVectorElementCount();
8956 ElementCount WidenEC = NVT.getVectorElementCount();
8957 if (WidenEC.hasKnownScalarFactor(InEC)) {
8958 unsigned NumConcat = WidenEC.getKnownScalarFactor(InEC);
8959 SmallVector<SDValue, 16> Ops(NumConcat);
8960 SDValue FillVal =
8961 FillWithZeroes ? DAG.getConstant(0, dl, InVT) : DAG.getPOISON(InVT);
8962 Ops[0] = InOp;
8963 for (unsigned i = 1; i != NumConcat; ++i)
8964 Ops[i] = FillVal;
8965
8966 return DAG.getNode(ISD::CONCAT_VECTORS, dl, NVT, Ops);
8967 }
8968
8969 if (InEC.hasKnownScalarFactor(WidenEC))
8970 return DAG.getExtractSubvector(dl, NVT, InOp, 0);
8971
8972 assert(!InVT.isScalableVector() && !NVT.isScalableVector() &&
8973 "Scalable vectors should have been handled already.");
8974
8975 unsigned InNumElts = InEC.getFixedValue();
8976 unsigned WidenNumElts = WidenEC.getFixedValue();
8977
8978 // Fall back to extract and build (+ mask, if padding with zeros).
8979 SmallVector<SDValue, 16> Ops(WidenNumElts);
8980 EVT EltVT = NVT.getVectorElementType();
8981 unsigned MinNumElts = std::min(WidenNumElts, InNumElts);
8982 unsigned Idx;
8983 for (Idx = 0; Idx < MinNumElts; ++Idx)
8984 Ops[Idx] = DAG.getExtractVectorElt(dl, EltVT, InOp, Idx);
8985
8986 SDValue UndefVal = DAG.getPOISON(EltVT);
8987 for (; Idx < WidenNumElts; ++Idx)
8988 Ops[Idx] = UndefVal;
8989
8990 SDValue Widened = DAG.getBuildVector(NVT, dl, Ops);
8991 if (!FillWithZeroes)
8992 return Widened;
8993
8994 assert(NVT.isInteger() &&
8995 "We expect to never want to FillWithZeroes for non-integral types.");
8996
8998 MaskOps.append(MinNumElts, DAG.getAllOnesConstant(dl, EltVT));
8999 MaskOps.append(WidenNumElts - MinNumElts, DAG.getConstant(0, dl, EltVT));
9000
9001 return DAG.getNode(ISD::AND, dl, NVT, Widened,
9002 DAG.getBuildVector(NVT, dl, MaskOps));
9003}
return SDValue()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static constexpr Value * getValue(Ty &ValueOrUse)
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static unsigned getExtendForIntVecReduction(SDNode *N)
static SDValue BuildVectorFromScalar(SelectionDAG &DAG, EVT VecTy, SmallVectorImpl< SDValue > &LdOps, unsigned Start, unsigned End)
static std::optional< EVT > findMemType(SelectionDAG &DAG, const TargetLowering &TLI, unsigned Width, EVT WidenVT, unsigned Align, unsigned WidenEx)
static EVT getSETCCOperandType(SDValue N)
static bool isSETCCOp(unsigned Opcode)
static bool isLogicalMaskOp(unsigned Opcode)
static bool isSETCCorConvertedSETCC(SDValue N)
static SDValue 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:403
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:292
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:358
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
Definition ValueTypes.h:479
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:381
bool isByteSized() const
Return true if the bit size is a multiple of 8.
Definition ValueTypes.h:251
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
Definition ValueTypes.h:367
uint64_t getScalarSizeInBits() const
Definition ValueTypes.h:393
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
Definition ValueTypes.h:486
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:389
EVT widenIntegerVectorElementType(LLVMContext &Context) const
Return a VT for an integer vector type with the size of the elements doubled.
Definition ValueTypes.h:460
bool isFixedLengthVector() const
Definition ValueTypes.h:189
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:427
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:331
bool bitsEq(EVT VT) const
Return true if this has the same number of bits as VT.
Definition ValueTypes.h:264
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:182
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:276
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition ValueTypes.h:336
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:344
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
Definition ValueTypes.h:469
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.