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