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