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