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