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 // We store LoVec and then insert HiVec starting at offset=|1s| in LoMask.
2685 SDValue WideMask =
2686 DAG.getNode(ISD::ZERO_EXTEND, DL, LoMask.getValueType(), LoMask);
2687 SDValue Offset = DAG.getNode(ISD::VECREDUCE_ADD, DL, MVT::i32, WideMask);
2688 Offset = TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Offset);
2689
2690 SDValue Chain = DAG.getEntryNode();
2691 Chain = DAG.getStore(Chain, DL, Lo, StackPtr, PtrInfo);
2692 Chain = DAG.getStore(Chain, DL, Hi, Offset,
2694
2695 SDValue Compressed = DAG.getLoad(VecVT, DL, Chain, StackPtr, PtrInfo);
2696 if (!Passthru.isUndef()) {
2697 Compressed =
2698 DAG.getNode(ISD::VSELECT, DL, VecVT, Mask, Compressed, Passthru);
2699 }
2700 std::tie(Lo, Hi) = DAG.SplitVector(Compressed, DL);
2701}
2702
2703void DAGTypeLegalizer::SplitVecRes_SETCC(SDNode *N, SDValue &Lo, SDValue &Hi) {
2704 assert(N->getValueType(0).isVector() &&
2705 N->getOperand(0).getValueType().isVector() &&
2706 "Operand types must be vectors");
2707
2708 EVT LoVT, HiVT;
2709 SDLoc DL(N);
2710 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2711
2712 // If the input also splits, handle it directly. Otherwise split it by hand.
2713 SDValue LL, LH, RL, RH;
2714 if (getTypeAction(N->getOperand(0).getValueType()) ==
2716 GetSplitVector(N->getOperand(0), LL, LH);
2717 else
2718 std::tie(LL, LH) = DAG.SplitVectorOperand(N, 0);
2719
2720 if (getTypeAction(N->getOperand(1).getValueType()) ==
2722 GetSplitVector(N->getOperand(1), RL, RH);
2723 else
2724 std::tie(RL, RH) = DAG.SplitVectorOperand(N, 1);
2725
2726 if (N->getOpcode() == ISD::SETCC) {
2727 Lo = DAG.getNode(N->getOpcode(), DL, LoVT, LL, RL, N->getOperand(2));
2728 Hi = DAG.getNode(N->getOpcode(), DL, HiVT, LH, RH, N->getOperand(2));
2729 } else {
2730 assert(N->getOpcode() == ISD::VP_SETCC && "Expected VP_SETCC opcode");
2731 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
2732 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(3));
2733 std::tie(EVLLo, EVLHi) =
2734 DAG.SplitEVL(N->getOperand(4), N->getValueType(0), DL);
2735 Lo = DAG.getNode(N->getOpcode(), DL, LoVT, LL, RL, N->getOperand(2), MaskLo,
2736 EVLLo);
2737 Hi = DAG.getNode(N->getOpcode(), DL, HiVT, LH, RH, N->getOperand(2), MaskHi,
2738 EVLHi);
2739 }
2740}
2741
2742void DAGTypeLegalizer::SplitVecRes_UnaryOp(SDNode *N, SDValue &Lo,
2743 SDValue &Hi) {
2744 // Get the dest types - they may not match the input types, e.g. int_to_fp.
2745 EVT LoVT, HiVT;
2746 SDLoc dl(N);
2747 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2748
2749 // If the input also splits, handle it directly for a compile time speedup.
2750 // Otherwise split it by hand.
2751 EVT InVT = N->getOperand(0).getValueType();
2752 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
2753 GetSplitVector(N->getOperand(0), Lo, Hi);
2754 else
2755 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
2756
2757 const SDNodeFlags Flags = N->getFlags();
2758 unsigned Opcode = N->getOpcode();
2759 if (N->getNumOperands() <= 2) {
2760 if (Opcode == ISD::FP_ROUND || Opcode == ISD::AssertNoFPClass) {
2761 Lo = DAG.getNode(Opcode, dl, LoVT, Lo, N->getOperand(1), Flags);
2762 Hi = DAG.getNode(Opcode, dl, HiVT, Hi, N->getOperand(1), Flags);
2763 } else {
2764 Lo = DAG.getNode(Opcode, dl, LoVT, Lo, Flags);
2765 Hi = DAG.getNode(Opcode, dl, HiVT, Hi, Flags);
2766 }
2767 return;
2768 }
2769
2770 assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
2771 assert(N->isVPOpcode() && "Expected VP opcode");
2772
2773 SDValue MaskLo, MaskHi;
2774 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
2775
2776 SDValue EVLLo, EVLHi;
2777 std::tie(EVLLo, EVLHi) =
2778 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), dl);
2779
2780 Lo = DAG.getNode(Opcode, dl, LoVT, {Lo, MaskLo, EVLLo}, Flags);
2781 Hi = DAG.getNode(Opcode, dl, HiVT, {Hi, MaskHi, EVLHi}, Flags);
2782}
2783
2784void DAGTypeLegalizer::SplitVecRes_ADDRSPACECAST(SDNode *N, SDValue &Lo,
2785 SDValue &Hi) {
2786 SDLoc dl(N);
2787 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(N->getValueType(0));
2788
2789 // If the input also splits, handle it directly for a compile time speedup.
2790 // Otherwise split it by hand.
2791 EVT InVT = N->getOperand(0).getValueType();
2792 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
2793 GetSplitVector(N->getOperand(0), Lo, Hi);
2794 else
2795 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
2796
2797 auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
2798 unsigned SrcAS = AddrSpaceCastN->getSrcAddressSpace();
2799 unsigned DestAS = AddrSpaceCastN->getDestAddressSpace();
2800 Lo = DAG.getAddrSpaceCast(dl, LoVT, Lo, SrcAS, DestAS);
2801 Hi = DAG.getAddrSpaceCast(dl, HiVT, Hi, SrcAS, DestAS);
2802}
2803
2804void DAGTypeLegalizer::SplitVecRes_UnaryOpWithTwoResults(SDNode *N,
2805 unsigned ResNo,
2806 SDValue &Lo,
2807 SDValue &Hi) {
2808 SDLoc dl(N);
2809 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(N->getValueType(0));
2810 auto [LoVT1, HiVT1] = DAG.GetSplitDestVTs(N->getValueType(1));
2811
2812 // If the input also splits, handle it directly for a compile time speedup.
2813 // Otherwise split it by hand.
2814 EVT InVT = N->getOperand(0).getValueType();
2815 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
2816 GetSplitVector(N->getOperand(0), Lo, Hi);
2817 else
2818 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
2819
2820 Lo = DAG.getNode(N->getOpcode(), dl, {LoVT, LoVT1}, Lo, N->getFlags());
2821 Hi = DAG.getNode(N->getOpcode(), dl, {HiVT, HiVT1}, Hi, N->getFlags());
2822
2823 SDNode *HiNode = Hi.getNode();
2824 SDNode *LoNode = Lo.getNode();
2825
2826 // Replace the other vector result not being explicitly split here.
2827 unsigned OtherNo = 1 - ResNo;
2828 EVT OtherVT = N->getValueType(OtherNo);
2829 if (getTypeAction(OtherVT) == TargetLowering::TypeSplitVector) {
2830 SetSplitVector(SDValue(N, OtherNo), SDValue(LoNode, OtherNo),
2831 SDValue(HiNode, OtherNo));
2832 } else {
2833 SDValue OtherVal =
2834 DAG.getNode(ISD::CONCAT_VECTORS, dl, OtherVT, SDValue(LoNode, OtherNo),
2835 SDValue(HiNode, OtherNo));
2836 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
2837 }
2838}
2839
2840void DAGTypeLegalizer::SplitVecRes_ExtendOp(SDNode *N, SDValue &Lo,
2841 SDValue &Hi) {
2842 SDLoc dl(N);
2843 EVT SrcVT = N->getOperand(0).getValueType();
2844 EVT DestVT = N->getValueType(0);
2845 EVT LoVT, HiVT;
2846 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(DestVT);
2847
2848 // We can do better than a generic split operation if the extend is doing
2849 // more than just doubling the width of the elements and the following are
2850 // true:
2851 // - The number of vector elements is even,
2852 // - the source type is legal,
2853 // - the type of a split source is illegal,
2854 // - the type of an extended (by doubling element size) source is legal, and
2855 // - the type of that extended source when split is legal.
2856 //
2857 // This won't necessarily completely legalize the operation, but it will
2858 // more effectively move in the right direction and prevent falling down
2859 // to scalarization in many cases due to the input vector being split too
2860 // far.
2861 if (SrcVT.getVectorElementCount().isKnownEven() &&
2862 SrcVT.getScalarSizeInBits() * 2 < DestVT.getScalarSizeInBits()) {
2863 LLVMContext &Ctx = *DAG.getContext();
2864 EVT NewSrcVT = SrcVT.widenIntegerVectorElementType(Ctx);
2865 EVT SplitSrcVT = SrcVT.getHalfNumVectorElementsVT(Ctx);
2866
2867 EVT SplitLoVT, SplitHiVT;
2868 std::tie(SplitLoVT, SplitHiVT) = DAG.GetSplitDestVTs(NewSrcVT);
2869 if (TLI.isTypeLegal(SrcVT) && !TLI.isTypeLegal(SplitSrcVT) &&
2870 TLI.isTypeLegal(NewSrcVT) && TLI.isTypeLegal(SplitLoVT)) {
2871 LLVM_DEBUG(dbgs() << "Split vector extend via incremental extend:";
2872 N->dump(&DAG); dbgs() << "\n");
2873 if (!N->isVPOpcode()) {
2874 // Extend the source vector by one step.
2875 SDValue NewSrc =
2876 DAG.getNode(N->getOpcode(), dl, NewSrcVT, N->getOperand(0));
2877 // Get the low and high halves of the new, extended one step, vector.
2878 std::tie(Lo, Hi) = DAG.SplitVector(NewSrc, dl);
2879 // Extend those vector halves the rest of the way.
2880 Lo = DAG.getNode(N->getOpcode(), dl, LoVT, Lo);
2881 Hi = DAG.getNode(N->getOpcode(), dl, HiVT, Hi);
2882 return;
2883 }
2884
2885 // Extend the source vector by one step.
2886 SDValue NewSrc =
2887 DAG.getNode(N->getOpcode(), dl, NewSrcVT, N->getOperand(0),
2888 N->getOperand(1), N->getOperand(2));
2889 // Get the low and high halves of the new, extended one step, vector.
2890 std::tie(Lo, Hi) = DAG.SplitVector(NewSrc, dl);
2891
2892 SDValue MaskLo, MaskHi;
2893 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
2894
2895 SDValue EVLLo, EVLHi;
2896 std::tie(EVLLo, EVLHi) =
2897 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), dl);
2898 // Extend those vector halves the rest of the way.
2899 Lo = DAG.getNode(N->getOpcode(), dl, LoVT, {Lo, MaskLo, EVLLo});
2900 Hi = DAG.getNode(N->getOpcode(), dl, HiVT, {Hi, MaskHi, EVLHi});
2901 return;
2902 }
2903 }
2904 // Fall back to the generic unary operator splitting otherwise.
2905 SplitVecRes_UnaryOp(N, Lo, Hi);
2906}
2907
2908void DAGTypeLegalizer::SplitVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N,
2909 SDValue &Lo, SDValue &Hi) {
2910 // The low and high parts of the original input give four input vectors.
2911 SDValue Inputs[4];
2912 SDLoc DL(N);
2913 GetSplitVector(N->getOperand(0), Inputs[0], Inputs[1]);
2914 GetSplitVector(N->getOperand(1), Inputs[2], Inputs[3]);
2915 EVT NewVT = Inputs[0].getValueType();
2916 unsigned NewElts = NewVT.getVectorNumElements();
2917
2918 auto &&IsConstant = [](const SDValue &N) {
2919 APInt SplatValue;
2920 return N.getResNo() == 0 &&
2921 (ISD::isConstantSplatVector(N.getNode(), SplatValue) ||
2923 };
2924 auto &&BuildVector = [NewElts, &DAG = DAG, NewVT, &DL](SDValue &Input1,
2925 SDValue &Input2,
2926 ArrayRef<int> Mask) {
2927 assert(Input1->getOpcode() == ISD::BUILD_VECTOR &&
2928 Input2->getOpcode() == ISD::BUILD_VECTOR &&
2929 "Expected build vector node.");
2930 EVT EltVT = NewVT.getVectorElementType();
2931 SmallVector<SDValue> Ops(NewElts, DAG.getPOISON(EltVT));
2932 for (unsigned I = 0; I < NewElts; ++I) {
2933 if (Mask[I] == PoisonMaskElem)
2934 continue;
2935 unsigned Idx = Mask[I];
2936 if (Idx >= NewElts)
2937 Ops[I] = Input2.getOperand(Idx - NewElts);
2938 else
2939 Ops[I] = Input1.getOperand(Idx);
2940 // Make the type of all elements the same as the element type.
2941 if (Ops[I].getValueType().bitsGT(EltVT))
2942 Ops[I] = DAG.getNode(ISD::TRUNCATE, DL, EltVT, Ops[I]);
2943 }
2944 return DAG.getBuildVector(NewVT, DL, Ops);
2945 };
2946
2947 // If Lo or Hi uses elements from at most two of the four input vectors, then
2948 // express it as a vector shuffle of those two inputs. Otherwise extract the
2949 // input elements by hand and construct the Lo/Hi output using a BUILD_VECTOR.
2950 SmallVector<int> OrigMask(N->getMask());
2951 // Try to pack incoming shuffles/inputs.
2952 auto &&TryPeekThroughShufflesInputs = [&Inputs, &NewVT, this, NewElts,
2953 &DL](SmallVectorImpl<int> &Mask) {
2954 // Check if all inputs are shuffles of the same operands or non-shuffles.
2955 MapVector<std::pair<SDValue, SDValue>, SmallVector<unsigned>> ShufflesIdxs;
2956 for (unsigned Idx = 0; Idx < std::size(Inputs); ++Idx) {
2957 SDValue Input = Inputs[Idx];
2958 auto *Shuffle = dyn_cast<ShuffleVectorSDNode>(Input.getNode());
2959 if (!Shuffle ||
2960 Input.getOperand(0).getValueType() != Input.getValueType())
2961 continue;
2962 ShufflesIdxs[std::make_pair(Input.getOperand(0), Input.getOperand(1))]
2963 .push_back(Idx);
2964 ShufflesIdxs[std::make_pair(Input.getOperand(1), Input.getOperand(0))]
2965 .push_back(Idx);
2966 }
2967 for (auto &P : ShufflesIdxs) {
2968 if (P.second.size() < 2)
2969 continue;
2970 // Use shuffles operands instead of shuffles themselves.
2971 // 1. Adjust mask.
2972 for (int &Idx : Mask) {
2973 if (Idx == PoisonMaskElem)
2974 continue;
2975 unsigned SrcRegIdx = Idx / NewElts;
2976 if (Inputs[SrcRegIdx].isUndef()) {
2977 Idx = PoisonMaskElem;
2978 continue;
2979 }
2980 auto *Shuffle =
2981 dyn_cast<ShuffleVectorSDNode>(Inputs[SrcRegIdx].getNode());
2982 if (!Shuffle || !is_contained(P.second, SrcRegIdx))
2983 continue;
2984 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
2985 if (MaskElt == PoisonMaskElem) {
2986 Idx = PoisonMaskElem;
2987 continue;
2988 }
2989 Idx = MaskElt % NewElts +
2990 P.second[Shuffle->getOperand(MaskElt / NewElts) == P.first.first
2991 ? 0
2992 : 1] *
2993 NewElts;
2994 }
2995 // 2. Update inputs.
2996 Inputs[P.second[0]] = P.first.first;
2997 Inputs[P.second[1]] = P.first.second;
2998 // Clear the pair data.
2999 P.second.clear();
3000 ShufflesIdxs[std::make_pair(P.first.second, P.first.first)].clear();
3001 }
3002 // Check if any concat_vectors can be simplified.
3003 SmallBitVector UsedSubVector(2 * std::size(Inputs));
3004 for (int &Idx : Mask) {
3005 if (Idx == PoisonMaskElem)
3006 continue;
3007 unsigned SrcRegIdx = Idx / NewElts;
3008 if (Inputs[SrcRegIdx].isUndef()) {
3009 Idx = PoisonMaskElem;
3010 continue;
3011 }
3013 getTypeAction(Inputs[SrcRegIdx].getValueType());
3014 if (Inputs[SrcRegIdx].getOpcode() == ISD::CONCAT_VECTORS &&
3015 Inputs[SrcRegIdx].getNumOperands() == 2 &&
3016 !Inputs[SrcRegIdx].getOperand(1).isUndef() &&
3017 (TypeAction == TargetLowering::TypeLegal ||
3018 TypeAction == TargetLowering::TypeWidenVector))
3019 UsedSubVector.set(2 * SrcRegIdx + (Idx % NewElts) / (NewElts / 2));
3020 }
3021 if (UsedSubVector.count() > 1) {
3023 for (unsigned I = 0; I < std::size(Inputs); ++I) {
3024 if (UsedSubVector.test(2 * I) == UsedSubVector.test(2 * I + 1))
3025 continue;
3026 if (Pairs.empty() || Pairs.back().size() == 2)
3027 Pairs.emplace_back();
3028 if (UsedSubVector.test(2 * I)) {
3029 Pairs.back().emplace_back(I, 0);
3030 } else {
3031 assert(UsedSubVector.test(2 * I + 1) &&
3032 "Expected to be used one of the subvectors.");
3033 Pairs.back().emplace_back(I, 1);
3034 }
3035 }
3036 if (!Pairs.empty() && Pairs.front().size() > 1) {
3037 // Adjust mask.
3038 for (int &Idx : Mask) {
3039 if (Idx == PoisonMaskElem)
3040 continue;
3041 unsigned SrcRegIdx = Idx / NewElts;
3042 auto *It = find_if(
3043 Pairs, [SrcRegIdx](ArrayRef<std::pair<unsigned, int>> Idxs) {
3044 return Idxs.front().first == SrcRegIdx ||
3045 Idxs.back().first == SrcRegIdx;
3046 });
3047 if (It == Pairs.end())
3048 continue;
3049 Idx = It->front().first * NewElts + (Idx % NewElts) % (NewElts / 2) +
3050 (SrcRegIdx == It->front().first ? 0 : (NewElts / 2));
3051 }
3052 // Adjust inputs.
3053 for (ArrayRef<std::pair<unsigned, int>> Idxs : Pairs) {
3054 Inputs[Idxs.front().first] = DAG.getNode(
3056 Inputs[Idxs.front().first].getValueType(),
3057 Inputs[Idxs.front().first].getOperand(Idxs.front().second),
3058 Inputs[Idxs.back().first].getOperand(Idxs.back().second));
3059 }
3060 }
3061 }
3062 bool Changed;
3063 do {
3064 // Try to remove extra shuffles (except broadcasts) and shuffles with the
3065 // reused operands.
3066 Changed = false;
3067 for (unsigned I = 0; I < std::size(Inputs); ++I) {
3068 auto *Shuffle = dyn_cast<ShuffleVectorSDNode>(Inputs[I].getNode());
3069 if (!Shuffle)
3070 continue;
3071 if (Shuffle->getOperand(0).getValueType() != NewVT)
3072 continue;
3073 int Op = -1;
3074 if (!Inputs[I].hasOneUse() && Shuffle->getOperand(1).isUndef() &&
3075 !Shuffle->isSplat()) {
3076 Op = 0;
3077 } else if (!Inputs[I].hasOneUse() &&
3078 !Shuffle->getOperand(1).isUndef()) {
3079 // Find the only used operand, if possible.
3080 for (int &Idx : Mask) {
3081 if (Idx == PoisonMaskElem)
3082 continue;
3083 unsigned SrcRegIdx = Idx / NewElts;
3084 if (SrcRegIdx != I)
3085 continue;
3086 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
3087 if (MaskElt == PoisonMaskElem) {
3088 Idx = PoisonMaskElem;
3089 continue;
3090 }
3091 int OpIdx = MaskElt / NewElts;
3092 if (Op == -1) {
3093 Op = OpIdx;
3094 continue;
3095 }
3096 if (Op != OpIdx) {
3097 Op = -1;
3098 break;
3099 }
3100 }
3101 }
3102 if (Op < 0) {
3103 // Try to check if one of the shuffle operands is used already.
3104 for (int OpIdx = 0; OpIdx < 2; ++OpIdx) {
3105 if (Shuffle->getOperand(OpIdx).isUndef())
3106 continue;
3107 auto *It = find(Inputs, Shuffle->getOperand(OpIdx));
3108 if (It == std::end(Inputs))
3109 continue;
3110 int FoundOp = std::distance(std::begin(Inputs), It);
3111 // Found that operand is used already.
3112 // 1. Fix the mask for the reused operand.
3113 for (int &Idx : Mask) {
3114 if (Idx == PoisonMaskElem)
3115 continue;
3116 unsigned SrcRegIdx = Idx / NewElts;
3117 if (SrcRegIdx != I)
3118 continue;
3119 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
3120 if (MaskElt == PoisonMaskElem) {
3121 Idx = PoisonMaskElem;
3122 continue;
3123 }
3124 int MaskIdx = MaskElt / NewElts;
3125 if (OpIdx == MaskIdx)
3126 Idx = MaskElt % NewElts + FoundOp * NewElts;
3127 }
3128 // 2. Set Op to the unused OpIdx.
3129 Op = (OpIdx + 1) % 2;
3130 break;
3131 }
3132 }
3133 if (Op >= 0) {
3134 Changed = true;
3135 Inputs[I] = Shuffle->getOperand(Op);
3136 // Adjust mask.
3137 for (int &Idx : Mask) {
3138 if (Idx == PoisonMaskElem)
3139 continue;
3140 unsigned SrcRegIdx = Idx / NewElts;
3141 if (SrcRegIdx != I)
3142 continue;
3143 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
3144 int OpIdx = MaskElt / NewElts;
3145 if (OpIdx != Op)
3146 continue;
3147 Idx = MaskElt % NewElts + SrcRegIdx * NewElts;
3148 }
3149 }
3150 }
3151 } while (Changed);
3152 };
3153 TryPeekThroughShufflesInputs(OrigMask);
3154 // Proces unique inputs.
3155 auto &&MakeUniqueInputs = [&Inputs, &IsConstant,
3156 NewElts](SmallVectorImpl<int> &Mask) {
3157 SetVector<SDValue> UniqueInputs;
3158 SetVector<SDValue> UniqueConstantInputs;
3159 for (const auto &I : Inputs) {
3160 if (IsConstant(I))
3161 UniqueConstantInputs.insert(I);
3162 else if (!I.isUndef())
3163 UniqueInputs.insert(I);
3164 }
3165 // Adjust mask in case of reused inputs. Also, need to insert constant
3166 // inputs at first, otherwise it affects the final outcome.
3167 if (UniqueInputs.size() != std::size(Inputs)) {
3168 auto &&UniqueVec = UniqueInputs.takeVector();
3169 auto &&UniqueConstantVec = UniqueConstantInputs.takeVector();
3170 unsigned ConstNum = UniqueConstantVec.size();
3171 for (int &Idx : Mask) {
3172 if (Idx == PoisonMaskElem)
3173 continue;
3174 unsigned SrcRegIdx = Idx / NewElts;
3175 if (Inputs[SrcRegIdx].isUndef()) {
3176 Idx = PoisonMaskElem;
3177 continue;
3178 }
3179 const auto It = find(UniqueConstantVec, Inputs[SrcRegIdx]);
3180 if (It != UniqueConstantVec.end()) {
3181 Idx = (Idx % NewElts) +
3182 NewElts * std::distance(UniqueConstantVec.begin(), It);
3183 assert(Idx >= 0 && "Expected defined mask idx.");
3184 continue;
3185 }
3186 const auto RegIt = find(UniqueVec, Inputs[SrcRegIdx]);
3187 assert(RegIt != UniqueVec.end() && "Cannot find non-const value.");
3188 Idx = (Idx % NewElts) +
3189 NewElts * (std::distance(UniqueVec.begin(), RegIt) + ConstNum);
3190 assert(Idx >= 0 && "Expected defined mask idx.");
3191 }
3192 copy(UniqueConstantVec, std::begin(Inputs));
3193 copy(UniqueVec, std::next(std::begin(Inputs), ConstNum));
3194 }
3195 };
3196 MakeUniqueInputs(OrigMask);
3197 SDValue OrigInputs[4];
3198 copy(Inputs, std::begin(OrigInputs));
3199 for (unsigned High = 0; High < 2; ++High) {
3200 SDValue &Output = High ? Hi : Lo;
3201
3202 // Build a shuffle mask for the output, discovering on the fly which
3203 // input vectors to use as shuffle operands.
3204 unsigned FirstMaskIdx = High * NewElts;
3205 SmallVector<int> Mask(NewElts * std::size(Inputs), PoisonMaskElem);
3206 copy(ArrayRef(OrigMask).slice(FirstMaskIdx, NewElts), Mask.begin());
3207 assert(!Output && "Expected default initialized initial value.");
3208 TryPeekThroughShufflesInputs(Mask);
3209 MakeUniqueInputs(Mask);
3210 SDValue TmpInputs[4];
3211 copy(Inputs, std::begin(TmpInputs));
3212 // Track changes in the output registers.
3213 int UsedIdx = -1;
3214 bool SecondIteration = false;
3215 auto &&AccumulateResults = [&UsedIdx, &SecondIteration](unsigned Idx) {
3216 if (UsedIdx < 0) {
3217 UsedIdx = Idx;
3218 return false;
3219 }
3220 if (UsedIdx >= 0 && static_cast<unsigned>(UsedIdx) == Idx)
3221 SecondIteration = true;
3222 return SecondIteration;
3223 };
3225 Mask, std::size(Inputs), std::size(Inputs),
3226 /*NumOfUsedRegs=*/1,
3227 [&Output, &DAG = DAG, NewVT]() { Output = DAG.getUNDEF(NewVT); },
3228 [&Output, &DAG = DAG, NewVT, &DL, &Inputs,
3229 &BuildVector](ArrayRef<int> Mask, unsigned Idx, unsigned /*Unused*/) {
3230 if (Inputs[Idx]->getOpcode() == ISD::BUILD_VECTOR)
3231 Output = BuildVector(Inputs[Idx], Inputs[Idx], Mask);
3232 else
3233 Output = DAG.getVectorShuffle(NewVT, DL, Inputs[Idx],
3234 DAG.getUNDEF(NewVT), Mask);
3235 Inputs[Idx] = Output;
3236 },
3237 [&AccumulateResults, &Output, &DAG = DAG, NewVT, &DL, &Inputs,
3238 &TmpInputs, &BuildVector](ArrayRef<int> Mask, unsigned Idx1,
3239 unsigned Idx2, bool /*Unused*/) {
3240 if (AccumulateResults(Idx1)) {
3241 if (Inputs[Idx1]->getOpcode() == ISD::BUILD_VECTOR &&
3242 Inputs[Idx2]->getOpcode() == ISD::BUILD_VECTOR)
3243 Output = BuildVector(Inputs[Idx1], Inputs[Idx2], Mask);
3244 else
3245 Output = DAG.getVectorShuffle(NewVT, DL, Inputs[Idx1],
3246 Inputs[Idx2], Mask);
3247 } else {
3248 if (TmpInputs[Idx1]->getOpcode() == ISD::BUILD_VECTOR &&
3249 TmpInputs[Idx2]->getOpcode() == ISD::BUILD_VECTOR)
3250 Output = BuildVector(TmpInputs[Idx1], TmpInputs[Idx2], Mask);
3251 else
3252 Output = DAG.getVectorShuffle(NewVT, DL, TmpInputs[Idx1],
3253 TmpInputs[Idx2], Mask);
3254 }
3255 Inputs[Idx1] = Output;
3256 });
3257 copy(OrigInputs, std::begin(Inputs));
3258 }
3259}
3260
3261void DAGTypeLegalizer::SplitVecRes_VAARG(SDNode *N, SDValue &Lo, SDValue &Hi) {
3262 EVT OVT = N->getValueType(0);
3263 EVT NVT = OVT.getHalfNumVectorElementsVT(*DAG.getContext());
3264 SDValue Chain = N->getOperand(0);
3265 SDValue Ptr = N->getOperand(1);
3266 SDValue SV = N->getOperand(2);
3267 SDLoc dl(N);
3268
3269 const Align Alignment =
3270 DAG.getDataLayout().getABITypeAlign(NVT.getTypeForEVT(*DAG.getContext()));
3271
3272 Lo = DAG.getVAArg(NVT, dl, Chain, Ptr, SV, Alignment.value());
3273 Hi = DAG.getVAArg(NVT, dl, Lo.getValue(1), Ptr, SV, Alignment.value());
3274 Chain = Hi.getValue(1);
3275
3276 // Modified the chain - switch anything that used the old chain to use
3277 // the new one.
3278 ReplaceValueWith(SDValue(N, 1), Chain);
3279}
3280
3281void DAGTypeLegalizer::SplitVecRes_FP_TO_XINT_SAT(SDNode *N, SDValue &Lo,
3282 SDValue &Hi) {
3283 EVT DstVTLo, DstVTHi;
3284 std::tie(DstVTLo, DstVTHi) = DAG.GetSplitDestVTs(N->getValueType(0));
3285 SDLoc dl(N);
3286
3287 SDValue SrcLo, SrcHi;
3288 EVT SrcVT = N->getOperand(0).getValueType();
3289 if (getTypeAction(SrcVT) == TargetLowering::TypeSplitVector)
3290 GetSplitVector(N->getOperand(0), SrcLo, SrcHi);
3291 else
3292 std::tie(SrcLo, SrcHi) = DAG.SplitVectorOperand(N, 0);
3293
3294 Lo = DAG.getNode(N->getOpcode(), dl, DstVTLo, SrcLo, N->getOperand(1));
3295 Hi = DAG.getNode(N->getOpcode(), dl, DstVTHi, SrcHi, N->getOperand(1));
3296}
3297
3298void DAGTypeLegalizer::SplitVecRes_VECTOR_REVERSE(SDNode *N, SDValue &Lo,
3299 SDValue &Hi) {
3300 SDValue InLo, InHi;
3301 GetSplitVector(N->getOperand(0), InLo, InHi);
3302 SDLoc DL(N);
3303
3304 Lo = DAG.getNode(ISD::VECTOR_REVERSE, DL, InHi.getValueType(), InHi);
3305 Hi = DAG.getNode(ISD::VECTOR_REVERSE, DL, InLo.getValueType(), InLo);
3306}
3307
3308void DAGTypeLegalizer::SplitVecRes_VECTOR_SPLICE(SDNode *N, SDValue &Lo,
3309 SDValue &Hi) {
3310 SDLoc DL(N);
3311
3312 SDValue Expanded = TLI.expandVectorSplice(N, DAG);
3313 std::tie(Lo, Hi) = DAG.SplitVector(Expanded, DL);
3314}
3315
3316void DAGTypeLegalizer::SplitVecRes_VP_REVERSE(SDNode *N, SDValue &Lo,
3317 SDValue &Hi) {
3318 EVT VT = N->getValueType(0);
3319 SDValue Val = N->getOperand(0);
3320 SDValue Mask = N->getOperand(1);
3321 SDValue EVL = N->getOperand(2);
3322 SDLoc DL(N);
3323
3324 // Fallback to VP_STRIDED_STORE to stack followed by VP_LOAD.
3325 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
3326
3327 EVT MemVT = EVT::getVectorVT(*DAG.getContext(), VT.getVectorElementType(),
3329 SDValue StackPtr = DAG.CreateStackTemporary(MemVT.getStoreSize(), Alignment);
3330 EVT PtrVT = StackPtr.getValueType();
3331 auto &MF = DAG.getMachineFunction();
3332 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
3333 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
3334
3335 MachineMemOperand *StoreMMO = DAG.getMachineFunction().getMachineMemOperand(
3337 Alignment);
3338 MachineMemOperand *LoadMMO = DAG.getMachineFunction().getMachineMemOperand(
3340 Alignment);
3341
3342 unsigned EltWidth = VT.getScalarSizeInBits() / 8;
3343 SDValue NumElemMinus1 =
3344 DAG.getNode(ISD::SUB, DL, PtrVT, DAG.getZExtOrTrunc(EVL, DL, PtrVT),
3345 DAG.getConstant(1, DL, PtrVT));
3346 SDValue StartOffset = DAG.getNode(ISD::MUL, DL, PtrVT, NumElemMinus1,
3347 DAG.getConstant(EltWidth, DL, PtrVT));
3348 SDValue StorePtr = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, StartOffset);
3349 SDValue Stride = DAG.getConstant(-(int64_t)EltWidth, DL, PtrVT);
3350
3351 SDValue TrueMask = DAG.getBoolConstant(true, DL, Mask.getValueType(), VT);
3352 SDValue Store = DAG.getStridedStoreVP(DAG.getEntryNode(), DL, Val, StorePtr,
3353 DAG.getUNDEF(PtrVT), Stride, TrueMask,
3354 EVL, MemVT, StoreMMO, ISD::UNINDEXED);
3355
3356 SDValue Load = DAG.getLoadVP(VT, DL, Store, StackPtr, Mask, EVL, LoadMMO);
3357
3358 std::tie(Lo, Hi) = DAG.SplitVector(Load, DL);
3359}
3360
3361void DAGTypeLegalizer::SplitVecRes_VP_SPLICE(SDNode *N, SDValue &Lo,
3362 SDValue &Hi) {
3363 EVT VT = N->getValueType(0);
3364 SDValue V1 = N->getOperand(0);
3365 SDValue V2 = N->getOperand(1);
3366 int64_t Imm = cast<ConstantSDNode>(N->getOperand(2))->getSExtValue();
3367 SDValue Mask = N->getOperand(3);
3368 SDValue EVL1 = N->getOperand(4);
3369 SDValue EVL2 = N->getOperand(5);
3370 SDLoc DL(N);
3371
3372 // Since EVL2 is considered the real VL it gets promoted during
3373 // SelectionDAGBuilder. Promote EVL1 here if needed.
3374 if (getTypeAction(EVL1.getValueType()) == TargetLowering::TypePromoteInteger)
3375 EVL1 = ZExtPromotedInteger(EVL1);
3376
3377 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
3378
3379 EVT MemVT = EVT::getVectorVT(*DAG.getContext(), VT.getVectorElementType(),
3380 VT.getVectorElementCount() * 2);
3381 SDValue StackPtr = DAG.CreateStackTemporary(MemVT.getStoreSize(), Alignment);
3382 EVT PtrVT = StackPtr.getValueType();
3383 auto &MF = DAG.getMachineFunction();
3384 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
3385 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
3386
3387 MachineMemOperand *StoreMMO = DAG.getMachineFunction().getMachineMemOperand(
3389 Alignment);
3390 MachineMemOperand *LoadMMO = DAG.getMachineFunction().getMachineMemOperand(
3392 Alignment);
3393
3394 SDValue StackPtr2 = TLI.getVectorElementPointer(DAG, StackPtr, VT, EVL1);
3395
3396 SDValue TrueMask = DAG.getBoolConstant(true, DL, Mask.getValueType(), VT);
3397 SDValue StoreV1 = DAG.getStoreVP(DAG.getEntryNode(), DL, V1, StackPtr,
3398 DAG.getUNDEF(PtrVT), TrueMask, EVL1,
3399 V1.getValueType(), StoreMMO, ISD::UNINDEXED);
3400
3402 DAG.getStoreVP(StoreV1, DL, V2, StackPtr2, DAG.getUNDEF(PtrVT), TrueMask,
3403 EVL2, V2.getValueType(), StoreMMO, ISD::UNINDEXED);
3404
3405 SDValue Load;
3406 if (Imm >= 0) {
3407 StackPtr = TLI.getVectorElementPointer(DAG, StackPtr, VT, N->getOperand(2));
3408 Load = DAG.getLoadVP(VT, DL, StoreV2, StackPtr, Mask, EVL2, LoadMMO);
3409 } else {
3410 uint64_t TrailingElts = -Imm;
3411 unsigned EltWidth = VT.getScalarSizeInBits() / 8;
3412 SDValue TrailingBytes = DAG.getConstant(TrailingElts * EltWidth, DL, PtrVT);
3413
3414 // Make sure TrailingBytes doesn't exceed the size of vec1.
3415 SDValue OffsetToV2 = DAG.getNode(ISD::SUB, DL, PtrVT, StackPtr2, StackPtr);
3416 TrailingBytes =
3417 DAG.getNode(ISD::UMIN, DL, PtrVT, TrailingBytes, OffsetToV2);
3418
3419 // Calculate the start address of the spliced result.
3420 StackPtr2 = DAG.getNode(ISD::SUB, DL, PtrVT, StackPtr2, TrailingBytes);
3421 Load = DAG.getLoadVP(VT, DL, StoreV2, StackPtr2, Mask, EVL2, LoadMMO);
3422 }
3423
3424 EVT LoVT, HiVT;
3425 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(VT);
3426 Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, LoVT, Load,
3427 DAG.getVectorIdxConstant(0, DL));
3428 Hi =
3429 DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, HiVT, Load,
3430 DAG.getVectorIdxConstant(LoVT.getVectorMinNumElements(), DL));
3431}
3432
3433void DAGTypeLegalizer::SplitVecRes_PARTIAL_REDUCE_MLA(SDNode *N, SDValue &Lo,
3434 SDValue &Hi) {
3435 SDLoc DL(N);
3436 SDValue Acc = N->getOperand(0);
3437 SDValue Input1 = N->getOperand(1);
3438 SDValue Input2 = N->getOperand(2);
3439
3440 SDValue AccLo, AccHi;
3441 GetSplitVector(Acc, AccLo, AccHi);
3442 unsigned Opcode = N->getOpcode();
3443
3444 // If the input types don't need splitting, just accumulate into the
3445 // low part of the accumulator.
3446 if (getTypeAction(Input1.getValueType()) != TargetLowering::TypeSplitVector) {
3447 Lo = DAG.getNode(Opcode, DL, AccLo.getValueType(), AccLo, Input1, Input2);
3448 Hi = AccHi;
3449 return;
3450 }
3451
3452 SDValue Input1Lo, Input1Hi;
3453 SDValue Input2Lo, Input2Hi;
3454 GetSplitVector(Input1, Input1Lo, Input1Hi);
3455 GetSplitVector(Input2, Input2Lo, Input2Hi);
3456 EVT ResultVT = AccLo.getValueType();
3457
3458 Lo = DAG.getNode(Opcode, DL, ResultVT, AccLo, Input1Lo, Input2Lo);
3459 Hi = DAG.getNode(Opcode, DL, ResultVT, AccHi, Input1Hi, Input2Hi);
3460}
3461
3462void DAGTypeLegalizer::SplitVecRes_GET_ACTIVE_LANE_MASK(SDNode *N, SDValue &Lo,
3463 SDValue &Hi) {
3464 SDLoc DL(N);
3465 SDValue Op0 = N->getOperand(0);
3466 SDValue Op1 = N->getOperand(1);
3467 EVT OpVT = Op0.getValueType();
3468
3469 EVT LoVT, HiVT;
3470 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
3471
3472 Lo = DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, DL, LoVT, Op0, Op1);
3473 SDValue LoElts = DAG.getElementCount(DL, OpVT, LoVT.getVectorElementCount());
3474 SDValue HiStartVal = DAG.getNode(ISD::UADDSAT, DL, OpVT, Op0, LoElts);
3475 Hi = DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, DL, HiVT, HiStartVal, Op1);
3476}
3477
3478void DAGTypeLegalizer::SplitVecRes_VECTOR_DEINTERLEAVE(SDNode *N) {
3479 unsigned Factor = N->getNumOperands();
3480
3481 SmallVector<SDValue, 8> Ops(Factor * 2);
3482 for (unsigned i = 0; i != Factor; ++i) {
3483 SDValue OpLo, OpHi;
3484 GetSplitVector(N->getOperand(i), OpLo, OpHi);
3485 Ops[i * 2] = OpLo;
3486 Ops[i * 2 + 1] = OpHi;
3487 }
3488
3489 SmallVector<EVT, 8> VTs(Factor, Ops[0].getValueType());
3490
3491 SDLoc DL(N);
3492 SDValue ResLo = DAG.getNode(ISD::VECTOR_DEINTERLEAVE, DL, VTs,
3493 ArrayRef(Ops).slice(0, Factor));
3494 SDValue ResHi = DAG.getNode(ISD::VECTOR_DEINTERLEAVE, DL, VTs,
3495 ArrayRef(Ops).slice(Factor, Factor));
3496
3497 for (unsigned i = 0; i != Factor; ++i)
3498 SetSplitVector(SDValue(N, i), ResLo.getValue(i), ResHi.getValue(i));
3499}
3500
3501void DAGTypeLegalizer::SplitVecRes_VECTOR_INTERLEAVE(SDNode *N) {
3502 unsigned Factor = N->getNumOperands();
3503
3504 SmallVector<SDValue, 8> Ops(Factor * 2);
3505 for (unsigned i = 0; i != Factor; ++i) {
3506 SDValue OpLo, OpHi;
3507 GetSplitVector(N->getOperand(i), OpLo, OpHi);
3508 Ops[i] = OpLo;
3509 Ops[i + Factor] = OpHi;
3510 }
3511
3512 SmallVector<EVT, 8> VTs(Factor, Ops[0].getValueType());
3513
3514 SDLoc DL(N);
3515 SDValue Res[] = {DAG.getNode(ISD::VECTOR_INTERLEAVE, DL, VTs,
3516 ArrayRef(Ops).slice(0, Factor)),
3517 DAG.getNode(ISD::VECTOR_INTERLEAVE, DL, VTs,
3518 ArrayRef(Ops).slice(Factor, Factor))};
3519
3520 for (unsigned i = 0; i != Factor; ++i) {
3521 unsigned IdxLo = 2 * i;
3522 unsigned IdxHi = 2 * i + 1;
3523 SetSplitVector(SDValue(N, i), Res[IdxLo / Factor].getValue(IdxLo % Factor),
3524 Res[IdxHi / Factor].getValue(IdxHi % Factor));
3525 }
3526}
3527
3528//===----------------------------------------------------------------------===//
3529// Operand Vector Splitting
3530//===----------------------------------------------------------------------===//
3531
3532/// This method is called when the specified operand of the specified node is
3533/// found to need vector splitting. At this point, all of the result types of
3534/// the node are known to be legal, but other operands of the node may need
3535/// legalization as well as the specified one.
3536bool DAGTypeLegalizer::SplitVectorOperand(SDNode *N, unsigned OpNo) {
3537 LLVM_DEBUG(dbgs() << "Split node operand: "; N->dump(&DAG));
3538 SDValue Res = SDValue();
3539
3540 // See if the target wants to custom split this node.
3541 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
3542 return false;
3543
3544 switch (N->getOpcode()) {
3545 default:
3546#ifndef NDEBUG
3547 dbgs() << "SplitVectorOperand Op #" << OpNo << ": ";
3548 N->dump(&DAG);
3549 dbgs() << "\n";
3550#endif
3551 report_fatal_error("Do not know how to split this operator's "
3552 "operand!\n");
3553
3554 case ISD::VP_SETCC:
3555 case ISD::STRICT_FSETCC:
3557 case ISD::SETCC: Res = SplitVecOp_VSETCC(N); break;
3558 case ISD::BITCAST: Res = SplitVecOp_BITCAST(N); break;
3559 case ISD::EXTRACT_SUBVECTOR: Res = SplitVecOp_EXTRACT_SUBVECTOR(N); break;
3560 case ISD::INSERT_SUBVECTOR: Res = SplitVecOp_INSERT_SUBVECTOR(N, OpNo); break;
3561 case ISD::EXTRACT_VECTOR_ELT:Res = SplitVecOp_EXTRACT_VECTOR_ELT(N); break;
3562 case ISD::CONCAT_VECTORS: Res = SplitVecOp_CONCAT_VECTORS(N); break;
3563 case ISD::VP_TRUNCATE:
3564 case ISD::TRUNCATE:
3565 Res = SplitVecOp_TruncateHelper(N);
3566 break;
3568 case ISD::VP_FP_ROUND:
3569 case ISD::FP_ROUND: Res = SplitVecOp_FP_ROUND(N); break;
3570 case ISD::FCOPYSIGN: Res = SplitVecOp_FPOpDifferentTypes(N); break;
3571 case ISD::STORE:
3572 Res = SplitVecOp_STORE(cast<StoreSDNode>(N), OpNo);
3573 break;
3574 case ISD::VP_STORE:
3575 Res = SplitVecOp_VP_STORE(cast<VPStoreSDNode>(N), OpNo);
3576 break;
3577 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
3578 Res = SplitVecOp_VP_STRIDED_STORE(cast<VPStridedStoreSDNode>(N), OpNo);
3579 break;
3580 case ISD::MSTORE:
3581 Res = SplitVecOp_MSTORE(cast<MaskedStoreSDNode>(N), OpNo);
3582 break;
3583 case ISD::MSCATTER:
3584 case ISD::VP_SCATTER:
3585 Res = SplitVecOp_Scatter(cast<MemSDNode>(N), OpNo);
3586 break;
3587 case ISD::MGATHER:
3588 case ISD::VP_GATHER:
3589 Res = SplitVecOp_Gather(cast<MemSDNode>(N), OpNo);
3590 break;
3591 case ISD::VSELECT:
3592 Res = SplitVecOp_VSELECT(N, OpNo);
3593 break;
3595 Res = SplitVecOp_VECTOR_COMPRESS(N, OpNo);
3596 break;
3599 case ISD::SINT_TO_FP:
3600 case ISD::UINT_TO_FP:
3601 case ISD::VP_SINT_TO_FP:
3602 case ISD::VP_UINT_TO_FP:
3603 if (N->getValueType(0).bitsLT(
3604 N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType()))
3605 Res = SplitVecOp_TruncateHelper(N);
3606 else
3607 Res = SplitVecOp_UnaryOp(N);
3608 break;
3611 Res = SplitVecOp_FP_TO_XINT_SAT(N);
3612 break;
3613 case ISD::FP_TO_SINT:
3614 case ISD::FP_TO_UINT:
3615 case ISD::VP_FP_TO_SINT:
3616 case ISD::VP_FP_TO_UINT:
3620 case ISD::FP_EXTEND:
3621 case ISD::SIGN_EXTEND:
3622 case ISD::ZERO_EXTEND:
3623 case ISD::ANY_EXTEND:
3624 case ISD::FTRUNC:
3625 case ISD::LROUND:
3626 case ISD::LLROUND:
3627 case ISD::LRINT:
3628 case ISD::LLRINT:
3629 Res = SplitVecOp_UnaryOp(N);
3630 break;
3631 case ISD::FLDEXP:
3632 Res = SplitVecOp_FPOpDifferentTypes(N);
3633 break;
3634
3635 case ISD::SCMP:
3636 case ISD::UCMP:
3637 Res = SplitVecOp_CMP(N);
3638 break;
3639
3640 case ISD::FAKE_USE:
3641 Res = SplitVecOp_FAKE_USE(N);
3642 break;
3646 Res = SplitVecOp_ExtVecInRegOp(N);
3647 break;
3648
3651 case ISD::VECREDUCE_ADD:
3652 case ISD::VECREDUCE_MUL:
3653 case ISD::VECREDUCE_AND:
3654 case ISD::VECREDUCE_OR:
3655 case ISD::VECREDUCE_XOR:
3664 Res = SplitVecOp_VECREDUCE(N, OpNo);
3665 break;
3668 Res = SplitVecOp_VECREDUCE_SEQ(N);
3669 break;
3670 case ISD::VP_REDUCE_FADD:
3671 case ISD::VP_REDUCE_SEQ_FADD:
3672 case ISD::VP_REDUCE_FMUL:
3673 case ISD::VP_REDUCE_SEQ_FMUL:
3674 case ISD::VP_REDUCE_ADD:
3675 case ISD::VP_REDUCE_MUL:
3676 case ISD::VP_REDUCE_AND:
3677 case ISD::VP_REDUCE_OR:
3678 case ISD::VP_REDUCE_XOR:
3679 case ISD::VP_REDUCE_SMAX:
3680 case ISD::VP_REDUCE_SMIN:
3681 case ISD::VP_REDUCE_UMAX:
3682 case ISD::VP_REDUCE_UMIN:
3683 case ISD::VP_REDUCE_FMAX:
3684 case ISD::VP_REDUCE_FMIN:
3685 case ISD::VP_REDUCE_FMAXIMUM:
3686 case ISD::VP_REDUCE_FMINIMUM:
3687 Res = SplitVecOp_VP_REDUCE(N, OpNo);
3688 break;
3689 case ISD::VP_CTTZ_ELTS:
3690 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
3691 Res = SplitVecOp_VP_CttzElements(N);
3692 break;
3694 Res = SplitVecOp_VECTOR_HISTOGRAM(N);
3695 break;
3700 Res = SplitVecOp_PARTIAL_REDUCE_MLA(N);
3701 break;
3702 }
3703
3704 // If the result is null, the sub-method took care of registering results etc.
3705 if (!Res.getNode()) return false;
3706
3707 // If the result is N, the sub-method updated N in place. Tell the legalizer
3708 // core about this.
3709 if (Res.getNode() == N)
3710 return true;
3711
3712 if (N->isStrictFPOpcode())
3713 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
3714 "Invalid operand expansion");
3715 else
3716 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
3717 "Invalid operand expansion");
3718
3719 ReplaceValueWith(SDValue(N, 0), Res);
3720 return false;
3721}
3722
3723SDValue DAGTypeLegalizer::SplitVecOp_VSELECT(SDNode *N, unsigned OpNo) {
3724 // The only possibility for an illegal operand is the mask, since result type
3725 // legalization would have handled this node already otherwise.
3726 assert(OpNo == 0 && "Illegal operand must be mask");
3727
3728 SDValue Mask = N->getOperand(0);
3729 SDValue Src0 = N->getOperand(1);
3730 SDValue Src1 = N->getOperand(2);
3731 EVT Src0VT = Src0.getValueType();
3732 SDLoc DL(N);
3733 assert(Mask.getValueType().isVector() && "VSELECT without a vector mask?");
3734
3735 SDValue Lo, Hi;
3736 GetSplitVector(N->getOperand(0), Lo, Hi);
3737 assert(Lo.getValueType() == Hi.getValueType() &&
3738 "Lo and Hi have differing types");
3739
3740 EVT LoOpVT, HiOpVT;
3741 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(Src0VT);
3742 assert(LoOpVT == HiOpVT && "Asymmetric vector split?");
3743
3744 SDValue LoOp0, HiOp0, LoOp1, HiOp1, LoMask, HiMask;
3745 std::tie(LoOp0, HiOp0) = DAG.SplitVector(Src0, DL);
3746 std::tie(LoOp1, HiOp1) = DAG.SplitVector(Src1, DL);
3747 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
3748
3749 SDValue LoSelect =
3750 DAG.getNode(ISD::VSELECT, DL, LoOpVT, LoMask, LoOp0, LoOp1);
3751 SDValue HiSelect =
3752 DAG.getNode(ISD::VSELECT, DL, HiOpVT, HiMask, HiOp0, HiOp1);
3753
3754 return DAG.getNode(ISD::CONCAT_VECTORS, DL, Src0VT, LoSelect, HiSelect);
3755}
3756
3757SDValue DAGTypeLegalizer::SplitVecOp_VECTOR_COMPRESS(SDNode *N, unsigned OpNo) {
3758 // The only possibility for an illegal operand is the mask, since result type
3759 // legalization would have handled this node already otherwise.
3760 assert(OpNo == 1 && "Illegal operand must be mask");
3761
3762 // To split the mask, we need to split the result type too, so we can just
3763 // reuse that logic here.
3764 SDValue Lo, Hi;
3765 SplitVecRes_VECTOR_COMPRESS(N, Lo, Hi);
3766
3767 EVT VecVT = N->getValueType(0);
3768 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), VecVT, Lo, Hi);
3769}
3770
3771SDValue DAGTypeLegalizer::SplitVecOp_VECREDUCE(SDNode *N, unsigned OpNo) {
3772 EVT ResVT = N->getValueType(0);
3773 SDValue Lo, Hi;
3774 SDLoc dl(N);
3775
3776 SDValue VecOp = N->getOperand(OpNo);
3777 EVT VecVT = VecOp.getValueType();
3778 assert(VecVT.isVector() && "Can only split reduce vector operand");
3779 GetSplitVector(VecOp, Lo, Hi);
3780 EVT LoOpVT, HiOpVT;
3781 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(VecVT);
3782
3783 // Use the appropriate scalar instruction on the split subvectors before
3784 // reducing the now partially reduced smaller vector.
3785 unsigned CombineOpc = ISD::getVecReduceBaseOpcode(N->getOpcode());
3786 SDValue Partial = DAG.getNode(CombineOpc, dl, LoOpVT, Lo, Hi, N->getFlags());
3787 return DAG.getNode(N->getOpcode(), dl, ResVT, Partial, N->getFlags());
3788}
3789
3790SDValue DAGTypeLegalizer::SplitVecOp_VECREDUCE_SEQ(SDNode *N) {
3791 EVT ResVT = N->getValueType(0);
3792 SDValue Lo, Hi;
3793 SDLoc dl(N);
3794
3795 SDValue AccOp = N->getOperand(0);
3796 SDValue VecOp = N->getOperand(1);
3797 SDNodeFlags Flags = N->getFlags();
3798
3799 EVT VecVT = VecOp.getValueType();
3800 assert(VecVT.isVector() && "Can only split reduce vector operand");
3801 GetSplitVector(VecOp, Lo, Hi);
3802 EVT LoOpVT, HiOpVT;
3803 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(VecVT);
3804
3805 // Reduce low half.
3806 SDValue Partial = DAG.getNode(N->getOpcode(), dl, ResVT, AccOp, Lo, Flags);
3807
3808 // Reduce high half, using low half result as initial value.
3809 return DAG.getNode(N->getOpcode(), dl, ResVT, Partial, Hi, Flags);
3810}
3811
3812SDValue DAGTypeLegalizer::SplitVecOp_VP_REDUCE(SDNode *N, unsigned OpNo) {
3813 assert(N->isVPOpcode() && "Expected VP opcode");
3814 assert(OpNo == 1 && "Can only split reduce vector operand");
3815
3816 unsigned Opc = N->getOpcode();
3817 EVT ResVT = N->getValueType(0);
3818 SDValue Lo, Hi;
3819 SDLoc dl(N);
3820
3821 SDValue VecOp = N->getOperand(OpNo);
3822 EVT VecVT = VecOp.getValueType();
3823 assert(VecVT.isVector() && "Can only split reduce vector operand");
3824 GetSplitVector(VecOp, Lo, Hi);
3825
3826 SDValue MaskLo, MaskHi;
3827 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(2));
3828
3829 SDValue EVLLo, EVLHi;
3830 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(N->getOperand(3), VecVT, dl);
3831
3832 const SDNodeFlags Flags = N->getFlags();
3833
3834 SDValue ResLo =
3835 DAG.getNode(Opc, dl, ResVT, {N->getOperand(0), Lo, MaskLo, EVLLo}, Flags);
3836 return DAG.getNode(Opc, dl, ResVT, {ResLo, Hi, MaskHi, EVLHi}, Flags);
3837}
3838
3839SDValue DAGTypeLegalizer::SplitVecOp_UnaryOp(SDNode *N) {
3840 // The result has a legal vector type, but the input needs splitting.
3841 EVT ResVT = N->getValueType(0);
3842 SDValue Lo, Hi;
3843 SDLoc dl(N);
3844 GetSplitVector(N->getOperand(N->isStrictFPOpcode() ? 1 : 0), Lo, Hi);
3845 EVT InVT = Lo.getValueType();
3846
3847 EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
3848 InVT.getVectorElementCount());
3849
3850 if (N->isStrictFPOpcode()) {
3851 Lo = DAG.getNode(N->getOpcode(), dl, {OutVT, MVT::Other},
3852 {N->getOperand(0), Lo});
3853 Hi = DAG.getNode(N->getOpcode(), dl, {OutVT, MVT::Other},
3854 {N->getOperand(0), Hi});
3855
3856 // Build a factor node to remember that this operation is independent
3857 // of the other one.
3858 SDValue Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
3859 Hi.getValue(1));
3860
3861 // Legalize the chain result - switch anything that used the old chain to
3862 // use the new one.
3863 ReplaceValueWith(SDValue(N, 1), Ch);
3864 } else if (N->getNumOperands() == 3) {
3865 assert(N->isVPOpcode() && "Expected VP opcode");
3866 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
3867 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
3868 std::tie(EVLLo, EVLHi) =
3869 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), dl);
3870 Lo = DAG.getNode(N->getOpcode(), dl, OutVT, Lo, MaskLo, EVLLo);
3871 Hi = DAG.getNode(N->getOpcode(), dl, OutVT, Hi, MaskHi, EVLHi);
3872 } else {
3873 Lo = DAG.getNode(N->getOpcode(), dl, OutVT, Lo);
3874 Hi = DAG.getNode(N->getOpcode(), dl, OutVT, Hi);
3875 }
3876
3877 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
3878}
3879
3880// Split a FAKE_USE use of a vector into FAKE_USEs of hi and lo part.
3881SDValue DAGTypeLegalizer::SplitVecOp_FAKE_USE(SDNode *N) {
3882 SDValue Lo, Hi;
3883 GetSplitVector(N->getOperand(1), Lo, Hi);
3884 SDValue Chain =
3885 DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, N->getOperand(0), Lo);
3886 return DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, Chain, Hi);
3887}
3888
3889SDValue DAGTypeLegalizer::SplitVecOp_BITCAST(SDNode *N) {
3890 // For example, i64 = BITCAST v4i16 on alpha. Typically the vector will
3891 // end up being split all the way down to individual components. Convert the
3892 // split pieces into integers and reassemble.
3893 EVT ResVT = N->getValueType(0);
3894 SDValue Lo, Hi;
3895 GetSplitVector(N->getOperand(0), Lo, Hi);
3896 SDLoc dl(N);
3897
3898 if (ResVT.isScalableVector()) {
3899 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(ResVT);
3900 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
3901 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
3902 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
3903 }
3904
3905 Lo = BitConvertToInteger(Lo);
3906 Hi = BitConvertToInteger(Hi);
3907
3908 if (DAG.getDataLayout().isBigEndian())
3909 std::swap(Lo, Hi);
3910
3911 return DAG.getNode(ISD::BITCAST, dl, ResVT, JoinIntegers(Lo, Hi));
3912}
3913
3914SDValue DAGTypeLegalizer::SplitVecOp_INSERT_SUBVECTOR(SDNode *N,
3915 unsigned OpNo) {
3916 assert(OpNo == 1 && "Invalid OpNo; can only split SubVec.");
3917 // We know that the result type is legal.
3918 EVT ResVT = N->getValueType(0);
3919
3920 SDValue Vec = N->getOperand(0);
3921 SDValue SubVec = N->getOperand(1);
3922 SDValue Idx = N->getOperand(2);
3923 SDLoc dl(N);
3924
3925 SDValue Lo, Hi;
3926 GetSplitVector(SubVec, Lo, Hi);
3927
3928 uint64_t IdxVal = Idx->getAsZExtVal();
3929 uint64_t LoElts = Lo.getValueType().getVectorMinNumElements();
3930
3931 SDValue FirstInsertion =
3932 DAG.getNode(ISD::INSERT_SUBVECTOR, dl, ResVT, Vec, Lo, Idx);
3933 SDValue SecondInsertion =
3934 DAG.getNode(ISD::INSERT_SUBVECTOR, dl, ResVT, FirstInsertion, Hi,
3935 DAG.getVectorIdxConstant(IdxVal + LoElts, dl));
3936
3937 return SecondInsertion;
3938}
3939
3940SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
3941 // We know that the extracted result type is legal.
3942 EVT SubVT = N->getValueType(0);
3943 SDValue Idx = N->getOperand(1);
3944 SDLoc dl(N);
3945 SDValue Lo, Hi;
3946
3947 GetSplitVector(N->getOperand(0), Lo, Hi);
3948
3949 ElementCount LoElts = Lo.getValueType().getVectorElementCount();
3950 // Note: For scalable vectors, the index is scaled by vscale.
3951 ElementCount IdxVal =
3953 uint64_t IdxValMin = IdxVal.getKnownMinValue();
3954
3955 EVT SrcVT = N->getOperand(0).getValueType();
3956 ElementCount NumResultElts = SubVT.getVectorElementCount();
3957
3958 // If the extracted elements are all in the low half, do a simple extract.
3959 if (ElementCount::isKnownLE(IdxVal + NumResultElts, LoElts))
3960 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, SubVT, Lo, Idx);
3961
3962 unsigned LoEltsMin = LoElts.getKnownMinValue();
3963 if (IdxValMin < LoEltsMin && SubVT.isFixedLengthVector() &&
3964 SrcVT.isFixedLengthVector()) {
3965 // Extracted subvector crosses vector split, so we need to blend the two
3966 // halves.
3967 // TODO: May be able to emit partial extract_subvector.
3969 Elts.reserve(NumResultElts.getFixedValue());
3970
3971 // This is not valid for scalable vectors. If SubVT is scalable, this is the
3972 // same as unrolling a scalable dimension (invalid). If ScrVT is scalable,
3973 // `Lo[LoEltsMin]` may not be the last element of `Lo`.
3974 DAG.ExtractVectorElements(Lo, Elts, /*Start=*/IdxValMin,
3975 /*Count=*/LoEltsMin - IdxValMin);
3976 DAG.ExtractVectorElements(Hi, Elts, /*Start=*/0,
3977 /*Count=*/SubVT.getVectorNumElements() -
3978 Elts.size());
3979 return DAG.getBuildVector(SubVT, dl, Elts);
3980 }
3981
3982 if (SubVT.isScalableVector() == SrcVT.isScalableVector()) {
3983 ElementCount ExtractIdx = IdxVal - LoElts;
3984 if (ExtractIdx.isKnownMultipleOf(NumResultElts))
3985 return DAG.getExtractSubvector(dl, SubVT, Hi,
3986 ExtractIdx.getKnownMinValue());
3987
3988 EVT HiVT = Hi.getValueType();
3989 assert(HiVT.isFixedLengthVector() &&
3990 "Only fixed-vector extracts are supported in this case");
3991
3992 // We cannot create an extract_subvector that isn't a multiple of the
3993 // result size, which may go out of bounds for the last elements. Shuffle
3994 // the desired elements down to 0 and do a simple 0 extract.
3995 SmallVector<int, 8> Mask(HiVT.getVectorNumElements(), -1);
3996 for (int I = 0; I != int(NumResultElts.getFixedValue()); ++I)
3997 Mask[I] = int(ExtractIdx.getFixedValue()) + I;
3998
3999 SDValue Shuffle =
4000 DAG.getVectorShuffle(HiVT, dl, Hi, DAG.getPOISON(HiVT), Mask);
4001 return DAG.getExtractSubvector(dl, SubVT, Shuffle, 0);
4002 }
4003
4004 // After this point the DAG node only permits extracting fixed-width
4005 // subvectors from scalable vectors.
4006 assert(SubVT.isFixedLengthVector() &&
4007 "Extracting scalable subvector from fixed-width unsupported");
4008
4009 // If the element type is i1 and we're not promoting the result, then we may
4010 // end up loading the wrong data since the bits are packed tightly into
4011 // bytes. For example, if we extract a v4i1 (legal) from a nxv4i1 (legal)
4012 // type at index 4, then we will load a byte starting at index 0.
4013 if (SubVT.getScalarType() == MVT::i1)
4014 report_fatal_error("Don't know how to extract fixed-width predicate "
4015 "subvector from a scalable predicate vector");
4016
4017 // Spill the vector to the stack. We should use the alignment for
4018 // the smallest part.
4019 SDValue Vec = N->getOperand(0);
4020 EVT VecVT = Vec.getValueType();
4021 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
4023 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
4024 auto &MF = DAG.getMachineFunction();
4025 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
4026 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
4027
4028 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
4029 SmallestAlign);
4030
4031 // Extract the subvector by loading the correct part.
4032 StackPtr = TLI.getVectorSubVecPointer(DAG, StackPtr, VecVT, SubVT, Idx);
4033
4034 return DAG.getLoad(
4035 SubVT, dl, Store, StackPtr,
4036 MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()));
4037}
4038
4039SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
4040 SDValue Vec = N->getOperand(0);
4041 SDValue Idx = N->getOperand(1);
4042 EVT VecVT = Vec.getValueType();
4043
4044 if (const ConstantSDNode *Index = dyn_cast<ConstantSDNode>(Idx)) {
4045 uint64_t IdxVal = Index->getZExtValue();
4046
4047 SDValue Lo, Hi;
4048 GetSplitVector(Vec, Lo, Hi);
4049
4050 uint64_t LoElts = Lo.getValueType().getVectorMinNumElements();
4051
4052 if (IdxVal < LoElts)
4053 return SDValue(DAG.UpdateNodeOperands(N, Lo, Idx), 0);
4054 else if (!Vec.getValueType().isScalableVector())
4055 return SDValue(DAG.UpdateNodeOperands(N, Hi,
4056 DAG.getConstant(IdxVal - LoElts, SDLoc(N),
4057 Idx.getValueType())), 0);
4058 }
4059
4060 // See if the target wants to custom expand this node.
4061 if (CustomLowerNode(N, N->getValueType(0), true))
4062 return SDValue();
4063
4064 // Make the vector elements byte-addressable if they aren't already.
4065 SDLoc dl(N);
4066 EVT EltVT = VecVT.getVectorElementType();
4067 if (!EltVT.isByteSized()) {
4068 EltVT = EltVT.changeTypeToInteger().getRoundIntegerType(*DAG.getContext());
4069 VecVT = VecVT.changeElementType(EltVT);
4070 Vec = DAG.getNode(ISD::ANY_EXTEND, dl, VecVT, Vec);
4071 SDValue NewExtract =
4072 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, Vec, Idx);
4073 return DAG.getAnyExtOrTrunc(NewExtract, dl, N->getValueType(0));
4074 }
4075
4076 // Store the vector to the stack.
4077 // In cases where the vector is illegal it will be broken down into parts
4078 // and stored in parts - we should use the alignment for the smallest part.
4079 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
4081 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
4082 auto &MF = DAG.getMachineFunction();
4083 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
4084 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
4085 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
4086 SmallestAlign);
4087
4088 // Load back the required element.
4089 StackPtr = TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Idx);
4090
4091 // EXTRACT_VECTOR_ELT can extend the element type to the width of the return
4092 // type, leaving the high bits undefined. But it can't truncate.
4093 assert(N->getValueType(0).bitsGE(EltVT) && "Illegal EXTRACT_VECTOR_ELT.");
4094
4095 return DAG.getExtLoad(
4096 ISD::EXTLOAD, dl, N->getValueType(0), Store, StackPtr,
4097 MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()), EltVT,
4098 commonAlignment(SmallestAlign, EltVT.getFixedSizeInBits() / 8));
4099}
4100
4101SDValue DAGTypeLegalizer::SplitVecOp_ExtVecInRegOp(SDNode *N) {
4102 SDValue Lo, Hi;
4103
4104 // *_EXTEND_VECTOR_INREG only reference the lower half of the input, so
4105 // splitting the result has the same effect as splitting the input operand.
4106 SplitVecRes_ExtVecInRegOp(N, Lo, Hi);
4107
4108 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), N->getValueType(0), Lo, Hi);
4109}
4110
4111SDValue DAGTypeLegalizer::SplitVecOp_Gather(MemSDNode *N, unsigned OpNo) {
4112 (void)OpNo;
4113 SDValue Lo, Hi;
4114 SplitVecRes_Gather(N, Lo, Hi);
4115
4116 SDValue Res = DAG.getNode(ISD::CONCAT_VECTORS, N, N->getValueType(0), Lo, Hi);
4117 ReplaceValueWith(SDValue(N, 0), Res);
4118 return SDValue();
4119}
4120
4121SDValue DAGTypeLegalizer::SplitVecOp_VP_STORE(VPStoreSDNode *N, unsigned OpNo) {
4122 assert(N->isUnindexed() && "Indexed vp_store of vector?");
4123 SDValue Ch = N->getChain();
4124 SDValue Ptr = N->getBasePtr();
4125 SDValue Offset = N->getOffset();
4126 assert(Offset.isUndef() && "Unexpected VP store offset");
4127 SDValue Mask = N->getMask();
4128 SDValue EVL = N->getVectorLength();
4129 SDValue Data = N->getValue();
4130 Align Alignment = N->getBaseAlign();
4131 SDLoc DL(N);
4132
4133 SDValue DataLo, DataHi;
4134 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
4135 // Split Data operand
4136 GetSplitVector(Data, DataLo, DataHi);
4137 else
4138 std::tie(DataLo, DataHi) = DAG.SplitVector(Data, DL);
4139
4140 // Split Mask operand
4141 SDValue MaskLo, MaskHi;
4142 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC) {
4143 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
4144 } else {
4145 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
4146 GetSplitVector(Mask, MaskLo, MaskHi);
4147 else
4148 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
4149 }
4150
4151 EVT MemoryVT = N->getMemoryVT();
4152 EVT LoMemVT, HiMemVT;
4153 bool HiIsEmpty = false;
4154 std::tie(LoMemVT, HiMemVT) =
4155 DAG.GetDependentSplitDestVTs(MemoryVT, DataLo.getValueType(), &HiIsEmpty);
4156
4157 // Split EVL
4158 SDValue EVLLo, EVLHi;
4159 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(EVL, Data.getValueType(), DL);
4160
4161 SDValue Lo, Hi;
4162 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
4163 N->getPointerInfo(), MachineMemOperand::MOStore,
4164 LocationSize::beforeOrAfterPointer(), Alignment, N->getAAInfo(),
4165 N->getRanges());
4166
4167 Lo = DAG.getStoreVP(Ch, DL, DataLo, Ptr, Offset, MaskLo, EVLLo, LoMemVT, MMO,
4168 N->getAddressingMode(), N->isTruncatingStore(),
4169 N->isCompressingStore());
4170
4171 // If the hi vp_store has zero storage size, only the lo vp_store is needed.
4172 if (HiIsEmpty)
4173 return Lo;
4174
4175 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, DL, LoMemVT, DAG,
4176 N->isCompressingStore());
4177
4178 MachinePointerInfo MPI;
4179 if (LoMemVT.isScalableVector()) {
4180 Alignment = commonAlignment(Alignment,
4181 LoMemVT.getSizeInBits().getKnownMinValue() / 8);
4182 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
4183 } else
4184 MPI = N->getPointerInfo().getWithOffset(
4185 LoMemVT.getStoreSize().getFixedValue());
4186
4187 MMO = DAG.getMachineFunction().getMachineMemOperand(
4189 Alignment, N->getAAInfo(), N->getRanges());
4190
4191 Hi = DAG.getStoreVP(Ch, DL, DataHi, Ptr, Offset, MaskHi, EVLHi, HiMemVT, MMO,
4192 N->getAddressingMode(), N->isTruncatingStore(),
4193 N->isCompressingStore());
4194
4195 // Build a factor node to remember that this store is independent of the
4196 // other one.
4197 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4198}
4199
4200SDValue DAGTypeLegalizer::SplitVecOp_VP_STRIDED_STORE(VPStridedStoreSDNode *N,
4201 unsigned OpNo) {
4202 assert(N->isUnindexed() && "Indexed vp_strided_store of a vector?");
4203 assert(N->getOffset().isUndef() && "Unexpected VP strided store offset");
4204
4205 SDLoc DL(N);
4206
4207 SDValue Data = N->getValue();
4208 SDValue LoData, HiData;
4209 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
4210 GetSplitVector(Data, LoData, HiData);
4211 else
4212 std::tie(LoData, HiData) = DAG.SplitVector(Data, DL);
4213
4214 EVT LoMemVT, HiMemVT;
4215 bool HiIsEmpty = false;
4216 std::tie(LoMemVT, HiMemVT) = DAG.GetDependentSplitDestVTs(
4217 N->getMemoryVT(), LoData.getValueType(), &HiIsEmpty);
4218
4219 SDValue Mask = N->getMask();
4220 SDValue LoMask, HiMask;
4221 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC)
4222 SplitVecRes_SETCC(Mask.getNode(), LoMask, HiMask);
4223 else if (getTypeAction(Mask.getValueType()) ==
4225 GetSplitVector(Mask, LoMask, HiMask);
4226 else
4227 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
4228
4229 SDValue LoEVL, HiEVL;
4230 std::tie(LoEVL, HiEVL) =
4231 DAG.SplitEVL(N->getVectorLength(), Data.getValueType(), DL);
4232
4233 // Generate the low vp_strided_store
4234 SDValue Lo = DAG.getStridedStoreVP(
4235 N->getChain(), DL, LoData, N->getBasePtr(), N->getOffset(),
4236 N->getStride(), LoMask, LoEVL, LoMemVT, N->getMemOperand(),
4237 N->getAddressingMode(), N->isTruncatingStore(), N->isCompressingStore());
4238
4239 // If the high vp_strided_store has zero storage size, only the low
4240 // vp_strided_store is needed.
4241 if (HiIsEmpty)
4242 return Lo;
4243
4244 // Generate the high vp_strided_store.
4245 // To calculate the high base address, we need to sum to the low base
4246 // address stride number of bytes for each element already stored by low,
4247 // that is: Ptr = Ptr + (LoEVL * Stride)
4248 EVT PtrVT = N->getBasePtr().getValueType();
4250 DAG.getNode(ISD::MUL, DL, PtrVT, LoEVL,
4251 DAG.getSExtOrTrunc(N->getStride(), DL, PtrVT));
4252 SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, N->getBasePtr(), Increment);
4253
4254 Align Alignment = N->getBaseAlign();
4255 if (LoMemVT.isScalableVector())
4256 Alignment = commonAlignment(Alignment,
4257 LoMemVT.getSizeInBits().getKnownMinValue() / 8);
4258
4259 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
4260 MachinePointerInfo(N->getPointerInfo().getAddrSpace()),
4262 Alignment, N->getAAInfo(), N->getRanges());
4263
4264 SDValue Hi = DAG.getStridedStoreVP(
4265 N->getChain(), DL, HiData, Ptr, N->getOffset(), N->getStride(), HiMask,
4266 HiEVL, HiMemVT, MMO, N->getAddressingMode(), N->isTruncatingStore(),
4267 N->isCompressingStore());
4268
4269 // Build a factor node to remember that this store is independent of the
4270 // other one.
4271 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4272}
4273
4274SDValue DAGTypeLegalizer::SplitVecOp_MSTORE(MaskedStoreSDNode *N,
4275 unsigned OpNo) {
4276 assert(N->isUnindexed() && "Indexed masked store of vector?");
4277 SDValue Ch = N->getChain();
4278 SDValue Ptr = N->getBasePtr();
4279 SDValue Offset = N->getOffset();
4280 assert(Offset.isUndef() && "Unexpected indexed masked store offset");
4281 SDValue Mask = N->getMask();
4282 SDValue Data = N->getValue();
4283 Align Alignment = N->getBaseAlign();
4284 SDLoc DL(N);
4285
4286 SDValue DataLo, DataHi;
4287 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
4288 // Split Data operand
4289 GetSplitVector(Data, DataLo, DataHi);
4290 else
4291 std::tie(DataLo, DataHi) = DAG.SplitVector(Data, DL);
4292
4293 // Split Mask operand
4294 SDValue MaskLo, MaskHi;
4295 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC) {
4296 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
4297 } else {
4298 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
4299 GetSplitVector(Mask, MaskLo, MaskHi);
4300 else
4301 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
4302 }
4303
4304 EVT MemoryVT = N->getMemoryVT();
4305 EVT LoMemVT, HiMemVT;
4306 bool HiIsEmpty = false;
4307 std::tie(LoMemVT, HiMemVT) =
4308 DAG.GetDependentSplitDestVTs(MemoryVT, DataLo.getValueType(), &HiIsEmpty);
4309
4310 SDValue Lo, Hi, Res;
4311 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
4312 N->getPointerInfo(), MachineMemOperand::MOStore,
4313 LocationSize::beforeOrAfterPointer(), Alignment, N->getAAInfo(),
4314 N->getRanges());
4315
4316 Lo = DAG.getMaskedStore(Ch, DL, DataLo, Ptr, Offset, MaskLo, LoMemVT, MMO,
4317 N->getAddressingMode(), N->isTruncatingStore(),
4318 N->isCompressingStore());
4319
4320 if (HiIsEmpty) {
4321 // The hi masked store has zero storage size.
4322 // Only the lo masked store is needed.
4323 Res = Lo;
4324 } else {
4325
4326 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, DL, LoMemVT, DAG,
4327 N->isCompressingStore());
4328
4329 MachinePointerInfo MPI;
4330 if (LoMemVT.isScalableVector()) {
4331 Alignment = commonAlignment(
4332 Alignment, LoMemVT.getSizeInBits().getKnownMinValue() / 8);
4333 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
4334 } else
4335 MPI = N->getPointerInfo().getWithOffset(
4336 LoMemVT.getStoreSize().getFixedValue());
4337
4338 MMO = DAG.getMachineFunction().getMachineMemOperand(
4340 Alignment, N->getAAInfo(), N->getRanges());
4341
4342 Hi = DAG.getMaskedStore(Ch, DL, DataHi, Ptr, Offset, MaskHi, HiMemVT, MMO,
4343 N->getAddressingMode(), N->isTruncatingStore(),
4344 N->isCompressingStore());
4345
4346 // Build a factor node to remember that this store is independent of the
4347 // other one.
4348 Res = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4349 }
4350
4351 return Res;
4352}
4353
4354SDValue DAGTypeLegalizer::SplitVecOp_Scatter(MemSDNode *N, unsigned OpNo) {
4355 SDValue Ch = N->getChain();
4356 SDValue Ptr = N->getBasePtr();
4357 EVT MemoryVT = N->getMemoryVT();
4358 Align Alignment = N->getBaseAlign();
4359 SDLoc DL(N);
4360 struct Operands {
4361 SDValue Mask;
4362 SDValue Index;
4363 SDValue Scale;
4364 SDValue Data;
4365 } Ops = [&]() -> Operands {
4366 if (auto *MSC = dyn_cast<MaskedScatterSDNode>(N)) {
4367 return {MSC->getMask(), MSC->getIndex(), MSC->getScale(),
4368 MSC->getValue()};
4369 }
4370 auto *VPSC = cast<VPScatterSDNode>(N);
4371 return {VPSC->getMask(), VPSC->getIndex(), VPSC->getScale(),
4372 VPSC->getValue()};
4373 }();
4374 // Split all operands
4375
4376 EVT LoMemVT, HiMemVT;
4377 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
4378
4379 SDValue DataLo, DataHi;
4380 if (getTypeAction(Ops.Data.getValueType()) == TargetLowering::TypeSplitVector)
4381 // Split Data operand
4382 GetSplitVector(Ops.Data, DataLo, DataHi);
4383 else
4384 std::tie(DataLo, DataHi) = DAG.SplitVector(Ops.Data, DL);
4385
4386 // Split Mask operand
4387 SDValue MaskLo, MaskHi;
4388 if (OpNo == 1 && Ops.Mask.getOpcode() == ISD::SETCC) {
4389 SplitVecRes_SETCC(Ops.Mask.getNode(), MaskLo, MaskHi);
4390 } else {
4391 std::tie(MaskLo, MaskHi) = SplitMask(Ops.Mask, DL);
4392 }
4393
4394 SDValue IndexHi, IndexLo;
4395 if (getTypeAction(Ops.Index.getValueType()) ==
4397 GetSplitVector(Ops.Index, IndexLo, IndexHi);
4398 else
4399 std::tie(IndexLo, IndexHi) = DAG.SplitVector(Ops.Index, DL);
4400
4401 SDValue Lo;
4402 MachineMemOperand::Flags MMOFlags = N->getMemOperand()->getFlags();
4403 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
4404 N->getPointerInfo(), MMOFlags, LocationSize::beforeOrAfterPointer(),
4405 Alignment, N->getAAInfo(), N->getRanges());
4406
4407 if (auto *MSC = dyn_cast<MaskedScatterSDNode>(N)) {
4408 SDValue OpsLo[] = {Ch, DataLo, MaskLo, Ptr, IndexLo, Ops.Scale};
4409 Lo =
4410 DAG.getMaskedScatter(DAG.getVTList(MVT::Other), LoMemVT, DL, OpsLo, MMO,
4411 MSC->getIndexType(), MSC->isTruncatingStore());
4412
4413 // The order of the Scatter operation after split is well defined. The "Hi"
4414 // part comes after the "Lo". So these two operations should be chained one
4415 // after another.
4416 SDValue OpsHi[] = {Lo, DataHi, MaskHi, Ptr, IndexHi, Ops.Scale};
4417 return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), HiMemVT, DL, OpsHi,
4418 MMO, MSC->getIndexType(),
4419 MSC->isTruncatingStore());
4420 }
4421 auto *VPSC = cast<VPScatterSDNode>(N);
4422 SDValue EVLLo, EVLHi;
4423 std::tie(EVLLo, EVLHi) =
4424 DAG.SplitEVL(VPSC->getVectorLength(), Ops.Data.getValueType(), DL);
4425
4426 SDValue OpsLo[] = {Ch, DataLo, Ptr, IndexLo, Ops.Scale, MaskLo, EVLLo};
4427 Lo = DAG.getScatterVP(DAG.getVTList(MVT::Other), LoMemVT, DL, OpsLo, MMO,
4428 VPSC->getIndexType());
4429
4430 // The order of the Scatter operation after split is well defined. The "Hi"
4431 // part comes after the "Lo". So these two operations should be chained one
4432 // after another.
4433 SDValue OpsHi[] = {Lo, DataHi, Ptr, IndexHi, Ops.Scale, MaskHi, EVLHi};
4434 return DAG.getScatterVP(DAG.getVTList(MVT::Other), HiMemVT, DL, OpsHi, MMO,
4435 VPSC->getIndexType());
4436}
4437
4438SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) {
4439 assert(N->isUnindexed() && "Indexed store of vector?");
4440 assert(OpNo == 1 && "Can only split the stored value");
4441 SDLoc DL(N);
4442
4443 bool isTruncating = N->isTruncatingStore();
4444 SDValue Ch = N->getChain();
4445 SDValue Ptr = N->getBasePtr();
4446 EVT MemoryVT = N->getMemoryVT();
4447 Align Alignment = N->getBaseAlign();
4448 MachineMemOperand::Flags MMOFlags = N->getMemOperand()->getFlags();
4449 AAMDNodes AAInfo = N->getAAInfo();
4450 SDValue Lo, Hi;
4451 GetSplitVector(N->getOperand(1), Lo, Hi);
4452
4453 EVT LoMemVT, HiMemVT;
4454 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
4455
4456 // Scalarize if the split halves are not byte-sized.
4457 if (!LoMemVT.isByteSized() || !HiMemVT.isByteSized())
4458 return TLI.scalarizeVectorStore(N, DAG);
4459
4460 if (isTruncating)
4461 Lo = DAG.getTruncStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), LoMemVT,
4462 Alignment, MMOFlags, AAInfo);
4463 else
4464 Lo = DAG.getStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), Alignment, MMOFlags,
4465 AAInfo);
4466
4467 MachinePointerInfo MPI;
4468 IncrementPointer(N, LoMemVT, MPI, Ptr);
4469
4470 if (isTruncating)
4471 Hi = DAG.getTruncStore(Ch, DL, Hi, Ptr, MPI,
4472 HiMemVT, Alignment, MMOFlags, AAInfo);
4473 else
4474 Hi = DAG.getStore(Ch, DL, Hi, Ptr, MPI, Alignment, MMOFlags, AAInfo);
4475
4476 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4477}
4478
4479SDValue DAGTypeLegalizer::SplitVecOp_CONCAT_VECTORS(SDNode *N) {
4480 SDLoc DL(N);
4481
4482 // The input operands all must have the same type, and we know the result
4483 // type is valid. Convert this to a buildvector which extracts all the
4484 // input elements.
4485 // TODO: If the input elements are power-two vectors, we could convert this to
4486 // a new CONCAT_VECTORS node with elements that are half-wide.
4488 EVT EltVT = N->getValueType(0).getVectorElementType();
4489 for (const SDValue &Op : N->op_values()) {
4490 for (unsigned i = 0, e = Op.getValueType().getVectorNumElements();
4491 i != e; ++i) {
4492 Elts.push_back(DAG.getExtractVectorElt(DL, EltVT, Op, i));
4493 }
4494 }
4495
4496 return DAG.getBuildVector(N->getValueType(0), DL, Elts);
4497}
4498
4499SDValue DAGTypeLegalizer::SplitVecOp_TruncateHelper(SDNode *N) {
4500 // The result type is legal, but the input type is illegal. If splitting
4501 // ends up with the result type of each half still being legal, just
4502 // do that. If, however, that would result in an illegal result type,
4503 // we can try to get more clever with power-two vectors. Specifically,
4504 // split the input type, but also widen the result element size, then
4505 // concatenate the halves and truncate again. For example, consider a target
4506 // where v8i8 is legal and v8i32 is not (ARM, which doesn't have 256-bit
4507 // vectors). To perform a "%res = v8i8 trunc v8i32 %in" we do:
4508 // %inlo = v4i32 extract_subvector %in, 0
4509 // %inhi = v4i32 extract_subvector %in, 4
4510 // %lo16 = v4i16 trunc v4i32 %inlo
4511 // %hi16 = v4i16 trunc v4i32 %inhi
4512 // %in16 = v8i16 concat_vectors v4i16 %lo16, v4i16 %hi16
4513 // %res = v8i8 trunc v8i16 %in16
4514 //
4515 // Without this transform, the original truncate would end up being
4516 // scalarized, which is pretty much always a last resort.
4517 unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
4518 SDValue InVec = N->getOperand(OpNo);
4519 EVT InVT = InVec->getValueType(0);
4520 EVT OutVT = N->getValueType(0);
4521 ElementCount NumElements = OutVT.getVectorElementCount();
4522 bool IsFloat = OutVT.isFloatingPoint();
4523
4524 unsigned InElementSize = InVT.getScalarSizeInBits();
4525 unsigned OutElementSize = OutVT.getScalarSizeInBits();
4526
4527 // Determine the split output VT. If its legal we can just split dirctly.
4528 EVT LoOutVT, HiOutVT;
4529 std::tie(LoOutVT, HiOutVT) = DAG.GetSplitDestVTs(OutVT);
4530 assert(LoOutVT == HiOutVT && "Unequal split?");
4531
4532 // If the input elements are only 1/2 the width of the result elements,
4533 // just use the normal splitting. Our trick only work if there's room
4534 // to split more than once.
4535 if (isTypeLegal(LoOutVT) ||
4536 InElementSize <= OutElementSize * 2)
4537 return SplitVecOp_UnaryOp(N);
4538 SDLoc DL(N);
4539
4540 // Don't touch if this will be scalarized.
4541 EVT FinalVT = InVT;
4542 while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
4543 FinalVT = FinalVT.getHalfNumVectorElementsVT(*DAG.getContext());
4544
4545 if (getTypeAction(FinalVT) == TargetLowering::TypeScalarizeVector)
4546 return SplitVecOp_UnaryOp(N);
4547
4548 // Get the split input vector.
4549 SDValue InLoVec, InHiVec;
4550 GetSplitVector(InVec, InLoVec, InHiVec);
4551
4552 // Truncate them to 1/2 the element size.
4553 //
4554 // This assumes the number of elements is a power of two; any vector that
4555 // isn't should be widened, not split.
4556 EVT HalfElementVT = IsFloat ?
4557 EVT::getFloatingPointVT(InElementSize/2) :
4558 EVT::getIntegerVT(*DAG.getContext(), InElementSize/2);
4559 EVT HalfVT = EVT::getVectorVT(*DAG.getContext(), HalfElementVT,
4560 NumElements.divideCoefficientBy(2));
4561
4562 SDValue HalfLo;
4563 SDValue HalfHi;
4564 SDValue Chain;
4565 if (N->isStrictFPOpcode()) {
4566 HalfLo = DAG.getNode(N->getOpcode(), DL, {HalfVT, MVT::Other},
4567 {N->getOperand(0), InLoVec});
4568 HalfHi = DAG.getNode(N->getOpcode(), DL, {HalfVT, MVT::Other},
4569 {N->getOperand(0), InHiVec});
4570 // Legalize the chain result - switch anything that used the old chain to
4571 // use the new one.
4572 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, HalfLo.getValue(1),
4573 HalfHi.getValue(1));
4574 } else {
4575 HalfLo = DAG.getNode(N->getOpcode(), DL, HalfVT, InLoVec);
4576 HalfHi = DAG.getNode(N->getOpcode(), DL, HalfVT, InHiVec);
4577 }
4578
4579 // Concatenate them to get the full intermediate truncation result.
4580 EVT InterVT = EVT::getVectorVT(*DAG.getContext(), HalfElementVT, NumElements);
4581 SDValue InterVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InterVT, HalfLo,
4582 HalfHi);
4583 // Now finish up by truncating all the way down to the original result
4584 // type. This should normally be something that ends up being legal directly,
4585 // but in theory if a target has very wide vectors and an annoyingly
4586 // restricted set of legal types, this split can chain to build things up.
4587
4588 if (N->isStrictFPOpcode()) {
4589 SDValue Res = DAG.getNode(
4590 ISD::STRICT_FP_ROUND, DL, {OutVT, MVT::Other},
4591 {Chain, InterVec,
4592 DAG.getTargetConstant(0, DL, TLI.getPointerTy(DAG.getDataLayout()))});
4593 // Relink the chain
4594 ReplaceValueWith(SDValue(N, 1), SDValue(Res.getNode(), 1));
4595 return Res;
4596 }
4597
4598 return IsFloat
4599 ? DAG.getNode(ISD::FP_ROUND, DL, OutVT, InterVec,
4600 DAG.getTargetConstant(
4601 0, DL, TLI.getPointerTy(DAG.getDataLayout())))
4602 : DAG.getNode(ISD::TRUNCATE, DL, OutVT, InterVec);
4603}
4604
4605SDValue DAGTypeLegalizer::SplitVecOp_VSETCC(SDNode *N) {
4606 unsigned Opc = N->getOpcode();
4607 bool isStrict = Opc == ISD::STRICT_FSETCC || Opc == ISD::STRICT_FSETCCS;
4608 assert(N->getValueType(0).isVector() &&
4609 N->getOperand(isStrict ? 1 : 0).getValueType().isVector() &&
4610 "Operand types must be vectors");
4611 // The result has a legal vector type, but the input needs splitting.
4612 SDValue Lo0, Hi0, Lo1, Hi1, LoRes, HiRes;
4613 SDLoc DL(N);
4614 GetSplitVector(N->getOperand(isStrict ? 1 : 0), Lo0, Hi0);
4615 GetSplitVector(N->getOperand(isStrict ? 2 : 1), Lo1, Hi1);
4616
4617 EVT VT = N->getValueType(0);
4618 EVT PartResVT = Lo0.getValueType().changeElementType(VT.getScalarType());
4619
4620 if (Opc == ISD::SETCC) {
4621 LoRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Lo0, Lo1, N->getOperand(2));
4622 HiRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Hi0, Hi1, N->getOperand(2));
4623 } else if (isStrict) {
4624 LoRes = DAG.getNode(Opc, DL, DAG.getVTList(PartResVT, N->getValueType(1)),
4625 N->getOperand(0), Lo0, Lo1, N->getOperand(3));
4626 HiRes = DAG.getNode(Opc, DL, DAG.getVTList(PartResVT, N->getValueType(1)),
4627 N->getOperand(0), Hi0, Hi1, N->getOperand(3));
4628 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
4629 LoRes.getValue(1), HiRes.getValue(1));
4630 ReplaceValueWith(SDValue(N, 1), NewChain);
4631 } else {
4632 assert(Opc == ISD::VP_SETCC && "Expected VP_SETCC opcode");
4633 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
4634 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(3));
4635 std::tie(EVLLo, EVLHi) =
4636 DAG.SplitEVL(N->getOperand(4), N->getValueType(0), DL);
4637 LoRes = DAG.getNode(ISD::VP_SETCC, DL, PartResVT, Lo0, Lo1,
4638 N->getOperand(2), MaskLo, EVLLo);
4639 HiRes = DAG.getNode(ISD::VP_SETCC, DL, PartResVT, Hi0, Hi1,
4640 N->getOperand(2), MaskHi, EVLHi);
4641 }
4642
4643 return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, LoRes, HiRes);
4644}
4645
4646
4647SDValue DAGTypeLegalizer::SplitVecOp_FP_ROUND(SDNode *N) {
4648 // The result has a legal vector type, but the input needs splitting.
4649 EVT ResVT = N->getValueType(0);
4650 SDValue Lo, Hi;
4651 SDLoc DL(N);
4652 GetSplitVector(N->getOperand(N->isStrictFPOpcode() ? 1 : 0), Lo, Hi);
4653 EVT InVT = Lo.getValueType();
4654
4655 EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
4656 InVT.getVectorElementCount());
4657
4658 if (N->isStrictFPOpcode()) {
4659 Lo = DAG.getNode(N->getOpcode(), DL, {OutVT, MVT::Other},
4660 {N->getOperand(0), Lo, N->getOperand(2)});
4661 Hi = DAG.getNode(N->getOpcode(), DL, {OutVT, MVT::Other},
4662 {N->getOperand(0), Hi, N->getOperand(2)});
4663 // Legalize the chain result - switch anything that used the old chain to
4664 // use the new one.
4665 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
4666 Lo.getValue(1), Hi.getValue(1));
4667 ReplaceValueWith(SDValue(N, 1), NewChain);
4668 } else if (N->getOpcode() == ISD::VP_FP_ROUND) {
4669 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
4670 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
4671 std::tie(EVLLo, EVLHi) =
4672 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), DL);
4673 Lo = DAG.getNode(ISD::VP_FP_ROUND, DL, OutVT, Lo, MaskLo, EVLLo);
4674 Hi = DAG.getNode(ISD::VP_FP_ROUND, DL, OutVT, Hi, MaskHi, EVLHi);
4675 } else {
4676 Lo = DAG.getNode(ISD::FP_ROUND, DL, OutVT, Lo, N->getOperand(1));
4677 Hi = DAG.getNode(ISD::FP_ROUND, DL, OutVT, Hi, N->getOperand(1));
4678 }
4679
4680 return DAG.getNode(ISD::CONCAT_VECTORS, DL, ResVT, Lo, Hi);
4681}
4682
4683// Split a vector type in an FP binary operation where the second operand has a
4684// different type from the first.
4685//
4686// The result (and the first input) has a legal vector type, but the second
4687// input needs splitting.
4688SDValue DAGTypeLegalizer::SplitVecOp_FPOpDifferentTypes(SDNode *N) {
4689 SDLoc DL(N);
4690
4691 EVT LHSLoVT, LHSHiVT;
4692 std::tie(LHSLoVT, LHSHiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
4693
4694 if (!isTypeLegal(LHSLoVT) || !isTypeLegal(LHSHiVT))
4695 return DAG.UnrollVectorOp(N, N->getValueType(0).getVectorNumElements());
4696
4697 SDValue LHSLo, LHSHi;
4698 std::tie(LHSLo, LHSHi) =
4699 DAG.SplitVector(N->getOperand(0), DL, LHSLoVT, LHSHiVT);
4700
4701 SDValue RHSLo, RHSHi;
4702 std::tie(RHSLo, RHSHi) = DAG.SplitVector(N->getOperand(1), DL);
4703
4704 SDValue Lo = DAG.getNode(N->getOpcode(), DL, LHSLoVT, LHSLo, RHSLo);
4705 SDValue Hi = DAG.getNode(N->getOpcode(), DL, LHSHiVT, LHSHi, RHSHi);
4706
4707 return DAG.getNode(ISD::CONCAT_VECTORS, DL, N->getValueType(0), Lo, Hi);
4708}
4709
4710SDValue DAGTypeLegalizer::SplitVecOp_CMP(SDNode *N) {
4711 LLVMContext &Ctxt = *DAG.getContext();
4712 SDLoc dl(N);
4713
4714 SDValue LHSLo, LHSHi, RHSLo, RHSHi;
4715 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
4716 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
4717
4718 EVT ResVT = N->getValueType(0);
4719 ElementCount SplitOpEC = LHSLo.getValueType().getVectorElementCount();
4720 EVT NewResVT =
4721 EVT::getVectorVT(Ctxt, ResVT.getVectorElementType(), SplitOpEC);
4722
4723 SDValue Lo = DAG.getNode(N->getOpcode(), dl, NewResVT, LHSLo, RHSLo);
4724 SDValue Hi = DAG.getNode(N->getOpcode(), dl, NewResVT, LHSHi, RHSHi);
4725
4726 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
4727}
4728
4729SDValue DAGTypeLegalizer::SplitVecOp_FP_TO_XINT_SAT(SDNode *N) {
4730 EVT ResVT = N->getValueType(0);
4731 SDValue Lo, Hi;
4732 SDLoc dl(N);
4733 GetSplitVector(N->getOperand(0), Lo, Hi);
4734 EVT InVT = Lo.getValueType();
4735
4736 EVT NewResVT =
4737 EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
4738 InVT.getVectorElementCount());
4739
4740 Lo = DAG.getNode(N->getOpcode(), dl, NewResVT, Lo, N->getOperand(1));
4741 Hi = DAG.getNode(N->getOpcode(), dl, NewResVT, Hi, N->getOperand(1));
4742
4743 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
4744}
4745
4746SDValue DAGTypeLegalizer::SplitVecOp_VP_CttzElements(SDNode *N) {
4747 SDLoc DL(N);
4748 EVT ResVT = N->getValueType(0);
4749
4750 SDValue Lo, Hi;
4751 SDValue VecOp = N->getOperand(0);
4752 GetSplitVector(VecOp, Lo, Hi);
4753
4754 auto [MaskLo, MaskHi] = SplitMask(N->getOperand(1));
4755 auto [EVLLo, EVLHi] =
4756 DAG.SplitEVL(N->getOperand(2), VecOp.getValueType(), DL);
4757 SDValue VLo = DAG.getZExtOrTrunc(EVLLo, DL, ResVT);
4758
4759 // if VP_CTTZ_ELTS(Lo) != EVLLo => VP_CTTZ_ELTS(Lo).
4760 // else => EVLLo + (VP_CTTZ_ELTS(Hi) or VP_CTTZ_ELTS_ZERO_UNDEF(Hi)).
4761 SDValue ResLo = DAG.getNode(ISD::VP_CTTZ_ELTS, DL, ResVT, Lo, MaskLo, EVLLo);
4762 SDValue ResLoNotEVL =
4763 DAG.getSetCC(DL, getSetCCResultType(ResVT), ResLo, VLo, ISD::SETNE);
4764 SDValue ResHi = DAG.getNode(N->getOpcode(), DL, ResVT, Hi, MaskHi, EVLHi);
4765 return DAG.getSelect(DL, ResVT, ResLoNotEVL, ResLo,
4766 DAG.getNode(ISD::ADD, DL, ResVT, VLo, ResHi));
4767}
4768
4769SDValue DAGTypeLegalizer::SplitVecOp_VECTOR_HISTOGRAM(SDNode *N) {
4770 MaskedHistogramSDNode *HG = cast<MaskedHistogramSDNode>(N);
4771 SDLoc DL(HG);
4772 SDValue Inc = HG->getInc();
4773 SDValue Ptr = HG->getBasePtr();
4774 SDValue Scale = HG->getScale();
4775 SDValue IntID = HG->getIntID();
4776 EVT MemVT = HG->getMemoryVT();
4777 MachineMemOperand *MMO = HG->getMemOperand();
4778 ISD::MemIndexType IndexType = HG->getIndexType();
4779
4780 SDValue IndexLo, IndexHi, MaskLo, MaskHi;
4781 std::tie(IndexLo, IndexHi) = DAG.SplitVector(HG->getIndex(), DL);
4782 std::tie(MaskLo, MaskHi) = DAG.SplitVector(HG->getMask(), DL);
4783 SDValue OpsLo[] = {HG->getChain(), Inc, MaskLo, Ptr, IndexLo, Scale, IntID};
4784 SDValue Lo = DAG.getMaskedHistogram(DAG.getVTList(MVT::Other), MemVT, DL,
4785 OpsLo, MMO, IndexType);
4786 SDValue OpsHi[] = {Lo, Inc, MaskHi, Ptr, IndexHi, Scale, IntID};
4787 return DAG.getMaskedHistogram(DAG.getVTList(MVT::Other), MemVT, DL, OpsHi,
4788 MMO, IndexType);
4789}
4790
4791SDValue DAGTypeLegalizer::SplitVecOp_PARTIAL_REDUCE_MLA(SDNode *N) {
4792 SDValue Acc = N->getOperand(0);
4793 assert(getTypeAction(Acc.getValueType()) != TargetLowering::TypeSplitVector &&
4794 "Accumulator should already be a legal type, and shouldn't need "
4795 "further splitting");
4796
4797 SDLoc DL(N);
4798 SDValue Input1Lo, Input1Hi, Input2Lo, Input2Hi;
4799 GetSplitVector(N->getOperand(1), Input1Lo, Input1Hi);
4800 GetSplitVector(N->getOperand(2), Input2Lo, Input2Hi);
4801 unsigned Opcode = N->getOpcode();
4802 EVT ResultVT = Acc.getValueType();
4803
4804 SDValue Lo = DAG.getNode(Opcode, DL, ResultVT, Acc, Input1Lo, Input2Lo);
4805 return DAG.getNode(Opcode, DL, ResultVT, Lo, Input1Hi, Input2Hi);
4806}
4807
4808//===----------------------------------------------------------------------===//
4809// Result Vector Widening
4810//===----------------------------------------------------------------------===//
4811
4812void DAGTypeLegalizer::ReplaceOtherWidenResults(SDNode *N, SDNode *WidenNode,
4813 unsigned WidenResNo) {
4814 unsigned NumResults = N->getNumValues();
4815 for (unsigned ResNo = 0; ResNo < NumResults; ResNo++) {
4816 if (ResNo == WidenResNo)
4817 continue;
4818 EVT ResVT = N->getValueType(ResNo);
4819 if (getTypeAction(ResVT) == TargetLowering::TypeWidenVector) {
4820 SetWidenedVector(SDValue(N, ResNo), SDValue(WidenNode, ResNo));
4821 } else {
4822 SDLoc DL(N);
4823 SDValue ResVal =
4824 DAG.getExtractSubvector(DL, ResVT, SDValue(WidenNode, ResNo), 0);
4825 ReplaceValueWith(SDValue(N, ResNo), ResVal);
4826 }
4827 }
4828}
4829
4830void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
4831 LLVM_DEBUG(dbgs() << "Widen node result " << ResNo << ": "; N->dump(&DAG));
4832
4833 // See if the target wants to custom widen this node.
4834 if (CustomWidenLowerNode(N, N->getValueType(ResNo)))
4835 return;
4836
4837 SDValue Res = SDValue();
4838
4839 auto unrollExpandedOp = [&]() {
4840 // We're going to widen this vector op to a legal type by padding with undef
4841 // elements. If the wide vector op is eventually going to be expanded to
4842 // scalar libcalls, then unroll into scalar ops now to avoid unnecessary
4843 // libcalls on the undef elements.
4844 EVT VT = N->getValueType(0);
4845 EVT WideVecVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
4846 if (!TLI.isOperationLegalOrCustomOrPromote(N->getOpcode(), WideVecVT) &&
4847 TLI.isOperationExpand(N->getOpcode(), VT.getScalarType())) {
4848 Res = DAG.UnrollVectorOp(N, WideVecVT.getVectorNumElements());
4849 if (N->getNumValues() > 1)
4850 ReplaceOtherWidenResults(N, Res.getNode(), ResNo);
4851 return true;
4852 }
4853 return false;
4854 };
4855
4856 switch (N->getOpcode()) {
4857 default:
4858#ifndef NDEBUG
4859 dbgs() << "WidenVectorResult #" << ResNo << ": ";
4860 N->dump(&DAG);
4861 dbgs() << "\n";
4862#endif
4863 report_fatal_error("Do not know how to widen the result of this operator!");
4864
4867 Res = WidenVecRes_LOOP_DEPENDENCE_MASK(N);
4868 break;
4869 case ISD::MERGE_VALUES: Res = WidenVecRes_MERGE_VALUES(N, ResNo); break;
4870 case ISD::ADDRSPACECAST:
4871 Res = WidenVecRes_ADDRSPACECAST(N);
4872 break;
4873 case ISD::AssertZext: Res = WidenVecRes_AssertZext(N); break;
4874 case ISD::BITCAST: Res = WidenVecRes_BITCAST(N); break;
4875 case ISD::BUILD_VECTOR: Res = WidenVecRes_BUILD_VECTOR(N); break;
4876 case ISD::CONCAT_VECTORS: Res = WidenVecRes_CONCAT_VECTORS(N); break;
4878 Res = WidenVecRes_INSERT_SUBVECTOR(N);
4879 break;
4880 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecRes_EXTRACT_SUBVECTOR(N); break;
4881 case ISD::INSERT_VECTOR_ELT: Res = WidenVecRes_INSERT_VECTOR_ELT(N); break;
4882 case ISD::LOAD: Res = WidenVecRes_LOAD(N); break;
4883 case ISD::STEP_VECTOR:
4884 case ISD::SPLAT_VECTOR:
4886 Res = WidenVecRes_ScalarOp(N);
4887 break;
4888 case ISD::SIGN_EXTEND_INREG: Res = WidenVecRes_InregOp(N); break;
4889 case ISD::VSELECT:
4890 case ISD::SELECT:
4891 case ISD::VP_SELECT:
4892 case ISD::VP_MERGE:
4893 Res = WidenVecRes_Select(N);
4894 break;
4895 case ISD::SELECT_CC: Res = WidenVecRes_SELECT_CC(N); break;
4896 case ISD::VP_SETCC:
4897 case ISD::SETCC: Res = WidenVecRes_SETCC(N); break;
4898 case ISD::POISON:
4899 case ISD::UNDEF: Res = WidenVecRes_UNDEF(N); break;
4901 Res = WidenVecRes_VECTOR_SHUFFLE(cast<ShuffleVectorSDNode>(N));
4902 break;
4903 case ISD::VP_LOAD:
4904 Res = WidenVecRes_VP_LOAD(cast<VPLoadSDNode>(N));
4905 break;
4906 case ISD::VP_LOAD_FF:
4907 Res = WidenVecRes_VP_LOAD_FF(cast<VPLoadFFSDNode>(N));
4908 break;
4909 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
4910 Res = WidenVecRes_VP_STRIDED_LOAD(cast<VPStridedLoadSDNode>(N));
4911 break;
4913 Res = WidenVecRes_VECTOR_COMPRESS(N);
4914 break;
4915 case ISD::MLOAD:
4916 Res = WidenVecRes_MLOAD(cast<MaskedLoadSDNode>(N));
4917 break;
4918 case ISD::MGATHER:
4919 Res = WidenVecRes_MGATHER(cast<MaskedGatherSDNode>(N));
4920 break;
4921 case ISD::VP_GATHER:
4922 Res = WidenVecRes_VP_GATHER(cast<VPGatherSDNode>(N));
4923 break;
4925 Res = WidenVecRes_VECTOR_REVERSE(N);
4926 break;
4928 Res = WidenVecRes_GET_ACTIVE_LANE_MASK(N);
4929 break;
4930
4931 case ISD::ADD: case ISD::VP_ADD:
4932 case ISD::AND: case ISD::VP_AND:
4933 case ISD::MUL: case ISD::VP_MUL:
4934 case ISD::MULHS:
4935 case ISD::MULHU:
4936 case ISD::ABDS:
4937 case ISD::ABDU:
4938 case ISD::OR: case ISD::VP_OR:
4939 case ISD::SUB: case ISD::VP_SUB:
4940 case ISD::XOR: case ISD::VP_XOR:
4941 case ISD::SHL: case ISD::VP_SHL:
4942 case ISD::SRA: case ISD::VP_SRA:
4943 case ISD::SRL: case ISD::VP_SRL:
4944 case ISD::FMINNUM:
4945 case ISD::FMINNUM_IEEE:
4946 case ISD::VP_FMINNUM:
4947 case ISD::FMAXNUM:
4948 case ISD::FMAXNUM_IEEE:
4949 case ISD::VP_FMAXNUM:
4950 case ISD::FMINIMUM:
4951 case ISD::VP_FMINIMUM:
4952 case ISD::FMAXIMUM:
4953 case ISD::VP_FMAXIMUM:
4954 case ISD::FMINIMUMNUM:
4955 case ISD::FMAXIMUMNUM:
4956 case ISD::SMIN: case ISD::VP_SMIN:
4957 case ISD::SMAX: case ISD::VP_SMAX:
4958 case ISD::UMIN: case ISD::VP_UMIN:
4959 case ISD::UMAX: case ISD::VP_UMAX:
4960 case ISD::UADDSAT: case ISD::VP_UADDSAT:
4961 case ISD::SADDSAT: case ISD::VP_SADDSAT:
4962 case ISD::USUBSAT: case ISD::VP_USUBSAT:
4963 case ISD::SSUBSAT: case ISD::VP_SSUBSAT:
4964 case ISD::SSHLSAT:
4965 case ISD::USHLSAT:
4966 case ISD::ROTL:
4967 case ISD::ROTR:
4968 case ISD::AVGFLOORS:
4969 case ISD::AVGFLOORU:
4970 case ISD::AVGCEILS:
4971 case ISD::AVGCEILU:
4972 // Vector-predicated binary op widening. Note that -- unlike the
4973 // unpredicated versions -- we don't have to worry about trapping on
4974 // operations like UDIV, FADD, etc., as we pass on the original vector
4975 // length parameter. This means the widened elements containing garbage
4976 // aren't active.
4977 case ISD::VP_SDIV:
4978 case ISD::VP_UDIV:
4979 case ISD::VP_SREM:
4980 case ISD::VP_UREM:
4981 case ISD::VP_FADD:
4982 case ISD::VP_FSUB:
4983 case ISD::VP_FMUL:
4984 case ISD::VP_FDIV:
4985 case ISD::VP_FREM:
4986 case ISD::VP_FCOPYSIGN:
4987 Res = WidenVecRes_Binary(N);
4988 break;
4989
4990 case ISD::SCMP:
4991 case ISD::UCMP:
4992 Res = WidenVecRes_CMP(N);
4993 break;
4994
4995 case ISD::FPOW:
4996 case ISD::FATAN2:
4997 case ISD::FREM:
4998 if (unrollExpandedOp())
4999 break;
5000 // If the target has custom/legal support for the scalar FP intrinsic ops
5001 // (they are probably not destined to become libcalls), then widen those
5002 // like any other binary ops.
5003 [[fallthrough]];
5004
5005 case ISD::FADD:
5006 case ISD::FMUL:
5007 case ISD::FSUB:
5008 case ISD::FDIV:
5009 case ISD::SDIV:
5010 case ISD::UDIV:
5011 case ISD::SREM:
5012 case ISD::UREM:
5013 Res = WidenVecRes_BinaryCanTrap(N);
5014 break;
5015
5016 case ISD::SMULFIX:
5017 case ISD::SMULFIXSAT:
5018 case ISD::UMULFIX:
5019 case ISD::UMULFIXSAT:
5020 // These are binary operations, but with an extra operand that shouldn't
5021 // be widened (the scale).
5022 Res = WidenVecRes_BinaryWithExtraScalarOp(N);
5023 break;
5024
5025#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
5026 case ISD::STRICT_##DAGN:
5027#include "llvm/IR/ConstrainedOps.def"
5028 Res = WidenVecRes_StrictFP(N);
5029 break;
5030
5031 case ISD::UADDO:
5032 case ISD::SADDO:
5033 case ISD::USUBO:
5034 case ISD::SSUBO:
5035 case ISD::UMULO:
5036 case ISD::SMULO:
5037 Res = WidenVecRes_OverflowOp(N, ResNo);
5038 break;
5039
5040 case ISD::FCOPYSIGN:
5041 Res = WidenVecRes_FCOPYSIGN(N);
5042 break;
5043
5044 case ISD::IS_FPCLASS:
5045 case ISD::FPTRUNC_ROUND:
5046 Res = WidenVecRes_UnarySameEltsWithScalarArg(N);
5047 break;
5048
5049 case ISD::FLDEXP:
5050 case ISD::FPOWI:
5051 if (!unrollExpandedOp())
5052 Res = WidenVecRes_ExpOp(N);
5053 break;
5054
5058 Res = WidenVecRes_EXTEND_VECTOR_INREG(N);
5059 break;
5060
5061 case ISD::ANY_EXTEND:
5062 case ISD::FP_EXTEND:
5063 case ISD::VP_FP_EXTEND:
5064 case ISD::FP_ROUND:
5065 case ISD::VP_FP_ROUND:
5066 case ISD::FP_TO_SINT:
5067 case ISD::VP_FP_TO_SINT:
5068 case ISD::FP_TO_UINT:
5069 case ISD::VP_FP_TO_UINT:
5070 case ISD::SIGN_EXTEND:
5071 case ISD::VP_SIGN_EXTEND:
5072 case ISD::SINT_TO_FP:
5073 case ISD::VP_SINT_TO_FP:
5074 case ISD::VP_TRUNCATE:
5075 case ISD::TRUNCATE:
5076 case ISD::UINT_TO_FP:
5077 case ISD::VP_UINT_TO_FP:
5078 case ISD::ZERO_EXTEND:
5079 case ISD::VP_ZERO_EXTEND:
5080 Res = WidenVecRes_Convert(N);
5081 break;
5082
5085 Res = WidenVecRes_FP_TO_XINT_SAT(N);
5086 break;
5087
5088 case ISD::LRINT:
5089 case ISD::LLRINT:
5090 case ISD::VP_LRINT:
5091 case ISD::VP_LLRINT:
5092 case ISD::LROUND:
5093 case ISD::LLROUND:
5094 Res = WidenVecRes_XROUND(N);
5095 break;
5096
5097 case ISD::FACOS:
5098 case ISD::FASIN:
5099 case ISD::FATAN:
5100 case ISD::FCEIL:
5101 case ISD::FCOS:
5102 case ISD::FCOSH:
5103 case ISD::FEXP:
5104 case ISD::FEXP2:
5105 case ISD::FEXP10:
5106 case ISD::FFLOOR:
5107 case ISD::FLOG:
5108 case ISD::FLOG10:
5109 case ISD::FLOG2:
5110 case ISD::FNEARBYINT:
5111 case ISD::FRINT:
5112 case ISD::FROUND:
5113 case ISD::FROUNDEVEN:
5114 case ISD::FSIN:
5115 case ISD::FSINH:
5116 case ISD::FSQRT:
5117 case ISD::FTAN:
5118 case ISD::FTANH:
5119 case ISD::FTRUNC:
5120 if (unrollExpandedOp())
5121 break;
5122 // If the target has custom/legal support for the scalar FP intrinsic ops
5123 // (they are probably not destined to become libcalls), then widen those
5124 // like any other unary ops.
5125 [[fallthrough]];
5126
5127 case ISD::ABS:
5128 case ISD::VP_ABS:
5129 case ISD::BITREVERSE:
5130 case ISD::VP_BITREVERSE:
5131 case ISD::BSWAP:
5132 case ISD::VP_BSWAP:
5133 case ISD::CTLZ:
5134 case ISD::VP_CTLZ:
5136 case ISD::VP_CTLZ_ZERO_UNDEF:
5137 case ISD::CTPOP:
5138 case ISD::VP_CTPOP:
5139 case ISD::CTTZ:
5140 case ISD::VP_CTTZ:
5142 case ISD::VP_CTTZ_ZERO_UNDEF:
5143 case ISD::FNEG: case ISD::VP_FNEG:
5144 case ISD::FABS: case ISD::VP_FABS:
5145 case ISD::VP_SQRT:
5146 case ISD::VP_FCEIL:
5147 case ISD::VP_FFLOOR:
5148 case ISD::VP_FRINT:
5149 case ISD::VP_FNEARBYINT:
5150 case ISD::VP_FROUND:
5151 case ISD::VP_FROUNDEVEN:
5152 case ISD::VP_FROUNDTOZERO:
5153 case ISD::FREEZE:
5154 case ISD::ARITH_FENCE:
5155 case ISD::FCANONICALIZE:
5157 Res = WidenVecRes_Unary(N);
5158 break;
5159 case ISD::FMA: case ISD::VP_FMA:
5160 case ISD::FSHL:
5161 case ISD::VP_FSHL:
5162 case ISD::FSHR:
5163 case ISD::VP_FSHR:
5164 Res = WidenVecRes_Ternary(N);
5165 break;
5166 case ISD::FMODF:
5167 case ISD::FFREXP:
5168 case ISD::FSINCOS:
5169 case ISD::FSINCOSPI: {
5170 if (!unrollExpandedOp())
5171 Res = WidenVecRes_UnaryOpWithTwoResults(N, ResNo);
5172 break;
5173 }
5174 }
5175
5176 // If Res is null, the sub-method took care of registering the result.
5177 if (Res.getNode())
5178 SetWidenedVector(SDValue(N, ResNo), Res);
5179}
5180
5181SDValue DAGTypeLegalizer::WidenVecRes_Ternary(SDNode *N) {
5182 // Ternary op widening.
5183 SDLoc dl(N);
5184 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5185 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5186 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5187 SDValue InOp3 = GetWidenedVector(N->getOperand(2));
5188 if (N->getNumOperands() == 3)
5189 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3);
5190
5191 assert(N->getNumOperands() == 5 && "Unexpected number of operands!");
5192 assert(N->isVPOpcode() && "Expected VP opcode");
5193
5194 SDValue Mask =
5195 GetWidenedMask(N->getOperand(3), WidenVT.getVectorElementCount());
5196 return DAG.getNode(N->getOpcode(), dl, WidenVT,
5197 {InOp1, InOp2, InOp3, Mask, N->getOperand(4)});
5198}
5199
5200SDValue DAGTypeLegalizer::WidenVecRes_Binary(SDNode *N) {
5201 // Binary op widening.
5202 SDLoc dl(N);
5203 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5204 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5205 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5206 if (N->getNumOperands() == 2)
5207 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2,
5208 N->getFlags());
5209
5210 assert(N->getNumOperands() == 4 && "Unexpected number of operands!");
5211 assert(N->isVPOpcode() && "Expected VP opcode");
5212
5213 SDValue Mask =
5214 GetWidenedMask(N->getOperand(2), WidenVT.getVectorElementCount());
5215 return DAG.getNode(N->getOpcode(), dl, WidenVT,
5216 {InOp1, InOp2, Mask, N->getOperand(3)}, N->getFlags());
5217}
5218
5219SDValue DAGTypeLegalizer::WidenVecRes_CMP(SDNode *N) {
5220 LLVMContext &Ctxt = *DAG.getContext();
5221 SDLoc dl(N);
5222
5223 SDValue LHS = N->getOperand(0);
5224 SDValue RHS = N->getOperand(1);
5225 EVT OpVT = LHS.getValueType();
5226 if (getTypeAction(OpVT) == TargetLowering::TypeWidenVector) {
5227 LHS = GetWidenedVector(LHS);
5228 RHS = GetWidenedVector(RHS);
5229 OpVT = LHS.getValueType();
5230 }
5231
5232 EVT WidenResVT = TLI.getTypeToTransformTo(Ctxt, N->getValueType(0));
5233 ElementCount WidenResEC = WidenResVT.getVectorElementCount();
5234 if (WidenResEC == OpVT.getVectorElementCount()) {
5235 return DAG.getNode(N->getOpcode(), dl, WidenResVT, LHS, RHS);
5236 }
5237
5238 return DAG.UnrollVectorOp(N, WidenResVT.getVectorNumElements());
5239}
5240
5241SDValue DAGTypeLegalizer::WidenVecRes_BinaryWithExtraScalarOp(SDNode *N) {
5242 // Binary op widening, but with an extra operand that shouldn't be widened.
5243 SDLoc dl(N);
5244 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5245 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5246 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5247 SDValue InOp3 = N->getOperand(2);
5248 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3,
5249 N->getFlags());
5250}
5251
5252// Given a vector of operations that have been broken up to widen, see
5253// if we can collect them together into the next widest legal VT. This
5254// implementation is trap-safe.
5256 SmallVectorImpl<SDValue> &ConcatOps,
5257 unsigned ConcatEnd, EVT VT, EVT MaxVT,
5258 EVT WidenVT) {
5259 // Check to see if we have a single operation with the widen type.
5260 if (ConcatEnd == 1) {
5261 VT = ConcatOps[0].getValueType();
5262 if (VT == WidenVT)
5263 return ConcatOps[0];
5264 }
5265
5266 SDLoc dl(ConcatOps[0]);
5267 EVT WidenEltVT = WidenVT.getVectorElementType();
5268
5269 // while (Some element of ConcatOps is not of type MaxVT) {
5270 // From the end of ConcatOps, collect elements of the same type and put
5271 // them into an op of the next larger supported type
5272 // }
5273 while (ConcatOps[ConcatEnd-1].getValueType() != MaxVT) {
5274 int Idx = ConcatEnd - 1;
5275 VT = ConcatOps[Idx--].getValueType();
5276 while (Idx >= 0 && ConcatOps[Idx].getValueType() == VT)
5277 Idx--;
5278
5279 int NextSize = VT.isVector() ? VT.getVectorNumElements() : 1;
5280 EVT NextVT;
5281 do {
5282 NextSize *= 2;
5283 NextVT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NextSize);
5284 } while (!TLI.isTypeLegal(NextVT));
5285
5286 if (!VT.isVector()) {
5287 // Scalar type, create an INSERT_VECTOR_ELEMENT of type NextVT
5288 SDValue VecOp = DAG.getUNDEF(NextVT);
5289 unsigned NumToInsert = ConcatEnd - Idx - 1;
5290 for (unsigned i = 0, OpIdx = Idx + 1; i < NumToInsert; i++, OpIdx++)
5291 VecOp = DAG.getInsertVectorElt(dl, VecOp, ConcatOps[OpIdx], i);
5292 ConcatOps[Idx+1] = VecOp;
5293 ConcatEnd = Idx + 2;
5294 } else {
5295 // Vector type, create a CONCAT_VECTORS of type NextVT
5296 SDValue undefVec = DAG.getUNDEF(VT);
5297 unsigned OpsToConcat = NextSize/VT.getVectorNumElements();
5298 SmallVector<SDValue, 16> SubConcatOps(OpsToConcat);
5299 unsigned RealVals = ConcatEnd - Idx - 1;
5300 unsigned SubConcatEnd = 0;
5301 unsigned SubConcatIdx = Idx + 1;
5302 while (SubConcatEnd < RealVals)
5303 SubConcatOps[SubConcatEnd++] = ConcatOps[++Idx];
5304 while (SubConcatEnd < OpsToConcat)
5305 SubConcatOps[SubConcatEnd++] = undefVec;
5306 ConcatOps[SubConcatIdx] = DAG.getNode(ISD::CONCAT_VECTORS, dl,
5307 NextVT, SubConcatOps);
5308 ConcatEnd = SubConcatIdx + 1;
5309 }
5310 }
5311
5312 // Check to see if we have a single operation with the widen type.
5313 if (ConcatEnd == 1) {
5314 VT = ConcatOps[0].getValueType();
5315 if (VT == WidenVT)
5316 return ConcatOps[0];
5317 }
5318
5319 // add undefs of size MaxVT until ConcatOps grows to length of WidenVT
5320 unsigned NumOps = WidenVT.getVectorNumElements()/MaxVT.getVectorNumElements();
5321 if (NumOps != ConcatEnd ) {
5322 SDValue UndefVal = DAG.getUNDEF(MaxVT);
5323 for (unsigned j = ConcatEnd; j < NumOps; ++j)
5324 ConcatOps[j] = UndefVal;
5325 }
5326 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
5327 ArrayRef(ConcatOps.data(), NumOps));
5328}
5329
5330SDValue DAGTypeLegalizer::WidenVecRes_BinaryCanTrap(SDNode *N) {
5331 // Binary op widening for operations that can trap.
5332 unsigned Opcode = N->getOpcode();
5333 SDLoc dl(N);
5334 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5335 EVT WidenEltVT = WidenVT.getVectorElementType();
5336 EVT VT = WidenVT;
5337 unsigned NumElts = VT.getVectorMinNumElements();
5338 const SDNodeFlags Flags = N->getFlags();
5339 while (!TLI.isTypeLegal(VT) && NumElts != 1) {
5340 NumElts = NumElts / 2;
5341 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5342 }
5343
5344 if (NumElts != 1 && !TLI.canOpTrap(N->getOpcode(), VT)) {
5345 // Operation doesn't trap so just widen as normal.
5346 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5347 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5348 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, Flags);
5349 }
5350
5351 // Generate a vp.op if it is custom/legal for the target. This avoids need
5352 // to split and tile the subvectors (below), because the inactive lanes can
5353 // simply be disabled. To avoid possible recursion, only do this if the
5354 // widened mask type is legal.
5355 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opcode);
5356 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WidenVT)) {
5357 if (EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
5358 WidenVT.getVectorElementCount());
5359 TLI.isTypeLegal(WideMaskVT)) {
5360 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5361 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5362 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
5363 SDValue EVL =
5364 DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
5365 N->getValueType(0).getVectorElementCount());
5366 return DAG.getNode(*VPOpcode, dl, WidenVT, InOp1, InOp2, Mask, EVL,
5367 Flags);
5368 }
5369 }
5370
5371 // FIXME: Improve support for scalable vectors.
5372 assert(!VT.isScalableVector() && "Scalable vectors not handled yet.");
5373
5374 // No legal vector version so unroll the vector operation and then widen.
5375 if (NumElts == 1)
5376 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
5377
5378 // Since the operation can trap, apply operation on the original vector.
5379 EVT MaxVT = VT;
5380 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5381 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5382 unsigned CurNumElts = N->getValueType(0).getVectorNumElements();
5383
5384 SmallVector<SDValue, 16> ConcatOps(CurNumElts);
5385 unsigned ConcatEnd = 0; // Current ConcatOps index.
5386 int Idx = 0; // Current Idx into input vectors.
5387
5388 // NumElts := greatest legal vector size (at most WidenVT)
5389 // while (orig. vector has unhandled elements) {
5390 // take munches of size NumElts from the beginning and add to ConcatOps
5391 // NumElts := next smaller supported vector size or 1
5392 // }
5393 while (CurNumElts != 0) {
5394 while (CurNumElts >= NumElts) {
5395 SDValue EOp1 = DAG.getExtractSubvector(dl, VT, InOp1, Idx);
5396 SDValue EOp2 = DAG.getExtractSubvector(dl, VT, InOp2, Idx);
5397 ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, VT, EOp1, EOp2, Flags);
5398 Idx += NumElts;
5399 CurNumElts -= NumElts;
5400 }
5401 do {
5402 NumElts = NumElts / 2;
5403 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5404 } while (!TLI.isTypeLegal(VT) && NumElts != 1);
5405
5406 if (NumElts == 1) {
5407 for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
5408 SDValue EOp1 = DAG.getExtractVectorElt(dl, WidenEltVT, InOp1, Idx);
5409 SDValue EOp2 = DAG.getExtractVectorElt(dl, WidenEltVT, InOp2, Idx);
5410 ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, WidenEltVT,
5411 EOp1, EOp2, Flags);
5412 }
5413 CurNumElts = 0;
5414 }
5415 }
5416
5417 return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
5418}
5419
5420SDValue DAGTypeLegalizer::WidenVecRes_StrictFP(SDNode *N) {
5421 switch (N->getOpcode()) {
5422 case ISD::STRICT_FSETCC:
5424 return WidenVecRes_STRICT_FSETCC(N);
5431 return WidenVecRes_Convert_StrictFP(N);
5432 default:
5433 break;
5434 }
5435
5436 // StrictFP op widening for operations that can trap.
5437 unsigned NumOpers = N->getNumOperands();
5438 unsigned Opcode = N->getOpcode();
5439 SDLoc dl(N);
5440 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5441 EVT WidenEltVT = WidenVT.getVectorElementType();
5442 EVT VT = WidenVT;
5443 unsigned NumElts = VT.getVectorNumElements();
5444 while (!TLI.isTypeLegal(VT) && NumElts != 1) {
5445 NumElts = NumElts / 2;
5446 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5447 }
5448
5449 // No legal vector version so unroll the vector operation and then widen.
5450 if (NumElts == 1)
5451 return UnrollVectorOp_StrictFP(N, WidenVT.getVectorNumElements());
5452
5453 // Since the operation can trap, apply operation on the original vector.
5454 EVT MaxVT = VT;
5456 unsigned CurNumElts = N->getValueType(0).getVectorNumElements();
5457
5458 SmallVector<SDValue, 16> ConcatOps(CurNumElts);
5460 unsigned ConcatEnd = 0; // Current ConcatOps index.
5461 int Idx = 0; // Current Idx into input vectors.
5462
5463 // The Chain is the first operand.
5464 InOps.push_back(N->getOperand(0));
5465
5466 // Now process the remaining operands.
5467 for (unsigned i = 1; i < NumOpers; ++i) {
5468 SDValue Oper = N->getOperand(i);
5469
5470 EVT OpVT = Oper.getValueType();
5471 if (OpVT.isVector()) {
5472 if (getTypeAction(OpVT) == TargetLowering::TypeWidenVector)
5473 Oper = GetWidenedVector(Oper);
5474 else {
5475 EVT WideOpVT =
5476 EVT::getVectorVT(*DAG.getContext(), OpVT.getVectorElementType(),
5477 WidenVT.getVectorElementCount());
5478 Oper = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WideOpVT,
5479 DAG.getUNDEF(WideOpVT), Oper,
5480 DAG.getVectorIdxConstant(0, dl));
5481 }
5482 }
5483
5484 InOps.push_back(Oper);
5485 }
5486
5487 // NumElts := greatest legal vector size (at most WidenVT)
5488 // while (orig. vector has unhandled elements) {
5489 // take munches of size NumElts from the beginning and add to ConcatOps
5490 // NumElts := next smaller supported vector size or 1
5491 // }
5492 while (CurNumElts != 0) {
5493 while (CurNumElts >= NumElts) {
5495
5496 for (unsigned i = 0; i < NumOpers; ++i) {
5497 SDValue Op = InOps[i];
5498
5499 EVT OpVT = Op.getValueType();
5500 if (OpVT.isVector()) {
5501 EVT OpExtractVT =
5502 EVT::getVectorVT(*DAG.getContext(), OpVT.getVectorElementType(),
5504 Op = DAG.getExtractSubvector(dl, OpExtractVT, Op, Idx);
5505 }
5506
5507 EOps.push_back(Op);
5508 }
5509
5510 EVT OperVT[] = {VT, MVT::Other};
5511 SDValue Oper = DAG.getNode(Opcode, dl, OperVT, EOps);
5512 ConcatOps[ConcatEnd++] = Oper;
5513 Chains.push_back(Oper.getValue(1));
5514 Idx += NumElts;
5515 CurNumElts -= NumElts;
5516 }
5517 do {
5518 NumElts = NumElts / 2;
5519 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5520 } while (!TLI.isTypeLegal(VT) && NumElts != 1);
5521
5522 if (NumElts == 1) {
5523 for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
5525
5526 for (unsigned i = 0; i < NumOpers; ++i) {
5527 SDValue Op = InOps[i];
5528
5529 EVT OpVT = Op.getValueType();
5530 if (OpVT.isVector())
5531 Op = DAG.getExtractVectorElt(dl, OpVT.getVectorElementType(), Op,
5532 Idx);
5533
5534 EOps.push_back(Op);
5535 }
5536
5537 EVT WidenVT[] = {WidenEltVT, MVT::Other};
5538 SDValue Oper = DAG.getNode(Opcode, dl, WidenVT, EOps);
5539 ConcatOps[ConcatEnd++] = Oper;
5540 Chains.push_back(Oper.getValue(1));
5541 }
5542 CurNumElts = 0;
5543 }
5544 }
5545
5546 // Build a factor node to remember all the Ops that have been created.
5547 SDValue NewChain;
5548 if (Chains.size() == 1)
5549 NewChain = Chains[0];
5550 else
5551 NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
5552 ReplaceValueWith(SDValue(N, 1), NewChain);
5553
5554 return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
5555}
5556
5557SDValue DAGTypeLegalizer::WidenVecRes_OverflowOp(SDNode *N, unsigned ResNo) {
5558 SDLoc DL(N);
5559 EVT ResVT = N->getValueType(0);
5560 EVT OvVT = N->getValueType(1);
5561 EVT WideResVT, WideOvVT;
5562 SDValue WideLHS, WideRHS;
5563
5564 // TODO: This might result in a widen/split loop.
5565 if (ResNo == 0) {
5566 WideResVT = TLI.getTypeToTransformTo(*DAG.getContext(), ResVT);
5567 WideOvVT = EVT::getVectorVT(
5568 *DAG.getContext(), OvVT.getVectorElementType(),
5569 WideResVT.getVectorNumElements());
5570
5571 WideLHS = GetWidenedVector(N->getOperand(0));
5572 WideRHS = GetWidenedVector(N->getOperand(1));
5573 } else {
5574 WideOvVT = TLI.getTypeToTransformTo(*DAG.getContext(), OvVT);
5575 WideResVT = EVT::getVectorVT(
5576 *DAG.getContext(), ResVT.getVectorElementType(),
5577 WideOvVT.getVectorNumElements());
5578
5579 SDValue Zero = DAG.getVectorIdxConstant(0, DL);
5580 WideLHS = DAG.getNode(
5581 ISD::INSERT_SUBVECTOR, DL, WideResVT, DAG.getUNDEF(WideResVT),
5582 N->getOperand(0), Zero);
5583 WideRHS = DAG.getNode(
5584 ISD::INSERT_SUBVECTOR, DL, WideResVT, DAG.getUNDEF(WideResVT),
5585 N->getOperand(1), Zero);
5586 }
5587
5588 SDVTList WideVTs = DAG.getVTList(WideResVT, WideOvVT);
5589 SDNode *WideNode = DAG.getNode(
5590 N->getOpcode(), DL, WideVTs, WideLHS, WideRHS).getNode();
5591
5592 // Replace the other vector result not being explicitly widened here.
5593 unsigned OtherNo = 1 - ResNo;
5594 EVT OtherVT = N->getValueType(OtherNo);
5595 if (getTypeAction(OtherVT) == TargetLowering::TypeWidenVector) {
5596 SetWidenedVector(SDValue(N, OtherNo), SDValue(WideNode, OtherNo));
5597 } else {
5598 SDValue Zero = DAG.getVectorIdxConstant(0, DL);
5599 SDValue OtherVal = DAG.getNode(
5600 ISD::EXTRACT_SUBVECTOR, DL, OtherVT, SDValue(WideNode, OtherNo), Zero);
5601 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
5602 }
5603
5604 return SDValue(WideNode, ResNo);
5605}
5606
5607SDValue DAGTypeLegalizer::WidenVecRes_Convert(SDNode *N) {
5608 LLVMContext &Ctx = *DAG.getContext();
5609 SDValue InOp = N->getOperand(0);
5610 SDLoc DL(N);
5611
5612 EVT WidenVT = TLI.getTypeToTransformTo(Ctx, N->getValueType(0));
5613 ElementCount WidenEC = WidenVT.getVectorElementCount();
5614
5615 EVT InVT = InOp.getValueType();
5616
5617 unsigned Opcode = N->getOpcode();
5618 const SDNodeFlags Flags = N->getFlags();
5619
5620 // Handle the case of ZERO_EXTEND where the promoted InVT element size does
5621 // not equal that of WidenVT.
5622 if (N->getOpcode() == ISD::ZERO_EXTEND &&
5623 getTypeAction(InVT) == TargetLowering::TypePromoteInteger &&
5624 TLI.getTypeToTransformTo(Ctx, InVT).getScalarSizeInBits() !=
5625 WidenVT.getScalarSizeInBits()) {
5626 InOp = ZExtPromotedInteger(InOp);
5627 InVT = InOp.getValueType();
5628 if (WidenVT.getScalarSizeInBits() < InVT.getScalarSizeInBits())
5629 Opcode = ISD::TRUNCATE;
5630 }
5631
5632 EVT InEltVT = InVT.getVectorElementType();
5633 EVT InWidenVT = EVT::getVectorVT(Ctx, InEltVT, WidenEC);
5634 ElementCount InVTEC = InVT.getVectorElementCount();
5635
5636 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
5637 InOp = GetWidenedVector(N->getOperand(0));
5638 InVT = InOp.getValueType();
5639 InVTEC = InVT.getVectorElementCount();
5640 if (InVTEC == WidenEC) {
5641 if (N->getNumOperands() == 1)
5642 return DAG.getNode(Opcode, DL, WidenVT, InOp, Flags);
5643 if (N->getNumOperands() == 3) {
5644 assert(N->isVPOpcode() && "Expected VP opcode");
5645 SDValue Mask =
5646 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
5647 return DAG.getNode(Opcode, DL, WidenVT, InOp, Mask, N->getOperand(2));
5648 }
5649 return DAG.getNode(Opcode, DL, WidenVT, InOp, N->getOperand(1), Flags);
5650 }
5651 if (WidenVT.getSizeInBits() == InVT.getSizeInBits()) {
5652 // If both input and result vector types are of same width, extend
5653 // operations should be done with SIGN/ZERO_EXTEND_VECTOR_INREG, which
5654 // accepts fewer elements in the result than in the input.
5655 if (Opcode == ISD::ANY_EXTEND)
5656 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
5657 if (Opcode == ISD::SIGN_EXTEND)
5658 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
5659 if (Opcode == ISD::ZERO_EXTEND)
5660 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
5661 }
5662 }
5663
5664 if (TLI.isTypeLegal(InWidenVT)) {
5665 // Because the result and the input are different vector types, widening
5666 // the result could create a legal type but widening the input might make
5667 // it an illegal type that might lead to repeatedly splitting the input
5668 // and then widening it. To avoid this, we widen the input only if
5669 // it results in a legal type.
5670 if (WidenEC.isKnownMultipleOf(InVTEC.getKnownMinValue())) {
5671 // Widen the input and call convert on the widened input vector.
5672 unsigned NumConcat =
5673 WidenEC.getKnownMinValue() / InVTEC.getKnownMinValue();
5674 SmallVector<SDValue, 16> Ops(NumConcat, DAG.getPOISON(InVT));
5675 Ops[0] = InOp;
5676 SDValue InVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InWidenVT, Ops);
5677 if (N->getNumOperands() == 1)
5678 return DAG.getNode(Opcode, DL, WidenVT, InVec, Flags);
5679 return DAG.getNode(Opcode, DL, WidenVT, InVec, N->getOperand(1), Flags);
5680 }
5681
5682 if (InVTEC.isKnownMultipleOf(WidenEC.getKnownMinValue())) {
5683 SDValue InVal = DAG.getExtractSubvector(DL, InWidenVT, InOp, 0);
5684 // Extract the input and convert the shorten input vector.
5685 if (N->getNumOperands() == 1)
5686 return DAG.getNode(Opcode, DL, WidenVT, InVal, Flags);
5687 return DAG.getNode(Opcode, DL, WidenVT, InVal, N->getOperand(1), Flags);
5688 }
5689 }
5690
5691 // Otherwise unroll into some nasty scalar code and rebuild the vector.
5692 EVT EltVT = WidenVT.getVectorElementType();
5693 SmallVector<SDValue, 16> Ops(WidenEC.getFixedValue(), DAG.getPOISON(EltVT));
5694 // Use the original element count so we don't do more scalar opts than
5695 // necessary.
5696 unsigned MinElts = N->getValueType(0).getVectorNumElements();
5697 for (unsigned i=0; i < MinElts; ++i) {
5698 SDValue Val = DAG.getExtractVectorElt(DL, InEltVT, InOp, i);
5699 if (N->getNumOperands() == 1)
5700 Ops[i] = DAG.getNode(Opcode, DL, EltVT, Val, Flags);
5701 else
5702 Ops[i] = DAG.getNode(Opcode, DL, EltVT, Val, N->getOperand(1), Flags);
5703 }
5704
5705 return DAG.getBuildVector(WidenVT, DL, Ops);
5706}
5707
5708SDValue DAGTypeLegalizer::WidenVecRes_FP_TO_XINT_SAT(SDNode *N) {
5709 SDLoc dl(N);
5710 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5711 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
5712
5713 SDValue Src = N->getOperand(0);
5714 EVT SrcVT = Src.getValueType();
5715
5716 // Also widen the input.
5717 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
5718 Src = GetWidenedVector(Src);
5719 SrcVT = Src.getValueType();
5720 }
5721
5722 // Input and output not widened to the same size, give up.
5723 if (WidenNumElts != SrcVT.getVectorElementCount())
5724 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
5725
5726 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src, N->getOperand(1));
5727}
5728
5729SDValue DAGTypeLegalizer::WidenVecRes_XROUND(SDNode *N) {
5730 SDLoc dl(N);
5731 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5732 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
5733
5734 SDValue Src = N->getOperand(0);
5735 EVT SrcVT = Src.getValueType();
5736
5737 // Also widen the input.
5738 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
5739 Src = GetWidenedVector(Src);
5740 SrcVT = Src.getValueType();
5741 }
5742
5743 // Input and output not widened to the same size, give up.
5744 if (WidenNumElts != SrcVT.getVectorElementCount())
5745 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
5746
5747 if (N->getNumOperands() == 1)
5748 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src);
5749
5750 assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
5751 assert(N->isVPOpcode() && "Expected VP opcode");
5752
5753 SDValue Mask =
5754 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
5755 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src, Mask, N->getOperand(2));
5756}
5757
5758SDValue DAGTypeLegalizer::WidenVecRes_Convert_StrictFP(SDNode *N) {
5759 SDValue InOp = N->getOperand(1);
5760 SDLoc DL(N);
5761 SmallVector<SDValue, 4> NewOps(N->ops());
5762
5763 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5764 unsigned WidenNumElts = WidenVT.getVectorNumElements();
5765
5766 EVT InVT = InOp.getValueType();
5767 EVT InEltVT = InVT.getVectorElementType();
5768
5769 unsigned Opcode = N->getOpcode();
5770
5771 // FIXME: Optimizations need to be implemented here.
5772
5773 // Otherwise unroll into some nasty scalar code and rebuild the vector.
5774 EVT EltVT = WidenVT.getVectorElementType();
5775 std::array<EVT, 2> EltVTs = {{EltVT, MVT::Other}};
5776 SmallVector<SDValue, 16> Ops(WidenNumElts, DAG.getPOISON(EltVT));
5777 SmallVector<SDValue, 32> OpChains;
5778 // Use the original element count so we don't do more scalar opts than
5779 // necessary.
5780 unsigned MinElts = N->getValueType(0).getVectorNumElements();
5781 for (unsigned i=0; i < MinElts; ++i) {
5782 NewOps[1] = DAG.getExtractVectorElt(DL, InEltVT, InOp, i);
5783 Ops[i] = DAG.getNode(Opcode, DL, EltVTs, NewOps);
5784 OpChains.push_back(Ops[i].getValue(1));
5785 }
5786 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OpChains);
5787 ReplaceValueWith(SDValue(N, 1), NewChain);
5788
5789 return DAG.getBuildVector(WidenVT, DL, Ops);
5790}
5791
5792SDValue DAGTypeLegalizer::WidenVecRes_EXTEND_VECTOR_INREG(SDNode *N) {
5793 unsigned Opcode = N->getOpcode();
5794 SDValue InOp = N->getOperand(0);
5795 SDLoc DL(N);
5796
5797 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5798 EVT WidenSVT = WidenVT.getVectorElementType();
5799 unsigned WidenNumElts = WidenVT.getVectorNumElements();
5800
5801 EVT InVT = InOp.getValueType();
5802 EVT InSVT = InVT.getVectorElementType();
5803 unsigned InVTNumElts = InVT.getVectorNumElements();
5804
5805 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
5806 InOp = GetWidenedVector(InOp);
5807 InVT = InOp.getValueType();
5808 if (InVT.getSizeInBits() == WidenVT.getSizeInBits()) {
5809 switch (Opcode) {
5813 return DAG.getNode(Opcode, DL, WidenVT, InOp);
5814 }
5815 }
5816 }
5817
5818 // Unroll, extend the scalars and rebuild the vector.
5820 for (unsigned i = 0, e = std::min(InVTNumElts, WidenNumElts); i != e; ++i) {
5821 SDValue Val = DAG.getExtractVectorElt(DL, InSVT, InOp, i);
5822 switch (Opcode) {
5824 Val = DAG.getNode(ISD::ANY_EXTEND, DL, WidenSVT, Val);
5825 break;
5827 Val = DAG.getNode(ISD::SIGN_EXTEND, DL, WidenSVT, Val);
5828 break;
5830 Val = DAG.getNode(ISD::ZERO_EXTEND, DL, WidenSVT, Val);
5831 break;
5832 default:
5833 llvm_unreachable("A *_EXTEND_VECTOR_INREG node was expected");
5834 }
5835 Ops.push_back(Val);
5836 }
5837
5838 while (Ops.size() != WidenNumElts)
5839 Ops.push_back(DAG.getPOISON(WidenSVT));
5840
5841 return DAG.getBuildVector(WidenVT, DL, Ops);
5842}
5843
5844SDValue DAGTypeLegalizer::WidenVecRes_FCOPYSIGN(SDNode *N) {
5845 // If this is an FCOPYSIGN with same input types, we can treat it as a
5846 // normal (can trap) binary op.
5847 if (N->getOperand(0).getValueType() == N->getOperand(1).getValueType())
5848 return WidenVecRes_BinaryCanTrap(N);
5849
5850 // If the types are different, fall back to unrolling.
5851 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5852 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
5853}
5854
5855/// Result and first source operand are different scalar types, but must have
5856/// the same number of elements. There is an additional control argument which
5857/// should be passed through unchanged.
5858SDValue DAGTypeLegalizer::WidenVecRes_UnarySameEltsWithScalarArg(SDNode *N) {
5859 SDValue FpValue = N->getOperand(0);
5860 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5861 if (getTypeAction(FpValue.getValueType()) != TargetLowering::TypeWidenVector)
5862 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
5863 SDValue Arg = GetWidenedVector(FpValue);
5864 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, {Arg, N->getOperand(1)},
5865 N->getFlags());
5866}
5867
5868SDValue DAGTypeLegalizer::WidenVecRes_ExpOp(SDNode *N) {
5869 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5870 SDValue InOp = GetWidenedVector(N->getOperand(0));
5871 SDValue RHS = N->getOperand(1);
5872 EVT ExpVT = RHS.getValueType();
5873 SDValue ExpOp = RHS;
5874 if (ExpVT.isVector()) {
5875 EVT WideExpVT =
5877 ExpOp = ModifyToType(RHS, WideExpVT);
5878 }
5879
5880 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, ExpOp);
5881}
5882
5883SDValue DAGTypeLegalizer::WidenVecRes_Unary(SDNode *N) {
5884 // Unary op widening.
5885 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5886 SDValue InOp = GetWidenedVector(N->getOperand(0));
5887 if (N->getNumOperands() == 1)
5888 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, N->getFlags());
5889 if (N->getOpcode() == ISD::AssertNoFPClass)
5890 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp,
5891 N->getOperand(1), N->getFlags());
5892
5893 assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
5894 assert(N->isVPOpcode() && "Expected VP opcode");
5895
5896 SDValue Mask =
5897 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
5898 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT,
5899 {InOp, Mask, N->getOperand(2)});
5900}
5901
5902SDValue DAGTypeLegalizer::WidenVecRes_InregOp(SDNode *N) {
5903 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5904 EVT ExtVT = EVT::getVectorVT(*DAG.getContext(),
5905 cast<VTSDNode>(N->getOperand(1))->getVT()
5906 .getVectorElementType(),
5907 WidenVT.getVectorNumElements());
5908 SDValue WidenLHS = GetWidenedVector(N->getOperand(0));
5909 return DAG.getNode(N->getOpcode(), SDLoc(N),
5910 WidenVT, WidenLHS, DAG.getValueType(ExtVT));
5911}
5912
5913SDValue DAGTypeLegalizer::WidenVecRes_UnaryOpWithTwoResults(SDNode *N,
5914 unsigned ResNo) {
5915 EVT VT0 = N->getValueType(0);
5916 EVT VT1 = N->getValueType(1);
5917
5918 assert(VT0.isVector() && VT1.isVector() &&
5920 "expected both results to be vectors of matching element count");
5921
5922 LLVMContext &Ctx = *DAG.getContext();
5923 SDValue InOp = GetWidenedVector(N->getOperand(0));
5924
5925 EVT WidenVT = TLI.getTypeToTransformTo(Ctx, N->getValueType(ResNo));
5926 ElementCount WidenEC = WidenVT.getVectorElementCount();
5927
5928 EVT WidenVT0 = EVT::getVectorVT(Ctx, VT0.getVectorElementType(), WidenEC);
5929 EVT WidenVT1 = EVT::getVectorVT(Ctx, VT1.getVectorElementType(), WidenEC);
5930
5931 SDNode *WidenNode =
5932 DAG.getNode(N->getOpcode(), SDLoc(N), {WidenVT0, WidenVT1}, InOp)
5933 .getNode();
5934
5935 ReplaceOtherWidenResults(N, WidenNode, ResNo);
5936 return SDValue(WidenNode, ResNo);
5937}
5938
5939SDValue DAGTypeLegalizer::WidenVecRes_MERGE_VALUES(SDNode *N, unsigned ResNo) {
5940 SDValue WidenVec = DisintegrateMERGE_VALUES(N, ResNo);
5941 return GetWidenedVector(WidenVec);
5942}
5943
5944SDValue DAGTypeLegalizer::WidenVecRes_ADDRSPACECAST(SDNode *N) {
5945 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5946 SDValue InOp = GetWidenedVector(N->getOperand(0));
5947 auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
5948
5949 return DAG.getAddrSpaceCast(SDLoc(N), WidenVT, InOp,
5950 AddrSpaceCastN->getSrcAddressSpace(),
5951 AddrSpaceCastN->getDestAddressSpace());
5952}
5953
5954SDValue DAGTypeLegalizer::WidenVecRes_BITCAST(SDNode *N) {
5955 SDValue InOp = N->getOperand(0);
5956 EVT InVT = InOp.getValueType();
5957 EVT VT = N->getValueType(0);
5958 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
5959 SDLoc dl(N);
5960
5961 switch (getTypeAction(InVT)) {
5963 break;
5965 report_fatal_error("Scalarization of scalable vectors is not supported.");
5967 // If the incoming type is a vector that is being promoted, then
5968 // we know that the elements are arranged differently and that we
5969 // must perform the conversion using a stack slot.
5970 if (InVT.isVector())
5971 break;
5972
5973 // If the InOp is promoted to the same size, convert it. Otherwise,
5974 // fall out of the switch and widen the promoted input.
5975 SDValue NInOp = GetPromotedInteger(InOp);
5976 EVT NInVT = NInOp.getValueType();
5977 if (WidenVT.bitsEq(NInVT)) {
5978 // For big endian targets we need to shift the input integer or the
5979 // interesting bits will end up at the wrong place.
5980 if (DAG.getDataLayout().isBigEndian()) {
5981 unsigned ShiftAmt = NInVT.getSizeInBits() - InVT.getSizeInBits();
5982 NInOp = DAG.getNode(ISD::SHL, dl, NInVT, NInOp,
5983 DAG.getShiftAmountConstant(ShiftAmt, NInVT, dl));
5984 }
5985 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NInOp);
5986 }
5987 InOp = NInOp;
5988 InVT = NInVT;
5989 break;
5990 }
5998 break;
6000 // If the InOp is widened to the same size, convert it. Otherwise, fall
6001 // out of the switch and widen the widened input.
6002 InOp = GetWidenedVector(InOp);
6003 InVT = InOp.getValueType();
6004 if (WidenVT.bitsEq(InVT))
6005 // The input widens to the same size. Convert to the widen value.
6006 return DAG.getNode(ISD::BITCAST, dl, WidenVT, InOp);
6007 break;
6008 }
6009
6010 unsigned WidenSize = WidenVT.getSizeInBits();
6011 unsigned InSize = InVT.getSizeInBits();
6012 unsigned InScalarSize = InVT.getScalarSizeInBits();
6013 // x86mmx is not an acceptable vector element type, so don't try.
6014 if (WidenSize % InScalarSize == 0 && InVT != MVT::x86mmx) {
6015 // Determine new input vector type. The new input vector type will use
6016 // the same element type (if its a vector) or use the input type as a
6017 // vector. It is the same size as the type to widen to.
6018 EVT NewInVT;
6019 unsigned NewNumParts = WidenSize / InSize;
6020 if (InVT.isVector()) {
6021 EVT InEltVT = InVT.getVectorElementType();
6022 NewInVT = EVT::getVectorVT(*DAG.getContext(), InEltVT,
6023 WidenSize / InEltVT.getSizeInBits());
6024 } else {
6025 // For big endian systems, using the promoted input scalar type
6026 // to produce the scalar_to_vector would put the desired bits into
6027 // the least significant byte(s) of the wider element zero. This
6028 // will mean that the users of the result vector are using incorrect
6029 // bits. Use the original input type instead. Although either input
6030 // type can be used on little endian systems, for consistency we
6031 // use the original type there as well.
6032 EVT OrigInVT = N->getOperand(0).getValueType();
6033 NewNumParts = WidenSize / OrigInVT.getSizeInBits();
6034 NewInVT = EVT::getVectorVT(*DAG.getContext(), OrigInVT, NewNumParts);
6035 }
6036
6037 if (TLI.isTypeLegal(NewInVT)) {
6038 SDValue NewVec;
6039 if (InVT.isVector()) {
6040 // Because the result and the input are different vector types, widening
6041 // the result could create a legal type but widening the input might
6042 // make it an illegal type that might lead to repeatedly splitting the
6043 // input and then widening it. To avoid this, we widen the input only if
6044 // it results in a legal type.
6045 if (WidenSize % InSize == 0) {
6046 SmallVector<SDValue, 16> Ops(NewNumParts, DAG.getPOISON(InVT));
6047 Ops[0] = InOp;
6048
6049 NewVec = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewInVT, Ops);
6050 } else {
6052 DAG.ExtractVectorElements(InOp, Ops);
6053 Ops.append(WidenSize / InScalarSize - Ops.size(),
6054 DAG.getPOISON(InVT.getVectorElementType()));
6055
6056 NewVec = DAG.getNode(ISD::BUILD_VECTOR, dl, NewInVT, Ops);
6057 }
6058 } else {
6059 NewVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewInVT, InOp);
6060 }
6061 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NewVec);
6062 }
6063 }
6064
6065 return CreateStackStoreLoad(InOp, WidenVT);
6066}
6067
6068SDValue DAGTypeLegalizer::WidenVecRes_LOOP_DEPENDENCE_MASK(SDNode *N) {
6069 return DAG.getNode(
6070 N->getOpcode(), SDLoc(N),
6071 TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)),
6072 N->getOperand(0), N->getOperand(1), N->getOperand(2), N->getOperand(3));
6073}
6074
6075SDValue DAGTypeLegalizer::WidenVecRes_BUILD_VECTOR(SDNode *N) {
6076 SDLoc dl(N);
6077 // Build a vector with poison for the new nodes.
6078 EVT VT = N->getValueType(0);
6079
6080 // Integer BUILD_VECTOR operands may be larger than the node's vector element
6081 // type. The POISONs need to have the same type as the existing operands.
6082 EVT EltVT = N->getOperand(0).getValueType();
6083 unsigned NumElts = VT.getVectorNumElements();
6084
6085 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6086 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6087
6088 SmallVector<SDValue, 16> NewOps(N->ops());
6089 assert(WidenNumElts >= NumElts && "Shrinking vector instead of widening!");
6090 NewOps.append(WidenNumElts - NumElts, DAG.getPOISON(EltVT));
6091
6092 return DAG.getBuildVector(WidenVT, dl, NewOps);
6093}
6094
6095SDValue DAGTypeLegalizer::WidenVecRes_CONCAT_VECTORS(SDNode *N) {
6096 EVT InVT = N->getOperand(0).getValueType();
6097 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6098 SDLoc dl(N);
6099 unsigned NumOperands = N->getNumOperands();
6100
6101 bool InputWidened = false; // Indicates we need to widen the input.
6102 if (getTypeAction(InVT) != TargetLowering::TypeWidenVector) {
6103 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6104 unsigned NumInElts = InVT.getVectorMinNumElements();
6105 if (WidenNumElts % NumInElts == 0) {
6106 // Add undef vectors to widen to correct length.
6107 unsigned NumConcat = WidenNumElts / NumInElts;
6108 SDValue UndefVal = DAG.getPOISON(InVT);
6109 SmallVector<SDValue, 16> Ops(NumConcat);
6110 for (unsigned i=0; i < NumOperands; ++i)
6111 Ops[i] = N->getOperand(i);
6112 for (unsigned i = NumOperands; i != NumConcat; ++i)
6113 Ops[i] = UndefVal;
6114 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Ops);
6115 }
6116 } else {
6117 InputWidened = true;
6118 if (WidenVT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
6119 // The inputs and the result are widen to the same value.
6120 unsigned i;
6121 for (i=1; i < NumOperands; ++i)
6122 if (!N->getOperand(i).isUndef())
6123 break;
6124
6125 if (i == NumOperands)
6126 // Everything but the first operand is an UNDEF so just return the
6127 // widened first operand.
6128 return GetWidenedVector(N->getOperand(0));
6129
6130 if (NumOperands == 2) {
6131 assert(!WidenVT.isScalableVector() &&
6132 "Cannot use vector shuffles to widen CONCAT_VECTOR result");
6133 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6134 unsigned NumInElts = InVT.getVectorNumElements();
6135
6136 // Replace concat of two operands with a shuffle.
6137 SmallVector<int, 16> MaskOps(WidenNumElts, -1);
6138 for (unsigned i = 0; i < NumInElts; ++i) {
6139 MaskOps[i] = i;
6140 MaskOps[i + NumInElts] = i + WidenNumElts;
6141 }
6142 return DAG.getVectorShuffle(WidenVT, dl,
6143 GetWidenedVector(N->getOperand(0)),
6144 GetWidenedVector(N->getOperand(1)),
6145 MaskOps);
6146 }
6147 }
6148 }
6149
6150 assert(!WidenVT.isScalableVector() &&
6151 "Cannot use build vectors to widen CONCAT_VECTOR result");
6152 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6153 unsigned NumInElts = InVT.getVectorNumElements();
6154
6155 // Fall back to use extracts and build vector.
6156 EVT EltVT = WidenVT.getVectorElementType();
6157 SmallVector<SDValue, 16> Ops(WidenNumElts);
6158 unsigned Idx = 0;
6159 for (unsigned i=0; i < NumOperands; ++i) {
6160 SDValue InOp = N->getOperand(i);
6161 if (InputWidened)
6162 InOp = GetWidenedVector(InOp);
6163 for (unsigned j = 0; j < NumInElts; ++j)
6164 Ops[Idx++] = DAG.getExtractVectorElt(dl, EltVT, InOp, j);
6165 }
6166 SDValue UndefVal = DAG.getPOISON(EltVT);
6167 for (; Idx < WidenNumElts; ++Idx)
6168 Ops[Idx] = UndefVal;
6169 return DAG.getBuildVector(WidenVT, dl, Ops);
6170}
6171
6172SDValue DAGTypeLegalizer::WidenVecRes_INSERT_SUBVECTOR(SDNode *N) {
6173 EVT VT = N->getValueType(0);
6174 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6175 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
6176 SDValue InOp2 = N->getOperand(1);
6177 SDValue Idx = N->getOperand(2);
6178 SDLoc dl(N);
6179 return DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WidenVT, InOp1, InOp2, Idx);
6180}
6181
6182SDValue DAGTypeLegalizer::WidenVecRes_EXTRACT_SUBVECTOR(SDNode *N) {
6183 EVT VT = N->getValueType(0);
6184 EVT EltVT = VT.getVectorElementType();
6185 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6186 SDValue InOp = N->getOperand(0);
6187 SDValue Idx = N->getOperand(1);
6188 SDLoc dl(N);
6189
6190 auto InOpTypeAction = getTypeAction(InOp.getValueType());
6191 if (InOpTypeAction == TargetLowering::TypeWidenVector)
6192 InOp = GetWidenedVector(InOp);
6193
6194 EVT InVT = InOp.getValueType();
6195
6196 // Check if we can just return the input vector after widening.
6197 uint64_t IdxVal = Idx->getAsZExtVal();
6198 if (IdxVal == 0 && InVT == WidenVT)
6199 return InOp;
6200
6201 // Check if we can extract from the vector.
6202 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6203 unsigned InNumElts = InVT.getVectorMinNumElements();
6204 unsigned VTNumElts = VT.getVectorMinNumElements();
6205 assert(IdxVal % VTNumElts == 0 &&
6206 "Expected Idx to be a multiple of subvector minimum vector length");
6207 if (IdxVal % WidenNumElts == 0 && IdxVal + WidenNumElts < InNumElts)
6208 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, WidenVT, InOp, Idx);
6209
6210 if (VT.isScalableVector()) {
6211 // Try to split the operation up into smaller extracts and concat the
6212 // results together, e.g.
6213 // nxv6i64 extract_subvector(nxv12i64, 6)
6214 // <->
6215 // nxv8i64 concat(
6216 // nxv2i64 extract_subvector(nxv16i64, 6)
6217 // nxv2i64 extract_subvector(nxv16i64, 8)
6218 // nxv2i64 extract_subvector(nxv16i64, 10)
6219 // undef)
6220 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
6221 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
6222 "down type's element count");
6223 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
6225 // Avoid recursion around e.g. nxv1i8.
6226 if (getTypeAction(PartVT) != TargetLowering::TypeWidenVector) {
6228 unsigned I = 0;
6229 for (; I < VTNumElts / GCD; ++I)
6230 Parts.push_back(
6231 DAG.getExtractSubvector(dl, PartVT, InOp, IdxVal + I * GCD));
6232 for (; I < WidenNumElts / GCD; ++I)
6233 Parts.push_back(DAG.getPOISON(PartVT));
6234
6235 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
6236 }
6237
6238 // Fallback to extracting through memory.
6239
6240 Align Alignment = DAG.getReducedAlign(InVT, /*UseABI=*/false);
6241 SDValue StackPtr = DAG.CreateStackTemporary(InVT.getStoreSize(), Alignment);
6242 MachineFunction &MF = DAG.getMachineFunction();
6243 int FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
6244 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
6245
6246 MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
6249 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
6252
6253 // Write out the input vector.
6254 SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, InOp, StackPtr, StoreMMO);
6255
6256 // Build a mask to match the length of the non-widened result.
6257 SDValue Mask =
6258 DAG.getMaskFromElementCount(dl, WidenVT, VT.getVectorElementCount());
6259
6260 // Read back the sub-vector setting the remaining lanes to poison.
6261 StackPtr = TLI.getVectorSubVecPointer(DAG, StackPtr, InVT, VT, Idx);
6262 return DAG.getMaskedLoad(
6263 WidenVT, dl, Ch, StackPtr, DAG.getUNDEF(StackPtr.getValueType()), Mask,
6264 DAG.getPOISON(WidenVT), VT, LoadMMO, ISD::UNINDEXED, ISD::NON_EXTLOAD);
6265 }
6266
6267 // We could try widening the input to the right length but for now, extract
6268 // the original elements, fill the rest with undefs and build a vector.
6269 SmallVector<SDValue, 16> Ops(WidenNumElts);
6270 unsigned i;
6271 for (i = 0; i < VTNumElts; ++i)
6272 Ops[i] = DAG.getExtractVectorElt(dl, EltVT, InOp, IdxVal + i);
6273
6274 SDValue UndefVal = DAG.getPOISON(EltVT);
6275 for (; i < WidenNumElts; ++i)
6276 Ops[i] = UndefVal;
6277 return DAG.getBuildVector(WidenVT, dl, Ops);
6278}
6279
6280SDValue DAGTypeLegalizer::WidenVecRes_AssertZext(SDNode *N) {
6281 SDValue InOp = ModifyToType(
6282 N->getOperand(0),
6283 TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)), true);
6284 return DAG.getNode(ISD::AssertZext, SDLoc(N), InOp.getValueType(), InOp,
6285 N->getOperand(1));
6286}
6287
6288SDValue DAGTypeLegalizer::WidenVecRes_INSERT_VECTOR_ELT(SDNode *N) {
6289 SDValue InOp = GetWidenedVector(N->getOperand(0));
6290 return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(N),
6291 InOp.getValueType(), InOp,
6292 N->getOperand(1), N->getOperand(2));
6293}
6294
6295SDValue DAGTypeLegalizer::WidenVecRes_LOAD(SDNode *N) {
6296 LoadSDNode *LD = cast<LoadSDNode>(N);
6297 ISD::LoadExtType ExtType = LD->getExtensionType();
6298
6299 // A vector must always be stored in memory as-is, i.e. without any padding
6300 // between the elements, since various code depend on it, e.g. in the
6301 // handling of a bitcast of a vector type to int, which may be done with a
6302 // vector store followed by an integer load. A vector that does not have
6303 // elements that are byte-sized must therefore be stored as an integer
6304 // built out of the extracted vector elements.
6305 if (!LD->getMemoryVT().isByteSized()) {
6306 SDValue Value, NewChain;
6307 std::tie(Value, NewChain) = TLI.scalarizeVectorLoad(LD, DAG);
6308 ReplaceValueWith(SDValue(LD, 0), Value);
6309 ReplaceValueWith(SDValue(LD, 1), NewChain);
6310 return SDValue();
6311 }
6312
6313 // Generate a vector-predicated load if it is custom/legal on the target. To
6314 // avoid possible recursion, only do this if the widened mask type is legal.
6315 // FIXME: Not all targets may support EVL in VP_LOAD. These will have been
6316 // removed from the IR by the ExpandVectorPredication pass but we're
6317 // reintroducing them here.
6318 EVT VT = LD->getValueType(0);
6319 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6320 EVT WideMaskVT = getSetCCResultType(WideVT);
6321
6322 if (ExtType == ISD::NON_EXTLOAD &&
6323 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WideVT) &&
6324 TLI.isTypeLegal(WideMaskVT)) {
6325 SDLoc DL(N);
6326 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
6327 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
6329 SDValue NewLoad =
6330 DAG.getLoadVP(LD->getAddressingMode(), ISD::NON_EXTLOAD, WideVT, DL,
6331 LD->getChain(), LD->getBasePtr(), LD->getOffset(), Mask,
6332 EVL, LD->getMemoryVT(), LD->getMemOperand());
6333
6334 // Modified the chain - switch anything that used the old chain to use
6335 // the new one.
6336 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6337
6338 return NewLoad;
6339 }
6340
6342 SmallVector<SDValue, 16> LdChain; // Chain for the series of load
6343 if (ExtType != ISD::NON_EXTLOAD)
6344 Result = GenWidenVectorExtLoads(LdChain, LD, ExtType);
6345 else
6346 Result = GenWidenVectorLoads(LdChain, LD);
6347
6348 if (Result) {
6349 // If we generate a single load, we can use that for the chain. Otherwise,
6350 // build a factor node to remember the multiple loads are independent and
6351 // chain to that.
6352 SDValue NewChain;
6353 if (LdChain.size() == 1)
6354 NewChain = LdChain[0];
6355 else
6356 NewChain = DAG.getNode(ISD::TokenFactor, SDLoc(LD), MVT::Other, LdChain);
6357
6358 // Modified the chain - switch anything that used the old chain to use
6359 // the new one.
6360 ReplaceValueWith(SDValue(N, 1), NewChain);
6361
6362 return Result;
6363 }
6364
6365 if (VT.isVector()) {
6366 // If all else fails replace the load with a wide masked load.
6367 SDLoc DL(N);
6368 SDValue Mask =
6369 DAG.getMaskFromElementCount(DL, WideVT, VT.getVectorElementCount());
6370
6371 SDValue NewLoad = DAG.getMaskedLoad(
6372 WideVT, DL, LD->getChain(), LD->getBasePtr(), LD->getOffset(), Mask,
6373 DAG.getPOISON(WideVT), LD->getMemoryVT(), LD->getMemOperand(),
6374 LD->getAddressingMode(), LD->getExtensionType());
6375
6376 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6377 return NewLoad;
6378 }
6379
6380 report_fatal_error("Unable to widen vector load");
6381}
6382
6383SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD(VPLoadSDNode *N) {
6384 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6385 SDValue Mask = N->getMask();
6386 SDValue EVL = N->getVectorLength();
6387 ISD::LoadExtType ExtType = N->getExtensionType();
6388 SDLoc dl(N);
6389
6390 // The mask should be widened as well
6391 assert(getTypeAction(Mask.getValueType()) ==
6393 "Unable to widen binary VP op");
6394 Mask = GetWidenedVector(Mask);
6395 assert(Mask.getValueType().getVectorElementCount() ==
6396 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
6397 .getVectorElementCount() &&
6398 "Unable to widen vector load");
6399
6400 SDValue Res =
6401 DAG.getLoadVP(N->getAddressingMode(), ExtType, WidenVT, dl, N->getChain(),
6402 N->getBasePtr(), N->getOffset(), Mask, EVL,
6403 N->getMemoryVT(), N->getMemOperand(), N->isExpandingLoad());
6404 // Legalize the chain result - switch anything that used the old chain to
6405 // use the new one.
6406 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6407 return Res;
6408}
6409
6410SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD_FF(VPLoadFFSDNode *N) {
6411 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6412 SDValue Mask = N->getMask();
6413 SDValue EVL = N->getVectorLength();
6414 SDLoc dl(N);
6415
6416 // The mask should be widened as well
6417 assert(getTypeAction(Mask.getValueType()) ==
6419 "Unable to widen binary VP op");
6420 Mask = GetWidenedVector(Mask);
6421 assert(Mask.getValueType().getVectorElementCount() ==
6422 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
6423 .getVectorElementCount() &&
6424 "Unable to widen vector load");
6425
6426 SDValue Res = DAG.getLoadFFVP(WidenVT, dl, N->getChain(), N->getBasePtr(),
6427 Mask, EVL, N->getMemOperand());
6428 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6429 ReplaceValueWith(SDValue(N, 2), Res.getValue(2));
6430 return Res;
6431}
6432
6433SDValue DAGTypeLegalizer::WidenVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode *N) {
6434 SDLoc DL(N);
6435
6436 // The mask should be widened as well
6437 SDValue Mask = N->getMask();
6438 assert(getTypeAction(Mask.getValueType()) ==
6440 "Unable to widen VP strided load");
6441 Mask = GetWidenedVector(Mask);
6442
6443 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6444 assert(Mask.getValueType().getVectorElementCount() ==
6445 WidenVT.getVectorElementCount() &&
6446 "Data and mask vectors should have the same number of elements");
6447
6448 SDValue Res = DAG.getStridedLoadVP(
6449 N->getAddressingMode(), N->getExtensionType(), WidenVT, DL, N->getChain(),
6450 N->getBasePtr(), N->getOffset(), N->getStride(), Mask,
6451 N->getVectorLength(), N->getMemoryVT(), N->getMemOperand(),
6452 N->isExpandingLoad());
6453
6454 // Legalize the chain result - switch anything that used the old chain to
6455 // use the new one.
6456 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6457 return Res;
6458}
6459
6460SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_COMPRESS(SDNode *N) {
6461 SDValue Vec = N->getOperand(0);
6462 SDValue Mask = N->getOperand(1);
6463 SDValue Passthru = N->getOperand(2);
6464 EVT WideVecVT =
6465 TLI.getTypeToTransformTo(*DAG.getContext(), Vec.getValueType());
6466 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
6467 Mask.getValueType().getVectorElementType(),
6468 WideVecVT.getVectorElementCount());
6469
6470 SDValue WideVec = ModifyToType(Vec, WideVecVT);
6471 SDValue WideMask = ModifyToType(Mask, WideMaskVT, /*FillWithZeroes=*/true);
6472 SDValue WidePassthru = ModifyToType(Passthru, WideVecVT);
6473 return DAG.getNode(ISD::VECTOR_COMPRESS, SDLoc(N), WideVecVT, WideVec,
6474 WideMask, WidePassthru);
6475}
6476
6477SDValue DAGTypeLegalizer::WidenVecRes_MLOAD(MaskedLoadSDNode *N) {
6478 EVT VT = N->getValueType(0);
6479 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6480 SDValue Mask = N->getMask();
6481 EVT MaskVT = Mask.getValueType();
6482 SDValue PassThru = GetWidenedVector(N->getPassThru());
6483 ISD::LoadExtType ExtType = N->getExtensionType();
6484 SDLoc dl(N);
6485
6486 EVT WideMaskVT =
6487 EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(),
6488 WidenVT.getVectorElementCount());
6489
6490 if (ExtType == ISD::NON_EXTLOAD &&
6491 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WidenVT) &&
6492 TLI.isTypeLegal(WideMaskVT) &&
6493 // If there is a passthru, we shouldn't use vp.load. However,
6494 // type legalizer will struggle on masked.load with
6495 // scalable vectors, so for scalable vectors, we still use vp.load
6496 // but manually merge the load result with the passthru using vp.select.
6497 (N->getPassThru()->isUndef() || VT.isScalableVector())) {
6498 Mask = DAG.getInsertSubvector(dl, DAG.getUNDEF(WideMaskVT), Mask, 0);
6499 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
6501 SDValue NewLoad =
6502 DAG.getLoadVP(N->getAddressingMode(), ISD::NON_EXTLOAD, WidenVT, dl,
6503 N->getChain(), N->getBasePtr(), N->getOffset(), Mask, EVL,
6504 N->getMemoryVT(), N->getMemOperand());
6505 SDValue NewVal = NewLoad;
6506
6507 // Manually merge with vp.select
6508 if (!N->getPassThru()->isUndef()) {
6509 assert(WidenVT.isScalableVector());
6510 NewVal =
6511 DAG.getNode(ISD::VP_SELECT, dl, WidenVT, Mask, NewVal, PassThru, EVL);
6512 }
6513
6514 // Modified the chain - switch anything that used the old chain to use
6515 // the new one.
6516 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6517
6518 return NewVal;
6519 }
6520
6521 // The mask should be widened as well
6522 Mask = ModifyToType(Mask, WideMaskVT, true);
6523
6524 SDValue Res = DAG.getMaskedLoad(
6525 WidenVT, dl, N->getChain(), N->getBasePtr(), N->getOffset(), Mask,
6526 PassThru, N->getMemoryVT(), N->getMemOperand(), N->getAddressingMode(),
6527 ExtType, N->isExpandingLoad());
6528 // Legalize the chain result - switch anything that used the old chain to
6529 // use the new one.
6530 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6531 return Res;
6532}
6533
6534SDValue DAGTypeLegalizer::WidenVecRes_MGATHER(MaskedGatherSDNode *N) {
6535
6536 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6537 SDValue Mask = N->getMask();
6538 EVT MaskVT = Mask.getValueType();
6539 SDValue PassThru = GetWidenedVector(N->getPassThru());
6540 SDValue Scale = N->getScale();
6541 unsigned NumElts = WideVT.getVectorNumElements();
6542 SDLoc dl(N);
6543
6544 // The mask should be widened as well
6545 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
6546 MaskVT.getVectorElementType(),
6547 WideVT.getVectorNumElements());
6548 Mask = ModifyToType(Mask, WideMaskVT, true);
6549
6550 // Widen the Index operand
6551 SDValue Index = N->getIndex();
6552 EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
6553 Index.getValueType().getScalarType(),
6554 NumElts);
6555 Index = ModifyToType(Index, WideIndexVT);
6556 SDValue Ops[] = { N->getChain(), PassThru, Mask, N->getBasePtr(), Index,
6557 Scale };
6558
6559 // Widen the MemoryType
6560 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
6561 N->getMemoryVT().getScalarType(), NumElts);
6562 SDValue Res = DAG.getMaskedGather(DAG.getVTList(WideVT, MVT::Other),
6563 WideMemVT, dl, Ops, N->getMemOperand(),
6564 N->getIndexType(), N->getExtensionType());
6565
6566 // Legalize the chain result - switch anything that used the old chain to
6567 // use the new one.
6568 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6569 return Res;
6570}
6571
6572SDValue DAGTypeLegalizer::WidenVecRes_VP_GATHER(VPGatherSDNode *N) {
6573 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6574 SDValue Mask = N->getMask();
6575 SDValue Scale = N->getScale();
6576 ElementCount WideEC = WideVT.getVectorElementCount();
6577 SDLoc dl(N);
6578
6579 SDValue Index = GetWidenedVector(N->getIndex());
6580 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
6581 N->getMemoryVT().getScalarType(), WideEC);
6582 Mask = GetWidenedMask(Mask, WideEC);
6583
6584 SDValue Ops[] = {N->getChain(), N->getBasePtr(), Index, Scale,
6585 Mask, N->getVectorLength()};
6586 SDValue Res = DAG.getGatherVP(DAG.getVTList(WideVT, MVT::Other), WideMemVT,
6587 dl, Ops, N->getMemOperand(), N->getIndexType());
6588
6589 // Legalize the chain result - switch anything that used the old chain to
6590 // use the new one.
6591 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6592 return Res;
6593}
6594
6595SDValue DAGTypeLegalizer::WidenVecRes_ScalarOp(SDNode *N) {
6596 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6597 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, N->getOperand(0));
6598}
6599
6600// Return true is this is a SETCC node or a strict version of it.
6601static inline bool isSETCCOp(unsigned Opcode) {
6602 switch (Opcode) {
6603 case ISD::SETCC:
6604 case ISD::STRICT_FSETCC:
6606 return true;
6607 }
6608 return false;
6609}
6610
6611// Return true if this is a node that could have two SETCCs as operands.
6612static inline bool isLogicalMaskOp(unsigned Opcode) {
6613 switch (Opcode) {
6614 case ISD::AND:
6615 case ISD::OR:
6616 case ISD::XOR:
6617 return true;
6618 }
6619 return false;
6620}
6621
6622// If N is a SETCC or a strict variant of it, return the type
6623// of the compare operands.
6625 unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
6626 return N->getOperand(OpNo).getValueType();
6627}
6628
6629// This is used just for the assert in convertMask(). Check that this either
6630// a SETCC or a previously handled SETCC by convertMask().
6631#ifndef NDEBUG
6632static inline bool isSETCCorConvertedSETCC(SDValue N) {
6633 if (N.getOpcode() == ISD::EXTRACT_SUBVECTOR)
6634 N = N.getOperand(0);
6635 else if (N.getOpcode() == ISD::CONCAT_VECTORS) {
6636 for (unsigned i = 1; i < N->getNumOperands(); ++i)
6637 if (!N->getOperand(i)->isUndef())
6638 return false;
6639 N = N.getOperand(0);
6640 }
6641
6642 if (N.getOpcode() == ISD::TRUNCATE)
6643 N = N.getOperand(0);
6644 else if (N.getOpcode() == ISD::SIGN_EXTEND)
6645 N = N.getOperand(0);
6646
6647 if (isLogicalMaskOp(N.getOpcode()))
6648 return isSETCCorConvertedSETCC(N.getOperand(0)) &&
6649 isSETCCorConvertedSETCC(N.getOperand(1));
6650
6651 return (isSETCCOp(N.getOpcode()) ||
6653}
6654#endif
6655
6656// Return a mask of vector type MaskVT to replace InMask. Also adjust MaskVT
6657// to ToMaskVT if needed with vector extension or truncation.
6658SDValue DAGTypeLegalizer::convertMask(SDValue InMask, EVT MaskVT,
6659 EVT ToMaskVT) {
6660 // Currently a SETCC or a AND/OR/XOR with two SETCCs are handled.
6661 // FIXME: This code seems to be too restrictive, we might consider
6662 // generalizing it or dropping it.
6663 assert(isSETCCorConvertedSETCC(InMask) && "Unexpected mask argument.");
6664
6665 // Make a new Mask node, with a legal result VT.
6666 SDValue Mask;
6668 for (unsigned i = 0, e = InMask->getNumOperands(); i < e; ++i)
6669 Ops.push_back(InMask->getOperand(i));
6670 if (InMask->isStrictFPOpcode()) {
6671 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask),
6672 { MaskVT, MVT::Other }, Ops);
6673 ReplaceValueWith(InMask.getValue(1), Mask.getValue(1));
6674 }
6675 else
6676 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask), MaskVT, Ops);
6677
6678 // If MaskVT has smaller or bigger elements than ToMaskVT, a vector sign
6679 // extend or truncate is needed.
6680 LLVMContext &Ctx = *DAG.getContext();
6681 unsigned MaskScalarBits = MaskVT.getScalarSizeInBits();
6682 unsigned ToMaskScalBits = ToMaskVT.getScalarSizeInBits();
6683 if (MaskScalarBits < ToMaskScalBits) {
6684 EVT ExtVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
6685 MaskVT.getVectorNumElements());
6686 Mask = DAG.getNode(ISD::SIGN_EXTEND, SDLoc(Mask), ExtVT, Mask);
6687 } else if (MaskScalarBits > ToMaskScalBits) {
6688 EVT TruncVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
6689 MaskVT.getVectorNumElements());
6690 Mask = DAG.getNode(ISD::TRUNCATE, SDLoc(Mask), TruncVT, Mask);
6691 }
6692
6693 assert(Mask->getValueType(0).getScalarSizeInBits() ==
6694 ToMaskVT.getScalarSizeInBits() &&
6695 "Mask should have the right element size by now.");
6696
6697 // Adjust Mask to the right number of elements.
6698 unsigned CurrMaskNumEls = Mask->getValueType(0).getVectorNumElements();
6699 if (CurrMaskNumEls > ToMaskVT.getVectorNumElements()) {
6700 Mask = DAG.getExtractSubvector(SDLoc(Mask), ToMaskVT, Mask, 0);
6701 } else if (CurrMaskNumEls < ToMaskVT.getVectorNumElements()) {
6702 unsigned NumSubVecs = (ToMaskVT.getVectorNumElements() / CurrMaskNumEls);
6703 EVT SubVT = Mask->getValueType(0);
6704 SmallVector<SDValue, 16> SubOps(NumSubVecs, DAG.getUNDEF(SubVT));
6705 SubOps[0] = Mask;
6706 Mask = DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Mask), ToMaskVT, SubOps);
6707 }
6708
6709 assert((Mask->getValueType(0) == ToMaskVT) &&
6710 "A mask of ToMaskVT should have been produced by now.");
6711
6712 return Mask;
6713}
6714
6715// This method tries to handle some special cases for the vselect mask
6716// and if needed adjusting the mask vector type to match that of the VSELECT.
6717// Without it, many cases end up with scalarization of the SETCC, with many
6718// unnecessary instructions.
6719SDValue DAGTypeLegalizer::WidenVSELECTMask(SDNode *N) {
6720 LLVMContext &Ctx = *DAG.getContext();
6721 SDValue Cond = N->getOperand(0);
6722
6723 if (N->getOpcode() != ISD::VSELECT)
6724 return SDValue();
6725
6726 if (!isSETCCOp(Cond->getOpcode()) && !isLogicalMaskOp(Cond->getOpcode()))
6727 return SDValue();
6728
6729 // If this is a splitted VSELECT that was previously already handled, do
6730 // nothing.
6731 EVT CondVT = Cond->getValueType(0);
6732 if (CondVT.getScalarSizeInBits() != 1)
6733 return SDValue();
6734
6735 EVT VSelVT = N->getValueType(0);
6736
6737 // This method can't handle scalable vector types.
6738 // FIXME: This support could be added in the future.
6739 if (VSelVT.isScalableVector())
6740 return SDValue();
6741
6742 // Only handle vector types which are a power of 2.
6743 if (!isPowerOf2_64(VSelVT.getSizeInBits()))
6744 return SDValue();
6745
6746 // Don't touch if this will be scalarized.
6747 EVT FinalVT = VSelVT;
6748 while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
6749 FinalVT = FinalVT.getHalfNumVectorElementsVT(Ctx);
6750
6751 if (FinalVT.getVectorNumElements() == 1)
6752 return SDValue();
6753
6754 // If there is support for an i1 vector mask, don't touch.
6755 if (isSETCCOp(Cond.getOpcode())) {
6756 EVT SetCCOpVT = getSETCCOperandType(Cond);
6757 while (TLI.getTypeAction(Ctx, SetCCOpVT) != TargetLowering::TypeLegal)
6758 SetCCOpVT = TLI.getTypeToTransformTo(Ctx, SetCCOpVT);
6759 EVT SetCCResVT = getSetCCResultType(SetCCOpVT);
6760 if (SetCCResVT.getScalarSizeInBits() == 1)
6761 return SDValue();
6762 } else if (CondVT.getScalarType() == MVT::i1) {
6763 // If there is support for an i1 vector mask (or only scalar i1 conditions),
6764 // don't touch.
6765 while (TLI.getTypeAction(Ctx, CondVT) != TargetLowering::TypeLegal)
6766 CondVT = TLI.getTypeToTransformTo(Ctx, CondVT);
6767
6768 if (CondVT.getScalarType() == MVT::i1)
6769 return SDValue();
6770 }
6771
6772 // Widen the vselect result type if needed.
6773 if (getTypeAction(VSelVT) == TargetLowering::TypeWidenVector)
6774 VSelVT = TLI.getTypeToTransformTo(Ctx, VSelVT);
6775
6776 // The mask of the VSELECT should have integer elements.
6777 EVT ToMaskVT = VSelVT;
6778 if (!ToMaskVT.getScalarType().isInteger())
6779 ToMaskVT = ToMaskVT.changeVectorElementTypeToInteger();
6780
6781 SDValue Mask;
6782 if (isSETCCOp(Cond->getOpcode())) {
6783 EVT MaskVT = getSetCCResultType(getSETCCOperandType(Cond));
6784 Mask = convertMask(Cond, MaskVT, ToMaskVT);
6785 } else if (isLogicalMaskOp(Cond->getOpcode()) &&
6786 isSETCCOp(Cond->getOperand(0).getOpcode()) &&
6787 isSETCCOp(Cond->getOperand(1).getOpcode())) {
6788 // Cond is (AND/OR/XOR (SETCC, SETCC))
6789 SDValue SETCC0 = Cond->getOperand(0);
6790 SDValue SETCC1 = Cond->getOperand(1);
6791 EVT VT0 = getSetCCResultType(getSETCCOperandType(SETCC0));
6792 EVT VT1 = getSetCCResultType(getSETCCOperandType(SETCC1));
6793 unsigned ScalarBits0 = VT0.getScalarSizeInBits();
6794 unsigned ScalarBits1 = VT1.getScalarSizeInBits();
6795 unsigned ScalarBits_ToMask = ToMaskVT.getScalarSizeInBits();
6796 EVT MaskVT;
6797 // If the two SETCCs have different VTs, either extend/truncate one of
6798 // them to the other "towards" ToMaskVT, or truncate one and extend the
6799 // other to ToMaskVT.
6800 if (ScalarBits0 != ScalarBits1) {
6801 EVT NarrowVT = ((ScalarBits0 < ScalarBits1) ? VT0 : VT1);
6802 EVT WideVT = ((NarrowVT == VT0) ? VT1 : VT0);
6803 if (ScalarBits_ToMask >= WideVT.getScalarSizeInBits())
6804 MaskVT = WideVT;
6805 else if (ScalarBits_ToMask <= NarrowVT.getScalarSizeInBits())
6806 MaskVT = NarrowVT;
6807 else
6808 MaskVT = ToMaskVT;
6809 } else
6810 // If the two SETCCs have the same VT, don't change it.
6811 MaskVT = VT0;
6812
6813 // Make new SETCCs and logical nodes.
6814 SETCC0 = convertMask(SETCC0, VT0, MaskVT);
6815 SETCC1 = convertMask(SETCC1, VT1, MaskVT);
6816 Cond = DAG.getNode(Cond->getOpcode(), SDLoc(Cond), MaskVT, SETCC0, SETCC1);
6817
6818 // Convert the logical op for VSELECT if needed.
6819 Mask = convertMask(Cond, MaskVT, ToMaskVT);
6820 } else
6821 return SDValue();
6822
6823 return Mask;
6824}
6825
6826SDValue DAGTypeLegalizer::WidenVecRes_Select(SDNode *N) {
6827 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6828 ElementCount WidenEC = WidenVT.getVectorElementCount();
6829
6830 SDValue Cond1 = N->getOperand(0);
6831 EVT CondVT = Cond1.getValueType();
6832 unsigned Opcode = N->getOpcode();
6833 if (CondVT.isVector()) {
6834 if (SDValue WideCond = WidenVSELECTMask(N)) {
6835 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
6836 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
6837 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
6838 return DAG.getNode(Opcode, SDLoc(N), WidenVT, WideCond, InOp1, InOp2);
6839 }
6840
6841 EVT CondEltVT = CondVT.getVectorElementType();
6842 EVT CondWidenVT = EVT::getVectorVT(*DAG.getContext(), CondEltVT, WidenEC);
6843 if (getTypeAction(CondVT) == TargetLowering::TypeWidenVector)
6844 Cond1 = GetWidenedVector(Cond1);
6845
6846 // If we have to split the condition there is no point in widening the
6847 // select. This would result in an cycle of widening the select ->
6848 // widening the condition operand -> splitting the condition operand ->
6849 // splitting the select -> widening the select. Instead split this select
6850 // further and widen the resulting type.
6851 if (getTypeAction(CondVT) == TargetLowering::TypeSplitVector) {
6852 SDValue SplitSelect = SplitVecOp_VSELECT(N, 0);
6853 SDValue Res = ModifyToType(SplitSelect, WidenVT);
6854 return Res;
6855 }
6856
6857 if (Cond1.getValueType() != CondWidenVT)
6858 Cond1 = ModifyToType(Cond1, CondWidenVT);
6859 }
6860
6861 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
6862 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
6863 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
6864 if (Opcode == ISD::VP_SELECT || Opcode == ISD::VP_MERGE)
6865 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2,
6866 N->getOperand(3));
6867 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2);
6868}
6869
6870SDValue DAGTypeLegalizer::WidenVecRes_SELECT_CC(SDNode *N) {
6871 SDValue InOp1 = GetWidenedVector(N->getOperand(2));
6872 SDValue InOp2 = GetWidenedVector(N->getOperand(3));
6873 return DAG.getNode(ISD::SELECT_CC, SDLoc(N),
6874 InOp1.getValueType(), N->getOperand(0),
6875 N->getOperand(1), InOp1, InOp2, N->getOperand(4));
6876}
6877
6878SDValue DAGTypeLegalizer::WidenVecRes_UNDEF(SDNode *N) {
6879 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6880 return DAG.getUNDEF(WidenVT);
6881}
6882
6883SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N) {
6884 EVT VT = N->getValueType(0);
6885 SDLoc dl(N);
6886
6887 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6888 unsigned NumElts = VT.getVectorNumElements();
6889 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6890
6891 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
6892 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
6893
6894 // Adjust mask based on new input vector length.
6895 SmallVector<int, 16> NewMask(WidenNumElts, -1);
6896 for (unsigned i = 0; i != NumElts; ++i) {
6897 int Idx = N->getMaskElt(i);
6898 if (Idx < (int)NumElts)
6899 NewMask[i] = Idx;
6900 else
6901 NewMask[i] = Idx - NumElts + WidenNumElts;
6902 }
6903 return DAG.getVectorShuffle(WidenVT, dl, InOp1, InOp2, NewMask);
6904}
6905
6906SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_REVERSE(SDNode *N) {
6907 EVT VT = N->getValueType(0);
6908 EVT EltVT = VT.getVectorElementType();
6909 SDLoc dl(N);
6910
6911 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6912 SDValue OpValue = GetWidenedVector(N->getOperand(0));
6913 assert(WidenVT == OpValue.getValueType() && "Unexpected widened vector type");
6914
6915 SDValue ReverseVal = DAG.getNode(ISD::VECTOR_REVERSE, dl, WidenVT, OpValue);
6916 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6917 unsigned VTNumElts = VT.getVectorMinNumElements();
6918 unsigned IdxVal = WidenNumElts - VTNumElts;
6919
6920 if (VT.isScalableVector()) {
6921 // Try to split the 'Widen ReverseVal' into smaller extracts and concat the
6922 // results together, e.g.(nxv6i64 -> nxv8i64)
6923 // nxv8i64 vector_reverse
6924 // <->
6925 // nxv8i64 concat(
6926 // nxv2i64 extract_subvector(nxv8i64, 2)
6927 // nxv2i64 extract_subvector(nxv8i64, 4)
6928 // nxv2i64 extract_subvector(nxv8i64, 6)
6929 // nxv2i64 undef)
6930
6931 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
6932 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
6934 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
6935 "down type's element count");
6937 unsigned i = 0;
6938 for (; i < VTNumElts / GCD; ++i)
6939 Parts.push_back(
6940 DAG.getExtractSubvector(dl, PartVT, ReverseVal, IdxVal + i * GCD));
6941 for (; i < WidenNumElts / GCD; ++i)
6942 Parts.push_back(DAG.getPOISON(PartVT));
6943
6944 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
6945 }
6946
6947 // Use VECTOR_SHUFFLE to combine new vector from 'ReverseVal' for
6948 // fixed-vectors.
6949 SmallVector<int, 16> Mask(WidenNumElts, -1);
6950 std::iota(Mask.begin(), Mask.begin() + VTNumElts, IdxVal);
6951
6952 return DAG.getVectorShuffle(WidenVT, dl, ReverseVal, DAG.getUNDEF(WidenVT),
6953 Mask);
6954}
6955
6956SDValue DAGTypeLegalizer::WidenVecRes_GET_ACTIVE_LANE_MASK(SDNode *N) {
6957 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6958 return DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, SDLoc(N), NVT, N->ops());
6959}
6960
6961SDValue DAGTypeLegalizer::WidenVecRes_SETCC(SDNode *N) {
6962 assert(N->getValueType(0).isVector() &&
6963 N->getOperand(0).getValueType().isVector() &&
6964 "Operands must be vectors");
6965 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6966 ElementCount WidenEC = WidenVT.getVectorElementCount();
6967
6968 SDValue InOp1 = N->getOperand(0);
6969 EVT InVT = InOp1.getValueType();
6970 assert(InVT.isVector() && "can not widen non-vector type");
6971 EVT WidenInVT =
6972 EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), WidenEC);
6973
6974 // The input and output types often differ here, and it could be that while
6975 // we'd prefer to widen the result type, the input operands have been split.
6976 // In this case, we also need to split the result of this node as well.
6977 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector) {
6978 SDValue SplitVSetCC = SplitVecOp_VSETCC(N);
6979 SDValue Res = ModifyToType(SplitVSetCC, WidenVT);
6980 return Res;
6981 }
6982
6983 // If the inputs also widen, handle them directly. Otherwise widen by hand.
6984 SDValue InOp2 = N->getOperand(1);
6985 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
6986 InOp1 = GetWidenedVector(InOp1);
6987 InOp2 = GetWidenedVector(InOp2);
6988 } else {
6989 SDValue Poison = DAG.getPOISON(WidenInVT);
6990 SDValue ZeroIdx = DAG.getVectorIdxConstant(0, SDLoc(N));
6991 InOp1 = DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), WidenInVT, Poison,
6992 InOp1, ZeroIdx);
6993 InOp2 = DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), WidenInVT, Poison,
6994 InOp2, ZeroIdx);
6995 }
6996
6997 // Assume that the input and output will be widen appropriately. If not,
6998 // we will have to unroll it at some point.
6999 assert(InOp1.getValueType() == WidenInVT &&
7000 InOp2.getValueType() == WidenInVT &&
7001 "Input not widened to expected type!");
7002 (void)WidenInVT;
7003 if (N->getOpcode() == ISD::VP_SETCC) {
7004 SDValue Mask =
7005 GetWidenedMask(N->getOperand(3), WidenVT.getVectorElementCount());
7006 return DAG.getNode(ISD::VP_SETCC, SDLoc(N), WidenVT, InOp1, InOp2,
7007 N->getOperand(2), Mask, N->getOperand(4));
7008 }
7009 return DAG.getNode(ISD::SETCC, SDLoc(N), WidenVT, InOp1, InOp2,
7010 N->getOperand(2));
7011}
7012
7013SDValue DAGTypeLegalizer::WidenVecRes_STRICT_FSETCC(SDNode *N) {
7014 assert(N->getValueType(0).isVector() &&
7015 N->getOperand(1).getValueType().isVector() &&
7016 "Operands must be vectors");
7017 EVT VT = N->getValueType(0);
7018 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7019 unsigned WidenNumElts = WidenVT.getVectorNumElements();
7020 unsigned NumElts = VT.getVectorNumElements();
7021 EVT EltVT = VT.getVectorElementType();
7022
7023 SDLoc dl(N);
7024 SDValue Chain = N->getOperand(0);
7025 SDValue LHS = N->getOperand(1);
7026 SDValue RHS = N->getOperand(2);
7027 SDValue CC = N->getOperand(3);
7028 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
7029
7030 // Fully unroll and reassemble.
7031 SmallVector<SDValue, 8> Scalars(WidenNumElts, DAG.getPOISON(EltVT));
7032 SmallVector<SDValue, 8> Chains(NumElts);
7033 for (unsigned i = 0; i != NumElts; ++i) {
7034 SDValue LHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, LHS, i);
7035 SDValue RHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, RHS, i);
7036
7037 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
7038 {Chain, LHSElem, RHSElem, CC});
7039 Chains[i] = Scalars[i].getValue(1);
7040 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
7041 DAG.getBoolConstant(true, dl, EltVT, VT),
7042 DAG.getBoolConstant(false, dl, EltVT, VT));
7043 }
7044
7045 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
7046 ReplaceValueWith(SDValue(N, 1), NewChain);
7047
7048 return DAG.getBuildVector(WidenVT, dl, Scalars);
7049}
7050
7051//===----------------------------------------------------------------------===//
7052// Widen Vector Operand
7053//===----------------------------------------------------------------------===//
7054bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned OpNo) {
7055 LLVM_DEBUG(dbgs() << "Widen node operand " << OpNo << ": "; N->dump(&DAG));
7056 SDValue Res = SDValue();
7057
7058 // See if the target wants to custom widen this node.
7059 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
7060 return false;
7061
7062 switch (N->getOpcode()) {
7063 default:
7064#ifndef NDEBUG
7065 dbgs() << "WidenVectorOperand op #" << OpNo << ": ";
7066 N->dump(&DAG);
7067 dbgs() << "\n";
7068#endif
7069 report_fatal_error("Do not know how to widen this operator's operand!");
7070
7071 case ISD::BITCAST: Res = WidenVecOp_BITCAST(N); break;
7072 case ISD::FAKE_USE:
7073 Res = WidenVecOp_FAKE_USE(N);
7074 break;
7075 case ISD::CONCAT_VECTORS: Res = WidenVecOp_CONCAT_VECTORS(N); break;
7076 case ISD::INSERT_SUBVECTOR: Res = WidenVecOp_INSERT_SUBVECTOR(N); break;
7077 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecOp_EXTRACT_SUBVECTOR(N); break;
7078 case ISD::EXTRACT_VECTOR_ELT: Res = WidenVecOp_EXTRACT_VECTOR_ELT(N); break;
7079 case ISD::STORE: Res = WidenVecOp_STORE(N); break;
7080 case ISD::VP_STORE: Res = WidenVecOp_VP_STORE(N, OpNo); break;
7081 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
7082 Res = WidenVecOp_VP_STRIDED_STORE(N, OpNo);
7083 break;
7087 Res = WidenVecOp_EXTEND_VECTOR_INREG(N);
7088 break;
7089 case ISD::MSTORE: Res = WidenVecOp_MSTORE(N, OpNo); break;
7090 case ISD::MGATHER: Res = WidenVecOp_MGATHER(N, OpNo); break;
7091 case ISD::MSCATTER: Res = WidenVecOp_MSCATTER(N, OpNo); break;
7092 case ISD::VP_SCATTER: Res = WidenVecOp_VP_SCATTER(N, OpNo); break;
7093 case ISD::SETCC: Res = WidenVecOp_SETCC(N); break;
7094 case ISD::STRICT_FSETCC:
7095 case ISD::STRICT_FSETCCS: Res = WidenVecOp_STRICT_FSETCC(N); break;
7096 case ISD::VSELECT: Res = WidenVecOp_VSELECT(N); break;
7097 case ISD::FLDEXP:
7098 case ISD::FCOPYSIGN:
7099 case ISD::LROUND:
7100 case ISD::LLROUND:
7101 case ISD::LRINT:
7102 case ISD::LLRINT:
7103 Res = WidenVecOp_UnrollVectorOp(N);
7104 break;
7105 case ISD::IS_FPCLASS: Res = WidenVecOp_IS_FPCLASS(N); break;
7106
7107 case ISD::ANY_EXTEND:
7108 case ISD::SIGN_EXTEND:
7109 case ISD::ZERO_EXTEND:
7110 Res = WidenVecOp_EXTEND(N);
7111 break;
7112
7113 case ISD::SCMP:
7114 case ISD::UCMP:
7115 Res = WidenVecOp_CMP(N);
7116 break;
7117
7118 case ISD::FP_EXTEND:
7120 case ISD::FP_ROUND:
7122 case ISD::FP_TO_SINT:
7124 case ISD::FP_TO_UINT:
7126 case ISD::SINT_TO_FP:
7128 case ISD::UINT_TO_FP:
7130 case ISD::TRUNCATE:
7131 Res = WidenVecOp_Convert(N);
7132 break;
7133
7136 Res = WidenVecOp_FP_TO_XINT_SAT(N);
7137 break;
7138
7141 case ISD::VECREDUCE_ADD:
7142 case ISD::VECREDUCE_MUL:
7143 case ISD::VECREDUCE_AND:
7144 case ISD::VECREDUCE_OR:
7145 case ISD::VECREDUCE_XOR:
7154 Res = WidenVecOp_VECREDUCE(N);
7155 break;
7158 Res = WidenVecOp_VECREDUCE_SEQ(N);
7159 break;
7160 case ISD::VP_REDUCE_FADD:
7161 case ISD::VP_REDUCE_SEQ_FADD:
7162 case ISD::VP_REDUCE_FMUL:
7163 case ISD::VP_REDUCE_SEQ_FMUL:
7164 case ISD::VP_REDUCE_ADD:
7165 case ISD::VP_REDUCE_MUL:
7166 case ISD::VP_REDUCE_AND:
7167 case ISD::VP_REDUCE_OR:
7168 case ISD::VP_REDUCE_XOR:
7169 case ISD::VP_REDUCE_SMAX:
7170 case ISD::VP_REDUCE_SMIN:
7171 case ISD::VP_REDUCE_UMAX:
7172 case ISD::VP_REDUCE_UMIN:
7173 case ISD::VP_REDUCE_FMAX:
7174 case ISD::VP_REDUCE_FMIN:
7175 case ISD::VP_REDUCE_FMAXIMUM:
7176 case ISD::VP_REDUCE_FMINIMUM:
7177 Res = WidenVecOp_VP_REDUCE(N);
7178 break;
7179 case ISD::VP_CTTZ_ELTS:
7180 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
7181 Res = WidenVecOp_VP_CttzElements(N);
7182 break;
7183 }
7184
7185 // If Res is null, the sub-method took care of registering the result.
7186 if (!Res.getNode()) return false;
7187
7188 // If the result is N, the sub-method updated N in place. Tell the legalizer
7189 // core about this.
7190 if (Res.getNode() == N)
7191 return true;
7192
7193
7194 if (N->isStrictFPOpcode())
7195 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
7196 "Invalid operand expansion");
7197 else
7198 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
7199 "Invalid operand expansion");
7200
7201 ReplaceValueWith(SDValue(N, 0), Res);
7202 return false;
7203}
7204
7205SDValue DAGTypeLegalizer::WidenVecOp_EXTEND(SDNode *N) {
7206 SDLoc DL(N);
7207 EVT VT = N->getValueType(0);
7208
7209 SDValue InOp = N->getOperand(0);
7210 assert(getTypeAction(InOp.getValueType()) ==
7212 "Unexpected type action");
7213 InOp = GetWidenedVector(InOp);
7216 "Input wasn't widened!");
7217
7218 // We may need to further widen the operand until it has the same total
7219 // vector size as the result.
7220 EVT InVT = InOp.getValueType();
7221 if (InVT.getSizeInBits() != VT.getSizeInBits()) {
7222 EVT InEltVT = InVT.getVectorElementType();
7223 for (EVT FixedVT : MVT::vector_valuetypes()) {
7224 EVT FixedEltVT = FixedVT.getVectorElementType();
7225 if (TLI.isTypeLegal(FixedVT) &&
7226 FixedVT.getSizeInBits() == VT.getSizeInBits() &&
7227 FixedEltVT == InEltVT) {
7228 assert(FixedVT.getVectorNumElements() >= VT.getVectorNumElements() &&
7229 "Not enough elements in the fixed type for the operand!");
7230 assert(FixedVT.getVectorNumElements() != InVT.getVectorNumElements() &&
7231 "We can't have the same type as we started with!");
7232 if (FixedVT.getVectorNumElements() > InVT.getVectorNumElements())
7233 InOp = DAG.getInsertSubvector(DL, DAG.getUNDEF(FixedVT), InOp, 0);
7234 else
7235 InOp = DAG.getExtractSubvector(DL, FixedVT, InOp, 0);
7236 break;
7237 }
7238 }
7239 InVT = InOp.getValueType();
7240 if (InVT.getSizeInBits() != VT.getSizeInBits())
7241 // We couldn't find a legal vector type that was a widening of the input
7242 // and could be extended in-register to the result type, so we have to
7243 // scalarize.
7244 return WidenVecOp_Convert(N);
7245 }
7246
7247 // Use special DAG nodes to represent the operation of extending the
7248 // low lanes.
7249 switch (N->getOpcode()) {
7250 default:
7251 llvm_unreachable("Extend legalization on extend operation!");
7252 case ISD::ANY_EXTEND:
7253 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, VT, InOp);
7254 case ISD::SIGN_EXTEND:
7255 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, VT, InOp);
7256 case ISD::ZERO_EXTEND:
7257 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, VT, InOp);
7258 }
7259}
7260
7261SDValue DAGTypeLegalizer::WidenVecOp_CMP(SDNode *N) {
7262 SDLoc dl(N);
7263
7264 EVT OpVT = N->getOperand(0).getValueType();
7265 EVT ResVT = N->getValueType(0);
7266 SDValue LHS = GetWidenedVector(N->getOperand(0));
7267 SDValue RHS = GetWidenedVector(N->getOperand(1));
7268
7269 // 1. EXTRACT_SUBVECTOR
7270 // 2. SIGN_EXTEND/ZERO_EXTEND
7271 // 3. CMP
7272 LHS = DAG.getExtractSubvector(dl, OpVT, LHS, 0);
7273 RHS = DAG.getExtractSubvector(dl, OpVT, RHS, 0);
7274
7275 // At this point the result type is guaranteed to be valid, so we can use it
7276 // as the operand type by extending it appropriately
7277 ISD::NodeType ExtendOpcode =
7278 N->getOpcode() == ISD::SCMP ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
7279 LHS = DAG.getNode(ExtendOpcode, dl, ResVT, LHS);
7280 RHS = DAG.getNode(ExtendOpcode, dl, ResVT, RHS);
7281
7282 return DAG.getNode(N->getOpcode(), dl, ResVT, LHS, RHS);
7283}
7284
7285SDValue DAGTypeLegalizer::WidenVecOp_UnrollVectorOp(SDNode *N) {
7286 // The result (and first input) is legal, but the second input is illegal.
7287 // We can't do much to fix that, so just unroll and let the extracts off of
7288 // the second input be widened as needed later.
7289 return DAG.UnrollVectorOp(N);
7290}
7291
7292SDValue DAGTypeLegalizer::WidenVecOp_IS_FPCLASS(SDNode *N) {
7293 SDLoc DL(N);
7294 EVT ResultVT = N->getValueType(0);
7295 SDValue Test = N->getOperand(1);
7296 SDValue WideArg = GetWidenedVector(N->getOperand(0));
7297
7298 // Process this node similarly to SETCC.
7299 EVT WideResultVT = getSetCCResultType(WideArg.getValueType());
7300 if (ResultVT.getScalarType() == MVT::i1)
7301 WideResultVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
7302 WideResultVT.getVectorNumElements());
7303
7304 SDValue WideNode = DAG.getNode(ISD::IS_FPCLASS, DL, WideResultVT,
7305 {WideArg, Test}, N->getFlags());
7306
7307 // Extract the needed results from the result vector.
7308 EVT ResVT =
7309 EVT::getVectorVT(*DAG.getContext(), WideResultVT.getVectorElementType(),
7310 ResultVT.getVectorNumElements());
7311 SDValue CC = DAG.getExtractSubvector(DL, ResVT, WideNode, 0);
7312
7313 EVT OpVT = N->getOperand(0).getValueType();
7314 ISD::NodeType ExtendCode =
7315 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
7316 return DAG.getNode(ExtendCode, DL, ResultVT, CC);
7317}
7318
7319SDValue DAGTypeLegalizer::WidenVecOp_Convert(SDNode *N) {
7320 // Since the result is legal and the input is illegal.
7321 EVT VT = N->getValueType(0);
7322 EVT EltVT = VT.getVectorElementType();
7323 SDLoc dl(N);
7324 SDValue InOp = N->getOperand(N->isStrictFPOpcode() ? 1 : 0);
7325 assert(getTypeAction(InOp.getValueType()) ==
7327 "Unexpected type action");
7328 InOp = GetWidenedVector(InOp);
7329 EVT InVT = InOp.getValueType();
7330 unsigned Opcode = N->getOpcode();
7331
7332 // See if a widened result type would be legal, if so widen the node.
7333 // FIXME: This isn't safe for StrictFP. Other optimization here is needed.
7334 EVT WideVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
7335 InVT.getVectorElementCount());
7336 if (TLI.isTypeLegal(WideVT) && !N->isStrictFPOpcode()) {
7337 SDValue Res;
7338 if (N->isStrictFPOpcode()) {
7339 if (Opcode == ISD::STRICT_FP_ROUND)
7340 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
7341 { N->getOperand(0), InOp, N->getOperand(2) });
7342 else
7343 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
7344 { N->getOperand(0), InOp });
7345 // Legalize the chain result - switch anything that used the old chain to
7346 // use the new one.
7347 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7348 } else {
7349 if (Opcode == ISD::FP_ROUND)
7350 Res = DAG.getNode(Opcode, dl, WideVT, InOp, N->getOperand(1));
7351 else
7352 Res = DAG.getNode(Opcode, dl, WideVT, InOp);
7353 }
7354 return DAG.getExtractSubvector(dl, VT, Res, 0);
7355 }
7356
7357 EVT InEltVT = InVT.getVectorElementType();
7358
7359 // Unroll the convert into some scalar code and create a nasty build vector.
7360 unsigned NumElts = VT.getVectorNumElements();
7362 if (N->isStrictFPOpcode()) {
7363 SmallVector<SDValue, 4> NewOps(N->ops());
7364 SmallVector<SDValue, 32> OpChains;
7365 for (unsigned i=0; i < NumElts; ++i) {
7366 NewOps[1] = DAG.getExtractVectorElt(dl, InEltVT, InOp, i);
7367 Ops[i] = DAG.getNode(Opcode, dl, { EltVT, MVT::Other }, NewOps);
7368 OpChains.push_back(Ops[i].getValue(1));
7369 }
7370 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OpChains);
7371 ReplaceValueWith(SDValue(N, 1), NewChain);
7372 } else {
7373 for (unsigned i = 0; i < NumElts; ++i)
7374 Ops[i] = DAG.getNode(Opcode, dl, EltVT,
7375 DAG.getExtractVectorElt(dl, InEltVT, InOp, i));
7376 }
7377
7378 return DAG.getBuildVector(VT, dl, Ops);
7379}
7380
7381SDValue DAGTypeLegalizer::WidenVecOp_FP_TO_XINT_SAT(SDNode *N) {
7382 EVT DstVT = N->getValueType(0);
7383 SDValue Src = GetWidenedVector(N->getOperand(0));
7384 EVT SrcVT = Src.getValueType();
7385 ElementCount WideNumElts = SrcVT.getVectorElementCount();
7386 SDLoc dl(N);
7387
7388 // See if a widened result type would be legal, if so widen the node.
7389 EVT WideDstVT = EVT::getVectorVT(*DAG.getContext(),
7390 DstVT.getVectorElementType(), WideNumElts);
7391 if (TLI.isTypeLegal(WideDstVT)) {
7392 SDValue Res =
7393 DAG.getNode(N->getOpcode(), dl, WideDstVT, Src, N->getOperand(1));
7394 return DAG.getNode(
7395 ISD::EXTRACT_SUBVECTOR, dl, DstVT, Res,
7396 DAG.getConstant(0, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
7397 }
7398
7399 // Give up and unroll.
7400 return DAG.UnrollVectorOp(N);
7401}
7402
7403SDValue DAGTypeLegalizer::WidenVecOp_BITCAST(SDNode *N) {
7404 EVT VT = N->getValueType(0);
7405 SDValue InOp = GetWidenedVector(N->getOperand(0));
7406 EVT InWidenVT = InOp.getValueType();
7407 SDLoc dl(N);
7408
7409 // Check if we can convert between two legal vector types and extract.
7410 TypeSize InWidenSize = InWidenVT.getSizeInBits();
7411 TypeSize Size = VT.getSizeInBits();
7412 // x86mmx is not an acceptable vector element type, so don't try.
7413 if (!VT.isVector() && VT != MVT::x86mmx &&
7414 InWidenSize.hasKnownScalarFactor(Size)) {
7415 unsigned NewNumElts = InWidenSize.getKnownScalarFactor(Size);
7416 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), VT, NewNumElts);
7417 if (TLI.isTypeLegal(NewVT)) {
7418 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
7419 return DAG.getExtractVectorElt(dl, VT, BitOp, 0);
7420 }
7421 }
7422
7423 // Handle a case like bitcast v12i8 -> v3i32. Normally that would get widened
7424 // to v16i8 -> v4i32, but for a target where v3i32 is legal but v12i8 is not,
7425 // we end up here. Handling the case here with EXTRACT_SUBVECTOR avoids
7426 // having to copy via memory.
7427 if (VT.isVector()) {
7428 EVT EltVT = VT.getVectorElementType();
7429 unsigned EltSize = EltVT.getFixedSizeInBits();
7430 if (InWidenSize.isKnownMultipleOf(EltSize)) {
7431 ElementCount NewNumElts =
7432 (InWidenVT.getVectorElementCount() * InWidenVT.getScalarSizeInBits())
7433 .divideCoefficientBy(EltSize);
7434 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NewNumElts);
7435 if (TLI.isTypeLegal(NewVT)) {
7436 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
7437 return DAG.getExtractSubvector(dl, VT, BitOp, 0);
7438 }
7439 }
7440 }
7441
7442 return CreateStackStoreLoad(InOp, VT);
7443}
7444
7445// Vectors with sizes that are not powers of 2 need to be widened to the
7446// next largest power of 2. For example, we may get a vector of 3 32-bit
7447// integers or of 6 16-bit integers, both of which have to be widened to a
7448// 128-bit vector.
7449SDValue DAGTypeLegalizer::WidenVecOp_FAKE_USE(SDNode *N) {
7450 SDValue WidenedOp = GetWidenedVector(N->getOperand(1));
7451 return DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, N->getOperand(0),
7452 WidenedOp);
7453}
7454
7455SDValue DAGTypeLegalizer::WidenVecOp_CONCAT_VECTORS(SDNode *N) {
7456 EVT VT = N->getValueType(0);
7457 EVT EltVT = VT.getVectorElementType();
7458 EVT InVT = N->getOperand(0).getValueType();
7459 SDLoc dl(N);
7460
7461 // If the widen width for this operand is the same as the width of the concat
7462 // and all but the first operand is undef, just use the widened operand.
7463 unsigned NumOperands = N->getNumOperands();
7464 if (VT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
7465 unsigned i;
7466 for (i = 1; i < NumOperands; ++i)
7467 if (!N->getOperand(i).isUndef())
7468 break;
7469
7470 if (i == NumOperands)
7471 return GetWidenedVector(N->getOperand(0));
7472 }
7473
7474 // Otherwise, fall back to a nasty build vector.
7475 unsigned NumElts = VT.getVectorNumElements();
7477
7478 unsigned NumInElts = InVT.getVectorNumElements();
7479
7480 unsigned Idx = 0;
7481 for (unsigned i=0; i < NumOperands; ++i) {
7482 SDValue InOp = N->getOperand(i);
7483 assert(getTypeAction(InOp.getValueType()) ==
7485 "Unexpected type action");
7486 InOp = GetWidenedVector(InOp);
7487 for (unsigned j = 0; j < NumInElts; ++j)
7488 Ops[Idx++] = DAG.getExtractVectorElt(dl, EltVT, InOp, j);
7489 }
7490 return DAG.getBuildVector(VT, dl, Ops);
7491}
7492
7493SDValue DAGTypeLegalizer::WidenVecOp_INSERT_SUBVECTOR(SDNode *N) {
7494 EVT VT = N->getValueType(0);
7495 SDValue SubVec = N->getOperand(1);
7496 SDValue InVec = N->getOperand(0);
7497
7498 EVT OrigVT = SubVec.getValueType();
7499 SubVec = GetWidenedVector(SubVec);
7500 EVT SubVT = SubVec.getValueType();
7501
7502 // Whether or not all the elements of the widened SubVec will be inserted into
7503 // valid indices of VT.
7504 bool IndicesValid = false;
7505 // If we statically know that VT can fit SubVT, the indices are valid.
7506 if (VT.knownBitsGE(SubVT))
7507 IndicesValid = true;
7508 else if (VT.isScalableVector() && SubVT.isFixedLengthVector()) {
7509 // Otherwise, if we're inserting a fixed vector into a scalable vector and
7510 // we know the minimum vscale we can work out if it's valid ourselves.
7511 Attribute Attr = DAG.getMachineFunction().getFunction().getFnAttribute(
7512 Attribute::VScaleRange);
7513 if (Attr.isValid()) {
7514 unsigned VScaleMin = Attr.getVScaleRangeMin();
7515 if (VT.getSizeInBits().getKnownMinValue() * VScaleMin >=
7516 SubVT.getFixedSizeInBits())
7517 IndicesValid = true;
7518 }
7519 }
7520
7521 if (!IndicesValid)
7523 "Don't know how to widen the operands for INSERT_SUBVECTOR");
7524
7525 SDLoc DL(N);
7526
7527 // We need to make sure that the indices are still valid, otherwise we might
7528 // widen what was previously well-defined to something undefined.
7529 if (InVec.isUndef() && N->getConstantOperandVal(2) == 0)
7530 return DAG.getNode(ISD::INSERT_SUBVECTOR, DL, VT, InVec, SubVec,
7531 N->getOperand(2));
7532
7533 if (OrigVT.isScalableVector()) {
7534 // Fallback to inserting through memory.
7535
7536 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
7537 SDValue StackPtr = DAG.CreateStackTemporary(VT.getStoreSize(), Alignment);
7538 MachineFunction &MF = DAG.getMachineFunction();
7539 int FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
7540 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
7541
7542 MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
7545 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
7548
7549 // Write out the vector being inserting into.
7550 SDValue Ch =
7551 DAG.getStore(DAG.getEntryNode(), DL, InVec, StackPtr, StoreMMO);
7552
7553 // Build a mask to match the length of the sub-vector.
7554 SDValue Mask =
7555 DAG.getMaskFromElementCount(DL, SubVT, OrigVT.getVectorElementCount());
7556
7557 // Overwrite the sub-vector at the required offset.
7558 SDValue SubVecPtr =
7559 TLI.getVectorSubVecPointer(DAG, StackPtr, VT, OrigVT, N->getOperand(2));
7560 Ch = DAG.getMaskedStore(Ch, DL, SubVec, SubVecPtr,
7561 DAG.getUNDEF(SubVecPtr.getValueType()), Mask, VT,
7562 StoreMMO, ISD::UNINDEXED, ISD::NON_EXTLOAD);
7563
7564 // Read back the result.
7565 return DAG.getLoad(VT, DL, Ch, StackPtr, LoadMMO);
7566 }
7567
7568 // If the operands can't be widened legally, just replace the INSERT_SUBVECTOR
7569 // with a series of INSERT_VECTOR_ELT
7570 unsigned Idx = N->getConstantOperandVal(2);
7571
7572 SDValue InsertElt = InVec;
7573 for (unsigned I = 0, E = OrigVT.getVectorNumElements(); I != E; ++I) {
7574 SDValue ExtractElt =
7575 DAG.getExtractVectorElt(DL, VT.getVectorElementType(), SubVec, I);
7576 InsertElt = DAG.getInsertVectorElt(DL, InsertElt, ExtractElt, I + Idx);
7577 }
7578
7579 return InsertElt;
7580}
7581
7582SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
7583 SDValue InOp = GetWidenedVector(N->getOperand(0));
7584 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SDLoc(N),
7585 N->getValueType(0), InOp, N->getOperand(1));
7586}
7587
7588SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
7589 SDValue InOp = GetWidenedVector(N->getOperand(0));
7590 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
7591 N->getValueType(0), InOp, N->getOperand(1));
7592}
7593
7594SDValue DAGTypeLegalizer::WidenVecOp_EXTEND_VECTOR_INREG(SDNode *N) {
7595 SDValue InOp = GetWidenedVector(N->getOperand(0));
7596 return DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0), InOp);
7597}
7598
7599SDValue DAGTypeLegalizer::WidenVecOp_STORE(SDNode *N) {
7600 // We have to widen the value, but we want only to store the original
7601 // vector type.
7602 StoreSDNode *ST = cast<StoreSDNode>(N);
7603
7604 if (!ST->getMemoryVT().getScalarType().isByteSized())
7605 return TLI.scalarizeVectorStore(ST, DAG);
7606
7607 if (ST->isTruncatingStore())
7608 return TLI.scalarizeVectorStore(ST, DAG);
7609
7610 // Generate a vector-predicated store if it is custom/legal on the target.
7611 // To avoid possible recursion, only do this if the widened mask type is
7612 // legal.
7613 // FIXME: Not all targets may support EVL in VP_STORE. These will have been
7614 // removed from the IR by the ExpandVectorPredication pass but we're
7615 // reintroducing them here.
7616 SDValue StVal = ST->getValue();
7617 EVT StVT = StVal.getValueType();
7618 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), StVT);
7619 EVT WideMaskVT = getSetCCResultType(WideVT);
7620
7621 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
7622 TLI.isTypeLegal(WideMaskVT)) {
7623 // Widen the value.
7624 SDLoc DL(N);
7625 StVal = GetWidenedVector(StVal);
7626 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
7627 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
7628 StVT.getVectorElementCount());
7629 return DAG.getStoreVP(ST->getChain(), DL, StVal, ST->getBasePtr(),
7630 ST->getOffset(), Mask, EVL, StVT, ST->getMemOperand(),
7631 ST->getAddressingMode());
7632 }
7633
7635 if (GenWidenVectorStores(StChain, ST)) {
7636 if (StChain.size() == 1)
7637 return StChain[0];
7638
7639 return DAG.getNode(ISD::TokenFactor, SDLoc(ST), MVT::Other, StChain);
7640 }
7641
7642 if (StVT.isVector()) {
7643 // If all else fails replace the store with a wide masked store.
7644 SDLoc DL(N);
7645 SDValue WideStVal = GetWidenedVector(StVal);
7646 SDValue Mask =
7647 DAG.getMaskFromElementCount(DL, WideVT, StVT.getVectorElementCount());
7648
7649 return DAG.getMaskedStore(ST->getChain(), DL, WideStVal, ST->getBasePtr(),
7650 ST->getOffset(), Mask, ST->getMemoryVT(),
7651 ST->getMemOperand(), ST->getAddressingMode(),
7652 ST->isTruncatingStore());
7653 }
7654
7655 report_fatal_error("Unable to widen vector store");
7656}
7657
7658SDValue DAGTypeLegalizer::WidenVecOp_VP_STORE(SDNode *N, unsigned OpNo) {
7659 assert((OpNo == 1 || OpNo == 3) &&
7660 "Can widen only data or mask operand of vp_store");
7661 VPStoreSDNode *ST = cast<VPStoreSDNode>(N);
7662 SDValue Mask = ST->getMask();
7663 SDValue StVal = ST->getValue();
7664 SDLoc dl(N);
7665
7666 if (OpNo == 1) {
7667 // Widen the value.
7668 StVal = GetWidenedVector(StVal);
7669
7670 // We only handle the case where the mask needs widening to an
7671 // identically-sized type as the vector inputs.
7672 assert(getTypeAction(Mask.getValueType()) ==
7674 "Unable to widen VP store");
7675 Mask = GetWidenedVector(Mask);
7676 } else {
7677 Mask = GetWidenedVector(Mask);
7678
7679 // We only handle the case where the stored value needs widening to an
7680 // identically-sized type as the mask.
7681 assert(getTypeAction(StVal.getValueType()) ==
7683 "Unable to widen VP store");
7684 StVal = GetWidenedVector(StVal);
7685 }
7686
7687 assert(Mask.getValueType().getVectorElementCount() ==
7689 "Mask and data vectors should have the same number of elements");
7690 return DAG.getStoreVP(ST->getChain(), dl, StVal, ST->getBasePtr(),
7691 ST->getOffset(), Mask, ST->getVectorLength(),
7692 ST->getMemoryVT(), ST->getMemOperand(),
7693 ST->getAddressingMode(), ST->isTruncatingStore(),
7694 ST->isCompressingStore());
7695}
7696
7697SDValue DAGTypeLegalizer::WidenVecOp_VP_STRIDED_STORE(SDNode *N,
7698 unsigned OpNo) {
7699 assert((OpNo == 1 || OpNo == 4) &&
7700 "Can widen only data or mask operand of vp_strided_store");
7701 VPStridedStoreSDNode *SST = cast<VPStridedStoreSDNode>(N);
7702 SDValue Mask = SST->getMask();
7703 SDValue StVal = SST->getValue();
7704 SDLoc DL(N);
7705
7706 if (OpNo == 1)
7707 assert(getTypeAction(Mask.getValueType()) ==
7709 "Unable to widen VP strided store");
7710 else
7711 assert(getTypeAction(StVal.getValueType()) ==
7713 "Unable to widen VP strided store");
7714
7715 StVal = GetWidenedVector(StVal);
7716 Mask = GetWidenedVector(Mask);
7717
7719 Mask.getValueType().getVectorElementCount() &&
7720 "Data and mask vectors should have the same number of elements");
7721
7722 return DAG.getStridedStoreVP(
7723 SST->getChain(), DL, StVal, SST->getBasePtr(), SST->getOffset(),
7724 SST->getStride(), Mask, SST->getVectorLength(), SST->getMemoryVT(),
7725 SST->getMemOperand(), SST->getAddressingMode(), SST->isTruncatingStore(),
7726 SST->isCompressingStore());
7727}
7728
7729SDValue DAGTypeLegalizer::WidenVecOp_MSTORE(SDNode *N, unsigned OpNo) {
7730 assert((OpNo == 1 || OpNo == 4) &&
7731 "Can widen only data or mask operand of mstore");
7732 MaskedStoreSDNode *MST = cast<MaskedStoreSDNode>(N);
7733 SDValue Mask = MST->getMask();
7734 EVT MaskVT = Mask.getValueType();
7735 SDValue StVal = MST->getValue();
7736 EVT VT = StVal.getValueType();
7737 SDLoc dl(N);
7738
7739 EVT WideVT, WideMaskVT;
7740 if (OpNo == 1) {
7741 // Widen the value.
7742 StVal = GetWidenedVector(StVal);
7743
7744 WideVT = StVal.getValueType();
7745 WideMaskVT =
7746 EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(),
7747 WideVT.getVectorElementCount());
7748 } else {
7749 WideMaskVT = TLI.getTypeToTransformTo(*DAG.getContext(), MaskVT);
7750
7751 EVT ValueVT = StVal.getValueType();
7752 WideVT = EVT::getVectorVT(*DAG.getContext(), ValueVT.getVectorElementType(),
7753 WideMaskVT.getVectorElementCount());
7754 }
7755
7756 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
7757 TLI.isTypeLegal(WideMaskVT)) {
7758 Mask = DAG.getInsertSubvector(dl, DAG.getUNDEF(WideMaskVT), Mask, 0);
7759 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
7761 return DAG.getStoreVP(MST->getChain(), dl, StVal, MST->getBasePtr(),
7762 MST->getOffset(), Mask, EVL, MST->getMemoryVT(),
7763 MST->getMemOperand(), MST->getAddressingMode());
7764 }
7765
7766 if (OpNo == 1) {
7767 // The mask should be widened as well.
7768 Mask = ModifyToType(Mask, WideMaskVT, true);
7769 } else {
7770 // Widen the mask.
7771 Mask = ModifyToType(Mask, WideMaskVT, true);
7772
7773 StVal = ModifyToType(StVal, WideVT);
7774 }
7775
7776 assert(Mask.getValueType().getVectorElementCount() ==
7778 "Mask and data vectors should have the same number of elements");
7779 return DAG.getMaskedStore(MST->getChain(), dl, StVal, MST->getBasePtr(),
7780 MST->getOffset(), Mask, MST->getMemoryVT(),
7781 MST->getMemOperand(), MST->getAddressingMode(),
7782 false, MST->isCompressingStore());
7783}
7784
7785SDValue DAGTypeLegalizer::WidenVecOp_MGATHER(SDNode *N, unsigned OpNo) {
7786 assert(OpNo == 4 && "Can widen only the index of mgather");
7787 auto *MG = cast<MaskedGatherSDNode>(N);
7788 SDValue DataOp = MG->getPassThru();
7789 SDValue Mask = MG->getMask();
7790 SDValue Scale = MG->getScale();
7791
7792 // Just widen the index. It's allowed to have extra elements.
7793 SDValue Index = GetWidenedVector(MG->getIndex());
7794
7795 SDLoc dl(N);
7796 SDValue Ops[] = {MG->getChain(), DataOp, Mask, MG->getBasePtr(), Index,
7797 Scale};
7798 SDValue Res = DAG.getMaskedGather(MG->getVTList(), MG->getMemoryVT(), dl, Ops,
7799 MG->getMemOperand(), MG->getIndexType(),
7800 MG->getExtensionType());
7801 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7802 ReplaceValueWith(SDValue(N, 0), Res.getValue(0));
7803 return SDValue();
7804}
7805
7806SDValue DAGTypeLegalizer::WidenVecOp_MSCATTER(SDNode *N, unsigned OpNo) {
7807 MaskedScatterSDNode *MSC = cast<MaskedScatterSDNode>(N);
7808 SDValue DataOp = MSC->getValue();
7809 SDValue Mask = MSC->getMask();
7810 SDValue Index = MSC->getIndex();
7811 SDValue Scale = MSC->getScale();
7812 EVT WideMemVT = MSC->getMemoryVT();
7813
7814 if (OpNo == 1) {
7815 DataOp = GetWidenedVector(DataOp);
7816 unsigned NumElts = DataOp.getValueType().getVectorNumElements();
7817
7818 // Widen index.
7819 EVT IndexVT = Index.getValueType();
7820 EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
7821 IndexVT.getVectorElementType(), NumElts);
7822 Index = ModifyToType(Index, WideIndexVT);
7823
7824 // The mask should be widened as well.
7825 EVT MaskVT = Mask.getValueType();
7826 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
7827 MaskVT.getVectorElementType(), NumElts);
7828 Mask = ModifyToType(Mask, WideMaskVT, true);
7829
7830 // Widen the MemoryType
7831 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
7832 MSC->getMemoryVT().getScalarType(), NumElts);
7833 } else if (OpNo == 4) {
7834 // Just widen the index. It's allowed to have extra elements.
7835 Index = GetWidenedVector(Index);
7836 } else
7837 llvm_unreachable("Can't widen this operand of mscatter");
7838
7839 SDValue Ops[] = {MSC->getChain(), DataOp, Mask, MSC->getBasePtr(), Index,
7840 Scale};
7841 return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N),
7842 Ops, MSC->getMemOperand(), MSC->getIndexType(),
7843 MSC->isTruncatingStore());
7844}
7845
7846SDValue DAGTypeLegalizer::WidenVecOp_VP_SCATTER(SDNode *N, unsigned OpNo) {
7847 VPScatterSDNode *VPSC = cast<VPScatterSDNode>(N);
7848 SDValue DataOp = VPSC->getValue();
7849 SDValue Mask = VPSC->getMask();
7850 SDValue Index = VPSC->getIndex();
7851 SDValue Scale = VPSC->getScale();
7852 EVT WideMemVT = VPSC->getMemoryVT();
7853
7854 if (OpNo == 1) {
7855 DataOp = GetWidenedVector(DataOp);
7856 Index = GetWidenedVector(Index);
7857 const auto WideEC = DataOp.getValueType().getVectorElementCount();
7858 Mask = GetWidenedMask(Mask, WideEC);
7859 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
7860 VPSC->getMemoryVT().getScalarType(), WideEC);
7861 } else if (OpNo == 3) {
7862 // Just widen the index. It's allowed to have extra elements.
7863 Index = GetWidenedVector(Index);
7864 } else
7865 llvm_unreachable("Can't widen this operand of VP_SCATTER");
7866
7867 SDValue Ops[] = {
7868 VPSC->getChain(), DataOp, VPSC->getBasePtr(), Index, Scale, Mask,
7869 VPSC->getVectorLength()};
7870 return DAG.getScatterVP(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N), Ops,
7871 VPSC->getMemOperand(), VPSC->getIndexType());
7872}
7873
7874SDValue DAGTypeLegalizer::WidenVecOp_SETCC(SDNode *N) {
7875 SDValue InOp0 = GetWidenedVector(N->getOperand(0));
7876 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
7877 SDLoc dl(N);
7878 EVT VT = N->getValueType(0);
7879
7880 // WARNING: In this code we widen the compare instruction with garbage.
7881 // This garbage may contain denormal floats which may be slow. Is this a real
7882 // concern ? Should we zero the unused lanes if this is a float compare ?
7883
7884 // Get a new SETCC node to compare the newly widened operands.
7885 // Only some of the compared elements are legal.
7886 EVT SVT = getSetCCResultType(InOp0.getValueType());
7887 // The result type is legal, if its vXi1, keep vXi1 for the new SETCC.
7888 if (VT.getScalarType() == MVT::i1)
7889 SVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
7890 SVT.getVectorElementCount());
7891
7892 SDValue WideSETCC = DAG.getNode(ISD::SETCC, SDLoc(N),
7893 SVT, InOp0, InOp1, N->getOperand(2));
7894
7895 // Extract the needed results from the result vector.
7896 EVT ResVT = EVT::getVectorVT(*DAG.getContext(),
7899 SDValue CC = DAG.getExtractSubvector(dl, ResVT, WideSETCC, 0);
7900
7901 EVT OpVT = N->getOperand(0).getValueType();
7902 ISD::NodeType ExtendCode =
7903 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
7904 return DAG.getNode(ExtendCode, dl, VT, CC);
7905}
7906
7907SDValue DAGTypeLegalizer::WidenVecOp_STRICT_FSETCC(SDNode *N) {
7908 SDValue Chain = N->getOperand(0);
7909 SDValue LHS = GetWidenedVector(N->getOperand(1));
7910 SDValue RHS = GetWidenedVector(N->getOperand(2));
7911 SDValue CC = N->getOperand(3);
7912 SDLoc dl(N);
7913
7914 EVT VT = N->getValueType(0);
7915 EVT EltVT = VT.getVectorElementType();
7916 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
7917 unsigned NumElts = VT.getVectorNumElements();
7918
7919 // Unroll into a build vector.
7920 SmallVector<SDValue, 8> Scalars(NumElts);
7921 SmallVector<SDValue, 8> Chains(NumElts);
7922
7923 for (unsigned i = 0; i != NumElts; ++i) {
7924 SDValue LHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, LHS, i);
7925 SDValue RHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, RHS, i);
7926
7927 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
7928 {Chain, LHSElem, RHSElem, CC});
7929 Chains[i] = Scalars[i].getValue(1);
7930 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
7931 DAG.getBoolConstant(true, dl, EltVT, VT),
7932 DAG.getBoolConstant(false, dl, EltVT, VT));
7933 }
7934
7935 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
7936 ReplaceValueWith(SDValue(N, 1), NewChain);
7937
7938 return DAG.getBuildVector(VT, dl, Scalars);
7939}
7940
7941static unsigned getExtendForIntVecReduction(unsigned Opc) {
7942 switch (Opc) {
7943 default:
7944 llvm_unreachable("Expected integer vector reduction");
7945 case ISD::VECREDUCE_ADD:
7946 case ISD::VECREDUCE_MUL:
7947 case ISD::VECREDUCE_AND:
7948 case ISD::VECREDUCE_OR:
7949 case ISD::VECREDUCE_XOR:
7950 return ISD::ANY_EXTEND;
7953 return ISD::SIGN_EXTEND;
7956 return ISD::ZERO_EXTEND;
7957 }
7958}
7959
7960SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE(SDNode *N) {
7961 SDLoc dl(N);
7962 SDValue Op = GetWidenedVector(N->getOperand(0));
7963 EVT VT = N->getValueType(0);
7964 EVT OrigVT = N->getOperand(0).getValueType();
7965 EVT WideVT = Op.getValueType();
7966 EVT ElemVT = OrigVT.getVectorElementType();
7967 SDNodeFlags Flags = N->getFlags();
7968
7969 unsigned Opc = N->getOpcode();
7970 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
7971 SDValue NeutralElem = DAG.getNeutralElement(BaseOpc, dl, ElemVT, Flags);
7972 assert(NeutralElem && "Neutral element must exist");
7973
7974 // Pad the vector with the neutral element.
7975 unsigned OrigElts = OrigVT.getVectorMinNumElements();
7976 unsigned WideElts = WideVT.getVectorMinNumElements();
7977
7978 // Generate a vp.reduce_op if it is custom/legal for the target. This avoids
7979 // needing to pad the source vector, because the inactive lanes can simply be
7980 // disabled and not contribute to the result.
7981 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opc);
7982 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WideVT)) {
7983 SDValue Start = NeutralElem;
7984 if (VT.isInteger())
7985 Start = DAG.getNode(getExtendForIntVecReduction(Opc), dl, VT, Start);
7986 assert(Start.getValueType() == VT);
7987 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
7988 WideVT.getVectorElementCount());
7989 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
7990 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
7991 OrigVT.getVectorElementCount());
7992 return DAG.getNode(*VPOpcode, dl, VT, {Start, Op, Mask, EVL}, Flags);
7993 }
7994
7995 if (WideVT.isScalableVector()) {
7996 unsigned GCD = std::gcd(OrigElts, WideElts);
7997 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
7999 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
8000 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
8001 Op = DAG.getInsertSubvector(dl, Op, SplatNeutral, Idx);
8002 return DAG.getNode(Opc, dl, VT, Op, Flags);
8003 }
8004
8005 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
8006 Op = DAG.getInsertVectorElt(dl, Op, NeutralElem, Idx);
8007
8008 return DAG.getNode(Opc, dl, VT, Op, Flags);
8009}
8010
8011SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE_SEQ(SDNode *N) {
8012 SDLoc dl(N);
8013 SDValue AccOp = N->getOperand(0);
8014 SDValue VecOp = N->getOperand(1);
8015 SDValue Op = GetWidenedVector(VecOp);
8016
8017 EVT VT = N->getValueType(0);
8018 EVT OrigVT = VecOp.getValueType();
8019 EVT WideVT = Op.getValueType();
8020 EVT ElemVT = OrigVT.getVectorElementType();
8021 SDNodeFlags Flags = N->getFlags();
8022
8023 unsigned Opc = N->getOpcode();
8024 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
8025 SDValue NeutralElem = DAG.getNeutralElement(BaseOpc, dl, ElemVT, Flags);
8026
8027 // Pad the vector with the neutral element.
8028 unsigned OrigElts = OrigVT.getVectorMinNumElements();
8029 unsigned WideElts = WideVT.getVectorMinNumElements();
8030
8031 // Generate a vp.reduce_op if it is custom/legal for the target. This avoids
8032 // needing to pad the source vector, because the inactive lanes can simply be
8033 // disabled and not contribute to the result.
8034 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opc);
8035 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WideVT)) {
8036 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8037 WideVT.getVectorElementCount());
8038 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
8039 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8040 OrigVT.getVectorElementCount());
8041 return DAG.getNode(*VPOpcode, dl, VT, {AccOp, Op, Mask, EVL}, Flags);
8042 }
8043
8044 if (WideVT.isScalableVector()) {
8045 unsigned GCD = std::gcd(OrigElts, WideElts);
8046 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
8048 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
8049 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
8050 Op = DAG.getInsertSubvector(dl, Op, SplatNeutral, Idx);
8051 return DAG.getNode(Opc, dl, VT, AccOp, Op, Flags);
8052 }
8053
8054 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
8055 Op = DAG.getInsertVectorElt(dl, Op, NeutralElem, Idx);
8056
8057 return DAG.getNode(Opc, dl, VT, AccOp, Op, Flags);
8058}
8059
8060SDValue DAGTypeLegalizer::WidenVecOp_VP_REDUCE(SDNode *N) {
8061 assert(N->isVPOpcode() && "Expected VP opcode");
8062
8063 SDLoc dl(N);
8064 SDValue Op = GetWidenedVector(N->getOperand(1));
8065 SDValue Mask = GetWidenedMask(N->getOperand(2),
8066 Op.getValueType().getVectorElementCount());
8067
8068 return DAG.getNode(N->getOpcode(), dl, N->getValueType(0),
8069 {N->getOperand(0), Op, Mask, N->getOperand(3)},
8070 N->getFlags());
8071}
8072
8073SDValue DAGTypeLegalizer::WidenVecOp_VSELECT(SDNode *N) {
8074 // This only gets called in the case that the left and right inputs and
8075 // result are of a legal odd vector type, and the condition is illegal i1 of
8076 // the same odd width that needs widening.
8077 EVT VT = N->getValueType(0);
8078 assert(VT.isVector() && !VT.isPow2VectorType() && isTypeLegal(VT));
8079
8080 SDValue Cond = GetWidenedVector(N->getOperand(0));
8081 SDValue LeftIn = DAG.WidenVector(N->getOperand(1), SDLoc(N));
8082 SDValue RightIn = DAG.WidenVector(N->getOperand(2), SDLoc(N));
8083 SDLoc DL(N);
8084
8085 SDValue Select = DAG.getNode(N->getOpcode(), DL, LeftIn.getValueType(), Cond,
8086 LeftIn, RightIn);
8087 return DAG.getExtractSubvector(DL, VT, Select, 0);
8088}
8089
8090SDValue DAGTypeLegalizer::WidenVecOp_VP_CttzElements(SDNode *N) {
8091 SDLoc DL(N);
8092 SDValue Source = GetWidenedVector(N->getOperand(0));
8093 EVT SrcVT = Source.getValueType();
8094 SDValue Mask =
8095 GetWidenedMask(N->getOperand(1), SrcVT.getVectorElementCount());
8096
8097 return DAG.getNode(N->getOpcode(), DL, N->getValueType(0),
8098 {Source, Mask, N->getOperand(2)}, N->getFlags());
8099}
8100
8101//===----------------------------------------------------------------------===//
8102// Vector Widening Utilities
8103//===----------------------------------------------------------------------===//
8104
8105// Utility function to find the type to chop up a widen vector for load/store
8106// TLI: Target lowering used to determine legal types.
8107// Width: Width left need to load/store.
8108// WidenVT: The widen vector type to load to/store from
8109// Align: If 0, don't allow use of a wider type
8110// WidenEx: If Align is not 0, the amount additional we can load/store from.
8111
8112static std::optional<EVT> findMemType(SelectionDAG &DAG,
8113 const TargetLowering &TLI, unsigned Width,
8114 EVT WidenVT, unsigned Align = 0,
8115 unsigned WidenEx = 0) {
8116 EVT WidenEltVT = WidenVT.getVectorElementType();
8117 const bool Scalable = WidenVT.isScalableVector();
8118 unsigned WidenWidth = WidenVT.getSizeInBits().getKnownMinValue();
8119 unsigned WidenEltWidth = WidenEltVT.getSizeInBits();
8120 unsigned AlignInBits = Align*8;
8121
8122 EVT RetVT = WidenEltVT;
8123 // Don't bother looking for an integer type if the vector is scalable, skip
8124 // to vector types.
8125 if (!Scalable) {
8126 // If we have one element to load/store, return it.
8127 if (Width == WidenEltWidth)
8128 return RetVT;
8129
8130 // See if there is larger legal integer than the element type to load/store.
8131 for (EVT MemVT : reverse(MVT::integer_valuetypes())) {
8132 unsigned MemVTWidth = MemVT.getSizeInBits();
8133 if (MemVT.getSizeInBits() <= WidenEltWidth)
8134 break;
8135 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
8136 if ((Action == TargetLowering::TypeLegal ||
8138 (WidenWidth % MemVTWidth) == 0 &&
8139 isPowerOf2_32(WidenWidth / MemVTWidth) &&
8140 (MemVTWidth <= Width ||
8141 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
8142 if (MemVTWidth == WidenWidth)
8143 return MemVT;
8144 RetVT = MemVT;
8145 break;
8146 }
8147 }
8148 }
8149
8150 // See if there is a larger vector type to load/store that has the same vector
8151 // element type and is evenly divisible with the WidenVT.
8152 for (EVT MemVT : reverse(MVT::vector_valuetypes())) {
8153 // Skip vector MVTs which don't match the scalable property of WidenVT.
8154 if (Scalable != MemVT.isScalableVector())
8155 continue;
8156 unsigned MemVTWidth = MemVT.getSizeInBits().getKnownMinValue();
8157 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
8158 if ((Action == TargetLowering::TypeLegal ||
8160 WidenEltVT == MemVT.getVectorElementType() &&
8161 (WidenWidth % MemVTWidth) == 0 &&
8162 isPowerOf2_32(WidenWidth / MemVTWidth) &&
8163 (MemVTWidth <= Width ||
8164 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
8165 if (RetVT.getFixedSizeInBits() < MemVTWidth || MemVT == WidenVT)
8166 return MemVT;
8167 }
8168 }
8169
8170 // Using element-wise loads and stores for widening operations is not
8171 // supported for scalable vectors
8172 if (Scalable)
8173 return std::nullopt;
8174
8175 return RetVT;
8176}
8177
8178// Builds a vector type from scalar loads
8179// VecTy: Resulting Vector type
8180// LDOps: Load operators to build a vector type
8181// [Start,End) the list of loads to use.
8184 unsigned Start, unsigned End) {
8185 SDLoc dl(LdOps[Start]);
8186 EVT LdTy = LdOps[Start].getValueType();
8187 unsigned Width = VecTy.getSizeInBits();
8188 unsigned NumElts = Width / LdTy.getSizeInBits();
8189 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), LdTy, NumElts);
8190
8191 unsigned Idx = 1;
8192 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT,LdOps[Start]);
8193
8194 for (unsigned i = Start + 1; i != End; ++i) {
8195 EVT NewLdTy = LdOps[i].getValueType();
8196 if (NewLdTy != LdTy) {
8197 NumElts = Width / NewLdTy.getSizeInBits();
8198 NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewLdTy, NumElts);
8199 VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, VecOp);
8200 // Readjust position and vector position based on new load type.
8201 Idx = Idx * LdTy.getSizeInBits() / NewLdTy.getSizeInBits();
8202 LdTy = NewLdTy;
8203 }
8204 VecOp = DAG.getInsertVectorElt(dl, VecOp, LdOps[i], Idx++);
8205 }
8206 return DAG.getNode(ISD::BITCAST, dl, VecTy, VecOp);
8207}
8208
8209SDValue DAGTypeLegalizer::GenWidenVectorLoads(SmallVectorImpl<SDValue> &LdChain,
8210 LoadSDNode *LD) {
8211 // The strategy assumes that we can efficiently load power-of-two widths.
8212 // The routine chops the vector into the largest vector loads with the same
8213 // element type or scalar loads and then recombines it to the widen vector
8214 // type.
8215 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
8216 EVT LdVT = LD->getMemoryVT();
8217 SDLoc dl(LD);
8218 assert(LdVT.isVector() && WidenVT.isVector());
8219 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
8221
8222 // Load information
8223 SDValue Chain = LD->getChain();
8224 SDValue BasePtr = LD->getBasePtr();
8225 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
8226 AAMDNodes AAInfo = LD->getAAInfo();
8227
8228 TypeSize LdWidth = LdVT.getSizeInBits();
8229 TypeSize WidenWidth = WidenVT.getSizeInBits();
8230 TypeSize WidthDiff = WidenWidth - LdWidth;
8231 // Allow wider loads if they are sufficiently aligned to avoid memory faults
8232 // and if the original load is simple.
8233 unsigned LdAlign =
8234 (!LD->isSimple() || LdVT.isScalableVector()) ? 0 : LD->getAlign().value();
8235
8236 // Find the vector type that can load from.
8237 std::optional<EVT> FirstVT =
8238 findMemType(DAG, TLI, LdWidth.getKnownMinValue(), WidenVT, LdAlign,
8239 WidthDiff.getKnownMinValue());
8240
8241 if (!FirstVT)
8242 return SDValue();
8243
8244 SmallVector<EVT, 8> MemVTs;
8245 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
8246
8247 // Unless we're able to load in one instruction we must work out how to load
8248 // the remainder.
8249 if (!TypeSize::isKnownLE(LdWidth, FirstVTWidth)) {
8250 std::optional<EVT> NewVT = FirstVT;
8251 TypeSize RemainingWidth = LdWidth;
8252 TypeSize NewVTWidth = FirstVTWidth;
8253 do {
8254 RemainingWidth -= NewVTWidth;
8255 if (TypeSize::isKnownLT(RemainingWidth, NewVTWidth)) {
8256 // The current type we are using is too large. Find a better size.
8257 NewVT = findMemType(DAG, TLI, RemainingWidth.getKnownMinValue(),
8258 WidenVT, LdAlign, WidthDiff.getKnownMinValue());
8259 if (!NewVT)
8260 return SDValue();
8261 NewVTWidth = NewVT->getSizeInBits();
8262 }
8263 MemVTs.push_back(*NewVT);
8264 } while (TypeSize::isKnownGT(RemainingWidth, NewVTWidth));
8265 }
8266
8267 SDValue LdOp = DAG.getLoad(*FirstVT, dl, Chain, BasePtr, LD->getPointerInfo(),
8268 LD->getBaseAlign(), MMOFlags, AAInfo);
8269 LdChain.push_back(LdOp.getValue(1));
8270
8271 // Check if we can load the element with one instruction.
8272 if (MemVTs.empty()) {
8273 assert(TypeSize::isKnownLE(LdWidth, FirstVTWidth));
8274 if (!FirstVT->isVector()) {
8275 unsigned NumElts =
8276 WidenWidth.getFixedValue() / FirstVTWidth.getFixedValue();
8277 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), *FirstVT, NumElts);
8278 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT, LdOp);
8279 return DAG.getNode(ISD::BITCAST, dl, WidenVT, VecOp);
8280 }
8281 if (FirstVT == WidenVT)
8282 return LdOp;
8283
8284 // TODO: We don't currently have any tests that exercise this code path.
8285 assert(WidenWidth.getFixedValue() % FirstVTWidth.getFixedValue() == 0);
8286 unsigned NumConcat =
8287 WidenWidth.getFixedValue() / FirstVTWidth.getFixedValue();
8288 SmallVector<SDValue, 16> ConcatOps(NumConcat);
8289 SDValue UndefVal = DAG.getUNDEF(*FirstVT);
8290 ConcatOps[0] = LdOp;
8291 for (unsigned i = 1; i != NumConcat; ++i)
8292 ConcatOps[i] = UndefVal;
8293 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, ConcatOps);
8294 }
8295
8296 // Load vector by using multiple loads from largest vector to scalar.
8298 LdOps.push_back(LdOp);
8299
8300 uint64_t ScaledOffset = 0;
8301 MachinePointerInfo MPI = LD->getPointerInfo();
8302
8303 // First incremement past the first load.
8304 IncrementPointer(cast<LoadSDNode>(LdOp), *FirstVT, MPI, BasePtr,
8305 &ScaledOffset);
8306
8307 for (EVT MemVT : MemVTs) {
8308 Align NewAlign = ScaledOffset == 0
8309 ? LD->getBaseAlign()
8310 : commonAlignment(LD->getAlign(), ScaledOffset);
8311 SDValue L =
8312 DAG.getLoad(MemVT, dl, Chain, BasePtr, MPI, NewAlign, MMOFlags, AAInfo);
8313
8314 LdOps.push_back(L);
8315 LdChain.push_back(L.getValue(1));
8316 IncrementPointer(cast<LoadSDNode>(L), MemVT, MPI, BasePtr, &ScaledOffset);
8317 }
8318
8319 // Build the vector from the load operations.
8320 unsigned End = LdOps.size();
8321 if (!LdOps[0].getValueType().isVector())
8322 // All the loads are scalar loads.
8323 return BuildVectorFromScalar(DAG, WidenVT, LdOps, 0, End);
8324
8325 // If the load contains vectors, build the vector using concat vector.
8326 // All of the vectors used to load are power-of-2, and the scalar loads can be
8327 // combined to make a power-of-2 vector.
8328 SmallVector<SDValue, 16> ConcatOps(End);
8329 int i = End - 1;
8330 int Idx = End;
8331 EVT LdTy = LdOps[i].getValueType();
8332 // First, combine the scalar loads to a vector.
8333 if (!LdTy.isVector()) {
8334 for (--i; i >= 0; --i) {
8335 LdTy = LdOps[i].getValueType();
8336 if (LdTy.isVector())
8337 break;
8338 }
8339 ConcatOps[--Idx] = BuildVectorFromScalar(DAG, LdTy, LdOps, i + 1, End);
8340 }
8341
8342 ConcatOps[--Idx] = LdOps[i];
8343 for (--i; i >= 0; --i) {
8344 EVT NewLdTy = LdOps[i].getValueType();
8345 if (NewLdTy != LdTy) {
8346 // Create a larger vector.
8347 TypeSize LdTySize = LdTy.getSizeInBits();
8348 TypeSize NewLdTySize = NewLdTy.getSizeInBits();
8349 assert(NewLdTySize.isScalable() == LdTySize.isScalable() &&
8350 NewLdTySize.isKnownMultipleOf(LdTySize.getKnownMinValue()));
8351 unsigned NumOps =
8352 NewLdTySize.getKnownMinValue() / LdTySize.getKnownMinValue();
8354 unsigned j = 0;
8355 for (; j != End-Idx; ++j)
8356 WidenOps[j] = ConcatOps[Idx+j];
8357 for (; j != NumOps; ++j)
8358 WidenOps[j] = DAG.getUNDEF(LdTy);
8359
8360 ConcatOps[End-1] = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewLdTy,
8361 WidenOps);
8362 Idx = End - 1;
8363 LdTy = NewLdTy;
8364 }
8365 ConcatOps[--Idx] = LdOps[i];
8366 }
8367
8368 if (WidenWidth == LdTy.getSizeInBits() * (End - Idx))
8369 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
8370 ArrayRef(&ConcatOps[Idx], End - Idx));
8371
8372 // We need to fill the rest with undefs to build the vector.
8373 unsigned NumOps =
8374 WidenWidth.getKnownMinValue() / LdTy.getSizeInBits().getKnownMinValue();
8376 SDValue UndefVal = DAG.getUNDEF(LdTy);
8377 {
8378 unsigned i = 0;
8379 for (; i != End-Idx; ++i)
8380 WidenOps[i] = ConcatOps[Idx+i];
8381 for (; i != NumOps; ++i)
8382 WidenOps[i] = UndefVal;
8383 }
8384 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, WidenOps);
8385}
8386
8387SDValue
8388DAGTypeLegalizer::GenWidenVectorExtLoads(SmallVectorImpl<SDValue> &LdChain,
8389 LoadSDNode *LD,
8390 ISD::LoadExtType ExtType) {
8391 // For extension loads, it may not be more efficient to chop up the vector
8392 // and then extend it. Instead, we unroll the load and build a new vector.
8393 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
8394 EVT LdVT = LD->getMemoryVT();
8395 SDLoc dl(LD);
8396 assert(LdVT.isVector() && WidenVT.isVector());
8397 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
8398
8399 // Load information
8400 SDValue Chain = LD->getChain();
8401 SDValue BasePtr = LD->getBasePtr();
8402 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
8403 AAMDNodes AAInfo = LD->getAAInfo();
8404
8405 if (LdVT.isScalableVector())
8406 return SDValue();
8407
8408 EVT EltVT = WidenVT.getVectorElementType();
8409 EVT LdEltVT = LdVT.getVectorElementType();
8410 unsigned NumElts = LdVT.getVectorNumElements();
8411
8412 // Load each element and widen.
8413 unsigned WidenNumElts = WidenVT.getVectorNumElements();
8414 SmallVector<SDValue, 16> Ops(WidenNumElts);
8415 unsigned Increment = LdEltVT.getSizeInBits() / 8;
8416 Ops[0] =
8417 DAG.getExtLoad(ExtType, dl, EltVT, Chain, BasePtr, LD->getPointerInfo(),
8418 LdEltVT, LD->getBaseAlign(), MMOFlags, AAInfo);
8419 LdChain.push_back(Ops[0].getValue(1));
8420 unsigned i = 0, Offset = Increment;
8421 for (i=1; i < NumElts; ++i, Offset += Increment) {
8422 SDValue NewBasePtr =
8423 DAG.getObjectPtrOffset(dl, BasePtr, TypeSize::getFixed(Offset));
8424 Ops[i] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, NewBasePtr,
8425 LD->getPointerInfo().getWithOffset(Offset), LdEltVT,
8426 LD->getBaseAlign(), MMOFlags, AAInfo);
8427 LdChain.push_back(Ops[i].getValue(1));
8428 }
8429
8430 // Fill the rest with undefs.
8431 SDValue UndefVal = DAG.getUNDEF(EltVT);
8432 for (; i != WidenNumElts; ++i)
8433 Ops[i] = UndefVal;
8434
8435 return DAG.getBuildVector(WidenVT, dl, Ops);
8436}
8437
8438bool DAGTypeLegalizer::GenWidenVectorStores(SmallVectorImpl<SDValue> &StChain,
8439 StoreSDNode *ST) {
8440 // The strategy assumes that we can efficiently store power-of-two widths.
8441 // The routine chops the vector into the largest vector stores with the same
8442 // element type or scalar stores.
8443 SDValue Chain = ST->getChain();
8444 SDValue BasePtr = ST->getBasePtr();
8445 MachineMemOperand::Flags MMOFlags = ST->getMemOperand()->getFlags();
8446 AAMDNodes AAInfo = ST->getAAInfo();
8447 SDValue ValOp = GetWidenedVector(ST->getValue());
8448 SDLoc dl(ST);
8449
8450 EVT StVT = ST->getMemoryVT();
8451 TypeSize StWidth = StVT.getSizeInBits();
8452 EVT ValVT = ValOp.getValueType();
8453 TypeSize ValWidth = ValVT.getSizeInBits();
8454 EVT ValEltVT = ValVT.getVectorElementType();
8455 unsigned ValEltWidth = ValEltVT.getFixedSizeInBits();
8456 assert(StVT.getVectorElementType() == ValEltVT);
8457 assert(StVT.isScalableVector() == ValVT.isScalableVector() &&
8458 "Mismatch between store and value types");
8459
8460 int Idx = 0; // current index to store
8461
8462 MachinePointerInfo MPI = ST->getPointerInfo();
8463 uint64_t ScaledOffset = 0;
8464
8465 // A breakdown of how to widen this vector store. Each element of the vector
8466 // is a memory VT combined with the number of times it is to be stored to,
8467 // e,g., v5i32 -> {{v2i32,2},{i32,1}}
8469
8470 while (StWidth.isNonZero()) {
8471 // Find the largest vector type we can store with.
8472 std::optional<EVT> NewVT =
8473 findMemType(DAG, TLI, StWidth.getKnownMinValue(), ValVT);
8474 if (!NewVT)
8475 return false;
8476 MemVTs.push_back({*NewVT, 0});
8477 TypeSize NewVTWidth = NewVT->getSizeInBits();
8478
8479 do {
8480 StWidth -= NewVTWidth;
8481 MemVTs.back().second++;
8482 } while (StWidth.isNonZero() && TypeSize::isKnownGE(StWidth, NewVTWidth));
8483 }
8484
8485 for (const auto &Pair : MemVTs) {
8486 EVT NewVT = Pair.first;
8487 unsigned Count = Pair.second;
8488 TypeSize NewVTWidth = NewVT.getSizeInBits();
8489
8490 if (NewVT.isVector()) {
8491 unsigned NumVTElts = NewVT.getVectorMinNumElements();
8492 do {
8493 Align NewAlign = ScaledOffset == 0
8494 ? ST->getBaseAlign()
8495 : commonAlignment(ST->getAlign(), ScaledOffset);
8496 SDValue EOp = DAG.getExtractSubvector(dl, NewVT, ValOp, Idx);
8497 SDValue PartStore = DAG.getStore(Chain, dl, EOp, BasePtr, MPI, NewAlign,
8498 MMOFlags, AAInfo);
8499 StChain.push_back(PartStore);
8500
8501 Idx += NumVTElts;
8502 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr,
8503 &ScaledOffset);
8504 } while (--Count);
8505 } else {
8506 // Cast the vector to the scalar type we can store.
8507 unsigned NumElts = ValWidth.getFixedValue() / NewVTWidth.getFixedValue();
8508 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewVT, NumElts);
8509 SDValue VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, ValOp);
8510 // Readjust index position based on new vector type.
8511 Idx = Idx * ValEltWidth / NewVTWidth.getFixedValue();
8512 do {
8513 SDValue EOp = DAG.getExtractVectorElt(dl, NewVT, VecOp, Idx++);
8514 SDValue PartStore = DAG.getStore(Chain, dl, EOp, BasePtr, MPI,
8515 ST->getBaseAlign(), MMOFlags, AAInfo);
8516 StChain.push_back(PartStore);
8517
8518 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr);
8519 } while (--Count);
8520 // Restore index back to be relative to the original widen element type.
8521 Idx = Idx * NewVTWidth.getFixedValue() / ValEltWidth;
8522 }
8523 }
8524
8525 return true;
8526}
8527
8528/// Modifies a vector input (widen or narrows) to a vector of NVT. The
8529/// input vector must have the same element type as NVT.
8530/// FillWithZeroes specifies that the vector should be widened with zeroes.
8531SDValue DAGTypeLegalizer::ModifyToType(SDValue InOp, EVT NVT,
8532 bool FillWithZeroes) {
8533 // Note that InOp might have been widened so it might already have
8534 // the right width or it might need be narrowed.
8535 EVT InVT = InOp.getValueType();
8537 "input and widen element type must match");
8538 assert(InVT.isScalableVector() == NVT.isScalableVector() &&
8539 "cannot modify scalable vectors in this way");
8540 SDLoc dl(InOp);
8541
8542 // Check if InOp already has the right width.
8543 if (InVT == NVT)
8544 return InOp;
8545
8546 ElementCount InEC = InVT.getVectorElementCount();
8547 ElementCount WidenEC = NVT.getVectorElementCount();
8548 if (WidenEC.hasKnownScalarFactor(InEC)) {
8549 unsigned NumConcat = WidenEC.getKnownScalarFactor(InEC);
8550 SmallVector<SDValue, 16> Ops(NumConcat);
8551 SDValue FillVal = FillWithZeroes ? DAG.getConstant(0, dl, InVT) :
8552 DAG.getUNDEF(InVT);
8553 Ops[0] = InOp;
8554 for (unsigned i = 1; i != NumConcat; ++i)
8555 Ops[i] = FillVal;
8556
8557 return DAG.getNode(ISD::CONCAT_VECTORS, dl, NVT, Ops);
8558 }
8559
8560 if (InEC.hasKnownScalarFactor(WidenEC))
8561 return DAG.getExtractSubvector(dl, NVT, InOp, 0);
8562
8563 assert(!InVT.isScalableVector() && !NVT.isScalableVector() &&
8564 "Scalable vectors should have been handled already.");
8565
8566 unsigned InNumElts = InEC.getFixedValue();
8567 unsigned WidenNumElts = WidenEC.getFixedValue();
8568
8569 // Fall back to extract and build (+ mask, if padding with zeros).
8570 SmallVector<SDValue, 16> Ops(WidenNumElts);
8571 EVT EltVT = NVT.getVectorElementType();
8572 unsigned MinNumElts = std::min(WidenNumElts, InNumElts);
8573 unsigned Idx;
8574 for (Idx = 0; Idx < MinNumElts; ++Idx)
8575 Ops[Idx] = DAG.getExtractVectorElt(dl, EltVT, InOp, Idx);
8576
8577 SDValue UndefVal = DAG.getUNDEF(EltVT);
8578 for (; Idx < WidenNumElts; ++Idx)
8579 Ops[Idx] = UndefVal;
8580
8581 SDValue Widened = DAG.getBuildVector(NVT, dl, Ops);
8582 if (!FillWithZeroes)
8583 return Widened;
8584
8585 assert(NVT.isInteger() &&
8586 "We expect to never want to FillWithZeroes for non-integral types.");
8587
8589 MaskOps.append(MinNumElts, DAG.getAllOnesConstant(dl, EltVT));
8590 MaskOps.append(WidenNumElts - MinNumElts, DAG.getConstant(0, dl, EltVT));
8591
8592 return DAG.getNode(ISD::AND, dl, NVT, Widened,
8593 DAG.getBuildVector(NVT, dl, MaskOps));
8594}
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
@ 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
@ 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
@ 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
LLVM_ABI bool isBuildVectorOfConstantSDNodes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR node of all ConstantSDNode or undef.
bool isUNINDEXEDLoad(const SDNode *N)
Returns true if the specified node is an unindexed load.
LLVM_ABI std::optional< unsigned > getVPForBaseOpcode(unsigned Opcode)
Translate this non-VP Opcode to its corresponding VP Opcode.
MemIndexType
MemIndexType enum - This enum defines how to interpret MGATHER/SCATTER's index parameter when calcula...
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
LLVM_ABI NodeType getVecReduceBaseOpcode(unsigned VecReduceOpcode)
Get underlying scalar opcode for VECREDUCE opcode.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
LLVM_ABI LegalityPredicate isVector(unsigned TypeIdx)
True iff the specified type index is a vector.
constexpr double e
Context & getContext() const
Definition BasicBlock.h:99
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:532
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1763
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:284
auto reverse(ContainerTy &&C)
Definition STLExtras.h:406
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:279
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:167
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr int PoisonMaskElem
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:189
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
Definition STLExtras.h:1847
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1770
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1909
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.