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