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