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