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