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