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