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