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 // The stack round-trip uses a byte stride, so a sub-byte element (e.g. i1)
3516 // would get stride 0 and alias every lane. Widen to a byte integer, reverse,
3517 // then truncate back.
3518 EVT OrigVT = VT;
3519 if (!VT.getVectorElementType().isByteSized()) {
3520 EVT WideEltVT = VT.getVectorElementType().changeTypeToInteger();
3521 WideEltVT = WideEltVT.getRoundIntegerType(*DAG.getContext());
3522 VT = VT.changeVectorElementType(*DAG.getContext(), WideEltVT);
3523 Val = DAG.getNode(ISD::ANY_EXTEND, DL, VT, Val);
3524 }
3525
3526 // Fallback to VP_STRIDED_STORE to stack followed by VP_LOAD.
3527 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
3528
3529 EVT MemVT = EVT::getVectorVT(*DAG.getContext(), VT.getVectorElementType(),
3531 SDValue StackPtr = DAG.CreateStackTemporary(MemVT.getStoreSize(), Alignment);
3532 EVT PtrVT = StackPtr.getValueType();
3533 auto &MF = DAG.getMachineFunction();
3534 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
3535 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
3536
3537 MachineMemOperand *StoreMMO = DAG.getMachineFunction().getMachineMemOperand(
3539 Alignment);
3540 MachineMemOperand *LoadMMO = DAG.getMachineFunction().getMachineMemOperand(
3542 Alignment);
3543
3544 unsigned EltWidth = VT.getScalarSizeInBits() / 8;
3545 SDValue NumElemMinus1 =
3546 DAG.getNode(ISD::SUB, DL, PtrVT, DAG.getZExtOrTrunc(EVL, DL, PtrVT),
3547 DAG.getConstant(1, DL, PtrVT));
3548 SDValue StartOffset = DAG.getNode(ISD::MUL, DL, PtrVT, NumElemMinus1,
3549 DAG.getConstant(EltWidth, DL, PtrVT));
3550 SDValue StorePtr = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, StartOffset);
3551 SDValue Stride = DAG.getConstant(-(int64_t)EltWidth, DL, PtrVT);
3552
3553 SDValue TrueMask = DAG.getBoolConstant(true, DL, Mask.getValueType(), VT);
3554 SDValue Store = DAG.getStridedStoreVP(DAG.getEntryNode(), DL, Val, StorePtr,
3555 DAG.getPOISON(PtrVT), Stride, TrueMask,
3556 EVL, MemVT, StoreMMO, ISD::UNINDEXED);
3557
3558 SDValue Load = DAG.getLoadVP(VT, DL, Store, StackPtr, Mask, EVL, LoadMMO);
3559
3560 // Truncate back if we widened above.
3561 if (OrigVT != VT)
3562 Load = DAG.getNode(ISD::TRUNCATE, DL, OrigVT, Load);
3563
3564 std::tie(Lo, Hi) = DAG.SplitVector(Load, DL);
3565}
3566
3567void DAGTypeLegalizer::SplitVecRes_VP_SPLICE(SDNode *N, SDValue &Lo,
3568 SDValue &Hi) {
3569 EVT VT = N->getValueType(0);
3570 SDValue V1 = N->getOperand(0);
3571 SDValue V2 = N->getOperand(1);
3572 int64_t Imm = cast<ConstantSDNode>(N->getOperand(2))->getSExtValue();
3573 SDValue Mask = N->getOperand(3);
3574 SDValue EVL1 = N->getOperand(4);
3575 SDValue EVL2 = N->getOperand(5);
3576 SDLoc DL(N);
3577
3578 // Since EVL2 is considered the real VL it gets promoted during
3579 // SelectionDAGBuilder. Promote EVL1 here if needed.
3580 if (getTypeAction(EVL1.getValueType()) == TargetLowering::TypePromoteInteger)
3581 EVL1 = ZExtPromotedInteger(EVL1);
3582
3583 // The stack splice addresses elements by byte offset/stride, which breaks for
3584 // a sub-byte element (e.g. i1): getVectorElementPointer asserts and the
3585 // stride is 0. Widen to a byte integer, splice, then truncate back.
3586 EVT OrigVT = VT;
3587 if (!VT.getVectorElementType().isByteSized()) {
3588 EVT WideEltVT = VT.getVectorElementType().changeTypeToInteger();
3589 WideEltVT = WideEltVT.getRoundIntegerType(*DAG.getContext());
3590 VT = VT.changeVectorElementType(*DAG.getContext(), WideEltVT);
3591 V1 = DAG.getNode(ISD::ANY_EXTEND, DL, VT, V1);
3592 V2 = DAG.getNode(ISD::ANY_EXTEND, DL, VT, V2);
3593 }
3594
3595 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
3596
3597 EVT MemVT = EVT::getVectorVT(*DAG.getContext(), VT.getVectorElementType(),
3598 VT.getVectorElementCount() * 2);
3599 SDValue StackPtr = DAG.CreateStackTemporary(MemVT.getStoreSize(), Alignment);
3600 EVT PtrVT = StackPtr.getValueType();
3601 auto &MF = DAG.getMachineFunction();
3602 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
3603 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
3604
3605 MachineMemOperand *StoreMMO = DAG.getMachineFunction().getMachineMemOperand(
3607 Alignment);
3608 MachineMemOperand *LoadMMO = DAG.getMachineFunction().getMachineMemOperand(
3610 Alignment);
3611
3612 SDValue StackPtr2 = TLI.getVectorElementPointer(DAG, StackPtr, VT, EVL1);
3613 SDValue PoisonPtr = DAG.getPOISON(PtrVT);
3614
3615 SDValue TrueMask = DAG.getBoolConstant(true, DL, Mask.getValueType(), VT);
3616 SDValue StoreV1 =
3617 DAG.getStoreVP(DAG.getEntryNode(), DL, V1, StackPtr, PoisonPtr, TrueMask,
3618 EVL1, V1.getValueType(), StoreMMO, ISD::UNINDEXED);
3619
3621 DAG.getStoreVP(StoreV1, DL, V2, StackPtr2, PoisonPtr, TrueMask, EVL2,
3622 V2.getValueType(), StoreMMO, ISD::UNINDEXED);
3623
3624 SDValue Load;
3625 if (Imm >= 0) {
3626 StackPtr = TLI.getVectorElementPointer(DAG, StackPtr, VT, N->getOperand(2));
3627 Load = DAG.getLoadVP(VT, DL, StoreV2, StackPtr, Mask, EVL2, LoadMMO);
3628 } else {
3629 uint64_t TrailingElts = -Imm;
3630 unsigned EltWidth = VT.getScalarSizeInBits() / 8;
3631 SDValue TrailingBytes = DAG.getConstant(TrailingElts * EltWidth, DL, PtrVT);
3632
3633 // Make sure TrailingBytes doesn't exceed the size of vec1.
3634 SDValue OffsetToV2 = DAG.getNode(ISD::SUB, DL, PtrVT, StackPtr2, StackPtr);
3635 TrailingBytes =
3636 DAG.getNode(ISD::UMIN, DL, PtrVT, TrailingBytes, OffsetToV2);
3637
3638 // Calculate the start address of the spliced result.
3639 StackPtr2 = DAG.getNode(ISD::SUB, DL, PtrVT, StackPtr2, TrailingBytes);
3640 Load = DAG.getLoadVP(VT, DL, StoreV2, StackPtr2, Mask, EVL2, LoadMMO);
3641 }
3642
3643 // Truncate back if we widened above.
3644 if (OrigVT != VT)
3645 Load = DAG.getNode(ISD::TRUNCATE, DL, OrigVT, Load);
3646
3647 EVT LoVT, HiVT;
3648 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(OrigVT);
3649 Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, LoVT, Load,
3650 DAG.getVectorIdxConstant(0, DL));
3651 Hi =
3652 DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, HiVT, Load,
3653 DAG.getVectorIdxConstant(LoVT.getVectorMinNumElements(), DL));
3654}
3655
3656void DAGTypeLegalizer::SplitVecRes_PARTIAL_REDUCE_MLA(SDNode *N, SDValue &Lo,
3657 SDValue &Hi) {
3658 SDLoc DL(N);
3659 SDValue Acc = N->getOperand(0);
3660 SDValue Input1 = N->getOperand(1);
3661 SDValue Input2 = N->getOperand(2);
3662
3663 SDValue AccLo, AccHi;
3664 GetSplitVector(Acc, AccLo, AccHi);
3665 unsigned Opcode = N->getOpcode();
3666
3667 // If the input types don't need splitting, just accumulate into the
3668 // low part of the accumulator.
3669 if (getTypeAction(Input1.getValueType()) != TargetLowering::TypeSplitVector) {
3670 Lo = DAG.getNode(Opcode, DL, AccLo.getValueType(), AccLo, Input1, Input2);
3671 Hi = AccHi;
3672 return;
3673 }
3674
3675 SDValue Input1Lo, Input1Hi;
3676 SDValue Input2Lo, Input2Hi;
3677 GetSplitVector(Input1, Input1Lo, Input1Hi);
3678 GetSplitVector(Input2, Input2Lo, Input2Hi);
3679 EVT ResultVT = AccLo.getValueType();
3680
3681 Lo = DAG.getNode(Opcode, DL, ResultVT, AccLo, Input1Lo, Input2Lo);
3682 Hi = DAG.getNode(Opcode, DL, ResultVT, AccHi, Input1Hi, Input2Hi);
3683}
3684
3685void DAGTypeLegalizer::SplitVecRes_GET_ACTIVE_LANE_MASK(SDNode *N, SDValue &Lo,
3686 SDValue &Hi) {
3687 SDLoc DL(N);
3688 SDValue Op0 = N->getOperand(0);
3689 SDValue Op1 = N->getOperand(1);
3690 EVT OpVT = Op0.getValueType();
3691
3692 EVT LoVT, HiVT;
3693 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
3694
3695 Lo = DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, DL, LoVT, Op0, Op1);
3696 SDValue LoElts = DAG.getElementCount(DL, OpVT, LoVT.getVectorElementCount());
3697 SDValue HiStartVal = DAG.getNode(ISD::UADDSAT, DL, OpVT, Op0, LoElts);
3698 Hi = DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, DL, HiVT, HiStartVal, Op1);
3699}
3700
3701void DAGTypeLegalizer::SplitVecRes_VECTOR_DEINTERLEAVE(SDNode *N) {
3702 unsigned Factor = N->getNumOperands();
3703
3704 SmallVector<SDValue, 8> Ops(Factor * 2);
3705 for (unsigned i = 0; i != Factor; ++i) {
3706 SDValue OpLo, OpHi;
3707 GetSplitVector(N->getOperand(i), OpLo, OpHi);
3708 Ops[i * 2] = OpLo;
3709 Ops[i * 2 + 1] = OpHi;
3710 }
3711
3712 SmallVector<EVT, 8> VTs(Factor, Ops[0].getValueType());
3713
3714 SDLoc DL(N);
3715 SDValue ResLo = DAG.getNode(ISD::VECTOR_DEINTERLEAVE, DL, VTs,
3716 ArrayRef(Ops).slice(0, Factor));
3717 SDValue ResHi = DAG.getNode(ISD::VECTOR_DEINTERLEAVE, DL, VTs,
3718 ArrayRef(Ops).slice(Factor, Factor));
3719
3720 for (unsigned i = 0; i != Factor; ++i)
3721 SetSplitVector(SDValue(N, i), ResLo.getValue(i), ResHi.getValue(i));
3722}
3723
3724void DAGTypeLegalizer::SplitVecRes_VECTOR_INTERLEAVE(SDNode *N) {
3725 unsigned Factor = N->getNumOperands();
3726
3727 SmallVector<SDValue, 8> Ops(Factor * 2);
3728 for (unsigned i = 0; i != Factor; ++i) {
3729 SDValue OpLo, OpHi;
3730 GetSplitVector(N->getOperand(i), OpLo, OpHi);
3731 Ops[i] = OpLo;
3732 Ops[i + Factor] = OpHi;
3733 }
3734
3735 SmallVector<EVT, 8> VTs(Factor, Ops[0].getValueType());
3736
3737 SDLoc DL(N);
3738 SDValue Res[] = {DAG.getNode(ISD::VECTOR_INTERLEAVE, DL, VTs,
3739 ArrayRef(Ops).slice(0, Factor)),
3740 DAG.getNode(ISD::VECTOR_INTERLEAVE, DL, VTs,
3741 ArrayRef(Ops).slice(Factor, Factor))};
3742
3743 for (unsigned i = 0; i != Factor; ++i) {
3744 unsigned IdxLo = 2 * i;
3745 unsigned IdxHi = 2 * i + 1;
3746 SetSplitVector(SDValue(N, i), Res[IdxLo / Factor].getValue(IdxLo % Factor),
3747 Res[IdxHi / Factor].getValue(IdxHi % Factor));
3748 }
3749}
3750
3751//===----------------------------------------------------------------------===//
3752// Operand Vector Splitting
3753//===----------------------------------------------------------------------===//
3754
3755/// This method is called when the specified operand of the specified node is
3756/// found to need vector splitting. At this point, all of the result types of
3757/// the node are known to be legal, but other operands of the node may need
3758/// legalization as well as the specified one.
3759bool DAGTypeLegalizer::SplitVectorOperand(SDNode *N, unsigned OpNo) {
3760 LLVM_DEBUG(dbgs() << "Split node operand: "; N->dump(&DAG));
3761 SDValue Res = SDValue();
3762
3763 // See if the target wants to custom split this node.
3764 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
3765 return false;
3766
3767 switch (N->getOpcode()) {
3768 default:
3769#ifndef NDEBUG
3770 dbgs() << "SplitVectorOperand Op #" << OpNo << ": ";
3771 N->dump(&DAG);
3772 dbgs() << "\n";
3773#endif
3774 report_fatal_error("Do not know how to split this operator's "
3775 "operand!\n");
3776
3777 case ISD::VP_SETCC:
3778 case ISD::STRICT_FSETCC:
3780 case ISD::SETCC: Res = SplitVecOp_VSETCC(N); break;
3781 case ISD::BITCAST: Res = SplitVecOp_BITCAST(N); break;
3782 case ISD::EXTRACT_SUBVECTOR: Res = SplitVecOp_EXTRACT_SUBVECTOR(N); break;
3783 case ISD::INSERT_SUBVECTOR: Res = SplitVecOp_INSERT_SUBVECTOR(N, OpNo); break;
3784 case ISD::EXTRACT_VECTOR_ELT:Res = SplitVecOp_EXTRACT_VECTOR_ELT(N); break;
3785 case ISD::CONCAT_VECTORS: Res = SplitVecOp_CONCAT_VECTORS(N); break;
3787 Res = SplitVecOp_VECTOR_FIND_LAST_ACTIVE(N);
3788 break;
3789 case ISD::VP_TRUNCATE:
3790 case ISD::TRUNCATE:
3791 Res = SplitVecOp_TruncateHelper(N);
3792 break;
3794 case ISD::VP_FP_ROUND:
3795 case ISD::FP_ROUND:
3797 Res = SplitVecOp_FP_ROUND(N);
3798 break;
3799 case ISD::FCOPYSIGN: Res = SplitVecOp_FPOpDifferentTypes(N); break;
3800 case ISD::STORE:
3801 Res = SplitVecOp_STORE(cast<StoreSDNode>(N), OpNo);
3802 break;
3803 case ISD::VP_STORE:
3804 Res = SplitVecOp_VP_STORE(cast<VPStoreSDNode>(N), OpNo);
3805 break;
3806 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
3807 Res = SplitVecOp_VP_STRIDED_STORE(cast<VPStridedStoreSDNode>(N), OpNo);
3808 break;
3809 case ISD::MSTORE:
3810 Res = SplitVecOp_MSTORE(cast<MaskedStoreSDNode>(N), OpNo);
3811 break;
3812 case ISD::MSCATTER:
3813 case ISD::VP_SCATTER:
3814 Res = SplitVecOp_Scatter(cast<MemSDNode>(N), OpNo);
3815 break;
3816 case ISD::MGATHER:
3817 case ISD::VP_GATHER:
3818 Res = SplitVecOp_Gather(cast<MemSDNode>(N), OpNo);
3819 break;
3820 case ISD::VSELECT:
3821 Res = SplitVecOp_VSELECT(N, OpNo);
3822 break;
3824 Res = SplitVecOp_VECTOR_COMPRESS(N, OpNo);
3825 break;
3828 case ISD::SINT_TO_FP:
3829 case ISD::UINT_TO_FP:
3830 case ISD::VP_SINT_TO_FP:
3831 case ISD::VP_UINT_TO_FP:
3832 if (N->getValueType(0).bitsLT(
3833 N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType()))
3834 Res = SplitVecOp_TruncateHelper(N);
3835 else
3836 Res = SplitVecOp_UnaryOp(N);
3837 break;
3840 Res = SplitVecOp_FP_TO_XINT_SAT(N);
3841 break;
3842 case ISD::FP_TO_SINT:
3843 case ISD::FP_TO_UINT:
3844 case ISD::VP_FP_TO_SINT:
3845 case ISD::VP_FP_TO_UINT:
3849 case ISD::FP_EXTEND:
3850 case ISD::SIGN_EXTEND:
3851 case ISD::ZERO_EXTEND:
3852 case ISD::ANY_EXTEND:
3853 case ISD::FTRUNC:
3854 case ISD::LROUND:
3855 case ISD::LLROUND:
3856 case ISD::LRINT:
3857 case ISD::LLRINT:
3858 Res = SplitVecOp_UnaryOp(N);
3859 break;
3860 case ISD::FLDEXP:
3861 Res = SplitVecOp_FPOpDifferentTypes(N);
3862 break;
3863
3864 case ISD::SCMP:
3865 case ISD::UCMP:
3866 Res = SplitVecOp_CMP(N);
3867 break;
3868
3869 case ISD::FAKE_USE:
3870 Res = SplitVecOp_FAKE_USE(N);
3871 break;
3875 Res = SplitVecOp_ExtVecInRegOp(N);
3876 break;
3877
3880 case ISD::VECREDUCE_ADD:
3881 case ISD::VECREDUCE_MUL:
3882 case ISD::VECREDUCE_AND:
3883 case ISD::VECREDUCE_OR:
3884 case ISD::VECREDUCE_XOR:
3893 Res = SplitVecOp_VECREDUCE(N, OpNo);
3894 break;
3897 Res = SplitVecOp_VECREDUCE_SEQ(N);
3898 break;
3899 case ISD::VP_REDUCE_FADD:
3900 case ISD::VP_REDUCE_SEQ_FADD:
3901 case ISD::VP_REDUCE_FMUL:
3902 case ISD::VP_REDUCE_SEQ_FMUL:
3903 case ISD::VP_REDUCE_ADD:
3904 case ISD::VP_REDUCE_MUL:
3905 case ISD::VP_REDUCE_AND:
3906 case ISD::VP_REDUCE_OR:
3907 case ISD::VP_REDUCE_XOR:
3908 case ISD::VP_REDUCE_SMAX:
3909 case ISD::VP_REDUCE_SMIN:
3910 case ISD::VP_REDUCE_UMAX:
3911 case ISD::VP_REDUCE_UMIN:
3912 case ISD::VP_REDUCE_FMAX:
3913 case ISD::VP_REDUCE_FMIN:
3914 case ISD::VP_REDUCE_FMAXIMUM:
3915 case ISD::VP_REDUCE_FMINIMUM:
3916 Res = SplitVecOp_VP_REDUCE(N, OpNo);
3917 break;
3918 case ISD::CTTZ_ELTS:
3920 Res = SplitVecOp_CttzElts(N);
3921 break;
3922 case ISD::VP_CTTZ_ELTS:
3923 case ISD::VP_CTTZ_ELTS_ZERO_POISON:
3924 Res = SplitVecOp_VP_CttzElements(N);
3925 break;
3927 Res = SplitVecOp_VECTOR_HISTOGRAM(N);
3928 break;
3933 Res = SplitVecOp_PARTIAL_REDUCE_MLA(N);
3934 break;
3935 }
3936
3937 // If the result is null, the sub-method took care of registering results etc.
3938 if (!Res.getNode()) return false;
3939
3940 // If the result is N, the sub-method updated N in place. Tell the legalizer
3941 // core about this.
3942 if (Res.getNode() == N)
3943 return true;
3944
3945 if (N->isStrictFPOpcode())
3946 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
3947 "Invalid operand expansion");
3948 else
3949 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
3950 "Invalid operand expansion");
3951
3952 ReplaceValueWith(SDValue(N, 0), Res);
3953 return false;
3954}
3955
3956SDValue DAGTypeLegalizer::SplitVecOp_VECTOR_FIND_LAST_ACTIVE(SDNode *N) {
3957 SDLoc DL(N);
3958
3959 SDValue LoMask, HiMask;
3960 GetSplitVector(N->getOperand(0), LoMask, HiMask);
3961
3962 EVT VT = N->getValueType(0);
3963 EVT SplitVT = LoMask.getValueType();
3964 ElementCount SplitEC = SplitVT.getVectorElementCount();
3965
3966 // Find the last active in both the low and the high masks.
3967 SDValue LoFind = DAG.getNode(ISD::VECTOR_FIND_LAST_ACTIVE, DL, VT, LoMask);
3968 SDValue HiFind = DAG.getNode(ISD::VECTOR_FIND_LAST_ACTIVE, DL, VT, HiMask);
3969
3970 // Check if any lane is active in the high mask.
3971 // FIXME: This would not be necessary if VECTOR_FIND_LAST_ACTIVE returned a
3972 // sentinel value for "none active".
3973 SDValue AnyHiActive = DAG.getNode(ISD::VECREDUCE_OR, DL, MVT::i1, HiMask);
3974 SDValue Cond = DAG.getBoolExtOrTrunc(AnyHiActive, DL,
3975 getSetCCResultType(MVT::i1), MVT::i1);
3976
3977 // Return: AnyHiActive ? (HiFind + SplitEC) : LoFind;
3978 return DAG.getNode(ISD::SELECT, DL, VT, Cond,
3979 DAG.getNode(ISD::ADD, DL, VT, HiFind,
3980 DAG.getElementCount(DL, VT, SplitEC)),
3981 LoFind);
3982}
3983
3984SDValue DAGTypeLegalizer::SplitVecOp_VSELECT(SDNode *N, unsigned OpNo) {
3985 // The only possibility for an illegal operand is the mask, since result type
3986 // legalization would have handled this node already otherwise.
3987 assert(OpNo == 0 && "Illegal operand must be mask");
3988
3989 SDValue Mask = N->getOperand(0);
3990 SDValue Src0 = N->getOperand(1);
3991 SDValue Src1 = N->getOperand(2);
3992 EVT Src0VT = Src0.getValueType();
3993 SDLoc DL(N);
3994 assert(Mask.getValueType().isVector() && "VSELECT without a vector mask?");
3995
3996 SDValue Lo, Hi;
3997 GetSplitVector(N->getOperand(0), Lo, Hi);
3998 assert(Lo.getValueType() == Hi.getValueType() &&
3999 "Lo and Hi have differing types");
4000
4001 EVT LoOpVT, HiOpVT;
4002 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(Src0VT);
4003 assert(LoOpVT == HiOpVT && "Asymmetric vector split?");
4004
4005 SDValue LoOp0, HiOp0, LoOp1, HiOp1, LoMask, HiMask;
4006 std::tie(LoOp0, HiOp0) = DAG.SplitVector(Src0, DL);
4007 std::tie(LoOp1, HiOp1) = DAG.SplitVector(Src1, DL);
4008 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
4009
4010 SDValue LoSelect =
4011 DAG.getNode(ISD::VSELECT, DL, LoOpVT, LoMask, LoOp0, LoOp1);
4012 SDValue HiSelect =
4013 DAG.getNode(ISD::VSELECT, DL, HiOpVT, HiMask, HiOp0, HiOp1);
4014
4015 return DAG.getNode(ISD::CONCAT_VECTORS, DL, Src0VT, LoSelect, HiSelect);
4016}
4017
4018SDValue DAGTypeLegalizer::SplitVecOp_VECTOR_COMPRESS(SDNode *N, unsigned OpNo) {
4019 // The only possibility for an illegal operand is the mask, since result type
4020 // legalization would have handled this node already otherwise.
4021 assert(OpNo == 1 && "Illegal operand must be mask");
4022
4023 // To split the mask, we need to split the result type too, so we can just
4024 // reuse that logic here.
4025 SDValue Lo, Hi;
4026 SplitVecRes_VECTOR_COMPRESS(N, Lo, Hi);
4027
4028 EVT VecVT = N->getValueType(0);
4029 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), VecVT, Lo, Hi);
4030}
4031
4032SDValue DAGTypeLegalizer::SplitVecOp_VECREDUCE(SDNode *N, unsigned OpNo) {
4033 EVT ResVT = N->getValueType(0);
4034 SDValue Lo, Hi;
4035 SDLoc dl(N);
4036
4037 SDValue VecOp = N->getOperand(OpNo);
4038 EVT VecVT = VecOp.getValueType();
4039 assert(VecVT.isVector() && "Can only split reduce vector operand");
4040 GetSplitVector(VecOp, Lo, Hi);
4041 EVT LoOpVT, HiOpVT;
4042 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(VecVT);
4043
4044 // Use the appropriate scalar instruction on the split subvectors before
4045 // reducing the now partially reduced smaller vector.
4046 unsigned CombineOpc = ISD::getVecReduceBaseOpcode(N->getOpcode());
4047 SDValue Partial = DAG.getNode(CombineOpc, dl, LoOpVT, Lo, Hi, N->getFlags());
4048 return DAG.getNode(N->getOpcode(), dl, ResVT, Partial, N->getFlags());
4049}
4050
4051SDValue DAGTypeLegalizer::SplitVecOp_VECREDUCE_SEQ(SDNode *N) {
4052 EVT ResVT = N->getValueType(0);
4053 SDValue Lo, Hi;
4054 SDLoc dl(N);
4055
4056 SDValue AccOp = N->getOperand(0);
4057 SDValue VecOp = N->getOperand(1);
4058 SDNodeFlags Flags = N->getFlags();
4059
4060 EVT VecVT = VecOp.getValueType();
4061 assert(VecVT.isVector() && "Can only split reduce vector operand");
4062 GetSplitVector(VecOp, Lo, Hi);
4063 EVT LoOpVT, HiOpVT;
4064 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(VecVT);
4065
4066 // Reduce low half.
4067 SDValue Partial = DAG.getNode(N->getOpcode(), dl, ResVT, AccOp, Lo, Flags);
4068
4069 // Reduce high half, using low half result as initial value.
4070 return DAG.getNode(N->getOpcode(), dl, ResVT, Partial, Hi, Flags);
4071}
4072
4073SDValue DAGTypeLegalizer::SplitVecOp_VP_REDUCE(SDNode *N, unsigned OpNo) {
4074 assert(N->isVPOpcode() && "Expected VP opcode");
4075 assert(OpNo == 1 && "Can only split reduce vector operand");
4076
4077 unsigned Opc = N->getOpcode();
4078 EVT ResVT = N->getValueType(0);
4079 SDValue Lo, Hi;
4080 SDLoc dl(N);
4081
4082 SDValue VecOp = N->getOperand(OpNo);
4083 EVT VecVT = VecOp.getValueType();
4084 assert(VecVT.isVector() && "Can only split reduce vector operand");
4085 GetSplitVector(VecOp, Lo, Hi);
4086
4087 SDValue MaskLo, MaskHi;
4088 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(2));
4089
4090 SDValue EVLLo, EVLHi;
4091 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(N->getOperand(3), VecVT, dl);
4092
4093 const SDNodeFlags Flags = N->getFlags();
4094
4095 SDValue ResLo =
4096 DAG.getNode(Opc, dl, ResVT, {N->getOperand(0), Lo, MaskLo, EVLLo}, Flags);
4097 return DAG.getNode(Opc, dl, ResVT, {ResLo, Hi, MaskHi, EVLHi}, Flags);
4098}
4099
4100SDValue DAGTypeLegalizer::SplitVecOp_UnaryOp(SDNode *N) {
4101 // The result has a legal vector type, but the input needs splitting.
4102 EVT ResVT = N->getValueType(0);
4103 SDValue Lo, Hi;
4104 SDLoc dl(N);
4105 GetSplitVector(N->getOperand(N->isStrictFPOpcode() ? 1 : 0), Lo, Hi);
4106 EVT InVT = Lo.getValueType();
4107
4108 EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
4109 InVT.getVectorElementCount());
4110
4111 if (N->isStrictFPOpcode()) {
4112 Lo = DAG.getNode(N->getOpcode(), dl, {OutVT, MVT::Other},
4113 {N->getOperand(0), Lo});
4114 Hi = DAG.getNode(N->getOpcode(), dl, {OutVT, MVT::Other},
4115 {N->getOperand(0), Hi});
4116
4117 // Build a factor node to remember that this operation is independent
4118 // of the other one.
4119 SDValue Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
4120 Hi.getValue(1));
4121
4122 // Legalize the chain result - switch anything that used the old chain to
4123 // use the new one.
4124 ReplaceValueWith(SDValue(N, 1), Ch);
4125 } else if (N->getNumOperands() == 3) {
4126 assert(N->isVPOpcode() && "Expected VP opcode");
4127 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
4128 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
4129 std::tie(EVLLo, EVLHi) =
4130 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), dl);
4131 Lo = DAG.getNode(N->getOpcode(), dl, OutVT, Lo, MaskLo, EVLLo);
4132 Hi = DAG.getNode(N->getOpcode(), dl, OutVT, Hi, MaskHi, EVLHi);
4133 } else {
4134 Lo = DAG.getNode(N->getOpcode(), dl, OutVT, Lo);
4135 Hi = DAG.getNode(N->getOpcode(), dl, OutVT, Hi);
4136 }
4137
4138 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
4139}
4140
4141// Split a FAKE_USE use of a vector into FAKE_USEs of hi and lo part.
4142SDValue DAGTypeLegalizer::SplitVecOp_FAKE_USE(SDNode *N) {
4143 SDValue Lo, Hi;
4144 GetSplitVector(N->getOperand(1), Lo, Hi);
4145 SDValue Chain =
4146 DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, N->getOperand(0), Lo);
4147 return DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, Chain, Hi);
4148}
4149
4150SDValue DAGTypeLegalizer::SplitVecOp_BITCAST(SDNode *N) {
4151 // For example, i64 = BITCAST v4i16 on alpha. Typically the vector will
4152 // end up being split all the way down to individual components. Convert the
4153 // split pieces into integers and reassemble.
4154 EVT ResVT = N->getValueType(0);
4155 SDValue Lo, Hi;
4156 GetSplitVector(N->getOperand(0), Lo, Hi);
4157 SDLoc dl(N);
4158
4159 if (ResVT.isScalableVector()) {
4160 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(ResVT);
4161 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
4162 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
4163 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
4164 }
4165
4166 Lo = BitConvertToInteger(Lo);
4167 Hi = BitConvertToInteger(Hi);
4168
4169 if (DAG.getDataLayout().isBigEndian())
4170 std::swap(Lo, Hi);
4171
4172 return DAG.getNode(ISD::BITCAST, dl, ResVT, JoinIntegers(Lo, Hi));
4173}
4174
4175SDValue DAGTypeLegalizer::SplitVecOp_INSERT_SUBVECTOR(SDNode *N,
4176 unsigned OpNo) {
4177 assert(OpNo == 1 && "Invalid OpNo; can only split SubVec.");
4178 // We know that the result type is legal.
4179 EVT ResVT = N->getValueType(0);
4180
4181 SDValue Vec = N->getOperand(0);
4182 SDValue SubVec = N->getOperand(1);
4183 SDValue Idx = N->getOperand(2);
4184 SDLoc dl(N);
4185
4186 SDValue Lo, Hi;
4187 GetSplitVector(SubVec, Lo, Hi);
4188
4189 uint64_t IdxVal = Idx->getAsZExtVal();
4190 uint64_t LoElts = Lo.getValueType().getVectorMinNumElements();
4191
4192 SDValue FirstInsertion =
4193 DAG.getNode(ISD::INSERT_SUBVECTOR, dl, ResVT, Vec, Lo, Idx);
4194 SDValue SecondInsertion =
4195 DAG.getNode(ISD::INSERT_SUBVECTOR, dl, ResVT, FirstInsertion, Hi,
4196 DAG.getVectorIdxConstant(IdxVal + LoElts, dl));
4197
4198 return SecondInsertion;
4199}
4200
4201SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
4202 // We know that the extracted result type is legal.
4203 EVT SubVT = N->getValueType(0);
4204 SDValue Idx = N->getOperand(1);
4205 SDLoc dl(N);
4206 SDValue Lo, Hi;
4207
4208 GetSplitVector(N->getOperand(0), Lo, Hi);
4209
4210 ElementCount LoElts = Lo.getValueType().getVectorElementCount();
4211 // Note: For scalable vectors, the index is scaled by vscale.
4212 ElementCount IdxVal =
4214 uint64_t IdxValMin = IdxVal.getKnownMinValue();
4215
4216 EVT SrcVT = N->getOperand(0).getValueType();
4217 ElementCount NumResultElts = SubVT.getVectorElementCount();
4218
4219 // If the extracted elements are all in the low half, do a simple extract.
4220 if (ElementCount::isKnownLE(IdxVal + NumResultElts, LoElts))
4221 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, SubVT, Lo, Idx);
4222
4223 unsigned LoEltsMin = LoElts.getKnownMinValue();
4224 if (IdxValMin < LoEltsMin && SubVT.isFixedLengthVector() &&
4225 SrcVT.isFixedLengthVector()) {
4226 // Extracted subvector crosses vector split, so we need to blend the two
4227 // halves.
4228 // TODO: May be able to emit partial extract_subvector.
4230 Elts.reserve(NumResultElts.getFixedValue());
4231
4232 // This is not valid for scalable vectors. If SubVT is scalable, this is the
4233 // same as unrolling a scalable dimension (invalid). If ScrVT is scalable,
4234 // `Lo[LoEltsMin]` may not be the last element of `Lo`.
4235 DAG.ExtractVectorElements(Lo, Elts, /*Start=*/IdxValMin,
4236 /*Count=*/LoEltsMin - IdxValMin);
4237 DAG.ExtractVectorElements(Hi, Elts, /*Start=*/0,
4238 /*Count=*/SubVT.getVectorNumElements() -
4239 Elts.size());
4240 return DAG.getBuildVector(SubVT, dl, Elts);
4241 }
4242
4243 if (SubVT.isScalableVector() == SrcVT.isScalableVector()) {
4244 ElementCount ExtractIdx = IdxVal - LoElts;
4245 if (ExtractIdx.isKnownMultipleOf(NumResultElts))
4246 return DAG.getExtractSubvector(dl, SubVT, Hi,
4247 ExtractIdx.getKnownMinValue());
4248
4249 EVT HiVT = Hi.getValueType();
4250 assert(HiVT.isFixedLengthVector() &&
4251 "Only fixed-vector extracts are supported in this case");
4252
4253 // We cannot create an extract_subvector that isn't a multiple of the
4254 // result size, which may go out of bounds for the last elements. Shuffle
4255 // the desired elements down to 0 and do a simple 0 extract.
4256 SmallVector<int, 8> Mask(HiVT.getVectorNumElements(), -1);
4257 for (int I = 0; I != int(NumResultElts.getFixedValue()); ++I)
4258 Mask[I] = int(ExtractIdx.getFixedValue()) + I;
4259
4260 SDValue Shuffle =
4261 DAG.getVectorShuffle(HiVT, dl, Hi, DAG.getPOISON(HiVT), Mask);
4262 return DAG.getExtractSubvector(dl, SubVT, Shuffle, 0);
4263 }
4264
4265 // After this point the DAG node only permits extracting fixed-width
4266 // subvectors from scalable vectors.
4267 assert(SubVT.isFixedLengthVector() &&
4268 "Extracting scalable subvector from fixed-width unsupported");
4269
4270 // If the element type is i1 and we're not promoting the result, then we may
4271 // end up loading the wrong data since the bits are packed tightly into
4272 // bytes. For example, if we extract a v4i1 (legal) from a nxv4i1 (legal)
4273 // type at index 4, then we will load a byte starting at index 0.
4274 if (SubVT.getScalarType() == MVT::i1)
4275 report_fatal_error("Don't know how to extract fixed-width predicate "
4276 "subvector from a scalable predicate vector");
4277
4278 // Spill the vector to the stack. We should use the alignment for
4279 // the smallest part.
4280 SDValue Vec = N->getOperand(0);
4281 EVT VecVT = Vec.getValueType();
4282 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
4284 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
4285 auto &MF = DAG.getMachineFunction();
4286 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
4287 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
4288
4289 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
4290 SmallestAlign);
4291
4292 // Extract the subvector by loading the correct part.
4293 StackPtr = TLI.getVectorSubVecPointer(DAG, StackPtr, VecVT, SubVT, Idx);
4294
4295 return DAG.getLoad(
4296 SubVT, dl, Store, StackPtr,
4297 MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()));
4298}
4299
4300SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
4301 SDValue Vec = N->getOperand(0);
4302 SDValue Idx = N->getOperand(1);
4303 EVT VecVT = Vec.getValueType();
4304
4305 if (const ConstantSDNode *Index = dyn_cast<ConstantSDNode>(Idx)) {
4306 uint64_t IdxVal = Index->getZExtValue();
4307
4308 SDValue Lo, Hi;
4309 GetSplitVector(Vec, Lo, Hi);
4310
4311 uint64_t LoElts = Lo.getValueType().getVectorMinNumElements();
4312
4313 if (IdxVal < LoElts)
4314 return SDValue(DAG.UpdateNodeOperands(N, Lo, Idx), 0);
4315 else if (!Vec.getValueType().isScalableVector())
4316 return SDValue(DAG.UpdateNodeOperands(N, Hi,
4317 DAG.getConstant(IdxVal - LoElts, SDLoc(N),
4318 Idx.getValueType())), 0);
4319 }
4320
4321 // See if the target wants to custom expand this node.
4322 if (CustomLowerNode(N, N->getValueType(0), true))
4323 return SDValue();
4324
4325 // Make the vector elements byte-addressable if they aren't already.
4326 SDLoc dl(N);
4327 EVT EltVT = VecVT.getVectorElementType();
4328 if (!EltVT.isByteSized()) {
4329 EltVT = EltVT.changeTypeToInteger().getRoundIntegerType(*DAG.getContext());
4330 VecVT = VecVT.changeElementType(*DAG.getContext(), EltVT);
4331 Vec = DAG.getNode(ISD::ANY_EXTEND, dl, VecVT, Vec);
4332 SDValue NewExtract =
4333 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, Vec, Idx);
4334 return DAG.getAnyExtOrTrunc(NewExtract, dl, N->getValueType(0));
4335 }
4336
4337 // Store the vector to the stack.
4338 // In cases where the vector is illegal it will be broken down into parts
4339 // and stored in parts - we should use the alignment for the smallest part.
4340 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
4342 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
4343 auto &MF = DAG.getMachineFunction();
4344 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
4345 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
4346 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
4347 SmallestAlign);
4348
4349 // Load back the required element.
4350 StackPtr = TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Idx);
4351
4352 // EXTRACT_VECTOR_ELT can extend the element type to the width of the return
4353 // type, leaving the high bits undefined. But it can't truncate.
4354 assert(N->getValueType(0).bitsGE(EltVT) && "Illegal EXTRACT_VECTOR_ELT.");
4355
4356 return DAG.getExtLoad(
4357 ISD::EXTLOAD, dl, N->getValueType(0), Store, StackPtr,
4358 MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()), EltVT,
4359 commonAlignment(SmallestAlign, EltVT.getFixedSizeInBits() / 8));
4360}
4361
4362SDValue DAGTypeLegalizer::SplitVecOp_ExtVecInRegOp(SDNode *N) {
4363 SDValue Lo, Hi;
4364
4365 // *_EXTEND_VECTOR_INREG only reference the lower half of the input, so
4366 // splitting the result has the same effect as splitting the input operand.
4367 SplitVecRes_ExtVecInRegOp(N, Lo, Hi);
4368
4369 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), N->getValueType(0), Lo, Hi);
4370}
4371
4372SDValue DAGTypeLegalizer::SplitVecOp_Gather(MemSDNode *N, unsigned OpNo) {
4373 (void)OpNo;
4374 SDValue Lo, Hi;
4375 SplitVecRes_Gather(N, Lo, Hi);
4376
4377 SDValue Res = DAG.getNode(ISD::CONCAT_VECTORS, N, N->getValueType(0), Lo, Hi);
4378 ReplaceValueWith(SDValue(N, 0), Res);
4379 return SDValue();
4380}
4381
4382SDValue DAGTypeLegalizer::SplitVecOp_VP_STORE(VPStoreSDNode *N, unsigned OpNo) {
4383 assert(N->isUnindexed() && "Indexed vp_store of vector?");
4384 SDValue Ch = N->getChain();
4385 SDValue Ptr = N->getBasePtr();
4386 SDValue Offset = N->getOffset();
4387 assert(Offset.isUndef() && "Unexpected VP store offset");
4388 SDValue Mask = N->getMask();
4389 SDValue EVL = N->getVectorLength();
4390 SDValue Data = N->getValue();
4391 Align Alignment = N->getBaseAlign();
4392 SDLoc DL(N);
4393
4394 SDValue DataLo, DataHi;
4395 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
4396 // Split Data operand
4397 GetSplitVector(Data, DataLo, DataHi);
4398 else
4399 std::tie(DataLo, DataHi) = DAG.SplitVector(Data, DL);
4400
4401 // Split Mask operand
4402 SDValue MaskLo, MaskHi;
4403 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC) {
4404 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
4405 } else {
4406 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
4407 GetSplitVector(Mask, MaskLo, MaskHi);
4408 else
4409 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
4410 }
4411
4412 EVT MemoryVT = N->getMemoryVT();
4413 EVT LoMemVT, HiMemVT;
4414 bool HiIsEmpty = false;
4415 std::tie(LoMemVT, HiMemVT) =
4416 DAG.GetDependentSplitDestVTs(MemoryVT, DataLo.getValueType(), &HiIsEmpty);
4417
4418 // Split EVL
4419 SDValue EVLLo, EVLHi;
4420 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(EVL, Data.getValueType(), DL);
4421
4422 SDValue Lo, Hi;
4423 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
4424 N->getPointerInfo(), MachineMemOperand::MOStore,
4425 LocationSize::beforeOrAfterPointer(), Alignment, N->getAAInfo(),
4426 N->getRanges());
4427
4428 Lo = DAG.getStoreVP(Ch, DL, DataLo, Ptr, Offset, MaskLo, EVLLo, LoMemVT, MMO,
4429 N->getAddressingMode(), N->isTruncatingStore(),
4430 N->isCompressingStore());
4431
4432 // If the hi vp_store has zero storage size, only the lo vp_store is needed.
4433 if (HiIsEmpty)
4434 return Lo;
4435
4436 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, DL, LoMemVT, DAG,
4437 N->isCompressingStore());
4438
4439 MachinePointerInfo MPI;
4440 if (LoMemVT.isScalableVector()) {
4441 Alignment = commonAlignment(Alignment,
4442 LoMemVT.getSizeInBits().getKnownMinValue() / 8);
4443 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
4444 } else
4445 MPI = N->getPointerInfo().getWithOffset(
4446 LoMemVT.getStoreSize().getFixedValue());
4447
4448 MMO = DAG.getMachineFunction().getMachineMemOperand(
4450 Alignment, N->getAAInfo(), N->getRanges());
4451
4452 Hi = DAG.getStoreVP(Ch, DL, DataHi, Ptr, Offset, MaskHi, EVLHi, HiMemVT, MMO,
4453 N->getAddressingMode(), N->isTruncatingStore(),
4454 N->isCompressingStore());
4455
4456 // Build a factor node to remember that this store is independent of the
4457 // other one.
4458 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4459}
4460
4461SDValue DAGTypeLegalizer::SplitVecOp_VP_STRIDED_STORE(VPStridedStoreSDNode *N,
4462 unsigned OpNo) {
4463 assert(N->isUnindexed() && "Indexed vp_strided_store of a vector?");
4464 assert(N->getOffset().isUndef() && "Unexpected VP strided store offset");
4465
4466 SDLoc DL(N);
4467
4468 SDValue Data = N->getValue();
4469 SDValue LoData, HiData;
4470 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
4471 GetSplitVector(Data, LoData, HiData);
4472 else
4473 std::tie(LoData, HiData) = DAG.SplitVector(Data, DL);
4474
4475 EVT LoMemVT, HiMemVT;
4476 bool HiIsEmpty = false;
4477 std::tie(LoMemVT, HiMemVT) = DAG.GetDependentSplitDestVTs(
4478 N->getMemoryVT(), LoData.getValueType(), &HiIsEmpty);
4479
4480 SDValue Mask = N->getMask();
4481 SDValue LoMask, HiMask;
4482 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC)
4483 SplitVecRes_SETCC(Mask.getNode(), LoMask, HiMask);
4484 else if (getTypeAction(Mask.getValueType()) ==
4486 GetSplitVector(Mask, LoMask, HiMask);
4487 else
4488 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
4489
4490 SDValue LoEVL, HiEVL;
4491 std::tie(LoEVL, HiEVL) =
4492 DAG.SplitEVL(N->getVectorLength(), Data.getValueType(), DL);
4493
4494 // Generate the low vp_strided_store
4495 SDValue Lo = DAG.getStridedStoreVP(
4496 N->getChain(), DL, LoData, N->getBasePtr(), N->getOffset(),
4497 N->getStride(), LoMask, LoEVL, LoMemVT, N->getMemOperand(),
4498 N->getAddressingMode(), N->isTruncatingStore(), N->isCompressingStore());
4499
4500 // If the high vp_strided_store has zero storage size, only the low
4501 // vp_strided_store is needed.
4502 if (HiIsEmpty)
4503 return Lo;
4504
4505 // Generate the high vp_strided_store.
4506 // To calculate the high base address, we need to sum to the low base
4507 // address stride number of bytes for each element already stored by low,
4508 // that is: Ptr = Ptr + (LoEVL * Stride)
4509 EVT PtrVT = N->getBasePtr().getValueType();
4511 DAG.getNode(ISD::MUL, DL, PtrVT, LoEVL,
4512 DAG.getSExtOrTrunc(N->getStride(), DL, PtrVT));
4513 SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, N->getBasePtr(), Increment);
4514
4515 Align Alignment = N->getBaseAlign();
4516 if (LoMemVT.isScalableVector())
4517 Alignment = commonAlignment(Alignment,
4518 LoMemVT.getSizeInBits().getKnownMinValue() / 8);
4519
4520 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
4521 MachinePointerInfo(N->getPointerInfo().getAddrSpace()),
4523 Alignment, N->getAAInfo(), N->getRanges());
4524
4525 SDValue Hi = DAG.getStridedStoreVP(
4526 N->getChain(), DL, HiData, Ptr, N->getOffset(), N->getStride(), HiMask,
4527 HiEVL, HiMemVT, MMO, N->getAddressingMode(), N->isTruncatingStore(),
4528 N->isCompressingStore());
4529
4530 // Build a factor node to remember that this store is independent of the
4531 // other one.
4532 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4533}
4534
4535SDValue DAGTypeLegalizer::SplitVecOp_MSTORE(MaskedStoreSDNode *N,
4536 unsigned OpNo) {
4537 assert(N->isUnindexed() && "Indexed masked store of vector?");
4538 SDValue Ch = N->getChain();
4539 SDValue Ptr = N->getBasePtr();
4540 SDValue Offset = N->getOffset();
4541 assert(Offset.isUndef() && "Unexpected indexed masked store offset");
4542 SDValue Mask = N->getMask();
4543 SDValue Data = N->getValue();
4544 Align Alignment = N->getBaseAlign();
4545 SDLoc DL(N);
4546
4547 SDValue DataLo, DataHi;
4548 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
4549 // Split Data operand
4550 GetSplitVector(Data, DataLo, DataHi);
4551 else
4552 std::tie(DataLo, DataHi) = DAG.SplitVector(Data, DL);
4553
4554 // Split Mask operand
4555 SDValue MaskLo, MaskHi;
4556 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC) {
4557 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
4558 } else {
4559 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
4560 GetSplitVector(Mask, MaskLo, MaskHi);
4561 else
4562 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
4563 }
4564
4565 EVT MemoryVT = N->getMemoryVT();
4566 EVT LoMemVT, HiMemVT;
4567 bool HiIsEmpty = false;
4568 std::tie(LoMemVT, HiMemVT) =
4569 DAG.GetDependentSplitDestVTs(MemoryVT, DataLo.getValueType(), &HiIsEmpty);
4570
4571 SDValue Lo, Hi, Res;
4572 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
4573 N->getPointerInfo(), MachineMemOperand::MOStore,
4574 LocationSize::beforeOrAfterPointer(), Alignment, N->getAAInfo(),
4575 N->getRanges());
4576
4577 Lo = DAG.getMaskedStore(Ch, DL, DataLo, Ptr, Offset, MaskLo, LoMemVT, MMO,
4578 N->getAddressingMode(), N->isTruncatingStore(),
4579 N->isCompressingStore());
4580
4581 if (HiIsEmpty) {
4582 // The hi masked store has zero storage size.
4583 // Only the lo masked store is needed.
4584 Res = Lo;
4585 } else {
4586
4587 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, DL, LoMemVT, DAG,
4588 N->isCompressingStore());
4589
4590 MachinePointerInfo MPI;
4591 if (LoMemVT.isScalableVector()) {
4592 Alignment = commonAlignment(
4593 Alignment, LoMemVT.getSizeInBits().getKnownMinValue() / 8);
4594 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
4595 } else
4596 MPI = N->getPointerInfo().getWithOffset(
4597 LoMemVT.getStoreSize().getFixedValue());
4598
4599 MMO = DAG.getMachineFunction().getMachineMemOperand(
4601 Alignment, N->getAAInfo(), N->getRanges());
4602
4603 Hi = DAG.getMaskedStore(Ch, DL, DataHi, Ptr, Offset, MaskHi, HiMemVT, MMO,
4604 N->getAddressingMode(), N->isTruncatingStore(),
4605 N->isCompressingStore());
4606
4607 // Build a factor node to remember that this store is independent of the
4608 // other one.
4609 Res = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4610 }
4611
4612 return Res;
4613}
4614
4615SDValue DAGTypeLegalizer::SplitVecOp_Scatter(MemSDNode *N, unsigned OpNo) {
4616 SDValue Ch = N->getChain();
4617 SDValue Ptr = N->getBasePtr();
4618 EVT MemoryVT = N->getMemoryVT();
4619 Align Alignment = N->getBaseAlign();
4620 SDLoc DL(N);
4621 struct Operands {
4622 SDValue Mask;
4623 SDValue Index;
4624 SDValue Scale;
4625 SDValue Data;
4626 } Ops = [&]() -> Operands {
4627 if (auto *MSC = dyn_cast<MaskedScatterSDNode>(N)) {
4628 return {MSC->getMask(), MSC->getIndex(), MSC->getScale(),
4629 MSC->getValue()};
4630 }
4631 auto *VPSC = cast<VPScatterSDNode>(N);
4632 return {VPSC->getMask(), VPSC->getIndex(), VPSC->getScale(),
4633 VPSC->getValue()};
4634 }();
4635 // Split all operands
4636
4637 EVT LoMemVT, HiMemVT;
4638 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
4639
4640 SDValue DataLo, DataHi;
4641 if (getTypeAction(Ops.Data.getValueType()) == TargetLowering::TypeSplitVector)
4642 // Split Data operand
4643 GetSplitVector(Ops.Data, DataLo, DataHi);
4644 else
4645 std::tie(DataLo, DataHi) = DAG.SplitVector(Ops.Data, DL);
4646
4647 // Split Mask operand
4648 SDValue MaskLo, MaskHi;
4649 if (OpNo == 1 && Ops.Mask.getOpcode() == ISD::SETCC) {
4650 SplitVecRes_SETCC(Ops.Mask.getNode(), MaskLo, MaskHi);
4651 } else {
4652 std::tie(MaskLo, MaskHi) = SplitMask(Ops.Mask, DL);
4653 }
4654
4655 SDValue IndexHi, IndexLo;
4656 if (getTypeAction(Ops.Index.getValueType()) ==
4658 GetSplitVector(Ops.Index, IndexLo, IndexHi);
4659 else
4660 std::tie(IndexLo, IndexHi) = DAG.SplitVector(Ops.Index, DL);
4661
4662 SDValue Lo;
4663 MachineMemOperand::Flags MMOFlags = N->getMemOperand()->getFlags();
4664 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
4665 N->getPointerInfo(), MMOFlags, LocationSize::beforeOrAfterPointer(),
4666 Alignment, N->getAAInfo(), N->getRanges());
4667
4668 if (auto *MSC = dyn_cast<MaskedScatterSDNode>(N)) {
4669 SDValue OpsLo[] = {Ch, DataLo, MaskLo, Ptr, IndexLo, Ops.Scale};
4670 Lo =
4671 DAG.getMaskedScatter(DAG.getVTList(MVT::Other), LoMemVT, DL, OpsLo, MMO,
4672 MSC->getIndexType(), MSC->isTruncatingStore());
4673
4674 // The order of the Scatter operation after split is well defined. The "Hi"
4675 // part comes after the "Lo". So these two operations should be chained one
4676 // after another.
4677 SDValue OpsHi[] = {Lo, DataHi, MaskHi, Ptr, IndexHi, Ops.Scale};
4678 return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), HiMemVT, DL, OpsHi,
4679 MMO, MSC->getIndexType(),
4680 MSC->isTruncatingStore());
4681 }
4682 auto *VPSC = cast<VPScatterSDNode>(N);
4683 SDValue EVLLo, EVLHi;
4684 std::tie(EVLLo, EVLHi) =
4685 DAG.SplitEVL(VPSC->getVectorLength(), Ops.Data.getValueType(), DL);
4686
4687 SDValue OpsLo[] = {Ch, DataLo, Ptr, IndexLo, Ops.Scale, MaskLo, EVLLo};
4688 Lo = DAG.getScatterVP(DAG.getVTList(MVT::Other), LoMemVT, DL, OpsLo, MMO,
4689 VPSC->getIndexType());
4690
4691 // The order of the Scatter operation after split is well defined. The "Hi"
4692 // part comes after the "Lo". So these two operations should be chained one
4693 // after another.
4694 SDValue OpsHi[] = {Lo, DataHi, Ptr, IndexHi, Ops.Scale, MaskHi, EVLHi};
4695 return DAG.getScatterVP(DAG.getVTList(MVT::Other), HiMemVT, DL, OpsHi, MMO,
4696 VPSC->getIndexType());
4697}
4698
4699SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) {
4700 assert(N->isUnindexed() && "Indexed store of vector?");
4701 assert(OpNo == 1 && "Can only split the stored value");
4702 SDLoc DL(N);
4703
4704 bool isTruncating = N->isTruncatingStore();
4705 SDValue Ch = N->getChain();
4706 SDValue Ptr = N->getBasePtr();
4707 EVT MemoryVT = N->getMemoryVT();
4708 Align Alignment = N->getBaseAlign();
4709 MachineMemOperand::Flags MMOFlags = N->getMemOperand()->getFlags();
4710 AAMDNodes AAInfo = N->getAAInfo();
4711 SDValue Lo, Hi;
4712 GetSplitVector(N->getOperand(1), Lo, Hi);
4713
4714 EVT LoMemVT, HiMemVT;
4715 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
4716
4717 // Scalarize if the split halves are not byte-sized.
4718 if (!LoMemVT.isByteSized() || !HiMemVT.isByteSized())
4719 return TLI.scalarizeVectorStore(N, DAG);
4720
4721 if (isTruncating)
4722 Lo = DAG.getTruncStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), LoMemVT,
4723 Alignment, MMOFlags, AAInfo);
4724 else
4725 Lo = DAG.getStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), Alignment, MMOFlags,
4726 AAInfo);
4727
4728 MachinePointerInfo MPI;
4729 IncrementPointer(N, LoMemVT, MPI, Ptr);
4730
4731 if (isTruncating)
4732 Hi = DAG.getTruncStore(Ch, DL, Hi, Ptr, MPI,
4733 HiMemVT, Alignment, MMOFlags, AAInfo);
4734 else
4735 Hi = DAG.getStore(Ch, DL, Hi, Ptr, MPI, Alignment, MMOFlags, AAInfo);
4736
4737 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4738}
4739
4740SDValue DAGTypeLegalizer::SplitVecOp_CONCAT_VECTORS(SDNode *N) {
4741 SDLoc DL(N);
4742
4743 // The input operands all must have the same type, and we know the result
4744 // type is valid. Convert this to a buildvector which extracts all the
4745 // input elements.
4746 // TODO: If the input elements are power-two vectors, we could convert this to
4747 // a new CONCAT_VECTORS node with elements that are half-wide.
4749 EVT EltVT = N->getValueType(0).getVectorElementType();
4750 for (const SDValue &Op : N->op_values()) {
4751 for (unsigned i = 0, e = Op.getValueType().getVectorNumElements();
4752 i != e; ++i) {
4753 Elts.push_back(DAG.getExtractVectorElt(DL, EltVT, Op, i));
4754 }
4755 }
4756
4757 return DAG.getBuildVector(N->getValueType(0), DL, Elts);
4758}
4759
4760SDValue DAGTypeLegalizer::SplitVecOp_TruncateHelper(SDNode *N) {
4761 // The result type is legal, but the input type is illegal. If splitting
4762 // ends up with the result type of each half still being legal, just
4763 // do that. If, however, that would result in an illegal result type,
4764 // we can try to get more clever with power-two vectors. Specifically,
4765 // split the input type, but also widen the result element size, then
4766 // concatenate the halves and truncate again. For example, consider a target
4767 // where v8i8 is legal and v8i32 is not (ARM, which doesn't have 256-bit
4768 // vectors). To perform a "%res = v8i8 trunc v8i32 %in" we do:
4769 // %inlo = v4i32 extract_subvector %in, 0
4770 // %inhi = v4i32 extract_subvector %in, 4
4771 // %lo16 = v4i16 trunc v4i32 %inlo
4772 // %hi16 = v4i16 trunc v4i32 %inhi
4773 // %in16 = v8i16 concat_vectors v4i16 %lo16, v4i16 %hi16
4774 // %res = v8i8 trunc v8i16 %in16
4775 //
4776 // Without this transform, the original truncate would end up being
4777 // scalarized, which is pretty much always a last resort.
4778 unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
4779 SDValue InVec = N->getOperand(OpNo);
4780 EVT InVT = InVec->getValueType(0);
4781 EVT OutVT = N->getValueType(0);
4782 ElementCount NumElements = OutVT.getVectorElementCount();
4783 bool IsFloat = OutVT.isFloatingPoint();
4784
4785 unsigned InElementSize = InVT.getScalarSizeInBits();
4786 unsigned OutElementSize = OutVT.getScalarSizeInBits();
4787
4788 // Determine the split output VT. If its legal we can just split dirctly.
4789 EVT LoOutVT, HiOutVT;
4790 std::tie(LoOutVT, HiOutVT) = DAG.GetSplitDestVTs(OutVT);
4791 assert(LoOutVT == HiOutVT && "Unequal split?");
4792
4793 // If the input elements are only 1/2 the width of the result elements,
4794 // just use the normal splitting. Our trick only work if there's room
4795 // to split more than once.
4796 if (isTypeLegal(LoOutVT) || InElementSize <= OutElementSize * 2 ||
4797 (IsFloat && !isPowerOf2_32(InElementSize)))
4798 return SplitVecOp_UnaryOp(N);
4799 SDLoc DL(N);
4800
4801 // Don't touch if this will be scalarized.
4802 EVT FinalVT = InVT;
4803 while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
4804 FinalVT = FinalVT.getHalfNumVectorElementsVT(*DAG.getContext());
4805
4806 if (getTypeAction(FinalVT) == TargetLowering::TypeScalarizeVector)
4807 return SplitVecOp_UnaryOp(N);
4808
4809 // Get the split input vector.
4810 SDValue InLoVec, InHiVec;
4811 GetSplitVector(InVec, InLoVec, InHiVec);
4812
4813 // Truncate them to 1/2 the element size.
4814 //
4815 // This assumes the number of elements is a power of two; any vector that
4816 // isn't should be widened, not split.
4817 EVT HalfElementVT = IsFloat ?
4818 EVT::getFloatingPointVT(InElementSize/2) :
4819 EVT::getIntegerVT(*DAG.getContext(), InElementSize/2);
4820 EVT HalfVT = EVT::getVectorVT(*DAG.getContext(), HalfElementVT,
4821 NumElements.divideCoefficientBy(2));
4822
4823 SDValue HalfLo;
4824 SDValue HalfHi;
4825 SDValue Chain;
4826 if (N->isStrictFPOpcode()) {
4827 HalfLo = DAG.getNode(N->getOpcode(), DL, {HalfVT, MVT::Other},
4828 {N->getOperand(0), InLoVec});
4829 HalfHi = DAG.getNode(N->getOpcode(), DL, {HalfVT, MVT::Other},
4830 {N->getOperand(0), InHiVec});
4831 // Legalize the chain result - switch anything that used the old chain to
4832 // use the new one.
4833 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, HalfLo.getValue(1),
4834 HalfHi.getValue(1));
4835 } else {
4836 HalfLo = DAG.getNode(N->getOpcode(), DL, HalfVT, InLoVec);
4837 HalfHi = DAG.getNode(N->getOpcode(), DL, HalfVT, InHiVec);
4838 }
4839
4840 // Concatenate them to get the full intermediate truncation result.
4841 EVT InterVT = EVT::getVectorVT(*DAG.getContext(), HalfElementVT, NumElements);
4842 SDValue InterVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InterVT, HalfLo,
4843 HalfHi);
4844 // Now finish up by truncating all the way down to the original result
4845 // type. This should normally be something that ends up being legal directly,
4846 // but in theory if a target has very wide vectors and an annoyingly
4847 // restricted set of legal types, this split can chain to build things up.
4848
4849 if (N->isStrictFPOpcode()) {
4850 SDValue Res = DAG.getNode(
4851 ISD::STRICT_FP_ROUND, DL, {OutVT, MVT::Other},
4852 {Chain, InterVec,
4853 DAG.getTargetConstant(0, DL, TLI.getPointerTy(DAG.getDataLayout()))});
4854 // Relink the chain
4855 ReplaceValueWith(SDValue(N, 1), SDValue(Res.getNode(), 1));
4856 return Res;
4857 }
4858
4859 return IsFloat
4860 ? DAG.getNode(ISD::FP_ROUND, DL, OutVT, InterVec,
4861 DAG.getTargetConstant(
4862 0, DL, TLI.getPointerTy(DAG.getDataLayout())))
4863 : DAG.getNode(ISD::TRUNCATE, DL, OutVT, InterVec);
4864}
4865
4866SDValue DAGTypeLegalizer::SplitVecOp_VSETCC(SDNode *N) {
4867 unsigned Opc = N->getOpcode();
4868 bool isStrict = Opc == ISD::STRICT_FSETCC || Opc == ISD::STRICT_FSETCCS;
4869 assert(N->getValueType(0).isVector() &&
4870 N->getOperand(isStrict ? 1 : 0).getValueType().isVector() &&
4871 "Operand types must be vectors");
4872 // The result has a legal vector type, but the input needs splitting.
4873 SDValue Lo0, Hi0, Lo1, Hi1, LoRes, HiRes;
4874 SDLoc DL(N);
4875 GetSplitVector(N->getOperand(isStrict ? 1 : 0), Lo0, Hi0);
4876 GetSplitVector(N->getOperand(isStrict ? 2 : 1), Lo1, Hi1);
4877
4878 EVT VT = N->getValueType(0);
4879 EVT PartResVT = getSetCCResultType(Lo0.getValueType());
4880
4881 if (Opc == ISD::SETCC) {
4882 LoRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Lo0, Lo1, N->getOperand(2));
4883 HiRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Hi0, Hi1, N->getOperand(2));
4884 } else if (isStrict) {
4885 LoRes = DAG.getNode(Opc, DL, DAG.getVTList(PartResVT, N->getValueType(1)),
4886 N->getOperand(0), Lo0, Lo1, N->getOperand(3));
4887 HiRes = DAG.getNode(Opc, DL, DAG.getVTList(PartResVT, N->getValueType(1)),
4888 N->getOperand(0), Hi0, Hi1, N->getOperand(3));
4889 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
4890 LoRes.getValue(1), HiRes.getValue(1));
4891 ReplaceValueWith(SDValue(N, 1), NewChain);
4892 } else {
4893 assert(Opc == ISD::VP_SETCC && "Expected VP_SETCC opcode");
4894 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
4895 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(3));
4896 std::tie(EVLLo, EVLHi) =
4897 DAG.SplitEVL(N->getOperand(4), N->getValueType(0), DL);
4898 LoRes = DAG.getNode(ISD::VP_SETCC, DL, PartResVT, Lo0, Lo1,
4899 N->getOperand(2), MaskLo, EVLLo);
4900 HiRes = DAG.getNode(ISD::VP_SETCC, DL, PartResVT, Hi0, Hi1,
4901 N->getOperand(2), MaskHi, EVLHi);
4902 }
4903
4904 EVT ConcatVT = PartResVT.getDoubleNumVectorElementsVT(*DAG.getContext());
4905 SDValue Con = DAG.getNode(ISD::CONCAT_VECTORS, DL, ConcatVT, LoRes, HiRes);
4906 if (VT == ConcatVT)
4907 return Con;
4908
4909 EVT OpVT = N->getOperand(0).getValueType();
4910 ISD::NodeType ExtendCode =
4911 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
4912 return DAG.getExtOrTrunc(Con, DL, VT, ExtendCode);
4913}
4914
4915
4916SDValue DAGTypeLegalizer::SplitVecOp_FP_ROUND(SDNode *N) {
4917 // The result has a legal vector type, but the input needs splitting.
4918 EVT ResVT = N->getValueType(0);
4919 SDValue Lo, Hi;
4920 SDLoc DL(N);
4921 GetSplitVector(N->getOperand(N->isStrictFPOpcode() ? 1 : 0), Lo, Hi);
4922 EVT InVT = Lo.getValueType();
4923
4924 EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
4925 InVT.getVectorElementCount());
4926
4927 if (N->isStrictFPOpcode()) {
4928 Lo = DAG.getNode(N->getOpcode(), DL, {OutVT, MVT::Other},
4929 {N->getOperand(0), Lo, N->getOperand(2)});
4930 Hi = DAG.getNode(N->getOpcode(), DL, {OutVT, MVT::Other},
4931 {N->getOperand(0), Hi, N->getOperand(2)});
4932 // Legalize the chain result - switch anything that used the old chain to
4933 // use the new one.
4934 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
4935 Lo.getValue(1), Hi.getValue(1));
4936 ReplaceValueWith(SDValue(N, 1), NewChain);
4937 } else if (N->getOpcode() == ISD::VP_FP_ROUND) {
4938 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
4939 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
4940 std::tie(EVLLo, EVLHi) =
4941 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), DL);
4942 Lo = DAG.getNode(ISD::VP_FP_ROUND, DL, OutVT, Lo, MaskLo, EVLLo);
4943 Hi = DAG.getNode(ISD::VP_FP_ROUND, DL, OutVT, Hi, MaskHi, EVLHi);
4944 } else {
4945 Lo = DAG.getNode(N->getOpcode(), DL, OutVT, Lo, N->getOperand(1));
4946 Hi = DAG.getNode(N->getOpcode(), DL, OutVT, Hi, N->getOperand(1));
4947 }
4948
4949 return DAG.getNode(ISD::CONCAT_VECTORS, DL, ResVT, Lo, Hi);
4950}
4951
4952// Split a vector type in an FP binary operation where the second operand has a
4953// different type from the first.
4954//
4955// The result (and the first input) has a legal vector type, but the second
4956// input needs splitting.
4957SDValue DAGTypeLegalizer::SplitVecOp_FPOpDifferentTypes(SDNode *N) {
4958 SDLoc DL(N);
4959
4960 EVT LHSLoVT, LHSHiVT;
4961 std::tie(LHSLoVT, LHSHiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
4962
4963 if (!isTypeLegal(LHSLoVT) || !isTypeLegal(LHSHiVT))
4964 return DAG.UnrollVectorOp(N, N->getValueType(0).getVectorNumElements());
4965
4966 SDValue LHSLo, LHSHi;
4967 std::tie(LHSLo, LHSHi) =
4968 DAG.SplitVector(N->getOperand(0), DL, LHSLoVT, LHSHiVT);
4969
4970 SDValue RHSLo, RHSHi;
4971 std::tie(RHSLo, RHSHi) = DAG.SplitVector(N->getOperand(1), DL);
4972
4973 SDValue Lo = DAG.getNode(N->getOpcode(), DL, LHSLoVT, LHSLo, RHSLo);
4974 SDValue Hi = DAG.getNode(N->getOpcode(), DL, LHSHiVT, LHSHi, RHSHi);
4975
4976 return DAG.getNode(ISD::CONCAT_VECTORS, DL, N->getValueType(0), Lo, Hi);
4977}
4978
4979SDValue DAGTypeLegalizer::SplitVecOp_CMP(SDNode *N) {
4980 LLVMContext &Ctxt = *DAG.getContext();
4981 SDLoc dl(N);
4982
4983 SDValue LHSLo, LHSHi, RHSLo, RHSHi;
4984 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
4985 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
4986
4987 EVT ResVT = N->getValueType(0);
4988 ElementCount SplitOpEC = LHSLo.getValueType().getVectorElementCount();
4989 EVT NewResVT =
4990 EVT::getVectorVT(Ctxt, ResVT.getVectorElementType(), SplitOpEC);
4991
4992 SDValue Lo = DAG.getNode(N->getOpcode(), dl, NewResVT, LHSLo, RHSLo);
4993 SDValue Hi = DAG.getNode(N->getOpcode(), dl, NewResVT, LHSHi, RHSHi);
4994
4995 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
4996}
4997
4998SDValue DAGTypeLegalizer::SplitVecOp_FP_TO_XINT_SAT(SDNode *N) {
4999 EVT ResVT = N->getValueType(0);
5000 SDValue Lo, Hi;
5001 SDLoc dl(N);
5002 GetSplitVector(N->getOperand(0), Lo, Hi);
5003 EVT InVT = Lo.getValueType();
5004
5005 EVT NewResVT =
5006 EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
5007 InVT.getVectorElementCount());
5008
5009 Lo = DAG.getNode(N->getOpcode(), dl, NewResVT, Lo, N->getOperand(1));
5010 Hi = DAG.getNode(N->getOpcode(), dl, NewResVT, Hi, N->getOperand(1));
5011
5012 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
5013}
5014
5015SDValue DAGTypeLegalizer::SplitVecOp_CttzElts(SDNode *N) {
5016 SDLoc DL(N);
5017 EVT ResVT = N->getValueType(0);
5018
5019 SDValue Lo, Hi;
5020 SDValue VecOp = N->getOperand(0);
5021 GetSplitVector(VecOp, Lo, Hi);
5022
5023 // if CTTZ_ELTS(Lo) != VL => CTTZ_ELTS(Lo).
5024 // else => VL + (CTTZ_ELTS(Hi) or CTTZ_ELTS_ZERO_POISON(Hi)).
5025 SDValue ResLo = DAG.getNode(ISD::CTTZ_ELTS, DL, ResVT, Lo);
5026 SDValue VL =
5027 DAG.getElementCount(DL, ResVT, Lo.getValueType().getVectorElementCount());
5028 SDValue ResLoNotVL =
5029 DAG.getSetCC(DL, getSetCCResultType(ResVT), ResLo, VL, ISD::SETNE);
5030 SDValue ResHi = DAG.getNode(N->getOpcode(), DL, ResVT, Hi);
5031 return DAG.getSelect(DL, ResVT, ResLoNotVL, ResLo,
5032 DAG.getNode(ISD::ADD, DL, ResVT, VL, ResHi));
5033}
5034
5035SDValue DAGTypeLegalizer::SplitVecOp_VP_CttzElements(SDNode *N) {
5036 SDLoc DL(N);
5037 EVT ResVT = N->getValueType(0);
5038
5039 SDValue Lo, Hi;
5040 SDValue VecOp = N->getOperand(0);
5041 GetSplitVector(VecOp, Lo, Hi);
5042
5043 auto [MaskLo, MaskHi] = SplitMask(N->getOperand(1));
5044 auto [EVLLo, EVLHi] =
5045 DAG.SplitEVL(N->getOperand(2), VecOp.getValueType(), DL);
5046 SDValue VLo = DAG.getZExtOrTrunc(EVLLo, DL, ResVT);
5047
5048 // if VP_CTTZ_ELTS(Lo) != EVLLo => VP_CTTZ_ELTS(Lo).
5049 // else => EVLLo + (VP_CTTZ_ELTS(Hi) or VP_CTTZ_ELTS_ZERO_POISON(Hi)).
5050 SDValue ResLo = DAG.getNode(ISD::VP_CTTZ_ELTS, DL, ResVT, Lo, MaskLo, EVLLo);
5051 SDValue ResLoNotEVL =
5052 DAG.getSetCC(DL, getSetCCResultType(ResVT), ResLo, VLo, ISD::SETNE);
5053 SDValue ResHi = DAG.getNode(N->getOpcode(), DL, ResVT, Hi, MaskHi, EVLHi);
5054 return DAG.getSelect(DL, ResVT, ResLoNotEVL, ResLo,
5055 DAG.getNode(ISD::ADD, DL, ResVT, VLo, ResHi));
5056}
5057
5058SDValue DAGTypeLegalizer::SplitVecOp_VECTOR_HISTOGRAM(SDNode *N) {
5059 MaskedHistogramSDNode *HG = cast<MaskedHistogramSDNode>(N);
5060 SDLoc DL(HG);
5061 SDValue Inc = HG->getInc();
5062 SDValue Ptr = HG->getBasePtr();
5063 SDValue Scale = HG->getScale();
5064 SDValue IntID = HG->getIntID();
5065 EVT MemVT = HG->getMemoryVT();
5066 MachineMemOperand *MMO = HG->getMemOperand();
5067 ISD::MemIndexType IndexType = HG->getIndexType();
5068
5069 SDValue IndexLo, IndexHi, MaskLo, MaskHi;
5070 std::tie(IndexLo, IndexHi) = DAG.SplitVector(HG->getIndex(), DL);
5071 std::tie(MaskLo, MaskHi) = DAG.SplitVector(HG->getMask(), DL);
5072 SDValue OpsLo[] = {HG->getChain(), Inc, MaskLo, Ptr, IndexLo, Scale, IntID};
5073 SDValue Lo = DAG.getMaskedHistogram(DAG.getVTList(MVT::Other), MemVT, DL,
5074 OpsLo, MMO, IndexType);
5075 SDValue OpsHi[] = {Lo, Inc, MaskHi, Ptr, IndexHi, Scale, IntID};
5076 return DAG.getMaskedHistogram(DAG.getVTList(MVT::Other), MemVT, DL, OpsHi,
5077 MMO, IndexType);
5078}
5079
5080SDValue DAGTypeLegalizer::SplitVecOp_PARTIAL_REDUCE_MLA(SDNode *N) {
5081 SDValue Acc = N->getOperand(0);
5082 assert(getTypeAction(Acc.getValueType()) != TargetLowering::TypeSplitVector &&
5083 "Accumulator should already be a legal type, and shouldn't need "
5084 "further splitting");
5085
5086 SDLoc DL(N);
5087 SDValue Input1Lo, Input1Hi, Input2Lo, Input2Hi;
5088 GetSplitVector(N->getOperand(1), Input1Lo, Input1Hi);
5089 GetSplitVector(N->getOperand(2), Input2Lo, Input2Hi);
5090 unsigned Opcode = N->getOpcode();
5091 EVT ResultVT = Acc.getValueType();
5092
5093 SDValue Lo = DAG.getNode(Opcode, DL, ResultVT, Acc, Input1Lo, Input2Lo);
5094 return DAG.getNode(Opcode, DL, ResultVT, Lo, Input1Hi, Input2Hi);
5095}
5096
5097//===----------------------------------------------------------------------===//
5098// Result Vector Widening
5099//===----------------------------------------------------------------------===//
5100
5101void DAGTypeLegalizer::ReplaceOtherWidenResults(SDNode *N, SDNode *WidenNode,
5102 unsigned WidenResNo) {
5103 unsigned NumResults = N->getNumValues();
5104 for (unsigned ResNo = 0; ResNo < NumResults; ResNo++) {
5105 if (ResNo == WidenResNo)
5106 continue;
5107 EVT ResVT = N->getValueType(ResNo);
5108 if (getTypeAction(ResVT) == TargetLowering::TypeWidenVector) {
5109 SetWidenedVector(SDValue(N, ResNo), SDValue(WidenNode, ResNo));
5110 } else {
5111 SDLoc DL(N);
5112 SDValue ResVal =
5113 DAG.getExtractSubvector(DL, ResVT, SDValue(WidenNode, ResNo), 0);
5114 ReplaceValueWith(SDValue(N, ResNo), ResVal);
5115 }
5116 }
5117}
5118
5119void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
5120 LLVM_DEBUG(dbgs() << "Widen node result " << ResNo << ": "; N->dump(&DAG));
5121
5122 // See if the target wants to custom widen this node.
5123 if (CustomWidenLowerNode(N, N->getValueType(ResNo)))
5124 return;
5125
5126 SDValue Res = SDValue();
5127
5128 auto unrollExpandedOp = [&]() {
5129 // We're going to widen this vector op to a legal type by padding with undef
5130 // elements. If the wide vector op is eventually going to be expanded to
5131 // scalar libcalls, then unroll into scalar ops now to avoid unnecessary
5132 // libcalls on the undef elements.
5133 EVT VT = N->getValueType(0);
5134 EVT WideVecVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
5135 if (!TLI.isOperationLegalOrCustomOrPromote(N->getOpcode(), WideVecVT) &&
5136 TLI.isOperationExpandOrLibCall(N->getOpcode(), VT.getScalarType())) {
5137 Res = DAG.UnrollVectorOp(N, WideVecVT.getVectorNumElements());
5138 if (N->getNumValues() > 1)
5139 ReplaceOtherWidenResults(N, Res.getNode(), ResNo);
5140 return true;
5141 }
5142 return false;
5143 };
5144
5145 switch (N->getOpcode()) {
5146 default:
5147#ifndef NDEBUG
5148 dbgs() << "WidenVectorResult #" << ResNo << ": ";
5149 N->dump(&DAG);
5150 dbgs() << "\n";
5151#endif
5152 report_fatal_error("Do not know how to widen the result of this operator!");
5153
5156 Res = WidenVecRes_LOOP_DEPENDENCE_MASK(N);
5157 break;
5158 case ISD::MERGE_VALUES: Res = WidenVecRes_MERGE_VALUES(N, ResNo); break;
5159 case ISD::ADDRSPACECAST:
5160 Res = WidenVecRes_ADDRSPACECAST(N);
5161 break;
5162 case ISD::AssertZext: Res = WidenVecRes_AssertZext(N); break;
5163 case ISD::BITCAST: Res = WidenVecRes_BITCAST(N); break;
5164 case ISD::BUILD_VECTOR: Res = WidenVecRes_BUILD_VECTOR(N); break;
5165 case ISD::CONCAT_VECTORS: Res = WidenVecRes_CONCAT_VECTORS(N); break;
5167 Res = WidenVecRes_INSERT_SUBVECTOR(N);
5168 break;
5169 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecRes_EXTRACT_SUBVECTOR(N); break;
5170 case ISD::INSERT_VECTOR_ELT: Res = WidenVecRes_INSERT_VECTOR_ELT(N); break;
5171 case ISD::ATOMIC_LOAD:
5172 Res = WidenVecRes_ATOMIC_LOAD(cast<AtomicSDNode>(N));
5173 break;
5174 case ISD::LOAD: Res = WidenVecRes_LOAD(N); break;
5175 case ISD::STEP_VECTOR:
5176 case ISD::SPLAT_VECTOR:
5178 Res = WidenVecRes_ScalarOp(N);
5179 break;
5180 case ISD::SIGN_EXTEND_INREG: Res = WidenVecRes_InregOp(N); break;
5181 case ISD::VSELECT:
5182 case ISD::SELECT:
5183 case ISD::VP_SELECT:
5184 case ISD::VP_MERGE:
5185 Res = WidenVecRes_Select(N);
5186 break;
5187 case ISD::SELECT_CC: Res = WidenVecRes_SELECT_CC(N); break;
5188 case ISD::VP_SETCC:
5189 case ISD::SETCC: Res = WidenVecRes_SETCC(N); break;
5190 case ISD::POISON:
5191 case ISD::UNDEF: Res = WidenVecRes_UNDEF(N); break;
5193 Res = WidenVecRes_VECTOR_SHUFFLE(cast<ShuffleVectorSDNode>(N));
5194 break;
5195 case ISD::VP_LOAD:
5196 Res = WidenVecRes_VP_LOAD(cast<VPLoadSDNode>(N));
5197 break;
5198 case ISD::VP_LOAD_FF:
5199 Res = WidenVecRes_VP_LOAD_FF(cast<VPLoadFFSDNode>(N));
5200 break;
5201 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
5202 Res = WidenVecRes_VP_STRIDED_LOAD(cast<VPStridedLoadSDNode>(N));
5203 break;
5205 Res = WidenVecRes_VECTOR_COMPRESS(N);
5206 break;
5207 case ISD::MLOAD:
5208 Res = WidenVecRes_MLOAD(cast<MaskedLoadSDNode>(N));
5209 break;
5210 case ISD::MGATHER:
5211 Res = WidenVecRes_MGATHER(cast<MaskedGatherSDNode>(N));
5212 break;
5213 case ISD::VP_GATHER:
5214 Res = WidenVecRes_VP_GATHER(cast<VPGatherSDNode>(N));
5215 break;
5217 Res = WidenVecRes_VECTOR_REVERSE(N);
5218 break;
5220 Res = WidenVecRes_GET_ACTIVE_LANE_MASK(N);
5221 break;
5222
5223 case ISD::ADD: case ISD::VP_ADD:
5224 case ISD::AND: case ISD::VP_AND:
5225 case ISD::MUL: case ISD::VP_MUL:
5226 case ISD::MULHS:
5227 case ISD::MULHU:
5228 case ISD::ABDS:
5229 case ISD::ABDU:
5230 case ISD::OR: case ISD::VP_OR:
5231 case ISD::SUB: case ISD::VP_SUB:
5232 case ISD::XOR: case ISD::VP_XOR:
5233 case ISD::SHL: case ISD::VP_SHL:
5234 case ISD::SRA: case ISD::VP_SRA:
5235 case ISD::SRL: case ISD::VP_SRL:
5236 case ISD::CLMUL:
5237 case ISD::CLMULR:
5238 case ISD::CLMULH:
5239 case ISD::FMINNUM:
5240 case ISD::FMINNUM_IEEE:
5241 case ISD::VP_FMINNUM:
5242 case ISD::FMAXNUM:
5243 case ISD::FMAXNUM_IEEE:
5244 case ISD::VP_FMAXNUM:
5245 case ISD::FMINIMUM:
5246 case ISD::VP_FMINIMUM:
5247 case ISD::FMAXIMUM:
5248 case ISD::VP_FMAXIMUM:
5249 case ISD::FMINIMUMNUM:
5250 case ISD::FMAXIMUMNUM:
5251 case ISD::SMIN: case ISD::VP_SMIN:
5252 case ISD::SMAX: case ISD::VP_SMAX:
5253 case ISD::UMIN: case ISD::VP_UMIN:
5254 case ISD::UMAX: case ISD::VP_UMAX:
5255 case ISD::UADDSAT: case ISD::VP_UADDSAT:
5256 case ISD::SADDSAT: case ISD::VP_SADDSAT:
5257 case ISD::USUBSAT: case ISD::VP_USUBSAT:
5258 case ISD::SSUBSAT: case ISD::VP_SSUBSAT:
5259 case ISD::SSHLSAT:
5260 case ISD::USHLSAT:
5261 case ISD::ROTL:
5262 case ISD::ROTR:
5263 case ISD::AVGFLOORS:
5264 case ISD::AVGFLOORU:
5265 case ISD::AVGCEILS:
5266 case ISD::AVGCEILU:
5267 // Vector-predicated binary op widening. Note that -- unlike the
5268 // unpredicated versions -- we don't have to worry about trapping on
5269 // operations like UDIV, FADD, etc., as we pass on the original vector
5270 // length parameter. This means the widened elements containing garbage
5271 // aren't active.
5272 case ISD::VP_SDIV:
5273 case ISD::VP_UDIV:
5274 case ISD::VP_SREM:
5275 case ISD::VP_UREM:
5276 case ISD::VP_FADD:
5277 case ISD::VP_FSUB:
5278 case ISD::VP_FMUL:
5279 case ISD::VP_FDIV:
5280 case ISD::VP_FREM:
5281 case ISD::VP_FCOPYSIGN:
5282 Res = WidenVecRes_Binary(N);
5283 break;
5284
5285 case ISD::MASKED_UDIV:
5286 case ISD::MASKED_SDIV:
5287 case ISD::MASKED_UREM:
5288 case ISD::MASKED_SREM:
5289 Res = WidenVecRes_MaskedBinary(N);
5290 break;
5291
5292 case ISD::SCMP:
5293 case ISD::UCMP:
5294 Res = WidenVecRes_CMP(N);
5295 break;
5296
5297 case ISD::FPOW:
5298 case ISD::FATAN2:
5299 case ISD::FREM:
5300 if (unrollExpandedOp())
5301 break;
5302 // If the target has custom/legal support for the scalar FP intrinsic ops
5303 // (they are probably not destined to become libcalls), then widen those
5304 // like any other binary ops.
5305 [[fallthrough]];
5306
5307 case ISD::FADD:
5308 case ISD::FMUL:
5309 case ISD::FSUB:
5310 case ISD::FDIV:
5311 case ISD::SDIV:
5312 case ISD::UDIV:
5313 case ISD::SREM:
5314 case ISD::UREM:
5315 Res = WidenVecRes_BinaryCanTrap(N);
5316 break;
5317
5318 case ISD::SMULFIX:
5319 case ISD::SMULFIXSAT:
5320 case ISD::UMULFIX:
5321 case ISD::UMULFIXSAT:
5322 // These are binary operations, but with an extra operand that shouldn't
5323 // be widened (the scale).
5324 Res = WidenVecRes_BinaryWithExtraScalarOp(N);
5325 break;
5326
5327#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
5328 case ISD::STRICT_##DAGN:
5329#include "llvm/IR/ConstrainedOps.def"
5330 Res = WidenVecRes_StrictFP(N);
5331 break;
5332
5333 case ISD::UADDO:
5334 case ISD::SADDO:
5335 case ISD::USUBO:
5336 case ISD::SSUBO:
5337 case ISD::UMULO:
5338 case ISD::SMULO:
5339 Res = WidenVecRes_OverflowOp(N, ResNo);
5340 break;
5341
5342 case ISD::FCOPYSIGN:
5343 Res = WidenVecRes_FCOPYSIGN(N);
5344 break;
5345
5346 case ISD::IS_FPCLASS:
5347 case ISD::FPTRUNC_ROUND:
5348 Res = WidenVecRes_UnarySameEltsWithScalarArg(N);
5349 break;
5350
5351 case ISD::FLDEXP:
5352 case ISD::FPOWI:
5353 if (!unrollExpandedOp())
5354 Res = WidenVecRes_ExpOp(N);
5355 break;
5356
5360 Res = WidenVecRes_EXTEND_VECTOR_INREG(N);
5361 break;
5362
5363 case ISD::ANY_EXTEND:
5364 case ISD::FP_EXTEND:
5365 case ISD::VP_FP_EXTEND:
5366 case ISD::FP_ROUND:
5367 case ISD::VP_FP_ROUND:
5368 case ISD::FP_TO_SINT:
5369 case ISD::VP_FP_TO_SINT:
5370 case ISD::FP_TO_UINT:
5371 case ISD::VP_FP_TO_UINT:
5372 case ISD::SIGN_EXTEND:
5373 case ISD::VP_SIGN_EXTEND:
5374 case ISD::SINT_TO_FP:
5375 case ISD::VP_SINT_TO_FP:
5376 case ISD::VP_TRUNCATE:
5377 case ISD::TRUNCATE:
5378 case ISD::UINT_TO_FP:
5379 case ISD::VP_UINT_TO_FP:
5380 case ISD::ZERO_EXTEND:
5381 case ISD::VP_ZERO_EXTEND:
5383 Res = WidenVecRes_Convert(N);
5384 break;
5385
5388 Res = WidenVecRes_FP_TO_XINT_SAT(N);
5389 break;
5390
5391 case ISD::LRINT:
5392 case ISD::LLRINT:
5393 case ISD::VP_LRINT:
5394 case ISD::VP_LLRINT:
5395 case ISD::LROUND:
5396 case ISD::LLROUND:
5397 Res = WidenVecRes_XROUND(N);
5398 break;
5399
5400 case ISD::FACOS:
5401 case ISD::FASIN:
5402 case ISD::FATAN:
5403 case ISD::FCEIL:
5404 case ISD::FCOS:
5405 case ISD::FCOSH:
5406 case ISD::FEXP:
5407 case ISD::FEXP2:
5408 case ISD::FEXP10:
5409 case ISD::FFLOOR:
5410 case ISD::FLOG:
5411 case ISD::FLOG10:
5412 case ISD::FLOG2:
5413 case ISD::FNEARBYINT:
5414 case ISD::FRINT:
5415 case ISD::FROUND:
5416 case ISD::FROUNDEVEN:
5417 case ISD::FSIN:
5418 case ISD::FSINH:
5419 case ISD::FSQRT:
5420 case ISD::FTAN:
5421 case ISD::FTANH:
5422 case ISD::FTRUNC:
5423 if (unrollExpandedOp())
5424 break;
5425 // If the target has custom/legal support for the scalar FP intrinsic ops
5426 // (they are probably not destined to become libcalls), then widen those
5427 // like any other unary ops.
5428 [[fallthrough]];
5429
5430 case ISD::ABS:
5432 case ISD::VP_ABS:
5433 case ISD::BITREVERSE:
5434 case ISD::VP_BITREVERSE:
5435 case ISD::BSWAP:
5436 case ISD::VP_BSWAP:
5437 case ISD::CTLZ:
5438 case ISD::VP_CTLZ:
5440 case ISD::VP_CTLZ_ZERO_POISON:
5441 case ISD::CTPOP:
5442 case ISD::VP_CTPOP:
5443 case ISD::CTTZ:
5444 case ISD::VP_CTTZ:
5446 case ISD::VP_CTTZ_ZERO_POISON:
5447 case ISD::FNEG: case ISD::VP_FNEG:
5448 case ISD::FABS: case ISD::VP_FABS:
5449 case ISD::VP_SQRT:
5450 case ISD::VP_FCEIL:
5451 case ISD::VP_FFLOOR:
5452 case ISD::VP_FRINT:
5453 case ISD::VP_FNEARBYINT:
5454 case ISD::VP_FROUND:
5455 case ISD::VP_FROUNDEVEN:
5456 case ISD::VP_FROUNDTOZERO:
5457 case ISD::FREEZE:
5458 case ISD::ARITH_FENCE:
5459 case ISD::FCANONICALIZE:
5461 Res = WidenVecRes_Unary(N);
5462 break;
5463 case ISD::FMA: case ISD::VP_FMA:
5464 case ISD::FSHL:
5465 case ISD::VP_FSHL:
5466 case ISD::FSHR:
5467 case ISD::VP_FSHR:
5468 Res = WidenVecRes_Ternary(N);
5469 break;
5470 case ISD::FMODF:
5471 case ISD::FFREXP:
5472 case ISD::FSINCOS:
5473 case ISD::FSINCOSPI: {
5474 if (!unrollExpandedOp())
5475 Res = WidenVecRes_UnaryOpWithTwoResults(N, ResNo);
5476 break;
5477 }
5478 }
5479
5480 // If Res is null, the sub-method took care of registering the result.
5481 if (Res.getNode())
5482 SetWidenedVector(SDValue(N, ResNo), Res);
5483}
5484
5485SDValue DAGTypeLegalizer::WidenVecRes_Ternary(SDNode *N) {
5486 // Ternary op widening.
5487 SDLoc dl(N);
5488 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5489 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5490 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5491 SDValue InOp3 = GetWidenedVector(N->getOperand(2));
5492 if (N->getNumOperands() == 3)
5493 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3);
5494
5495 assert(N->getNumOperands() == 5 && "Unexpected number of operands!");
5496 assert(N->isVPOpcode() && "Expected VP opcode");
5497
5498 SDValue Mask =
5499 GetWidenedMask(N->getOperand(3), WidenVT.getVectorElementCount());
5500 return DAG.getNode(N->getOpcode(), dl, WidenVT,
5501 {InOp1, InOp2, InOp3, Mask, N->getOperand(4)});
5502}
5503
5504SDValue DAGTypeLegalizer::WidenVecRes_Binary(SDNode *N) {
5505 // Binary op widening.
5506 SDLoc dl(N);
5507 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5508 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5509 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5510 if (N->getNumOperands() == 2)
5511 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2,
5512 N->getFlags());
5513
5514 assert(N->getNumOperands() == 4 && "Unexpected number of operands!");
5515 assert(N->isVPOpcode() && "Expected VP opcode");
5516
5517 SDValue Mask =
5518 GetWidenedMask(N->getOperand(2), WidenVT.getVectorElementCount());
5519 return DAG.getNode(N->getOpcode(), dl, WidenVT,
5520 {InOp1, InOp2, Mask, N->getOperand(3)}, N->getFlags());
5521}
5522
5523SDValue DAGTypeLegalizer::WidenVecRes_MaskedBinary(SDNode *N) {
5524 SDLoc dl(N);
5525 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5526 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5527 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5528 SDValue Mask = N->getOperand(2);
5529 EVT WideMaskVT = WidenVT.changeVectorElementType(
5530 *DAG.getContext(), Mask.getValueType().getVectorElementType());
5531 Mask = ModifyToType(Mask, WideMaskVT, /*FillWithZeros=*/true);
5532 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, Mask,
5533 N->getFlags());
5534}
5535
5536SDValue DAGTypeLegalizer::WidenVecRes_CMP(SDNode *N) {
5537 LLVMContext &Ctxt = *DAG.getContext();
5538 SDLoc dl(N);
5539
5540 SDValue LHS = N->getOperand(0);
5541 SDValue RHS = N->getOperand(1);
5542 EVT OpVT = LHS.getValueType();
5543 if (getTypeAction(OpVT) == TargetLowering::TypeWidenVector) {
5544 LHS = GetWidenedVector(LHS);
5545 RHS = GetWidenedVector(RHS);
5546 OpVT = LHS.getValueType();
5547 }
5548
5549 EVT WidenResVT = TLI.getTypeToTransformTo(Ctxt, N->getValueType(0));
5550 ElementCount WidenResEC = WidenResVT.getVectorElementCount();
5551 if (WidenResEC == OpVT.getVectorElementCount()) {
5552 return DAG.getNode(N->getOpcode(), dl, WidenResVT, LHS, RHS);
5553 }
5554
5555 return DAG.UnrollVectorOp(N, WidenResVT.getVectorNumElements());
5556}
5557
5558SDValue DAGTypeLegalizer::WidenVecRes_BinaryWithExtraScalarOp(SDNode *N) {
5559 // Binary op widening, but with an extra operand that shouldn't be widened.
5560 SDLoc dl(N);
5561 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5562 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5563 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5564 SDValue InOp3 = N->getOperand(2);
5565 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3,
5566 N->getFlags());
5567}
5568
5569// Given a vector of operations that have been broken up to widen, see
5570// if we can collect them together into the next widest legal VT. This
5571// implementation is trap-safe.
5573 SmallVectorImpl<SDValue> &ConcatOps,
5574 unsigned ConcatEnd, EVT VT, EVT MaxVT,
5575 EVT WidenVT) {
5576 // Check to see if we have a single operation with the widen type.
5577 if (ConcatEnd == 1) {
5578 VT = ConcatOps[0].getValueType();
5579 if (VT == WidenVT)
5580 return ConcatOps[0];
5581 }
5582
5583 SDLoc dl(ConcatOps[0]);
5584 EVT WidenEltVT = WidenVT.getVectorElementType();
5585
5586 // while (Some element of ConcatOps is not of type MaxVT) {
5587 // From the end of ConcatOps, collect elements of the same type and put
5588 // them into an op of the next larger supported type
5589 // }
5590 while (ConcatOps[ConcatEnd-1].getValueType() != MaxVT) {
5591 int Idx = ConcatEnd - 1;
5592 VT = ConcatOps[Idx--].getValueType();
5593 while (Idx >= 0 && ConcatOps[Idx].getValueType() == VT)
5594 Idx--;
5595
5596 int NextSize = VT.isVector() ? VT.getVectorNumElements() : 1;
5597 EVT NextVT;
5598 do {
5599 NextSize *= 2;
5600 NextVT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NextSize);
5601 } while (!TLI.isTypeLegal(NextVT));
5602
5603 if (!VT.isVector()) {
5604 // Scalar type, create an INSERT_VECTOR_ELEMENT of type NextVT
5605 SDValue VecOp = DAG.getPOISON(NextVT);
5606 unsigned NumToInsert = ConcatEnd - Idx - 1;
5607 for (unsigned i = 0, OpIdx = Idx + 1; i < NumToInsert; i++, OpIdx++)
5608 VecOp = DAG.getInsertVectorElt(dl, VecOp, ConcatOps[OpIdx], i);
5609 ConcatOps[Idx+1] = VecOp;
5610 ConcatEnd = Idx + 2;
5611 } else {
5612 // Vector type, create a CONCAT_VECTORS of type NextVT
5613 SDValue undefVec = DAG.getPOISON(VT);
5614 unsigned OpsToConcat = NextSize/VT.getVectorNumElements();
5615 SmallVector<SDValue, 16> SubConcatOps(OpsToConcat);
5616 unsigned RealVals = ConcatEnd - Idx - 1;
5617 unsigned SubConcatEnd = 0;
5618 unsigned SubConcatIdx = Idx + 1;
5619 while (SubConcatEnd < RealVals)
5620 SubConcatOps[SubConcatEnd++] = ConcatOps[++Idx];
5621 while (SubConcatEnd < OpsToConcat)
5622 SubConcatOps[SubConcatEnd++] = undefVec;
5623 ConcatOps[SubConcatIdx] = DAG.getNode(ISD::CONCAT_VECTORS, dl,
5624 NextVT, SubConcatOps);
5625 ConcatEnd = SubConcatIdx + 1;
5626 }
5627 }
5628
5629 // Check to see if we have a single operation with the widen type.
5630 if (ConcatEnd == 1) {
5631 VT = ConcatOps[0].getValueType();
5632 if (VT == WidenVT)
5633 return ConcatOps[0];
5634 }
5635
5636 // add undefs of size MaxVT until ConcatOps grows to length of WidenVT
5637 unsigned NumOps = WidenVT.getVectorNumElements()/MaxVT.getVectorNumElements();
5638 if (NumOps != ConcatEnd ) {
5639 SDValue UndefVal = DAG.getPOISON(MaxVT);
5640 for (unsigned j = ConcatEnd; j < NumOps; ++j)
5641 ConcatOps[j] = UndefVal;
5642 }
5643 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
5644 ArrayRef(ConcatOps.data(), NumOps));
5645}
5646
5647SDValue DAGTypeLegalizer::WidenVecRes_BinaryCanTrap(SDNode *N) {
5648 // Binary op widening for operations that can trap.
5649 unsigned Opcode = N->getOpcode();
5650 SDLoc dl(N);
5651 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5652 EVT WidenEltVT = WidenVT.getVectorElementType();
5653 EVT VT = WidenVT;
5654 unsigned NumElts = VT.getVectorMinNumElements();
5655 const SDNodeFlags Flags = N->getFlags();
5656 while (!TLI.isTypeLegal(VT) && NumElts != 1) {
5657 NumElts = NumElts / 2;
5658 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5659 }
5660
5661 if (NumElts != 1 && !TLI.canOpTrap(N->getOpcode(), VT)) {
5662 // Operation doesn't trap so just widen as normal.
5663 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5664 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5665 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, Flags);
5666 }
5667
5668 // Generate a vp.op if it is custom/legal for the target. This avoids need
5669 // to split and tile the subvectors (below), because the inactive lanes can
5670 // simply be disabled. To avoid possible recursion, only do this if the
5671 // widened mask type is legal.
5672 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opcode);
5673 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WidenVT)) {
5674 if (EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
5675 WidenVT.getVectorElementCount());
5676 TLI.isTypeLegal(WideMaskVT)) {
5677 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5678 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5679 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
5680 SDValue EVL =
5681 DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
5682 N->getValueType(0).getVectorElementCount());
5683 return DAG.getNode(*VPOpcode, dl, WidenVT, InOp1, InOp2, Mask, EVL,
5684 Flags);
5685 }
5686 }
5687
5688 // FIXME: Improve support for scalable vectors.
5689 assert(!VT.isScalableVector() && "Scalable vectors not handled yet.");
5690
5691 // No legal vector version so unroll the vector operation and then widen.
5692 if (NumElts == 1)
5693 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
5694
5695 // Since the operation can trap, apply operation on the original vector.
5696 EVT MaxVT = VT;
5697 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5698 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5699 unsigned CurNumElts = N->getValueType(0).getVectorNumElements();
5700
5701 SmallVector<SDValue, 16> ConcatOps(CurNumElts);
5702 unsigned ConcatEnd = 0; // Current ConcatOps index.
5703 int Idx = 0; // Current Idx into input vectors.
5704
5705 // NumElts := greatest legal vector size (at most WidenVT)
5706 // while (orig. vector has unhandled elements) {
5707 // take munches of size NumElts from the beginning and add to ConcatOps
5708 // NumElts := next smaller supported vector size or 1
5709 // }
5710 while (CurNumElts != 0) {
5711 while (CurNumElts >= NumElts) {
5712 SDValue EOp1 = DAG.getExtractSubvector(dl, VT, InOp1, Idx);
5713 SDValue EOp2 = DAG.getExtractSubvector(dl, VT, InOp2, Idx);
5714 ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, VT, EOp1, EOp2, Flags);
5715 Idx += NumElts;
5716 CurNumElts -= NumElts;
5717 }
5718 do {
5719 NumElts = NumElts / 2;
5720 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5721 } while (!TLI.isTypeLegal(VT) && NumElts != 1);
5722
5723 if (NumElts == 1) {
5724 for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
5725 SDValue EOp1 = DAG.getExtractVectorElt(dl, WidenEltVT, InOp1, Idx);
5726 SDValue EOp2 = DAG.getExtractVectorElt(dl, WidenEltVT, InOp2, Idx);
5727 ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, WidenEltVT,
5728 EOp1, EOp2, Flags);
5729 }
5730 CurNumElts = 0;
5731 }
5732 }
5733
5734 return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
5735}
5736
5737SDValue DAGTypeLegalizer::WidenVecRes_StrictFP(SDNode *N) {
5738 switch (N->getOpcode()) {
5739 case ISD::STRICT_FSETCC:
5741 return WidenVecRes_STRICT_FSETCC(N);
5748 return WidenVecRes_Convert_StrictFP(N);
5749 default:
5750 break;
5751 }
5752
5753 // StrictFP op widening for operations that can trap.
5754 unsigned NumOpers = N->getNumOperands();
5755 unsigned Opcode = N->getOpcode();
5756 SDLoc dl(N);
5757 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5758 EVT WidenEltVT = WidenVT.getVectorElementType();
5759 EVT VT = WidenVT;
5760 unsigned NumElts = VT.getVectorNumElements();
5761 while (!TLI.isTypeLegal(VT) && NumElts != 1) {
5762 NumElts = NumElts / 2;
5763 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5764 }
5765
5766 // No legal vector version so unroll the vector operation and then widen.
5767 if (NumElts == 1)
5768 return UnrollVectorOp_StrictFP(N, WidenVT.getVectorNumElements());
5769
5770 // Since the operation can trap, apply operation on the original vector.
5771 EVT MaxVT = VT;
5773 unsigned CurNumElts = N->getValueType(0).getVectorNumElements();
5774
5775 SmallVector<SDValue, 16> ConcatOps(CurNumElts);
5777 unsigned ConcatEnd = 0; // Current ConcatOps index.
5778 int Idx = 0; // Current Idx into input vectors.
5779
5780 // The Chain is the first operand.
5781 InOps.push_back(N->getOperand(0));
5782
5783 // Now process the remaining operands.
5784 for (unsigned i = 1; i < NumOpers; ++i) {
5785 SDValue Oper = N->getOperand(i);
5786
5787 EVT OpVT = Oper.getValueType();
5788 if (OpVT.isVector()) {
5789 if (getTypeAction(OpVT) == TargetLowering::TypeWidenVector)
5790 Oper = GetWidenedVector(Oper);
5791 else {
5792 EVT WideOpVT =
5793 EVT::getVectorVT(*DAG.getContext(), OpVT.getVectorElementType(),
5794 WidenVT.getVectorElementCount());
5795 Oper = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WideOpVT,
5796 DAG.getPOISON(WideOpVT), Oper,
5797 DAG.getVectorIdxConstant(0, dl));
5798 }
5799 }
5800
5801 InOps.push_back(Oper);
5802 }
5803
5804 // NumElts := greatest legal vector size (at most WidenVT)
5805 // while (orig. vector has unhandled elements) {
5806 // take munches of size NumElts from the beginning and add to ConcatOps
5807 // NumElts := next smaller supported vector size or 1
5808 // }
5809 while (CurNumElts != 0) {
5810 while (CurNumElts >= NumElts) {
5812
5813 for (unsigned i = 0; i < NumOpers; ++i) {
5814 SDValue Op = InOps[i];
5815
5816 EVT OpVT = Op.getValueType();
5817 if (OpVT.isVector()) {
5818 EVT OpExtractVT =
5819 EVT::getVectorVT(*DAG.getContext(), OpVT.getVectorElementType(),
5821 Op = DAG.getExtractSubvector(dl, OpExtractVT, Op, Idx);
5822 }
5823
5824 EOps.push_back(Op);
5825 }
5826
5827 EVT OperVT[] = {VT, MVT::Other};
5828 SDValue Oper = DAG.getNode(Opcode, dl, OperVT, EOps);
5829 ConcatOps[ConcatEnd++] = Oper;
5830 Chains.push_back(Oper.getValue(1));
5831 Idx += NumElts;
5832 CurNumElts -= NumElts;
5833 }
5834 do {
5835 NumElts = NumElts / 2;
5836 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5837 } while (!TLI.isTypeLegal(VT) && NumElts != 1);
5838
5839 if (NumElts == 1) {
5840 for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
5842
5843 for (unsigned i = 0; i < NumOpers; ++i) {
5844 SDValue Op = InOps[i];
5845
5846 EVT OpVT = Op.getValueType();
5847 if (OpVT.isVector())
5848 Op = DAG.getExtractVectorElt(dl, OpVT.getVectorElementType(), Op,
5849 Idx);
5850
5851 EOps.push_back(Op);
5852 }
5853
5854 EVT WidenVT[] = {WidenEltVT, MVT::Other};
5855 SDValue Oper = DAG.getNode(Opcode, dl, WidenVT, EOps);
5856 ConcatOps[ConcatEnd++] = Oper;
5857 Chains.push_back(Oper.getValue(1));
5858 }
5859 CurNumElts = 0;
5860 }
5861 }
5862
5863 // Build a factor node to remember all the Ops that have been created.
5864 SDValue NewChain;
5865 if (Chains.size() == 1)
5866 NewChain = Chains[0];
5867 else
5868 NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
5869 ReplaceValueWith(SDValue(N, 1), NewChain);
5870
5871 return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
5872}
5873
5874SDValue DAGTypeLegalizer::WidenVecRes_OverflowOp(SDNode *N, unsigned ResNo) {
5875 SDLoc DL(N);
5876 EVT ResVT = N->getValueType(0);
5877 EVT OvVT = N->getValueType(1);
5878 EVT WideResVT, WideOvVT;
5879 SDValue WideLHS, WideRHS;
5880
5881 // TODO: This might result in a widen/split loop.
5882 if (ResNo == 0) {
5883 WideResVT = TLI.getTypeToTransformTo(*DAG.getContext(), ResVT);
5884 WideOvVT = EVT::getVectorVT(
5885 *DAG.getContext(), OvVT.getVectorElementType(),
5886 WideResVT.getVectorNumElements());
5887
5888 WideLHS = GetWidenedVector(N->getOperand(0));
5889 WideRHS = GetWidenedVector(N->getOperand(1));
5890 } else {
5891 WideOvVT = TLI.getTypeToTransformTo(*DAG.getContext(), OvVT);
5892 WideResVT = EVT::getVectorVT(
5893 *DAG.getContext(), ResVT.getVectorElementType(),
5894 WideOvVT.getVectorNumElements());
5895
5896 SDValue Zero = DAG.getVectorIdxConstant(0, DL);
5897 SDValue Poison = DAG.getPOISON(WideResVT);
5898
5899 WideLHS = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideResVT, Poison,
5900 N->getOperand(0), Zero);
5901 WideRHS = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideResVT, Poison,
5902 N->getOperand(1), Zero);
5903 }
5904
5905 SDVTList WideVTs = DAG.getVTList(WideResVT, WideOvVT);
5906 SDNode *WideNode = DAG.getNode(
5907 N->getOpcode(), DL, WideVTs, WideLHS, WideRHS).getNode();
5908
5909 // Replace the other vector result not being explicitly widened here.
5910 unsigned OtherNo = 1 - ResNo;
5911 EVT OtherVT = N->getValueType(OtherNo);
5912 if (getTypeAction(OtherVT) == TargetLowering::TypeWidenVector) {
5913 SetWidenedVector(SDValue(N, OtherNo), SDValue(WideNode, OtherNo));
5914 } else {
5915 SDValue Zero = DAG.getVectorIdxConstant(0, DL);
5916 SDValue OtherVal = DAG.getNode(
5917 ISD::EXTRACT_SUBVECTOR, DL, OtherVT, SDValue(WideNode, OtherNo), Zero);
5918 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
5919 }
5920
5921 return SDValue(WideNode, ResNo);
5922}
5923
5924SDValue DAGTypeLegalizer::WidenVecRes_Convert(SDNode *N) {
5925 LLVMContext &Ctx = *DAG.getContext();
5926 SDValue InOp = N->getOperand(0);
5927 SDLoc DL(N);
5928
5929 EVT WidenVT = TLI.getTypeToTransformTo(Ctx, N->getValueType(0));
5930 ElementCount WidenEC = WidenVT.getVectorElementCount();
5931
5932 EVT InVT = InOp.getValueType();
5933
5934 unsigned Opcode = N->getOpcode();
5935 const SDNodeFlags Flags = N->getFlags();
5936
5937 // Handle the case of ZERO_EXTEND where the promoted InVT element size does
5938 // not equal that of WidenVT.
5939 if (N->getOpcode() == ISD::ZERO_EXTEND &&
5940 getTypeAction(InVT) == TargetLowering::TypePromoteInteger &&
5941 TLI.getTypeToTransformTo(Ctx, InVT).getScalarSizeInBits() !=
5942 WidenVT.getScalarSizeInBits()) {
5943 InOp = ZExtPromotedInteger(InOp);
5944 InVT = InOp.getValueType();
5945 if (WidenVT.getScalarSizeInBits() < InVT.getScalarSizeInBits())
5946 Opcode = ISD::TRUNCATE;
5947 }
5948
5949 EVT InEltVT = InVT.getVectorElementType();
5950 EVT InWidenVT = EVT::getVectorVT(Ctx, InEltVT, WidenEC);
5951 ElementCount InVTEC = InVT.getVectorElementCount();
5952
5953 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
5954 InOp = GetWidenedVector(N->getOperand(0));
5955 InVT = InOp.getValueType();
5956 InVTEC = InVT.getVectorElementCount();
5957 if (InVTEC == WidenEC) {
5958 if (N->getNumOperands() == 1)
5959 return DAG.getNode(Opcode, DL, WidenVT, InOp, Flags);
5960 if (N->getNumOperands() == 3) {
5961 assert(N->isVPOpcode() && "Expected VP opcode");
5962 SDValue Mask =
5963 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
5964 return DAG.getNode(Opcode, DL, WidenVT, InOp, Mask, N->getOperand(2));
5965 }
5966 return DAG.getNode(Opcode, DL, WidenVT, InOp, N->getOperand(1), Flags);
5967 }
5968 if (WidenVT.getSizeInBits() == InVT.getSizeInBits()) {
5969 // If both input and result vector types are of same width, extend
5970 // operations should be done with SIGN/ZERO_EXTEND_VECTOR_INREG, which
5971 // accepts fewer elements in the result than in the input.
5972 if (Opcode == ISD::ANY_EXTEND)
5973 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
5974 if (Opcode == ISD::SIGN_EXTEND)
5975 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
5976 if (Opcode == ISD::ZERO_EXTEND)
5977 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
5978 }
5979
5980 // For TRUNCATE, try to widen using the legal EC of the input type instead
5981 // if the legalisation action for that intermediate type is not widening.
5982 // E.g. for trunc nxv1i64 -> nxv1i8 where
5983 // - nxv1i64 input gets widened to nxv2i64
5984 // - nxv1i8 output gets widened to nxv16i8
5985 // Then one can try widening the result to nxv2i8 (instead of going all the
5986 // way to nxv16i8) if this later allows type promotion.
5987 EVT MidResVT =
5988 EVT::getVectorVT(Ctx, WidenVT.getVectorElementType(), InVTEC);
5989 if (N->getOpcode() == ISD::TRUNCATE &&
5990 getTypeAction(MidResVT) == TargetLowering::TypePromoteInteger) {
5991 SDValue MidRes = DAG.getNode(ISD::TRUNCATE, DL, MidResVT, InOp, Flags);
5992 return DAG.getInsertSubvector(DL, DAG.getPOISON(WidenVT), MidRes, 0);
5993 }
5994 }
5995
5996 if (TLI.isTypeLegal(InWidenVT)) {
5997 // Because the result and the input are different vector types, widening
5998 // the result could create a legal type but widening the input might make
5999 // it an illegal type that might lead to repeatedly splitting the input
6000 // and then widening it. To avoid this, we widen the input only if
6001 // it results in a legal type.
6002 if (WidenEC.isKnownMultipleOf(InVTEC.getKnownMinValue())) {
6003 // Widen the input and call convert on the widened input vector.
6004 unsigned NumConcat =
6005 WidenEC.getKnownMinValue() / InVTEC.getKnownMinValue();
6006 SmallVector<SDValue, 16> Ops(NumConcat, DAG.getPOISON(InVT));
6007 Ops[0] = InOp;
6008 SDValue InVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InWidenVT, Ops);
6009 if (N->getNumOperands() == 1)
6010 return DAG.getNode(Opcode, DL, WidenVT, InVec, Flags);
6011 return DAG.getNode(Opcode, DL, WidenVT, InVec, N->getOperand(1), Flags);
6012 }
6013
6014 if (InVTEC.isKnownMultipleOf(WidenEC.getKnownMinValue())) {
6015 SDValue InVal = DAG.getExtractSubvector(DL, InWidenVT, InOp, 0);
6016 // Extract the input and convert the shorten input vector.
6017 if (N->getNumOperands() == 1)
6018 return DAG.getNode(Opcode, DL, WidenVT, InVal, Flags);
6019 return DAG.getNode(Opcode, DL, WidenVT, InVal, N->getOperand(1), Flags);
6020 }
6021 }
6022
6023 // Otherwise unroll into some nasty scalar code and rebuild the vector.
6024 EVT EltVT = WidenVT.getVectorElementType();
6025 SmallVector<SDValue, 16> Ops(WidenEC.getFixedValue(), DAG.getPOISON(EltVT));
6026 // Use the original element count so we don't do more scalar opts than
6027 // necessary.
6028 unsigned MinElts = N->getValueType(0).getVectorNumElements();
6029 for (unsigned i=0; i < MinElts; ++i) {
6030 SDValue Val = DAG.getExtractVectorElt(DL, InEltVT, InOp, i);
6031 if (N->getNumOperands() == 1)
6032 Ops[i] = DAG.getNode(Opcode, DL, EltVT, Val, Flags);
6033 else
6034 Ops[i] = DAG.getNode(Opcode, DL, EltVT, Val, N->getOperand(1), Flags);
6035 }
6036
6037 return DAG.getBuildVector(WidenVT, DL, Ops);
6038}
6039
6040SDValue DAGTypeLegalizer::WidenVecRes_FP_TO_XINT_SAT(SDNode *N) {
6041 SDLoc dl(N);
6042 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6043 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
6044
6045 SDValue Src = N->getOperand(0);
6046 EVT SrcVT = Src.getValueType();
6047
6048 // Also widen the input.
6049 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
6050 Src = GetWidenedVector(Src);
6051 SrcVT = Src.getValueType();
6052 }
6053
6054 // Input and output not widened to the same size, give up.
6055 if (WidenNumElts != SrcVT.getVectorElementCount())
6056 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
6057
6058 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src, N->getOperand(1));
6059}
6060
6061SDValue DAGTypeLegalizer::WidenVecRes_XROUND(SDNode *N) {
6062 SDLoc dl(N);
6063 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6064 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
6065
6066 SDValue Src = N->getOperand(0);
6067 EVT SrcVT = Src.getValueType();
6068
6069 // Also widen the input.
6070 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
6071 Src = GetWidenedVector(Src);
6072 SrcVT = Src.getValueType();
6073 }
6074
6075 // Input and output not widened to the same size, give up.
6076 if (WidenNumElts != SrcVT.getVectorElementCount())
6077 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
6078
6079 if (N->getNumOperands() == 1)
6080 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src);
6081
6082 assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
6083 assert(N->isVPOpcode() && "Expected VP opcode");
6084
6085 SDValue Mask =
6086 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
6087 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src, Mask, N->getOperand(2));
6088}
6089
6090SDValue DAGTypeLegalizer::WidenVecRes_Convert_StrictFP(SDNode *N) {
6091 SDValue InOp = N->getOperand(1);
6092 SDLoc DL(N);
6093 SmallVector<SDValue, 4> NewOps(N->ops());
6094
6095 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6096 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6097
6098 EVT InVT = InOp.getValueType();
6099 EVT InEltVT = InVT.getVectorElementType();
6100
6101 unsigned Opcode = N->getOpcode();
6102
6103 // FIXME: Optimizations need to be implemented here.
6104
6105 // Otherwise unroll into some nasty scalar code and rebuild the vector.
6106 EVT EltVT = WidenVT.getVectorElementType();
6107 std::array<EVT, 2> EltVTs = {{EltVT, MVT::Other}};
6108 SmallVector<SDValue, 16> Ops(WidenNumElts, DAG.getPOISON(EltVT));
6109 SmallVector<SDValue, 32> OpChains;
6110 // Use the original element count so we don't do more scalar opts than
6111 // necessary.
6112 unsigned MinElts = N->getValueType(0).getVectorNumElements();
6113 for (unsigned i=0; i < MinElts; ++i) {
6114 NewOps[1] = DAG.getExtractVectorElt(DL, InEltVT, InOp, i);
6115 Ops[i] = DAG.getNode(Opcode, DL, EltVTs, NewOps);
6116 OpChains.push_back(Ops[i].getValue(1));
6117 }
6118 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OpChains);
6119 ReplaceValueWith(SDValue(N, 1), NewChain);
6120
6121 return DAG.getBuildVector(WidenVT, DL, Ops);
6122}
6123
6124SDValue DAGTypeLegalizer::WidenVecRes_EXTEND_VECTOR_INREG(SDNode *N) {
6125 unsigned Opcode = N->getOpcode();
6126 SDValue InOp = N->getOperand(0);
6127 SDLoc DL(N);
6128
6129 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6130 EVT WidenSVT = WidenVT.getVectorElementType();
6131 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6132
6133 EVT InVT = InOp.getValueType();
6134 EVT InSVT = InVT.getVectorElementType();
6135 unsigned InVTNumElts = InVT.getVectorNumElements();
6136
6137 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
6138 InOp = GetWidenedVector(InOp);
6139 InVT = InOp.getValueType();
6140 if (InVT.getSizeInBits() == WidenVT.getSizeInBits()) {
6141 switch (Opcode) {
6145 return DAG.getNode(Opcode, DL, WidenVT, InOp);
6146 }
6147 }
6148 }
6149
6150 // Unroll, extend the scalars and rebuild the vector.
6152 for (unsigned i = 0, e = std::min(InVTNumElts, WidenNumElts); i != e; ++i) {
6153 SDValue Val = DAG.getExtractVectorElt(DL, InSVT, InOp, i);
6154 switch (Opcode) {
6156 Val = DAG.getNode(ISD::ANY_EXTEND, DL, WidenSVT, Val);
6157 break;
6159 Val = DAG.getNode(ISD::SIGN_EXTEND, DL, WidenSVT, Val);
6160 break;
6162 Val = DAG.getNode(ISD::ZERO_EXTEND, DL, WidenSVT, Val);
6163 break;
6164 default:
6165 llvm_unreachable("A *_EXTEND_VECTOR_INREG node was expected");
6166 }
6167 Ops.push_back(Val);
6168 }
6169
6170 while (Ops.size() != WidenNumElts)
6171 Ops.push_back(DAG.getPOISON(WidenSVT));
6172
6173 return DAG.getBuildVector(WidenVT, DL, Ops);
6174}
6175
6176SDValue DAGTypeLegalizer::WidenVecRes_FCOPYSIGN(SDNode *N) {
6177 // If this is an FCOPYSIGN with same input types, we can treat it as a
6178 // normal (can trap) binary op.
6179 if (N->getOperand(0).getValueType() == N->getOperand(1).getValueType())
6180 return WidenVecRes_BinaryCanTrap(N);
6181
6182 // If the types are different, fall back to unrolling.
6183 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6184 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
6185}
6186
6187/// Result and first source operand are different scalar types, but must have
6188/// the same number of elements. There is an additional control argument which
6189/// should be passed through unchanged.
6190SDValue DAGTypeLegalizer::WidenVecRes_UnarySameEltsWithScalarArg(SDNode *N) {
6191 SDValue FpValue = N->getOperand(0);
6192 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6193 if (getTypeAction(FpValue.getValueType()) != TargetLowering::TypeWidenVector)
6194 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
6195 SDValue Arg = GetWidenedVector(FpValue);
6196 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, {Arg, N->getOperand(1)},
6197 N->getFlags());
6198}
6199
6200SDValue DAGTypeLegalizer::WidenVecRes_ExpOp(SDNode *N) {
6201 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6202 SDValue InOp = GetWidenedVector(N->getOperand(0));
6203 SDValue RHS = N->getOperand(1);
6204 EVT ExpVT = RHS.getValueType();
6205 SDValue ExpOp = RHS;
6206 if (ExpVT.isVector()) {
6207 EVT WideExpVT = WidenVT.changeVectorElementType(
6208 *DAG.getContext(), ExpVT.getVectorElementType());
6209 ExpOp = ModifyToType(RHS, WideExpVT);
6210 }
6211
6212 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, ExpOp);
6213}
6214
6215SDValue DAGTypeLegalizer::WidenVecRes_Unary(SDNode *N) {
6216 // Unary op widening.
6217 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6218 SDValue InOp = GetWidenedVector(N->getOperand(0));
6219 if (N->getNumOperands() == 1)
6220 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, N->getFlags());
6221 if (N->getOpcode() == ISD::AssertNoFPClass)
6222 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp,
6223 N->getOperand(1), N->getFlags());
6224
6225 assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
6226 assert(N->isVPOpcode() && "Expected VP opcode");
6227
6228 SDValue Mask =
6229 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
6230 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT,
6231 {InOp, Mask, N->getOperand(2)});
6232}
6233
6234SDValue DAGTypeLegalizer::WidenVecRes_InregOp(SDNode *N) {
6235 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6236 EVT ExtVT = EVT::getVectorVT(
6237 *DAG.getContext(),
6238 cast<VTSDNode>(N->getOperand(1))->getVT().getVectorElementType(),
6239 WidenVT.getVectorElementCount());
6240 SDValue WidenLHS = GetWidenedVector(N->getOperand(0));
6241 return DAG.getNode(N->getOpcode(), SDLoc(N),
6242 WidenVT, WidenLHS, DAG.getValueType(ExtVT));
6243}
6244
6245SDValue DAGTypeLegalizer::WidenVecRes_UnaryOpWithTwoResults(SDNode *N,
6246 unsigned ResNo) {
6247 EVT VT0 = N->getValueType(0);
6248 EVT VT1 = N->getValueType(1);
6249
6250 assert(VT0.isVector() && VT1.isVector() &&
6252 "expected both results to be vectors of matching element count");
6253
6254 LLVMContext &Ctx = *DAG.getContext();
6255 SDValue InOp = GetWidenedVector(N->getOperand(0));
6256
6257 EVT WidenVT = TLI.getTypeToTransformTo(Ctx, N->getValueType(ResNo));
6258 ElementCount WidenEC = WidenVT.getVectorElementCount();
6259
6260 EVT WidenVT0 = EVT::getVectorVT(Ctx, VT0.getVectorElementType(), WidenEC);
6261 EVT WidenVT1 = EVT::getVectorVT(Ctx, VT1.getVectorElementType(), WidenEC);
6262
6263 SDNode *WidenNode =
6264 DAG.getNode(N->getOpcode(), SDLoc(N), {WidenVT0, WidenVT1}, InOp)
6265 .getNode();
6266
6267 ReplaceOtherWidenResults(N, WidenNode, ResNo);
6268 return SDValue(WidenNode, ResNo);
6269}
6270
6271SDValue DAGTypeLegalizer::WidenVecRes_MERGE_VALUES(SDNode *N, unsigned ResNo) {
6272 SDValue WidenVec = DisintegrateMERGE_VALUES(N, ResNo);
6273 return GetWidenedVector(WidenVec);
6274}
6275
6276SDValue DAGTypeLegalizer::WidenVecRes_ADDRSPACECAST(SDNode *N) {
6277 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6278 SDValue InOp = GetWidenedVector(N->getOperand(0));
6279 auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
6280
6281 return DAG.getAddrSpaceCast(SDLoc(N), WidenVT, InOp,
6282 AddrSpaceCastN->getSrcAddressSpace(),
6283 AddrSpaceCastN->getDestAddressSpace());
6284}
6285
6286SDValue DAGTypeLegalizer::WidenVecRes_BITCAST(SDNode *N) {
6287 SDValue InOp = N->getOperand(0);
6288 EVT InVT = InOp.getValueType();
6289 EVT VT = N->getValueType(0);
6290 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6291 SDLoc dl(N);
6292
6293 switch (getTypeAction(InVT)) {
6295 break;
6297 report_fatal_error("Scalarization of scalable vectors is not supported.");
6299 // If the incoming type is a vector that is being promoted, then
6300 // we know that the elements are arranged differently and that we
6301 // must perform the conversion using a stack slot.
6302 if (InVT.isVector())
6303 break;
6304
6305 // If the InOp is promoted to the same size, convert it. Otherwise,
6306 // fall out of the switch and widen the promoted input.
6307 SDValue NInOp = GetPromotedInteger(InOp);
6308 EVT NInVT = NInOp.getValueType();
6309 if (WidenVT.bitsEq(NInVT)) {
6310 // For big endian targets we need to shift the input integer or the
6311 // interesting bits will end up at the wrong place.
6312 if (DAG.getDataLayout().isBigEndian()) {
6313 unsigned ShiftAmt = NInVT.getSizeInBits() - InVT.getSizeInBits();
6314 NInOp = DAG.getNode(ISD::SHL, dl, NInVT, NInOp,
6315 DAG.getShiftAmountConstant(ShiftAmt, NInVT, dl));
6316 }
6317 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NInOp);
6318 }
6319 InOp = NInOp;
6320 InVT = NInVT;
6321 break;
6322 }
6329 break;
6331 // If the InOp is widened to the same size, convert it. Otherwise, fall
6332 // out of the switch and widen the widened input.
6333 InOp = GetWidenedVector(InOp);
6334 InVT = InOp.getValueType();
6335 if (WidenVT.bitsEq(InVT))
6336 // The input widens to the same size. Convert to the widen value.
6337 return DAG.getNode(ISD::BITCAST, dl, WidenVT, InOp);
6338 break;
6339 }
6340
6341 unsigned WidenSize = WidenVT.getSizeInBits();
6342 unsigned InSize = InVT.getSizeInBits();
6343 unsigned InScalarSize = InVT.getScalarSizeInBits();
6344 // x86mmx is not an acceptable vector element type, so don't try.
6345 if (WidenSize % InScalarSize == 0 && InVT != MVT::x86mmx) {
6346 // Determine new input vector type. The new input vector type will use
6347 // the same element type (if its a vector) or use the input type as a
6348 // vector. It is the same size as the type to widen to.
6349 EVT NewInVT;
6350 unsigned NewNumParts = WidenSize / InSize;
6351 if (InVT.isVector()) {
6352 EVT InEltVT = InVT.getVectorElementType();
6353 NewInVT = EVT::getVectorVT(*DAG.getContext(), InEltVT,
6354 WidenSize / InEltVT.getSizeInBits());
6355 } else {
6356 // For big endian systems, using the promoted input scalar type
6357 // to produce the scalar_to_vector would put the desired bits into
6358 // the least significant byte(s) of the wider element zero. This
6359 // will mean that the users of the result vector are using incorrect
6360 // bits. Use the original input type instead. Although either input
6361 // type can be used on little endian systems, for consistency we
6362 // use the original type there as well.
6363 EVT OrigInVT = N->getOperand(0).getValueType();
6364 NewNumParts = WidenSize / OrigInVT.getSizeInBits();
6365 NewInVT = EVT::getVectorVT(*DAG.getContext(), OrigInVT, NewNumParts);
6366 }
6367
6368 if (TLI.isTypeLegal(NewInVT)) {
6369 SDValue NewVec;
6370 if (InVT.isVector()) {
6371 // Because the result and the input are different vector types, widening
6372 // the result could create a legal type but widening the input might
6373 // make it an illegal type that might lead to repeatedly splitting the
6374 // input and then widening it. To avoid this, we widen the input only if
6375 // it results in a legal type.
6376 if (WidenSize % InSize == 0) {
6377 SmallVector<SDValue, 16> Ops(NewNumParts, DAG.getPOISON(InVT));
6378 Ops[0] = InOp;
6379
6380 NewVec = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewInVT, Ops);
6381 } else {
6383 DAG.ExtractVectorElements(InOp, Ops);
6384 Ops.append(WidenSize / InScalarSize - Ops.size(),
6385 DAG.getPOISON(InVT.getVectorElementType()));
6386
6387 NewVec = DAG.getNode(ISD::BUILD_VECTOR, dl, NewInVT, Ops);
6388 }
6389 } else {
6390 NewVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewInVT, InOp);
6391 }
6392 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NewVec);
6393 }
6394 }
6395
6396 return CreateStackStoreLoad(InOp, WidenVT);
6397}
6398
6399SDValue DAGTypeLegalizer::WidenVecRes_LOOP_DEPENDENCE_MASK(SDNode *N) {
6400 return DAG.getNode(
6401 N->getOpcode(), SDLoc(N),
6402 TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)),
6403 N->getOperand(0), N->getOperand(1), N->getOperand(2), N->getOperand(3));
6404}
6405
6406SDValue DAGTypeLegalizer::WidenVecRes_BUILD_VECTOR(SDNode *N) {
6407 SDLoc dl(N);
6408 // Build a vector with poison for the new nodes.
6409 EVT VT = N->getValueType(0);
6410
6411 // Integer BUILD_VECTOR operands may be larger than the node's vector element
6412 // type. The POISONs need to have the same type as the existing operands.
6413 EVT EltVT = N->getOperand(0).getValueType();
6414 unsigned NumElts = VT.getVectorNumElements();
6415
6416 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6417 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6418
6419 SmallVector<SDValue, 16> NewOps(N->ops());
6420 assert(WidenNumElts >= NumElts && "Shrinking vector instead of widening!");
6421 NewOps.append(WidenNumElts - NumElts, DAG.getPOISON(EltVT));
6422
6423 return DAG.getBuildVector(WidenVT, dl, NewOps);
6424}
6425
6426SDValue DAGTypeLegalizer::WidenVecRes_CONCAT_VECTORS(SDNode *N) {
6427 EVT InVT = N->getOperand(0).getValueType();
6428 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6429 SDLoc dl(N);
6430 unsigned NumOperands = N->getNumOperands();
6431
6432 bool InputWidened = false; // Indicates we need to widen the input.
6433 if (getTypeAction(InVT) != TargetLowering::TypeWidenVector) {
6434 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6435 unsigned NumInElts = InVT.getVectorMinNumElements();
6436 if (WidenNumElts % NumInElts == 0) {
6437 // Add undef vectors to widen to correct length.
6438 unsigned NumConcat = WidenNumElts / NumInElts;
6439 SDValue UndefVal = DAG.getPOISON(InVT);
6440 SmallVector<SDValue, 16> Ops(NumConcat);
6441 for (unsigned i=0; i < NumOperands; ++i)
6442 Ops[i] = N->getOperand(i);
6443 for (unsigned i = NumOperands; i != NumConcat; ++i)
6444 Ops[i] = UndefVal;
6445 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Ops);
6446 }
6447 } else {
6448 InputWidened = true;
6449 if (WidenVT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
6450 // The inputs and the result are widen to the same value.
6451 unsigned i;
6452 for (i=1; i < NumOperands; ++i)
6453 if (!N->getOperand(i).isUndef())
6454 break;
6455
6456 if (i == NumOperands)
6457 // Everything but the first operand is an UNDEF so just return the
6458 // widened first operand.
6459 return GetWidenedVector(N->getOperand(0));
6460
6461 if (NumOperands == 2) {
6462 assert(!WidenVT.isScalableVector() &&
6463 "Cannot use vector shuffles to widen CONCAT_VECTOR result");
6464 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6465 unsigned NumInElts = InVT.getVectorNumElements();
6466
6467 // Replace concat of two operands with a shuffle.
6468 SmallVector<int, 16> MaskOps(WidenNumElts, -1);
6469 for (unsigned i = 0; i < NumInElts; ++i) {
6470 MaskOps[i] = i;
6471 MaskOps[i + NumInElts] = i + WidenNumElts;
6472 }
6473 return DAG.getVectorShuffle(WidenVT, dl,
6474 GetWidenedVector(N->getOperand(0)),
6475 GetWidenedVector(N->getOperand(1)),
6476 MaskOps);
6477 }
6478 }
6479 }
6480
6481 assert(!WidenVT.isScalableVector() &&
6482 "Cannot use build vectors to widen CONCAT_VECTOR result");
6483 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6484 unsigned NumInElts = InVT.getVectorNumElements();
6485
6486 // Fall back to use extracts and build vector.
6487 EVT EltVT = WidenVT.getVectorElementType();
6488 SmallVector<SDValue, 16> Ops(WidenNumElts);
6489 unsigned Idx = 0;
6490 for (unsigned i=0; i < NumOperands; ++i) {
6491 SDValue InOp = N->getOperand(i);
6492 if (InputWidened)
6493 InOp = GetWidenedVector(InOp);
6494 for (unsigned j = 0; j < NumInElts; ++j)
6495 Ops[Idx++] = DAG.getExtractVectorElt(dl, EltVT, InOp, j);
6496 }
6497 SDValue UndefVal = DAG.getPOISON(EltVT);
6498 for (; Idx < WidenNumElts; ++Idx)
6499 Ops[Idx] = UndefVal;
6500 return DAG.getBuildVector(WidenVT, dl, Ops);
6501}
6502
6503SDValue DAGTypeLegalizer::WidenVecRes_INSERT_SUBVECTOR(SDNode *N) {
6504 EVT VT = N->getValueType(0);
6505 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6506 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
6507 SDValue InOp2 = N->getOperand(1);
6508 SDValue Idx = N->getOperand(2);
6509 SDLoc dl(N);
6510 return DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WidenVT, InOp1, InOp2, Idx);
6511}
6512
6513SDValue DAGTypeLegalizer::WidenVecRes_EXTRACT_SUBVECTOR(SDNode *N) {
6514 EVT VT = N->getValueType(0);
6515 EVT EltVT = VT.getVectorElementType();
6516 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6517 SDValue InOp = N->getOperand(0);
6518 SDValue Idx = N->getOperand(1);
6519 SDLoc dl(N);
6520
6521 auto InOpTypeAction = getTypeAction(InOp.getValueType());
6522 if (InOpTypeAction == TargetLowering::TypeWidenVector)
6523 InOp = GetWidenedVector(InOp);
6524
6525 EVT InVT = InOp.getValueType();
6526
6527 // Check if we can just return the input vector after widening.
6528 uint64_t IdxVal = Idx->getAsZExtVal();
6529 if (IdxVal == 0 && InVT == WidenVT)
6530 return InOp;
6531
6532 // Check if we can extract from the vector.
6533 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6534 unsigned InNumElts = InVT.getVectorMinNumElements();
6535 unsigned VTNumElts = VT.getVectorMinNumElements();
6536 assert(IdxVal % VTNumElts == 0 &&
6537 "Expected Idx to be a multiple of subvector minimum vector length");
6538 if (IdxVal % WidenNumElts == 0 && IdxVal + WidenNumElts < InNumElts)
6539 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, WidenVT, InOp, Idx);
6540
6541 if (VT.isScalableVector()) {
6542 // Try to split the operation up into smaller extracts and concat the
6543 // results together, e.g.
6544 // nxv6i64 extract_subvector(nxv12i64, 6)
6545 // <->
6546 // nxv8i64 concat(
6547 // nxv2i64 extract_subvector(nxv16i64, 6)
6548 // nxv2i64 extract_subvector(nxv16i64, 8)
6549 // nxv2i64 extract_subvector(nxv16i64, 10)
6550 // undef)
6551 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
6552 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
6553 "down type's element count");
6554 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
6556 // Avoid recursion around e.g. nxv1i8.
6557 if (getTypeAction(PartVT) != TargetLowering::TypeWidenVector) {
6559 unsigned I = 0;
6560 for (; I < VTNumElts / GCD; ++I)
6561 Parts.push_back(
6562 DAG.getExtractSubvector(dl, PartVT, InOp, IdxVal + I * GCD));
6563 for (; I < WidenNumElts / GCD; ++I)
6564 Parts.push_back(DAG.getPOISON(PartVT));
6565
6566 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
6567 }
6568
6569 // Fallback to extracting through memory.
6570
6571 Align Alignment = DAG.getReducedAlign(InVT, /*UseABI=*/false);
6572 SDValue StackPtr = DAG.CreateStackTemporary(InVT.getStoreSize(), Alignment);
6573 MachineFunction &MF = DAG.getMachineFunction();
6574 int FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
6575 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
6576
6577 MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
6580 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
6583
6584 // Write out the input vector.
6585 SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, InOp, StackPtr, StoreMMO);
6586
6587 // Build a mask to match the length of the non-widened result.
6588 SDValue Mask =
6589 DAG.getMaskFromElementCount(dl, WidenVT, VT.getVectorElementCount());
6590
6591 // Read back the sub-vector setting the remaining lanes to poison.
6592 StackPtr = TLI.getVectorSubVecPointer(DAG, StackPtr, InVT, VT, Idx);
6593 return DAG.getMaskedLoad(
6594 WidenVT, dl, Ch, StackPtr, DAG.getPOISON(StackPtr.getValueType()), Mask,
6595 DAG.getPOISON(WidenVT), VT, LoadMMO, ISD::UNINDEXED, ISD::NON_EXTLOAD);
6596 }
6597
6598 // We could try widening the input to the right length but for now, extract
6599 // the original elements, fill the rest with undefs and build a vector.
6600 SmallVector<SDValue, 16> Ops(WidenNumElts);
6601 unsigned i;
6602 for (i = 0; i < VTNumElts; ++i)
6603 Ops[i] = DAG.getExtractVectorElt(dl, EltVT, InOp, IdxVal + i);
6604
6605 SDValue UndefVal = DAG.getPOISON(EltVT);
6606 for (; i < WidenNumElts; ++i)
6607 Ops[i] = UndefVal;
6608 return DAG.getBuildVector(WidenVT, dl, Ops);
6609}
6610
6611SDValue DAGTypeLegalizer::WidenVecRes_AssertZext(SDNode *N) {
6612 SDValue InOp = ModifyToType(
6613 N->getOperand(0),
6614 TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)), true);
6615 return DAG.getNode(ISD::AssertZext, SDLoc(N), InOp.getValueType(), InOp,
6616 N->getOperand(1));
6617}
6618
6619SDValue DAGTypeLegalizer::WidenVecRes_INSERT_VECTOR_ELT(SDNode *N) {
6620 SDValue InOp = GetWidenedVector(N->getOperand(0));
6621 return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(N),
6622 InOp.getValueType(), InOp,
6623 N->getOperand(1), N->getOperand(2));
6624}
6625
6626/// Either return the same load or provide appropriate casts
6627/// from the load and return that.
6628static SDValue coerceLoadedValue(SDValue LdOp, EVT FirstVT, EVT WidenVT,
6629 TypeSize LdWidth, TypeSize FirstVTWidth,
6630 SDLoc dl, SelectionDAG &DAG) {
6631 assert(TypeSize::isKnownLE(LdWidth, FirstVTWidth) &&
6632 "Load width must be less than or equal to first value type width");
6633 TypeSize WidenWidth = WidenVT.getSizeInBits();
6634 if (!FirstVT.isVector()) {
6635 unsigned NumElts =
6636 WidenWidth.getFixedValue() / FirstVTWidth.getFixedValue();
6637 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), FirstVT, NumElts);
6638 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT, LdOp);
6639 return DAG.getNode(ISD::BITCAST, dl, WidenVT, VecOp);
6640 }
6641 assert(FirstVT == WidenVT && "First value type must equal widen value type");
6642 return LdOp;
6643}
6644
6645/// Inverse of coerceLoadedValue: pull a FirstVT-sized scalar/vector out of the
6646/// widened value so it can be issued in a single atomic store.
6647static SDValue coerceStoredValue(SDValue StVal, EVT FirstVT, EVT WidenVT,
6648 TypeSize FirstVTWidth, const SDLoc &dl,
6649 SelectionDAG &DAG) {
6650 TypeSize WidenWidth = WidenVT.getSizeInBits();
6651 if (!FirstVT.isVector()) {
6652 unsigned NumElts =
6653 WidenWidth.getFixedValue() / FirstVTWidth.getFixedValue();
6654 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), FirstVT, NumElts);
6655 SDValue VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, StVal);
6656 return DAG.getExtractVectorElt(dl, FirstVT, VecOp, 0);
6657 }
6658 assert(FirstVT == WidenVT && "First value type must equal widen value type");
6659 return StVal;
6660}
6661
6662static std::optional<EVT> findMemType(SelectionDAG &DAG,
6663 const TargetLowering &TLI, unsigned Width,
6664 EVT WidenVT, unsigned Align,
6665 unsigned WidenEx);
6666
6667SDValue DAGTypeLegalizer::WidenVecRes_ATOMIC_LOAD(AtomicSDNode *LD) {
6668 EVT WidenVT =
6669 TLI.getTypeToTransformTo(*DAG.getContext(), LD->getValueType(0));
6670 EVT LdVT = LD->getMemoryVT();
6671 SDLoc dl(LD);
6672
6673 // Load information
6674 SDValue Chain = LD->getChain();
6675 SDValue BasePtr = LD->getBasePtr();
6676
6677 TypeSize LdWidth = LdVT.getSizeInBits();
6678 TypeSize WidenWidth = WidenVT.getSizeInBits();
6679 TypeSize WidthDiff = WidenWidth - LdWidth;
6680
6681 // Find the vector type that can load from.
6682 std::optional<EVT> FirstVT =
6683 findMemType(DAG, TLI, LdWidth.getKnownMinValue(), WidenVT, /*LdAlign=*/0,
6684 WidthDiff.getKnownMinValue());
6685
6686 if (!FirstVT)
6687 return SDValue();
6688
6689 SmallVector<EVT, 8> MemVTs;
6690 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
6691
6692 SDValue LdOp = DAG.getAtomicLoad(ISD::NON_EXTLOAD, dl, *FirstVT, *FirstVT,
6693 Chain, BasePtr, LD->getMemOperand());
6694
6695 // Load the element with one instruction.
6696 SDValue Result = coerceLoadedValue(LdOp, *FirstVT, WidenVT, LdWidth,
6697 FirstVTWidth, dl, DAG);
6698
6699 // Modified the chain - switch anything that used the old chain to use
6700 // the new one.
6701 ReplaceValueWith(SDValue(LD, 1), LdOp.getValue(1));
6702 return Result;
6703}
6704
6705SDValue DAGTypeLegalizer::WidenVecRes_LOAD(SDNode *N) {
6706 LoadSDNode *LD = cast<LoadSDNode>(N);
6707 ISD::LoadExtType ExtType = LD->getExtensionType();
6708
6709 // A vector must always be stored in memory as-is, i.e. without any padding
6710 // between the elements, since various code depend on it, e.g. in the
6711 // handling of a bitcast of a vector type to int, which may be done with a
6712 // vector store followed by an integer load. A vector that does not have
6713 // elements that are byte-sized must therefore be stored as an integer
6714 // built out of the extracted vector elements.
6715 if (!LD->getMemoryVT().isByteSized()) {
6716 SDValue Value, NewChain;
6717 std::tie(Value, NewChain) = TLI.scalarizeVectorLoad(LD, DAG);
6718 ReplaceValueWith(SDValue(LD, 0), Value);
6719 ReplaceValueWith(SDValue(LD, 1), NewChain);
6720 return SDValue();
6721 }
6722
6723 // Generate a vector-predicated load if it is custom/legal on the target. To
6724 // avoid possible recursion, only do this if the widened mask type is legal.
6725 // FIXME: Not all targets may support EVL in VP_LOAD. These will have been
6726 // removed from the IR by the ExpandVectorPredication pass but we're
6727 // reintroducing them here.
6728 EVT VT = LD->getValueType(0);
6729 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6730 EVT WideMaskVT = getSetCCResultType(WideVT);
6731
6732 if (ExtType == ISD::NON_EXTLOAD &&
6733 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WideVT) &&
6734 TLI.isTypeLegal(WideMaskVT)) {
6735 SDLoc DL(N);
6736 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
6737 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
6739 SDValue NewLoad =
6740 DAG.getLoadVP(LD->getAddressingMode(), ISD::NON_EXTLOAD, WideVT, DL,
6741 LD->getChain(), LD->getBasePtr(), LD->getOffset(), Mask,
6742 EVL, LD->getMemoryVT(), LD->getMemOperand());
6743
6744 // Modified the chain - switch anything that used the old chain to use
6745 // the new one.
6746 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6747
6748 return NewLoad;
6749 }
6750
6752 SmallVector<SDValue, 16> LdChain; // Chain for the series of load
6753 if (ExtType != ISD::NON_EXTLOAD)
6754 Result = GenWidenVectorExtLoads(LdChain, LD, ExtType);
6755 else
6756 Result = GenWidenVectorLoads(LdChain, LD);
6757
6758 if (Result) {
6759 // If we generate a single load, we can use that for the chain. Otherwise,
6760 // build a factor node to remember the multiple loads are independent and
6761 // chain to that.
6762 SDValue NewChain;
6763 if (LdChain.size() == 1)
6764 NewChain = LdChain[0];
6765 else
6766 NewChain = DAG.getNode(ISD::TokenFactor, SDLoc(LD), MVT::Other, LdChain);
6767
6768 // Modified the chain - switch anything that used the old chain to use
6769 // the new one.
6770 ReplaceValueWith(SDValue(N, 1), NewChain);
6771
6772 return Result;
6773 }
6774
6775 if (VT.isVector()) {
6776 // If all else fails replace the load with a wide masked load.
6777 SDLoc DL(N);
6778 SDValue Mask =
6779 DAG.getMaskFromElementCount(DL, WideVT, VT.getVectorElementCount());
6780
6781 SDValue NewLoad = DAG.getMaskedLoad(
6782 WideVT, DL, LD->getChain(), LD->getBasePtr(), LD->getOffset(), Mask,
6783 DAG.getPOISON(WideVT), LD->getMemoryVT(), LD->getMemOperand(),
6784 LD->getAddressingMode(), LD->getExtensionType());
6785
6786 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6787 return NewLoad;
6788 }
6789
6790 report_fatal_error("Unable to widen vector load");
6791}
6792
6793SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD(VPLoadSDNode *N) {
6794 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6795 SDValue Mask = N->getMask();
6796 SDValue EVL = N->getVectorLength();
6797 ISD::LoadExtType ExtType = N->getExtensionType();
6798 SDLoc dl(N);
6799
6800 // The mask should be widened as well
6801 assert(getTypeAction(Mask.getValueType()) ==
6803 "Unable to widen binary VP op");
6804 Mask = GetWidenedVector(Mask);
6805 assert(Mask.getValueType().getVectorElementCount() ==
6806 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
6807 .getVectorElementCount() &&
6808 "Unable to widen vector load");
6809
6810 SDValue Res =
6811 DAG.getLoadVP(N->getAddressingMode(), ExtType, WidenVT, dl, N->getChain(),
6812 N->getBasePtr(), N->getOffset(), Mask, EVL,
6813 N->getMemoryVT(), N->getMemOperand(), N->isExpandingLoad());
6814 // Legalize the chain result - switch anything that used the old chain to
6815 // use the new one.
6816 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6817 return Res;
6818}
6819
6820SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD_FF(VPLoadFFSDNode *N) {
6821 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6822 SDValue Mask = N->getMask();
6823 SDValue EVL = N->getVectorLength();
6824 SDLoc dl(N);
6825
6826 // The mask should be widened as well
6827 assert(getTypeAction(Mask.getValueType()) ==
6829 "Unable to widen binary VP op");
6830 Mask = GetWidenedVector(Mask);
6831 assert(Mask.getValueType().getVectorElementCount() ==
6832 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
6833 .getVectorElementCount() &&
6834 "Unable to widen vector load");
6835
6836 SDValue Res = DAG.getLoadFFVP(WidenVT, dl, N->getChain(), N->getBasePtr(),
6837 Mask, EVL, N->getMemOperand());
6838 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6839 ReplaceValueWith(SDValue(N, 2), Res.getValue(2));
6840 return Res;
6841}
6842
6843SDValue DAGTypeLegalizer::WidenVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode *N) {
6844 SDLoc DL(N);
6845
6846 // The mask should be widened as well
6847 SDValue Mask = N->getMask();
6848 assert(getTypeAction(Mask.getValueType()) ==
6850 "Unable to widen VP strided load");
6851 Mask = GetWidenedVector(Mask);
6852
6853 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6854 assert(Mask.getValueType().getVectorElementCount() ==
6855 WidenVT.getVectorElementCount() &&
6856 "Data and mask vectors should have the same number of elements");
6857
6858 SDValue Res = DAG.getStridedLoadVP(
6859 N->getAddressingMode(), N->getExtensionType(), WidenVT, DL, N->getChain(),
6860 N->getBasePtr(), N->getOffset(), N->getStride(), Mask,
6861 N->getVectorLength(), N->getMemoryVT(), N->getMemOperand(),
6862 N->isExpandingLoad());
6863
6864 // Legalize the chain result - switch anything that used the old chain to
6865 // use the new one.
6866 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6867 return Res;
6868}
6869
6870SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_COMPRESS(SDNode *N) {
6871 SDValue Vec = N->getOperand(0);
6872 SDValue Mask = N->getOperand(1);
6873 SDValue Passthru = N->getOperand(2);
6874 EVT WideVecVT =
6875 TLI.getTypeToTransformTo(*DAG.getContext(), Vec.getValueType());
6876 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
6877 Mask.getValueType().getVectorElementType(),
6878 WideVecVT.getVectorElementCount());
6879
6880 SDValue WideVec = ModifyToType(Vec, WideVecVT);
6881 SDValue WideMask = ModifyToType(Mask, WideMaskVT, /*FillWithZeroes=*/true);
6882 SDValue WidePassthru = ModifyToType(Passthru, WideVecVT);
6883 return DAG.getNode(ISD::VECTOR_COMPRESS, SDLoc(N), WideVecVT, WideVec,
6884 WideMask, WidePassthru);
6885}
6886
6887SDValue DAGTypeLegalizer::WidenVecRes_MLOAD(MaskedLoadSDNode *N) {
6888 EVT VT = N->getValueType(0);
6889 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6890 SDValue Mask = N->getMask();
6891 EVT MaskVT = Mask.getValueType();
6892 SDValue PassThru = GetWidenedVector(N->getPassThru());
6893 ISD::LoadExtType ExtType = N->getExtensionType();
6894 SDLoc dl(N);
6895
6896 EVT WideMaskVT =
6897 EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(),
6898 WidenVT.getVectorElementCount());
6899
6900 if (ExtType == ISD::NON_EXTLOAD && !N->isExpandingLoad() &&
6901 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WidenVT) &&
6902 TLI.isTypeLegal(WideMaskVT) &&
6903 // If there is a passthru, we shouldn't use vp.load. However,
6904 // type legalizer will struggle on masked.load with
6905 // scalable vectors, so for scalable vectors, we still use vp.load
6906 // but manually merge the load result with the passthru using vp.select.
6907 (N->getPassThru()->isUndef() || VT.isScalableVector())) {
6908 Mask = DAG.getInsertSubvector(dl, DAG.getPOISON(WideMaskVT), Mask, 0);
6909 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
6911 SDValue NewLoad =
6912 DAG.getLoadVP(N->getAddressingMode(), ISD::NON_EXTLOAD, WidenVT, dl,
6913 N->getChain(), N->getBasePtr(), N->getOffset(), Mask, EVL,
6914 N->getMemoryVT(), N->getMemOperand());
6915 SDValue NewVal = NewLoad;
6916
6917 // Manually merge with vselect
6918 if (!N->getPassThru()->isUndef()) {
6919 assert(WidenVT.isScalableVector());
6920 NewVal = DAG.getNode(ISD::VSELECT, dl, WidenVT, Mask, NewVal, PassThru);
6921 // The lanes past EVL are poison.
6922 NewVal = DAG.getNode(ISD::VP_MERGE, dl, WidenVT,
6923 DAG.getAllOnesConstant(dl, WideMaskVT), NewVal,
6924 DAG.getPOISON(WidenVT), EVL);
6925 }
6926
6927 // Modified the chain - switch anything that used the old chain to use
6928 // the new one.
6929 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6930
6931 return NewVal;
6932 }
6933
6934 // The mask should be widened as well
6935 Mask = ModifyToType(Mask, WideMaskVT, true);
6936
6937 SDValue Res = DAG.getMaskedLoad(
6938 WidenVT, dl, N->getChain(), N->getBasePtr(), N->getOffset(), Mask,
6939 PassThru, N->getMemoryVT(), N->getMemOperand(), N->getAddressingMode(),
6940 ExtType, N->isExpandingLoad());
6941 // Legalize the chain result - switch anything that used the old chain to
6942 // use the new one.
6943 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6944 return Res;
6945}
6946
6947SDValue DAGTypeLegalizer::WidenVecRes_MGATHER(MaskedGatherSDNode *N) {
6948
6949 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6950 SDValue Mask = N->getMask();
6951 EVT MaskVT = Mask.getValueType();
6952 SDValue PassThru = GetWidenedVector(N->getPassThru());
6953 SDValue Scale = N->getScale();
6954 unsigned NumElts = WideVT.getVectorNumElements();
6955 SDLoc dl(N);
6956
6957 // The mask should be widened as well
6958 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
6959 MaskVT.getVectorElementType(),
6960 WideVT.getVectorNumElements());
6961 Mask = ModifyToType(Mask, WideMaskVT, true);
6962
6963 // Widen the Index operand
6964 SDValue Index = N->getIndex();
6965 EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
6966 Index.getValueType().getScalarType(),
6967 NumElts);
6968 Index = ModifyToType(Index, WideIndexVT);
6969 SDValue Ops[] = { N->getChain(), PassThru, Mask, N->getBasePtr(), Index,
6970 Scale };
6971
6972 // Widen the MemoryType
6973 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
6974 N->getMemoryVT().getScalarType(), NumElts);
6975 SDValue Res = DAG.getMaskedGather(DAG.getVTList(WideVT, MVT::Other),
6976 WideMemVT, dl, Ops, N->getMemOperand(),
6977 N->getIndexType(), N->getExtensionType());
6978
6979 // Legalize the chain result - switch anything that used the old chain to
6980 // use the new one.
6981 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6982 return Res;
6983}
6984
6985SDValue DAGTypeLegalizer::WidenVecRes_VP_GATHER(VPGatherSDNode *N) {
6986 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6987 SDValue Mask = N->getMask();
6988 SDValue Scale = N->getScale();
6989 ElementCount WideEC = WideVT.getVectorElementCount();
6990 SDLoc dl(N);
6991
6992 SDValue Index = GetWidenedVector(N->getIndex());
6993 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
6994 N->getMemoryVT().getScalarType(), WideEC);
6995 Mask = GetWidenedMask(Mask, WideEC);
6996
6997 SDValue Ops[] = {N->getChain(), N->getBasePtr(), Index, Scale,
6998 Mask, N->getVectorLength()};
6999 SDValue Res = DAG.getGatherVP(DAG.getVTList(WideVT, MVT::Other), WideMemVT,
7000 dl, Ops, N->getMemOperand(), N->getIndexType());
7001
7002 // Legalize the chain result - switch anything that used the old chain to
7003 // use the new one.
7004 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7005 return Res;
7006}
7007
7008SDValue DAGTypeLegalizer::WidenVecRes_ScalarOp(SDNode *N) {
7009 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7010 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, N->getOperand(0));
7011}
7012
7013// Return true is this is a SETCC node or a strict version of it.
7014static inline bool isSETCCOp(unsigned Opcode) {
7015 switch (Opcode) {
7016 case ISD::SETCC:
7017 case ISD::STRICT_FSETCC:
7019 return true;
7020 }
7021 return false;
7022}
7023
7024// Return true if this is a node that could have two SETCCs as operands.
7025static inline bool isLogicalMaskOp(unsigned Opcode) {
7026 switch (Opcode) {
7027 case ISD::AND:
7028 case ISD::OR:
7029 case ISD::XOR:
7030 return true;
7031 }
7032 return false;
7033}
7034
7035// If N is a SETCC or a strict variant of it, return the type
7036// of the compare operands.
7038 unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
7039 return N->getOperand(OpNo).getValueType();
7040}
7041
7042// This is used just for the assert in convertMask(). Check that this either
7043// a SETCC or a previously handled SETCC by convertMask().
7044#ifndef NDEBUG
7045static inline bool isSETCCorConvertedSETCC(SDValue N) {
7046 if (N.getOpcode() == ISD::EXTRACT_SUBVECTOR)
7047 N = N.getOperand(0);
7048 else if (N.getOpcode() == ISD::CONCAT_VECTORS) {
7049 for (unsigned i = 1; i < N->getNumOperands(); ++i)
7050 if (!N->getOperand(i)->isUndef())
7051 return false;
7052 N = N.getOperand(0);
7053 }
7054
7055 if (N.getOpcode() == ISD::TRUNCATE)
7056 N = N.getOperand(0);
7057 else if (N.getOpcode() == ISD::SIGN_EXTEND)
7058 N = N.getOperand(0);
7059
7060 if (isLogicalMaskOp(N.getOpcode()))
7061 return isSETCCorConvertedSETCC(N.getOperand(0)) &&
7062 isSETCCorConvertedSETCC(N.getOperand(1));
7063
7064 return (isSETCCOp(N.getOpcode()) ||
7066}
7067#endif
7068
7069// Return a mask of vector type MaskVT to replace InMask. Also adjust MaskVT
7070// to ToMaskVT if needed with vector extension or truncation.
7071SDValue DAGTypeLegalizer::convertMask(SDValue InMask, EVT MaskVT,
7072 EVT ToMaskVT) {
7073 // Currently a SETCC or a AND/OR/XOR with two SETCCs are handled.
7074 // FIXME: This code seems to be too restrictive, we might consider
7075 // generalizing it or dropping it.
7076 assert(isSETCCorConvertedSETCC(InMask) && "Unexpected mask argument.");
7077
7078 // Make a new Mask node, with a legal result VT.
7079 SDValue Mask;
7081 for (unsigned i = 0, e = InMask->getNumOperands(); i < e; ++i)
7082 Ops.push_back(InMask->getOperand(i));
7083 if (InMask->isStrictFPOpcode()) {
7084 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask),
7085 { MaskVT, MVT::Other }, Ops);
7086 ReplaceValueWith(InMask.getValue(1), Mask.getValue(1));
7087 }
7088 else
7089 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask), MaskVT, Ops,
7090 InMask->getFlags());
7091
7092 // If MaskVT has smaller or bigger elements than ToMaskVT, a vector sign
7093 // extend or truncate is needed.
7094 LLVMContext &Ctx = *DAG.getContext();
7095 unsigned MaskScalarBits = MaskVT.getScalarSizeInBits();
7096 unsigned ToMaskScalBits = ToMaskVT.getScalarSizeInBits();
7097 if (MaskScalarBits < ToMaskScalBits) {
7098 EVT ExtVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
7099 MaskVT.getVectorNumElements());
7100 Mask = DAG.getNode(ISD::SIGN_EXTEND, SDLoc(Mask), ExtVT, Mask);
7101 } else if (MaskScalarBits > ToMaskScalBits) {
7102 EVT TruncVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
7103 MaskVT.getVectorNumElements());
7104 Mask = DAG.getNode(ISD::TRUNCATE, SDLoc(Mask), TruncVT, Mask);
7105 }
7106
7107 assert(Mask->getValueType(0).getScalarSizeInBits() ==
7108 ToMaskVT.getScalarSizeInBits() &&
7109 "Mask should have the right element size by now.");
7110
7111 // Adjust Mask to the right number of elements.
7112 unsigned CurrMaskNumEls = Mask->getValueType(0).getVectorNumElements();
7113 if (CurrMaskNumEls > ToMaskVT.getVectorNumElements()) {
7114 Mask = DAG.getExtractSubvector(SDLoc(Mask), ToMaskVT, Mask, 0);
7115 } else if (CurrMaskNumEls < ToMaskVT.getVectorNumElements()) {
7116 unsigned NumSubVecs = (ToMaskVT.getVectorNumElements() / CurrMaskNumEls);
7117 EVT SubVT = Mask->getValueType(0);
7118 SmallVector<SDValue, 16> SubOps(NumSubVecs, DAG.getPOISON(SubVT));
7119 SubOps[0] = Mask;
7120 Mask = DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Mask), ToMaskVT, SubOps);
7121 }
7122
7123 assert((Mask->getValueType(0) == ToMaskVT) &&
7124 "A mask of ToMaskVT should have been produced by now.");
7125
7126 return Mask;
7127}
7128
7129// This method tries to handle some special cases for the vselect mask
7130// and if needed adjusting the mask vector type to match that of the VSELECT.
7131// Without it, many cases end up with scalarization of the SETCC, with many
7132// unnecessary instructions.
7133SDValue DAGTypeLegalizer::WidenVSELECTMask(SDNode *N) {
7134 LLVMContext &Ctx = *DAG.getContext();
7135 SDValue Cond = N->getOperand(0);
7136
7137 if (N->getOpcode() != ISD::VSELECT)
7138 return SDValue();
7139
7140 if (!isSETCCOp(Cond->getOpcode()) && !isLogicalMaskOp(Cond->getOpcode()))
7141 return SDValue();
7142
7143 // If this is a splitted VSELECT that was previously already handled, do
7144 // nothing.
7145 EVT CondVT = Cond->getValueType(0);
7146 if (CondVT.getScalarSizeInBits() != 1)
7147 return SDValue();
7148
7149 EVT VSelVT = N->getValueType(0);
7150
7151 // This method can't handle scalable vector types.
7152 // FIXME: This support could be added in the future.
7153 if (VSelVT.isScalableVector())
7154 return SDValue();
7155
7156 // Only handle vector types which are a power of 2.
7157 if (!isPowerOf2_64(VSelVT.getSizeInBits()))
7158 return SDValue();
7159
7160 // Don't touch if this will be scalarized.
7161 EVT FinalVT = VSelVT;
7162 while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
7163 FinalVT = FinalVT.getHalfNumVectorElementsVT(Ctx);
7164
7165 if (FinalVT.getVectorNumElements() == 1)
7166 return SDValue();
7167
7168 // If there is support for an i1 vector mask, don't touch.
7169 if (isSETCCOp(Cond.getOpcode())) {
7170 EVT SetCCOpVT = getSETCCOperandType(Cond);
7171 while (TLI.getTypeAction(Ctx, SetCCOpVT) != TargetLowering::TypeLegal)
7172 SetCCOpVT = TLI.getTypeToTransformTo(Ctx, SetCCOpVT);
7173 EVT SetCCResVT = getSetCCResultType(SetCCOpVT);
7174 if (SetCCResVT.getScalarSizeInBits() == 1)
7175 return SDValue();
7176 } else if (CondVT.getScalarType() == MVT::i1) {
7177 // If there is support for an i1 vector mask (or only scalar i1 conditions),
7178 // don't touch.
7179 while (TLI.getTypeAction(Ctx, CondVT) != TargetLowering::TypeLegal)
7180 CondVT = TLI.getTypeToTransformTo(Ctx, CondVT);
7181
7182 if (CondVT.getScalarType() == MVT::i1)
7183 return SDValue();
7184 }
7185
7186 // Widen the vselect result type if needed.
7187 if (getTypeAction(VSelVT) == TargetLowering::TypeWidenVector)
7188 VSelVT = TLI.getTypeToTransformTo(Ctx, VSelVT);
7189
7190 // The mask of the VSELECT should have integer elements.
7191 EVT ToMaskVT = VSelVT;
7192 if (!ToMaskVT.getScalarType().isInteger())
7193 ToMaskVT = ToMaskVT.changeVectorElementTypeToInteger();
7194
7195 SDValue Mask;
7196 if (isSETCCOp(Cond->getOpcode())) {
7197 EVT MaskVT = getSetCCResultType(getSETCCOperandType(Cond));
7198 Mask = convertMask(Cond, MaskVT, ToMaskVT);
7199 } else if (isLogicalMaskOp(Cond->getOpcode()) &&
7200 isSETCCOp(Cond->getOperand(0).getOpcode()) &&
7201 isSETCCOp(Cond->getOperand(1).getOpcode())) {
7202 // Cond is (AND/OR/XOR (SETCC, SETCC))
7203 SDValue SETCC0 = Cond->getOperand(0);
7204 SDValue SETCC1 = Cond->getOperand(1);
7205 EVT VT0 = getSetCCResultType(getSETCCOperandType(SETCC0));
7206 EVT VT1 = getSetCCResultType(getSETCCOperandType(SETCC1));
7207 unsigned ScalarBits0 = VT0.getScalarSizeInBits();
7208 unsigned ScalarBits1 = VT1.getScalarSizeInBits();
7209 unsigned ScalarBits_ToMask = ToMaskVT.getScalarSizeInBits();
7210 EVT MaskVT;
7211 // If the two SETCCs have different VTs, either extend/truncate one of
7212 // them to the other "towards" ToMaskVT, or truncate one and extend the
7213 // other to ToMaskVT.
7214 if (ScalarBits0 != ScalarBits1) {
7215 EVT NarrowVT = ((ScalarBits0 < ScalarBits1) ? VT0 : VT1);
7216 EVT WideVT = ((NarrowVT == VT0) ? VT1 : VT0);
7217 if (ScalarBits_ToMask >= WideVT.getScalarSizeInBits())
7218 MaskVT = WideVT;
7219 else if (ScalarBits_ToMask <= NarrowVT.getScalarSizeInBits())
7220 MaskVT = NarrowVT;
7221 else
7222 MaskVT = ToMaskVT;
7223 } else
7224 // If the two SETCCs have the same VT, don't change it.
7225 MaskVT = VT0;
7226
7227 // Make new SETCCs and logical nodes.
7228 SETCC0 = convertMask(SETCC0, VT0, MaskVT);
7229 SETCC1 = convertMask(SETCC1, VT1, MaskVT);
7230 Cond = DAG.getNode(Cond->getOpcode(), SDLoc(Cond), MaskVT, SETCC0, SETCC1);
7231
7232 // Convert the logical op for VSELECT if needed.
7233 Mask = convertMask(Cond, MaskVT, ToMaskVT);
7234 } else
7235 return SDValue();
7236
7237 return Mask;
7238}
7239
7240SDValue DAGTypeLegalizer::WidenVecRes_Select(SDNode *N) {
7241 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7242 ElementCount WidenEC = WidenVT.getVectorElementCount();
7243
7244 SDValue Cond1 = N->getOperand(0);
7245 EVT CondVT = Cond1.getValueType();
7246 unsigned Opcode = N->getOpcode();
7247 if (CondVT.isVector()) {
7248 if (SDValue WideCond = WidenVSELECTMask(N)) {
7249 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
7250 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
7251 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
7252 return DAG.getNode(Opcode, SDLoc(N), WidenVT, WideCond, InOp1, InOp2);
7253 }
7254
7255 EVT CondEltVT = CondVT.getVectorElementType();
7256 EVT CondWidenVT = EVT::getVectorVT(*DAG.getContext(), CondEltVT, WidenEC);
7257 if (getTypeAction(CondVT) == TargetLowering::TypeWidenVector)
7258 Cond1 = GetWidenedVector(Cond1);
7259
7260 // If we have to split the condition there is no point in widening the
7261 // select. This would result in an cycle of widening the select ->
7262 // widening the condition operand -> splitting the condition operand ->
7263 // splitting the select -> widening the select. Instead split this select
7264 // further and widen the resulting type.
7265 if (getTypeAction(CondVT) == TargetLowering::TypeSplitVector) {
7266 SDValue SplitSelect = SplitVecOp_VSELECT(N, 0);
7267 SDValue Res = ModifyToType(SplitSelect, WidenVT);
7268 return Res;
7269 }
7270
7271 if (Cond1.getValueType() != CondWidenVT)
7272 Cond1 = ModifyToType(Cond1, CondWidenVT);
7273 }
7274
7275 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
7276 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
7277 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
7278 if (Opcode == ISD::VP_SELECT || Opcode == ISD::VP_MERGE)
7279 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2,
7280 N->getOperand(3));
7281 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2);
7282}
7283
7284SDValue DAGTypeLegalizer::WidenVecRes_SELECT_CC(SDNode *N) {
7285 SDValue InOp1 = GetWidenedVector(N->getOperand(2));
7286 SDValue InOp2 = GetWidenedVector(N->getOperand(3));
7287 return DAG.getNode(ISD::SELECT_CC, SDLoc(N),
7288 InOp1.getValueType(), N->getOperand(0),
7289 N->getOperand(1), InOp1, InOp2, N->getOperand(4));
7290}
7291
7292SDValue DAGTypeLegalizer::WidenVecRes_UNDEF(SDNode *N) {
7293 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7294 return DAG.getUNDEF(WidenVT);
7295}
7296
7297SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N) {
7298 EVT VT = N->getValueType(0);
7299 SDLoc dl(N);
7300
7301 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7302 unsigned NumElts = VT.getVectorNumElements();
7303 unsigned WidenNumElts = WidenVT.getVectorNumElements();
7304
7305 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
7306 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
7307
7308 // Adjust mask based on new input vector length.
7309 SmallVector<int, 16> NewMask(WidenNumElts, -1);
7310 for (unsigned i = 0; i != NumElts; ++i) {
7311 int Idx = N->getMaskElt(i);
7312 if (Idx < (int)NumElts)
7313 NewMask[i] = Idx;
7314 else
7315 NewMask[i] = Idx - NumElts + WidenNumElts;
7316 }
7317 return DAG.getVectorShuffle(WidenVT, dl, InOp1, InOp2, NewMask);
7318}
7319
7320SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_REVERSE(SDNode *N) {
7321 EVT VT = N->getValueType(0);
7322 EVT EltVT = VT.getVectorElementType();
7323 SDLoc dl(N);
7324
7325 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7326 SDValue OpValue = GetWidenedVector(N->getOperand(0));
7327 assert(WidenVT == OpValue.getValueType() && "Unexpected widened vector type");
7328
7329 SDValue ReverseVal = DAG.getNode(ISD::VECTOR_REVERSE, dl, WidenVT, OpValue);
7330 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
7331 unsigned VTNumElts = VT.getVectorMinNumElements();
7332 unsigned IdxVal = WidenNumElts - VTNumElts;
7333
7334 if (VT.isScalableVector()) {
7335 // Try to split the 'Widen ReverseVal' into smaller extracts and concat the
7336 // results together, e.g.(nxv6i64 -> nxv8i64)
7337 // nxv8i64 vector_reverse
7338 // <->
7339 // nxv8i64 concat(
7340 // nxv2i64 extract_subvector(nxv8i64, 2)
7341 // nxv2i64 extract_subvector(nxv8i64, 4)
7342 // nxv2i64 extract_subvector(nxv8i64, 6)
7343 // nxv2i64 undef)
7344
7345 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
7346 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
7348 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
7349 "down type's element count");
7351 unsigned i = 0;
7352 for (; i < VTNumElts / GCD; ++i)
7353 Parts.push_back(
7354 DAG.getExtractSubvector(dl, PartVT, ReverseVal, IdxVal + i * GCD));
7355 for (; i < WidenNumElts / GCD; ++i)
7356 Parts.push_back(DAG.getPOISON(PartVT));
7357
7358 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
7359 }
7360
7361 // Use VECTOR_SHUFFLE to combine new vector from 'ReverseVal' for
7362 // fixed-vectors.
7363 SmallVector<int, 16> Mask(WidenNumElts, -1);
7364 std::iota(Mask.begin(), Mask.begin() + VTNumElts, IdxVal);
7365
7366 return DAG.getVectorShuffle(WidenVT, dl, ReverseVal, DAG.getPOISON(WidenVT),
7367 Mask);
7368}
7369
7370SDValue DAGTypeLegalizer::WidenVecRes_GET_ACTIVE_LANE_MASK(SDNode *N) {
7371 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7372 return DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, SDLoc(N), NVT, N->ops());
7373}
7374
7375SDValue DAGTypeLegalizer::WidenVecRes_SETCC(SDNode *N) {
7376 assert(N->getValueType(0).isVector() &&
7377 N->getOperand(0).getValueType().isVector() &&
7378 "Operands must be vectors");
7379 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7380 ElementCount WidenEC = WidenVT.getVectorElementCount();
7381
7382 SDValue InOp1 = N->getOperand(0);
7383 EVT InVT = InOp1.getValueType();
7384 assert(InVT.isVector() && "can not widen non-vector type");
7385 EVT WidenInVT =
7386 EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), WidenEC);
7387
7388 // The input and output types often differ here, and it could be that while
7389 // we'd prefer to widen the result type, the input operands have been split.
7390 // In this case, we also need to split the result of this node as well.
7391 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector) {
7392 SDValue SplitVSetCC = SplitVecOp_VSETCC(N);
7393 SDValue Res = ModifyToType(SplitVSetCC, WidenVT);
7394 return Res;
7395 }
7396
7397 // If the inputs also widen, handle them directly. Otherwise widen by hand.
7398 SDValue InOp2 = N->getOperand(1);
7399 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
7400 InOp1 = GetWidenedVector(InOp1);
7401 InOp2 = GetWidenedVector(InOp2);
7402 } else {
7403 SDValue Poison = DAG.getPOISON(WidenInVT);
7404 SDValue ZeroIdx = DAG.getVectorIdxConstant(0, SDLoc(N));
7405 InOp1 = DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), WidenInVT, Poison,
7406 InOp1, ZeroIdx);
7407 InOp2 = DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), WidenInVT, Poison,
7408 InOp2, ZeroIdx);
7409 }
7410
7411 // Assume that the input and output will be widen appropriately. If not,
7412 // we will have to unroll it at some point.
7413 assert(InOp1.getValueType() == WidenInVT &&
7414 InOp2.getValueType() == WidenInVT &&
7415 "Input not widened to expected type!");
7416 (void)WidenInVT;
7417 if (N->getOpcode() == ISD::VP_SETCC) {
7418 SDValue Mask =
7419 GetWidenedMask(N->getOperand(3), WidenVT.getVectorElementCount());
7420 return DAG.getNode(ISD::VP_SETCC, SDLoc(N), WidenVT, InOp1, InOp2,
7421 N->getOperand(2), Mask, N->getOperand(4));
7422 }
7423 return DAG.getNode(ISD::SETCC, SDLoc(N), WidenVT, InOp1, InOp2,
7424 N->getOperand(2));
7425}
7426
7427SDValue DAGTypeLegalizer::WidenVecRes_STRICT_FSETCC(SDNode *N) {
7428 assert(N->getValueType(0).isVector() &&
7429 N->getOperand(1).getValueType().isVector() &&
7430 "Operands must be vectors");
7431 EVT VT = N->getValueType(0);
7432 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7433 unsigned WidenNumElts = WidenVT.getVectorNumElements();
7434 unsigned NumElts = VT.getVectorNumElements();
7435 EVT EltVT = VT.getVectorElementType();
7436
7437 SDLoc dl(N);
7438 SDValue Chain = N->getOperand(0);
7439 SDValue LHS = N->getOperand(1);
7440 SDValue RHS = N->getOperand(2);
7441 SDValue CC = N->getOperand(3);
7442 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
7443
7444 // Fully unroll and reassemble.
7445 SmallVector<SDValue, 8> Scalars(WidenNumElts, DAG.getPOISON(EltVT));
7446 SmallVector<SDValue, 8> Chains(NumElts);
7447 for (unsigned i = 0; i != NumElts; ++i) {
7448 SDValue LHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, LHS, i);
7449 SDValue RHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, RHS, i);
7450
7451 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
7452 {Chain, LHSElem, RHSElem, CC});
7453 Chains[i] = Scalars[i].getValue(1);
7454 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
7455 DAG.getBoolConstant(true, dl, EltVT, VT),
7456 DAG.getBoolConstant(false, dl, EltVT, VT));
7457 }
7458
7459 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
7460 ReplaceValueWith(SDValue(N, 1), NewChain);
7461
7462 return DAG.getBuildVector(WidenVT, dl, Scalars);
7463}
7464
7465//===----------------------------------------------------------------------===//
7466// Widen Vector Operand
7467//===----------------------------------------------------------------------===//
7468bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned OpNo) {
7469 LLVM_DEBUG(dbgs() << "Widen node operand " << OpNo << ": "; N->dump(&DAG));
7470 SDValue Res = SDValue();
7471
7472 // See if the target wants to custom widen this node.
7473 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
7474 return false;
7475
7476 switch (N->getOpcode()) {
7477 default:
7478#ifndef NDEBUG
7479 dbgs() << "WidenVectorOperand op #" << OpNo << ": ";
7480 N->dump(&DAG);
7481 dbgs() << "\n";
7482#endif
7483 report_fatal_error("Do not know how to widen this operator's operand!");
7484
7485 case ISD::BITCAST: Res = WidenVecOp_BITCAST(N); break;
7486 case ISD::FAKE_USE:
7487 Res = WidenVecOp_FAKE_USE(N);
7488 break;
7489 case ISD::CONCAT_VECTORS: Res = WidenVecOp_CONCAT_VECTORS(N); break;
7490 case ISD::INSERT_SUBVECTOR: Res = WidenVecOp_INSERT_SUBVECTOR(N); break;
7491 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecOp_EXTRACT_SUBVECTOR(N); break;
7492 case ISD::EXTRACT_VECTOR_ELT: Res = WidenVecOp_EXTRACT_VECTOR_ELT(N); break;
7493 case ISD::STORE: Res = WidenVecOp_STORE(N); break;
7494 case ISD::ATOMIC_STORE:
7495 Res = WidenVecOp_ATOMIC_STORE(cast<AtomicSDNode>(N));
7496 break;
7497 case ISD::VP_STORE: Res = WidenVecOp_VP_STORE(N, OpNo); break;
7498 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
7499 Res = WidenVecOp_VP_STRIDED_STORE(N, OpNo);
7500 break;
7504 Res = WidenVecOp_EXTEND_VECTOR_INREG(N);
7505 break;
7506 case ISD::MSTORE: Res = WidenVecOp_MSTORE(N, OpNo); break;
7507 case ISD::MGATHER: Res = WidenVecOp_MGATHER(N, OpNo); break;
7508 case ISD::MSCATTER: Res = WidenVecOp_MSCATTER(N, OpNo); break;
7509 case ISD::VP_SCATTER: Res = WidenVecOp_VP_SCATTER(N, OpNo); break;
7510 case ISD::SETCC: Res = WidenVecOp_SETCC(N); break;
7511 case ISD::STRICT_FSETCC:
7512 case ISD::STRICT_FSETCCS: Res = WidenVecOp_STRICT_FSETCC(N); break;
7513 case ISD::VSELECT: Res = WidenVecOp_VSELECT(N); break;
7514 case ISD::FLDEXP:
7515 case ISD::FCOPYSIGN:
7516 case ISD::LROUND:
7517 case ISD::LLROUND:
7518 case ISD::LRINT:
7519 case ISD::LLRINT:
7520 Res = WidenVecOp_UnrollVectorOp(N);
7521 break;
7522 case ISD::IS_FPCLASS: Res = WidenVecOp_IS_FPCLASS(N); break;
7523
7524 case ISD::ANY_EXTEND:
7525 case ISD::SIGN_EXTEND:
7526 case ISD::ZERO_EXTEND:
7527 Res = WidenVecOp_EXTEND(N);
7528 break;
7529
7530 case ISD::SCMP:
7531 case ISD::UCMP:
7532 Res = WidenVecOp_CMP(N);
7533 break;
7534
7535 case ISD::FP_EXTEND:
7537 case ISD::FP_ROUND:
7539 case ISD::FP_TO_SINT:
7541 case ISD::FP_TO_UINT:
7543 case ISD::SINT_TO_FP:
7545 case ISD::UINT_TO_FP:
7547 case ISD::TRUNCATE:
7549 Res = WidenVecOp_Convert(N);
7550 break;
7551
7554 Res = WidenVecOp_FP_TO_XINT_SAT(N);
7555 break;
7556
7559 case ISD::VECREDUCE_ADD:
7560 case ISD::VECREDUCE_MUL:
7561 case ISD::VECREDUCE_AND:
7562 case ISD::VECREDUCE_OR:
7563 case ISD::VECREDUCE_XOR:
7572 Res = WidenVecOp_VECREDUCE(N);
7573 break;
7576 Res = WidenVecOp_VECREDUCE_SEQ(N);
7577 break;
7578 case ISD::VP_REDUCE_FADD:
7579 case ISD::VP_REDUCE_SEQ_FADD:
7580 case ISD::VP_REDUCE_FMUL:
7581 case ISD::VP_REDUCE_SEQ_FMUL:
7582 case ISD::VP_REDUCE_ADD:
7583 case ISD::VP_REDUCE_MUL:
7584 case ISD::VP_REDUCE_AND:
7585 case ISD::VP_REDUCE_OR:
7586 case ISD::VP_REDUCE_XOR:
7587 case ISD::VP_REDUCE_SMAX:
7588 case ISD::VP_REDUCE_SMIN:
7589 case ISD::VP_REDUCE_UMAX:
7590 case ISD::VP_REDUCE_UMIN:
7591 case ISD::VP_REDUCE_FMAX:
7592 case ISD::VP_REDUCE_FMIN:
7593 case ISD::VP_REDUCE_FMAXIMUM:
7594 case ISD::VP_REDUCE_FMINIMUM:
7595 Res = WidenVecOp_VP_REDUCE(N);
7596 break;
7597 case ISD::VP_CTTZ_ELTS:
7598 case ISD::VP_CTTZ_ELTS_ZERO_POISON:
7599 Res = WidenVecOp_VP_CttzElements(N);
7600 break;
7602 Res = WidenVecOp_VECTOR_FIND_LAST_ACTIVE(N);
7603 break;
7604 }
7605
7606 // If Res is null, the sub-method took care of registering the result.
7607 if (!Res.getNode()) return false;
7608
7609 // If the result is N, the sub-method updated N in place. Tell the legalizer
7610 // core about this.
7611 if (Res.getNode() == N)
7612 return true;
7613
7614
7615 if (N->isStrictFPOpcode())
7616 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
7617 "Invalid operand expansion");
7618 else
7619 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
7620 "Invalid operand expansion");
7621
7622 ReplaceValueWith(SDValue(N, 0), Res);
7623 return false;
7624}
7625
7626SDValue DAGTypeLegalizer::WidenVecOp_EXTEND(SDNode *N) {
7627 SDLoc DL(N);
7628 EVT VT = N->getValueType(0);
7629
7630 SDValue InOp = N->getOperand(0);
7631 assert(getTypeAction(InOp.getValueType()) ==
7633 "Unexpected type action");
7634 InOp = GetWidenedVector(InOp);
7637 "Input wasn't widened!");
7638
7639 // We may need to further widen the operand until it has the same total
7640 // vector size as the result.
7641 EVT InVT = InOp.getValueType();
7642 if (InVT.getSizeInBits() != VT.getSizeInBits()) {
7643 EVT InEltVT = InVT.getVectorElementType();
7644 for (EVT FixedVT : MVT::vector_valuetypes()) {
7645 EVT FixedEltVT = FixedVT.getVectorElementType();
7646 if (TLI.isTypeLegal(FixedVT) &&
7647 FixedVT.getSizeInBits() == VT.getSizeInBits() &&
7648 FixedEltVT == InEltVT) {
7649 assert(FixedVT.getVectorNumElements() >= VT.getVectorNumElements() &&
7650 "Not enough elements in the fixed type for the operand!");
7651 assert(FixedVT.getVectorNumElements() != InVT.getVectorNumElements() &&
7652 "We can't have the same type as we started with!");
7653 if (FixedVT.getVectorNumElements() > InVT.getVectorNumElements())
7654 InOp = DAG.getInsertSubvector(DL, DAG.getPOISON(FixedVT), InOp, 0);
7655 else
7656 InOp = DAG.getExtractSubvector(DL, FixedVT, InOp, 0);
7657 break;
7658 }
7659 }
7660 InVT = InOp.getValueType();
7661 if (InVT.getSizeInBits() != VT.getSizeInBits())
7662 // We couldn't find a legal vector type that was a widening of the input
7663 // and could be extended in-register to the result type, so we have to
7664 // scalarize.
7665 return WidenVecOp_Convert(N);
7666 }
7667
7668 // Use special DAG nodes to represent the operation of extending the
7669 // low lanes.
7670 switch (N->getOpcode()) {
7671 default:
7672 llvm_unreachable("Extend legalization on extend operation!");
7673 case ISD::ANY_EXTEND:
7674 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, VT, InOp);
7675 case ISD::SIGN_EXTEND:
7676 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, VT, InOp);
7677 case ISD::ZERO_EXTEND:
7678 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, VT, InOp);
7679 }
7680}
7681
7682SDValue DAGTypeLegalizer::WidenVecOp_CMP(SDNode *N) {
7683 SDLoc dl(N);
7684
7685 EVT OpVT = N->getOperand(0).getValueType();
7686 EVT ResVT = N->getValueType(0);
7687 SDValue LHS = GetWidenedVector(N->getOperand(0));
7688 SDValue RHS = GetWidenedVector(N->getOperand(1));
7689
7690 // 1. EXTRACT_SUBVECTOR
7691 // 2. SIGN_EXTEND/ZERO_EXTEND
7692 // 3. CMP
7693 LHS = DAG.getExtractSubvector(dl, OpVT, LHS, 0);
7694 RHS = DAG.getExtractSubvector(dl, OpVT, RHS, 0);
7695
7696 // At this point the result type is guaranteed to be valid, so we can use it
7697 // as the operand type by extending it appropriately
7698 ISD::NodeType ExtendOpcode =
7699 N->getOpcode() == ISD::SCMP ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
7700 LHS = DAG.getNode(ExtendOpcode, dl, ResVT, LHS);
7701 RHS = DAG.getNode(ExtendOpcode, dl, ResVT, RHS);
7702
7703 return DAG.getNode(N->getOpcode(), dl, ResVT, LHS, RHS);
7704}
7705
7706SDValue DAGTypeLegalizer::WidenVecOp_UnrollVectorOp(SDNode *N) {
7707 // The result (and first input) is legal, but the second input is illegal.
7708 // We can't do much to fix that, so just unroll and let the extracts off of
7709 // the second input be widened as needed later.
7710 return DAG.UnrollVectorOp(N);
7711}
7712
7713SDValue DAGTypeLegalizer::WidenVecOp_IS_FPCLASS(SDNode *N) {
7714 SDLoc DL(N);
7715 EVT ResultVT = N->getValueType(0);
7716 SDValue Test = N->getOperand(1);
7717 SDValue WideArg = GetWidenedVector(N->getOperand(0));
7718
7719 // Process this node similarly to SETCC.
7720 EVT WideResultVT = getSetCCResultType(WideArg.getValueType());
7721 if (ResultVT.getScalarType() == MVT::i1)
7722 WideResultVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
7723 WideResultVT.getVectorNumElements());
7724
7725 SDValue WideNode = DAG.getNode(ISD::IS_FPCLASS, DL, WideResultVT,
7726 {WideArg, Test}, N->getFlags());
7727
7728 // Extract the needed results from the result vector.
7729 EVT ResVT =
7730 EVT::getVectorVT(*DAG.getContext(), WideResultVT.getVectorElementType(),
7731 ResultVT.getVectorNumElements());
7732 SDValue CC = DAG.getExtractSubvector(DL, ResVT, WideNode, 0);
7733
7734 EVT OpVT = N->getOperand(0).getValueType();
7735 ISD::NodeType ExtendCode =
7736 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
7737 return DAG.getNode(ExtendCode, DL, ResultVT, CC);
7738}
7739
7740SDValue DAGTypeLegalizer::WidenVecOp_Convert(SDNode *N) {
7741 // Since the result is legal and the input is illegal.
7742 EVT VT = N->getValueType(0);
7743 EVT EltVT = VT.getVectorElementType();
7744 SDLoc dl(N);
7745 SDValue InOp = N->getOperand(N->isStrictFPOpcode() ? 1 : 0);
7746 assert(getTypeAction(InOp.getValueType()) ==
7748 "Unexpected type action");
7749 InOp = GetWidenedVector(InOp);
7750 EVT InVT = InOp.getValueType();
7751 unsigned Opcode = N->getOpcode();
7752
7753 // See if a widened result type would be legal, if so widen the node.
7754 // FIXME: This isn't safe for StrictFP. Other optimization here is needed.
7755 EVT WideVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
7756 InVT.getVectorElementCount());
7757 if (TLI.isTypeLegal(WideVT) && !N->isStrictFPOpcode()) {
7758 SDValue Res;
7759 if (N->isStrictFPOpcode()) {
7760 if (Opcode == ISD::STRICT_FP_ROUND)
7761 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
7762 { N->getOperand(0), InOp, N->getOperand(2) });
7763 else
7764 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
7765 { N->getOperand(0), InOp });
7766 // Legalize the chain result - switch anything that used the old chain to
7767 // use the new one.
7768 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7769 } else {
7770 if (Opcode == ISD::FP_ROUND || Opcode == ISD::CONVERT_FROM_ARBITRARY_FP)
7771 Res = DAG.getNode(Opcode, dl, WideVT, InOp, N->getOperand(1));
7772 else
7773 Res = DAG.getNode(Opcode, dl, WideVT, InOp);
7774 }
7775 return DAG.getExtractSubvector(dl, VT, Res, 0);
7776 }
7777
7778 EVT InEltVT = InVT.getVectorElementType();
7779
7780 // Unroll the convert into some scalar code and create a nasty build vector.
7781 unsigned NumElts = VT.getVectorNumElements();
7783 if (N->isStrictFPOpcode()) {
7784 SmallVector<SDValue, 4> NewOps(N->ops());
7785 SmallVector<SDValue, 32> OpChains;
7786 for (unsigned i=0; i < NumElts; ++i) {
7787 NewOps[1] = DAG.getExtractVectorElt(dl, InEltVT, InOp, i);
7788 Ops[i] = DAG.getNode(Opcode, dl, { EltVT, MVT::Other }, NewOps);
7789 OpChains.push_back(Ops[i].getValue(1));
7790 }
7791 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OpChains);
7792 ReplaceValueWith(SDValue(N, 1), NewChain);
7793 } else {
7794 for (unsigned i = 0; i < NumElts; ++i) {
7795 SDValue Elt = DAG.getExtractVectorElt(dl, InEltVT, InOp, i);
7796 if (Opcode == ISD::FP_ROUND || Opcode == ISD::CONVERT_FROM_ARBITRARY_FP)
7797 Ops[i] = DAG.getNode(Opcode, dl, EltVT, Elt, N->getOperand(1));
7798 else
7799 Ops[i] = DAG.getNode(Opcode, dl, EltVT, Elt);
7800 }
7801 }
7802
7803 return DAG.getBuildVector(VT, dl, Ops);
7804}
7805
7806SDValue DAGTypeLegalizer::WidenVecOp_FP_TO_XINT_SAT(SDNode *N) {
7807 EVT DstVT = N->getValueType(0);
7808 SDValue Src = GetWidenedVector(N->getOperand(0));
7809 EVT SrcVT = Src.getValueType();
7810 ElementCount WideNumElts = SrcVT.getVectorElementCount();
7811 SDLoc dl(N);
7812
7813 // See if a widened result type would be legal, if so widen the node.
7814 EVT WideDstVT = EVT::getVectorVT(*DAG.getContext(),
7815 DstVT.getVectorElementType(), WideNumElts);
7816 if (TLI.isTypeLegal(WideDstVT)) {
7817 SDValue Res =
7818 DAG.getNode(N->getOpcode(), dl, WideDstVT, Src, N->getOperand(1));
7819 return DAG.getNode(
7820 ISD::EXTRACT_SUBVECTOR, dl, DstVT, Res,
7821 DAG.getConstant(0, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
7822 }
7823
7824 // Give up and unroll.
7825 return DAG.UnrollVectorOp(N);
7826}
7827
7828SDValue DAGTypeLegalizer::WidenVecOp_BITCAST(SDNode *N) {
7829 EVT VT = N->getValueType(0);
7830 SDValue InOp = GetWidenedVector(N->getOperand(0));
7831 EVT InWidenVT = InOp.getValueType();
7832 SDLoc dl(N);
7833
7834 // Check if we can convert between two legal vector types and extract.
7835 TypeSize InWidenSize = InWidenVT.getSizeInBits();
7836 TypeSize Size = VT.getSizeInBits();
7837 // x86mmx is not an acceptable vector element type, so don't try.
7838 if (!VT.isVector() && VT != MVT::x86mmx &&
7839 InWidenSize.hasKnownScalarFactor(Size)) {
7840 unsigned NewNumElts = InWidenSize.getKnownScalarFactor(Size);
7841 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), VT, NewNumElts);
7842 if (TLI.isTypeLegal(NewVT)) {
7843 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
7844 return DAG.getExtractVectorElt(dl, VT, BitOp, 0);
7845 }
7846 }
7847
7848 // Handle a case like bitcast v12i8 -> v3i32. Normally that would get widened
7849 // to v16i8 -> v4i32, but for a target where v3i32 is legal but v12i8 is not,
7850 // we end up here. Handling the case here with EXTRACT_SUBVECTOR avoids
7851 // having to copy via memory.
7852 if (VT.isVector()) {
7853 EVT EltVT = VT.getVectorElementType();
7854 unsigned EltSize = EltVT.getFixedSizeInBits();
7855 if (InWidenSize.isKnownMultipleOf(EltSize)) {
7856 ElementCount NewNumElts =
7857 (InWidenVT.getVectorElementCount() * InWidenVT.getScalarSizeInBits())
7858 .divideCoefficientBy(EltSize);
7859 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NewNumElts);
7860 if (TLI.isTypeLegal(NewVT)) {
7861 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
7862 return DAG.getExtractSubvector(dl, VT, BitOp, 0);
7863 }
7864 }
7865 }
7866
7867 return CreateStackStoreLoad(InOp, VT);
7868}
7869
7870// Vectors with sizes that are not powers of 2 need to be widened to the
7871// next largest power of 2. For example, we may get a vector of 3 32-bit
7872// integers or of 6 16-bit integers, both of which have to be widened to a
7873// 128-bit vector.
7874SDValue DAGTypeLegalizer::WidenVecOp_FAKE_USE(SDNode *N) {
7875 SDValue WidenedOp = GetWidenedVector(N->getOperand(1));
7876 return DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, N->getOperand(0),
7877 WidenedOp);
7878}
7879
7880SDValue DAGTypeLegalizer::WidenVecOp_CONCAT_VECTORS(SDNode *N) {
7881 EVT VT = N->getValueType(0);
7882 EVT EltVT = VT.getVectorElementType();
7883 EVT InVT = N->getOperand(0).getValueType();
7884 SDLoc dl(N);
7885
7886 // If the widen width for this operand is the same as the width of the concat
7887 // and all but the first operand is undef, just use the widened operand.
7888 unsigned NumOperands = N->getNumOperands();
7889 if (VT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
7890 unsigned i;
7891 for (i = 1; i < NumOperands; ++i)
7892 if (!N->getOperand(i).isUndef())
7893 break;
7894
7895 if (i == NumOperands)
7896 return GetWidenedVector(N->getOperand(0));
7897 }
7898
7899 // Otherwise, fall back to a nasty build vector.
7900 unsigned NumElts = VT.getVectorNumElements();
7902
7903 unsigned NumInElts = InVT.getVectorNumElements();
7904
7905 unsigned Idx = 0;
7906 for (unsigned i=0; i < NumOperands; ++i) {
7907 SDValue InOp = N->getOperand(i);
7908 assert(getTypeAction(InOp.getValueType()) ==
7910 "Unexpected type action");
7911 InOp = GetWidenedVector(InOp);
7912 for (unsigned j = 0; j < NumInElts; ++j)
7913 Ops[Idx++] = DAG.getExtractVectorElt(dl, EltVT, InOp, j);
7914 }
7915 return DAG.getBuildVector(VT, dl, Ops);
7916}
7917
7918SDValue DAGTypeLegalizer::WidenVecOp_INSERT_SUBVECTOR(SDNode *N) {
7919 EVT VT = N->getValueType(0);
7920 SDValue SubVec = N->getOperand(1);
7921 SDValue InVec = N->getOperand(0);
7922
7923 EVT OrigVT = SubVec.getValueType();
7924 SubVec = GetWidenedVector(SubVec);
7925 EVT SubVT = SubVec.getValueType();
7926
7927 // Whether or not all the elements of the widened SubVec will be inserted into
7928 // valid indices of VT.
7929 bool IndicesValid = false;
7930 // If we statically know that VT can fit SubVT, the indices are valid.
7931 if (VT.knownBitsGE(SubVT))
7932 IndicesValid = true;
7933 else if (VT.isScalableVector() && SubVT.isFixedLengthVector()) {
7934 // Otherwise, if we're inserting a fixed vector into a scalable vector and
7935 // we know the minimum vscale we can work out if it's valid ourselves.
7936 Attribute Attr = DAG.getMachineFunction().getFunction().getFnAttribute(
7937 Attribute::VScaleRange);
7938 if (Attr.isValid()) {
7939 unsigned VScaleMin = Attr.getVScaleRangeMin();
7940 if (VT.getSizeInBits().getKnownMinValue() * VScaleMin >=
7941 SubVT.getFixedSizeInBits())
7942 IndicesValid = true;
7943 }
7944 }
7945
7946 if (!IndicesValid)
7948 "Don't know how to widen the operands for INSERT_SUBVECTOR");
7949
7950 SDLoc DL(N);
7951
7952 // We need to make sure that the indices are still valid, otherwise we might
7953 // widen what was previously well-defined to something undefined.
7954 if (InVec.isUndef() && N->getConstantOperandVal(2) == 0)
7955 return DAG.getNode(ISD::INSERT_SUBVECTOR, DL, VT, InVec, SubVec,
7956 N->getOperand(2));
7957
7958 if (OrigVT.isScalableVector()) {
7959 // When the widened types match, overwriting the start of a vector is
7960 // effectively a merge operation that can be implement as a vselect.
7961 if (SubVT == VT && N->getConstantOperandVal(2) == 0) {
7962 SDValue Mask =
7963 DAG.getMaskFromElementCount(DL, VT, OrigVT.getVectorElementCount());
7964 return DAG.getNode(ISD::VSELECT, DL, VT, Mask, SubVec, InVec);
7965 }
7966
7967 // Fallback to inserting through memory.
7968 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
7969 SDValue StackPtr = DAG.CreateStackTemporary(VT.getStoreSize(), Alignment);
7970 MachineFunction &MF = DAG.getMachineFunction();
7971 int FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
7972 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
7973
7974 MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
7977 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
7980
7981 // Write out the vector being inserting into.
7982 SDValue Ch =
7983 DAG.getStore(DAG.getEntryNode(), DL, InVec, StackPtr, StoreMMO);
7984
7985 // Build a mask to match the length of the sub-vector.
7986 SDValue Mask =
7987 DAG.getMaskFromElementCount(DL, SubVT, OrigVT.getVectorElementCount());
7988
7989 // Overwrite the sub-vector at the required offset.
7990 SDValue SubVecPtr =
7991 TLI.getVectorSubVecPointer(DAG, StackPtr, VT, OrigVT, N->getOperand(2));
7992 Ch = DAG.getMaskedStore(Ch, DL, SubVec, SubVecPtr,
7993 DAG.getPOISON(SubVecPtr.getValueType()), Mask, VT,
7994 StoreMMO, ISD::UNINDEXED, ISD::NON_EXTLOAD);
7995
7996 // Read back the result.
7997 return DAG.getLoad(VT, DL, Ch, StackPtr, LoadMMO);
7998 }
7999
8000 // If the operands can't be widened legally, just replace the INSERT_SUBVECTOR
8001 // with a series of INSERT_VECTOR_ELT
8002 unsigned Idx = N->getConstantOperandVal(2);
8003
8004 SDValue InsertElt = InVec;
8005 for (unsigned I = 0, E = OrigVT.getVectorNumElements(); I != E; ++I) {
8006 SDValue ExtractElt =
8007 DAG.getExtractVectorElt(DL, VT.getVectorElementType(), SubVec, I);
8008 InsertElt = DAG.getInsertVectorElt(DL, InsertElt, ExtractElt, I + Idx);
8009 }
8010
8011 return InsertElt;
8012}
8013
8014SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
8015 SDValue InOp = GetWidenedVector(N->getOperand(0));
8016 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SDLoc(N),
8017 N->getValueType(0), InOp, N->getOperand(1));
8018}
8019
8020SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
8021 SDValue InOp = GetWidenedVector(N->getOperand(0));
8022 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
8023 N->getValueType(0), InOp, N->getOperand(1));
8024}
8025
8026SDValue DAGTypeLegalizer::WidenVecOp_EXTEND_VECTOR_INREG(SDNode *N) {
8027 SDLoc DL(N);
8028 EVT ResVT = N->getValueType(0);
8029
8030 // Widen the input as requested by the legalizer.
8031 SDValue WideInOp = GetWidenedVector(N->getOperand(0));
8032 EVT WideInVT = WideInOp.getValueType();
8033
8034 // Simple case: if widened input is still smaller than or equal to result,
8035 // just use it directly.
8036 if (WideInVT.getSizeInBits() <= ResVT.getSizeInBits())
8037 return DAG.getNode(N->getOpcode(), DL, ResVT, WideInOp);
8038
8039 // EXTEND_VECTOR_INREG requires input bits <= result bits.
8040 // If widening makes the input larger than the original result, widen the
8041 // result to match, then extract back down.
8042 EVT ResEltVT = ResVT.getVectorElementType();
8043 unsigned EltBits = ResEltVT.getSizeInBits();
8044 assert((WideInVT.getSizeInBits() % EltBits) == 0 &&
8045 "Widened input size must be a multiple of result element size");
8046
8047 unsigned WideNumElts = WideInVT.getSizeInBits() / EltBits;
8048 EVT WideResVT = EVT::getVectorVT(*DAG.getContext(), ResEltVT, WideNumElts);
8049
8050 SDValue WideRes = DAG.getNode(N->getOpcode(), DL, WideResVT, WideInOp);
8051 return DAG.getExtractSubvector(DL, ResVT, WideRes, 0);
8052}
8053
8054SDValue DAGTypeLegalizer::WidenVecOp_STORE(SDNode *N) {
8055 // We have to widen the value, but we want only to store the original
8056 // vector type.
8057 StoreSDNode *ST = cast<StoreSDNode>(N);
8058
8059 if (!ST->getMemoryVT().getScalarType().isByteSized())
8060 return TLI.scalarizeVectorStore(ST, DAG);
8061
8062 if (ST->isTruncatingStore())
8063 return TLI.scalarizeVectorStore(ST, DAG);
8064
8065 // Generate a vector-predicated store if it is custom/legal on the target.
8066 // To avoid possible recursion, only do this if the widened mask type is
8067 // legal.
8068 // FIXME: Not all targets may support EVL in VP_STORE. These will have been
8069 // removed from the IR by the ExpandVectorPredication pass but we're
8070 // reintroducing them here.
8071 SDValue StVal = ST->getValue();
8072 EVT StVT = StVal.getValueType();
8073 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), StVT);
8074 EVT WideMaskVT = getSetCCResultType(WideVT);
8075
8076 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
8077 TLI.isTypeLegal(WideMaskVT)) {
8078 // Widen the value.
8079 SDLoc DL(N);
8080 StVal = GetWidenedVector(StVal);
8081 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
8082 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
8083 StVT.getVectorElementCount());
8084 return DAG.getStoreVP(ST->getChain(), DL, StVal, ST->getBasePtr(),
8085 ST->getOffset(), Mask, EVL, StVT, ST->getMemOperand(),
8086 ST->getAddressingMode());
8087 }
8088
8090 if (GenWidenVectorStores(StChain, ST)) {
8091 if (StChain.size() == 1)
8092 return StChain[0];
8093
8094 return DAG.getNode(ISD::TokenFactor, SDLoc(ST), MVT::Other, StChain);
8095 }
8096
8097 if (StVT.isVector()) {
8098 // If all else fails replace the store with a wide masked store.
8099 SDLoc DL(N);
8100 SDValue WideStVal = GetWidenedVector(StVal);
8101 SDValue Mask =
8102 DAG.getMaskFromElementCount(DL, WideVT, StVT.getVectorElementCount());
8103
8104 return DAG.getMaskedStore(ST->getChain(), DL, WideStVal, ST->getBasePtr(),
8105 ST->getOffset(), Mask, ST->getMemoryVT(),
8106 ST->getMemOperand(), ST->getAddressingMode(),
8107 ST->isTruncatingStore());
8108 }
8109
8110 report_fatal_error("Unable to widen vector store");
8111}
8112
8113SDValue DAGTypeLegalizer::WidenVecOp_ATOMIC_STORE(AtomicSDNode *ST) {
8114 EVT StVT = ST->getMemoryVT();
8115 SDLoc dl(ST);
8116
8117 SDValue StVal = GetWidenedVector(ST->getVal());
8118 EVT WidenVT = StVal.getValueType();
8119
8120 TypeSize StWidth = StVT.getSizeInBits();
8121 TypeSize WidenWidth = WidenVT.getSizeInBits();
8122 TypeSize WidthDiff = WidenWidth - StWidth;
8123
8124 // Find the vector type that can store the original memory width in one
8125 // atomic operation. Pass StAlign=0 (like atomic loads); a real align would
8126 // let findMemType widen the access past the value (e.g. <2 x i8> at align 4
8127 // implies a 4-byte movl, writing undef bytes past its object).
8128 std::optional<EVT> FirstVT =
8129 findMemType(DAG, TLI, StWidth.getKnownMinValue(), WidenVT, /*StAlign=*/0,
8130 WidthDiff.getKnownMinValue());
8131 if (!FirstVT)
8132 return SDValue();
8133
8134 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
8135
8136 SDValue StOp =
8137 coerceStoredValue(StVal, *FirstVT, WidenVT, FirstVTWidth, dl, DAG);
8138
8139 return DAG.getAtomic(ISD::ATOMIC_STORE, dl, *FirstVT, ST->getChain(), StOp,
8140 ST->getBasePtr(), ST->getMemOperand());
8141}
8142
8143SDValue DAGTypeLegalizer::WidenVecOp_VP_STORE(SDNode *N, unsigned OpNo) {
8144 assert((OpNo == 1 || OpNo == 3) &&
8145 "Can widen only data or mask operand of vp_store");
8146 VPStoreSDNode *ST = cast<VPStoreSDNode>(N);
8147 SDValue Mask = ST->getMask();
8148 SDValue StVal = ST->getValue();
8149 SDLoc dl(N);
8150
8151 if (OpNo == 1) {
8152 // Widen the value.
8153 StVal = GetWidenedVector(StVal);
8154
8155 // We only handle the case where the mask needs widening to an
8156 // identically-sized type as the vector inputs.
8157 assert(getTypeAction(Mask.getValueType()) ==
8159 "Unable to widen VP store");
8160 Mask = GetWidenedVector(Mask);
8161 } else {
8162 Mask = GetWidenedVector(Mask);
8163
8164 // We only handle the case where the stored value needs widening to an
8165 // identically-sized type as the mask.
8166 assert(getTypeAction(StVal.getValueType()) ==
8168 "Unable to widen VP store");
8169 StVal = GetWidenedVector(StVal);
8170 }
8171
8172 assert(Mask.getValueType().getVectorElementCount() ==
8174 "Mask and data vectors should have the same number of elements");
8175 return DAG.getStoreVP(ST->getChain(), dl, StVal, ST->getBasePtr(),
8176 ST->getOffset(), Mask, ST->getVectorLength(),
8177 ST->getMemoryVT(), ST->getMemOperand(),
8178 ST->getAddressingMode(), ST->isTruncatingStore(),
8179 ST->isCompressingStore());
8180}
8181
8182SDValue DAGTypeLegalizer::WidenVecOp_VP_STRIDED_STORE(SDNode *N,
8183 unsigned OpNo) {
8184 assert((OpNo == 1 || OpNo == 4) &&
8185 "Can widen only data or mask operand of vp_strided_store");
8186 VPStridedStoreSDNode *SST = cast<VPStridedStoreSDNode>(N);
8187 SDValue Mask = SST->getMask();
8188 SDValue StVal = SST->getValue();
8189 SDLoc DL(N);
8190
8191 if (OpNo == 1)
8192 assert(getTypeAction(Mask.getValueType()) ==
8194 "Unable to widen VP strided store");
8195 else
8196 assert(getTypeAction(StVal.getValueType()) ==
8198 "Unable to widen VP strided store");
8199
8200 StVal = GetWidenedVector(StVal);
8201 Mask = GetWidenedVector(Mask);
8202
8204 Mask.getValueType().getVectorElementCount() &&
8205 "Data and mask vectors should have the same number of elements");
8206
8207 return DAG.getStridedStoreVP(
8208 SST->getChain(), DL, StVal, SST->getBasePtr(), SST->getOffset(),
8209 SST->getStride(), Mask, SST->getVectorLength(), SST->getMemoryVT(),
8210 SST->getMemOperand(), SST->getAddressingMode(), SST->isTruncatingStore(),
8211 SST->isCompressingStore());
8212}
8213
8214SDValue DAGTypeLegalizer::WidenVecOp_MSTORE(SDNode *N, unsigned OpNo) {
8215 assert((OpNo == 1 || OpNo == 4) &&
8216 "Can widen only data or mask operand of mstore");
8217 MaskedStoreSDNode *MST = cast<MaskedStoreSDNode>(N);
8218 SDValue Mask = MST->getMask();
8219 EVT MaskVT = Mask.getValueType();
8220 SDValue StVal = MST->getValue();
8221 EVT VT = StVal.getValueType();
8222 SDLoc dl(N);
8223
8224 EVT WideVT, WideMaskVT;
8225 if (OpNo == 1) {
8226 // Widen the value.
8227 StVal = GetWidenedVector(StVal);
8228
8229 WideVT = StVal.getValueType();
8230 WideMaskVT =
8231 EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(),
8232 WideVT.getVectorElementCount());
8233 } else {
8234 WideMaskVT = TLI.getTypeToTransformTo(*DAG.getContext(), MaskVT);
8235
8236 EVT ValueVT = StVal.getValueType();
8237 WideVT = EVT::getVectorVT(*DAG.getContext(), ValueVT.getVectorElementType(),
8238 WideMaskVT.getVectorElementCount());
8239 }
8240
8241 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
8242 TLI.isTypeLegal(WideMaskVT) && !MST->isCompressingStore()) {
8243 Mask = DAG.getInsertSubvector(dl, DAG.getPOISON(WideMaskVT), Mask, 0);
8244 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8246 return DAG.getStoreVP(MST->getChain(), dl, StVal, MST->getBasePtr(),
8247 MST->getOffset(), Mask, EVL, MST->getMemoryVT(),
8248 MST->getMemOperand(), MST->getAddressingMode());
8249 }
8250
8251 if (OpNo == 1) {
8252 // The mask should be widened as well.
8253 Mask = ModifyToType(Mask, WideMaskVT, true);
8254 } else {
8255 // Widen the mask.
8256 Mask = ModifyToType(Mask, WideMaskVT, true);
8257
8258 StVal = ModifyToType(StVal, WideVT);
8259 }
8260
8261 assert(Mask.getValueType().getVectorElementCount() ==
8263 "Mask and data vectors should have the same number of elements");
8264 return DAG.getMaskedStore(MST->getChain(), dl, StVal, MST->getBasePtr(),
8265 MST->getOffset(), Mask, MST->getMemoryVT(),
8266 MST->getMemOperand(), MST->getAddressingMode(),
8267 false, MST->isCompressingStore());
8268}
8269
8270SDValue DAGTypeLegalizer::WidenVecOp_MGATHER(SDNode *N, unsigned OpNo) {
8271 assert(OpNo == 4 && "Can widen only the index of mgather");
8272 auto *MG = cast<MaskedGatherSDNode>(N);
8273 SDValue DataOp = MG->getPassThru();
8274 SDValue Mask = MG->getMask();
8275 SDValue Scale = MG->getScale();
8276
8277 // Just widen the index. It's allowed to have extra elements.
8278 SDValue Index = GetWidenedVector(MG->getIndex());
8279
8280 SDLoc dl(N);
8281 SDValue Ops[] = {MG->getChain(), DataOp, Mask, MG->getBasePtr(), Index,
8282 Scale};
8283 SDValue Res = DAG.getMaskedGather(MG->getVTList(), MG->getMemoryVT(), dl, Ops,
8284 MG->getMemOperand(), MG->getIndexType(),
8285 MG->getExtensionType());
8286 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
8287 ReplaceValueWith(SDValue(N, 0), Res.getValue(0));
8288 return SDValue();
8289}
8290
8291SDValue DAGTypeLegalizer::WidenVecOp_MSCATTER(SDNode *N, unsigned OpNo) {
8292 MaskedScatterSDNode *MSC = cast<MaskedScatterSDNode>(N);
8293 SDValue DataOp = MSC->getValue();
8294 SDValue Mask = MSC->getMask();
8295 SDValue Index = MSC->getIndex();
8296 SDValue Scale = MSC->getScale();
8297 EVT WideMemVT = MSC->getMemoryVT();
8298
8299 if (OpNo == 1) {
8300 DataOp = GetWidenedVector(DataOp);
8301 unsigned NumElts = DataOp.getValueType().getVectorNumElements();
8302
8303 // Widen index.
8304 EVT IndexVT = Index.getValueType();
8305 EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
8306 IndexVT.getVectorElementType(), NumElts);
8307 Index = ModifyToType(Index, WideIndexVT);
8308
8309 // The mask should be widened as well.
8310 EVT MaskVT = Mask.getValueType();
8311 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
8312 MaskVT.getVectorElementType(), NumElts);
8313 Mask = ModifyToType(Mask, WideMaskVT, true);
8314
8315 // Widen the MemoryType
8316 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
8317 MSC->getMemoryVT().getScalarType(), NumElts);
8318 } else if (OpNo == 4) {
8319 // Just widen the index. It's allowed to have extra elements.
8320 Index = GetWidenedVector(Index);
8321 } else
8322 llvm_unreachable("Can't widen this operand of mscatter");
8323
8324 SDValue Ops[] = {MSC->getChain(), DataOp, Mask, MSC->getBasePtr(), Index,
8325 Scale};
8326 return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N),
8327 Ops, MSC->getMemOperand(), MSC->getIndexType(),
8328 MSC->isTruncatingStore());
8329}
8330
8331SDValue DAGTypeLegalizer::WidenVecOp_VP_SCATTER(SDNode *N, unsigned OpNo) {
8332 VPScatterSDNode *VPSC = cast<VPScatterSDNode>(N);
8333 SDValue DataOp = VPSC->getValue();
8334 SDValue Mask = VPSC->getMask();
8335 SDValue Index = VPSC->getIndex();
8336 SDValue Scale = VPSC->getScale();
8337 EVT WideMemVT = VPSC->getMemoryVT();
8338
8339 if (OpNo == 1) {
8340 DataOp = GetWidenedVector(DataOp);
8341 Index = GetWidenedVector(Index);
8342 const auto WideEC = DataOp.getValueType().getVectorElementCount();
8343 Mask = GetWidenedMask(Mask, WideEC);
8344 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
8345 VPSC->getMemoryVT().getScalarType(), WideEC);
8346 } else if (OpNo == 3) {
8347 // Just widen the index. It's allowed to have extra elements.
8348 Index = GetWidenedVector(Index);
8349 } else
8350 llvm_unreachable("Can't widen this operand of VP_SCATTER");
8351
8352 SDValue Ops[] = {
8353 VPSC->getChain(), DataOp, VPSC->getBasePtr(), Index, Scale, Mask,
8354 VPSC->getVectorLength()};
8355 return DAG.getScatterVP(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N), Ops,
8356 VPSC->getMemOperand(), VPSC->getIndexType());
8357}
8358
8359SDValue DAGTypeLegalizer::WidenVecOp_SETCC(SDNode *N) {
8360 SDValue InOp0 = GetWidenedVector(N->getOperand(0));
8361 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
8362 SDLoc dl(N);
8363 EVT VT = N->getValueType(0);
8364
8365 // WARNING: In this code we widen the compare instruction with garbage.
8366 // This garbage may contain denormal floats which may be slow. Is this a real
8367 // concern ? Should we zero the unused lanes if this is a float compare ?
8368
8369 // Get a new SETCC node to compare the newly widened operands.
8370 // Only some of the compared elements are legal.
8371 EVT SVT = getSetCCResultType(InOp0.getValueType());
8372 // The result type is legal, if its vXi1, keep vXi1 for the new SETCC.
8373 if (VT.getScalarType() == MVT::i1)
8374 SVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8375 SVT.getVectorElementCount());
8376
8377 SDValue WideSETCC = DAG.getNode(ISD::SETCC, SDLoc(N),
8378 SVT, InOp0, InOp1, N->getOperand(2));
8379
8380 // Extract the needed results from the result vector.
8381 EVT ResVT = EVT::getVectorVT(*DAG.getContext(),
8384 SDValue CC = DAG.getExtractSubvector(dl, ResVT, WideSETCC, 0);
8385
8386 EVT OpVT = N->getOperand(0).getValueType();
8387 ISD::NodeType ExtendCode =
8388 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
8389 return DAG.getNode(ExtendCode, dl, VT, CC);
8390}
8391
8392SDValue DAGTypeLegalizer::WidenVecOp_STRICT_FSETCC(SDNode *N) {
8393 SDValue Chain = N->getOperand(0);
8394 SDValue LHS = GetWidenedVector(N->getOperand(1));
8395 SDValue RHS = GetWidenedVector(N->getOperand(2));
8396 SDValue CC = N->getOperand(3);
8397 SDLoc dl(N);
8398
8399 EVT VT = N->getValueType(0);
8400 EVT EltVT = VT.getVectorElementType();
8401 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
8402 unsigned NumElts = VT.getVectorNumElements();
8403
8404 // Unroll into a build vector.
8405 SmallVector<SDValue, 8> Scalars(NumElts);
8406 SmallVector<SDValue, 8> Chains(NumElts);
8407
8408 for (unsigned i = 0; i != NumElts; ++i) {
8409 SDValue LHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, LHS, i);
8410 SDValue RHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, RHS, i);
8411
8412 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
8413 {Chain, LHSElem, RHSElem, CC});
8414 Chains[i] = Scalars[i].getValue(1);
8415 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
8416 DAG.getBoolConstant(true, dl, EltVT, VT),
8417 DAG.getBoolConstant(false, dl, EltVT, VT));
8418 }
8419
8420 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
8421 ReplaceValueWith(SDValue(N, 1), NewChain);
8422
8423 return DAG.getBuildVector(VT, dl, Scalars);
8424}
8425
8426static unsigned getExtendForIntVecReduction(unsigned Opc) {
8427 switch (Opc) {
8428 default:
8429 llvm_unreachable("Expected integer vector reduction");
8430 case ISD::VECREDUCE_ADD:
8431 case ISD::VECREDUCE_MUL:
8432 case ISD::VECREDUCE_AND:
8433 case ISD::VECREDUCE_OR:
8434 case ISD::VECREDUCE_XOR:
8435 return ISD::ANY_EXTEND;
8438 return ISD::SIGN_EXTEND;
8441 return ISD::ZERO_EXTEND;
8442 }
8443}
8444
8445SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE(SDNode *N) {
8446 SDLoc dl(N);
8447 SDValue Op = GetWidenedVector(N->getOperand(0));
8448 EVT VT = N->getValueType(0);
8449 EVT OrigVT = N->getOperand(0).getValueType();
8450 EVT WideVT = Op.getValueType();
8451 EVT ElemVT = OrigVT.getVectorElementType();
8452 SDNodeFlags Flags = N->getFlags();
8453
8454 unsigned Opc = N->getOpcode();
8455 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
8456 SDValue NeutralElem = DAG.getIdentityElement(BaseOpc, dl, ElemVT, Flags);
8457 assert(NeutralElem && "Neutral element must exist");
8458
8459 // Pad the vector with the neutral element.
8460 unsigned OrigElts = OrigVT.getVectorMinNumElements();
8461 unsigned WideElts = WideVT.getVectorMinNumElements();
8462
8463 // Generate a vp.reduce_op if it is custom/legal for the target. This avoids
8464 // needing to pad the source vector, because the inactive lanes can simply be
8465 // disabled and not contribute to the result.
8466 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opc);
8467 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WideVT)) {
8468 SDValue Start = NeutralElem;
8469 if (VT.isInteger())
8470 Start = DAG.getNode(getExtendForIntVecReduction(Opc), dl, VT, Start);
8471 assert(Start.getValueType() == VT);
8472 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8473 WideVT.getVectorElementCount());
8474 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
8475 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8476 OrigVT.getVectorElementCount());
8477 return DAG.getNode(*VPOpcode, dl, VT, {Start, Op, Mask, EVL}, Flags);
8478 }
8479
8480 if (WideVT.isScalableVector()) {
8481 unsigned GCD = std::gcd(OrigElts, WideElts);
8482 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
8484 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
8485 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
8486 Op = DAG.getInsertSubvector(dl, Op, SplatNeutral, Idx);
8487 return DAG.getNode(Opc, dl, VT, Op, Flags);
8488 }
8489
8490 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
8491 Op = DAG.getInsertVectorElt(dl, Op, NeutralElem, Idx);
8492
8493 return DAG.getNode(Opc, dl, VT, Op, Flags);
8494}
8495
8496SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE_SEQ(SDNode *N) {
8497 SDLoc dl(N);
8498 SDValue AccOp = N->getOperand(0);
8499 SDValue VecOp = N->getOperand(1);
8500 SDValue Op = GetWidenedVector(VecOp);
8501
8502 EVT VT = N->getValueType(0);
8503 EVT OrigVT = VecOp.getValueType();
8504 EVT WideVT = Op.getValueType();
8505 EVT ElemVT = OrigVT.getVectorElementType();
8506 SDNodeFlags Flags = N->getFlags();
8507
8508 unsigned Opc = N->getOpcode();
8509 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
8510 SDValue NeutralElem = DAG.getIdentityElement(BaseOpc, dl, ElemVT, Flags);
8511
8512 // Pad the vector with the neutral element.
8513 unsigned OrigElts = OrigVT.getVectorMinNumElements();
8514 unsigned WideElts = WideVT.getVectorMinNumElements();
8515
8516 // Generate a vp.reduce_op if it is custom/legal for the target. This avoids
8517 // needing to pad the source vector, because the inactive lanes can simply be
8518 // disabled and not contribute to the result.
8519 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opc);
8520 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WideVT)) {
8521 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8522 WideVT.getVectorElementCount());
8523 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
8524 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8525 OrigVT.getVectorElementCount());
8526 return DAG.getNode(*VPOpcode, dl, VT, {AccOp, Op, Mask, EVL}, Flags);
8527 }
8528
8529 if (WideVT.isScalableVector()) {
8530 unsigned GCD = std::gcd(OrigElts, WideElts);
8531 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
8533 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
8534 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
8535 Op = DAG.getInsertSubvector(dl, Op, SplatNeutral, Idx);
8536 return DAG.getNode(Opc, dl, VT, AccOp, Op, Flags);
8537 }
8538
8539 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
8540 Op = DAG.getInsertVectorElt(dl, Op, NeutralElem, Idx);
8541
8542 return DAG.getNode(Opc, dl, VT, AccOp, Op, Flags);
8543}
8544
8545SDValue DAGTypeLegalizer::WidenVecOp_VP_REDUCE(SDNode *N) {
8546 assert(N->isVPOpcode() && "Expected VP opcode");
8547
8548 SDLoc dl(N);
8549 SDValue Op = GetWidenedVector(N->getOperand(1));
8550 SDValue Mask = GetWidenedMask(N->getOperand(2),
8551 Op.getValueType().getVectorElementCount());
8552
8553 return DAG.getNode(N->getOpcode(), dl, N->getValueType(0),
8554 {N->getOperand(0), Op, Mask, N->getOperand(3)},
8555 N->getFlags());
8556}
8557
8558SDValue DAGTypeLegalizer::WidenVecOp_VSELECT(SDNode *N) {
8559 // This only gets called in the case that the left and right inputs and
8560 // result are of a legal odd vector type, and the condition is illegal i1 of
8561 // the same odd width that needs widening.
8562 EVT VT = N->getValueType(0);
8563 assert(VT.isVector() && !VT.isPow2VectorType() && isTypeLegal(VT));
8564
8565 SDValue Cond = GetWidenedVector(N->getOperand(0));
8566 SDValue LeftIn = DAG.WidenVector(N->getOperand(1), SDLoc(N));
8567 SDValue RightIn = DAG.WidenVector(N->getOperand(2), SDLoc(N));
8568 SDLoc DL(N);
8569
8570 SDValue Select = DAG.getNode(N->getOpcode(), DL, LeftIn.getValueType(), Cond,
8571 LeftIn, RightIn);
8572 return DAG.getExtractSubvector(DL, VT, Select, 0);
8573}
8574
8575SDValue DAGTypeLegalizer::WidenVecOp_VP_CttzElements(SDNode *N) {
8576 SDLoc DL(N);
8577 SDValue Source = GetWidenedVector(N->getOperand(0));
8578 EVT SrcVT = Source.getValueType();
8579 SDValue Mask =
8580 GetWidenedMask(N->getOperand(1), SrcVT.getVectorElementCount());
8581
8582 return DAG.getNode(N->getOpcode(), DL, N->getValueType(0),
8583 {Source, Mask, N->getOperand(2)}, N->getFlags());
8584}
8585
8586SDValue DAGTypeLegalizer::WidenVecOp_VECTOR_FIND_LAST_ACTIVE(SDNode *N) {
8587 SDLoc DL(N);
8588 SDValue Mask = N->getOperand(0);
8589 EVT OrigMaskVT = Mask.getValueType();
8590 SDValue WideMask = GetWidenedVector(Mask);
8591 EVT WideMaskVT = WideMask.getValueType();
8592
8593 // Pad the mask with zeros to ensure inactive lanes don't affect the result.
8594 unsigned OrigElts = OrigMaskVT.getVectorNumElements();
8595 unsigned WideElts = WideMaskVT.getVectorNumElements();
8596 if (OrigElts != WideElts) {
8597 SDValue ZeroMask = DAG.getConstant(0, DL, WideMaskVT);
8598 WideMask = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideMaskVT, ZeroMask,
8599 Mask, DAG.getVectorIdxConstant(0, DL));
8600 }
8601
8602 return DAG.getNode(ISD::VECTOR_FIND_LAST_ACTIVE, DL, N->getValueType(0),
8603 WideMask);
8604}
8605
8606//===----------------------------------------------------------------------===//
8607// Vector Widening Utilities
8608//===----------------------------------------------------------------------===//
8609
8610// Utility function to find the type to chop up a widen vector for load/store
8611// TLI: Target lowering used to determine legal types.
8612// Width: Width left need to load/store.
8613// WidenVT: The widen vector type to load to/store from
8614// Align: If 0, don't allow use of a wider type
8615// WidenEx: If Align is not 0, the amount additional we can load/store from.
8616
8617static std::optional<EVT> findMemType(SelectionDAG &DAG,
8618 const TargetLowering &TLI, unsigned Width,
8619 EVT WidenVT, unsigned Align = 0,
8620 unsigned WidenEx = 0) {
8621 EVT WidenEltVT = WidenVT.getVectorElementType();
8622 const bool Scalable = WidenVT.isScalableVector();
8623 unsigned WidenWidth = WidenVT.getSizeInBits().getKnownMinValue();
8624 unsigned WidenEltWidth = WidenEltVT.getSizeInBits();
8625 unsigned AlignInBits = Align*8;
8626
8627 EVT RetVT = WidenEltVT;
8628 // Don't bother looking for an integer type if the vector is scalable, skip
8629 // to vector types.
8630 if (!Scalable) {
8631 // If we have one element to load/store, return it.
8632 if (Width == WidenEltWidth)
8633 return RetVT;
8634
8635 // See if there is larger legal integer than the element type to load/store.
8636 for (EVT MemVT : reverse(MVT::integer_valuetypes())) {
8637 unsigned MemVTWidth = MemVT.getSizeInBits();
8638 if (MemVT.getSizeInBits() <= WidenEltWidth)
8639 break;
8640 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
8641 if ((Action == TargetLowering::TypeLegal ||
8643 (WidenWidth % MemVTWidth) == 0 &&
8644 isPowerOf2_32(WidenWidth / MemVTWidth) &&
8645 (MemVTWidth <= Width ||
8646 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
8647 if (MemVTWidth == WidenWidth)
8648 return MemVT;
8649 RetVT = MemVT;
8650 break;
8651 }
8652 }
8653 }
8654
8655 // See if there is a larger vector type to load/store that has the same vector
8656 // element type and is evenly divisible with the WidenVT.
8657 for (EVT MemVT : reverse(MVT::vector_valuetypes())) {
8658 // Skip vector MVTs which don't match the scalable property of WidenVT.
8659 if (Scalable != MemVT.isScalableVector())
8660 continue;
8661 unsigned MemVTWidth = MemVT.getSizeInBits().getKnownMinValue();
8662 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
8663 if ((Action == TargetLowering::TypeLegal ||
8665 WidenEltVT == MemVT.getVectorElementType() &&
8666 (WidenWidth % MemVTWidth) == 0 &&
8667 isPowerOf2_32(WidenWidth / MemVTWidth) &&
8668 (MemVTWidth <= Width ||
8669 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
8670 if (RetVT.getFixedSizeInBits() < MemVTWidth || MemVT == WidenVT)
8671 return MemVT;
8672 }
8673 }
8674
8675 // Using element-wise loads and stores for widening operations is not
8676 // supported for scalable vectors
8677 if (Scalable)
8678 return std::nullopt;
8679
8680 return RetVT;
8681}
8682
8683// Builds a vector type from scalar loads
8684// VecTy: Resulting Vector type
8685// LDOps: Load operators to build a vector type
8686// [Start,End) the list of loads to use.
8689 unsigned Start, unsigned End) {
8690 SDLoc dl(LdOps[Start]);
8691 EVT LdTy = LdOps[Start].getValueType();
8692 unsigned Width = VecTy.getSizeInBits();
8693 unsigned NumElts = Width / LdTy.getSizeInBits();
8694 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), LdTy, NumElts);
8695
8696 unsigned Idx = 1;
8697 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT,LdOps[Start]);
8698
8699 for (unsigned i = Start + 1; i != End; ++i) {
8700 EVT NewLdTy = LdOps[i].getValueType();
8701 if (NewLdTy != LdTy) {
8702 NumElts = Width / NewLdTy.getSizeInBits();
8703 NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewLdTy, NumElts);
8704 VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, VecOp);
8705 // Readjust position and vector position based on new load type.
8706 Idx = Idx * LdTy.getSizeInBits() / NewLdTy.getSizeInBits();
8707 LdTy = NewLdTy;
8708 }
8709 VecOp = DAG.getInsertVectorElt(dl, VecOp, LdOps[i], Idx++);
8710 }
8711 return DAG.getNode(ISD::BITCAST, dl, VecTy, VecOp);
8712}
8713
8714SDValue DAGTypeLegalizer::GenWidenVectorLoads(SmallVectorImpl<SDValue> &LdChain,
8715 LoadSDNode *LD) {
8716 // The strategy assumes that we can efficiently load power-of-two widths.
8717 // The routine chops the vector into the largest vector loads with the same
8718 // element type or scalar loads and then recombines it to the widen vector
8719 // type.
8720 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
8721 EVT LdVT = LD->getMemoryVT();
8722 SDLoc dl(LD);
8723 assert(LdVT.isVector() && WidenVT.isVector());
8724 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
8726
8727 // Load information
8728 SDValue Chain = LD->getChain();
8729 SDValue BasePtr = LD->getBasePtr();
8730 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
8731 AAMDNodes AAInfo = LD->getAAInfo();
8732
8733 TypeSize LdWidth = LdVT.getSizeInBits();
8734 TypeSize WidenWidth = WidenVT.getSizeInBits();
8735 TypeSize WidthDiff = WidenWidth - LdWidth;
8736 // Allow wider loads if they are sufficiently aligned to avoid memory faults
8737 // and if the original load is simple.
8738 unsigned LdAlign =
8739 (!LD->isSimple() || LdVT.isScalableVector()) ? 0 : LD->getAlign().value();
8740
8741 // Find the vector type that can load from.
8742 std::optional<EVT> FirstVT =
8743 findMemType(DAG, TLI, LdWidth.getKnownMinValue(), WidenVT, LdAlign,
8744 WidthDiff.getKnownMinValue());
8745
8746 if (!FirstVT)
8747 return SDValue();
8748
8749 SmallVector<EVT, 8> MemVTs;
8750 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
8751
8752 // Unless we're able to load in one instruction we must work out how to load
8753 // the remainder.
8754 if (!TypeSize::isKnownLE(LdWidth, FirstVTWidth)) {
8755 std::optional<EVT> NewVT = FirstVT;
8756 TypeSize RemainingWidth = LdWidth;
8757 TypeSize NewVTWidth = FirstVTWidth;
8758 do {
8759 RemainingWidth -= NewVTWidth;
8760 if (TypeSize::isKnownLT(RemainingWidth, NewVTWidth)) {
8761 // The current type we are using is too large. Find a better size.
8762 NewVT = findMemType(DAG, TLI, RemainingWidth.getKnownMinValue(),
8763 WidenVT, LdAlign, WidthDiff.getKnownMinValue());
8764 if (!NewVT)
8765 return SDValue();
8766 NewVTWidth = NewVT->getSizeInBits();
8767 }
8768 MemVTs.push_back(*NewVT);
8769 } while (TypeSize::isKnownGT(RemainingWidth, NewVTWidth));
8770 }
8771
8772 SDValue LdOp = DAG.getLoad(*FirstVT, dl, Chain, BasePtr, LD->getPointerInfo(),
8773 LD->getBaseAlign(), MMOFlags, AAInfo);
8774 LdChain.push_back(LdOp.getValue(1));
8775
8776 // Check if we can load the element with one instruction.
8777 if (MemVTs.empty())
8778 return coerceLoadedValue(LdOp, *FirstVT, WidenVT, LdWidth, FirstVTWidth, dl,
8779 DAG);
8780
8781 // Load vector by using multiple loads from largest vector to scalar.
8783 LdOps.push_back(LdOp);
8784
8785 uint64_t ScaledOffset = 0;
8786 MachinePointerInfo MPI = LD->getPointerInfo();
8787
8788 // First incremement past the first load.
8789 IncrementPointer(cast<LoadSDNode>(LdOp), *FirstVT, MPI, BasePtr,
8790 &ScaledOffset);
8791
8792 for (EVT MemVT : MemVTs) {
8793 Align NewAlign = ScaledOffset == 0
8794 ? LD->getBaseAlign()
8795 : commonAlignment(LD->getAlign(), ScaledOffset);
8796 SDValue L =
8797 DAG.getLoad(MemVT, dl, Chain, BasePtr, MPI, NewAlign, MMOFlags, AAInfo);
8798
8799 LdOps.push_back(L);
8800 LdChain.push_back(L.getValue(1));
8801 IncrementPointer(cast<LoadSDNode>(L), MemVT, MPI, BasePtr, &ScaledOffset);
8802 }
8803
8804 // Build the vector from the load operations.
8805 unsigned End = LdOps.size();
8806 if (!LdOps[0].getValueType().isVector())
8807 // All the loads are scalar loads.
8808 return BuildVectorFromScalar(DAG, WidenVT, LdOps, 0, End);
8809
8810 // If the load contains vectors, build the vector using concat vector.
8811 // All of the vectors used to load are power-of-2, and the scalar loads can be
8812 // combined to make a power-of-2 vector.
8813 SmallVector<SDValue, 16> ConcatOps(End);
8814 int i = End - 1;
8815 int Idx = End;
8816 EVT LdTy = LdOps[i].getValueType();
8817 // First, combine the scalar loads to a vector.
8818 if (!LdTy.isVector()) {
8819 for (--i; i >= 0; --i) {
8820 LdTy = LdOps[i].getValueType();
8821 if (LdTy.isVector())
8822 break;
8823 }
8824 ConcatOps[--Idx] = BuildVectorFromScalar(DAG, LdTy, LdOps, i + 1, End);
8825 }
8826
8827 ConcatOps[--Idx] = LdOps[i];
8828 for (--i; i >= 0; --i) {
8829 EVT NewLdTy = LdOps[i].getValueType();
8830 if (NewLdTy != LdTy) {
8831 // Create a larger vector.
8832 TypeSize LdTySize = LdTy.getSizeInBits();
8833 TypeSize NewLdTySize = NewLdTy.getSizeInBits();
8834 assert(NewLdTySize.isScalable() == LdTySize.isScalable() &&
8835 NewLdTySize.isKnownMultipleOf(LdTySize.getKnownMinValue()));
8836 unsigned NumOps =
8837 NewLdTySize.getKnownMinValue() / LdTySize.getKnownMinValue();
8839 unsigned j = 0;
8840 for (; j != End-Idx; ++j)
8841 WidenOps[j] = ConcatOps[Idx+j];
8842 for (; j != NumOps; ++j)
8843 WidenOps[j] = DAG.getPOISON(LdTy);
8844
8845 ConcatOps[End-1] = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewLdTy,
8846 WidenOps);
8847 Idx = End - 1;
8848 LdTy = NewLdTy;
8849 }
8850 ConcatOps[--Idx] = LdOps[i];
8851 }
8852
8853 if (WidenWidth == LdTy.getSizeInBits() * (End - Idx))
8854 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
8855 ArrayRef(&ConcatOps[Idx], End - Idx));
8856
8857 // We need to fill the rest with undefs to build the vector.
8858 unsigned NumOps =
8859 WidenWidth.getKnownMinValue() / LdTy.getSizeInBits().getKnownMinValue();
8861 SDValue UndefVal = DAG.getPOISON(LdTy);
8862 {
8863 unsigned i = 0;
8864 for (; i != End-Idx; ++i)
8865 WidenOps[i] = ConcatOps[Idx+i];
8866 for (; i != NumOps; ++i)
8867 WidenOps[i] = UndefVal;
8868 }
8869 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, WidenOps);
8870}
8871
8872SDValue
8873DAGTypeLegalizer::GenWidenVectorExtLoads(SmallVectorImpl<SDValue> &LdChain,
8874 LoadSDNode *LD,
8875 ISD::LoadExtType ExtType) {
8876 // For extension loads, it may not be more efficient to chop up the vector
8877 // and then extend it. Instead, we unroll the load and build a new vector.
8878 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
8879 EVT LdVT = LD->getMemoryVT();
8880 SDLoc dl(LD);
8881 assert(LdVT.isVector() && WidenVT.isVector());
8882 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
8883
8884 // Load information
8885 SDValue Chain = LD->getChain();
8886 SDValue BasePtr = LD->getBasePtr();
8887 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
8888 AAMDNodes AAInfo = LD->getAAInfo();
8889
8890 if (LdVT.isScalableVector())
8891 return SDValue();
8892
8893 EVT EltVT = WidenVT.getVectorElementType();
8894 EVT LdEltVT = LdVT.getVectorElementType();
8895 unsigned NumElts = LdVT.getVectorNumElements();
8896
8897 // Load each element and widen.
8898 unsigned WidenNumElts = WidenVT.getVectorNumElements();
8899 SmallVector<SDValue, 16> Ops(WidenNumElts);
8900 unsigned Increment = LdEltVT.getSizeInBits() / 8;
8901 Ops[0] =
8902 DAG.getExtLoad(ExtType, dl, EltVT, Chain, BasePtr, LD->getPointerInfo(),
8903 LdEltVT, LD->getBaseAlign(), MMOFlags, AAInfo);
8904 LdChain.push_back(Ops[0].getValue(1));
8905 unsigned i = 0, Offset = Increment;
8906 for (i=1; i < NumElts; ++i, Offset += Increment) {
8907 SDValue NewBasePtr =
8908 DAG.getObjectPtrOffset(dl, BasePtr, TypeSize::getFixed(Offset));
8909 Ops[i] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, NewBasePtr,
8910 LD->getPointerInfo().getWithOffset(Offset), LdEltVT,
8911 LD->getBaseAlign(), MMOFlags, AAInfo);
8912 LdChain.push_back(Ops[i].getValue(1));
8913 }
8914
8915 // Fill the rest with undefs.
8916 SDValue UndefVal = DAG.getPOISON(EltVT);
8917 for (; i != WidenNumElts; ++i)
8918 Ops[i] = UndefVal;
8919
8920 return DAG.getBuildVector(WidenVT, dl, Ops);
8921}
8922
8923bool DAGTypeLegalizer::GenWidenVectorStores(SmallVectorImpl<SDValue> &StChain,
8924 StoreSDNode *ST) {
8925 // The strategy assumes that we can efficiently store power-of-two widths.
8926 // The routine chops the vector into the largest vector stores with the same
8927 // element type or scalar stores.
8928 SDValue Chain = ST->getChain();
8929 SDValue BasePtr = ST->getBasePtr();
8930 MachineMemOperand::Flags MMOFlags = ST->getMemOperand()->getFlags();
8931 AAMDNodes AAInfo = ST->getAAInfo();
8932 SDValue ValOp = GetWidenedVector(ST->getValue());
8933 SDLoc dl(ST);
8934
8935 EVT StVT = ST->getMemoryVT();
8936 TypeSize StWidth = StVT.getSizeInBits();
8937 EVT ValVT = ValOp.getValueType();
8938 TypeSize ValWidth = ValVT.getSizeInBits();
8939 EVT ValEltVT = ValVT.getVectorElementType();
8940 unsigned ValEltWidth = ValEltVT.getFixedSizeInBits();
8941 assert(StVT.getVectorElementType() == ValEltVT);
8942 assert(StVT.isScalableVector() == ValVT.isScalableVector() &&
8943 "Mismatch between store and value types");
8944
8945 int Idx = 0; // current index to store
8946
8947 MachinePointerInfo MPI = ST->getPointerInfo();
8948 uint64_t ScaledOffset = 0;
8949
8950 // A breakdown of how to widen this vector store. Each element of the vector
8951 // is a memory VT combined with the number of times it is to be stored to,
8952 // e,g., v5i32 -> {{v2i32,2},{i32,1}}
8954
8955 while (StWidth.isNonZero()) {
8956 // Find the largest vector type we can store with.
8957 std::optional<EVT> NewVT =
8958 findMemType(DAG, TLI, StWidth.getKnownMinValue(), ValVT);
8959 if (!NewVT)
8960 return false;
8961 MemVTs.push_back({*NewVT, 0});
8962 TypeSize NewVTWidth = NewVT->getSizeInBits();
8963
8964 do {
8965 StWidth -= NewVTWidth;
8966 MemVTs.back().second++;
8967 } while (StWidth.isNonZero() && TypeSize::isKnownGE(StWidth, NewVTWidth));
8968 }
8969
8970 for (const auto &Pair : MemVTs) {
8971 EVT NewVT = Pair.first;
8972 unsigned Count = Pair.second;
8973 TypeSize NewVTWidth = NewVT.getSizeInBits();
8974
8975 if (NewVT.isVector()) {
8976 unsigned NumVTElts = NewVT.getVectorMinNumElements();
8977 do {
8978 Align NewAlign = ScaledOffset == 0
8979 ? ST->getBaseAlign()
8980 : commonAlignment(ST->getAlign(), ScaledOffset);
8981 SDValue EOp = DAG.getExtractSubvector(dl, NewVT, ValOp, Idx);
8982 SDValue PartStore = DAG.getStore(Chain, dl, EOp, BasePtr, MPI, NewAlign,
8983 MMOFlags, AAInfo);
8984 StChain.push_back(PartStore);
8985
8986 Idx += NumVTElts;
8987 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr,
8988 &ScaledOffset);
8989 } while (--Count);
8990 } else {
8991 // Cast the vector to the scalar type we can store.
8992 unsigned NumElts = ValWidth.getFixedValue() / NewVTWidth.getFixedValue();
8993 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewVT, NumElts);
8994 SDValue VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, ValOp);
8995 // Readjust index position based on new vector type.
8996 Idx = Idx * ValEltWidth / NewVTWidth.getFixedValue();
8997 do {
8998 SDValue EOp = DAG.getExtractVectorElt(dl, NewVT, VecOp, Idx++);
8999 SDValue PartStore = DAG.getStore(Chain, dl, EOp, BasePtr, MPI,
9000 ST->getBaseAlign(), MMOFlags, AAInfo);
9001 StChain.push_back(PartStore);
9002
9003 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr);
9004 } while (--Count);
9005 // Restore index back to be relative to the original widen element type.
9006 Idx = Idx * NewVTWidth.getFixedValue() / ValEltWidth;
9007 }
9008 }
9009
9010 return true;
9011}
9012
9013/// Modifies a vector input (widen or narrows) to a vector of NVT. The
9014/// input vector must have the same element type as NVT.
9015/// FillWithZeroes specifies that the vector should be widened with zeroes.
9016SDValue DAGTypeLegalizer::ModifyToType(SDValue InOp, EVT NVT,
9017 bool FillWithZeroes) {
9018 // Note that InOp might have been widened so it might already have
9019 // the right width or it might need be narrowed.
9020 EVT InVT = InOp.getValueType();
9022 "input and widen element type must match");
9023 assert(InVT.isScalableVector() == NVT.isScalableVector() &&
9024 "cannot modify scalable vectors in this way");
9025 SDLoc dl(InOp);
9026
9027 // Check if InOp already has the right width.
9028 if (InVT == NVT)
9029 return InOp;
9030
9031 ElementCount InEC = InVT.getVectorElementCount();
9032 ElementCount WidenEC = NVT.getVectorElementCount();
9033 if (WidenEC.hasKnownScalarFactor(InEC)) {
9034 unsigned NumConcat = WidenEC.getKnownScalarFactor(InEC);
9035 SmallVector<SDValue, 16> Ops(NumConcat);
9036 SDValue FillVal =
9037 FillWithZeroes ? DAG.getConstant(0, dl, InVT) : DAG.getPOISON(InVT);
9038 Ops[0] = InOp;
9039 for (unsigned i = 1; i != NumConcat; ++i)
9040 Ops[i] = FillVal;
9041
9042 return DAG.getNode(ISD::CONCAT_VECTORS, dl, NVT, Ops);
9043 }
9044
9045 if (InEC.hasKnownScalarFactor(WidenEC))
9046 return DAG.getExtractSubvector(dl, NVT, InOp, 0);
9047
9048 assert(!InVT.isScalableVector() && !NVT.isScalableVector() &&
9049 "Scalable vectors should have been handled already.");
9050
9051 unsigned InNumElts = InEC.getFixedValue();
9052 unsigned WidenNumElts = WidenEC.getFixedValue();
9053
9054 // Fall back to extract and build (+ mask, if padding with zeros).
9055 SmallVector<SDValue, 16> Ops(WidenNumElts);
9056 EVT EltVT = NVT.getVectorElementType();
9057 unsigned MinNumElts = std::min(WidenNumElts, InNumElts);
9058 unsigned Idx;
9059 for (Idx = 0; Idx < MinNumElts; ++Idx)
9060 Ops[Idx] = DAG.getExtractVectorElt(dl, EltVT, InOp, Idx);
9061
9062 SDValue UndefVal = DAG.getPOISON(EltVT);
9063 for (; Idx < WidenNumElts; ++Idx)
9064 Ops[Idx] = UndefVal;
9065
9066 SDValue Widened = DAG.getBuildVector(NVT, dl, Ops);
9067 if (!FillWithZeroes)
9068 return Widened;
9069
9070 assert(NVT.isInteger() &&
9071 "We expect to never want to FillWithZeroes for non-integral types.");
9072
9074 MaskOps.append(MinNumElts, DAG.getAllOnesConstant(dl, EltVT));
9075 MaskOps.append(WidenNumElts - MinNumElts, DAG.getConstant(0, dl, EltVT));
9076
9077 return DAG.getNode(ISD::AND, dl, NVT, Widened,
9078 DAG.getBuildVector(NVT, dl, MaskOps));
9079}
return SDValue()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static constexpr Value * getValue(Ty &ValueOrUse)
static Value * getOpcode(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static unsigned getExtendForIntVecReduction(SDNode *N)
static SDValue BuildVectorFromScalar(SelectionDAG &DAG, EVT VecTy, SmallVectorImpl< SDValue > &LdOps, unsigned Start, unsigned End)
static std::optional< EVT > findMemType(SelectionDAG &DAG, const TargetLowering &TLI, unsigned Width, EVT WidenVT, unsigned Align, unsigned WidenEx)
static EVT getSETCCOperandType(SDValue N)
static bool isSETCCOp(unsigned Opcode)
static bool isLogicalMaskOp(unsigned Opcode)
static bool isSETCCorConvertedSETCC(SDValue N)
static SDValue coerceStoredValue(SDValue StVal, EVT FirstVT, EVT WidenVT, TypeSize FirstVTWidth, const SDLoc &dl, SelectionDAG &DAG)
Inverse of coerceLoadedValue: pull a FirstVT-sized scalar/vector out of the widened value so it can b...
static SDValue CollectOpsToWiden(SelectionDAG &DAG, const TargetLowering &TLI, SmallVectorImpl< SDValue > &ConcatOps, unsigned ConcatEnd, EVT VT, EVT MaxVT, EVT WidenVT)
static SDValue coerceLoadedValue(SDValue LdOp, EVT FirstVT, EVT WidenVT, TypeSize LdWidth, TypeSize FirstVTWidth, SDLoc dl, SelectionDAG &DAG)
Either return the same load or provide appropriate casts from the load and return that.
#define I(x, y, z)
Definition MD5.cpp:57
static bool isUndef(const MachineInstr &MI)
This file provides utility analysis objects describing memory locations.
MachineInstr unsigned OpIdx
uint64_t High
#define P(N)
const SmallVectorImpl< MachineOperand > & Cond
static Type * getValueType(Value *V, bool LookThroughCmp=false)
Returns the "element type" of the given value/instruction V.
This file implements the SmallBitVector class.
#define LLVM_DEBUG(...)
Definition Debug.h:119
Value * RHS
Value * LHS
This is an SDNode representing atomic operations.
LLVM_ABI unsigned getVScaleRangeMin() const
Returns the minimum value for the vscale_range attribute.
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition Attributes.h:261
static constexpr ElementCount getScalable(ScalarTy MinVal)
Definition TypeSize.h:312
static constexpr ElementCount get(ScalarTy MinVal, bool Scalable)
Definition TypeSize.h:315
This class is used to represent ISD::LOAD nodes.
static constexpr LocationSize beforeOrAfterPointer()
Any location before or after the base pointer (but still within the underlying object).
static auto integer_valuetypes()
static auto vector_valuetypes()
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
Flags
Flags values. These may be or'd together.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
This class is used to represent an MGATHER node.
const SDValue & getBasePtr() const
ISD::MemIndexType getIndexType() const
How is Index applied to BasePtr when computing addresses.
const SDValue & getInc() const
const SDValue & getScale() const
const SDValue & getMask() const
const SDValue & getIntID() const
const SDValue & getIndex() const
const SDValue & getBasePtr() const
ISD::MemIndexType getIndexType() const
This class is used to represent an MLOAD node.
const SDValue & getBasePtr() const
ISD::LoadExtType getExtensionType() const
const SDValue & getMask() const
const SDValue & getPassThru() const
const SDValue & getOffset() const
bool isUnindexed() const
Return true if this is NOT a pre/post inc/dec load/store.
ISD::MemIndexedMode getAddressingMode() const
Return the addressing mode for this load or store: unindexed, pre-inc, pre-dec, post-inc,...
const SDValue & getValue() const
bool isTruncatingStore() const
Return true if the op does a truncation before store.
This class is used to represent an MSTORE node.
bool isCompressingStore() const
Returns true if the op does a compression to the vector before storing.
const SDValue & getOffset() const
const SDValue & getBasePtr() const
const SDValue & getMask() const
const SDValue & getValue() const
This is an abstract virtual class for memory operations.
Align getBaseAlign() const
Returns alignment and volatility of the memory access.
const MDNode * getRanges() const
Returns the Ranges that describes the dereference.
AAMDNodes getAAInfo() const
Returns the AA info that describes the dereference.
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
bool isStrictFPOpcode()
Test if this node is a strict floating point pseudo-op.
const APInt & getAsAPIntVal() const
Helper method returns the APInt value of a ConstantSDNode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
SDNodeFlags getFlags() const
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
bool isUndef() const
SDNode * getNode() const
get the SDNode which holds the desired result
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
SDValue getExtractVectorElt(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Extract element at Idx from Vec.
SDValue getInsertVectorElt(const SDLoc &DL, SDValue Vec, SDValue Elt, unsigned Idx)
Insert Elt into Vec at offset Idx.
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getPOISON(EVT VT)
Return a POISON node. POISON does not have a useful SDLoc.
LLVMContext * getContext() const
size_type size() const
Determine the number of elements in the SetVector.
Definition SetVector.h:103
Vector takeVector()
Clear the SetVector and return the underlying vector.
Definition SetVector.h:94
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:151
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
pointer data()
Return a pointer to the vector's buffer, even if empty().
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
BooleanContent
Enum that describes how the target represents true/false values.
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
static ISD::NodeType getExtendForContent(BooleanContent Content)
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:343
ISD::MemIndexedMode getAddressingMode() const
Return the addressing mode for this load or store: unindexed, pre-inc, pre-dec, post-inc,...
bool isUnindexed() const
Return true if this is NOT a pre/post inc/dec load/store.
This class is used to represent an VP_GATHER node.
const SDValue & getScale() const
ISD::MemIndexType getIndexType() const
How is Index applied to BasePtr when computing addresses.
const SDValue & getVectorLength() const
const SDValue & getIndex() const
const SDValue & getBasePtr() const
const SDValue & getMask() const
This class is used to represent a VP_LOAD node.
const SDValue & getValue() const
This class is used to represent a VP_STORE node.
This class is used to represent an EXPERIMENTAL_VP_STRIDED_LOAD node.
const SDValue & getMask() const
ISD::LoadExtType getExtensionType() const
const SDValue & getStride() const
const SDValue & getOffset() const
const SDValue & getVectorLength() const
const SDValue & getBasePtr() const
This class is used to represent an EXPERIMENTAL_VP_STRIDED_STORE node.
const SDValue & getBasePtr() const
const SDValue & getMask() const
const SDValue & getValue() const
bool isTruncatingStore() const
Return true if this is a truncating store.
const SDValue & getOffset() const
const SDValue & getVectorLength() const
const SDValue & getStride() const
bool isCompressingStore() const
Returns true if the op does a compression to the vector before storing.
constexpr bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
Definition TypeSize.h:180
constexpr bool hasKnownScalarFactor(const FixedOrScalableQuantity &RHS) const
Returns true if there exists a value X where RHS.multiplyCoefficientBy(X) will result in a value whos...
Definition TypeSize.h:269
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:200
static constexpr bool isKnownLE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:230
constexpr bool isNonZero() const
Definition TypeSize.h:155
constexpr ScalarTy getKnownScalarFactor(const FixedOrScalableQuantity &RHS) const
Returns a value X where RHS.multiplyCoefficientBy(X) will result in a value whose quantity matches ou...
Definition TypeSize.h:277
static constexpr bool isKnownLT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:216
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:168
constexpr bool isKnownEven() const
A return value of true indicates we know at compile time that the number of elements (vscale * Min) i...
Definition TypeSize.h:176
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:165
static constexpr bool isKnownGT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:223
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
Definition TypeSize.h:252
static constexpr bool isKnownGE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:237
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
Definition ISDOpcodes.h:41
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
Definition ISDOpcodes.h:823
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
Definition ISDOpcodes.h:261
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
Definition ISDOpcodes.h:511
@ POISON
POISON - A poison node.
Definition ISDOpcodes.h:236
@ PARTIAL_REDUCE_SMLA
PARTIAL_REDUCE_[U|S]MLA(Accumulator, Input1, Input2) The partial reduction nodes sign or zero extend ...
@ LOOP_DEPENDENCE_RAW_MASK
@ VECREDUCE_SEQ_FADD
Generic reduction nodes.
@ MLOAD
Masked load and store - consecutive vector load and store operations with additional mask operand tha...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
Definition ISDOpcodes.h:600
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:783
@ SMULFIX
RESULT = [US]MULFIX(LHS, RHS, SCALE) - Perform fixed point multiplication on 2 integers with the same...
Definition ISDOpcodes.h:394
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:264
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ SMULFIXSAT
Same as the corresponding unsaturated fixed point instructions, but the result is clamped between the...
Definition ISDOpcodes.h:400
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition ISDOpcodes.h:857
@ CTTZ_ELTS
Returns the number of number of trailing (least significant) zero elements in a vector.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
Definition ISDOpcodes.h:518
@ VECTOR_FIND_LAST_ACTIVE
Finds the index of the last active mask element Operands: Mask.
@ FMODF
FMODF - Decomposes the operand into integral and fractional parts, each having the same type and sign...
@ FATAN2
FATAN2 - atan2, inspired by libm.
@ FSINCOSPI
FSINCOSPI - Compute both the sine and cosine times pi more accurately than FSINCOS(pi*x),...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Definition ISDOpcodes.h:884
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
Definition ISDOpcodes.h:584
@ VECREDUCE_FMAX
FMIN/FMAX nodes can have flags, for NaN/NoNaN variants.
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:417
@ VECREDUCE_FMAXIMUM
FMINIMUM/FMAXIMUM nodes propatate NaNs and signed zeroes using the llvm.minimum and llvm....
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
Definition ISDOpcodes.h:747
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
Definition ISDOpcodes.h:914
@ FPTRUNC_ROUND
FPTRUNC_ROUND - This corresponds to the fptrunc_round intrinsic.
Definition ISDOpcodes.h:515
@ FAKE_USE
FAKE_USE represents a use of the operand but does not do anything.
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
Definition ISDOpcodes.h:997
@ CLMUL
Carry-less multiplication operations.
Definition ISDOpcodes.h:778
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ SDIVFIX
RESULT = [US]DIVFIX(LHS, RHS, SCALE) - Perform fixed point division on 2 integers with the same width...
Definition ISDOpcodes.h:407
@ CONVERT_FROM_ARBITRARY_FP
CONVERT_FROM_ARBITRARY_FP - This operator converts from an arbitrary floating-point represented as an...
@ CTLZ_ZERO_POISON
Definition ISDOpcodes.h:792
@ PARTIAL_REDUCE_UMLA
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:848
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
Definition ISDOpcodes.h:715
@ STRICT_UINT_TO_FP
Definition ISDOpcodes.h:485
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
Definition ISDOpcodes.h:665
@ VECREDUCE_FADD
These reductions have relaxed evaluation order semantics, and have a single vector operand.
@ PARTIAL_REDUCE_FMLA
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ SSUBO
Same for subtraction.
Definition ISDOpcodes.h:352
@ VECTOR_INTERLEAVE
VECTOR_INTERLEAVE(VEC1, VEC2, ...) - Returns N vectors from N input vectors, where N is the factor to...
Definition ISDOpcodes.h:635
@ STEP_VECTOR
STEP_VECTOR(IMM) - Returns a scalable vector whose lanes are comprised of a linear sequence of unsign...
Definition ISDOpcodes.h:691
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
Definition ISDOpcodes.h:541
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
Definition ISDOpcodes.h:548
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
Definition ISDOpcodes.h:374
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:800
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
Definition ISDOpcodes.h:233
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
Definition ISDOpcodes.h:672
@ GET_ACTIVE_LANE_MASK
GET_ACTIVE_LANE_MASK - this corrosponds to the llvm.get.active.lane.mask intrinsic.
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
Definition ISDOpcodes.h:348
@ ARITH_FENCE
ARITH_FENCE - This corresponds to a arithmetic fence intrinsic.
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition ISDOpcodes.h:704
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:769
@ AssertNoFPClass
AssertNoFPClass - These nodes record if a register contains a float value that is known to be not som...
Definition ISDOpcodes.h:78
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition ISDOpcodes.h:649
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition ISDOpcodes.h:614
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimumNumber or maximumNumber on two values,...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:576
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:854
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:815
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ SSHLSAT
RESULT = [US]SHLSAT(LHS, RHS) - Perform saturation left shift.
Definition ISDOpcodes.h:386
@ SMULO
Same for multiplication.
Definition ISDOpcodes.h:356
@ VECTOR_SPLICE_LEFT
VECTOR_SPLICE_LEFT(VEC1, VEC2, OFFSET) - Shifts CONCAT_VECTORS(VEC1, VEC2) left by OFFSET elements an...
Definition ISDOpcodes.h:653
@ ANY_EXTEND_VECTOR_INREG
ANY_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register any-extension of the low la...
Definition ISDOpcodes.h:903
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition ISDOpcodes.h:892
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:727
@ MASKED_UDIV
Masked vector arithmetic that returns poison on disabled lanes.
@ VECTOR_REVERSE
VECTOR_REVERSE(VECTOR) - Returns a vector, of the same type as VECTOR, whose elements are shuffled us...
Definition ISDOpcodes.h:640
@ SDIVFIXSAT
Same as the corresponding unsaturated fixed point instructions, but the result is clamped between the...
Definition ISDOpcodes.h:413
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:982
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition ISDOpcodes.h:809
@ STRICT_SINT_TO_FP
STRICT_[US]INT_TO_FP - Convert a signed or unsigned integer to a floating point value.
Definition ISDOpcodes.h:484
@ MGATHER
Masked gather and scatter - load and store operations for a vector of random addresses with additiona...
@ STRICT_FP_TO_UINT
Definition ISDOpcodes.h:478
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
Definition ISDOpcodes.h:500
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:477
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:930
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:505
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:739
@ SCMP
[US]CMP - 3-way comparison of signed or unsigned integers.
Definition ISDOpcodes.h:735
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
Definition ISDOpcodes.h:710
@ VECTOR_SPLICE_RIGHT
VECTOR_SPLICE_RIGHT(VEC1, VEC2, OFFSET) - Shifts CONCAT_VECTORS(VEC1,VEC2) right by OFFSET elements a...
Definition ISDOpcodes.h:657
@ FREEZE
FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or is evaluated to UNDEF),...
Definition ISDOpcodes.h:241
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
Definition ISDOpcodes.h:565
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition ISDOpcodes.h:53
@ CTTZ_ZERO_POISON
Bit counting operators with a poisoned result for zero inputs.
Definition ISDOpcodes.h:791
@ FFREXP
FFREXP - frexp, extract fractional and exponent component of a floating-point value.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
Definition ISDOpcodes.h:963
@ VECTOR_COMPRESS
VECTOR_COMPRESS(Vec, Mask, Passthru) consecutively place vector elements based on mask e....
Definition ISDOpcodes.h:699
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
Definition ISDOpcodes.h:925
@ ADDRSPACECAST
ADDRSPACECAST - This operator converts between pointers of different address spaces.
@ EXPERIMENTAL_VECTOR_HISTOGRAM
Experimental vector histogram intrinsic Operands: Input Chain, Inc, Mask, Base, Index,...
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
Definition ISDOpcodes.h:949
@ VECREDUCE_FMINIMUM
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:860
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ VECREDUCE_SEQ_FMUL
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
Definition ISDOpcodes.h:62
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
Definition ISDOpcodes.h:534
@ PARTIAL_REDUCE_SUMLA
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
Definition ISDOpcodes.h:365
@ VECTOR_DEINTERLEAVE
VECTOR_DEINTERLEAVE(VEC1, VEC2, ...) - Returns N vectors from N input vectors, where N is the factor ...
Definition ISDOpcodes.h:624
@ CTTZ_ELTS_ZERO_POISON
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - minimumnum/maximumnum that is same with FMINNUM_IEEE and FMAXNUM_IEEE besid...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
Definition ISDOpcodes.h:722
@ ABS_MIN_POISON
ABS with a poison result for INT_MIN.
Definition ISDOpcodes.h:751
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition ISDOpcodes.h:556
@ LOOP_DEPENDENCE_WAR_MASK
The llvm.loop.dependence.
LLVM_ABI bool isBuildVectorOfConstantSDNodes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR node of all ConstantSDNode or undef.
LLVM_ABI NodeType getUnmaskedBinOpOpcode(unsigned MaskedOpc)
Given a MaskedOpc of ISD::MASKED_(U|S)(DIV|REM), returns the unmasked ISD::(U|S)(DIV|REM).
bool isUNINDEXEDLoad(const SDNode *N)
Returns true if the specified node is an unindexed load.
LLVM_ABI std::optional< unsigned > getVPForBaseOpcode(unsigned Opcode)
Translate this non-VP Opcode to its corresponding VP Opcode.
MemIndexType
MemIndexType enum - This enum defines how to interpret MGATHER/SCATTER's index parameter when calcula...
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
LLVM_ABI NodeType getVecReduceBaseOpcode(unsigned VecReduceOpcode)
Get underlying scalar opcode for VECREDUCE opcode.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
LLVM_ABI LegalityPredicate isVector(unsigned TypeIdx)
True iff the specified type index is a vector.
constexpr double e
Context & getContext() const
Definition BasicBlock.h:99
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:558
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1764
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:284
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:279
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr int PoisonMaskElem
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:221
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
Definition STLExtras.h:1884
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1771
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1946
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Definition Alignment.h:201
LLVM_ABI void processShuffleMasks(ArrayRef< int > Mask, unsigned NumOfSrcRegs, unsigned NumOfDestRegs, unsigned NumOfUsedRegs, function_ref< void()> NoInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned)> SingleInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned, bool)> ManyInputsAction)
Splits and processes shuffle mask depending on the number of input and output registers.
@ Increment
Incrementally increasing token ID.
Definition AllocToken.h:26
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:876
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77
Extended Value Type.
Definition ValueTypes.h:35
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
Definition ValueTypes.h:90
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
Definition ValueTypes.h:418
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
Definition ValueTypes.h:70
EVT changeTypeToInteger() const
Return the type converted to an equivalently sized integer or vector with integer element type.
Definition ValueTypes.h:129
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
Definition ValueTypes.h:307
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
Definition ValueTypes.h:155
ElementCount getVectorElementCount() const
Definition ValueTypes.h:373
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
Definition ValueTypes.h:494
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:396
bool isByteSized() const
Return true if the bit size is a multiple of 8.
Definition ValueTypes.h:266
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
Definition ValueTypes.h:382
uint64_t getScalarSizeInBits() const
Definition ValueTypes.h:408
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
Definition ValueTypes.h:501
EVT changeVectorElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
Definition ValueTypes.h:98
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
Definition ValueTypes.h:61
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
Definition ValueTypes.h:404
EVT widenIntegerVectorElementType(LLVMContext &Context) const
Return a VT for an integer vector type with the size of the elements doubled.
Definition ValueTypes.h:475
bool isFixedLengthVector() const
Definition ValueTypes.h:199
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
Definition ValueTypes.h:55
EVT getRoundIntegerType(LLVMContext &Context) const
Rounds the bit-width of the given integer EVT up to the nearest power of two (and at least to eight),...
Definition ValueTypes.h:442
bool isVector() const
Return true if this is a vector value type.
Definition ValueTypes.h:176
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
Definition ValueTypes.h:346
bool bitsEq(EVT VT) const
Return true if this has the same number of bits as VT.
Definition ValueTypes.h:279
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
Definition ValueTypes.h:187
bool knownBitsGE(EVT VT) const
Return true if we know at compile time this has more than or the same bits as VT.
Definition ValueTypes.h:291
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition ValueTypes.h:351
EVT changeElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a type whose attributes match ourselves with the exception of the element type that i...
Definition ValueTypes.h:121
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Definition ValueTypes.h:359
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
Definition ValueTypes.h:484
bool isInteger() const
Return true if this is an integer or a vector integer type.
Definition ValueTypes.h:160
This class contains a discriminated union of information about pointers in memory operands,...
LLVM_ABI unsigned getAddrSpace() const
Return the LLVM IR address space number that this pointer points into.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getUnknownStack(MachineFunction &MF)
Stack memory without other information.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.