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