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
5668 if (TLI.isTypeLegal(InWidenVT)) {
5669 // Because the result and the input are different vector types, widening
5670 // the result could create a legal type but widening the input might make
5671 // it an illegal type that might lead to repeatedly splitting the input
5672 // and then widening it. To avoid this, we widen the input only if
5673 // it results in a legal type.
5674 if (WidenEC.isKnownMultipleOf(InVTEC.getKnownMinValue())) {
5675 // Widen the input and call convert on the widened input vector.
5676 unsigned NumConcat =
5677 WidenEC.getKnownMinValue() / InVTEC.getKnownMinValue();
5678 SmallVector<SDValue, 16> Ops(NumConcat, DAG.getPOISON(InVT));
5679 Ops[0] = InOp;
5680 SDValue InVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InWidenVT, Ops);
5681 if (N->getNumOperands() == 1)
5682 return DAG.getNode(Opcode, DL, WidenVT, InVec, Flags);
5683 return DAG.getNode(Opcode, DL, WidenVT, InVec, N->getOperand(1), Flags);
5684 }
5685
5686 if (InVTEC.isKnownMultipleOf(WidenEC.getKnownMinValue())) {
5687 SDValue InVal = DAG.getExtractSubvector(DL, InWidenVT, InOp, 0);
5688 // Extract the input and convert the shorten input vector.
5689 if (N->getNumOperands() == 1)
5690 return DAG.getNode(Opcode, DL, WidenVT, InVal, Flags);
5691 return DAG.getNode(Opcode, DL, WidenVT, InVal, N->getOperand(1), Flags);
5692 }
5693 }
5694
5695 // Otherwise unroll into some nasty scalar code and rebuild the vector.
5696 EVT EltVT = WidenVT.getVectorElementType();
5697 SmallVector<SDValue, 16> Ops(WidenEC.getFixedValue(), DAG.getPOISON(EltVT));
5698 // Use the original element count so we don't do more scalar opts than
5699 // necessary.
5700 unsigned MinElts = N->getValueType(0).getVectorNumElements();
5701 for (unsigned i=0; i < MinElts; ++i) {
5702 SDValue Val = DAG.getExtractVectorElt(DL, InEltVT, InOp, i);
5703 if (N->getNumOperands() == 1)
5704 Ops[i] = DAG.getNode(Opcode, DL, EltVT, Val, Flags);
5705 else
5706 Ops[i] = DAG.getNode(Opcode, DL, EltVT, Val, N->getOperand(1), Flags);
5707 }
5708
5709 return DAG.getBuildVector(WidenVT, DL, Ops);
5710}
5711
5712SDValue DAGTypeLegalizer::WidenVecRes_FP_TO_XINT_SAT(SDNode *N) {
5713 SDLoc dl(N);
5714 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5715 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
5716
5717 SDValue Src = N->getOperand(0);
5718 EVT SrcVT = Src.getValueType();
5719
5720 // Also widen the input.
5721 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
5722 Src = GetWidenedVector(Src);
5723 SrcVT = Src.getValueType();
5724 }
5725
5726 // Input and output not widened to the same size, give up.
5727 if (WidenNumElts != SrcVT.getVectorElementCount())
5728 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
5729
5730 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src, N->getOperand(1));
5731}
5732
5733SDValue DAGTypeLegalizer::WidenVecRes_XROUND(SDNode *N) {
5734 SDLoc dl(N);
5735 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5736 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
5737
5738 SDValue Src = N->getOperand(0);
5739 EVT SrcVT = Src.getValueType();
5740
5741 // Also widen the input.
5742 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
5743 Src = GetWidenedVector(Src);
5744 SrcVT = Src.getValueType();
5745 }
5746
5747 // Input and output not widened to the same size, give up.
5748 if (WidenNumElts != SrcVT.getVectorElementCount())
5749 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
5750
5751 if (N->getNumOperands() == 1)
5752 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src);
5753
5754 assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
5755 assert(N->isVPOpcode() && "Expected VP opcode");
5756
5757 SDValue Mask =
5758 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
5759 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src, Mask, N->getOperand(2));
5760}
5761
5762SDValue DAGTypeLegalizer::WidenVecRes_Convert_StrictFP(SDNode *N) {
5763 SDValue InOp = N->getOperand(1);
5764 SDLoc DL(N);
5765 SmallVector<SDValue, 4> NewOps(N->ops());
5766
5767 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5768 unsigned WidenNumElts = WidenVT.getVectorNumElements();
5769
5770 EVT InVT = InOp.getValueType();
5771 EVT InEltVT = InVT.getVectorElementType();
5772
5773 unsigned Opcode = N->getOpcode();
5774
5775 // FIXME: Optimizations need to be implemented here.
5776
5777 // Otherwise unroll into some nasty scalar code and rebuild the vector.
5778 EVT EltVT = WidenVT.getVectorElementType();
5779 std::array<EVT, 2> EltVTs = {{EltVT, MVT::Other}};
5780 SmallVector<SDValue, 16> Ops(WidenNumElts, DAG.getPOISON(EltVT));
5781 SmallVector<SDValue, 32> OpChains;
5782 // Use the original element count so we don't do more scalar opts than
5783 // necessary.
5784 unsigned MinElts = N->getValueType(0).getVectorNumElements();
5785 for (unsigned i=0; i < MinElts; ++i) {
5786 NewOps[1] = DAG.getExtractVectorElt(DL, InEltVT, InOp, i);
5787 Ops[i] = DAG.getNode(Opcode, DL, EltVTs, NewOps);
5788 OpChains.push_back(Ops[i].getValue(1));
5789 }
5790 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OpChains);
5791 ReplaceValueWith(SDValue(N, 1), NewChain);
5792
5793 return DAG.getBuildVector(WidenVT, DL, Ops);
5794}
5795
5796SDValue DAGTypeLegalizer::WidenVecRes_EXTEND_VECTOR_INREG(SDNode *N) {
5797 unsigned Opcode = N->getOpcode();
5798 SDValue InOp = N->getOperand(0);
5799 SDLoc DL(N);
5800
5801 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5802 EVT WidenSVT = WidenVT.getVectorElementType();
5803 unsigned WidenNumElts = WidenVT.getVectorNumElements();
5804
5805 EVT InVT = InOp.getValueType();
5806 EVT InSVT = InVT.getVectorElementType();
5807 unsigned InVTNumElts = InVT.getVectorNumElements();
5808
5809 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
5810 InOp = GetWidenedVector(InOp);
5811 InVT = InOp.getValueType();
5812 if (InVT.getSizeInBits() == WidenVT.getSizeInBits()) {
5813 switch (Opcode) {
5817 return DAG.getNode(Opcode, DL, WidenVT, InOp);
5818 }
5819 }
5820 }
5821
5822 // Unroll, extend the scalars and rebuild the vector.
5824 for (unsigned i = 0, e = std::min(InVTNumElts, WidenNumElts); i != e; ++i) {
5825 SDValue Val = DAG.getExtractVectorElt(DL, InSVT, InOp, i);
5826 switch (Opcode) {
5828 Val = DAG.getNode(ISD::ANY_EXTEND, DL, WidenSVT, Val);
5829 break;
5831 Val = DAG.getNode(ISD::SIGN_EXTEND, DL, WidenSVT, Val);
5832 break;
5834 Val = DAG.getNode(ISD::ZERO_EXTEND, DL, WidenSVT, Val);
5835 break;
5836 default:
5837 llvm_unreachable("A *_EXTEND_VECTOR_INREG node was expected");
5838 }
5839 Ops.push_back(Val);
5840 }
5841
5842 while (Ops.size() != WidenNumElts)
5843 Ops.push_back(DAG.getPOISON(WidenSVT));
5844
5845 return DAG.getBuildVector(WidenVT, DL, Ops);
5846}
5847
5848SDValue DAGTypeLegalizer::WidenVecRes_FCOPYSIGN(SDNode *N) {
5849 // If this is an FCOPYSIGN with same input types, we can treat it as a
5850 // normal (can trap) binary op.
5851 if (N->getOperand(0).getValueType() == N->getOperand(1).getValueType())
5852 return WidenVecRes_BinaryCanTrap(N);
5853
5854 // If the types are different, fall back to unrolling.
5855 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5856 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
5857}
5858
5859/// Result and first source operand are different scalar types, but must have
5860/// the same number of elements. There is an additional control argument which
5861/// should be passed through unchanged.
5862SDValue DAGTypeLegalizer::WidenVecRes_UnarySameEltsWithScalarArg(SDNode *N) {
5863 SDValue FpValue = N->getOperand(0);
5864 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5865 if (getTypeAction(FpValue.getValueType()) != TargetLowering::TypeWidenVector)
5866 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
5867 SDValue Arg = GetWidenedVector(FpValue);
5868 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, {Arg, N->getOperand(1)},
5869 N->getFlags());
5870}
5871
5872SDValue DAGTypeLegalizer::WidenVecRes_ExpOp(SDNode *N) {
5873 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5874 SDValue InOp = GetWidenedVector(N->getOperand(0));
5875 SDValue RHS = N->getOperand(1);
5876 EVT ExpVT = RHS.getValueType();
5877 SDValue ExpOp = RHS;
5878 if (ExpVT.isVector()) {
5879 EVT WideExpVT =
5881 ExpOp = ModifyToType(RHS, WideExpVT);
5882 }
5883
5884 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, ExpOp);
5885}
5886
5887SDValue DAGTypeLegalizer::WidenVecRes_Unary(SDNode *N) {
5888 // Unary op widening.
5889 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5890 SDValue InOp = GetWidenedVector(N->getOperand(0));
5891 if (N->getNumOperands() == 1)
5892 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, N->getFlags());
5893 if (N->getOpcode() == ISD::AssertNoFPClass)
5894 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp,
5895 N->getOperand(1), N->getFlags());
5896
5897 assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
5898 assert(N->isVPOpcode() && "Expected VP opcode");
5899
5900 SDValue Mask =
5901 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
5902 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT,
5903 {InOp, Mask, N->getOperand(2)});
5904}
5905
5906SDValue DAGTypeLegalizer::WidenVecRes_InregOp(SDNode *N) {
5907 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5908 EVT ExtVT = EVT::getVectorVT(*DAG.getContext(),
5909 cast<VTSDNode>(N->getOperand(1))->getVT()
5910 .getVectorElementType(),
5911 WidenVT.getVectorNumElements());
5912 SDValue WidenLHS = GetWidenedVector(N->getOperand(0));
5913 return DAG.getNode(N->getOpcode(), SDLoc(N),
5914 WidenVT, WidenLHS, DAG.getValueType(ExtVT));
5915}
5916
5917SDValue DAGTypeLegalizer::WidenVecRes_UnaryOpWithTwoResults(SDNode *N,
5918 unsigned ResNo) {
5919 EVT VT0 = N->getValueType(0);
5920 EVT VT1 = N->getValueType(1);
5921
5922 assert(VT0.isVector() && VT1.isVector() &&
5924 "expected both results to be vectors of matching element count");
5925
5926 LLVMContext &Ctx = *DAG.getContext();
5927 SDValue InOp = GetWidenedVector(N->getOperand(0));
5928
5929 EVT WidenVT = TLI.getTypeToTransformTo(Ctx, N->getValueType(ResNo));
5930 ElementCount WidenEC = WidenVT.getVectorElementCount();
5931
5932 EVT WidenVT0 = EVT::getVectorVT(Ctx, VT0.getVectorElementType(), WidenEC);
5933 EVT WidenVT1 = EVT::getVectorVT(Ctx, VT1.getVectorElementType(), WidenEC);
5934
5935 SDNode *WidenNode =
5936 DAG.getNode(N->getOpcode(), SDLoc(N), {WidenVT0, WidenVT1}, InOp)
5937 .getNode();
5938
5939 ReplaceOtherWidenResults(N, WidenNode, ResNo);
5940 return SDValue(WidenNode, ResNo);
5941}
5942
5943SDValue DAGTypeLegalizer::WidenVecRes_MERGE_VALUES(SDNode *N, unsigned ResNo) {
5944 SDValue WidenVec = DisintegrateMERGE_VALUES(N, ResNo);
5945 return GetWidenedVector(WidenVec);
5946}
5947
5948SDValue DAGTypeLegalizer::WidenVecRes_ADDRSPACECAST(SDNode *N) {
5949 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5950 SDValue InOp = GetWidenedVector(N->getOperand(0));
5951 auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
5952
5953 return DAG.getAddrSpaceCast(SDLoc(N), WidenVT, InOp,
5954 AddrSpaceCastN->getSrcAddressSpace(),
5955 AddrSpaceCastN->getDestAddressSpace());
5956}
5957
5958SDValue DAGTypeLegalizer::WidenVecRes_BITCAST(SDNode *N) {
5959 SDValue InOp = N->getOperand(0);
5960 EVT InVT = InOp.getValueType();
5961 EVT VT = N->getValueType(0);
5962 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
5963 SDLoc dl(N);
5964
5965 switch (getTypeAction(InVT)) {
5967 break;
5969 report_fatal_error("Scalarization of scalable vectors is not supported.");
5971 // If the incoming type is a vector that is being promoted, then
5972 // we know that the elements are arranged differently and that we
5973 // must perform the conversion using a stack slot.
5974 if (InVT.isVector())
5975 break;
5976
5977 // If the InOp is promoted to the same size, convert it. Otherwise,
5978 // fall out of the switch and widen the promoted input.
5979 SDValue NInOp = GetPromotedInteger(InOp);
5980 EVT NInVT = NInOp.getValueType();
5981 if (WidenVT.bitsEq(NInVT)) {
5982 // For big endian targets we need to shift the input integer or the
5983 // interesting bits will end up at the wrong place.
5984 if (DAG.getDataLayout().isBigEndian()) {
5985 unsigned ShiftAmt = NInVT.getSizeInBits() - InVT.getSizeInBits();
5986 NInOp = DAG.getNode(ISD::SHL, dl, NInVT, NInOp,
5987 DAG.getShiftAmountConstant(ShiftAmt, NInVT, dl));
5988 }
5989 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NInOp);
5990 }
5991 InOp = NInOp;
5992 InVT = NInVT;
5993 break;
5994 }
6002 break;
6004 // If the InOp is widened to the same size, convert it. Otherwise, fall
6005 // out of the switch and widen the widened input.
6006 InOp = GetWidenedVector(InOp);
6007 InVT = InOp.getValueType();
6008 if (WidenVT.bitsEq(InVT))
6009 // The input widens to the same size. Convert to the widen value.
6010 return DAG.getNode(ISD::BITCAST, dl, WidenVT, InOp);
6011 break;
6012 }
6013
6014 unsigned WidenSize = WidenVT.getSizeInBits();
6015 unsigned InSize = InVT.getSizeInBits();
6016 unsigned InScalarSize = InVT.getScalarSizeInBits();
6017 // x86mmx is not an acceptable vector element type, so don't try.
6018 if (WidenSize % InScalarSize == 0 && InVT != MVT::x86mmx) {
6019 // Determine new input vector type. The new input vector type will use
6020 // the same element type (if its a vector) or use the input type as a
6021 // vector. It is the same size as the type to widen to.
6022 EVT NewInVT;
6023 unsigned NewNumParts = WidenSize / InSize;
6024 if (InVT.isVector()) {
6025 EVT InEltVT = InVT.getVectorElementType();
6026 NewInVT = EVT::getVectorVT(*DAG.getContext(), InEltVT,
6027 WidenSize / InEltVT.getSizeInBits());
6028 } else {
6029 // For big endian systems, using the promoted input scalar type
6030 // to produce the scalar_to_vector would put the desired bits into
6031 // the least significant byte(s) of the wider element zero. This
6032 // will mean that the users of the result vector are using incorrect
6033 // bits. Use the original input type instead. Although either input
6034 // type can be used on little endian systems, for consistency we
6035 // use the original type there as well.
6036 EVT OrigInVT = N->getOperand(0).getValueType();
6037 NewNumParts = WidenSize / OrigInVT.getSizeInBits();
6038 NewInVT = EVT::getVectorVT(*DAG.getContext(), OrigInVT, NewNumParts);
6039 }
6040
6041 if (TLI.isTypeLegal(NewInVT)) {
6042 SDValue NewVec;
6043 if (InVT.isVector()) {
6044 // Because the result and the input are different vector types, widening
6045 // the result could create a legal type but widening the input might
6046 // make it an illegal type that might lead to repeatedly splitting the
6047 // input and then widening it. To avoid this, we widen the input only if
6048 // it results in a legal type.
6049 if (WidenSize % InSize == 0) {
6050 SmallVector<SDValue, 16> Ops(NewNumParts, DAG.getPOISON(InVT));
6051 Ops[0] = InOp;
6052
6053 NewVec = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewInVT, Ops);
6054 } else {
6056 DAG.ExtractVectorElements(InOp, Ops);
6057 Ops.append(WidenSize / InScalarSize - Ops.size(),
6058 DAG.getPOISON(InVT.getVectorElementType()));
6059
6060 NewVec = DAG.getNode(ISD::BUILD_VECTOR, dl, NewInVT, Ops);
6061 }
6062 } else {
6063 NewVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewInVT, InOp);
6064 }
6065 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NewVec);
6066 }
6067 }
6068
6069 return CreateStackStoreLoad(InOp, WidenVT);
6070}
6071
6072SDValue DAGTypeLegalizer::WidenVecRes_LOOP_DEPENDENCE_MASK(SDNode *N) {
6073 return DAG.getNode(
6074 N->getOpcode(), SDLoc(N),
6075 TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)),
6076 N->getOperand(0), N->getOperand(1), N->getOperand(2), N->getOperand(3));
6077}
6078
6079SDValue DAGTypeLegalizer::WidenVecRes_BUILD_VECTOR(SDNode *N) {
6080 SDLoc dl(N);
6081 // Build a vector with poison for the new nodes.
6082 EVT VT = N->getValueType(0);
6083
6084 // Integer BUILD_VECTOR operands may be larger than the node's vector element
6085 // type. The POISONs need to have the same type as the existing operands.
6086 EVT EltVT = N->getOperand(0).getValueType();
6087 unsigned NumElts = VT.getVectorNumElements();
6088
6089 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6090 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6091
6092 SmallVector<SDValue, 16> NewOps(N->ops());
6093 assert(WidenNumElts >= NumElts && "Shrinking vector instead of widening!");
6094 NewOps.append(WidenNumElts - NumElts, DAG.getPOISON(EltVT));
6095
6096 return DAG.getBuildVector(WidenVT, dl, NewOps);
6097}
6098
6099SDValue DAGTypeLegalizer::WidenVecRes_CONCAT_VECTORS(SDNode *N) {
6100 EVT InVT = N->getOperand(0).getValueType();
6101 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6102 SDLoc dl(N);
6103 unsigned NumOperands = N->getNumOperands();
6104
6105 bool InputWidened = false; // Indicates we need to widen the input.
6106 if (getTypeAction(InVT) != TargetLowering::TypeWidenVector) {
6107 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6108 unsigned NumInElts = InVT.getVectorMinNumElements();
6109 if (WidenNumElts % NumInElts == 0) {
6110 // Add undef vectors to widen to correct length.
6111 unsigned NumConcat = WidenNumElts / NumInElts;
6112 SDValue UndefVal = DAG.getPOISON(InVT);
6113 SmallVector<SDValue, 16> Ops(NumConcat);
6114 for (unsigned i=0; i < NumOperands; ++i)
6115 Ops[i] = N->getOperand(i);
6116 for (unsigned i = NumOperands; i != NumConcat; ++i)
6117 Ops[i] = UndefVal;
6118 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Ops);
6119 }
6120 } else {
6121 InputWidened = true;
6122 if (WidenVT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
6123 // The inputs and the result are widen to the same value.
6124 unsigned i;
6125 for (i=1; i < NumOperands; ++i)
6126 if (!N->getOperand(i).isUndef())
6127 break;
6128
6129 if (i == NumOperands)
6130 // Everything but the first operand is an UNDEF so just return the
6131 // widened first operand.
6132 return GetWidenedVector(N->getOperand(0));
6133
6134 if (NumOperands == 2) {
6135 assert(!WidenVT.isScalableVector() &&
6136 "Cannot use vector shuffles to widen CONCAT_VECTOR result");
6137 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6138 unsigned NumInElts = InVT.getVectorNumElements();
6139
6140 // Replace concat of two operands with a shuffle.
6141 SmallVector<int, 16> MaskOps(WidenNumElts, -1);
6142 for (unsigned i = 0; i < NumInElts; ++i) {
6143 MaskOps[i] = i;
6144 MaskOps[i + NumInElts] = i + WidenNumElts;
6145 }
6146 return DAG.getVectorShuffle(WidenVT, dl,
6147 GetWidenedVector(N->getOperand(0)),
6148 GetWidenedVector(N->getOperand(1)),
6149 MaskOps);
6150 }
6151 }
6152 }
6153
6154 assert(!WidenVT.isScalableVector() &&
6155 "Cannot use build vectors to widen CONCAT_VECTOR result");
6156 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6157 unsigned NumInElts = InVT.getVectorNumElements();
6158
6159 // Fall back to use extracts and build vector.
6160 EVT EltVT = WidenVT.getVectorElementType();
6161 SmallVector<SDValue, 16> Ops(WidenNumElts);
6162 unsigned Idx = 0;
6163 for (unsigned i=0; i < NumOperands; ++i) {
6164 SDValue InOp = N->getOperand(i);
6165 if (InputWidened)
6166 InOp = GetWidenedVector(InOp);
6167 for (unsigned j = 0; j < NumInElts; ++j)
6168 Ops[Idx++] = DAG.getExtractVectorElt(dl, EltVT, InOp, j);
6169 }
6170 SDValue UndefVal = DAG.getPOISON(EltVT);
6171 for (; Idx < WidenNumElts; ++Idx)
6172 Ops[Idx] = UndefVal;
6173 return DAG.getBuildVector(WidenVT, dl, Ops);
6174}
6175
6176SDValue DAGTypeLegalizer::WidenVecRes_INSERT_SUBVECTOR(SDNode *N) {
6177 EVT VT = N->getValueType(0);
6178 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6179 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
6180 SDValue InOp2 = N->getOperand(1);
6181 SDValue Idx = N->getOperand(2);
6182 SDLoc dl(N);
6183 return DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WidenVT, InOp1, InOp2, Idx);
6184}
6185
6186SDValue DAGTypeLegalizer::WidenVecRes_EXTRACT_SUBVECTOR(SDNode *N) {
6187 EVT VT = N->getValueType(0);
6188 EVT EltVT = VT.getVectorElementType();
6189 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6190 SDValue InOp = N->getOperand(0);
6191 SDValue Idx = N->getOperand(1);
6192 SDLoc dl(N);
6193
6194 auto InOpTypeAction = getTypeAction(InOp.getValueType());
6195 if (InOpTypeAction == TargetLowering::TypeWidenVector)
6196 InOp = GetWidenedVector(InOp);
6197
6198 EVT InVT = InOp.getValueType();
6199
6200 // Check if we can just return the input vector after widening.
6201 uint64_t IdxVal = Idx->getAsZExtVal();
6202 if (IdxVal == 0 && InVT == WidenVT)
6203 return InOp;
6204
6205 // Check if we can extract from the vector.
6206 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6207 unsigned InNumElts = InVT.getVectorMinNumElements();
6208 unsigned VTNumElts = VT.getVectorMinNumElements();
6209 assert(IdxVal % VTNumElts == 0 &&
6210 "Expected Idx to be a multiple of subvector minimum vector length");
6211 if (IdxVal % WidenNumElts == 0 && IdxVal + WidenNumElts < InNumElts)
6212 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, WidenVT, InOp, Idx);
6213
6214 if (VT.isScalableVector()) {
6215 // Try to split the operation up into smaller extracts and concat the
6216 // results together, e.g.
6217 // nxv6i64 extract_subvector(nxv12i64, 6)
6218 // <->
6219 // nxv8i64 concat(
6220 // nxv2i64 extract_subvector(nxv16i64, 6)
6221 // nxv2i64 extract_subvector(nxv16i64, 8)
6222 // nxv2i64 extract_subvector(nxv16i64, 10)
6223 // undef)
6224 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
6225 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
6226 "down type's element count");
6227 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
6229 // Avoid recursion around e.g. nxv1i8.
6230 if (getTypeAction(PartVT) != TargetLowering::TypeWidenVector) {
6232 unsigned I = 0;
6233 for (; I < VTNumElts / GCD; ++I)
6234 Parts.push_back(
6235 DAG.getExtractSubvector(dl, PartVT, InOp, IdxVal + I * GCD));
6236 for (; I < WidenNumElts / GCD; ++I)
6237 Parts.push_back(DAG.getPOISON(PartVT));
6238
6239 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
6240 }
6241
6242 // Fallback to extracting through memory.
6243
6244 Align Alignment = DAG.getReducedAlign(InVT, /*UseABI=*/false);
6245 SDValue StackPtr = DAG.CreateStackTemporary(InVT.getStoreSize(), Alignment);
6246 MachineFunction &MF = DAG.getMachineFunction();
6247 int FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
6248 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
6249
6250 MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
6253 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
6256
6257 // Write out the input vector.
6258 SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, InOp, StackPtr, StoreMMO);
6259
6260 // Build a mask to match the length of the non-widened result.
6261 SDValue Mask =
6262 DAG.getMaskFromElementCount(dl, WidenVT, VT.getVectorElementCount());
6263
6264 // Read back the sub-vector setting the remaining lanes to poison.
6265 StackPtr = TLI.getVectorSubVecPointer(DAG, StackPtr, InVT, VT, Idx);
6266 return DAG.getMaskedLoad(
6267 WidenVT, dl, Ch, StackPtr, DAG.getUNDEF(StackPtr.getValueType()), Mask,
6268 DAG.getPOISON(WidenVT), VT, LoadMMO, ISD::UNINDEXED, ISD::NON_EXTLOAD);
6269 }
6270
6271 // We could try widening the input to the right length but for now, extract
6272 // the original elements, fill the rest with undefs and build a vector.
6273 SmallVector<SDValue, 16> Ops(WidenNumElts);
6274 unsigned i;
6275 for (i = 0; i < VTNumElts; ++i)
6276 Ops[i] = DAG.getExtractVectorElt(dl, EltVT, InOp, IdxVal + i);
6277
6278 SDValue UndefVal = DAG.getPOISON(EltVT);
6279 for (; i < WidenNumElts; ++i)
6280 Ops[i] = UndefVal;
6281 return DAG.getBuildVector(WidenVT, dl, Ops);
6282}
6283
6284SDValue DAGTypeLegalizer::WidenVecRes_AssertZext(SDNode *N) {
6285 SDValue InOp = ModifyToType(
6286 N->getOperand(0),
6287 TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)), true);
6288 return DAG.getNode(ISD::AssertZext, SDLoc(N), InOp.getValueType(), InOp,
6289 N->getOperand(1));
6290}
6291
6292SDValue DAGTypeLegalizer::WidenVecRes_INSERT_VECTOR_ELT(SDNode *N) {
6293 SDValue InOp = GetWidenedVector(N->getOperand(0));
6294 return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(N),
6295 InOp.getValueType(), InOp,
6296 N->getOperand(1), N->getOperand(2));
6297}
6298
6299SDValue DAGTypeLegalizer::WidenVecRes_LOAD(SDNode *N) {
6300 LoadSDNode *LD = cast<LoadSDNode>(N);
6301 ISD::LoadExtType ExtType = LD->getExtensionType();
6302
6303 // A vector must always be stored in memory as-is, i.e. without any padding
6304 // between the elements, since various code depend on it, e.g. in the
6305 // handling of a bitcast of a vector type to int, which may be done with a
6306 // vector store followed by an integer load. A vector that does not have
6307 // elements that are byte-sized must therefore be stored as an integer
6308 // built out of the extracted vector elements.
6309 if (!LD->getMemoryVT().isByteSized()) {
6310 SDValue Value, NewChain;
6311 std::tie(Value, NewChain) = TLI.scalarizeVectorLoad(LD, DAG);
6312 ReplaceValueWith(SDValue(LD, 0), Value);
6313 ReplaceValueWith(SDValue(LD, 1), NewChain);
6314 return SDValue();
6315 }
6316
6317 // Generate a vector-predicated load if it is custom/legal on the target. To
6318 // avoid possible recursion, only do this if the widened mask type is legal.
6319 // FIXME: Not all targets may support EVL in VP_LOAD. These will have been
6320 // removed from the IR by the ExpandVectorPredication pass but we're
6321 // reintroducing them here.
6322 EVT VT = LD->getValueType(0);
6323 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6324 EVT WideMaskVT = getSetCCResultType(WideVT);
6325
6326 if (ExtType == ISD::NON_EXTLOAD &&
6327 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WideVT) &&
6328 TLI.isTypeLegal(WideMaskVT)) {
6329 SDLoc DL(N);
6330 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
6331 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
6333 SDValue NewLoad =
6334 DAG.getLoadVP(LD->getAddressingMode(), ISD::NON_EXTLOAD, WideVT, DL,
6335 LD->getChain(), LD->getBasePtr(), LD->getOffset(), Mask,
6336 EVL, LD->getMemoryVT(), LD->getMemOperand());
6337
6338 // Modified the chain - switch anything that used the old chain to use
6339 // the new one.
6340 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6341
6342 return NewLoad;
6343 }
6344
6346 SmallVector<SDValue, 16> LdChain; // Chain for the series of load
6347 if (ExtType != ISD::NON_EXTLOAD)
6348 Result = GenWidenVectorExtLoads(LdChain, LD, ExtType);
6349 else
6350 Result = GenWidenVectorLoads(LdChain, LD);
6351
6352 if (Result) {
6353 // If we generate a single load, we can use that for the chain. Otherwise,
6354 // build a factor node to remember the multiple loads are independent and
6355 // chain to that.
6356 SDValue NewChain;
6357 if (LdChain.size() == 1)
6358 NewChain = LdChain[0];
6359 else
6360 NewChain = DAG.getNode(ISD::TokenFactor, SDLoc(LD), MVT::Other, LdChain);
6361
6362 // Modified the chain - switch anything that used the old chain to use
6363 // the new one.
6364 ReplaceValueWith(SDValue(N, 1), NewChain);
6365
6366 return Result;
6367 }
6368
6369 if (VT.isVector()) {
6370 // If all else fails replace the load with a wide masked load.
6371 SDLoc DL(N);
6372 SDValue Mask =
6373 DAG.getMaskFromElementCount(DL, WideVT, VT.getVectorElementCount());
6374
6375 SDValue NewLoad = DAG.getMaskedLoad(
6376 WideVT, DL, LD->getChain(), LD->getBasePtr(), LD->getOffset(), Mask,
6377 DAG.getPOISON(WideVT), LD->getMemoryVT(), LD->getMemOperand(),
6378 LD->getAddressingMode(), LD->getExtensionType());
6379
6380 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6381 return NewLoad;
6382 }
6383
6384 report_fatal_error("Unable to widen vector load");
6385}
6386
6387SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD(VPLoadSDNode *N) {
6388 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6389 SDValue Mask = N->getMask();
6390 SDValue EVL = N->getVectorLength();
6391 ISD::LoadExtType ExtType = N->getExtensionType();
6392 SDLoc dl(N);
6393
6394 // The mask should be widened as well
6395 assert(getTypeAction(Mask.getValueType()) ==
6397 "Unable to widen binary VP op");
6398 Mask = GetWidenedVector(Mask);
6399 assert(Mask.getValueType().getVectorElementCount() ==
6400 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
6401 .getVectorElementCount() &&
6402 "Unable to widen vector load");
6403
6404 SDValue Res =
6405 DAG.getLoadVP(N->getAddressingMode(), ExtType, WidenVT, dl, N->getChain(),
6406 N->getBasePtr(), N->getOffset(), Mask, EVL,
6407 N->getMemoryVT(), N->getMemOperand(), N->isExpandingLoad());
6408 // Legalize the chain result - switch anything that used the old chain to
6409 // use the new one.
6410 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6411 return Res;
6412}
6413
6414SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD_FF(VPLoadFFSDNode *N) {
6415 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6416 SDValue Mask = N->getMask();
6417 SDValue EVL = N->getVectorLength();
6418 SDLoc dl(N);
6419
6420 // The mask should be widened as well
6421 assert(getTypeAction(Mask.getValueType()) ==
6423 "Unable to widen binary VP op");
6424 Mask = GetWidenedVector(Mask);
6425 assert(Mask.getValueType().getVectorElementCount() ==
6426 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
6427 .getVectorElementCount() &&
6428 "Unable to widen vector load");
6429
6430 SDValue Res = DAG.getLoadFFVP(WidenVT, dl, N->getChain(), N->getBasePtr(),
6431 Mask, EVL, N->getMemOperand());
6432 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6433 ReplaceValueWith(SDValue(N, 2), Res.getValue(2));
6434 return Res;
6435}
6436
6437SDValue DAGTypeLegalizer::WidenVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode *N) {
6438 SDLoc DL(N);
6439
6440 // The mask should be widened as well
6441 SDValue Mask = N->getMask();
6442 assert(getTypeAction(Mask.getValueType()) ==
6444 "Unable to widen VP strided load");
6445 Mask = GetWidenedVector(Mask);
6446
6447 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6448 assert(Mask.getValueType().getVectorElementCount() ==
6449 WidenVT.getVectorElementCount() &&
6450 "Data and mask vectors should have the same number of elements");
6451
6452 SDValue Res = DAG.getStridedLoadVP(
6453 N->getAddressingMode(), N->getExtensionType(), WidenVT, DL, N->getChain(),
6454 N->getBasePtr(), N->getOffset(), N->getStride(), Mask,
6455 N->getVectorLength(), N->getMemoryVT(), N->getMemOperand(),
6456 N->isExpandingLoad());
6457
6458 // Legalize the chain result - switch anything that used the old chain to
6459 // use the new one.
6460 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6461 return Res;
6462}
6463
6464SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_COMPRESS(SDNode *N) {
6465 SDValue Vec = N->getOperand(0);
6466 SDValue Mask = N->getOperand(1);
6467 SDValue Passthru = N->getOperand(2);
6468 EVT WideVecVT =
6469 TLI.getTypeToTransformTo(*DAG.getContext(), Vec.getValueType());
6470 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
6471 Mask.getValueType().getVectorElementType(),
6472 WideVecVT.getVectorElementCount());
6473
6474 SDValue WideVec = ModifyToType(Vec, WideVecVT);
6475 SDValue WideMask = ModifyToType(Mask, WideMaskVT, /*FillWithZeroes=*/true);
6476 SDValue WidePassthru = ModifyToType(Passthru, WideVecVT);
6477 return DAG.getNode(ISD::VECTOR_COMPRESS, SDLoc(N), WideVecVT, WideVec,
6478 WideMask, WidePassthru);
6479}
6480
6481SDValue DAGTypeLegalizer::WidenVecRes_MLOAD(MaskedLoadSDNode *N) {
6482 EVT VT = N->getValueType(0);
6483 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6484 SDValue Mask = N->getMask();
6485 EVT MaskVT = Mask.getValueType();
6486 SDValue PassThru = GetWidenedVector(N->getPassThru());
6487 ISD::LoadExtType ExtType = N->getExtensionType();
6488 SDLoc dl(N);
6489
6490 EVT WideMaskVT =
6491 EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(),
6492 WidenVT.getVectorElementCount());
6493
6494 if (ExtType == ISD::NON_EXTLOAD &&
6495 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WidenVT) &&
6496 TLI.isTypeLegal(WideMaskVT) &&
6497 // If there is a passthru, we shouldn't use vp.load. However,
6498 // type legalizer will struggle on masked.load with
6499 // scalable vectors, so for scalable vectors, we still use vp.load
6500 // but manually merge the load result with the passthru using vp.select.
6501 (N->getPassThru()->isUndef() || VT.isScalableVector())) {
6502 Mask = DAG.getInsertSubvector(dl, DAG.getUNDEF(WideMaskVT), Mask, 0);
6503 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
6505 SDValue NewLoad =
6506 DAG.getLoadVP(N->getAddressingMode(), ISD::NON_EXTLOAD, WidenVT, dl,
6507 N->getChain(), N->getBasePtr(), N->getOffset(), Mask, EVL,
6508 N->getMemoryVT(), N->getMemOperand());
6509 SDValue NewVal = NewLoad;
6510
6511 // Manually merge with vp.select
6512 if (!N->getPassThru()->isUndef()) {
6513 assert(WidenVT.isScalableVector());
6514 NewVal =
6515 DAG.getNode(ISD::VP_SELECT, dl, WidenVT, Mask, NewVal, PassThru, EVL);
6516 }
6517
6518 // Modified the chain - switch anything that used the old chain to use
6519 // the new one.
6520 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6521
6522 return NewVal;
6523 }
6524
6525 // The mask should be widened as well
6526 Mask = ModifyToType(Mask, WideMaskVT, true);
6527
6528 SDValue Res = DAG.getMaskedLoad(
6529 WidenVT, dl, N->getChain(), N->getBasePtr(), N->getOffset(), Mask,
6530 PassThru, N->getMemoryVT(), N->getMemOperand(), N->getAddressingMode(),
6531 ExtType, N->isExpandingLoad());
6532 // Legalize the chain result - switch anything that used the old chain to
6533 // use the new one.
6534 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6535 return Res;
6536}
6537
6538SDValue DAGTypeLegalizer::WidenVecRes_MGATHER(MaskedGatherSDNode *N) {
6539
6540 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6541 SDValue Mask = N->getMask();
6542 EVT MaskVT = Mask.getValueType();
6543 SDValue PassThru = GetWidenedVector(N->getPassThru());
6544 SDValue Scale = N->getScale();
6545 unsigned NumElts = WideVT.getVectorNumElements();
6546 SDLoc dl(N);
6547
6548 // The mask should be widened as well
6549 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
6550 MaskVT.getVectorElementType(),
6551 WideVT.getVectorNumElements());
6552 Mask = ModifyToType(Mask, WideMaskVT, true);
6553
6554 // Widen the Index operand
6555 SDValue Index = N->getIndex();
6556 EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
6557 Index.getValueType().getScalarType(),
6558 NumElts);
6559 Index = ModifyToType(Index, WideIndexVT);
6560 SDValue Ops[] = { N->getChain(), PassThru, Mask, N->getBasePtr(), Index,
6561 Scale };
6562
6563 // Widen the MemoryType
6564 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
6565 N->getMemoryVT().getScalarType(), NumElts);
6566 SDValue Res = DAG.getMaskedGather(DAG.getVTList(WideVT, MVT::Other),
6567 WideMemVT, dl, Ops, N->getMemOperand(),
6568 N->getIndexType(), N->getExtensionType());
6569
6570 // Legalize the chain result - switch anything that used the old chain to
6571 // use the new one.
6572 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6573 return Res;
6574}
6575
6576SDValue DAGTypeLegalizer::WidenVecRes_VP_GATHER(VPGatherSDNode *N) {
6577 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6578 SDValue Mask = N->getMask();
6579 SDValue Scale = N->getScale();
6580 ElementCount WideEC = WideVT.getVectorElementCount();
6581 SDLoc dl(N);
6582
6583 SDValue Index = GetWidenedVector(N->getIndex());
6584 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
6585 N->getMemoryVT().getScalarType(), WideEC);
6586 Mask = GetWidenedMask(Mask, WideEC);
6587
6588 SDValue Ops[] = {N->getChain(), N->getBasePtr(), Index, Scale,
6589 Mask, N->getVectorLength()};
6590 SDValue Res = DAG.getGatherVP(DAG.getVTList(WideVT, MVT::Other), WideMemVT,
6591 dl, Ops, N->getMemOperand(), N->getIndexType());
6592
6593 // Legalize the chain result - switch anything that used the old chain to
6594 // use the new one.
6595 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6596 return Res;
6597}
6598
6599SDValue DAGTypeLegalizer::WidenVecRes_ScalarOp(SDNode *N) {
6600 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6601 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, N->getOperand(0));
6602}
6603
6604// Return true is this is a SETCC node or a strict version of it.
6605static inline bool isSETCCOp(unsigned Opcode) {
6606 switch (Opcode) {
6607 case ISD::SETCC:
6608 case ISD::STRICT_FSETCC:
6610 return true;
6611 }
6612 return false;
6613}
6614
6615// Return true if this is a node that could have two SETCCs as operands.
6616static inline bool isLogicalMaskOp(unsigned Opcode) {
6617 switch (Opcode) {
6618 case ISD::AND:
6619 case ISD::OR:
6620 case ISD::XOR:
6621 return true;
6622 }
6623 return false;
6624}
6625
6626// If N is a SETCC or a strict variant of it, return the type
6627// of the compare operands.
6629 unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
6630 return N->getOperand(OpNo).getValueType();
6631}
6632
6633// This is used just for the assert in convertMask(). Check that this either
6634// a SETCC or a previously handled SETCC by convertMask().
6635#ifndef NDEBUG
6636static inline bool isSETCCorConvertedSETCC(SDValue N) {
6637 if (N.getOpcode() == ISD::EXTRACT_SUBVECTOR)
6638 N = N.getOperand(0);
6639 else if (N.getOpcode() == ISD::CONCAT_VECTORS) {
6640 for (unsigned i = 1; i < N->getNumOperands(); ++i)
6641 if (!N->getOperand(i)->isUndef())
6642 return false;
6643 N = N.getOperand(0);
6644 }
6645
6646 if (N.getOpcode() == ISD::TRUNCATE)
6647 N = N.getOperand(0);
6648 else if (N.getOpcode() == ISD::SIGN_EXTEND)
6649 N = N.getOperand(0);
6650
6651 if (isLogicalMaskOp(N.getOpcode()))
6652 return isSETCCorConvertedSETCC(N.getOperand(0)) &&
6653 isSETCCorConvertedSETCC(N.getOperand(1));
6654
6655 return (isSETCCOp(N.getOpcode()) ||
6657}
6658#endif
6659
6660// Return a mask of vector type MaskVT to replace InMask. Also adjust MaskVT
6661// to ToMaskVT if needed with vector extension or truncation.
6662SDValue DAGTypeLegalizer::convertMask(SDValue InMask, EVT MaskVT,
6663 EVT ToMaskVT) {
6664 // Currently a SETCC or a AND/OR/XOR with two SETCCs are handled.
6665 // FIXME: This code seems to be too restrictive, we might consider
6666 // generalizing it or dropping it.
6667 assert(isSETCCorConvertedSETCC(InMask) && "Unexpected mask argument.");
6668
6669 // Make a new Mask node, with a legal result VT.
6670 SDValue Mask;
6672 for (unsigned i = 0, e = InMask->getNumOperands(); i < e; ++i)
6673 Ops.push_back(InMask->getOperand(i));
6674 if (InMask->isStrictFPOpcode()) {
6675 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask),
6676 { MaskVT, MVT::Other }, Ops);
6677 ReplaceValueWith(InMask.getValue(1), Mask.getValue(1));
6678 }
6679 else
6680 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask), MaskVT, Ops);
6681
6682 // If MaskVT has smaller or bigger elements than ToMaskVT, a vector sign
6683 // extend or truncate is needed.
6684 LLVMContext &Ctx = *DAG.getContext();
6685 unsigned MaskScalarBits = MaskVT.getScalarSizeInBits();
6686 unsigned ToMaskScalBits = ToMaskVT.getScalarSizeInBits();
6687 if (MaskScalarBits < ToMaskScalBits) {
6688 EVT ExtVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
6689 MaskVT.getVectorNumElements());
6690 Mask = DAG.getNode(ISD::SIGN_EXTEND, SDLoc(Mask), ExtVT, Mask);
6691 } else if (MaskScalarBits > ToMaskScalBits) {
6692 EVT TruncVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
6693 MaskVT.getVectorNumElements());
6694 Mask = DAG.getNode(ISD::TRUNCATE, SDLoc(Mask), TruncVT, Mask);
6695 }
6696
6697 assert(Mask->getValueType(0).getScalarSizeInBits() ==
6698 ToMaskVT.getScalarSizeInBits() &&
6699 "Mask should have the right element size by now.");
6700
6701 // Adjust Mask to the right number of elements.
6702 unsigned CurrMaskNumEls = Mask->getValueType(0).getVectorNumElements();
6703 if (CurrMaskNumEls > ToMaskVT.getVectorNumElements()) {
6704 Mask = DAG.getExtractSubvector(SDLoc(Mask), ToMaskVT, Mask, 0);
6705 } else if (CurrMaskNumEls < ToMaskVT.getVectorNumElements()) {
6706 unsigned NumSubVecs = (ToMaskVT.getVectorNumElements() / CurrMaskNumEls);
6707 EVT SubVT = Mask->getValueType(0);
6708 SmallVector<SDValue, 16> SubOps(NumSubVecs, DAG.getUNDEF(SubVT));
6709 SubOps[0] = Mask;
6710 Mask = DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Mask), ToMaskVT, SubOps);
6711 }
6712
6713 assert((Mask->getValueType(0) == ToMaskVT) &&
6714 "A mask of ToMaskVT should have been produced by now.");
6715
6716 return Mask;
6717}
6718
6719// This method tries to handle some special cases for the vselect mask
6720// and if needed adjusting the mask vector type to match that of the VSELECT.
6721// Without it, many cases end up with scalarization of the SETCC, with many
6722// unnecessary instructions.
6723SDValue DAGTypeLegalizer::WidenVSELECTMask(SDNode *N) {
6724 LLVMContext &Ctx = *DAG.getContext();
6725 SDValue Cond = N->getOperand(0);
6726
6727 if (N->getOpcode() != ISD::VSELECT)
6728 return SDValue();
6729
6730 if (!isSETCCOp(Cond->getOpcode()) && !isLogicalMaskOp(Cond->getOpcode()))
6731 return SDValue();
6732
6733 // If this is a splitted VSELECT that was previously already handled, do
6734 // nothing.
6735 EVT CondVT = Cond->getValueType(0);
6736 if (CondVT.getScalarSizeInBits() != 1)
6737 return SDValue();
6738
6739 EVT VSelVT = N->getValueType(0);
6740
6741 // This method can't handle scalable vector types.
6742 // FIXME: This support could be added in the future.
6743 if (VSelVT.isScalableVector())
6744 return SDValue();
6745
6746 // Only handle vector types which are a power of 2.
6747 if (!isPowerOf2_64(VSelVT.getSizeInBits()))
6748 return SDValue();
6749
6750 // Don't touch if this will be scalarized.
6751 EVT FinalVT = VSelVT;
6752 while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
6753 FinalVT = FinalVT.getHalfNumVectorElementsVT(Ctx);
6754
6755 if (FinalVT.getVectorNumElements() == 1)
6756 return SDValue();
6757
6758 // If there is support for an i1 vector mask, don't touch.
6759 if (isSETCCOp(Cond.getOpcode())) {
6760 EVT SetCCOpVT = getSETCCOperandType(Cond);
6761 while (TLI.getTypeAction(Ctx, SetCCOpVT) != TargetLowering::TypeLegal)
6762 SetCCOpVT = TLI.getTypeToTransformTo(Ctx, SetCCOpVT);
6763 EVT SetCCResVT = getSetCCResultType(SetCCOpVT);
6764 if (SetCCResVT.getScalarSizeInBits() == 1)
6765 return SDValue();
6766 } else if (CondVT.getScalarType() == MVT::i1) {
6767 // If there is support for an i1 vector mask (or only scalar i1 conditions),
6768 // don't touch.
6769 while (TLI.getTypeAction(Ctx, CondVT) != TargetLowering::TypeLegal)
6770 CondVT = TLI.getTypeToTransformTo(Ctx, CondVT);
6771
6772 if (CondVT.getScalarType() == MVT::i1)
6773 return SDValue();
6774 }
6775
6776 // Widen the vselect result type if needed.
6777 if (getTypeAction(VSelVT) == TargetLowering::TypeWidenVector)
6778 VSelVT = TLI.getTypeToTransformTo(Ctx, VSelVT);
6779
6780 // The mask of the VSELECT should have integer elements.
6781 EVT ToMaskVT = VSelVT;
6782 if (!ToMaskVT.getScalarType().isInteger())
6783 ToMaskVT = ToMaskVT.changeVectorElementTypeToInteger();
6784
6785 SDValue Mask;
6786 if (isSETCCOp(Cond->getOpcode())) {
6787 EVT MaskVT = getSetCCResultType(getSETCCOperandType(Cond));
6788 Mask = convertMask(Cond, MaskVT, ToMaskVT);
6789 } else if (isLogicalMaskOp(Cond->getOpcode()) &&
6790 isSETCCOp(Cond->getOperand(0).getOpcode()) &&
6791 isSETCCOp(Cond->getOperand(1).getOpcode())) {
6792 // Cond is (AND/OR/XOR (SETCC, SETCC))
6793 SDValue SETCC0 = Cond->getOperand(0);
6794 SDValue SETCC1 = Cond->getOperand(1);
6795 EVT VT0 = getSetCCResultType(getSETCCOperandType(SETCC0));
6796 EVT VT1 = getSetCCResultType(getSETCCOperandType(SETCC1));
6797 unsigned ScalarBits0 = VT0.getScalarSizeInBits();
6798 unsigned ScalarBits1 = VT1.getScalarSizeInBits();
6799 unsigned ScalarBits_ToMask = ToMaskVT.getScalarSizeInBits();
6800 EVT MaskVT;
6801 // If the two SETCCs have different VTs, either extend/truncate one of
6802 // them to the other "towards" ToMaskVT, or truncate one and extend the
6803 // other to ToMaskVT.
6804 if (ScalarBits0 != ScalarBits1) {
6805 EVT NarrowVT = ((ScalarBits0 < ScalarBits1) ? VT0 : VT1);
6806 EVT WideVT = ((NarrowVT == VT0) ? VT1 : VT0);
6807 if (ScalarBits_ToMask >= WideVT.getScalarSizeInBits())
6808 MaskVT = WideVT;
6809 else if (ScalarBits_ToMask <= NarrowVT.getScalarSizeInBits())
6810 MaskVT = NarrowVT;
6811 else
6812 MaskVT = ToMaskVT;
6813 } else
6814 // If the two SETCCs have the same VT, don't change it.
6815 MaskVT = VT0;
6816
6817 // Make new SETCCs and logical nodes.
6818 SETCC0 = convertMask(SETCC0, VT0, MaskVT);
6819 SETCC1 = convertMask(SETCC1, VT1, MaskVT);
6820 Cond = DAG.getNode(Cond->getOpcode(), SDLoc(Cond), MaskVT, SETCC0, SETCC1);
6821
6822 // Convert the logical op for VSELECT if needed.
6823 Mask = convertMask(Cond, MaskVT, ToMaskVT);
6824 } else
6825 return SDValue();
6826
6827 return Mask;
6828}
6829
6830SDValue DAGTypeLegalizer::WidenVecRes_Select(SDNode *N) {
6831 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6832 ElementCount WidenEC = WidenVT.getVectorElementCount();
6833
6834 SDValue Cond1 = N->getOperand(0);
6835 EVT CondVT = Cond1.getValueType();
6836 unsigned Opcode = N->getOpcode();
6837 if (CondVT.isVector()) {
6838 if (SDValue WideCond = WidenVSELECTMask(N)) {
6839 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
6840 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
6841 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
6842 return DAG.getNode(Opcode, SDLoc(N), WidenVT, WideCond, InOp1, InOp2);
6843 }
6844
6845 EVT CondEltVT = CondVT.getVectorElementType();
6846 EVT CondWidenVT = EVT::getVectorVT(*DAG.getContext(), CondEltVT, WidenEC);
6847 if (getTypeAction(CondVT) == TargetLowering::TypeWidenVector)
6848 Cond1 = GetWidenedVector(Cond1);
6849
6850 // If we have to split the condition there is no point in widening the
6851 // select. This would result in an cycle of widening the select ->
6852 // widening the condition operand -> splitting the condition operand ->
6853 // splitting the select -> widening the select. Instead split this select
6854 // further and widen the resulting type.
6855 if (getTypeAction(CondVT) == TargetLowering::TypeSplitVector) {
6856 SDValue SplitSelect = SplitVecOp_VSELECT(N, 0);
6857 SDValue Res = ModifyToType(SplitSelect, WidenVT);
6858 return Res;
6859 }
6860
6861 if (Cond1.getValueType() != CondWidenVT)
6862 Cond1 = ModifyToType(Cond1, CondWidenVT);
6863 }
6864
6865 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
6866 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
6867 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
6868 if (Opcode == ISD::VP_SELECT || Opcode == ISD::VP_MERGE)
6869 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2,
6870 N->getOperand(3));
6871 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2);
6872}
6873
6874SDValue DAGTypeLegalizer::WidenVecRes_SELECT_CC(SDNode *N) {
6875 SDValue InOp1 = GetWidenedVector(N->getOperand(2));
6876 SDValue InOp2 = GetWidenedVector(N->getOperand(3));
6877 return DAG.getNode(ISD::SELECT_CC, SDLoc(N),
6878 InOp1.getValueType(), N->getOperand(0),
6879 N->getOperand(1), InOp1, InOp2, N->getOperand(4));
6880}
6881
6882SDValue DAGTypeLegalizer::WidenVecRes_UNDEF(SDNode *N) {
6883 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6884 return DAG.getUNDEF(WidenVT);
6885}
6886
6887SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N) {
6888 EVT VT = N->getValueType(0);
6889 SDLoc dl(N);
6890
6891 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6892 unsigned NumElts = VT.getVectorNumElements();
6893 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6894
6895 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
6896 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
6897
6898 // Adjust mask based on new input vector length.
6899 SmallVector<int, 16> NewMask(WidenNumElts, -1);
6900 for (unsigned i = 0; i != NumElts; ++i) {
6901 int Idx = N->getMaskElt(i);
6902 if (Idx < (int)NumElts)
6903 NewMask[i] = Idx;
6904 else
6905 NewMask[i] = Idx - NumElts + WidenNumElts;
6906 }
6907 return DAG.getVectorShuffle(WidenVT, dl, InOp1, InOp2, NewMask);
6908}
6909
6910SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_REVERSE(SDNode *N) {
6911 EVT VT = N->getValueType(0);
6912 EVT EltVT = VT.getVectorElementType();
6913 SDLoc dl(N);
6914
6915 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6916 SDValue OpValue = GetWidenedVector(N->getOperand(0));
6917 assert(WidenVT == OpValue.getValueType() && "Unexpected widened vector type");
6918
6919 SDValue ReverseVal = DAG.getNode(ISD::VECTOR_REVERSE, dl, WidenVT, OpValue);
6920 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6921 unsigned VTNumElts = VT.getVectorMinNumElements();
6922 unsigned IdxVal = WidenNumElts - VTNumElts;
6923
6924 if (VT.isScalableVector()) {
6925 // Try to split the 'Widen ReverseVal' into smaller extracts and concat the
6926 // results together, e.g.(nxv6i64 -> nxv8i64)
6927 // nxv8i64 vector_reverse
6928 // <->
6929 // nxv8i64 concat(
6930 // nxv2i64 extract_subvector(nxv8i64, 2)
6931 // nxv2i64 extract_subvector(nxv8i64, 4)
6932 // nxv2i64 extract_subvector(nxv8i64, 6)
6933 // nxv2i64 undef)
6934
6935 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
6936 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
6938 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
6939 "down type's element count");
6941 unsigned i = 0;
6942 for (; i < VTNumElts / GCD; ++i)
6943 Parts.push_back(
6944 DAG.getExtractSubvector(dl, PartVT, ReverseVal, IdxVal + i * GCD));
6945 for (; i < WidenNumElts / GCD; ++i)
6946 Parts.push_back(DAG.getPOISON(PartVT));
6947
6948 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
6949 }
6950
6951 // Use VECTOR_SHUFFLE to combine new vector from 'ReverseVal' for
6952 // fixed-vectors.
6953 SmallVector<int, 16> Mask(WidenNumElts, -1);
6954 std::iota(Mask.begin(), Mask.begin() + VTNumElts, IdxVal);
6955
6956 return DAG.getVectorShuffle(WidenVT, dl, ReverseVal, DAG.getUNDEF(WidenVT),
6957 Mask);
6958}
6959
6960SDValue DAGTypeLegalizer::WidenVecRes_GET_ACTIVE_LANE_MASK(SDNode *N) {
6961 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6962 return DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, SDLoc(N), NVT, N->ops());
6963}
6964
6965SDValue DAGTypeLegalizer::WidenVecRes_SETCC(SDNode *N) {
6966 assert(N->getValueType(0).isVector() &&
6967 N->getOperand(0).getValueType().isVector() &&
6968 "Operands must be vectors");
6969 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6970 ElementCount WidenEC = WidenVT.getVectorElementCount();
6971
6972 SDValue InOp1 = N->getOperand(0);
6973 EVT InVT = InOp1.getValueType();
6974 assert(InVT.isVector() && "can not widen non-vector type");
6975 EVT WidenInVT =
6976 EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), WidenEC);
6977
6978 // The input and output types often differ here, and it could be that while
6979 // we'd prefer to widen the result type, the input operands have been split.
6980 // In this case, we also need to split the result of this node as well.
6981 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector) {
6982 SDValue SplitVSetCC = SplitVecOp_VSETCC(N);
6983 SDValue Res = ModifyToType(SplitVSetCC, WidenVT);
6984 return Res;
6985 }
6986
6987 // If the inputs also widen, handle them directly. Otherwise widen by hand.
6988 SDValue InOp2 = N->getOperand(1);
6989 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
6990 InOp1 = GetWidenedVector(InOp1);
6991 InOp2 = GetWidenedVector(InOp2);
6992 } else {
6993 SDValue Poison = DAG.getPOISON(WidenInVT);
6994 SDValue ZeroIdx = DAG.getVectorIdxConstant(0, SDLoc(N));
6995 InOp1 = DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), WidenInVT, Poison,
6996 InOp1, ZeroIdx);
6997 InOp2 = DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), WidenInVT, Poison,
6998 InOp2, ZeroIdx);
6999 }
7000
7001 // Assume that the input and output will be widen appropriately. If not,
7002 // we will have to unroll it at some point.
7003 assert(InOp1.getValueType() == WidenInVT &&
7004 InOp2.getValueType() == WidenInVT &&
7005 "Input not widened to expected type!");
7006 (void)WidenInVT;
7007 if (N->getOpcode() == ISD::VP_SETCC) {
7008 SDValue Mask =
7009 GetWidenedMask(N->getOperand(3), WidenVT.getVectorElementCount());
7010 return DAG.getNode(ISD::VP_SETCC, SDLoc(N), WidenVT, InOp1, InOp2,
7011 N->getOperand(2), Mask, N->getOperand(4));
7012 }
7013 return DAG.getNode(ISD::SETCC, SDLoc(N), WidenVT, InOp1, InOp2,
7014 N->getOperand(2));
7015}
7016
7017SDValue DAGTypeLegalizer::WidenVecRes_STRICT_FSETCC(SDNode *N) {
7018 assert(N->getValueType(0).isVector() &&
7019 N->getOperand(1).getValueType().isVector() &&
7020 "Operands must be vectors");
7021 EVT VT = N->getValueType(0);
7022 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7023 unsigned WidenNumElts = WidenVT.getVectorNumElements();
7024 unsigned NumElts = VT.getVectorNumElements();
7025 EVT EltVT = VT.getVectorElementType();
7026
7027 SDLoc dl(N);
7028 SDValue Chain = N->getOperand(0);
7029 SDValue LHS = N->getOperand(1);
7030 SDValue RHS = N->getOperand(2);
7031 SDValue CC = N->getOperand(3);
7032 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
7033
7034 // Fully unroll and reassemble.
7035 SmallVector<SDValue, 8> Scalars(WidenNumElts, DAG.getPOISON(EltVT));
7036 SmallVector<SDValue, 8> Chains(NumElts);
7037 for (unsigned i = 0; i != NumElts; ++i) {
7038 SDValue LHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, LHS, i);
7039 SDValue RHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, RHS, i);
7040
7041 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
7042 {Chain, LHSElem, RHSElem, CC});
7043 Chains[i] = Scalars[i].getValue(1);
7044 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
7045 DAG.getBoolConstant(true, dl, EltVT, VT),
7046 DAG.getBoolConstant(false, dl, EltVT, VT));
7047 }
7048
7049 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
7050 ReplaceValueWith(SDValue(N, 1), NewChain);
7051
7052 return DAG.getBuildVector(WidenVT, dl, Scalars);
7053}
7054
7055//===----------------------------------------------------------------------===//
7056// Widen Vector Operand
7057//===----------------------------------------------------------------------===//
7058bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned OpNo) {
7059 LLVM_DEBUG(dbgs() << "Widen node operand " << OpNo << ": "; N->dump(&DAG));
7060 SDValue Res = SDValue();
7061
7062 // See if the target wants to custom widen this node.
7063 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
7064 return false;
7065
7066 switch (N->getOpcode()) {
7067 default:
7068#ifndef NDEBUG
7069 dbgs() << "WidenVectorOperand op #" << OpNo << ": ";
7070 N->dump(&DAG);
7071 dbgs() << "\n";
7072#endif
7073 report_fatal_error("Do not know how to widen this operator's operand!");
7074
7075 case ISD::BITCAST: Res = WidenVecOp_BITCAST(N); break;
7076 case ISD::FAKE_USE:
7077 Res = WidenVecOp_FAKE_USE(N);
7078 break;
7079 case ISD::CONCAT_VECTORS: Res = WidenVecOp_CONCAT_VECTORS(N); break;
7080 case ISD::INSERT_SUBVECTOR: Res = WidenVecOp_INSERT_SUBVECTOR(N); break;
7081 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecOp_EXTRACT_SUBVECTOR(N); break;
7082 case ISD::EXTRACT_VECTOR_ELT: Res = WidenVecOp_EXTRACT_VECTOR_ELT(N); break;
7083 case ISD::STORE: Res = WidenVecOp_STORE(N); break;
7084 case ISD::VP_STORE: Res = WidenVecOp_VP_STORE(N, OpNo); break;
7085 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
7086 Res = WidenVecOp_VP_STRIDED_STORE(N, OpNo);
7087 break;
7091 Res = WidenVecOp_EXTEND_VECTOR_INREG(N);
7092 break;
7093 case ISD::MSTORE: Res = WidenVecOp_MSTORE(N, OpNo); break;
7094 case ISD::MGATHER: Res = WidenVecOp_MGATHER(N, OpNo); break;
7095 case ISD::MSCATTER: Res = WidenVecOp_MSCATTER(N, OpNo); break;
7096 case ISD::VP_SCATTER: Res = WidenVecOp_VP_SCATTER(N, OpNo); break;
7097 case ISD::SETCC: Res = WidenVecOp_SETCC(N); break;
7098 case ISD::STRICT_FSETCC:
7099 case ISD::STRICT_FSETCCS: Res = WidenVecOp_STRICT_FSETCC(N); break;
7100 case ISD::VSELECT: Res = WidenVecOp_VSELECT(N); break;
7101 case ISD::FLDEXP:
7102 case ISD::FCOPYSIGN:
7103 case ISD::LROUND:
7104 case ISD::LLROUND:
7105 case ISD::LRINT:
7106 case ISD::LLRINT:
7107 Res = WidenVecOp_UnrollVectorOp(N);
7108 break;
7109 case ISD::IS_FPCLASS: Res = WidenVecOp_IS_FPCLASS(N); break;
7110
7111 case ISD::ANY_EXTEND:
7112 case ISD::SIGN_EXTEND:
7113 case ISD::ZERO_EXTEND:
7114 Res = WidenVecOp_EXTEND(N);
7115 break;
7116
7117 case ISD::SCMP:
7118 case ISD::UCMP:
7119 Res = WidenVecOp_CMP(N);
7120 break;
7121
7122 case ISD::FP_EXTEND:
7124 case ISD::FP_ROUND:
7126 case ISD::FP_TO_SINT:
7128 case ISD::FP_TO_UINT:
7130 case ISD::SINT_TO_FP:
7132 case ISD::UINT_TO_FP:
7134 case ISD::TRUNCATE:
7135 Res = WidenVecOp_Convert(N);
7136 break;
7137
7140 Res = WidenVecOp_FP_TO_XINT_SAT(N);
7141 break;
7142
7145 case ISD::VECREDUCE_ADD:
7146 case ISD::VECREDUCE_MUL:
7147 case ISD::VECREDUCE_AND:
7148 case ISD::VECREDUCE_OR:
7149 case ISD::VECREDUCE_XOR:
7158 Res = WidenVecOp_VECREDUCE(N);
7159 break;
7162 Res = WidenVecOp_VECREDUCE_SEQ(N);
7163 break;
7164 case ISD::VP_REDUCE_FADD:
7165 case ISD::VP_REDUCE_SEQ_FADD:
7166 case ISD::VP_REDUCE_FMUL:
7167 case ISD::VP_REDUCE_SEQ_FMUL:
7168 case ISD::VP_REDUCE_ADD:
7169 case ISD::VP_REDUCE_MUL:
7170 case ISD::VP_REDUCE_AND:
7171 case ISD::VP_REDUCE_OR:
7172 case ISD::VP_REDUCE_XOR:
7173 case ISD::VP_REDUCE_SMAX:
7174 case ISD::VP_REDUCE_SMIN:
7175 case ISD::VP_REDUCE_UMAX:
7176 case ISD::VP_REDUCE_UMIN:
7177 case ISD::VP_REDUCE_FMAX:
7178 case ISD::VP_REDUCE_FMIN:
7179 case ISD::VP_REDUCE_FMAXIMUM:
7180 case ISD::VP_REDUCE_FMINIMUM:
7181 Res = WidenVecOp_VP_REDUCE(N);
7182 break;
7183 case ISD::VP_CTTZ_ELTS:
7184 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
7185 Res = WidenVecOp_VP_CttzElements(N);
7186 break;
7187 }
7188
7189 // If Res is null, the sub-method took care of registering the result.
7190 if (!Res.getNode()) return false;
7191
7192 // If the result is N, the sub-method updated N in place. Tell the legalizer
7193 // core about this.
7194 if (Res.getNode() == N)
7195 return true;
7196
7197
7198 if (N->isStrictFPOpcode())
7199 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
7200 "Invalid operand expansion");
7201 else
7202 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
7203 "Invalid operand expansion");
7204
7205 ReplaceValueWith(SDValue(N, 0), Res);
7206 return false;
7207}
7208
7209SDValue DAGTypeLegalizer::WidenVecOp_EXTEND(SDNode *N) {
7210 SDLoc DL(N);
7211 EVT VT = N->getValueType(0);
7212
7213 SDValue InOp = N->getOperand(0);
7214 assert(getTypeAction(InOp.getValueType()) ==
7216 "Unexpected type action");
7217 InOp = GetWidenedVector(InOp);
7220 "Input wasn't widened!");
7221
7222 // We may need to further widen the operand until it has the same total
7223 // vector size as the result.
7224 EVT InVT = InOp.getValueType();
7225 if (InVT.getSizeInBits() != VT.getSizeInBits()) {
7226 EVT InEltVT = InVT.getVectorElementType();
7227 for (EVT FixedVT : MVT::vector_valuetypes()) {
7228 EVT FixedEltVT = FixedVT.getVectorElementType();
7229 if (TLI.isTypeLegal(FixedVT) &&
7230 FixedVT.getSizeInBits() == VT.getSizeInBits() &&
7231 FixedEltVT == InEltVT) {
7232 assert(FixedVT.getVectorNumElements() >= VT.getVectorNumElements() &&
7233 "Not enough elements in the fixed type for the operand!");
7234 assert(FixedVT.getVectorNumElements() != InVT.getVectorNumElements() &&
7235 "We can't have the same type as we started with!");
7236 if (FixedVT.getVectorNumElements() > InVT.getVectorNumElements())
7237 InOp = DAG.getInsertSubvector(DL, DAG.getUNDEF(FixedVT), InOp, 0);
7238 else
7239 InOp = DAG.getExtractSubvector(DL, FixedVT, InOp, 0);
7240 break;
7241 }
7242 }
7243 InVT = InOp.getValueType();
7244 if (InVT.getSizeInBits() != VT.getSizeInBits())
7245 // We couldn't find a legal vector type that was a widening of the input
7246 // and could be extended in-register to the result type, so we have to
7247 // scalarize.
7248 return WidenVecOp_Convert(N);
7249 }
7250
7251 // Use special DAG nodes to represent the operation of extending the
7252 // low lanes.
7253 switch (N->getOpcode()) {
7254 default:
7255 llvm_unreachable("Extend legalization on extend operation!");
7256 case ISD::ANY_EXTEND:
7257 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, VT, InOp);
7258 case ISD::SIGN_EXTEND:
7259 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, VT, InOp);
7260 case ISD::ZERO_EXTEND:
7261 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, VT, InOp);
7262 }
7263}
7264
7265SDValue DAGTypeLegalizer::WidenVecOp_CMP(SDNode *N) {
7266 SDLoc dl(N);
7267
7268 EVT OpVT = N->getOperand(0).getValueType();
7269 EVT ResVT = N->getValueType(0);
7270 SDValue LHS = GetWidenedVector(N->getOperand(0));
7271 SDValue RHS = GetWidenedVector(N->getOperand(1));
7272
7273 // 1. EXTRACT_SUBVECTOR
7274 // 2. SIGN_EXTEND/ZERO_EXTEND
7275 // 3. CMP
7276 LHS = DAG.getExtractSubvector(dl, OpVT, LHS, 0);
7277 RHS = DAG.getExtractSubvector(dl, OpVT, RHS, 0);
7278
7279 // At this point the result type is guaranteed to be valid, so we can use it
7280 // as the operand type by extending it appropriately
7281 ISD::NodeType ExtendOpcode =
7282 N->getOpcode() == ISD::SCMP ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
7283 LHS = DAG.getNode(ExtendOpcode, dl, ResVT, LHS);
7284 RHS = DAG.getNode(ExtendOpcode, dl, ResVT, RHS);
7285
7286 return DAG.getNode(N->getOpcode(), dl, ResVT, LHS, RHS);
7287}
7288
7289SDValue DAGTypeLegalizer::WidenVecOp_UnrollVectorOp(SDNode *N) {
7290 // The result (and first input) is legal, but the second input is illegal.
7291 // We can't do much to fix that, so just unroll and let the extracts off of
7292 // the second input be widened as needed later.
7293 return DAG.UnrollVectorOp(N);
7294}
7295
7296SDValue DAGTypeLegalizer::WidenVecOp_IS_FPCLASS(SDNode *N) {
7297 SDLoc DL(N);
7298 EVT ResultVT = N->getValueType(0);
7299 SDValue Test = N->getOperand(1);
7300 SDValue WideArg = GetWidenedVector(N->getOperand(0));
7301
7302 // Process this node similarly to SETCC.
7303 EVT WideResultVT = getSetCCResultType(WideArg.getValueType());
7304 if (ResultVT.getScalarType() == MVT::i1)
7305 WideResultVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
7306 WideResultVT.getVectorNumElements());
7307
7308 SDValue WideNode = DAG.getNode(ISD::IS_FPCLASS, DL, WideResultVT,
7309 {WideArg, Test}, N->getFlags());
7310
7311 // Extract the needed results from the result vector.
7312 EVT ResVT =
7313 EVT::getVectorVT(*DAG.getContext(), WideResultVT.getVectorElementType(),
7314 ResultVT.getVectorNumElements());
7315 SDValue CC = DAG.getExtractSubvector(DL, ResVT, WideNode, 0);
7316
7317 EVT OpVT = N->getOperand(0).getValueType();
7318 ISD::NodeType ExtendCode =
7319 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
7320 return DAG.getNode(ExtendCode, DL, ResultVT, CC);
7321}
7322
7323SDValue DAGTypeLegalizer::WidenVecOp_Convert(SDNode *N) {
7324 // Since the result is legal and the input is illegal.
7325 EVT VT = N->getValueType(0);
7326 EVT EltVT = VT.getVectorElementType();
7327 SDLoc dl(N);
7328 SDValue InOp = N->getOperand(N->isStrictFPOpcode() ? 1 : 0);
7329 assert(getTypeAction(InOp.getValueType()) ==
7331 "Unexpected type action");
7332 InOp = GetWidenedVector(InOp);
7333 EVT InVT = InOp.getValueType();
7334 unsigned Opcode = N->getOpcode();
7335
7336 // See if a widened result type would be legal, if so widen the node.
7337 // FIXME: This isn't safe for StrictFP. Other optimization here is needed.
7338 EVT WideVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
7339 InVT.getVectorElementCount());
7340 if (TLI.isTypeLegal(WideVT) && !N->isStrictFPOpcode()) {
7341 SDValue Res;
7342 if (N->isStrictFPOpcode()) {
7343 if (Opcode == ISD::STRICT_FP_ROUND)
7344 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
7345 { N->getOperand(0), InOp, N->getOperand(2) });
7346 else
7347 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
7348 { N->getOperand(0), InOp });
7349 // Legalize the chain result - switch anything that used the old chain to
7350 // use the new one.
7351 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7352 } else {
7353 if (Opcode == ISD::FP_ROUND)
7354 Res = DAG.getNode(Opcode, dl, WideVT, InOp, N->getOperand(1));
7355 else
7356 Res = DAG.getNode(Opcode, dl, WideVT, InOp);
7357 }
7358 return DAG.getExtractSubvector(dl, VT, Res, 0);
7359 }
7360
7361 EVT InEltVT = InVT.getVectorElementType();
7362
7363 // Unroll the convert into some scalar code and create a nasty build vector.
7364 unsigned NumElts = VT.getVectorNumElements();
7366 if (N->isStrictFPOpcode()) {
7367 SmallVector<SDValue, 4> NewOps(N->ops());
7368 SmallVector<SDValue, 32> OpChains;
7369 for (unsigned i=0; i < NumElts; ++i) {
7370 NewOps[1] = DAG.getExtractVectorElt(dl, InEltVT, InOp, i);
7371 Ops[i] = DAG.getNode(Opcode, dl, { EltVT, MVT::Other }, NewOps);
7372 OpChains.push_back(Ops[i].getValue(1));
7373 }
7374 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OpChains);
7375 ReplaceValueWith(SDValue(N, 1), NewChain);
7376 } else {
7377 for (unsigned i = 0; i < NumElts; ++i)
7378 Ops[i] = DAG.getNode(Opcode, dl, EltVT,
7379 DAG.getExtractVectorElt(dl, InEltVT, InOp, i));
7380 }
7381
7382 return DAG.getBuildVector(VT, dl, Ops);
7383}
7384
7385SDValue DAGTypeLegalizer::WidenVecOp_FP_TO_XINT_SAT(SDNode *N) {
7386 EVT DstVT = N->getValueType(0);
7387 SDValue Src = GetWidenedVector(N->getOperand(0));
7388 EVT SrcVT = Src.getValueType();
7389 ElementCount WideNumElts = SrcVT.getVectorElementCount();
7390 SDLoc dl(N);
7391
7392 // See if a widened result type would be legal, if so widen the node.
7393 EVT WideDstVT = EVT::getVectorVT(*DAG.getContext(),
7394 DstVT.getVectorElementType(), WideNumElts);
7395 if (TLI.isTypeLegal(WideDstVT)) {
7396 SDValue Res =
7397 DAG.getNode(N->getOpcode(), dl, WideDstVT, Src, N->getOperand(1));
7398 return DAG.getNode(
7399 ISD::EXTRACT_SUBVECTOR, dl, DstVT, Res,
7400 DAG.getConstant(0, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
7401 }
7402
7403 // Give up and unroll.
7404 return DAG.UnrollVectorOp(N);
7405}
7406
7407SDValue DAGTypeLegalizer::WidenVecOp_BITCAST(SDNode *N) {
7408 EVT VT = N->getValueType(0);
7409 SDValue InOp = GetWidenedVector(N->getOperand(0));
7410 EVT InWidenVT = InOp.getValueType();
7411 SDLoc dl(N);
7412
7413 // Check if we can convert between two legal vector types and extract.
7414 TypeSize InWidenSize = InWidenVT.getSizeInBits();
7415 TypeSize Size = VT.getSizeInBits();
7416 // x86mmx is not an acceptable vector element type, so don't try.
7417 if (!VT.isVector() && VT != MVT::x86mmx &&
7418 InWidenSize.hasKnownScalarFactor(Size)) {
7419 unsigned NewNumElts = InWidenSize.getKnownScalarFactor(Size);
7420 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), VT, NewNumElts);
7421 if (TLI.isTypeLegal(NewVT)) {
7422 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
7423 return DAG.getExtractVectorElt(dl, VT, BitOp, 0);
7424 }
7425 }
7426
7427 // Handle a case like bitcast v12i8 -> v3i32. Normally that would get widened
7428 // to v16i8 -> v4i32, but for a target where v3i32 is legal but v12i8 is not,
7429 // we end up here. Handling the case here with EXTRACT_SUBVECTOR avoids
7430 // having to copy via memory.
7431 if (VT.isVector()) {
7432 EVT EltVT = VT.getVectorElementType();
7433 unsigned EltSize = EltVT.getFixedSizeInBits();
7434 if (InWidenSize.isKnownMultipleOf(EltSize)) {
7435 ElementCount NewNumElts =
7436 (InWidenVT.getVectorElementCount() * InWidenVT.getScalarSizeInBits())
7437 .divideCoefficientBy(EltSize);
7438 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NewNumElts);
7439 if (TLI.isTypeLegal(NewVT)) {
7440 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
7441 return DAG.getExtractSubvector(dl, VT, BitOp, 0);
7442 }
7443 }
7444 }
7445
7446 return CreateStackStoreLoad(InOp, VT);
7447}
7448
7449// Vectors with sizes that are not powers of 2 need to be widened to the
7450// next largest power of 2. For example, we may get a vector of 3 32-bit
7451// integers or of 6 16-bit integers, both of which have to be widened to a
7452// 128-bit vector.
7453SDValue DAGTypeLegalizer::WidenVecOp_FAKE_USE(SDNode *N) {
7454 SDValue WidenedOp = GetWidenedVector(N->getOperand(1));
7455 return DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, N->getOperand(0),
7456 WidenedOp);
7457}
7458
7459SDValue DAGTypeLegalizer::WidenVecOp_CONCAT_VECTORS(SDNode *N) {
7460 EVT VT = N->getValueType(0);
7461 EVT EltVT = VT.getVectorElementType();
7462 EVT InVT = N->getOperand(0).getValueType();
7463 SDLoc dl(N);
7464
7465 // If the widen width for this operand is the same as the width of the concat
7466 // and all but the first operand is undef, just use the widened operand.
7467 unsigned NumOperands = N->getNumOperands();
7468 if (VT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
7469 unsigned i;
7470 for (i = 1; i < NumOperands; ++i)
7471 if (!N->getOperand(i).isUndef())
7472 break;
7473
7474 if (i == NumOperands)
7475 return GetWidenedVector(N->getOperand(0));
7476 }
7477
7478 // Otherwise, fall back to a nasty build vector.
7479 unsigned NumElts = VT.getVectorNumElements();
7481
7482 unsigned NumInElts = InVT.getVectorNumElements();
7483
7484 unsigned Idx = 0;
7485 for (unsigned i=0; i < NumOperands; ++i) {
7486 SDValue InOp = N->getOperand(i);
7487 assert(getTypeAction(InOp.getValueType()) ==
7489 "Unexpected type action");
7490 InOp = GetWidenedVector(InOp);
7491 for (unsigned j = 0; j < NumInElts; ++j)
7492 Ops[Idx++] = DAG.getExtractVectorElt(dl, EltVT, InOp, j);
7493 }
7494 return DAG.getBuildVector(VT, dl, Ops);
7495}
7496
7497SDValue DAGTypeLegalizer::WidenVecOp_INSERT_SUBVECTOR(SDNode *N) {
7498 EVT VT = N->getValueType(0);
7499 SDValue SubVec = N->getOperand(1);
7500 SDValue InVec = N->getOperand(0);
7501
7502 EVT OrigVT = SubVec.getValueType();
7503 SubVec = GetWidenedVector(SubVec);
7504 EVT SubVT = SubVec.getValueType();
7505
7506 // Whether or not all the elements of the widened SubVec will be inserted into
7507 // valid indices of VT.
7508 bool IndicesValid = false;
7509 // If we statically know that VT can fit SubVT, the indices are valid.
7510 if (VT.knownBitsGE(SubVT))
7511 IndicesValid = true;
7512 else if (VT.isScalableVector() && SubVT.isFixedLengthVector()) {
7513 // Otherwise, if we're inserting a fixed vector into a scalable vector and
7514 // we know the minimum vscale we can work out if it's valid ourselves.
7515 Attribute Attr = DAG.getMachineFunction().getFunction().getFnAttribute(
7516 Attribute::VScaleRange);
7517 if (Attr.isValid()) {
7518 unsigned VScaleMin = Attr.getVScaleRangeMin();
7519 if (VT.getSizeInBits().getKnownMinValue() * VScaleMin >=
7520 SubVT.getFixedSizeInBits())
7521 IndicesValid = true;
7522 }
7523 }
7524
7525 if (!IndicesValid)
7527 "Don't know how to widen the operands for INSERT_SUBVECTOR");
7528
7529 SDLoc DL(N);
7530
7531 // We need to make sure that the indices are still valid, otherwise we might
7532 // widen what was previously well-defined to something undefined.
7533 if (InVec.isUndef() && N->getConstantOperandVal(2) == 0)
7534 return DAG.getNode(ISD::INSERT_SUBVECTOR, DL, VT, InVec, SubVec,
7535 N->getOperand(2));
7536
7537 if (OrigVT.isScalableVector()) {
7538 // Fallback to inserting through memory.
7539
7540 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
7541 SDValue StackPtr = DAG.CreateStackTemporary(VT.getStoreSize(), Alignment);
7542 MachineFunction &MF = DAG.getMachineFunction();
7543 int FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
7544 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
7545
7546 MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
7549 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
7552
7553 // Write out the vector being inserting into.
7554 SDValue Ch =
7555 DAG.getStore(DAG.getEntryNode(), DL, InVec, StackPtr, StoreMMO);
7556
7557 // Build a mask to match the length of the sub-vector.
7558 SDValue Mask =
7559 DAG.getMaskFromElementCount(DL, SubVT, OrigVT.getVectorElementCount());
7560
7561 // Overwrite the sub-vector at the required offset.
7562 SDValue SubVecPtr =
7563 TLI.getVectorSubVecPointer(DAG, StackPtr, VT, OrigVT, N->getOperand(2));
7564 Ch = DAG.getMaskedStore(Ch, DL, SubVec, SubVecPtr,
7565 DAG.getUNDEF(SubVecPtr.getValueType()), Mask, VT,
7566 StoreMMO, ISD::UNINDEXED, ISD::NON_EXTLOAD);
7567
7568 // Read back the result.
7569 return DAG.getLoad(VT, DL, Ch, StackPtr, LoadMMO);
7570 }
7571
7572 // If the operands can't be widened legally, just replace the INSERT_SUBVECTOR
7573 // with a series of INSERT_VECTOR_ELT
7574 unsigned Idx = N->getConstantOperandVal(2);
7575
7576 SDValue InsertElt = InVec;
7577 for (unsigned I = 0, E = OrigVT.getVectorNumElements(); I != E; ++I) {
7578 SDValue ExtractElt =
7579 DAG.getExtractVectorElt(DL, VT.getVectorElementType(), SubVec, I);
7580 InsertElt = DAG.getInsertVectorElt(DL, InsertElt, ExtractElt, I + Idx);
7581 }
7582
7583 return InsertElt;
7584}
7585
7586SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
7587 SDValue InOp = GetWidenedVector(N->getOperand(0));
7588 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SDLoc(N),
7589 N->getValueType(0), InOp, N->getOperand(1));
7590}
7591
7592SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
7593 SDValue InOp = GetWidenedVector(N->getOperand(0));
7594 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
7595 N->getValueType(0), InOp, N->getOperand(1));
7596}
7597
7598SDValue DAGTypeLegalizer::WidenVecOp_EXTEND_VECTOR_INREG(SDNode *N) {
7599 SDValue InOp = GetWidenedVector(N->getOperand(0));
7600 return DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0), InOp);
7601}
7602
7603SDValue DAGTypeLegalizer::WidenVecOp_STORE(SDNode *N) {
7604 // We have to widen the value, but we want only to store the original
7605 // vector type.
7606 StoreSDNode *ST = cast<StoreSDNode>(N);
7607
7608 if (!ST->getMemoryVT().getScalarType().isByteSized())
7609 return TLI.scalarizeVectorStore(ST, DAG);
7610
7611 if (ST->isTruncatingStore())
7612 return TLI.scalarizeVectorStore(ST, DAG);
7613
7614 // Generate a vector-predicated store if it is custom/legal on the target.
7615 // To avoid possible recursion, only do this if the widened mask type is
7616 // legal.
7617 // FIXME: Not all targets may support EVL in VP_STORE. These will have been
7618 // removed from the IR by the ExpandVectorPredication pass but we're
7619 // reintroducing them here.
7620 SDValue StVal = ST->getValue();
7621 EVT StVT = StVal.getValueType();
7622 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), StVT);
7623 EVT WideMaskVT = getSetCCResultType(WideVT);
7624
7625 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
7626 TLI.isTypeLegal(WideMaskVT)) {
7627 // Widen the value.
7628 SDLoc DL(N);
7629 StVal = GetWidenedVector(StVal);
7630 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
7631 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
7632 StVT.getVectorElementCount());
7633 return DAG.getStoreVP(ST->getChain(), DL, StVal, ST->getBasePtr(),
7634 ST->getOffset(), Mask, EVL, StVT, ST->getMemOperand(),
7635 ST->getAddressingMode());
7636 }
7637
7639 if (GenWidenVectorStores(StChain, ST)) {
7640 if (StChain.size() == 1)
7641 return StChain[0];
7642
7643 return DAG.getNode(ISD::TokenFactor, SDLoc(ST), MVT::Other, StChain);
7644 }
7645
7646 if (StVT.isVector()) {
7647 // If all else fails replace the store with a wide masked store.
7648 SDLoc DL(N);
7649 SDValue WideStVal = GetWidenedVector(StVal);
7650 SDValue Mask =
7651 DAG.getMaskFromElementCount(DL, WideVT, StVT.getVectorElementCount());
7652
7653 return DAG.getMaskedStore(ST->getChain(), DL, WideStVal, ST->getBasePtr(),
7654 ST->getOffset(), Mask, ST->getMemoryVT(),
7655 ST->getMemOperand(), ST->getAddressingMode(),
7656 ST->isTruncatingStore());
7657 }
7658
7659 report_fatal_error("Unable to widen vector store");
7660}
7661
7662SDValue DAGTypeLegalizer::WidenVecOp_VP_STORE(SDNode *N, unsigned OpNo) {
7663 assert((OpNo == 1 || OpNo == 3) &&
7664 "Can widen only data or mask operand of vp_store");
7665 VPStoreSDNode *ST = cast<VPStoreSDNode>(N);
7666 SDValue Mask = ST->getMask();
7667 SDValue StVal = ST->getValue();
7668 SDLoc dl(N);
7669
7670 if (OpNo == 1) {
7671 // Widen the value.
7672 StVal = GetWidenedVector(StVal);
7673
7674 // We only handle the case where the mask needs widening to an
7675 // identically-sized type as the vector inputs.
7676 assert(getTypeAction(Mask.getValueType()) ==
7678 "Unable to widen VP store");
7679 Mask = GetWidenedVector(Mask);
7680 } else {
7681 Mask = GetWidenedVector(Mask);
7682
7683 // We only handle the case where the stored value needs widening to an
7684 // identically-sized type as the mask.
7685 assert(getTypeAction(StVal.getValueType()) ==
7687 "Unable to widen VP store");
7688 StVal = GetWidenedVector(StVal);
7689 }
7690
7691 assert(Mask.getValueType().getVectorElementCount() ==
7693 "Mask and data vectors should have the same number of elements");
7694 return DAG.getStoreVP(ST->getChain(), dl, StVal, ST->getBasePtr(),
7695 ST->getOffset(), Mask, ST->getVectorLength(),
7696 ST->getMemoryVT(), ST->getMemOperand(),
7697 ST->getAddressingMode(), ST->isTruncatingStore(),
7698 ST->isCompressingStore());
7699}
7700
7701SDValue DAGTypeLegalizer::WidenVecOp_VP_STRIDED_STORE(SDNode *N,
7702 unsigned OpNo) {
7703 assert((OpNo == 1 || OpNo == 4) &&
7704 "Can widen only data or mask operand of vp_strided_store");
7705 VPStridedStoreSDNode *SST = cast<VPStridedStoreSDNode>(N);
7706 SDValue Mask = SST->getMask();
7707 SDValue StVal = SST->getValue();
7708 SDLoc DL(N);
7709
7710 if (OpNo == 1)
7711 assert(getTypeAction(Mask.getValueType()) ==
7713 "Unable to widen VP strided store");
7714 else
7715 assert(getTypeAction(StVal.getValueType()) ==
7717 "Unable to widen VP strided store");
7718
7719 StVal = GetWidenedVector(StVal);
7720 Mask = GetWidenedVector(Mask);
7721
7723 Mask.getValueType().getVectorElementCount() &&
7724 "Data and mask vectors should have the same number of elements");
7725
7726 return DAG.getStridedStoreVP(
7727 SST->getChain(), DL, StVal, SST->getBasePtr(), SST->getOffset(),
7728 SST->getStride(), Mask, SST->getVectorLength(), SST->getMemoryVT(),
7729 SST->getMemOperand(), SST->getAddressingMode(), SST->isTruncatingStore(),
7730 SST->isCompressingStore());
7731}
7732
7733SDValue DAGTypeLegalizer::WidenVecOp_MSTORE(SDNode *N, unsigned OpNo) {
7734 assert((OpNo == 1 || OpNo == 4) &&
7735 "Can widen only data or mask operand of mstore");
7736 MaskedStoreSDNode *MST = cast<MaskedStoreSDNode>(N);
7737 SDValue Mask = MST->getMask();
7738 EVT MaskVT = Mask.getValueType();
7739 SDValue StVal = MST->getValue();
7740 EVT VT = StVal.getValueType();
7741 SDLoc dl(N);
7742
7743 EVT WideVT, WideMaskVT;
7744 if (OpNo == 1) {
7745 // Widen the value.
7746 StVal = GetWidenedVector(StVal);
7747
7748 WideVT = StVal.getValueType();
7749 WideMaskVT =
7750 EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(),
7751 WideVT.getVectorElementCount());
7752 } else {
7753 WideMaskVT = TLI.getTypeToTransformTo(*DAG.getContext(), MaskVT);
7754
7755 EVT ValueVT = StVal.getValueType();
7756 WideVT = EVT::getVectorVT(*DAG.getContext(), ValueVT.getVectorElementType(),
7757 WideMaskVT.getVectorElementCount());
7758 }
7759
7760 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
7761 TLI.isTypeLegal(WideMaskVT)) {
7762 Mask = DAG.getInsertSubvector(dl, DAG.getUNDEF(WideMaskVT), Mask, 0);
7763 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
7765 return DAG.getStoreVP(MST->getChain(), dl, StVal, MST->getBasePtr(),
7766 MST->getOffset(), Mask, EVL, MST->getMemoryVT(),
7767 MST->getMemOperand(), MST->getAddressingMode());
7768 }
7769
7770 if (OpNo == 1) {
7771 // The mask should be widened as well.
7772 Mask = ModifyToType(Mask, WideMaskVT, true);
7773 } else {
7774 // Widen the mask.
7775 Mask = ModifyToType(Mask, WideMaskVT, true);
7776
7777 StVal = ModifyToType(StVal, WideVT);
7778 }
7779
7780 assert(Mask.getValueType().getVectorElementCount() ==
7782 "Mask and data vectors should have the same number of elements");
7783 return DAG.getMaskedStore(MST->getChain(), dl, StVal, MST->getBasePtr(),
7784 MST->getOffset(), Mask, MST->getMemoryVT(),
7785 MST->getMemOperand(), MST->getAddressingMode(),
7786 false, MST->isCompressingStore());
7787}
7788
7789SDValue DAGTypeLegalizer::WidenVecOp_MGATHER(SDNode *N, unsigned OpNo) {
7790 assert(OpNo == 4 && "Can widen only the index of mgather");
7791 auto *MG = cast<MaskedGatherSDNode>(N);
7792 SDValue DataOp = MG->getPassThru();
7793 SDValue Mask = MG->getMask();
7794 SDValue Scale = MG->getScale();
7795
7796 // Just widen the index. It's allowed to have extra elements.
7797 SDValue Index = GetWidenedVector(MG->getIndex());
7798
7799 SDLoc dl(N);
7800 SDValue Ops[] = {MG->getChain(), DataOp, Mask, MG->getBasePtr(), Index,
7801 Scale};
7802 SDValue Res = DAG.getMaskedGather(MG->getVTList(), MG->getMemoryVT(), dl, Ops,
7803 MG->getMemOperand(), MG->getIndexType(),
7804 MG->getExtensionType());
7805 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7806 ReplaceValueWith(SDValue(N, 0), Res.getValue(0));
7807 return SDValue();
7808}
7809
7810SDValue DAGTypeLegalizer::WidenVecOp_MSCATTER(SDNode *N, unsigned OpNo) {
7811 MaskedScatterSDNode *MSC = cast<MaskedScatterSDNode>(N);
7812 SDValue DataOp = MSC->getValue();
7813 SDValue Mask = MSC->getMask();
7814 SDValue Index = MSC->getIndex();
7815 SDValue Scale = MSC->getScale();
7816 EVT WideMemVT = MSC->getMemoryVT();
7817
7818 if (OpNo == 1) {
7819 DataOp = GetWidenedVector(DataOp);
7820 unsigned NumElts = DataOp.getValueType().getVectorNumElements();
7821
7822 // Widen index.
7823 EVT IndexVT = Index.getValueType();
7824 EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
7825 IndexVT.getVectorElementType(), NumElts);
7826 Index = ModifyToType(Index, WideIndexVT);
7827
7828 // The mask should be widened as well.
7829 EVT MaskVT = Mask.getValueType();
7830 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
7831 MaskVT.getVectorElementType(), NumElts);
7832 Mask = ModifyToType(Mask, WideMaskVT, true);
7833
7834 // Widen the MemoryType
7835 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
7836 MSC->getMemoryVT().getScalarType(), NumElts);
7837 } else if (OpNo == 4) {
7838 // Just widen the index. It's allowed to have extra elements.
7839 Index = GetWidenedVector(Index);
7840 } else
7841 llvm_unreachable("Can't widen this operand of mscatter");
7842
7843 SDValue Ops[] = {MSC->getChain(), DataOp, Mask, MSC->getBasePtr(), Index,
7844 Scale};
7845 return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N),
7846 Ops, MSC->getMemOperand(), MSC->getIndexType(),
7847 MSC->isTruncatingStore());
7848}
7849
7850SDValue DAGTypeLegalizer::WidenVecOp_VP_SCATTER(SDNode *N, unsigned OpNo) {
7851 VPScatterSDNode *VPSC = cast<VPScatterSDNode>(N);
7852 SDValue DataOp = VPSC->getValue();
7853 SDValue Mask = VPSC->getMask();
7854 SDValue Index = VPSC->getIndex();
7855 SDValue Scale = VPSC->getScale();
7856 EVT WideMemVT = VPSC->getMemoryVT();
7857
7858 if (OpNo == 1) {
7859 DataOp = GetWidenedVector(DataOp);
7860 Index = GetWidenedVector(Index);
7861 const auto WideEC = DataOp.getValueType().getVectorElementCount();
7862 Mask = GetWidenedMask(Mask, WideEC);
7863 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
7864 VPSC->getMemoryVT().getScalarType(), WideEC);
7865 } else if (OpNo == 3) {
7866 // Just widen the index. It's allowed to have extra elements.
7867 Index = GetWidenedVector(Index);
7868 } else
7869 llvm_unreachable("Can't widen this operand of VP_SCATTER");
7870
7871 SDValue Ops[] = {
7872 VPSC->getChain(), DataOp, VPSC->getBasePtr(), Index, Scale, Mask,
7873 VPSC->getVectorLength()};
7874 return DAG.getScatterVP(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N), Ops,
7875 VPSC->getMemOperand(), VPSC->getIndexType());
7876}
7877
7878SDValue DAGTypeLegalizer::WidenVecOp_SETCC(SDNode *N) {
7879 SDValue InOp0 = GetWidenedVector(N->getOperand(0));
7880 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
7881 SDLoc dl(N);
7882 EVT VT = N->getValueType(0);
7883
7884 // WARNING: In this code we widen the compare instruction with garbage.
7885 // This garbage may contain denormal floats which may be slow. Is this a real
7886 // concern ? Should we zero the unused lanes if this is a float compare ?
7887
7888 // Get a new SETCC node to compare the newly widened operands.
7889 // Only some of the compared elements are legal.
7890 EVT SVT = getSetCCResultType(InOp0.getValueType());
7891 // The result type is legal, if its vXi1, keep vXi1 for the new SETCC.
7892 if (VT.getScalarType() == MVT::i1)
7893 SVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
7894 SVT.getVectorElementCount());
7895
7896 SDValue WideSETCC = DAG.getNode(ISD::SETCC, SDLoc(N),
7897 SVT, InOp0, InOp1, N->getOperand(2));
7898
7899 // Extract the needed results from the result vector.
7900 EVT ResVT = EVT::getVectorVT(*DAG.getContext(),
7903 SDValue CC = DAG.getExtractSubvector(dl, ResVT, WideSETCC, 0);
7904
7905 EVT OpVT = N->getOperand(0).getValueType();
7906 ISD::NodeType ExtendCode =
7907 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
7908 return DAG.getNode(ExtendCode, dl, VT, CC);
7909}
7910
7911SDValue DAGTypeLegalizer::WidenVecOp_STRICT_FSETCC(SDNode *N) {
7912 SDValue Chain = N->getOperand(0);
7913 SDValue LHS = GetWidenedVector(N->getOperand(1));
7914 SDValue RHS = GetWidenedVector(N->getOperand(2));
7915 SDValue CC = N->getOperand(3);
7916 SDLoc dl(N);
7917
7918 EVT VT = N->getValueType(0);
7919 EVT EltVT = VT.getVectorElementType();
7920 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
7921 unsigned NumElts = VT.getVectorNumElements();
7922
7923 // Unroll into a build vector.
7924 SmallVector<SDValue, 8> Scalars(NumElts);
7925 SmallVector<SDValue, 8> Chains(NumElts);
7926
7927 for (unsigned i = 0; i != NumElts; ++i) {
7928 SDValue LHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, LHS, i);
7929 SDValue RHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, RHS, i);
7930
7931 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
7932 {Chain, LHSElem, RHSElem, CC});
7933 Chains[i] = Scalars[i].getValue(1);
7934 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
7935 DAG.getBoolConstant(true, dl, EltVT, VT),
7936 DAG.getBoolConstant(false, dl, EltVT, VT));
7937 }
7938
7939 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
7940 ReplaceValueWith(SDValue(N, 1), NewChain);
7941
7942 return DAG.getBuildVector(VT, dl, Scalars);
7943}
7944
7945static unsigned getExtendForIntVecReduction(unsigned Opc) {
7946 switch (Opc) {
7947 default:
7948 llvm_unreachable("Expected integer vector reduction");
7949 case ISD::VECREDUCE_ADD:
7950 case ISD::VECREDUCE_MUL:
7951 case ISD::VECREDUCE_AND:
7952 case ISD::VECREDUCE_OR:
7953 case ISD::VECREDUCE_XOR:
7954 return ISD::ANY_EXTEND;
7957 return ISD::SIGN_EXTEND;
7960 return ISD::ZERO_EXTEND;
7961 }
7962}
7963
7964SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE(SDNode *N) {
7965 SDLoc dl(N);
7966 SDValue Op = GetWidenedVector(N->getOperand(0));
7967 EVT VT = N->getValueType(0);
7968 EVT OrigVT = N->getOperand(0).getValueType();
7969 EVT WideVT = Op.getValueType();
7970 EVT ElemVT = OrigVT.getVectorElementType();
7971 SDNodeFlags Flags = N->getFlags();
7972
7973 unsigned Opc = N->getOpcode();
7974 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
7975 SDValue NeutralElem = DAG.getNeutralElement(BaseOpc, dl, ElemVT, Flags);
7976 assert(NeutralElem && "Neutral element must exist");
7977
7978 // Pad the vector with the neutral element.
7979 unsigned OrigElts = OrigVT.getVectorMinNumElements();
7980 unsigned WideElts = WideVT.getVectorMinNumElements();
7981
7982 // Generate a vp.reduce_op if it is custom/legal for the target. This avoids
7983 // needing to pad the source vector, because the inactive lanes can simply be
7984 // disabled and not contribute to the result.
7985 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opc);
7986 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WideVT)) {
7987 SDValue Start = NeutralElem;
7988 if (VT.isInteger())
7989 Start = DAG.getNode(getExtendForIntVecReduction(Opc), dl, VT, Start);
7990 assert(Start.getValueType() == VT);
7991 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
7992 WideVT.getVectorElementCount());
7993 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
7994 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
7995 OrigVT.getVectorElementCount());
7996 return DAG.getNode(*VPOpcode, dl, VT, {Start, Op, Mask, EVL}, Flags);
7997 }
7998
7999 if (WideVT.isScalableVector()) {
8000 unsigned GCD = std::gcd(OrigElts, WideElts);
8001 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
8003 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
8004 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
8005 Op = DAG.getInsertSubvector(dl, Op, SplatNeutral, Idx);
8006 return DAG.getNode(Opc, dl, VT, Op, Flags);
8007 }
8008
8009 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
8010 Op = DAG.getInsertVectorElt(dl, Op, NeutralElem, Idx);
8011
8012 return DAG.getNode(Opc, dl, VT, Op, Flags);
8013}
8014
8015SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE_SEQ(SDNode *N) {
8016 SDLoc dl(N);
8017 SDValue AccOp = N->getOperand(0);
8018 SDValue VecOp = N->getOperand(1);
8019 SDValue Op = GetWidenedVector(VecOp);
8020
8021 EVT VT = N->getValueType(0);
8022 EVT OrigVT = VecOp.getValueType();
8023 EVT WideVT = Op.getValueType();
8024 EVT ElemVT = OrigVT.getVectorElementType();
8025 SDNodeFlags Flags = N->getFlags();
8026
8027 unsigned Opc = N->getOpcode();
8028 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
8029 SDValue NeutralElem = DAG.getNeutralElement(BaseOpc, dl, ElemVT, Flags);
8030
8031 // Pad the vector with the neutral element.
8032 unsigned OrigElts = OrigVT.getVectorMinNumElements();
8033 unsigned WideElts = WideVT.getVectorMinNumElements();
8034
8035 // Generate a vp.reduce_op if it is custom/legal for the target. This avoids
8036 // needing to pad the source vector, because the inactive lanes can simply be
8037 // disabled and not contribute to the result.
8038 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opc);
8039 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WideVT)) {
8040 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8041 WideVT.getVectorElementCount());
8042 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
8043 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8044 OrigVT.getVectorElementCount());
8045 return DAG.getNode(*VPOpcode, dl, VT, {AccOp, Op, Mask, EVL}, Flags);
8046 }
8047
8048 if (WideVT.isScalableVector()) {
8049 unsigned GCD = std::gcd(OrigElts, WideElts);
8050 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
8052 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
8053 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
8054 Op = DAG.getInsertSubvector(dl, Op, SplatNeutral, Idx);
8055 return DAG.getNode(Opc, dl, VT, AccOp, Op, Flags);
8056 }
8057
8058 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
8059 Op = DAG.getInsertVectorElt(dl, Op, NeutralElem, Idx);
8060
8061 return DAG.getNode(Opc, dl, VT, AccOp, Op, Flags);
8062}
8063
8064SDValue DAGTypeLegalizer::WidenVecOp_VP_REDUCE(SDNode *N) {
8065 assert(N->isVPOpcode() && "Expected VP opcode");
8066
8067 SDLoc dl(N);
8068 SDValue Op = GetWidenedVector(N->getOperand(1));
8069 SDValue Mask = GetWidenedMask(N->getOperand(2),
8070 Op.getValueType().getVectorElementCount());
8071
8072 return DAG.getNode(N->getOpcode(), dl, N->getValueType(0),
8073 {N->getOperand(0), Op, Mask, N->getOperand(3)},
8074 N->getFlags());
8075}
8076
8077SDValue DAGTypeLegalizer::WidenVecOp_VSELECT(SDNode *N) {
8078 // This only gets called in the case that the left and right inputs and
8079 // result are of a legal odd vector type, and the condition is illegal i1 of
8080 // the same odd width that needs widening.
8081 EVT VT = N->getValueType(0);
8082 assert(VT.isVector() && !VT.isPow2VectorType() && isTypeLegal(VT));
8083
8084 SDValue Cond = GetWidenedVector(N->getOperand(0));
8085 SDValue LeftIn = DAG.WidenVector(N->getOperand(1), SDLoc(N));
8086 SDValue RightIn = DAG.WidenVector(N->getOperand(2), SDLoc(N));
8087 SDLoc DL(N);
8088
8089 SDValue Select = DAG.getNode(N->getOpcode(), DL, LeftIn.getValueType(), Cond,
8090 LeftIn, RightIn);
8091 return DAG.getExtractSubvector(DL, VT, Select, 0);
8092}
8093
8094SDValue DAGTypeLegalizer::WidenVecOp_VP_CttzElements(SDNode *N) {
8095 SDLoc DL(N);
8096 SDValue Source = GetWidenedVector(N->getOperand(0));
8097 EVT SrcVT = Source.getValueType();
8098 SDValue Mask =
8099 GetWidenedMask(N->getOperand(1), SrcVT.getVectorElementCount());
8100
8101 return DAG.getNode(N->getOpcode(), DL, N->getValueType(0),
8102 {Source, Mask, N->getOperand(2)}, N->getFlags());
8103}
8104
8105//===----------------------------------------------------------------------===//
8106// Vector Widening Utilities
8107//===----------------------------------------------------------------------===//
8108
8109// Utility function to find the type to chop up a widen vector for load/store
8110// TLI: Target lowering used to determine legal types.
8111// Width: Width left need to load/store.
8112// WidenVT: The widen vector type to load to/store from
8113// Align: If 0, don't allow use of a wider type
8114// WidenEx: If Align is not 0, the amount additional we can load/store from.
8115
8116static std::optional<EVT> findMemType(SelectionDAG &DAG,
8117 const TargetLowering &TLI, unsigned Width,
8118 EVT WidenVT, unsigned Align = 0,
8119 unsigned WidenEx = 0) {
8120 EVT WidenEltVT = WidenVT.getVectorElementType();
8121 const bool Scalable = WidenVT.isScalableVector();
8122 unsigned WidenWidth = WidenVT.getSizeInBits().getKnownMinValue();
8123 unsigned WidenEltWidth = WidenEltVT.getSizeInBits();
8124 unsigned AlignInBits = Align*8;
8125
8126 EVT RetVT = WidenEltVT;
8127 // Don't bother looking for an integer type if the vector is scalable, skip
8128 // to vector types.
8129 if (!Scalable) {
8130 // If we have one element to load/store, return it.
8131 if (Width == WidenEltWidth)
8132 return RetVT;
8133
8134 // See if there is larger legal integer than the element type to load/store.
8135 for (EVT MemVT : reverse(MVT::integer_valuetypes())) {
8136 unsigned MemVTWidth = MemVT.getSizeInBits();
8137 if (MemVT.getSizeInBits() <= WidenEltWidth)
8138 break;
8139 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
8140 if ((Action == TargetLowering::TypeLegal ||
8142 (WidenWidth % MemVTWidth) == 0 &&
8143 isPowerOf2_32(WidenWidth / MemVTWidth) &&
8144 (MemVTWidth <= Width ||
8145 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
8146 if (MemVTWidth == WidenWidth)
8147 return MemVT;
8148 RetVT = MemVT;
8149 break;
8150 }
8151 }
8152 }
8153
8154 // See if there is a larger vector type to load/store that has the same vector
8155 // element type and is evenly divisible with the WidenVT.
8156 for (EVT MemVT : reverse(MVT::vector_valuetypes())) {
8157 // Skip vector MVTs which don't match the scalable property of WidenVT.
8158 if (Scalable != MemVT.isScalableVector())
8159 continue;
8160 unsigned MemVTWidth = MemVT.getSizeInBits().getKnownMinValue();
8161 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
8162 if ((Action == TargetLowering::TypeLegal ||
8164 WidenEltVT == MemVT.getVectorElementType() &&
8165 (WidenWidth % MemVTWidth) == 0 &&
8166 isPowerOf2_32(WidenWidth / MemVTWidth) &&
8167 (MemVTWidth <= Width ||
8168 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
8169 if (RetVT.getFixedSizeInBits() < MemVTWidth || MemVT == WidenVT)
8170 return MemVT;
8171 }
8172 }
8173
8174 // Using element-wise loads and stores for widening operations is not
8175 // supported for scalable vectors
8176 if (Scalable)
8177 return std::nullopt;
8178
8179 return RetVT;
8180}
8181
8182// Builds a vector type from scalar loads
8183// VecTy: Resulting Vector type
8184// LDOps: Load operators to build a vector type
8185// [Start,End) the list of loads to use.
8188 unsigned Start, unsigned End) {
8189 SDLoc dl(LdOps[Start]);
8190 EVT LdTy = LdOps[Start].getValueType();
8191 unsigned Width = VecTy.getSizeInBits();
8192 unsigned NumElts = Width / LdTy.getSizeInBits();
8193 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), LdTy, NumElts);
8194
8195 unsigned Idx = 1;
8196 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT,LdOps[Start]);
8197
8198 for (unsigned i = Start + 1; i != End; ++i) {
8199 EVT NewLdTy = LdOps[i].getValueType();
8200 if (NewLdTy != LdTy) {
8201 NumElts = Width / NewLdTy.getSizeInBits();
8202 NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewLdTy, NumElts);
8203 VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, VecOp);
8204 // Readjust position and vector position based on new load type.
8205 Idx = Idx * LdTy.getSizeInBits() / NewLdTy.getSizeInBits();
8206 LdTy = NewLdTy;
8207 }
8208 VecOp = DAG.getInsertVectorElt(dl, VecOp, LdOps[i], Idx++);
8209 }
8210 return DAG.getNode(ISD::BITCAST, dl, VecTy, VecOp);
8211}
8212
8213SDValue DAGTypeLegalizer::GenWidenVectorLoads(SmallVectorImpl<SDValue> &LdChain,
8214 LoadSDNode *LD) {
8215 // The strategy assumes that we can efficiently load power-of-two widths.
8216 // The routine chops the vector into the largest vector loads with the same
8217 // element type or scalar loads and then recombines it to the widen vector
8218 // type.
8219 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
8220 EVT LdVT = LD->getMemoryVT();
8221 SDLoc dl(LD);
8222 assert(LdVT.isVector() && WidenVT.isVector());
8223 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
8225
8226 // Load information
8227 SDValue Chain = LD->getChain();
8228 SDValue BasePtr = LD->getBasePtr();
8229 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
8230 AAMDNodes AAInfo = LD->getAAInfo();
8231
8232 TypeSize LdWidth = LdVT.getSizeInBits();
8233 TypeSize WidenWidth = WidenVT.getSizeInBits();
8234 TypeSize WidthDiff = WidenWidth - LdWidth;
8235 // Allow wider loads if they are sufficiently aligned to avoid memory faults
8236 // and if the original load is simple.
8237 unsigned LdAlign =
8238 (!LD->isSimple() || LdVT.isScalableVector()) ? 0 : LD->getAlign().value();
8239
8240 // Find the vector type that can load from.
8241 std::optional<EVT> FirstVT =
8242 findMemType(DAG, TLI, LdWidth.getKnownMinValue(), WidenVT, LdAlign,
8243 WidthDiff.getKnownMinValue());
8244
8245 if (!FirstVT)
8246 return SDValue();
8247
8248 SmallVector<EVT, 8> MemVTs;
8249 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
8250
8251 // Unless we're able to load in one instruction we must work out how to load
8252 // the remainder.
8253 if (!TypeSize::isKnownLE(LdWidth, FirstVTWidth)) {
8254 std::optional<EVT> NewVT = FirstVT;
8255 TypeSize RemainingWidth = LdWidth;
8256 TypeSize NewVTWidth = FirstVTWidth;
8257 do {
8258 RemainingWidth -= NewVTWidth;
8259 if (TypeSize::isKnownLT(RemainingWidth, NewVTWidth)) {
8260 // The current type we are using is too large. Find a better size.
8261 NewVT = findMemType(DAG, TLI, RemainingWidth.getKnownMinValue(),
8262 WidenVT, LdAlign, WidthDiff.getKnownMinValue());
8263 if (!NewVT)
8264 return SDValue();
8265 NewVTWidth = NewVT->getSizeInBits();
8266 }
8267 MemVTs.push_back(*NewVT);
8268 } while (TypeSize::isKnownGT(RemainingWidth, NewVTWidth));
8269 }
8270
8271 SDValue LdOp = DAG.getLoad(*FirstVT, dl, Chain, BasePtr, LD->getPointerInfo(),
8272 LD->getBaseAlign(), MMOFlags, AAInfo);
8273 LdChain.push_back(LdOp.getValue(1));
8274
8275 // Check if we can load the element with one instruction.
8276 if (MemVTs.empty()) {
8277 assert(TypeSize::isKnownLE(LdWidth, FirstVTWidth));
8278 if (!FirstVT->isVector()) {
8279 unsigned NumElts =
8280 WidenWidth.getFixedValue() / FirstVTWidth.getFixedValue();
8281 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), *FirstVT, NumElts);
8282 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT, LdOp);
8283 return DAG.getNode(ISD::BITCAST, dl, WidenVT, VecOp);
8284 }
8285 if (FirstVT == WidenVT)
8286 return LdOp;
8287
8288 // TODO: We don't currently have any tests that exercise this code path.
8289 assert(WidenWidth.getFixedValue() % FirstVTWidth.getFixedValue() == 0);
8290 unsigned NumConcat =
8291 WidenWidth.getFixedValue() / FirstVTWidth.getFixedValue();
8292 SmallVector<SDValue, 16> ConcatOps(NumConcat);
8293 SDValue UndefVal = DAG.getUNDEF(*FirstVT);
8294 ConcatOps[0] = LdOp;
8295 for (unsigned i = 1; i != NumConcat; ++i)
8296 ConcatOps[i] = UndefVal;
8297 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, ConcatOps);
8298 }
8299
8300 // Load vector by using multiple loads from largest vector to scalar.
8302 LdOps.push_back(LdOp);
8303
8304 uint64_t ScaledOffset = 0;
8305 MachinePointerInfo MPI = LD->getPointerInfo();
8306
8307 // First incremement past the first load.
8308 IncrementPointer(cast<LoadSDNode>(LdOp), *FirstVT, MPI, BasePtr,
8309 &ScaledOffset);
8310
8311 for (EVT MemVT : MemVTs) {
8312 Align NewAlign = ScaledOffset == 0
8313 ? LD->getBaseAlign()
8314 : commonAlignment(LD->getAlign(), ScaledOffset);
8315 SDValue L =
8316 DAG.getLoad(MemVT, dl, Chain, BasePtr, MPI, NewAlign, MMOFlags, AAInfo);
8317
8318 LdOps.push_back(L);
8319 LdChain.push_back(L.getValue(1));
8320 IncrementPointer(cast<LoadSDNode>(L), MemVT, MPI, BasePtr, &ScaledOffset);
8321 }
8322
8323 // Build the vector from the load operations.
8324 unsigned End = LdOps.size();
8325 if (!LdOps[0].getValueType().isVector())
8326 // All the loads are scalar loads.
8327 return BuildVectorFromScalar(DAG, WidenVT, LdOps, 0, End);
8328
8329 // If the load contains vectors, build the vector using concat vector.
8330 // All of the vectors used to load are power-of-2, and the scalar loads can be
8331 // combined to make a power-of-2 vector.
8332 SmallVector<SDValue, 16> ConcatOps(End);
8333 int i = End - 1;
8334 int Idx = End;
8335 EVT LdTy = LdOps[i].getValueType();
8336 // First, combine the scalar loads to a vector.
8337 if (!LdTy.isVector()) {
8338 for (--i; i >= 0; --i) {
8339 LdTy = LdOps[i].getValueType();
8340 if (LdTy.isVector())
8341 break;
8342 }
8343 ConcatOps[--Idx] = BuildVectorFromScalar(DAG, LdTy, LdOps, i + 1, End);
8344 }
8345
8346 ConcatOps[--Idx] = LdOps[i];
8347 for (--i; i >= 0; --i) {
8348 EVT NewLdTy = LdOps[i].getValueType();
8349 if (NewLdTy != LdTy) {
8350 // Create a larger vector.
8351 TypeSize LdTySize = LdTy.getSizeInBits();
8352 TypeSize NewLdTySize = NewLdTy.getSizeInBits();
8353 assert(NewLdTySize.isScalable() == LdTySize.isScalable() &&
8354 NewLdTySize.isKnownMultipleOf(LdTySize.getKnownMinValue()));
8355 unsigned NumOps =
8356 NewLdTySize.getKnownMinValue() / LdTySize.getKnownMinValue();
8358 unsigned j = 0;
8359 for (; j != End-Idx; ++j)
8360 WidenOps[j] = ConcatOps[Idx+j];
8361 for (; j != NumOps; ++j)
8362 WidenOps[j] = DAG.getUNDEF(LdTy);
8363
8364 ConcatOps[End-1] = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewLdTy,
8365 WidenOps);
8366 Idx = End - 1;
8367 LdTy = NewLdTy;
8368 }
8369 ConcatOps[--Idx] = LdOps[i];
8370 }
8371
8372 if (WidenWidth == LdTy.getSizeInBits() * (End - Idx))
8373 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
8374 ArrayRef(&ConcatOps[Idx], End - Idx));
8375
8376 // We need to fill the rest with undefs to build the vector.
8377 unsigned NumOps =
8378 WidenWidth.getKnownMinValue() / LdTy.getSizeInBits().getKnownMinValue();
8380 SDValue UndefVal = DAG.getUNDEF(LdTy);
8381 {
8382 unsigned i = 0;
8383 for (; i != End-Idx; ++i)
8384 WidenOps[i] = ConcatOps[Idx+i];
8385 for (; i != NumOps; ++i)
8386 WidenOps[i] = UndefVal;
8387 }
8388 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, WidenOps);
8389}
8390
8391SDValue
8392DAGTypeLegalizer::GenWidenVectorExtLoads(SmallVectorImpl<SDValue> &LdChain,
8393 LoadSDNode *LD,
8394 ISD::LoadExtType ExtType) {
8395 // For extension loads, it may not be more efficient to chop up the vector
8396 // and then extend it. Instead, we unroll the load and build a new vector.
8397 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
8398 EVT LdVT = LD->getMemoryVT();
8399 SDLoc dl(LD);
8400 assert(LdVT.isVector() && WidenVT.isVector());
8401 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
8402
8403 // Load information
8404 SDValue Chain = LD->getChain();
8405 SDValue BasePtr = LD->getBasePtr();
8406 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
8407 AAMDNodes AAInfo = LD->getAAInfo();
8408
8409 if (LdVT.isScalableVector())
8410 return SDValue();
8411
8412 EVT EltVT = WidenVT.getVectorElementType();
8413 EVT LdEltVT = LdVT.getVectorElementType();
8414 unsigned NumElts = LdVT.getVectorNumElements();
8415
8416 // Load each element and widen.
8417 unsigned WidenNumElts = WidenVT.getVectorNumElements();
8418 SmallVector<SDValue, 16> Ops(WidenNumElts);
8419 unsigned Increment = LdEltVT.getSizeInBits() / 8;
8420 Ops[0] =
8421 DAG.getExtLoad(ExtType, dl, EltVT, Chain, BasePtr, LD->getPointerInfo(),
8422 LdEltVT, LD->getBaseAlign(), MMOFlags, AAInfo);
8423 LdChain.push_back(Ops[0].getValue(1));
8424 unsigned i = 0, Offset = Increment;
8425 for (i=1; i < NumElts; ++i, Offset += Increment) {
8426 SDValue NewBasePtr =
8427 DAG.getObjectPtrOffset(dl, BasePtr, TypeSize::getFixed(Offset));
8428 Ops[i] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, NewBasePtr,
8429 LD->getPointerInfo().getWithOffset(Offset), LdEltVT,
8430 LD->getBaseAlign(), MMOFlags, AAInfo);
8431 LdChain.push_back(Ops[i].getValue(1));
8432 }
8433
8434 // Fill the rest with undefs.
8435 SDValue UndefVal = DAG.getUNDEF(EltVT);
8436 for (; i != WidenNumElts; ++i)
8437 Ops[i] = UndefVal;
8438
8439 return DAG.getBuildVector(WidenVT, dl, Ops);
8440}
8441
8442bool DAGTypeLegalizer::GenWidenVectorStores(SmallVectorImpl<SDValue> &StChain,
8443 StoreSDNode *ST) {
8444 // The strategy assumes that we can efficiently store power-of-two widths.
8445 // The routine chops the vector into the largest vector stores with the same
8446 // element type or scalar stores.
8447 SDValue Chain = ST->getChain();
8448 SDValue BasePtr = ST->getBasePtr();
8449 MachineMemOperand::Flags MMOFlags = ST->getMemOperand()->getFlags();
8450 AAMDNodes AAInfo = ST->getAAInfo();
8451 SDValue ValOp = GetWidenedVector(ST->getValue());
8452 SDLoc dl(ST);
8453
8454 EVT StVT = ST->getMemoryVT();
8455 TypeSize StWidth = StVT.getSizeInBits();
8456 EVT ValVT = ValOp.getValueType();
8457 TypeSize ValWidth = ValVT.getSizeInBits();
8458 EVT ValEltVT = ValVT.getVectorElementType();
8459 unsigned ValEltWidth = ValEltVT.getFixedSizeInBits();
8460 assert(StVT.getVectorElementType() == ValEltVT);
8461 assert(StVT.isScalableVector() == ValVT.isScalableVector() &&
8462 "Mismatch between store and value types");
8463
8464 int Idx = 0; // current index to store
8465
8466 MachinePointerInfo MPI = ST->getPointerInfo();
8467 uint64_t ScaledOffset = 0;
8468
8469 // A breakdown of how to widen this vector store. Each element of the vector
8470 // is a memory VT combined with the number of times it is to be stored to,
8471 // e,g., v5i32 -> {{v2i32,2},{i32,1}}
8473
8474 while (StWidth.isNonZero()) {
8475 // Find the largest vector type we can store with.
8476 std::optional<EVT> NewVT =
8477 findMemType(DAG, TLI, StWidth.getKnownMinValue(), ValVT);
8478 if (!NewVT)
8479 return false;
8480 MemVTs.push_back({*NewVT, 0});
8481 TypeSize NewVTWidth = NewVT->getSizeInBits();
8482
8483 do {
8484 StWidth -= NewVTWidth;
8485 MemVTs.back().second++;
8486 } while (StWidth.isNonZero() && TypeSize::isKnownGE(StWidth, NewVTWidth));
8487 }
8488
8489 for (const auto &Pair : MemVTs) {
8490 EVT NewVT = Pair.first;
8491 unsigned Count = Pair.second;
8492 TypeSize NewVTWidth = NewVT.getSizeInBits();
8493
8494 if (NewVT.isVector()) {
8495 unsigned NumVTElts = NewVT.getVectorMinNumElements();
8496 do {
8497 Align NewAlign = ScaledOffset == 0
8498 ? ST->getBaseAlign()
8499 : commonAlignment(ST->getAlign(), ScaledOffset);
8500 SDValue EOp = DAG.getExtractSubvector(dl, NewVT, ValOp, Idx);
8501 SDValue PartStore = DAG.getStore(Chain, dl, EOp, BasePtr, MPI, NewAlign,
8502 MMOFlags, AAInfo);
8503 StChain.push_back(PartStore);
8504
8505 Idx += NumVTElts;
8506 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr,
8507 &ScaledOffset);
8508 } while (--Count);
8509 } else {
8510 // Cast the vector to the scalar type we can store.
8511 unsigned NumElts = ValWidth.getFixedValue() / NewVTWidth.getFixedValue();
8512 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewVT, NumElts);
8513 SDValue VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, ValOp);
8514 // Readjust index position based on new vector type.
8515 Idx = Idx * ValEltWidth / NewVTWidth.getFixedValue();
8516 do {
8517 SDValue EOp = DAG.getExtractVectorElt(dl, NewVT, VecOp, Idx++);
8518 SDValue PartStore = DAG.getStore(Chain, dl, EOp, BasePtr, MPI,
8519 ST->getBaseAlign(), MMOFlags, AAInfo);
8520 StChain.push_back(PartStore);
8521
8522 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr);
8523 } while (--Count);
8524 // Restore index back to be relative to the original widen element type.
8525 Idx = Idx * NewVTWidth.getFixedValue() / ValEltWidth;
8526 }
8527 }
8528
8529 return true;
8530}
8531
8532/// Modifies a vector input (widen or narrows) to a vector of NVT. The
8533/// input vector must have the same element type as NVT.
8534/// FillWithZeroes specifies that the vector should be widened with zeroes.
8535SDValue DAGTypeLegalizer::ModifyToType(SDValue InOp, EVT NVT,
8536 bool FillWithZeroes) {
8537 // Note that InOp might have been widened so it might already have
8538 // the right width or it might need be narrowed.
8539 EVT InVT = InOp.getValueType();
8541 "input and widen element type must match");
8542 assert(InVT.isScalableVector() == NVT.isScalableVector() &&
8543 "cannot modify scalable vectors in this way");
8544 SDLoc dl(InOp);
8545
8546 // Check if InOp already has the right width.
8547 if (InVT == NVT)
8548 return InOp;
8549
8550 ElementCount InEC = InVT.getVectorElementCount();
8551 ElementCount WidenEC = NVT.getVectorElementCount();
8552 if (WidenEC.hasKnownScalarFactor(InEC)) {
8553 unsigned NumConcat = WidenEC.getKnownScalarFactor(InEC);
8554 SmallVector<SDValue, 16> Ops(NumConcat);
8555 SDValue FillVal = FillWithZeroes ? DAG.getConstant(0, dl, InVT) :
8556 DAG.getUNDEF(InVT);
8557 Ops[0] = InOp;
8558 for (unsigned i = 1; i != NumConcat; ++i)
8559 Ops[i] = FillVal;
8560
8561 return DAG.getNode(ISD::CONCAT_VECTORS, dl, NVT, Ops);
8562 }
8563
8564 if (InEC.hasKnownScalarFactor(WidenEC))
8565 return DAG.getExtractSubvector(dl, NVT, InOp, 0);
8566
8567 assert(!InVT.isScalableVector() && !NVT.isScalableVector() &&
8568 "Scalable vectors should have been handled already.");
8569
8570 unsigned InNumElts = InEC.getFixedValue();
8571 unsigned WidenNumElts = WidenEC.getFixedValue();
8572
8573 // Fall back to extract and build (+ mask, if padding with zeros).
8574 SmallVector<SDValue, 16> Ops(WidenNumElts);
8575 EVT EltVT = NVT.getVectorElementType();
8576 unsigned MinNumElts = std::min(WidenNumElts, InNumElts);
8577 unsigned Idx;
8578 for (Idx = 0; Idx < MinNumElts; ++Idx)
8579 Ops[Idx] = DAG.getExtractVectorElt(dl, EltVT, InOp, Idx);
8580
8581 SDValue UndefVal = DAG.getUNDEF(EltVT);
8582 for (; Idx < WidenNumElts; ++Idx)
8583 Ops[Idx] = UndefVal;
8584
8585 SDValue Widened = DAG.getBuildVector(NVT, dl, Ops);
8586 if (!FillWithZeroes)
8587 return Widened;
8588
8589 assert(NVT.isInteger() &&
8590 "We expect to never want to FillWithZeroes for non-integral types.");
8591
8593 MaskOps.append(MinNumElts, DAG.getAllOnesConstant(dl, EltVT));
8594 MaskOps.append(WidenNumElts - MinNumElts, DAG.getConstant(0, dl, EltVT));
8595
8596 return DAG.getNode(ISD::AND, dl, NVT, Widened,
8597 DAG.getBuildVector(NVT, dl, MaskOps));
8598}
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:807
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
Definition ISDOpcodes.h:256
@ CTLZ_ZERO_UNDEF
Definition ISDOpcodes.h:780
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
Definition ISDOpcodes.h:504
@ POISON
POISON - A poison node.
Definition ISDOpcodes.h:231
@ 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:593
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:771
@ SMULFIX
RESULT = [US]MULFIX(LHS, RHS, SCALE) - Perform fixed point multiplication on 2 integers with the same...
Definition ISDOpcodes.h:387
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:259
@ 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:393
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition ISDOpcodes.h:841
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
Definition ISDOpcodes.h:511
@ 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:868
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
Definition ISDOpcodes.h:577
@ VECREDUCE_FMAX
FMIN/FMAX nodes can have flags, for NaN/NoNaN variants.
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:410
@ 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:744
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
Definition ISDOpcodes.h:898
@ FPTRUNC_ROUND
FPTRUNC_ROUND - This corresponds to the fptrunc_round intrinsic.
Definition ISDOpcodes.h:508
@ 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:981
@ 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:400
@ PARTIAL_REDUCE_UMLA
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:832
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
Definition ISDOpcodes.h:712
@ STRICT_UINT_TO_FP
Definition ISDOpcodes.h:478
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
Definition ISDOpcodes.h:662
@ 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:779
@ 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:628
@ STEP_VECTOR
STEP_VECTOR(IMM) - Returns a scalable vector whose lanes are comprised of a linear sequence of unsign...
Definition ISDOpcodes.h:688
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
Definition ISDOpcodes.h:534
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
Definition ISDOpcodes.h:541
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
Definition ISDOpcodes.h:369
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:784
@ 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:669
@ 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:701
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:762
@ AssertNoFPClass
AssertNoFPClass - These nodes record if a register contains a float value that is known to be not som...
Definition ISDOpcodes.h:78
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition ISDOpcodes.h:642
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition ISDOpcodes.h:607
@ 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:569
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:838
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:799
@ 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:379
@ SMULO
Same for multiplication.
Definition ISDOpcodes.h:351
@ ANY_EXTEND_VECTOR_INREG
ANY_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register any-extension of the low la...
Definition ISDOpcodes.h:887
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition ISDOpcodes.h:876
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:724
@ VECTOR_REVERSE
VECTOR_REVERSE(VECTOR) - Returns a vector, of the same type as VECTOR, whose elements are shuffled us...
Definition ISDOpcodes.h:633
@ SDIVFIXSAT
Same as the corresponding unsaturated fixed point instructions, but the result is clamped between the...
Definition ISDOpcodes.h:406
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:966
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition ISDOpcodes.h:793
@ STRICT_SINT_TO_FP
STRICT_[US]INT_TO_FP - Convert a signed or unsigned integer to a floating point value.
Definition ISDOpcodes.h:477
@ MGATHER
Masked gather and scatter - load and store operations for a vector of random addresses with additiona...
@ STRICT_FP_TO_UINT
Definition ISDOpcodes.h:471
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
Definition ISDOpcodes.h:493
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:470
@ 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:914
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:498
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:736
@ SCMP
[US]CMP - 3-way comparison of signed or unsigned integers.
Definition ISDOpcodes.h:732
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
Definition ISDOpcodes.h:707
@ FREEZE
FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or is evaluated to UNDEF),...
Definition ISDOpcodes.h:236
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
Definition ISDOpcodes.h:558
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition ISDOpcodes.h:53
@ VECTOR_SPLICE
VECTOR_SPLICE(VEC1, VEC2, IMM) - Returns a subvector of the same type as VEC1/VEC2 from CONCAT_VECTOR...
Definition ISDOpcodes.h:654
@ 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:947
@ VECTOR_COMPRESS
VECTOR_COMPRESS(Vec, Mask, Passthru) consecutively place vector elements based on mask e....
Definition ISDOpcodes.h:696
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
Definition ISDOpcodes.h:909
@ ADDRSPACECAST
ADDRSPACECAST - This operator converts between pointers of different address spaces.
Definition ISDOpcodes.h:985
@ 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:933
@ VECREDUCE_FMINIMUM
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:844
@ 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:527
@ 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:617
@ 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:719
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition ISDOpcodes.h:549
@ LOOP_DEPENDENCE_WAR_MASK
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:1772
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:1856
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:1779
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1918
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.