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