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