LLVM 22.0.0git
LegalizeVectorTypes.cpp
Go to the documentation of this file.
1//===------- LegalizeVectorTypes.cpp - Legalization of vector types -------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file performs vector type splitting and scalarization for LegalizeTypes.
10// Scalarization is the act of changing a computation in an illegal one-element
11// vector type to be a computation in its scalar element type. For example,
12// implementing <1 x f32> arithmetic in a scalar f32 register. This is needed
13// as a base case when scalarizing vector arithmetic like <4 x f32>, which
14// eventually decomposes to scalars if the target doesn't support v4f32 or v2f32
15// types.
16// Splitting is the act of changing a computation in an invalid vector type to
17// be a computation in two vectors of half the size. For example, implementing
18// <128 x f32> operations in terms of two <64 x f32> operations.
19//
20//===----------------------------------------------------------------------===//
21
22#include "LegalizeTypes.h"
27#include "llvm/IR/DataLayout.h"
31#include <numeric>
32
33using namespace llvm;
34
35#define DEBUG_TYPE "legalize-types"
36
37//===----------------------------------------------------------------------===//
38// Result Vector Scalarization: <1 x ty> -> ty.
39//===----------------------------------------------------------------------===//
40
41void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) {
42 LLVM_DEBUG(dbgs() << "Scalarize node result " << ResNo << ": ";
43 N->dump(&DAG));
44 SDValue R = SDValue();
45
46 switch (N->getOpcode()) {
47 default:
48#ifndef NDEBUG
49 dbgs() << "ScalarizeVectorResult #" << ResNo << ": ";
50 N->dump(&DAG);
51 dbgs() << "\n";
52#endif
53 report_fatal_error("Do not know how to scalarize the result of this "
54 "operator!\n");
55
58 R = ScalarizeVecRes_LOOP_DEPENDENCE_MASK(N);
59 break;
60 case ISD::MERGE_VALUES: R = ScalarizeVecRes_MERGE_VALUES(N, ResNo);break;
61 case ISD::BITCAST: R = ScalarizeVecRes_BITCAST(N); break;
62 case ISD::BUILD_VECTOR: R = ScalarizeVecRes_BUILD_VECTOR(N); break;
63 case ISD::EXTRACT_SUBVECTOR: R = ScalarizeVecRes_EXTRACT_SUBVECTOR(N); break;
64 case ISD::FP_ROUND: R = ScalarizeVecRes_FP_ROUND(N); break;
65 case ISD::AssertZext:
66 case ISD::AssertSext:
67 case ISD::FPOWI:
69 R = ScalarizeVecRes_UnaryOpWithExtraInput(N);
70 break;
71 case ISD::INSERT_VECTOR_ELT: R = ScalarizeVecRes_INSERT_VECTOR_ELT(N); break;
73 R = ScalarizeVecRes_ATOMIC_LOAD(cast<AtomicSDNode>(N));
74 break;
75 case ISD::LOAD: R = ScalarizeVecRes_LOAD(cast<LoadSDNode>(N));break;
76 case ISD::SCALAR_TO_VECTOR: R = ScalarizeVecRes_SCALAR_TO_VECTOR(N); break;
77 case ISD::SIGN_EXTEND_INREG: R = ScalarizeVecRes_InregOp(N); break;
78 case ISD::VSELECT: R = ScalarizeVecRes_VSELECT(N); break;
79 case ISD::SELECT: R = ScalarizeVecRes_SELECT(N); break;
80 case ISD::SELECT_CC: R = ScalarizeVecRes_SELECT_CC(N); break;
81 case ISD::SETCC: R = ScalarizeVecRes_SETCC(N); break;
82 case ISD::POISON:
83 case ISD::UNDEF: R = ScalarizeVecRes_UNDEF(N); break;
84 case ISD::VECTOR_SHUFFLE: R = ScalarizeVecRes_VECTOR_SHUFFLE(N); break;
85 case ISD::IS_FPCLASS: R = ScalarizeVecRes_IS_FPCLASS(N); break;
89 R = ScalarizeVecRes_VecInregOp(N);
90 break;
91 case ISD::ABS:
92 case ISD::ANY_EXTEND:
93 case ISD::BITREVERSE:
94 case ISD::BSWAP:
95 case ISD::CTLZ:
97 case ISD::CTPOP:
98 case ISD::CTTZ:
100 case ISD::FABS:
101 case ISD::FACOS:
102 case ISD::FASIN:
103 case ISD::FATAN:
104 case ISD::FCEIL:
105 case ISD::FCOS:
106 case ISD::FCOSH:
107 case ISD::FEXP:
108 case ISD::FEXP2:
109 case ISD::FEXP10:
110 case ISD::FFLOOR:
111 case ISD::FLOG:
112 case ISD::FLOG10:
113 case ISD::FLOG2:
114 case ISD::FNEARBYINT:
115 case ISD::FNEG:
116 case ISD::FREEZE:
117 case ISD::ARITH_FENCE:
118 case ISD::FP_EXTEND:
119 case ISD::FP_TO_SINT:
120 case ISD::FP_TO_UINT:
121 case ISD::FRINT:
122 case ISD::LRINT:
123 case ISD::LLRINT:
124 case ISD::FROUND:
125 case ISD::FROUNDEVEN:
126 case ISD::LROUND:
127 case ISD::LLROUND:
128 case ISD::FSIN:
129 case ISD::FSINH:
130 case ISD::FSQRT:
131 case ISD::FTAN:
132 case ISD::FTANH:
133 case ISD::FTRUNC:
134 case ISD::SIGN_EXTEND:
135 case ISD::SINT_TO_FP:
136 case ISD::TRUNCATE:
137 case ISD::UINT_TO_FP:
138 case ISD::ZERO_EXTEND:
140 R = ScalarizeVecRes_UnaryOp(N);
141 break;
143 R = ScalarizeVecRes_ADDRSPACECAST(N);
144 break;
145 case ISD::FMODF:
146 case ISD::FFREXP:
147 case ISD::FSINCOS:
148 case ISD::FSINCOSPI:
149 R = ScalarizeVecRes_UnaryOpWithTwoResults(N, ResNo);
150 break;
151 case ISD::ADD:
152 case ISD::AND:
153 case ISD::AVGCEILS:
154 case ISD::AVGCEILU:
155 case ISD::AVGFLOORS:
156 case ISD::AVGFLOORU:
157 case ISD::FADD:
158 case ISD::FCOPYSIGN:
159 case ISD::FDIV:
160 case ISD::FMUL:
161 case ISD::FMINNUM:
162 case ISD::FMAXNUM:
165 case ISD::FMINIMUM:
166 case ISD::FMAXIMUM:
167 case ISD::FMINIMUMNUM:
168 case ISD::FMAXIMUMNUM:
169 case ISD::FLDEXP:
170 case ISD::ABDS:
171 case ISD::ABDU:
172 case ISD::SMIN:
173 case ISD::SMAX:
174 case ISD::UMIN:
175 case ISD::UMAX:
176
177 case ISD::SADDSAT:
178 case ISD::UADDSAT:
179 case ISD::SSUBSAT:
180 case ISD::USUBSAT:
181 case ISD::SSHLSAT:
182 case ISD::USHLSAT:
183
184 case ISD::FPOW:
185 case ISD::FATAN2:
186 case ISD::FREM:
187 case ISD::FSUB:
188 case ISD::MUL:
189 case ISD::MULHS:
190 case ISD::MULHU:
191 case ISD::OR:
192 case ISD::SDIV:
193 case ISD::SREM:
194 case ISD::SUB:
195 case ISD::UDIV:
196 case ISD::UREM:
197 case ISD::XOR:
198 case ISD::SHL:
199 case ISD::SRA:
200 case ISD::SRL:
201 case ISD::ROTL:
202 case ISD::ROTR:
203 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::LOAD: Res = WidenVecRes_LOAD(N); break;
4895 case ISD::STEP_VECTOR:
4896 case ISD::SPLAT_VECTOR:
4898 Res = WidenVecRes_ScalarOp(N);
4899 break;
4900 case ISD::SIGN_EXTEND_INREG: Res = WidenVecRes_InregOp(N); break;
4901 case ISD::VSELECT:
4902 case ISD::SELECT:
4903 case ISD::VP_SELECT:
4904 case ISD::VP_MERGE:
4905 Res = WidenVecRes_Select(N);
4906 break;
4907 case ISD::SELECT_CC: Res = WidenVecRes_SELECT_CC(N); break;
4908 case ISD::VP_SETCC:
4909 case ISD::SETCC: Res = WidenVecRes_SETCC(N); break;
4910 case ISD::POISON:
4911 case ISD::UNDEF: Res = WidenVecRes_UNDEF(N); break;
4913 Res = WidenVecRes_VECTOR_SHUFFLE(cast<ShuffleVectorSDNode>(N));
4914 break;
4915 case ISD::VP_LOAD:
4916 Res = WidenVecRes_VP_LOAD(cast<VPLoadSDNode>(N));
4917 break;
4918 case ISD::VP_LOAD_FF:
4919 Res = WidenVecRes_VP_LOAD_FF(cast<VPLoadFFSDNode>(N));
4920 break;
4921 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
4922 Res = WidenVecRes_VP_STRIDED_LOAD(cast<VPStridedLoadSDNode>(N));
4923 break;
4925 Res = WidenVecRes_VECTOR_COMPRESS(N);
4926 break;
4927 case ISD::MLOAD:
4928 Res = WidenVecRes_MLOAD(cast<MaskedLoadSDNode>(N));
4929 break;
4930 case ISD::MGATHER:
4931 Res = WidenVecRes_MGATHER(cast<MaskedGatherSDNode>(N));
4932 break;
4933 case ISD::VP_GATHER:
4934 Res = WidenVecRes_VP_GATHER(cast<VPGatherSDNode>(N));
4935 break;
4937 Res = WidenVecRes_VECTOR_REVERSE(N);
4938 break;
4940 Res = WidenVecRes_GET_ACTIVE_LANE_MASK(N);
4941 break;
4942
4943 case ISD::ADD: case ISD::VP_ADD:
4944 case ISD::AND: case ISD::VP_AND:
4945 case ISD::MUL: case ISD::VP_MUL:
4946 case ISD::MULHS:
4947 case ISD::MULHU:
4948 case ISD::ABDS:
4949 case ISD::ABDU:
4950 case ISD::OR: case ISD::VP_OR:
4951 case ISD::SUB: case ISD::VP_SUB:
4952 case ISD::XOR: case ISD::VP_XOR:
4953 case ISD::SHL: case ISD::VP_SHL:
4954 case ISD::SRA: case ISD::VP_SRA:
4955 case ISD::SRL: case ISD::VP_SRL:
4956 case ISD::CLMUL:
4957 case ISD::CLMULR:
4958 case ISD::CLMULH:
4959 case ISD::FMINNUM:
4960 case ISD::FMINNUM_IEEE:
4961 case ISD::VP_FMINNUM:
4962 case ISD::FMAXNUM:
4963 case ISD::FMAXNUM_IEEE:
4964 case ISD::VP_FMAXNUM:
4965 case ISD::FMINIMUM:
4966 case ISD::VP_FMINIMUM:
4967 case ISD::FMAXIMUM:
4968 case ISD::VP_FMAXIMUM:
4969 case ISD::FMINIMUMNUM:
4970 case ISD::FMAXIMUMNUM:
4971 case ISD::SMIN: case ISD::VP_SMIN:
4972 case ISD::SMAX: case ISD::VP_SMAX:
4973 case ISD::UMIN: case ISD::VP_UMIN:
4974 case ISD::UMAX: case ISD::VP_UMAX:
4975 case ISD::UADDSAT: case ISD::VP_UADDSAT:
4976 case ISD::SADDSAT: case ISD::VP_SADDSAT:
4977 case ISD::USUBSAT: case ISD::VP_USUBSAT:
4978 case ISD::SSUBSAT: case ISD::VP_SSUBSAT:
4979 case ISD::SSHLSAT:
4980 case ISD::USHLSAT:
4981 case ISD::ROTL:
4982 case ISD::ROTR:
4983 case ISD::AVGFLOORS:
4984 case ISD::AVGFLOORU:
4985 case ISD::AVGCEILS:
4986 case ISD::AVGCEILU:
4987 // Vector-predicated binary op widening. Note that -- unlike the
4988 // unpredicated versions -- we don't have to worry about trapping on
4989 // operations like UDIV, FADD, etc., as we pass on the original vector
4990 // length parameter. This means the widened elements containing garbage
4991 // aren't active.
4992 case ISD::VP_SDIV:
4993 case ISD::VP_UDIV:
4994 case ISD::VP_SREM:
4995 case ISD::VP_UREM:
4996 case ISD::VP_FADD:
4997 case ISD::VP_FSUB:
4998 case ISD::VP_FMUL:
4999 case ISD::VP_FDIV:
5000 case ISD::VP_FREM:
5001 case ISD::VP_FCOPYSIGN:
5002 Res = WidenVecRes_Binary(N);
5003 break;
5004
5005 case ISD::SCMP:
5006 case ISD::UCMP:
5007 Res = WidenVecRes_CMP(N);
5008 break;
5009
5010 case ISD::FPOW:
5011 case ISD::FATAN2:
5012 case ISD::FREM:
5013 if (unrollExpandedOp())
5014 break;
5015 // If the target has custom/legal support for the scalar FP intrinsic ops
5016 // (they are probably not destined to become libcalls), then widen those
5017 // like any other binary ops.
5018 [[fallthrough]];
5019
5020 case ISD::FADD:
5021 case ISD::FMUL:
5022 case ISD::FSUB:
5023 case ISD::FDIV:
5024 case ISD::SDIV:
5025 case ISD::UDIV:
5026 case ISD::SREM:
5027 case ISD::UREM:
5028 Res = WidenVecRes_BinaryCanTrap(N);
5029 break;
5030
5031 case ISD::SMULFIX:
5032 case ISD::SMULFIXSAT:
5033 case ISD::UMULFIX:
5034 case ISD::UMULFIXSAT:
5035 // These are binary operations, but with an extra operand that shouldn't
5036 // be widened (the scale).
5037 Res = WidenVecRes_BinaryWithExtraScalarOp(N);
5038 break;
5039
5040#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
5041 case ISD::STRICT_##DAGN:
5042#include "llvm/IR/ConstrainedOps.def"
5043 Res = WidenVecRes_StrictFP(N);
5044 break;
5045
5046 case ISD::UADDO:
5047 case ISD::SADDO:
5048 case ISD::USUBO:
5049 case ISD::SSUBO:
5050 case ISD::UMULO:
5051 case ISD::SMULO:
5052 Res = WidenVecRes_OverflowOp(N, ResNo);
5053 break;
5054
5055 case ISD::FCOPYSIGN:
5056 Res = WidenVecRes_FCOPYSIGN(N);
5057 break;
5058
5059 case ISD::IS_FPCLASS:
5060 case ISD::FPTRUNC_ROUND:
5061 Res = WidenVecRes_UnarySameEltsWithScalarArg(N);
5062 break;
5063
5064 case ISD::FLDEXP:
5065 case ISD::FPOWI:
5066 if (!unrollExpandedOp())
5067 Res = WidenVecRes_ExpOp(N);
5068 break;
5069
5073 Res = WidenVecRes_EXTEND_VECTOR_INREG(N);
5074 break;
5075
5076 case ISD::ANY_EXTEND:
5077 case ISD::FP_EXTEND:
5078 case ISD::VP_FP_EXTEND:
5079 case ISD::FP_ROUND:
5080 case ISD::VP_FP_ROUND:
5081 case ISD::FP_TO_SINT:
5082 case ISD::VP_FP_TO_SINT:
5083 case ISD::FP_TO_UINT:
5084 case ISD::VP_FP_TO_UINT:
5085 case ISD::SIGN_EXTEND:
5086 case ISD::VP_SIGN_EXTEND:
5087 case ISD::SINT_TO_FP:
5088 case ISD::VP_SINT_TO_FP:
5089 case ISD::VP_TRUNCATE:
5090 case ISD::TRUNCATE:
5091 case ISD::UINT_TO_FP:
5092 case ISD::VP_UINT_TO_FP:
5093 case ISD::ZERO_EXTEND:
5094 case ISD::VP_ZERO_EXTEND:
5095 Res = WidenVecRes_Convert(N);
5096 break;
5097
5100 Res = WidenVecRes_FP_TO_XINT_SAT(N);
5101 break;
5102
5103 case ISD::LRINT:
5104 case ISD::LLRINT:
5105 case ISD::VP_LRINT:
5106 case ISD::VP_LLRINT:
5107 case ISD::LROUND:
5108 case ISD::LLROUND:
5109 Res = WidenVecRes_XROUND(N);
5110 break;
5111
5112 case ISD::FACOS:
5113 case ISD::FASIN:
5114 case ISD::FATAN:
5115 case ISD::FCEIL:
5116 case ISD::FCOS:
5117 case ISD::FCOSH:
5118 case ISD::FEXP:
5119 case ISD::FEXP2:
5120 case ISD::FEXP10:
5121 case ISD::FFLOOR:
5122 case ISD::FLOG:
5123 case ISD::FLOG10:
5124 case ISD::FLOG2:
5125 case ISD::FNEARBYINT:
5126 case ISD::FRINT:
5127 case ISD::FROUND:
5128 case ISD::FROUNDEVEN:
5129 case ISD::FSIN:
5130 case ISD::FSINH:
5131 case ISD::FSQRT:
5132 case ISD::FTAN:
5133 case ISD::FTANH:
5134 case ISD::FTRUNC:
5135 if (unrollExpandedOp())
5136 break;
5137 // If the target has custom/legal support for the scalar FP intrinsic ops
5138 // (they are probably not destined to become libcalls), then widen those
5139 // like any other unary ops.
5140 [[fallthrough]];
5141
5142 case ISD::ABS:
5143 case ISD::VP_ABS:
5144 case ISD::BITREVERSE:
5145 case ISD::VP_BITREVERSE:
5146 case ISD::BSWAP:
5147 case ISD::VP_BSWAP:
5148 case ISD::CTLZ:
5149 case ISD::VP_CTLZ:
5151 case ISD::VP_CTLZ_ZERO_UNDEF:
5152 case ISD::CTPOP:
5153 case ISD::VP_CTPOP:
5154 case ISD::CTTZ:
5155 case ISD::VP_CTTZ:
5157 case ISD::VP_CTTZ_ZERO_UNDEF:
5158 case ISD::FNEG: case ISD::VP_FNEG:
5159 case ISD::FABS: case ISD::VP_FABS:
5160 case ISD::VP_SQRT:
5161 case ISD::VP_FCEIL:
5162 case ISD::VP_FFLOOR:
5163 case ISD::VP_FRINT:
5164 case ISD::VP_FNEARBYINT:
5165 case ISD::VP_FROUND:
5166 case ISD::VP_FROUNDEVEN:
5167 case ISD::VP_FROUNDTOZERO:
5168 case ISD::FREEZE:
5169 case ISD::ARITH_FENCE:
5170 case ISD::FCANONICALIZE:
5172 Res = WidenVecRes_Unary(N);
5173 break;
5174 case ISD::FMA: case ISD::VP_FMA:
5175 case ISD::FSHL:
5176 case ISD::VP_FSHL:
5177 case ISD::FSHR:
5178 case ISD::VP_FSHR:
5179 Res = WidenVecRes_Ternary(N);
5180 break;
5181 case ISD::FMODF:
5182 case ISD::FFREXP:
5183 case ISD::FSINCOS:
5184 case ISD::FSINCOSPI: {
5185 if (!unrollExpandedOp())
5186 Res = WidenVecRes_UnaryOpWithTwoResults(N, ResNo);
5187 break;
5188 }
5189 }
5190
5191 // If Res is null, the sub-method took care of registering the result.
5192 if (Res.getNode())
5193 SetWidenedVector(SDValue(N, ResNo), Res);
5194}
5195
5196SDValue DAGTypeLegalizer::WidenVecRes_Ternary(SDNode *N) {
5197 // Ternary op widening.
5198 SDLoc dl(N);
5199 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5200 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5201 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5202 SDValue InOp3 = GetWidenedVector(N->getOperand(2));
5203 if (N->getNumOperands() == 3)
5204 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3);
5205
5206 assert(N->getNumOperands() == 5 && "Unexpected number of operands!");
5207 assert(N->isVPOpcode() && "Expected VP opcode");
5208
5209 SDValue Mask =
5210 GetWidenedMask(N->getOperand(3), WidenVT.getVectorElementCount());
5211 return DAG.getNode(N->getOpcode(), dl, WidenVT,
5212 {InOp1, InOp2, InOp3, Mask, N->getOperand(4)});
5213}
5214
5215SDValue DAGTypeLegalizer::WidenVecRes_Binary(SDNode *N) {
5216 // Binary op widening.
5217 SDLoc dl(N);
5218 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5219 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5220 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5221 if (N->getNumOperands() == 2)
5222 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2,
5223 N->getFlags());
5224
5225 assert(N->getNumOperands() == 4 && "Unexpected number of operands!");
5226 assert(N->isVPOpcode() && "Expected VP opcode");
5227
5228 SDValue Mask =
5229 GetWidenedMask(N->getOperand(2), WidenVT.getVectorElementCount());
5230 return DAG.getNode(N->getOpcode(), dl, WidenVT,
5231 {InOp1, InOp2, Mask, N->getOperand(3)}, N->getFlags());
5232}
5233
5234SDValue DAGTypeLegalizer::WidenVecRes_CMP(SDNode *N) {
5235 LLVMContext &Ctxt = *DAG.getContext();
5236 SDLoc dl(N);
5237
5238 SDValue LHS = N->getOperand(0);
5239 SDValue RHS = N->getOperand(1);
5240 EVT OpVT = LHS.getValueType();
5241 if (getTypeAction(OpVT) == TargetLowering::TypeWidenVector) {
5242 LHS = GetWidenedVector(LHS);
5243 RHS = GetWidenedVector(RHS);
5244 OpVT = LHS.getValueType();
5245 }
5246
5247 EVT WidenResVT = TLI.getTypeToTransformTo(Ctxt, N->getValueType(0));
5248 ElementCount WidenResEC = WidenResVT.getVectorElementCount();
5249 if (WidenResEC == OpVT.getVectorElementCount()) {
5250 return DAG.getNode(N->getOpcode(), dl, WidenResVT, LHS, RHS);
5251 }
5252
5253 return DAG.UnrollVectorOp(N, WidenResVT.getVectorNumElements());
5254}
5255
5256SDValue DAGTypeLegalizer::WidenVecRes_BinaryWithExtraScalarOp(SDNode *N) {
5257 // Binary op widening, but with an extra operand that shouldn't be widened.
5258 SDLoc dl(N);
5259 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5260 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5261 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5262 SDValue InOp3 = N->getOperand(2);
5263 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3,
5264 N->getFlags());
5265}
5266
5267// Given a vector of operations that have been broken up to widen, see
5268// if we can collect them together into the next widest legal VT. This
5269// implementation is trap-safe.
5271 SmallVectorImpl<SDValue> &ConcatOps,
5272 unsigned ConcatEnd, EVT VT, EVT MaxVT,
5273 EVT WidenVT) {
5274 // Check to see if we have a single operation with the widen type.
5275 if (ConcatEnd == 1) {
5276 VT = ConcatOps[0].getValueType();
5277 if (VT == WidenVT)
5278 return ConcatOps[0];
5279 }
5280
5281 SDLoc dl(ConcatOps[0]);
5282 EVT WidenEltVT = WidenVT.getVectorElementType();
5283
5284 // while (Some element of ConcatOps is not of type MaxVT) {
5285 // From the end of ConcatOps, collect elements of the same type and put
5286 // them into an op of the next larger supported type
5287 // }
5288 while (ConcatOps[ConcatEnd-1].getValueType() != MaxVT) {
5289 int Idx = ConcatEnd - 1;
5290 VT = ConcatOps[Idx--].getValueType();
5291 while (Idx >= 0 && ConcatOps[Idx].getValueType() == VT)
5292 Idx--;
5293
5294 int NextSize = VT.isVector() ? VT.getVectorNumElements() : 1;
5295 EVT NextVT;
5296 do {
5297 NextSize *= 2;
5298 NextVT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NextSize);
5299 } while (!TLI.isTypeLegal(NextVT));
5300
5301 if (!VT.isVector()) {
5302 // Scalar type, create an INSERT_VECTOR_ELEMENT of type NextVT
5303 SDValue VecOp = DAG.getUNDEF(NextVT);
5304 unsigned NumToInsert = ConcatEnd - Idx - 1;
5305 for (unsigned i = 0, OpIdx = Idx + 1; i < NumToInsert; i++, OpIdx++)
5306 VecOp = DAG.getInsertVectorElt(dl, VecOp, ConcatOps[OpIdx], i);
5307 ConcatOps[Idx+1] = VecOp;
5308 ConcatEnd = Idx + 2;
5309 } else {
5310 // Vector type, create a CONCAT_VECTORS of type NextVT
5311 SDValue undefVec = DAG.getUNDEF(VT);
5312 unsigned OpsToConcat = NextSize/VT.getVectorNumElements();
5313 SmallVector<SDValue, 16> SubConcatOps(OpsToConcat);
5314 unsigned RealVals = ConcatEnd - Idx - 1;
5315 unsigned SubConcatEnd = 0;
5316 unsigned SubConcatIdx = Idx + 1;
5317 while (SubConcatEnd < RealVals)
5318 SubConcatOps[SubConcatEnd++] = ConcatOps[++Idx];
5319 while (SubConcatEnd < OpsToConcat)
5320 SubConcatOps[SubConcatEnd++] = undefVec;
5321 ConcatOps[SubConcatIdx] = DAG.getNode(ISD::CONCAT_VECTORS, dl,
5322 NextVT, SubConcatOps);
5323 ConcatEnd = SubConcatIdx + 1;
5324 }
5325 }
5326
5327 // Check to see if we have a single operation with the widen type.
5328 if (ConcatEnd == 1) {
5329 VT = ConcatOps[0].getValueType();
5330 if (VT == WidenVT)
5331 return ConcatOps[0];
5332 }
5333
5334 // add undefs of size MaxVT until ConcatOps grows to length of WidenVT
5335 unsigned NumOps = WidenVT.getVectorNumElements()/MaxVT.getVectorNumElements();
5336 if (NumOps != ConcatEnd ) {
5337 SDValue UndefVal = DAG.getUNDEF(MaxVT);
5338 for (unsigned j = ConcatEnd; j < NumOps; ++j)
5339 ConcatOps[j] = UndefVal;
5340 }
5341 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
5342 ArrayRef(ConcatOps.data(), NumOps));
5343}
5344
5345SDValue DAGTypeLegalizer::WidenVecRes_BinaryCanTrap(SDNode *N) {
5346 // Binary op widening for operations that can trap.
5347 unsigned Opcode = N->getOpcode();
5348 SDLoc dl(N);
5349 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5350 EVT WidenEltVT = WidenVT.getVectorElementType();
5351 EVT VT = WidenVT;
5352 unsigned NumElts = VT.getVectorMinNumElements();
5353 const SDNodeFlags Flags = N->getFlags();
5354 while (!TLI.isTypeLegal(VT) && NumElts != 1) {
5355 NumElts = NumElts / 2;
5356 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5357 }
5358
5359 if (NumElts != 1 && !TLI.canOpTrap(N->getOpcode(), VT)) {
5360 // Operation doesn't trap so just widen as normal.
5361 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5362 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5363 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, Flags);
5364 }
5365
5366 // Generate a vp.op if it is custom/legal for the target. This avoids need
5367 // to split and tile the subvectors (below), because the inactive lanes can
5368 // simply be disabled. To avoid possible recursion, only do this if the
5369 // widened mask type is legal.
5370 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opcode);
5371 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WidenVT)) {
5372 if (EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
5373 WidenVT.getVectorElementCount());
5374 TLI.isTypeLegal(WideMaskVT)) {
5375 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5376 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5377 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
5378 SDValue EVL =
5379 DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
5380 N->getValueType(0).getVectorElementCount());
5381 return DAG.getNode(*VPOpcode, dl, WidenVT, InOp1, InOp2, Mask, EVL,
5382 Flags);
5383 }
5384 }
5385
5386 // FIXME: Improve support for scalable vectors.
5387 assert(!VT.isScalableVector() && "Scalable vectors not handled yet.");
5388
5389 // No legal vector version so unroll the vector operation and then widen.
5390 if (NumElts == 1)
5391 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
5392
5393 // Since the operation can trap, apply operation on the original vector.
5394 EVT MaxVT = VT;
5395 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5396 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5397 unsigned CurNumElts = N->getValueType(0).getVectorNumElements();
5398
5399 SmallVector<SDValue, 16> ConcatOps(CurNumElts);
5400 unsigned ConcatEnd = 0; // Current ConcatOps index.
5401 int Idx = 0; // Current Idx into input vectors.
5402
5403 // NumElts := greatest legal vector size (at most WidenVT)
5404 // while (orig. vector has unhandled elements) {
5405 // take munches of size NumElts from the beginning and add to ConcatOps
5406 // NumElts := next smaller supported vector size or 1
5407 // }
5408 while (CurNumElts != 0) {
5409 while (CurNumElts >= NumElts) {
5410 SDValue EOp1 = DAG.getExtractSubvector(dl, VT, InOp1, Idx);
5411 SDValue EOp2 = DAG.getExtractSubvector(dl, VT, InOp2, Idx);
5412 ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, VT, EOp1, EOp2, Flags);
5413 Idx += NumElts;
5414 CurNumElts -= NumElts;
5415 }
5416 do {
5417 NumElts = NumElts / 2;
5418 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5419 } while (!TLI.isTypeLegal(VT) && NumElts != 1);
5420
5421 if (NumElts == 1) {
5422 for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
5423 SDValue EOp1 = DAG.getExtractVectorElt(dl, WidenEltVT, InOp1, Idx);
5424 SDValue EOp2 = DAG.getExtractVectorElt(dl, WidenEltVT, InOp2, Idx);
5425 ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, WidenEltVT,
5426 EOp1, EOp2, Flags);
5427 }
5428 CurNumElts = 0;
5429 }
5430 }
5431
5432 return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
5433}
5434
5435SDValue DAGTypeLegalizer::WidenVecRes_StrictFP(SDNode *N) {
5436 switch (N->getOpcode()) {
5437 case ISD::STRICT_FSETCC:
5439 return WidenVecRes_STRICT_FSETCC(N);
5446 return WidenVecRes_Convert_StrictFP(N);
5447 default:
5448 break;
5449 }
5450
5451 // StrictFP op widening for operations that can trap.
5452 unsigned NumOpers = N->getNumOperands();
5453 unsigned Opcode = N->getOpcode();
5454 SDLoc dl(N);
5455 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5456 EVT WidenEltVT = WidenVT.getVectorElementType();
5457 EVT VT = WidenVT;
5458 unsigned NumElts = VT.getVectorNumElements();
5459 while (!TLI.isTypeLegal(VT) && NumElts != 1) {
5460 NumElts = NumElts / 2;
5461 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5462 }
5463
5464 // No legal vector version so unroll the vector operation and then widen.
5465 if (NumElts == 1)
5466 return UnrollVectorOp_StrictFP(N, WidenVT.getVectorNumElements());
5467
5468 // Since the operation can trap, apply operation on the original vector.
5469 EVT MaxVT = VT;
5471 unsigned CurNumElts = N->getValueType(0).getVectorNumElements();
5472
5473 SmallVector<SDValue, 16> ConcatOps(CurNumElts);
5475 unsigned ConcatEnd = 0; // Current ConcatOps index.
5476 int Idx = 0; // Current Idx into input vectors.
5477
5478 // The Chain is the first operand.
5479 InOps.push_back(N->getOperand(0));
5480
5481 // Now process the remaining operands.
5482 for (unsigned i = 1; i < NumOpers; ++i) {
5483 SDValue Oper = N->getOperand(i);
5484
5485 EVT OpVT = Oper.getValueType();
5486 if (OpVT.isVector()) {
5487 if (getTypeAction(OpVT) == TargetLowering::TypeWidenVector)
5488 Oper = GetWidenedVector(Oper);
5489 else {
5490 EVT WideOpVT =
5491 EVT::getVectorVT(*DAG.getContext(), OpVT.getVectorElementType(),
5492 WidenVT.getVectorElementCount());
5493 Oper = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WideOpVT,
5494 DAG.getUNDEF(WideOpVT), Oper,
5495 DAG.getVectorIdxConstant(0, dl));
5496 }
5497 }
5498
5499 InOps.push_back(Oper);
5500 }
5501
5502 // NumElts := greatest legal vector size (at most WidenVT)
5503 // while (orig. vector has unhandled elements) {
5504 // take munches of size NumElts from the beginning and add to ConcatOps
5505 // NumElts := next smaller supported vector size or 1
5506 // }
5507 while (CurNumElts != 0) {
5508 while (CurNumElts >= NumElts) {
5510
5511 for (unsigned i = 0; i < NumOpers; ++i) {
5512 SDValue Op = InOps[i];
5513
5514 EVT OpVT = Op.getValueType();
5515 if (OpVT.isVector()) {
5516 EVT OpExtractVT =
5517 EVT::getVectorVT(*DAG.getContext(), OpVT.getVectorElementType(),
5519 Op = DAG.getExtractSubvector(dl, OpExtractVT, Op, Idx);
5520 }
5521
5522 EOps.push_back(Op);
5523 }
5524
5525 EVT OperVT[] = {VT, MVT::Other};
5526 SDValue Oper = DAG.getNode(Opcode, dl, OperVT, EOps);
5527 ConcatOps[ConcatEnd++] = Oper;
5528 Chains.push_back(Oper.getValue(1));
5529 Idx += NumElts;
5530 CurNumElts -= NumElts;
5531 }
5532 do {
5533 NumElts = NumElts / 2;
5534 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
5535 } while (!TLI.isTypeLegal(VT) && NumElts != 1);
5536
5537 if (NumElts == 1) {
5538 for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
5540
5541 for (unsigned i = 0; i < NumOpers; ++i) {
5542 SDValue Op = InOps[i];
5543
5544 EVT OpVT = Op.getValueType();
5545 if (OpVT.isVector())
5546 Op = DAG.getExtractVectorElt(dl, OpVT.getVectorElementType(), Op,
5547 Idx);
5548
5549 EOps.push_back(Op);
5550 }
5551
5552 EVT WidenVT[] = {WidenEltVT, MVT::Other};
5553 SDValue Oper = DAG.getNode(Opcode, dl, WidenVT, EOps);
5554 ConcatOps[ConcatEnd++] = Oper;
5555 Chains.push_back(Oper.getValue(1));
5556 }
5557 CurNumElts = 0;
5558 }
5559 }
5560
5561 // Build a factor node to remember all the Ops that have been created.
5562 SDValue NewChain;
5563 if (Chains.size() == 1)
5564 NewChain = Chains[0];
5565 else
5566 NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
5567 ReplaceValueWith(SDValue(N, 1), NewChain);
5568
5569 return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
5570}
5571
5572SDValue DAGTypeLegalizer::WidenVecRes_OverflowOp(SDNode *N, unsigned ResNo) {
5573 SDLoc DL(N);
5574 EVT ResVT = N->getValueType(0);
5575 EVT OvVT = N->getValueType(1);
5576 EVT WideResVT, WideOvVT;
5577 SDValue WideLHS, WideRHS;
5578
5579 // TODO: This might result in a widen/split loop.
5580 if (ResNo == 0) {
5581 WideResVT = TLI.getTypeToTransformTo(*DAG.getContext(), ResVT);
5582 WideOvVT = EVT::getVectorVT(
5583 *DAG.getContext(), OvVT.getVectorElementType(),
5584 WideResVT.getVectorNumElements());
5585
5586 WideLHS = GetWidenedVector(N->getOperand(0));
5587 WideRHS = GetWidenedVector(N->getOperand(1));
5588 } else {
5589 WideOvVT = TLI.getTypeToTransformTo(*DAG.getContext(), OvVT);
5590 WideResVT = EVT::getVectorVT(
5591 *DAG.getContext(), ResVT.getVectorElementType(),
5592 WideOvVT.getVectorNumElements());
5593
5594 SDValue Zero = DAG.getVectorIdxConstant(0, DL);
5595 WideLHS = DAG.getNode(
5596 ISD::INSERT_SUBVECTOR, DL, WideResVT, DAG.getUNDEF(WideResVT),
5597 N->getOperand(0), Zero);
5598 WideRHS = DAG.getNode(
5599 ISD::INSERT_SUBVECTOR, DL, WideResVT, DAG.getUNDEF(WideResVT),
5600 N->getOperand(1), Zero);
5601 }
5602
5603 SDVTList WideVTs = DAG.getVTList(WideResVT, WideOvVT);
5604 SDNode *WideNode = DAG.getNode(
5605 N->getOpcode(), DL, WideVTs, WideLHS, WideRHS).getNode();
5606
5607 // Replace the other vector result not being explicitly widened here.
5608 unsigned OtherNo = 1 - ResNo;
5609 EVT OtherVT = N->getValueType(OtherNo);
5610 if (getTypeAction(OtherVT) == TargetLowering::TypeWidenVector) {
5611 SetWidenedVector(SDValue(N, OtherNo), SDValue(WideNode, OtherNo));
5612 } else {
5613 SDValue Zero = DAG.getVectorIdxConstant(0, DL);
5614 SDValue OtherVal = DAG.getNode(
5615 ISD::EXTRACT_SUBVECTOR, DL, OtherVT, SDValue(WideNode, OtherNo), Zero);
5616 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
5617 }
5618
5619 return SDValue(WideNode, ResNo);
5620}
5621
5622SDValue DAGTypeLegalizer::WidenVecRes_Convert(SDNode *N) {
5623 LLVMContext &Ctx = *DAG.getContext();
5624 SDValue InOp = N->getOperand(0);
5625 SDLoc DL(N);
5626
5627 EVT WidenVT = TLI.getTypeToTransformTo(Ctx, N->getValueType(0));
5628 ElementCount WidenEC = WidenVT.getVectorElementCount();
5629
5630 EVT InVT = InOp.getValueType();
5631
5632 unsigned Opcode = N->getOpcode();
5633 const SDNodeFlags Flags = N->getFlags();
5634
5635 // Handle the case of ZERO_EXTEND where the promoted InVT element size does
5636 // not equal that of WidenVT.
5637 if (N->getOpcode() == ISD::ZERO_EXTEND &&
5638 getTypeAction(InVT) == TargetLowering::TypePromoteInteger &&
5639 TLI.getTypeToTransformTo(Ctx, InVT).getScalarSizeInBits() !=
5640 WidenVT.getScalarSizeInBits()) {
5641 InOp = ZExtPromotedInteger(InOp);
5642 InVT = InOp.getValueType();
5643 if (WidenVT.getScalarSizeInBits() < InVT.getScalarSizeInBits())
5644 Opcode = ISD::TRUNCATE;
5645 }
5646
5647 EVT InEltVT = InVT.getVectorElementType();
5648 EVT InWidenVT = EVT::getVectorVT(Ctx, InEltVT, WidenEC);
5649 ElementCount InVTEC = InVT.getVectorElementCount();
5650
5651 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
5652 InOp = GetWidenedVector(N->getOperand(0));
5653 InVT = InOp.getValueType();
5654 InVTEC = InVT.getVectorElementCount();
5655 if (InVTEC == WidenEC) {
5656 if (N->getNumOperands() == 1)
5657 return DAG.getNode(Opcode, DL, WidenVT, InOp, Flags);
5658 if (N->getNumOperands() == 3) {
5659 assert(N->isVPOpcode() && "Expected VP opcode");
5660 SDValue Mask =
5661 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
5662 return DAG.getNode(Opcode, DL, WidenVT, InOp, Mask, N->getOperand(2));
5663 }
5664 return DAG.getNode(Opcode, DL, WidenVT, InOp, N->getOperand(1), Flags);
5665 }
5666 if (WidenVT.getSizeInBits() == InVT.getSizeInBits()) {
5667 // If both input and result vector types are of same width, extend
5668 // operations should be done with SIGN/ZERO_EXTEND_VECTOR_INREG, which
5669 // accepts fewer elements in the result than in the input.
5670 if (Opcode == ISD::ANY_EXTEND)
5671 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
5672 if (Opcode == ISD::SIGN_EXTEND)
5673 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
5674 if (Opcode == ISD::ZERO_EXTEND)
5675 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
5676 }
5677
5678 // For TRUNCATE, try to widen using the legal EC of the input type instead
5679 // if the legalisation action for that intermediate type is not widening.
5680 // E.g. for trunc nxv1i64 -> nxv1i8 where
5681 // - nxv1i64 input gets widened to nxv2i64
5682 // - nxv1i8 output gets widened to nxv16i8
5683 // Then one can try widening the result to nxv2i8 (instead of going all the
5684 // way to nxv16i8) if this later allows type promotion.
5685 EVT MidResVT =
5686 EVT::getVectorVT(Ctx, WidenVT.getVectorElementType(), InVTEC);
5687 if (N->getOpcode() == ISD::TRUNCATE &&
5688 getTypeAction(MidResVT) == TargetLowering::TypePromoteInteger) {
5689 SDValue MidRes = DAG.getNode(ISD::TRUNCATE, DL, MidResVT, InOp, Flags);
5690 return DAG.getInsertSubvector(DL, DAG.getPOISON(WidenVT), MidRes, 0);
5691 }
5692 }
5693
5694 if (TLI.isTypeLegal(InWidenVT)) {
5695 // Because the result and the input are different vector types, widening
5696 // the result could create a legal type but widening the input might make
5697 // it an illegal type that might lead to repeatedly splitting the input
5698 // and then widening it. To avoid this, we widen the input only if
5699 // it results in a legal type.
5700 if (WidenEC.isKnownMultipleOf(InVTEC.getKnownMinValue())) {
5701 // Widen the input and call convert on the widened input vector.
5702 unsigned NumConcat =
5703 WidenEC.getKnownMinValue() / InVTEC.getKnownMinValue();
5704 SmallVector<SDValue, 16> Ops(NumConcat, DAG.getPOISON(InVT));
5705 Ops[0] = InOp;
5706 SDValue InVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InWidenVT, Ops);
5707 if (N->getNumOperands() == 1)
5708 return DAG.getNode(Opcode, DL, WidenVT, InVec, Flags);
5709 return DAG.getNode(Opcode, DL, WidenVT, InVec, N->getOperand(1), Flags);
5710 }
5711
5712 if (InVTEC.isKnownMultipleOf(WidenEC.getKnownMinValue())) {
5713 SDValue InVal = DAG.getExtractSubvector(DL, InWidenVT, InOp, 0);
5714 // Extract the input and convert the shorten input vector.
5715 if (N->getNumOperands() == 1)
5716 return DAG.getNode(Opcode, DL, WidenVT, InVal, Flags);
5717 return DAG.getNode(Opcode, DL, WidenVT, InVal, N->getOperand(1), Flags);
5718 }
5719 }
5720
5721 // Otherwise unroll into some nasty scalar code and rebuild the vector.
5722 EVT EltVT = WidenVT.getVectorElementType();
5723 SmallVector<SDValue, 16> Ops(WidenEC.getFixedValue(), DAG.getPOISON(EltVT));
5724 // Use the original element count so we don't do more scalar opts than
5725 // necessary.
5726 unsigned MinElts = N->getValueType(0).getVectorNumElements();
5727 for (unsigned i=0; i < MinElts; ++i) {
5728 SDValue Val = DAG.getExtractVectorElt(DL, InEltVT, InOp, i);
5729 if (N->getNumOperands() == 1)
5730 Ops[i] = DAG.getNode(Opcode, DL, EltVT, Val, Flags);
5731 else
5732 Ops[i] = DAG.getNode(Opcode, DL, EltVT, Val, N->getOperand(1), Flags);
5733 }
5734
5735 return DAG.getBuildVector(WidenVT, DL, Ops);
5736}
5737
5738SDValue DAGTypeLegalizer::WidenVecRes_FP_TO_XINT_SAT(SDNode *N) {
5739 SDLoc dl(N);
5740 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5741 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
5742
5743 SDValue Src = N->getOperand(0);
5744 EVT SrcVT = Src.getValueType();
5745
5746 // Also widen the input.
5747 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
5748 Src = GetWidenedVector(Src);
5749 SrcVT = Src.getValueType();
5750 }
5751
5752 // Input and output not widened to the same size, give up.
5753 if (WidenNumElts != SrcVT.getVectorElementCount())
5754 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
5755
5756 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src, N->getOperand(1));
5757}
5758
5759SDValue DAGTypeLegalizer::WidenVecRes_XROUND(SDNode *N) {
5760 SDLoc dl(N);
5761 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5762 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
5763
5764 SDValue Src = N->getOperand(0);
5765 EVT SrcVT = Src.getValueType();
5766
5767 // Also widen the input.
5768 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
5769 Src = GetWidenedVector(Src);
5770 SrcVT = Src.getValueType();
5771 }
5772
5773 // Input and output not widened to the same size, give up.
5774 if (WidenNumElts != SrcVT.getVectorElementCount())
5775 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
5776
5777 if (N->getNumOperands() == 1)
5778 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src);
5779
5780 assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
5781 assert(N->isVPOpcode() && "Expected VP opcode");
5782
5783 SDValue Mask =
5784 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
5785 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src, Mask, N->getOperand(2));
5786}
5787
5788SDValue DAGTypeLegalizer::WidenVecRes_Convert_StrictFP(SDNode *N) {
5789 SDValue InOp = N->getOperand(1);
5790 SDLoc DL(N);
5791 SmallVector<SDValue, 4> NewOps(N->ops());
5792
5793 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5794 unsigned WidenNumElts = WidenVT.getVectorNumElements();
5795
5796 EVT InVT = InOp.getValueType();
5797 EVT InEltVT = InVT.getVectorElementType();
5798
5799 unsigned Opcode = N->getOpcode();
5800
5801 // FIXME: Optimizations need to be implemented here.
5802
5803 // Otherwise unroll into some nasty scalar code and rebuild the vector.
5804 EVT EltVT = WidenVT.getVectorElementType();
5805 std::array<EVT, 2> EltVTs = {{EltVT, MVT::Other}};
5806 SmallVector<SDValue, 16> Ops(WidenNumElts, DAG.getPOISON(EltVT));
5807 SmallVector<SDValue, 32> OpChains;
5808 // Use the original element count so we don't do more scalar opts than
5809 // necessary.
5810 unsigned MinElts = N->getValueType(0).getVectorNumElements();
5811 for (unsigned i=0; i < MinElts; ++i) {
5812 NewOps[1] = DAG.getExtractVectorElt(DL, InEltVT, InOp, i);
5813 Ops[i] = DAG.getNode(Opcode, DL, EltVTs, NewOps);
5814 OpChains.push_back(Ops[i].getValue(1));
5815 }
5816 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OpChains);
5817 ReplaceValueWith(SDValue(N, 1), NewChain);
5818
5819 return DAG.getBuildVector(WidenVT, DL, Ops);
5820}
5821
5822SDValue DAGTypeLegalizer::WidenVecRes_EXTEND_VECTOR_INREG(SDNode *N) {
5823 unsigned Opcode = N->getOpcode();
5824 SDValue InOp = N->getOperand(0);
5825 SDLoc DL(N);
5826
5827 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5828 EVT WidenSVT = WidenVT.getVectorElementType();
5829 unsigned WidenNumElts = WidenVT.getVectorNumElements();
5830
5831 EVT InVT = InOp.getValueType();
5832 EVT InSVT = InVT.getVectorElementType();
5833 unsigned InVTNumElts = InVT.getVectorNumElements();
5834
5835 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
5836 InOp = GetWidenedVector(InOp);
5837 InVT = InOp.getValueType();
5838 if (InVT.getSizeInBits() == WidenVT.getSizeInBits()) {
5839 switch (Opcode) {
5843 return DAG.getNode(Opcode, DL, WidenVT, InOp);
5844 }
5845 }
5846 }
5847
5848 // Unroll, extend the scalars and rebuild the vector.
5850 for (unsigned i = 0, e = std::min(InVTNumElts, WidenNumElts); i != e; ++i) {
5851 SDValue Val = DAG.getExtractVectorElt(DL, InSVT, InOp, i);
5852 switch (Opcode) {
5854 Val = DAG.getNode(ISD::ANY_EXTEND, DL, WidenSVT, Val);
5855 break;
5857 Val = DAG.getNode(ISD::SIGN_EXTEND, DL, WidenSVT, Val);
5858 break;
5860 Val = DAG.getNode(ISD::ZERO_EXTEND, DL, WidenSVT, Val);
5861 break;
5862 default:
5863 llvm_unreachable("A *_EXTEND_VECTOR_INREG node was expected");
5864 }
5865 Ops.push_back(Val);
5866 }
5867
5868 while (Ops.size() != WidenNumElts)
5869 Ops.push_back(DAG.getPOISON(WidenSVT));
5870
5871 return DAG.getBuildVector(WidenVT, DL, Ops);
5872}
5873
5874SDValue DAGTypeLegalizer::WidenVecRes_FCOPYSIGN(SDNode *N) {
5875 // If this is an FCOPYSIGN with same input types, we can treat it as a
5876 // normal (can trap) binary op.
5877 if (N->getOperand(0).getValueType() == N->getOperand(1).getValueType())
5878 return WidenVecRes_BinaryCanTrap(N);
5879
5880 // If the types are different, fall back to unrolling.
5881 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5882 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
5883}
5884
5885/// Result and first source operand are different scalar types, but must have
5886/// the same number of elements. There is an additional control argument which
5887/// should be passed through unchanged.
5888SDValue DAGTypeLegalizer::WidenVecRes_UnarySameEltsWithScalarArg(SDNode *N) {
5889 SDValue FpValue = N->getOperand(0);
5890 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5891 if (getTypeAction(FpValue.getValueType()) != TargetLowering::TypeWidenVector)
5892 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
5893 SDValue Arg = GetWidenedVector(FpValue);
5894 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, {Arg, N->getOperand(1)},
5895 N->getFlags());
5896}
5897
5898SDValue DAGTypeLegalizer::WidenVecRes_ExpOp(SDNode *N) {
5899 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5900 SDValue InOp = GetWidenedVector(N->getOperand(0));
5901 SDValue RHS = N->getOperand(1);
5902 EVT ExpVT = RHS.getValueType();
5903 SDValue ExpOp = RHS;
5904 if (ExpVT.isVector()) {
5905 EVT WideExpVT = WidenVT.changeVectorElementType(
5906 *DAG.getContext(), ExpVT.getVectorElementType());
5907 ExpOp = ModifyToType(RHS, WideExpVT);
5908 }
5909
5910 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, ExpOp);
5911}
5912
5913SDValue DAGTypeLegalizer::WidenVecRes_Unary(SDNode *N) {
5914 // Unary op widening.
5915 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5916 SDValue InOp = GetWidenedVector(N->getOperand(0));
5917 if (N->getNumOperands() == 1)
5918 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, N->getFlags());
5919 if (N->getOpcode() == ISD::AssertNoFPClass)
5920 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp,
5921 N->getOperand(1), N->getFlags());
5922
5923 assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
5924 assert(N->isVPOpcode() && "Expected VP opcode");
5925
5926 SDValue Mask =
5927 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
5928 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT,
5929 {InOp, Mask, N->getOperand(2)});
5930}
5931
5932SDValue DAGTypeLegalizer::WidenVecRes_InregOp(SDNode *N) {
5933 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5934 EVT ExtVT = EVT::getVectorVT(*DAG.getContext(),
5935 cast<VTSDNode>(N->getOperand(1))->getVT()
5936 .getVectorElementType(),
5937 WidenVT.getVectorNumElements());
5938 SDValue WidenLHS = GetWidenedVector(N->getOperand(0));
5939 return DAG.getNode(N->getOpcode(), SDLoc(N),
5940 WidenVT, WidenLHS, DAG.getValueType(ExtVT));
5941}
5942
5943SDValue DAGTypeLegalizer::WidenVecRes_UnaryOpWithTwoResults(SDNode *N,
5944 unsigned ResNo) {
5945 EVT VT0 = N->getValueType(0);
5946 EVT VT1 = N->getValueType(1);
5947
5948 assert(VT0.isVector() && VT1.isVector() &&
5950 "expected both results to be vectors of matching element count");
5951
5952 LLVMContext &Ctx = *DAG.getContext();
5953 SDValue InOp = GetWidenedVector(N->getOperand(0));
5954
5955 EVT WidenVT = TLI.getTypeToTransformTo(Ctx, N->getValueType(ResNo));
5956 ElementCount WidenEC = WidenVT.getVectorElementCount();
5957
5958 EVT WidenVT0 = EVT::getVectorVT(Ctx, VT0.getVectorElementType(), WidenEC);
5959 EVT WidenVT1 = EVT::getVectorVT(Ctx, VT1.getVectorElementType(), WidenEC);
5960
5961 SDNode *WidenNode =
5962 DAG.getNode(N->getOpcode(), SDLoc(N), {WidenVT0, WidenVT1}, InOp)
5963 .getNode();
5964
5965 ReplaceOtherWidenResults(N, WidenNode, ResNo);
5966 return SDValue(WidenNode, ResNo);
5967}
5968
5969SDValue DAGTypeLegalizer::WidenVecRes_MERGE_VALUES(SDNode *N, unsigned ResNo) {
5970 SDValue WidenVec = DisintegrateMERGE_VALUES(N, ResNo);
5971 return GetWidenedVector(WidenVec);
5972}
5973
5974SDValue DAGTypeLegalizer::WidenVecRes_ADDRSPACECAST(SDNode *N) {
5975 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5976 SDValue InOp = GetWidenedVector(N->getOperand(0));
5977 auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
5978
5979 return DAG.getAddrSpaceCast(SDLoc(N), WidenVT, InOp,
5980 AddrSpaceCastN->getSrcAddressSpace(),
5981 AddrSpaceCastN->getDestAddressSpace());
5982}
5983
5984SDValue DAGTypeLegalizer::WidenVecRes_BITCAST(SDNode *N) {
5985 SDValue InOp = N->getOperand(0);
5986 EVT InVT = InOp.getValueType();
5987 EVT VT = N->getValueType(0);
5988 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
5989 SDLoc dl(N);
5990
5991 switch (getTypeAction(InVT)) {
5993 break;
5995 report_fatal_error("Scalarization of scalable vectors is not supported.");
5997 // If the incoming type is a vector that is being promoted, then
5998 // we know that the elements are arranged differently and that we
5999 // must perform the conversion using a stack slot.
6000 if (InVT.isVector())
6001 break;
6002
6003 // If the InOp is promoted to the same size, convert it. Otherwise,
6004 // fall out of the switch and widen the promoted input.
6005 SDValue NInOp = GetPromotedInteger(InOp);
6006 EVT NInVT = NInOp.getValueType();
6007 if (WidenVT.bitsEq(NInVT)) {
6008 // For big endian targets we need to shift the input integer or the
6009 // interesting bits will end up at the wrong place.
6010 if (DAG.getDataLayout().isBigEndian()) {
6011 unsigned ShiftAmt = NInVT.getSizeInBits() - InVT.getSizeInBits();
6012 NInOp = DAG.getNode(ISD::SHL, dl, NInVT, NInOp,
6013 DAG.getShiftAmountConstant(ShiftAmt, NInVT, dl));
6014 }
6015 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NInOp);
6016 }
6017 InOp = NInOp;
6018 InVT = NInVT;
6019 break;
6020 }
6028 break;
6030 // If the InOp is widened to the same size, convert it. Otherwise, fall
6031 // out of the switch and widen the widened input.
6032 InOp = GetWidenedVector(InOp);
6033 InVT = InOp.getValueType();
6034 if (WidenVT.bitsEq(InVT))
6035 // The input widens to the same size. Convert to the widen value.
6036 return DAG.getNode(ISD::BITCAST, dl, WidenVT, InOp);
6037 break;
6038 }
6039
6040 unsigned WidenSize = WidenVT.getSizeInBits();
6041 unsigned InSize = InVT.getSizeInBits();
6042 unsigned InScalarSize = InVT.getScalarSizeInBits();
6043 // x86mmx is not an acceptable vector element type, so don't try.
6044 if (WidenSize % InScalarSize == 0 && InVT != MVT::x86mmx) {
6045 // Determine new input vector type. The new input vector type will use
6046 // the same element type (if its a vector) or use the input type as a
6047 // vector. It is the same size as the type to widen to.
6048 EVT NewInVT;
6049 unsigned NewNumParts = WidenSize / InSize;
6050 if (InVT.isVector()) {
6051 EVT InEltVT = InVT.getVectorElementType();
6052 NewInVT = EVT::getVectorVT(*DAG.getContext(), InEltVT,
6053 WidenSize / InEltVT.getSizeInBits());
6054 } else {
6055 // For big endian systems, using the promoted input scalar type
6056 // to produce the scalar_to_vector would put the desired bits into
6057 // the least significant byte(s) of the wider element zero. This
6058 // will mean that the users of the result vector are using incorrect
6059 // bits. Use the original input type instead. Although either input
6060 // type can be used on little endian systems, for consistency we
6061 // use the original type there as well.
6062 EVT OrigInVT = N->getOperand(0).getValueType();
6063 NewNumParts = WidenSize / OrigInVT.getSizeInBits();
6064 NewInVT = EVT::getVectorVT(*DAG.getContext(), OrigInVT, NewNumParts);
6065 }
6066
6067 if (TLI.isTypeLegal(NewInVT)) {
6068 SDValue NewVec;
6069 if (InVT.isVector()) {
6070 // Because the result and the input are different vector types, widening
6071 // the result could create a legal type but widening the input might
6072 // make it an illegal type that might lead to repeatedly splitting the
6073 // input and then widening it. To avoid this, we widen the input only if
6074 // it results in a legal type.
6075 if (WidenSize % InSize == 0) {
6076 SmallVector<SDValue, 16> Ops(NewNumParts, DAG.getPOISON(InVT));
6077 Ops[0] = InOp;
6078
6079 NewVec = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewInVT, Ops);
6080 } else {
6082 DAG.ExtractVectorElements(InOp, Ops);
6083 Ops.append(WidenSize / InScalarSize - Ops.size(),
6084 DAG.getPOISON(InVT.getVectorElementType()));
6085
6086 NewVec = DAG.getNode(ISD::BUILD_VECTOR, dl, NewInVT, Ops);
6087 }
6088 } else {
6089 NewVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewInVT, InOp);
6090 }
6091 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NewVec);
6092 }
6093 }
6094
6095 return CreateStackStoreLoad(InOp, WidenVT);
6096}
6097
6098SDValue DAGTypeLegalizer::WidenVecRes_LOOP_DEPENDENCE_MASK(SDNode *N) {
6099 return DAG.getNode(
6100 N->getOpcode(), SDLoc(N),
6101 TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)),
6102 N->getOperand(0), N->getOperand(1), N->getOperand(2), N->getOperand(3));
6103}
6104
6105SDValue DAGTypeLegalizer::WidenVecRes_BUILD_VECTOR(SDNode *N) {
6106 SDLoc dl(N);
6107 // Build a vector with poison for the new nodes.
6108 EVT VT = N->getValueType(0);
6109
6110 // Integer BUILD_VECTOR operands may be larger than the node's vector element
6111 // type. The POISONs need to have the same type as the existing operands.
6112 EVT EltVT = N->getOperand(0).getValueType();
6113 unsigned NumElts = VT.getVectorNumElements();
6114
6115 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6116 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6117
6118 SmallVector<SDValue, 16> NewOps(N->ops());
6119 assert(WidenNumElts >= NumElts && "Shrinking vector instead of widening!");
6120 NewOps.append(WidenNumElts - NumElts, DAG.getPOISON(EltVT));
6121
6122 return DAG.getBuildVector(WidenVT, dl, NewOps);
6123}
6124
6125SDValue DAGTypeLegalizer::WidenVecRes_CONCAT_VECTORS(SDNode *N) {
6126 EVT InVT = N->getOperand(0).getValueType();
6127 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6128 SDLoc dl(N);
6129 unsigned NumOperands = N->getNumOperands();
6130
6131 bool InputWidened = false; // Indicates we need to widen the input.
6132 if (getTypeAction(InVT) != TargetLowering::TypeWidenVector) {
6133 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6134 unsigned NumInElts = InVT.getVectorMinNumElements();
6135 if (WidenNumElts % NumInElts == 0) {
6136 // Add undef vectors to widen to correct length.
6137 unsigned NumConcat = WidenNumElts / NumInElts;
6138 SDValue UndefVal = DAG.getPOISON(InVT);
6139 SmallVector<SDValue, 16> Ops(NumConcat);
6140 for (unsigned i=0; i < NumOperands; ++i)
6141 Ops[i] = N->getOperand(i);
6142 for (unsigned i = NumOperands; i != NumConcat; ++i)
6143 Ops[i] = UndefVal;
6144 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Ops);
6145 }
6146 } else {
6147 InputWidened = true;
6148 if (WidenVT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
6149 // The inputs and the result are widen to the same value.
6150 unsigned i;
6151 for (i=1; i < NumOperands; ++i)
6152 if (!N->getOperand(i).isUndef())
6153 break;
6154
6155 if (i == NumOperands)
6156 // Everything but the first operand is an UNDEF so just return the
6157 // widened first operand.
6158 return GetWidenedVector(N->getOperand(0));
6159
6160 if (NumOperands == 2) {
6161 assert(!WidenVT.isScalableVector() &&
6162 "Cannot use vector shuffles to widen CONCAT_VECTOR result");
6163 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6164 unsigned NumInElts = InVT.getVectorNumElements();
6165
6166 // Replace concat of two operands with a shuffle.
6167 SmallVector<int, 16> MaskOps(WidenNumElts, -1);
6168 for (unsigned i = 0; i < NumInElts; ++i) {
6169 MaskOps[i] = i;
6170 MaskOps[i + NumInElts] = i + WidenNumElts;
6171 }
6172 return DAG.getVectorShuffle(WidenVT, dl,
6173 GetWidenedVector(N->getOperand(0)),
6174 GetWidenedVector(N->getOperand(1)),
6175 MaskOps);
6176 }
6177 }
6178 }
6179
6180 assert(!WidenVT.isScalableVector() &&
6181 "Cannot use build vectors to widen CONCAT_VECTOR result");
6182 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6183 unsigned NumInElts = InVT.getVectorNumElements();
6184
6185 // Fall back to use extracts and build vector.
6186 EVT EltVT = WidenVT.getVectorElementType();
6187 SmallVector<SDValue, 16> Ops(WidenNumElts);
6188 unsigned Idx = 0;
6189 for (unsigned i=0; i < NumOperands; ++i) {
6190 SDValue InOp = N->getOperand(i);
6191 if (InputWidened)
6192 InOp = GetWidenedVector(InOp);
6193 for (unsigned j = 0; j < NumInElts; ++j)
6194 Ops[Idx++] = DAG.getExtractVectorElt(dl, EltVT, InOp, j);
6195 }
6196 SDValue UndefVal = DAG.getPOISON(EltVT);
6197 for (; Idx < WidenNumElts; ++Idx)
6198 Ops[Idx] = UndefVal;
6199 return DAG.getBuildVector(WidenVT, dl, Ops);
6200}
6201
6202SDValue DAGTypeLegalizer::WidenVecRes_INSERT_SUBVECTOR(SDNode *N) {
6203 EVT VT = N->getValueType(0);
6204 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6205 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
6206 SDValue InOp2 = N->getOperand(1);
6207 SDValue Idx = N->getOperand(2);
6208 SDLoc dl(N);
6209 return DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WidenVT, InOp1, InOp2, Idx);
6210}
6211
6212SDValue DAGTypeLegalizer::WidenVecRes_EXTRACT_SUBVECTOR(SDNode *N) {
6213 EVT VT = N->getValueType(0);
6214 EVT EltVT = VT.getVectorElementType();
6215 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6216 SDValue InOp = N->getOperand(0);
6217 SDValue Idx = N->getOperand(1);
6218 SDLoc dl(N);
6219
6220 auto InOpTypeAction = getTypeAction(InOp.getValueType());
6221 if (InOpTypeAction == TargetLowering::TypeWidenVector)
6222 InOp = GetWidenedVector(InOp);
6223
6224 EVT InVT = InOp.getValueType();
6225
6226 // Check if we can just return the input vector after widening.
6227 uint64_t IdxVal = Idx->getAsZExtVal();
6228 if (IdxVal == 0 && InVT == WidenVT)
6229 return InOp;
6230
6231 // Check if we can extract from the vector.
6232 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6233 unsigned InNumElts = InVT.getVectorMinNumElements();
6234 unsigned VTNumElts = VT.getVectorMinNumElements();
6235 assert(IdxVal % VTNumElts == 0 &&
6236 "Expected Idx to be a multiple of subvector minimum vector length");
6237 if (IdxVal % WidenNumElts == 0 && IdxVal + WidenNumElts < InNumElts)
6238 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, WidenVT, InOp, Idx);
6239
6240 if (VT.isScalableVector()) {
6241 // Try to split the operation up into smaller extracts and concat the
6242 // results together, e.g.
6243 // nxv6i64 extract_subvector(nxv12i64, 6)
6244 // <->
6245 // nxv8i64 concat(
6246 // nxv2i64 extract_subvector(nxv16i64, 6)
6247 // nxv2i64 extract_subvector(nxv16i64, 8)
6248 // nxv2i64 extract_subvector(nxv16i64, 10)
6249 // undef)
6250 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
6251 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
6252 "down type's element count");
6253 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
6255 // Avoid recursion around e.g. nxv1i8.
6256 if (getTypeAction(PartVT) != TargetLowering::TypeWidenVector) {
6258 unsigned I = 0;
6259 for (; I < VTNumElts / GCD; ++I)
6260 Parts.push_back(
6261 DAG.getExtractSubvector(dl, PartVT, InOp, IdxVal + I * GCD));
6262 for (; I < WidenNumElts / GCD; ++I)
6263 Parts.push_back(DAG.getPOISON(PartVT));
6264
6265 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
6266 }
6267
6268 // Fallback to extracting through memory.
6269
6270 Align Alignment = DAG.getReducedAlign(InVT, /*UseABI=*/false);
6271 SDValue StackPtr = DAG.CreateStackTemporary(InVT.getStoreSize(), Alignment);
6272 MachineFunction &MF = DAG.getMachineFunction();
6273 int FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
6274 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
6275
6276 MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
6279 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
6282
6283 // Write out the input vector.
6284 SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, InOp, StackPtr, StoreMMO);
6285
6286 // Build a mask to match the length of the non-widened result.
6287 SDValue Mask =
6288 DAG.getMaskFromElementCount(dl, WidenVT, VT.getVectorElementCount());
6289
6290 // Read back the sub-vector setting the remaining lanes to poison.
6291 StackPtr = TLI.getVectorSubVecPointer(DAG, StackPtr, InVT, VT, Idx);
6292 return DAG.getMaskedLoad(
6293 WidenVT, dl, Ch, StackPtr, DAG.getUNDEF(StackPtr.getValueType()), Mask,
6294 DAG.getPOISON(WidenVT), VT, LoadMMO, ISD::UNINDEXED, ISD::NON_EXTLOAD);
6295 }
6296
6297 // We could try widening the input to the right length but for now, extract
6298 // the original elements, fill the rest with undefs and build a vector.
6299 SmallVector<SDValue, 16> Ops(WidenNumElts);
6300 unsigned i;
6301 for (i = 0; i < VTNumElts; ++i)
6302 Ops[i] = DAG.getExtractVectorElt(dl, EltVT, InOp, IdxVal + i);
6303
6304 SDValue UndefVal = DAG.getPOISON(EltVT);
6305 for (; i < WidenNumElts; ++i)
6306 Ops[i] = UndefVal;
6307 return DAG.getBuildVector(WidenVT, dl, Ops);
6308}
6309
6310SDValue DAGTypeLegalizer::WidenVecRes_AssertZext(SDNode *N) {
6311 SDValue InOp = ModifyToType(
6312 N->getOperand(0),
6313 TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)), true);
6314 return DAG.getNode(ISD::AssertZext, SDLoc(N), InOp.getValueType(), InOp,
6315 N->getOperand(1));
6316}
6317
6318SDValue DAGTypeLegalizer::WidenVecRes_INSERT_VECTOR_ELT(SDNode *N) {
6319 SDValue InOp = GetWidenedVector(N->getOperand(0));
6320 return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(N),
6321 InOp.getValueType(), InOp,
6322 N->getOperand(1), N->getOperand(2));
6323}
6324
6325SDValue DAGTypeLegalizer::WidenVecRes_LOAD(SDNode *N) {
6326 LoadSDNode *LD = cast<LoadSDNode>(N);
6327 ISD::LoadExtType ExtType = LD->getExtensionType();
6328
6329 // A vector must always be stored in memory as-is, i.e. without any padding
6330 // between the elements, since various code depend on it, e.g. in the
6331 // handling of a bitcast of a vector type to int, which may be done with a
6332 // vector store followed by an integer load. A vector that does not have
6333 // elements that are byte-sized must therefore be stored as an integer
6334 // built out of the extracted vector elements.
6335 if (!LD->getMemoryVT().isByteSized()) {
6336 SDValue Value, NewChain;
6337 std::tie(Value, NewChain) = TLI.scalarizeVectorLoad(LD, DAG);
6338 ReplaceValueWith(SDValue(LD, 0), Value);
6339 ReplaceValueWith(SDValue(LD, 1), NewChain);
6340 return SDValue();
6341 }
6342
6343 // Generate a vector-predicated load if it is custom/legal on the target. To
6344 // avoid possible recursion, only do this if the widened mask type is legal.
6345 // FIXME: Not all targets may support EVL in VP_LOAD. These will have been
6346 // removed from the IR by the ExpandVectorPredication pass but we're
6347 // reintroducing them here.
6348 EVT VT = LD->getValueType(0);
6349 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6350 EVT WideMaskVT = getSetCCResultType(WideVT);
6351
6352 if (ExtType == ISD::NON_EXTLOAD &&
6353 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WideVT) &&
6354 TLI.isTypeLegal(WideMaskVT)) {
6355 SDLoc DL(N);
6356 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
6357 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
6359 SDValue NewLoad =
6360 DAG.getLoadVP(LD->getAddressingMode(), ISD::NON_EXTLOAD, WideVT, DL,
6361 LD->getChain(), LD->getBasePtr(), LD->getOffset(), Mask,
6362 EVL, LD->getMemoryVT(), LD->getMemOperand());
6363
6364 // Modified the chain - switch anything that used the old chain to use
6365 // the new one.
6366 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6367
6368 return NewLoad;
6369 }
6370
6372 SmallVector<SDValue, 16> LdChain; // Chain for the series of load
6373 if (ExtType != ISD::NON_EXTLOAD)
6374 Result = GenWidenVectorExtLoads(LdChain, LD, ExtType);
6375 else
6376 Result = GenWidenVectorLoads(LdChain, LD);
6377
6378 if (Result) {
6379 // If we generate a single load, we can use that for the chain. Otherwise,
6380 // build a factor node to remember the multiple loads are independent and
6381 // chain to that.
6382 SDValue NewChain;
6383 if (LdChain.size() == 1)
6384 NewChain = LdChain[0];
6385 else
6386 NewChain = DAG.getNode(ISD::TokenFactor, SDLoc(LD), MVT::Other, LdChain);
6387
6388 // Modified the chain - switch anything that used the old chain to use
6389 // the new one.
6390 ReplaceValueWith(SDValue(N, 1), NewChain);
6391
6392 return Result;
6393 }
6394
6395 if (VT.isVector()) {
6396 // If all else fails replace the load with a wide masked load.
6397 SDLoc DL(N);
6398 SDValue Mask =
6399 DAG.getMaskFromElementCount(DL, WideVT, VT.getVectorElementCount());
6400
6401 SDValue NewLoad = DAG.getMaskedLoad(
6402 WideVT, DL, LD->getChain(), LD->getBasePtr(), LD->getOffset(), Mask,
6403 DAG.getPOISON(WideVT), LD->getMemoryVT(), LD->getMemOperand(),
6404 LD->getAddressingMode(), LD->getExtensionType());
6405
6406 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6407 return NewLoad;
6408 }
6409
6410 report_fatal_error("Unable to widen vector load");
6411}
6412
6413SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD(VPLoadSDNode *N) {
6414 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6415 SDValue Mask = N->getMask();
6416 SDValue EVL = N->getVectorLength();
6417 ISD::LoadExtType ExtType = N->getExtensionType();
6418 SDLoc dl(N);
6419
6420 // The mask should be widened as well
6421 assert(getTypeAction(Mask.getValueType()) ==
6423 "Unable to widen binary VP op");
6424 Mask = GetWidenedVector(Mask);
6425 assert(Mask.getValueType().getVectorElementCount() ==
6426 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
6427 .getVectorElementCount() &&
6428 "Unable to widen vector load");
6429
6430 SDValue Res =
6431 DAG.getLoadVP(N->getAddressingMode(), ExtType, WidenVT, dl, N->getChain(),
6432 N->getBasePtr(), N->getOffset(), Mask, EVL,
6433 N->getMemoryVT(), N->getMemOperand(), N->isExpandingLoad());
6434 // Legalize the chain result - switch anything that used the old chain to
6435 // use the new one.
6436 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6437 return Res;
6438}
6439
6440SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD_FF(VPLoadFFSDNode *N) {
6441 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6442 SDValue Mask = N->getMask();
6443 SDValue EVL = N->getVectorLength();
6444 SDLoc dl(N);
6445
6446 // The mask should be widened as well
6447 assert(getTypeAction(Mask.getValueType()) ==
6449 "Unable to widen binary VP op");
6450 Mask = GetWidenedVector(Mask);
6451 assert(Mask.getValueType().getVectorElementCount() ==
6452 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
6453 .getVectorElementCount() &&
6454 "Unable to widen vector load");
6455
6456 SDValue Res = DAG.getLoadFFVP(WidenVT, dl, N->getChain(), N->getBasePtr(),
6457 Mask, EVL, N->getMemOperand());
6458 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6459 ReplaceValueWith(SDValue(N, 2), Res.getValue(2));
6460 return Res;
6461}
6462
6463SDValue DAGTypeLegalizer::WidenVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode *N) {
6464 SDLoc DL(N);
6465
6466 // The mask should be widened as well
6467 SDValue Mask = N->getMask();
6468 assert(getTypeAction(Mask.getValueType()) ==
6470 "Unable to widen VP strided load");
6471 Mask = GetWidenedVector(Mask);
6472
6473 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6474 assert(Mask.getValueType().getVectorElementCount() ==
6475 WidenVT.getVectorElementCount() &&
6476 "Data and mask vectors should have the same number of elements");
6477
6478 SDValue Res = DAG.getStridedLoadVP(
6479 N->getAddressingMode(), N->getExtensionType(), WidenVT, DL, N->getChain(),
6480 N->getBasePtr(), N->getOffset(), N->getStride(), Mask,
6481 N->getVectorLength(), N->getMemoryVT(), N->getMemOperand(),
6482 N->isExpandingLoad());
6483
6484 // Legalize the chain result - switch anything that used the old chain to
6485 // use the new one.
6486 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6487 return Res;
6488}
6489
6490SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_COMPRESS(SDNode *N) {
6491 SDValue Vec = N->getOperand(0);
6492 SDValue Mask = N->getOperand(1);
6493 SDValue Passthru = N->getOperand(2);
6494 EVT WideVecVT =
6495 TLI.getTypeToTransformTo(*DAG.getContext(), Vec.getValueType());
6496 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
6497 Mask.getValueType().getVectorElementType(),
6498 WideVecVT.getVectorElementCount());
6499
6500 SDValue WideVec = ModifyToType(Vec, WideVecVT);
6501 SDValue WideMask = ModifyToType(Mask, WideMaskVT, /*FillWithZeroes=*/true);
6502 SDValue WidePassthru = ModifyToType(Passthru, WideVecVT);
6503 return DAG.getNode(ISD::VECTOR_COMPRESS, SDLoc(N), WideVecVT, WideVec,
6504 WideMask, WidePassthru);
6505}
6506
6507SDValue DAGTypeLegalizer::WidenVecRes_MLOAD(MaskedLoadSDNode *N) {
6508 EVT VT = N->getValueType(0);
6509 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6510 SDValue Mask = N->getMask();
6511 EVT MaskVT = Mask.getValueType();
6512 SDValue PassThru = GetWidenedVector(N->getPassThru());
6513 ISD::LoadExtType ExtType = N->getExtensionType();
6514 SDLoc dl(N);
6515
6516 EVT WideMaskVT =
6517 EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(),
6518 WidenVT.getVectorElementCount());
6519
6520 if (ExtType == ISD::NON_EXTLOAD &&
6521 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WidenVT) &&
6522 TLI.isTypeLegal(WideMaskVT) &&
6523 // If there is a passthru, we shouldn't use vp.load. However,
6524 // type legalizer will struggle on masked.load with
6525 // scalable vectors, so for scalable vectors, we still use vp.load
6526 // but manually merge the load result with the passthru using vp.select.
6527 (N->getPassThru()->isUndef() || VT.isScalableVector())) {
6528 Mask = DAG.getInsertSubvector(dl, DAG.getUNDEF(WideMaskVT), Mask, 0);
6529 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
6531 SDValue NewLoad =
6532 DAG.getLoadVP(N->getAddressingMode(), ISD::NON_EXTLOAD, WidenVT, dl,
6533 N->getChain(), N->getBasePtr(), N->getOffset(), Mask, EVL,
6534 N->getMemoryVT(), N->getMemOperand());
6535 SDValue NewVal = NewLoad;
6536
6537 // Manually merge with vp.select
6538 if (!N->getPassThru()->isUndef()) {
6539 assert(WidenVT.isScalableVector());
6540 NewVal =
6541 DAG.getNode(ISD::VP_SELECT, dl, WidenVT, Mask, NewVal, PassThru, EVL);
6542 }
6543
6544 // Modified the chain - switch anything that used the old chain to use
6545 // the new one.
6546 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
6547
6548 return NewVal;
6549 }
6550
6551 // The mask should be widened as well
6552 Mask = ModifyToType(Mask, WideMaskVT, true);
6553
6554 SDValue Res = DAG.getMaskedLoad(
6555 WidenVT, dl, N->getChain(), N->getBasePtr(), N->getOffset(), Mask,
6556 PassThru, N->getMemoryVT(), N->getMemOperand(), N->getAddressingMode(),
6557 ExtType, N->isExpandingLoad());
6558 // Legalize the chain result - switch anything that used the old chain to
6559 // use the new one.
6560 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6561 return Res;
6562}
6563
6564SDValue DAGTypeLegalizer::WidenVecRes_MGATHER(MaskedGatherSDNode *N) {
6565
6566 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6567 SDValue Mask = N->getMask();
6568 EVT MaskVT = Mask.getValueType();
6569 SDValue PassThru = GetWidenedVector(N->getPassThru());
6570 SDValue Scale = N->getScale();
6571 unsigned NumElts = WideVT.getVectorNumElements();
6572 SDLoc dl(N);
6573
6574 // The mask should be widened as well
6575 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
6576 MaskVT.getVectorElementType(),
6577 WideVT.getVectorNumElements());
6578 Mask = ModifyToType(Mask, WideMaskVT, true);
6579
6580 // Widen the Index operand
6581 SDValue Index = N->getIndex();
6582 EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
6583 Index.getValueType().getScalarType(),
6584 NumElts);
6585 Index = ModifyToType(Index, WideIndexVT);
6586 SDValue Ops[] = { N->getChain(), PassThru, Mask, N->getBasePtr(), Index,
6587 Scale };
6588
6589 // Widen the MemoryType
6590 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
6591 N->getMemoryVT().getScalarType(), NumElts);
6592 SDValue Res = DAG.getMaskedGather(DAG.getVTList(WideVT, MVT::Other),
6593 WideMemVT, dl, Ops, N->getMemOperand(),
6594 N->getIndexType(), N->getExtensionType());
6595
6596 // Legalize the chain result - switch anything that used the old chain to
6597 // use the new one.
6598 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6599 return Res;
6600}
6601
6602SDValue DAGTypeLegalizer::WidenVecRes_VP_GATHER(VPGatherSDNode *N) {
6603 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6604 SDValue Mask = N->getMask();
6605 SDValue Scale = N->getScale();
6606 ElementCount WideEC = WideVT.getVectorElementCount();
6607 SDLoc dl(N);
6608
6609 SDValue Index = GetWidenedVector(N->getIndex());
6610 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
6611 N->getMemoryVT().getScalarType(), WideEC);
6612 Mask = GetWidenedMask(Mask, WideEC);
6613
6614 SDValue Ops[] = {N->getChain(), N->getBasePtr(), Index, Scale,
6615 Mask, N->getVectorLength()};
6616 SDValue Res = DAG.getGatherVP(DAG.getVTList(WideVT, MVT::Other), WideMemVT,
6617 dl, Ops, N->getMemOperand(), N->getIndexType());
6618
6619 // Legalize the chain result - switch anything that used the old chain to
6620 // use the new one.
6621 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6622 return Res;
6623}
6624
6625SDValue DAGTypeLegalizer::WidenVecRes_ScalarOp(SDNode *N) {
6626 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6627 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, N->getOperand(0));
6628}
6629
6630// Return true is this is a SETCC node or a strict version of it.
6631static inline bool isSETCCOp(unsigned Opcode) {
6632 switch (Opcode) {
6633 case ISD::SETCC:
6634 case ISD::STRICT_FSETCC:
6636 return true;
6637 }
6638 return false;
6639}
6640
6641// Return true if this is a node that could have two SETCCs as operands.
6642static inline bool isLogicalMaskOp(unsigned Opcode) {
6643 switch (Opcode) {
6644 case ISD::AND:
6645 case ISD::OR:
6646 case ISD::XOR:
6647 return true;
6648 }
6649 return false;
6650}
6651
6652// If N is a SETCC or a strict variant of it, return the type
6653// of the compare operands.
6655 unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
6656 return N->getOperand(OpNo).getValueType();
6657}
6658
6659// This is used just for the assert in convertMask(). Check that this either
6660// a SETCC or a previously handled SETCC by convertMask().
6661#ifndef NDEBUG
6662static inline bool isSETCCorConvertedSETCC(SDValue N) {
6663 if (N.getOpcode() == ISD::EXTRACT_SUBVECTOR)
6664 N = N.getOperand(0);
6665 else if (N.getOpcode() == ISD::CONCAT_VECTORS) {
6666 for (unsigned i = 1; i < N->getNumOperands(); ++i)
6667 if (!N->getOperand(i)->isUndef())
6668 return false;
6669 N = N.getOperand(0);
6670 }
6671
6672 if (N.getOpcode() == ISD::TRUNCATE)
6673 N = N.getOperand(0);
6674 else if (N.getOpcode() == ISD::SIGN_EXTEND)
6675 N = N.getOperand(0);
6676
6677 if (isLogicalMaskOp(N.getOpcode()))
6678 return isSETCCorConvertedSETCC(N.getOperand(0)) &&
6679 isSETCCorConvertedSETCC(N.getOperand(1));
6680
6681 return (isSETCCOp(N.getOpcode()) ||
6683}
6684#endif
6685
6686// Return a mask of vector type MaskVT to replace InMask. Also adjust MaskVT
6687// to ToMaskVT if needed with vector extension or truncation.
6688SDValue DAGTypeLegalizer::convertMask(SDValue InMask, EVT MaskVT,
6689 EVT ToMaskVT) {
6690 // Currently a SETCC or a AND/OR/XOR with two SETCCs are handled.
6691 // FIXME: This code seems to be too restrictive, we might consider
6692 // generalizing it or dropping it.
6693 assert(isSETCCorConvertedSETCC(InMask) && "Unexpected mask argument.");
6694
6695 // Make a new Mask node, with a legal result VT.
6696 SDValue Mask;
6698 for (unsigned i = 0, e = InMask->getNumOperands(); i < e; ++i)
6699 Ops.push_back(InMask->getOperand(i));
6700 if (InMask->isStrictFPOpcode()) {
6701 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask),
6702 { MaskVT, MVT::Other }, Ops);
6703 ReplaceValueWith(InMask.getValue(1), Mask.getValue(1));
6704 }
6705 else
6706 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask), MaskVT, Ops);
6707
6708 // If MaskVT has smaller or bigger elements than ToMaskVT, a vector sign
6709 // extend or truncate is needed.
6710 LLVMContext &Ctx = *DAG.getContext();
6711 unsigned MaskScalarBits = MaskVT.getScalarSizeInBits();
6712 unsigned ToMaskScalBits = ToMaskVT.getScalarSizeInBits();
6713 if (MaskScalarBits < ToMaskScalBits) {
6714 EVT ExtVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
6715 MaskVT.getVectorNumElements());
6716 Mask = DAG.getNode(ISD::SIGN_EXTEND, SDLoc(Mask), ExtVT, Mask);
6717 } else if (MaskScalarBits > ToMaskScalBits) {
6718 EVT TruncVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
6719 MaskVT.getVectorNumElements());
6720 Mask = DAG.getNode(ISD::TRUNCATE, SDLoc(Mask), TruncVT, Mask);
6721 }
6722
6723 assert(Mask->getValueType(0).getScalarSizeInBits() ==
6724 ToMaskVT.getScalarSizeInBits() &&
6725 "Mask should have the right element size by now.");
6726
6727 // Adjust Mask to the right number of elements.
6728 unsigned CurrMaskNumEls = Mask->getValueType(0).getVectorNumElements();
6729 if (CurrMaskNumEls > ToMaskVT.getVectorNumElements()) {
6730 Mask = DAG.getExtractSubvector(SDLoc(Mask), ToMaskVT, Mask, 0);
6731 } else if (CurrMaskNumEls < ToMaskVT.getVectorNumElements()) {
6732 unsigned NumSubVecs = (ToMaskVT.getVectorNumElements() / CurrMaskNumEls);
6733 EVT SubVT = Mask->getValueType(0);
6734 SmallVector<SDValue, 16> SubOps(NumSubVecs, DAG.getUNDEF(SubVT));
6735 SubOps[0] = Mask;
6736 Mask = DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Mask), ToMaskVT, SubOps);
6737 }
6738
6739 assert((Mask->getValueType(0) == ToMaskVT) &&
6740 "A mask of ToMaskVT should have been produced by now.");
6741
6742 return Mask;
6743}
6744
6745// This method tries to handle some special cases for the vselect mask
6746// and if needed adjusting the mask vector type to match that of the VSELECT.
6747// Without it, many cases end up with scalarization of the SETCC, with many
6748// unnecessary instructions.
6749SDValue DAGTypeLegalizer::WidenVSELECTMask(SDNode *N) {
6750 LLVMContext &Ctx = *DAG.getContext();
6751 SDValue Cond = N->getOperand(0);
6752
6753 if (N->getOpcode() != ISD::VSELECT)
6754 return SDValue();
6755
6756 if (!isSETCCOp(Cond->getOpcode()) && !isLogicalMaskOp(Cond->getOpcode()))
6757 return SDValue();
6758
6759 // If this is a splitted VSELECT that was previously already handled, do
6760 // nothing.
6761 EVT CondVT = Cond->getValueType(0);
6762 if (CondVT.getScalarSizeInBits() != 1)
6763 return SDValue();
6764
6765 EVT VSelVT = N->getValueType(0);
6766
6767 // This method can't handle scalable vector types.
6768 // FIXME: This support could be added in the future.
6769 if (VSelVT.isScalableVector())
6770 return SDValue();
6771
6772 // Only handle vector types which are a power of 2.
6773 if (!isPowerOf2_64(VSelVT.getSizeInBits()))
6774 return SDValue();
6775
6776 // Don't touch if this will be scalarized.
6777 EVT FinalVT = VSelVT;
6778 while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
6779 FinalVT = FinalVT.getHalfNumVectorElementsVT(Ctx);
6780
6781 if (FinalVT.getVectorNumElements() == 1)
6782 return SDValue();
6783
6784 // If there is support for an i1 vector mask, don't touch.
6785 if (isSETCCOp(Cond.getOpcode())) {
6786 EVT SetCCOpVT = getSETCCOperandType(Cond);
6787 while (TLI.getTypeAction(Ctx, SetCCOpVT) != TargetLowering::TypeLegal)
6788 SetCCOpVT = TLI.getTypeToTransformTo(Ctx, SetCCOpVT);
6789 EVT SetCCResVT = getSetCCResultType(SetCCOpVT);
6790 if (SetCCResVT.getScalarSizeInBits() == 1)
6791 return SDValue();
6792 } else if (CondVT.getScalarType() == MVT::i1) {
6793 // If there is support for an i1 vector mask (or only scalar i1 conditions),
6794 // don't touch.
6795 while (TLI.getTypeAction(Ctx, CondVT) != TargetLowering::TypeLegal)
6796 CondVT = TLI.getTypeToTransformTo(Ctx, CondVT);
6797
6798 if (CondVT.getScalarType() == MVT::i1)
6799 return SDValue();
6800 }
6801
6802 // Widen the vselect result type if needed.
6803 if (getTypeAction(VSelVT) == TargetLowering::TypeWidenVector)
6804 VSelVT = TLI.getTypeToTransformTo(Ctx, VSelVT);
6805
6806 // The mask of the VSELECT should have integer elements.
6807 EVT ToMaskVT = VSelVT;
6808 if (!ToMaskVT.getScalarType().isInteger())
6809 ToMaskVT = ToMaskVT.changeVectorElementTypeToInteger();
6810
6811 SDValue Mask;
6812 if (isSETCCOp(Cond->getOpcode())) {
6813 EVT MaskVT = getSetCCResultType(getSETCCOperandType(Cond));
6814 Mask = convertMask(Cond, MaskVT, ToMaskVT);
6815 } else if (isLogicalMaskOp(Cond->getOpcode()) &&
6816 isSETCCOp(Cond->getOperand(0).getOpcode()) &&
6817 isSETCCOp(Cond->getOperand(1).getOpcode())) {
6818 // Cond is (AND/OR/XOR (SETCC, SETCC))
6819 SDValue SETCC0 = Cond->getOperand(0);
6820 SDValue SETCC1 = Cond->getOperand(1);
6821 EVT VT0 = getSetCCResultType(getSETCCOperandType(SETCC0));
6822 EVT VT1 = getSetCCResultType(getSETCCOperandType(SETCC1));
6823 unsigned ScalarBits0 = VT0.getScalarSizeInBits();
6824 unsigned ScalarBits1 = VT1.getScalarSizeInBits();
6825 unsigned ScalarBits_ToMask = ToMaskVT.getScalarSizeInBits();
6826 EVT MaskVT;
6827 // If the two SETCCs have different VTs, either extend/truncate one of
6828 // them to the other "towards" ToMaskVT, or truncate one and extend the
6829 // other to ToMaskVT.
6830 if (ScalarBits0 != ScalarBits1) {
6831 EVT NarrowVT = ((ScalarBits0 < ScalarBits1) ? VT0 : VT1);
6832 EVT WideVT = ((NarrowVT == VT0) ? VT1 : VT0);
6833 if (ScalarBits_ToMask >= WideVT.getScalarSizeInBits())
6834 MaskVT = WideVT;
6835 else if (ScalarBits_ToMask <= NarrowVT.getScalarSizeInBits())
6836 MaskVT = NarrowVT;
6837 else
6838 MaskVT = ToMaskVT;
6839 } else
6840 // If the two SETCCs have the same VT, don't change it.
6841 MaskVT = VT0;
6842
6843 // Make new SETCCs and logical nodes.
6844 SETCC0 = convertMask(SETCC0, VT0, MaskVT);
6845 SETCC1 = convertMask(SETCC1, VT1, MaskVT);
6846 Cond = DAG.getNode(Cond->getOpcode(), SDLoc(Cond), MaskVT, SETCC0, SETCC1);
6847
6848 // Convert the logical op for VSELECT if needed.
6849 Mask = convertMask(Cond, MaskVT, ToMaskVT);
6850 } else
6851 return SDValue();
6852
6853 return Mask;
6854}
6855
6856SDValue DAGTypeLegalizer::WidenVecRes_Select(SDNode *N) {
6857 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6858 ElementCount WidenEC = WidenVT.getVectorElementCount();
6859
6860 SDValue Cond1 = N->getOperand(0);
6861 EVT CondVT = Cond1.getValueType();
6862 unsigned Opcode = N->getOpcode();
6863 if (CondVT.isVector()) {
6864 if (SDValue WideCond = WidenVSELECTMask(N)) {
6865 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
6866 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
6867 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
6868 return DAG.getNode(Opcode, SDLoc(N), WidenVT, WideCond, InOp1, InOp2);
6869 }
6870
6871 EVT CondEltVT = CondVT.getVectorElementType();
6872 EVT CondWidenVT = EVT::getVectorVT(*DAG.getContext(), CondEltVT, WidenEC);
6873 if (getTypeAction(CondVT) == TargetLowering::TypeWidenVector)
6874 Cond1 = GetWidenedVector(Cond1);
6875
6876 // If we have to split the condition there is no point in widening the
6877 // select. This would result in an cycle of widening the select ->
6878 // widening the condition operand -> splitting the condition operand ->
6879 // splitting the select -> widening the select. Instead split this select
6880 // further and widen the resulting type.
6881 if (getTypeAction(CondVT) == TargetLowering::TypeSplitVector) {
6882 SDValue SplitSelect = SplitVecOp_VSELECT(N, 0);
6883 SDValue Res = ModifyToType(SplitSelect, WidenVT);
6884 return Res;
6885 }
6886
6887 if (Cond1.getValueType() != CondWidenVT)
6888 Cond1 = ModifyToType(Cond1, CondWidenVT);
6889 }
6890
6891 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
6892 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
6893 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
6894 if (Opcode == ISD::VP_SELECT || Opcode == ISD::VP_MERGE)
6895 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2,
6896 N->getOperand(3));
6897 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2);
6898}
6899
6900SDValue DAGTypeLegalizer::WidenVecRes_SELECT_CC(SDNode *N) {
6901 SDValue InOp1 = GetWidenedVector(N->getOperand(2));
6902 SDValue InOp2 = GetWidenedVector(N->getOperand(3));
6903 return DAG.getNode(ISD::SELECT_CC, SDLoc(N),
6904 InOp1.getValueType(), N->getOperand(0),
6905 N->getOperand(1), InOp1, InOp2, N->getOperand(4));
6906}
6907
6908SDValue DAGTypeLegalizer::WidenVecRes_UNDEF(SDNode *N) {
6909 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6910 return DAG.getUNDEF(WidenVT);
6911}
6912
6913SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N) {
6914 EVT VT = N->getValueType(0);
6915 SDLoc dl(N);
6916
6917 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6918 unsigned NumElts = VT.getVectorNumElements();
6919 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6920
6921 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
6922 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
6923
6924 // Adjust mask based on new input vector length.
6925 SmallVector<int, 16> NewMask(WidenNumElts, -1);
6926 for (unsigned i = 0; i != NumElts; ++i) {
6927 int Idx = N->getMaskElt(i);
6928 if (Idx < (int)NumElts)
6929 NewMask[i] = Idx;
6930 else
6931 NewMask[i] = Idx - NumElts + WidenNumElts;
6932 }
6933 return DAG.getVectorShuffle(WidenVT, dl, InOp1, InOp2, NewMask);
6934}
6935
6936SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_REVERSE(SDNode *N) {
6937 EVT VT = N->getValueType(0);
6938 EVT EltVT = VT.getVectorElementType();
6939 SDLoc dl(N);
6940
6941 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6942 SDValue OpValue = GetWidenedVector(N->getOperand(0));
6943 assert(WidenVT == OpValue.getValueType() && "Unexpected widened vector type");
6944
6945 SDValue ReverseVal = DAG.getNode(ISD::VECTOR_REVERSE, dl, WidenVT, OpValue);
6946 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6947 unsigned VTNumElts = VT.getVectorMinNumElements();
6948 unsigned IdxVal = WidenNumElts - VTNumElts;
6949
6950 if (VT.isScalableVector()) {
6951 // Try to split the 'Widen ReverseVal' into smaller extracts and concat the
6952 // results together, e.g.(nxv6i64 -> nxv8i64)
6953 // nxv8i64 vector_reverse
6954 // <->
6955 // nxv8i64 concat(
6956 // nxv2i64 extract_subvector(nxv8i64, 2)
6957 // nxv2i64 extract_subvector(nxv8i64, 4)
6958 // nxv2i64 extract_subvector(nxv8i64, 6)
6959 // nxv2i64 undef)
6960
6961 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
6962 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
6964 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
6965 "down type's element count");
6967 unsigned i = 0;
6968 for (; i < VTNumElts / GCD; ++i)
6969 Parts.push_back(
6970 DAG.getExtractSubvector(dl, PartVT, ReverseVal, IdxVal + i * GCD));
6971 for (; i < WidenNumElts / GCD; ++i)
6972 Parts.push_back(DAG.getPOISON(PartVT));
6973
6974 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
6975 }
6976
6977 // Use VECTOR_SHUFFLE to combine new vector from 'ReverseVal' for
6978 // fixed-vectors.
6979 SmallVector<int, 16> Mask(WidenNumElts, -1);
6980 std::iota(Mask.begin(), Mask.begin() + VTNumElts, IdxVal);
6981
6982 return DAG.getVectorShuffle(WidenVT, dl, ReverseVal, DAG.getUNDEF(WidenVT),
6983 Mask);
6984}
6985
6986SDValue DAGTypeLegalizer::WidenVecRes_GET_ACTIVE_LANE_MASK(SDNode *N) {
6987 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6988 return DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, SDLoc(N), NVT, N->ops());
6989}
6990
6991SDValue DAGTypeLegalizer::WidenVecRes_SETCC(SDNode *N) {
6992 assert(N->getValueType(0).isVector() &&
6993 N->getOperand(0).getValueType().isVector() &&
6994 "Operands must be vectors");
6995 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6996 ElementCount WidenEC = WidenVT.getVectorElementCount();
6997
6998 SDValue InOp1 = N->getOperand(0);
6999 EVT InVT = InOp1.getValueType();
7000 assert(InVT.isVector() && "can not widen non-vector type");
7001 EVT WidenInVT =
7002 EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), WidenEC);
7003
7004 // The input and output types often differ here, and it could be that while
7005 // we'd prefer to widen the result type, the input operands have been split.
7006 // In this case, we also need to split the result of this node as well.
7007 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector) {
7008 SDValue SplitVSetCC = SplitVecOp_VSETCC(N);
7009 SDValue Res = ModifyToType(SplitVSetCC, WidenVT);
7010 return Res;
7011 }
7012
7013 // If the inputs also widen, handle them directly. Otherwise widen by hand.
7014 SDValue InOp2 = N->getOperand(1);
7015 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
7016 InOp1 = GetWidenedVector(InOp1);
7017 InOp2 = GetWidenedVector(InOp2);
7018 } else {
7019 SDValue Poison = DAG.getPOISON(WidenInVT);
7020 SDValue ZeroIdx = DAG.getVectorIdxConstant(0, SDLoc(N));
7021 InOp1 = DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), WidenInVT, Poison,
7022 InOp1, ZeroIdx);
7023 InOp2 = DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), WidenInVT, Poison,
7024 InOp2, ZeroIdx);
7025 }
7026
7027 // Assume that the input and output will be widen appropriately. If not,
7028 // we will have to unroll it at some point.
7029 assert(InOp1.getValueType() == WidenInVT &&
7030 InOp2.getValueType() == WidenInVT &&
7031 "Input not widened to expected type!");
7032 (void)WidenInVT;
7033 if (N->getOpcode() == ISD::VP_SETCC) {
7034 SDValue Mask =
7035 GetWidenedMask(N->getOperand(3), WidenVT.getVectorElementCount());
7036 return DAG.getNode(ISD::VP_SETCC, SDLoc(N), WidenVT, InOp1, InOp2,
7037 N->getOperand(2), Mask, N->getOperand(4));
7038 }
7039 return DAG.getNode(ISD::SETCC, SDLoc(N), WidenVT, InOp1, InOp2,
7040 N->getOperand(2));
7041}
7042
7043SDValue DAGTypeLegalizer::WidenVecRes_STRICT_FSETCC(SDNode *N) {
7044 assert(N->getValueType(0).isVector() &&
7045 N->getOperand(1).getValueType().isVector() &&
7046 "Operands must be vectors");
7047 EVT VT = N->getValueType(0);
7048 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7049 unsigned WidenNumElts = WidenVT.getVectorNumElements();
7050 unsigned NumElts = VT.getVectorNumElements();
7051 EVT EltVT = VT.getVectorElementType();
7052
7053 SDLoc dl(N);
7054 SDValue Chain = N->getOperand(0);
7055 SDValue LHS = N->getOperand(1);
7056 SDValue RHS = N->getOperand(2);
7057 SDValue CC = N->getOperand(3);
7058 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
7059
7060 // Fully unroll and reassemble.
7061 SmallVector<SDValue, 8> Scalars(WidenNumElts, DAG.getPOISON(EltVT));
7062 SmallVector<SDValue, 8> Chains(NumElts);
7063 for (unsigned i = 0; i != NumElts; ++i) {
7064 SDValue LHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, LHS, i);
7065 SDValue RHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, RHS, i);
7066
7067 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
7068 {Chain, LHSElem, RHSElem, CC});
7069 Chains[i] = Scalars[i].getValue(1);
7070 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
7071 DAG.getBoolConstant(true, dl, EltVT, VT),
7072 DAG.getBoolConstant(false, dl, EltVT, VT));
7073 }
7074
7075 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
7076 ReplaceValueWith(SDValue(N, 1), NewChain);
7077
7078 return DAG.getBuildVector(WidenVT, dl, Scalars);
7079}
7080
7081//===----------------------------------------------------------------------===//
7082// Widen Vector Operand
7083//===----------------------------------------------------------------------===//
7084bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned OpNo) {
7085 LLVM_DEBUG(dbgs() << "Widen node operand " << OpNo << ": "; N->dump(&DAG));
7086 SDValue Res = SDValue();
7087
7088 // See if the target wants to custom widen this node.
7089 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
7090 return false;
7091
7092 switch (N->getOpcode()) {
7093 default:
7094#ifndef NDEBUG
7095 dbgs() << "WidenVectorOperand op #" << OpNo << ": ";
7096 N->dump(&DAG);
7097 dbgs() << "\n";
7098#endif
7099 report_fatal_error("Do not know how to widen this operator's operand!");
7100
7101 case ISD::BITCAST: Res = WidenVecOp_BITCAST(N); break;
7102 case ISD::FAKE_USE:
7103 Res = WidenVecOp_FAKE_USE(N);
7104 break;
7105 case ISD::CONCAT_VECTORS: Res = WidenVecOp_CONCAT_VECTORS(N); break;
7106 case ISD::INSERT_SUBVECTOR: Res = WidenVecOp_INSERT_SUBVECTOR(N); break;
7107 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecOp_EXTRACT_SUBVECTOR(N); break;
7108 case ISD::EXTRACT_VECTOR_ELT: Res = WidenVecOp_EXTRACT_VECTOR_ELT(N); break;
7109 case ISD::STORE: Res = WidenVecOp_STORE(N); break;
7110 case ISD::VP_STORE: Res = WidenVecOp_VP_STORE(N, OpNo); break;
7111 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
7112 Res = WidenVecOp_VP_STRIDED_STORE(N, OpNo);
7113 break;
7117 Res = WidenVecOp_EXTEND_VECTOR_INREG(N);
7118 break;
7119 case ISD::MSTORE: Res = WidenVecOp_MSTORE(N, OpNo); break;
7120 case ISD::MGATHER: Res = WidenVecOp_MGATHER(N, OpNo); break;
7121 case ISD::MSCATTER: Res = WidenVecOp_MSCATTER(N, OpNo); break;
7122 case ISD::VP_SCATTER: Res = WidenVecOp_VP_SCATTER(N, OpNo); break;
7123 case ISD::SETCC: Res = WidenVecOp_SETCC(N); break;
7124 case ISD::STRICT_FSETCC:
7125 case ISD::STRICT_FSETCCS: Res = WidenVecOp_STRICT_FSETCC(N); break;
7126 case ISD::VSELECT: Res = WidenVecOp_VSELECT(N); break;
7127 case ISD::FLDEXP:
7128 case ISD::FCOPYSIGN:
7129 case ISD::LROUND:
7130 case ISD::LLROUND:
7131 case ISD::LRINT:
7132 case ISD::LLRINT:
7133 Res = WidenVecOp_UnrollVectorOp(N);
7134 break;
7135 case ISD::IS_FPCLASS: Res = WidenVecOp_IS_FPCLASS(N); break;
7136
7137 case ISD::ANY_EXTEND:
7138 case ISD::SIGN_EXTEND:
7139 case ISD::ZERO_EXTEND:
7140 Res = WidenVecOp_EXTEND(N);
7141 break;
7142
7143 case ISD::SCMP:
7144 case ISD::UCMP:
7145 Res = WidenVecOp_CMP(N);
7146 break;
7147
7148 case ISD::FP_EXTEND:
7150 case ISD::FP_ROUND:
7152 case ISD::FP_TO_SINT:
7154 case ISD::FP_TO_UINT:
7156 case ISD::SINT_TO_FP:
7158 case ISD::UINT_TO_FP:
7160 case ISD::TRUNCATE:
7161 Res = WidenVecOp_Convert(N);
7162 break;
7163
7166 Res = WidenVecOp_FP_TO_XINT_SAT(N);
7167 break;
7168
7171 case ISD::VECREDUCE_ADD:
7172 case ISD::VECREDUCE_MUL:
7173 case ISD::VECREDUCE_AND:
7174 case ISD::VECREDUCE_OR:
7175 case ISD::VECREDUCE_XOR:
7184 Res = WidenVecOp_VECREDUCE(N);
7185 break;
7188 Res = WidenVecOp_VECREDUCE_SEQ(N);
7189 break;
7190 case ISD::VP_REDUCE_FADD:
7191 case ISD::VP_REDUCE_SEQ_FADD:
7192 case ISD::VP_REDUCE_FMUL:
7193 case ISD::VP_REDUCE_SEQ_FMUL:
7194 case ISD::VP_REDUCE_ADD:
7195 case ISD::VP_REDUCE_MUL:
7196 case ISD::VP_REDUCE_AND:
7197 case ISD::VP_REDUCE_OR:
7198 case ISD::VP_REDUCE_XOR:
7199 case ISD::VP_REDUCE_SMAX:
7200 case ISD::VP_REDUCE_SMIN:
7201 case ISD::VP_REDUCE_UMAX:
7202 case ISD::VP_REDUCE_UMIN:
7203 case ISD::VP_REDUCE_FMAX:
7204 case ISD::VP_REDUCE_FMIN:
7205 case ISD::VP_REDUCE_FMAXIMUM:
7206 case ISD::VP_REDUCE_FMINIMUM:
7207 Res = WidenVecOp_VP_REDUCE(N);
7208 break;
7209 case ISD::VP_CTTZ_ELTS:
7210 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
7211 Res = WidenVecOp_VP_CttzElements(N);
7212 break;
7213 }
7214
7215 // If Res is null, the sub-method took care of registering the result.
7216 if (!Res.getNode()) return false;
7217
7218 // If the result is N, the sub-method updated N in place. Tell the legalizer
7219 // core about this.
7220 if (Res.getNode() == N)
7221 return true;
7222
7223
7224 if (N->isStrictFPOpcode())
7225 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
7226 "Invalid operand expansion");
7227 else
7228 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
7229 "Invalid operand expansion");
7230
7231 ReplaceValueWith(SDValue(N, 0), Res);
7232 return false;
7233}
7234
7235SDValue DAGTypeLegalizer::WidenVecOp_EXTEND(SDNode *N) {
7236 SDLoc DL(N);
7237 EVT VT = N->getValueType(0);
7238
7239 SDValue InOp = N->getOperand(0);
7240 assert(getTypeAction(InOp.getValueType()) ==
7242 "Unexpected type action");
7243 InOp = GetWidenedVector(InOp);
7246 "Input wasn't widened!");
7247
7248 // We may need to further widen the operand until it has the same total
7249 // vector size as the result.
7250 EVT InVT = InOp.getValueType();
7251 if (InVT.getSizeInBits() != VT.getSizeInBits()) {
7252 EVT InEltVT = InVT.getVectorElementType();
7253 for (EVT FixedVT : MVT::vector_valuetypes()) {
7254 EVT FixedEltVT = FixedVT.getVectorElementType();
7255 if (TLI.isTypeLegal(FixedVT) &&
7256 FixedVT.getSizeInBits() == VT.getSizeInBits() &&
7257 FixedEltVT == InEltVT) {
7258 assert(FixedVT.getVectorNumElements() >= VT.getVectorNumElements() &&
7259 "Not enough elements in the fixed type for the operand!");
7260 assert(FixedVT.getVectorNumElements() != InVT.getVectorNumElements() &&
7261 "We can't have the same type as we started with!");
7262 if (FixedVT.getVectorNumElements() > InVT.getVectorNumElements())
7263 InOp = DAG.getInsertSubvector(DL, DAG.getUNDEF(FixedVT), InOp, 0);
7264 else
7265 InOp = DAG.getExtractSubvector(DL, FixedVT, InOp, 0);
7266 break;
7267 }
7268 }
7269 InVT = InOp.getValueType();
7270 if (InVT.getSizeInBits() != VT.getSizeInBits())
7271 // We couldn't find a legal vector type that was a widening of the input
7272 // and could be extended in-register to the result type, so we have to
7273 // scalarize.
7274 return WidenVecOp_Convert(N);
7275 }
7276
7277 // Use special DAG nodes to represent the operation of extending the
7278 // low lanes.
7279 switch (N->getOpcode()) {
7280 default:
7281 llvm_unreachable("Extend legalization on extend operation!");
7282 case ISD::ANY_EXTEND:
7283 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, VT, InOp);
7284 case ISD::SIGN_EXTEND:
7285 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, VT, InOp);
7286 case ISD::ZERO_EXTEND:
7287 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, VT, InOp);
7288 }
7289}
7290
7291SDValue DAGTypeLegalizer::WidenVecOp_CMP(SDNode *N) {
7292 SDLoc dl(N);
7293
7294 EVT OpVT = N->getOperand(0).getValueType();
7295 EVT ResVT = N->getValueType(0);
7296 SDValue LHS = GetWidenedVector(N->getOperand(0));
7297 SDValue RHS = GetWidenedVector(N->getOperand(1));
7298
7299 // 1. EXTRACT_SUBVECTOR
7300 // 2. SIGN_EXTEND/ZERO_EXTEND
7301 // 3. CMP
7302 LHS = DAG.getExtractSubvector(dl, OpVT, LHS, 0);
7303 RHS = DAG.getExtractSubvector(dl, OpVT, RHS, 0);
7304
7305 // At this point the result type is guaranteed to be valid, so we can use it
7306 // as the operand type by extending it appropriately
7307 ISD::NodeType ExtendOpcode =
7308 N->getOpcode() == ISD::SCMP ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
7309 LHS = DAG.getNode(ExtendOpcode, dl, ResVT, LHS);
7310 RHS = DAG.getNode(ExtendOpcode, dl, ResVT, RHS);
7311
7312 return DAG.getNode(N->getOpcode(), dl, ResVT, LHS, RHS);
7313}
7314
7315SDValue DAGTypeLegalizer::WidenVecOp_UnrollVectorOp(SDNode *N) {
7316 // The result (and first input) is legal, but the second input is illegal.
7317 // We can't do much to fix that, so just unroll and let the extracts off of
7318 // the second input be widened as needed later.
7319 return DAG.UnrollVectorOp(N);
7320}
7321
7322SDValue DAGTypeLegalizer::WidenVecOp_IS_FPCLASS(SDNode *N) {
7323 SDLoc DL(N);
7324 EVT ResultVT = N->getValueType(0);
7325 SDValue Test = N->getOperand(1);
7326 SDValue WideArg = GetWidenedVector(N->getOperand(0));
7327
7328 // Process this node similarly to SETCC.
7329 EVT WideResultVT = getSetCCResultType(WideArg.getValueType());
7330 if (ResultVT.getScalarType() == MVT::i1)
7331 WideResultVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
7332 WideResultVT.getVectorNumElements());
7333
7334 SDValue WideNode = DAG.getNode(ISD::IS_FPCLASS, DL, WideResultVT,
7335 {WideArg, Test}, N->getFlags());
7336
7337 // Extract the needed results from the result vector.
7338 EVT ResVT =
7339 EVT::getVectorVT(*DAG.getContext(), WideResultVT.getVectorElementType(),
7340 ResultVT.getVectorNumElements());
7341 SDValue CC = DAG.getExtractSubvector(DL, ResVT, WideNode, 0);
7342
7343 EVT OpVT = N->getOperand(0).getValueType();
7344 ISD::NodeType ExtendCode =
7345 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
7346 return DAG.getNode(ExtendCode, DL, ResultVT, CC);
7347}
7348
7349SDValue DAGTypeLegalizer::WidenVecOp_Convert(SDNode *N) {
7350 // Since the result is legal and the input is illegal.
7351 EVT VT = N->getValueType(0);
7352 EVT EltVT = VT.getVectorElementType();
7353 SDLoc dl(N);
7354 SDValue InOp = N->getOperand(N->isStrictFPOpcode() ? 1 : 0);
7355 assert(getTypeAction(InOp.getValueType()) ==
7357 "Unexpected type action");
7358 InOp = GetWidenedVector(InOp);
7359 EVT InVT = InOp.getValueType();
7360 unsigned Opcode = N->getOpcode();
7361
7362 // See if a widened result type would be legal, if so widen the node.
7363 // FIXME: This isn't safe for StrictFP. Other optimization here is needed.
7364 EVT WideVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
7365 InVT.getVectorElementCount());
7366 if (TLI.isTypeLegal(WideVT) && !N->isStrictFPOpcode()) {
7367 SDValue Res;
7368 if (N->isStrictFPOpcode()) {
7369 if (Opcode == ISD::STRICT_FP_ROUND)
7370 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
7371 { N->getOperand(0), InOp, N->getOperand(2) });
7372 else
7373 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
7374 { N->getOperand(0), InOp });
7375 // Legalize the chain result - switch anything that used the old chain to
7376 // use the new one.
7377 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7378 } else {
7379 if (Opcode == ISD::FP_ROUND)
7380 Res = DAG.getNode(Opcode, dl, WideVT, InOp, N->getOperand(1));
7381 else
7382 Res = DAG.getNode(Opcode, dl, WideVT, InOp);
7383 }
7384 return DAG.getExtractSubvector(dl, VT, Res, 0);
7385 }
7386
7387 EVT InEltVT = InVT.getVectorElementType();
7388
7389 // Unroll the convert into some scalar code and create a nasty build vector.
7390 unsigned NumElts = VT.getVectorNumElements();
7392 if (N->isStrictFPOpcode()) {
7393 SmallVector<SDValue, 4> NewOps(N->ops());
7394 SmallVector<SDValue, 32> OpChains;
7395 for (unsigned i=0; i < NumElts; ++i) {
7396 NewOps[1] = DAG.getExtractVectorElt(dl, InEltVT, InOp, i);
7397 Ops[i] = DAG.getNode(Opcode, dl, { EltVT, MVT::Other }, NewOps);
7398 OpChains.push_back(Ops[i].getValue(1));
7399 }
7400 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OpChains);
7401 ReplaceValueWith(SDValue(N, 1), NewChain);
7402 } else {
7403 for (unsigned i = 0; i < NumElts; ++i)
7404 Ops[i] = DAG.getNode(Opcode, dl, EltVT,
7405 DAG.getExtractVectorElt(dl, InEltVT, InOp, i));
7406 }
7407
7408 return DAG.getBuildVector(VT, dl, Ops);
7409}
7410
7411SDValue DAGTypeLegalizer::WidenVecOp_FP_TO_XINT_SAT(SDNode *N) {
7412 EVT DstVT = N->getValueType(0);
7413 SDValue Src = GetWidenedVector(N->getOperand(0));
7414 EVT SrcVT = Src.getValueType();
7415 ElementCount WideNumElts = SrcVT.getVectorElementCount();
7416 SDLoc dl(N);
7417
7418 // See if a widened result type would be legal, if so widen the node.
7419 EVT WideDstVT = EVT::getVectorVT(*DAG.getContext(),
7420 DstVT.getVectorElementType(), WideNumElts);
7421 if (TLI.isTypeLegal(WideDstVT)) {
7422 SDValue Res =
7423 DAG.getNode(N->getOpcode(), dl, WideDstVT, Src, N->getOperand(1));
7424 return DAG.getNode(
7425 ISD::EXTRACT_SUBVECTOR, dl, DstVT, Res,
7426 DAG.getConstant(0, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
7427 }
7428
7429 // Give up and unroll.
7430 return DAG.UnrollVectorOp(N);
7431}
7432
7433SDValue DAGTypeLegalizer::WidenVecOp_BITCAST(SDNode *N) {
7434 EVT VT = N->getValueType(0);
7435 SDValue InOp = GetWidenedVector(N->getOperand(0));
7436 EVT InWidenVT = InOp.getValueType();
7437 SDLoc dl(N);
7438
7439 // Check if we can convert between two legal vector types and extract.
7440 TypeSize InWidenSize = InWidenVT.getSizeInBits();
7441 TypeSize Size = VT.getSizeInBits();
7442 // x86mmx is not an acceptable vector element type, so don't try.
7443 if (!VT.isVector() && VT != MVT::x86mmx &&
7444 InWidenSize.hasKnownScalarFactor(Size)) {
7445 unsigned NewNumElts = InWidenSize.getKnownScalarFactor(Size);
7446 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), VT, NewNumElts);
7447 if (TLI.isTypeLegal(NewVT)) {
7448 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
7449 return DAG.getExtractVectorElt(dl, VT, BitOp, 0);
7450 }
7451 }
7452
7453 // Handle a case like bitcast v12i8 -> v3i32. Normally that would get widened
7454 // to v16i8 -> v4i32, but for a target where v3i32 is legal but v12i8 is not,
7455 // we end up here. Handling the case here with EXTRACT_SUBVECTOR avoids
7456 // having to copy via memory.
7457 if (VT.isVector()) {
7458 EVT EltVT = VT.getVectorElementType();
7459 unsigned EltSize = EltVT.getFixedSizeInBits();
7460 if (InWidenSize.isKnownMultipleOf(EltSize)) {
7461 ElementCount NewNumElts =
7462 (InWidenVT.getVectorElementCount() * InWidenVT.getScalarSizeInBits())
7463 .divideCoefficientBy(EltSize);
7464 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NewNumElts);
7465 if (TLI.isTypeLegal(NewVT)) {
7466 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
7467 return DAG.getExtractSubvector(dl, VT, BitOp, 0);
7468 }
7469 }
7470 }
7471
7472 return CreateStackStoreLoad(InOp, VT);
7473}
7474
7475// Vectors with sizes that are not powers of 2 need to be widened to the
7476// next largest power of 2. For example, we may get a vector of 3 32-bit
7477// integers or of 6 16-bit integers, both of which have to be widened to a
7478// 128-bit vector.
7479SDValue DAGTypeLegalizer::WidenVecOp_FAKE_USE(SDNode *N) {
7480 SDValue WidenedOp = GetWidenedVector(N->getOperand(1));
7481 return DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, N->getOperand(0),
7482 WidenedOp);
7483}
7484
7485SDValue DAGTypeLegalizer::WidenVecOp_CONCAT_VECTORS(SDNode *N) {
7486 EVT VT = N->getValueType(0);
7487 EVT EltVT = VT.getVectorElementType();
7488 EVT InVT = N->getOperand(0).getValueType();
7489 SDLoc dl(N);
7490
7491 // If the widen width for this operand is the same as the width of the concat
7492 // and all but the first operand is undef, just use the widened operand.
7493 unsigned NumOperands = N->getNumOperands();
7494 if (VT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
7495 unsigned i;
7496 for (i = 1; i < NumOperands; ++i)
7497 if (!N->getOperand(i).isUndef())
7498 break;
7499
7500 if (i == NumOperands)
7501 return GetWidenedVector(N->getOperand(0));
7502 }
7503
7504 // Otherwise, fall back to a nasty build vector.
7505 unsigned NumElts = VT.getVectorNumElements();
7507
7508 unsigned NumInElts = InVT.getVectorNumElements();
7509
7510 unsigned Idx = 0;
7511 for (unsigned i=0; i < NumOperands; ++i) {
7512 SDValue InOp = N->getOperand(i);
7513 assert(getTypeAction(InOp.getValueType()) ==
7515 "Unexpected type action");
7516 InOp = GetWidenedVector(InOp);
7517 for (unsigned j = 0; j < NumInElts; ++j)
7518 Ops[Idx++] = DAG.getExtractVectorElt(dl, EltVT, InOp, j);
7519 }
7520 return DAG.getBuildVector(VT, dl, Ops);
7521}
7522
7523SDValue DAGTypeLegalizer::WidenVecOp_INSERT_SUBVECTOR(SDNode *N) {
7524 EVT VT = N->getValueType(0);
7525 SDValue SubVec = N->getOperand(1);
7526 SDValue InVec = N->getOperand(0);
7527
7528 EVT OrigVT = SubVec.getValueType();
7529 SubVec = GetWidenedVector(SubVec);
7530 EVT SubVT = SubVec.getValueType();
7531
7532 // Whether or not all the elements of the widened SubVec will be inserted into
7533 // valid indices of VT.
7534 bool IndicesValid = false;
7535 // If we statically know that VT can fit SubVT, the indices are valid.
7536 if (VT.knownBitsGE(SubVT))
7537 IndicesValid = true;
7538 else if (VT.isScalableVector() && SubVT.isFixedLengthVector()) {
7539 // Otherwise, if we're inserting a fixed vector into a scalable vector and
7540 // we know the minimum vscale we can work out if it's valid ourselves.
7541 Attribute Attr = DAG.getMachineFunction().getFunction().getFnAttribute(
7542 Attribute::VScaleRange);
7543 if (Attr.isValid()) {
7544 unsigned VScaleMin = Attr.getVScaleRangeMin();
7545 if (VT.getSizeInBits().getKnownMinValue() * VScaleMin >=
7546 SubVT.getFixedSizeInBits())
7547 IndicesValid = true;
7548 }
7549 }
7550
7551 if (!IndicesValid)
7553 "Don't know how to widen the operands for INSERT_SUBVECTOR");
7554
7555 SDLoc DL(N);
7556
7557 // We need to make sure that the indices are still valid, otherwise we might
7558 // widen what was previously well-defined to something undefined.
7559 if (InVec.isUndef() && N->getConstantOperandVal(2) == 0)
7560 return DAG.getNode(ISD::INSERT_SUBVECTOR, DL, VT, InVec, SubVec,
7561 N->getOperand(2));
7562
7563 if (OrigVT.isScalableVector()) {
7564 // When the widened types match, overwriting the start of a vector is
7565 // effectively a merge operation that can be implement as a vselect.
7566 if (SubVT == VT && N->getConstantOperandVal(2) == 0) {
7567 SDValue Mask =
7568 DAG.getMaskFromElementCount(DL, VT, OrigVT.getVectorElementCount());
7569 return DAG.getNode(ISD::VSELECT, DL, VT, Mask, SubVec, InVec);
7570 }
7571
7572 // Fallback to inserting through memory.
7573 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
7574 SDValue StackPtr = DAG.CreateStackTemporary(VT.getStoreSize(), Alignment);
7575 MachineFunction &MF = DAG.getMachineFunction();
7576 int FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
7577 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
7578
7579 MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
7582 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
7585
7586 // Write out the vector being inserting into.
7587 SDValue Ch =
7588 DAG.getStore(DAG.getEntryNode(), DL, InVec, StackPtr, StoreMMO);
7589
7590 // Build a mask to match the length of the sub-vector.
7591 SDValue Mask =
7592 DAG.getMaskFromElementCount(DL, SubVT, OrigVT.getVectorElementCount());
7593
7594 // Overwrite the sub-vector at the required offset.
7595 SDValue SubVecPtr =
7596 TLI.getVectorSubVecPointer(DAG, StackPtr, VT, OrigVT, N->getOperand(2));
7597 Ch = DAG.getMaskedStore(Ch, DL, SubVec, SubVecPtr,
7598 DAG.getUNDEF(SubVecPtr.getValueType()), Mask, VT,
7599 StoreMMO, ISD::UNINDEXED, ISD::NON_EXTLOAD);
7600
7601 // Read back the result.
7602 return DAG.getLoad(VT, DL, Ch, StackPtr, LoadMMO);
7603 }
7604
7605 // If the operands can't be widened legally, just replace the INSERT_SUBVECTOR
7606 // with a series of INSERT_VECTOR_ELT
7607 unsigned Idx = N->getConstantOperandVal(2);
7608
7609 SDValue InsertElt = InVec;
7610 for (unsigned I = 0, E = OrigVT.getVectorNumElements(); I != E; ++I) {
7611 SDValue ExtractElt =
7612 DAG.getExtractVectorElt(DL, VT.getVectorElementType(), SubVec, I);
7613 InsertElt = DAG.getInsertVectorElt(DL, InsertElt, ExtractElt, I + Idx);
7614 }
7615
7616 return InsertElt;
7617}
7618
7619SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
7620 SDValue InOp = GetWidenedVector(N->getOperand(0));
7621 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SDLoc(N),
7622 N->getValueType(0), InOp, N->getOperand(1));
7623}
7624
7625SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
7626 SDValue InOp = GetWidenedVector(N->getOperand(0));
7627 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
7628 N->getValueType(0), InOp, N->getOperand(1));
7629}
7630
7631SDValue DAGTypeLegalizer::WidenVecOp_EXTEND_VECTOR_INREG(SDNode *N) {
7632 SDValue InOp = GetWidenedVector(N->getOperand(0));
7633 return DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0), InOp);
7634}
7635
7636SDValue DAGTypeLegalizer::WidenVecOp_STORE(SDNode *N) {
7637 // We have to widen the value, but we want only to store the original
7638 // vector type.
7639 StoreSDNode *ST = cast<StoreSDNode>(N);
7640
7641 if (!ST->getMemoryVT().getScalarType().isByteSized())
7642 return TLI.scalarizeVectorStore(ST, DAG);
7643
7644 if (ST->isTruncatingStore())
7645 return TLI.scalarizeVectorStore(ST, DAG);
7646
7647 // Generate a vector-predicated store if it is custom/legal on the target.
7648 // To avoid possible recursion, only do this if the widened mask type is
7649 // legal.
7650 // FIXME: Not all targets may support EVL in VP_STORE. These will have been
7651 // removed from the IR by the ExpandVectorPredication pass but we're
7652 // reintroducing them here.
7653 SDValue StVal = ST->getValue();
7654 EVT StVT = StVal.getValueType();
7655 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), StVT);
7656 EVT WideMaskVT = getSetCCResultType(WideVT);
7657
7658 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
7659 TLI.isTypeLegal(WideMaskVT)) {
7660 // Widen the value.
7661 SDLoc DL(N);
7662 StVal = GetWidenedVector(StVal);
7663 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
7664 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
7665 StVT.getVectorElementCount());
7666 return DAG.getStoreVP(ST->getChain(), DL, StVal, ST->getBasePtr(),
7667 ST->getOffset(), Mask, EVL, StVT, ST->getMemOperand(),
7668 ST->getAddressingMode());
7669 }
7670
7672 if (GenWidenVectorStores(StChain, ST)) {
7673 if (StChain.size() == 1)
7674 return StChain[0];
7675
7676 return DAG.getNode(ISD::TokenFactor, SDLoc(ST), MVT::Other, StChain);
7677 }
7678
7679 if (StVT.isVector()) {
7680 // If all else fails replace the store with a wide masked store.
7681 SDLoc DL(N);
7682 SDValue WideStVal = GetWidenedVector(StVal);
7683 SDValue Mask =
7684 DAG.getMaskFromElementCount(DL, WideVT, StVT.getVectorElementCount());
7685
7686 return DAG.getMaskedStore(ST->getChain(), DL, WideStVal, ST->getBasePtr(),
7687 ST->getOffset(), Mask, ST->getMemoryVT(),
7688 ST->getMemOperand(), ST->getAddressingMode(),
7689 ST->isTruncatingStore());
7690 }
7691
7692 report_fatal_error("Unable to widen vector store");
7693}
7694
7695SDValue DAGTypeLegalizer::WidenVecOp_VP_STORE(SDNode *N, unsigned OpNo) {
7696 assert((OpNo == 1 || OpNo == 3) &&
7697 "Can widen only data or mask operand of vp_store");
7698 VPStoreSDNode *ST = cast<VPStoreSDNode>(N);
7699 SDValue Mask = ST->getMask();
7700 SDValue StVal = ST->getValue();
7701 SDLoc dl(N);
7702
7703 if (OpNo == 1) {
7704 // Widen the value.
7705 StVal = GetWidenedVector(StVal);
7706
7707 // We only handle the case where the mask needs widening to an
7708 // identically-sized type as the vector inputs.
7709 assert(getTypeAction(Mask.getValueType()) ==
7711 "Unable to widen VP store");
7712 Mask = GetWidenedVector(Mask);
7713 } else {
7714 Mask = GetWidenedVector(Mask);
7715
7716 // We only handle the case where the stored value needs widening to an
7717 // identically-sized type as the mask.
7718 assert(getTypeAction(StVal.getValueType()) ==
7720 "Unable to widen VP store");
7721 StVal = GetWidenedVector(StVal);
7722 }
7723
7724 assert(Mask.getValueType().getVectorElementCount() ==
7726 "Mask and data vectors should have the same number of elements");
7727 return DAG.getStoreVP(ST->getChain(), dl, StVal, ST->getBasePtr(),
7728 ST->getOffset(), Mask, ST->getVectorLength(),
7729 ST->getMemoryVT(), ST->getMemOperand(),
7730 ST->getAddressingMode(), ST->isTruncatingStore(),
7731 ST->isCompressingStore());
7732}
7733
7734SDValue DAGTypeLegalizer::WidenVecOp_VP_STRIDED_STORE(SDNode *N,
7735 unsigned OpNo) {
7736 assert((OpNo == 1 || OpNo == 4) &&
7737 "Can widen only data or mask operand of vp_strided_store");
7738 VPStridedStoreSDNode *SST = cast<VPStridedStoreSDNode>(N);
7739 SDValue Mask = SST->getMask();
7740 SDValue StVal = SST->getValue();
7741 SDLoc DL(N);
7742
7743 if (OpNo == 1)
7744 assert(getTypeAction(Mask.getValueType()) ==
7746 "Unable to widen VP strided store");
7747 else
7748 assert(getTypeAction(StVal.getValueType()) ==
7750 "Unable to widen VP strided store");
7751
7752 StVal = GetWidenedVector(StVal);
7753 Mask = GetWidenedVector(Mask);
7754
7756 Mask.getValueType().getVectorElementCount() &&
7757 "Data and mask vectors should have the same number of elements");
7758
7759 return DAG.getStridedStoreVP(
7760 SST->getChain(), DL, StVal, SST->getBasePtr(), SST->getOffset(),
7761 SST->getStride(), Mask, SST->getVectorLength(), SST->getMemoryVT(),
7762 SST->getMemOperand(), SST->getAddressingMode(), SST->isTruncatingStore(),
7763 SST->isCompressingStore());
7764}
7765
7766SDValue DAGTypeLegalizer::WidenVecOp_MSTORE(SDNode *N, unsigned OpNo) {
7767 assert((OpNo == 1 || OpNo == 4) &&
7768 "Can widen only data or mask operand of mstore");
7769 MaskedStoreSDNode *MST = cast<MaskedStoreSDNode>(N);
7770 SDValue Mask = MST->getMask();
7771 EVT MaskVT = Mask.getValueType();
7772 SDValue StVal = MST->getValue();
7773 EVT VT = StVal.getValueType();
7774 SDLoc dl(N);
7775
7776 EVT WideVT, WideMaskVT;
7777 if (OpNo == 1) {
7778 // Widen the value.
7779 StVal = GetWidenedVector(StVal);
7780
7781 WideVT = StVal.getValueType();
7782 WideMaskVT =
7783 EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(),
7784 WideVT.getVectorElementCount());
7785 } else {
7786 WideMaskVT = TLI.getTypeToTransformTo(*DAG.getContext(), MaskVT);
7787
7788 EVT ValueVT = StVal.getValueType();
7789 WideVT = EVT::getVectorVT(*DAG.getContext(), ValueVT.getVectorElementType(),
7790 WideMaskVT.getVectorElementCount());
7791 }
7792
7793 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
7794 TLI.isTypeLegal(WideMaskVT)) {
7795 Mask = DAG.getInsertSubvector(dl, DAG.getUNDEF(WideMaskVT), Mask, 0);
7796 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
7798 return DAG.getStoreVP(MST->getChain(), dl, StVal, MST->getBasePtr(),
7799 MST->getOffset(), Mask, EVL, MST->getMemoryVT(),
7800 MST->getMemOperand(), MST->getAddressingMode());
7801 }
7802
7803 if (OpNo == 1) {
7804 // The mask should be widened as well.
7805 Mask = ModifyToType(Mask, WideMaskVT, true);
7806 } else {
7807 // Widen the mask.
7808 Mask = ModifyToType(Mask, WideMaskVT, true);
7809
7810 StVal = ModifyToType(StVal, WideVT);
7811 }
7812
7813 assert(Mask.getValueType().getVectorElementCount() ==
7815 "Mask and data vectors should have the same number of elements");
7816 return DAG.getMaskedStore(MST->getChain(), dl, StVal, MST->getBasePtr(),
7817 MST->getOffset(), Mask, MST->getMemoryVT(),
7818 MST->getMemOperand(), MST->getAddressingMode(),
7819 false, MST->isCompressingStore());
7820}
7821
7822SDValue DAGTypeLegalizer::WidenVecOp_MGATHER(SDNode *N, unsigned OpNo) {
7823 assert(OpNo == 4 && "Can widen only the index of mgather");
7824 auto *MG = cast<MaskedGatherSDNode>(N);
7825 SDValue DataOp = MG->getPassThru();
7826 SDValue Mask = MG->getMask();
7827 SDValue Scale = MG->getScale();
7828
7829 // Just widen the index. It's allowed to have extra elements.
7830 SDValue Index = GetWidenedVector(MG->getIndex());
7831
7832 SDLoc dl(N);
7833 SDValue Ops[] = {MG->getChain(), DataOp, Mask, MG->getBasePtr(), Index,
7834 Scale};
7835 SDValue Res = DAG.getMaskedGather(MG->getVTList(), MG->getMemoryVT(), dl, Ops,
7836 MG->getMemOperand(), MG->getIndexType(),
7837 MG->getExtensionType());
7838 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7839 ReplaceValueWith(SDValue(N, 0), Res.getValue(0));
7840 return SDValue();
7841}
7842
7843SDValue DAGTypeLegalizer::WidenVecOp_MSCATTER(SDNode *N, unsigned OpNo) {
7844 MaskedScatterSDNode *MSC = cast<MaskedScatterSDNode>(N);
7845 SDValue DataOp = MSC->getValue();
7846 SDValue Mask = MSC->getMask();
7847 SDValue Index = MSC->getIndex();
7848 SDValue Scale = MSC->getScale();
7849 EVT WideMemVT = MSC->getMemoryVT();
7850
7851 if (OpNo == 1) {
7852 DataOp = GetWidenedVector(DataOp);
7853 unsigned NumElts = DataOp.getValueType().getVectorNumElements();
7854
7855 // Widen index.
7856 EVT IndexVT = Index.getValueType();
7857 EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
7858 IndexVT.getVectorElementType(), NumElts);
7859 Index = ModifyToType(Index, WideIndexVT);
7860
7861 // The mask should be widened as well.
7862 EVT MaskVT = Mask.getValueType();
7863 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
7864 MaskVT.getVectorElementType(), NumElts);
7865 Mask = ModifyToType(Mask, WideMaskVT, true);
7866
7867 // Widen the MemoryType
7868 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
7869 MSC->getMemoryVT().getScalarType(), NumElts);
7870 } else if (OpNo == 4) {
7871 // Just widen the index. It's allowed to have extra elements.
7872 Index = GetWidenedVector(Index);
7873 } else
7874 llvm_unreachable("Can't widen this operand of mscatter");
7875
7876 SDValue Ops[] = {MSC->getChain(), DataOp, Mask, MSC->getBasePtr(), Index,
7877 Scale};
7878 return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N),
7879 Ops, MSC->getMemOperand(), MSC->getIndexType(),
7880 MSC->isTruncatingStore());
7881}
7882
7883SDValue DAGTypeLegalizer::WidenVecOp_VP_SCATTER(SDNode *N, unsigned OpNo) {
7884 VPScatterSDNode *VPSC = cast<VPScatterSDNode>(N);
7885 SDValue DataOp = VPSC->getValue();
7886 SDValue Mask = VPSC->getMask();
7887 SDValue Index = VPSC->getIndex();
7888 SDValue Scale = VPSC->getScale();
7889 EVT WideMemVT = VPSC->getMemoryVT();
7890
7891 if (OpNo == 1) {
7892 DataOp = GetWidenedVector(DataOp);
7893 Index = GetWidenedVector(Index);
7894 const auto WideEC = DataOp.getValueType().getVectorElementCount();
7895 Mask = GetWidenedMask(Mask, WideEC);
7896 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
7897 VPSC->getMemoryVT().getScalarType(), WideEC);
7898 } else if (OpNo == 3) {
7899 // Just widen the index. It's allowed to have extra elements.
7900 Index = GetWidenedVector(Index);
7901 } else
7902 llvm_unreachable("Can't widen this operand of VP_SCATTER");
7903
7904 SDValue Ops[] = {
7905 VPSC->getChain(), DataOp, VPSC->getBasePtr(), Index, Scale, Mask,
7906 VPSC->getVectorLength()};
7907 return DAG.getScatterVP(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N), Ops,
7908 VPSC->getMemOperand(), VPSC->getIndexType());
7909}
7910
7911SDValue DAGTypeLegalizer::WidenVecOp_SETCC(SDNode *N) {
7912 SDValue InOp0 = GetWidenedVector(N->getOperand(0));
7913 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
7914 SDLoc dl(N);
7915 EVT VT = N->getValueType(0);
7916
7917 // WARNING: In this code we widen the compare instruction with garbage.
7918 // This garbage may contain denormal floats which may be slow. Is this a real
7919 // concern ? Should we zero the unused lanes if this is a float compare ?
7920
7921 // Get a new SETCC node to compare the newly widened operands.
7922 // Only some of the compared elements are legal.
7923 EVT SVT = getSetCCResultType(InOp0.getValueType());
7924 // The result type is legal, if its vXi1, keep vXi1 for the new SETCC.
7925 if (VT.getScalarType() == MVT::i1)
7926 SVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
7927 SVT.getVectorElementCount());
7928
7929 SDValue WideSETCC = DAG.getNode(ISD::SETCC, SDLoc(N),
7930 SVT, InOp0, InOp1, N->getOperand(2));
7931
7932 // Extract the needed results from the result vector.
7933 EVT ResVT = EVT::getVectorVT(*DAG.getContext(),
7936 SDValue CC = DAG.getExtractSubvector(dl, ResVT, WideSETCC, 0);
7937
7938 EVT OpVT = N->getOperand(0).getValueType();
7939 ISD::NodeType ExtendCode =
7940 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
7941 return DAG.getNode(ExtendCode, dl, VT, CC);
7942}
7943
7944SDValue DAGTypeLegalizer::WidenVecOp_STRICT_FSETCC(SDNode *N) {
7945 SDValue Chain = N->getOperand(0);
7946 SDValue LHS = GetWidenedVector(N->getOperand(1));
7947 SDValue RHS = GetWidenedVector(N->getOperand(2));
7948 SDValue CC = N->getOperand(3);
7949 SDLoc dl(N);
7950
7951 EVT VT = N->getValueType(0);
7952 EVT EltVT = VT.getVectorElementType();
7953 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
7954 unsigned NumElts = VT.getVectorNumElements();
7955
7956 // Unroll into a build vector.
7957 SmallVector<SDValue, 8> Scalars(NumElts);
7958 SmallVector<SDValue, 8> Chains(NumElts);
7959
7960 for (unsigned i = 0; i != NumElts; ++i) {
7961 SDValue LHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, LHS, i);
7962 SDValue RHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, RHS, i);
7963
7964 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
7965 {Chain, LHSElem, RHSElem, CC});
7966 Chains[i] = Scalars[i].getValue(1);
7967 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
7968 DAG.getBoolConstant(true, dl, EltVT, VT),
7969 DAG.getBoolConstant(false, dl, EltVT, VT));
7970 }
7971
7972 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
7973 ReplaceValueWith(SDValue(N, 1), NewChain);
7974
7975 return DAG.getBuildVector(VT, dl, Scalars);
7976}
7977
7978static unsigned getExtendForIntVecReduction(unsigned Opc) {
7979 switch (Opc) {
7980 default:
7981 llvm_unreachable("Expected integer vector reduction");
7982 case ISD::VECREDUCE_ADD:
7983 case ISD::VECREDUCE_MUL:
7984 case ISD::VECREDUCE_AND:
7985 case ISD::VECREDUCE_OR:
7986 case ISD::VECREDUCE_XOR:
7987 return ISD::ANY_EXTEND;
7990 return ISD::SIGN_EXTEND;
7993 return ISD::ZERO_EXTEND;
7994 }
7995}
7996
7997SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE(SDNode *N) {
7998 SDLoc dl(N);
7999 SDValue Op = GetWidenedVector(N->getOperand(0));
8000 EVT VT = N->getValueType(0);
8001 EVT OrigVT = N->getOperand(0).getValueType();
8002 EVT WideVT = Op.getValueType();
8003 EVT ElemVT = OrigVT.getVectorElementType();
8004 SDNodeFlags Flags = N->getFlags();
8005
8006 unsigned Opc = N->getOpcode();
8007 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
8008 SDValue NeutralElem = DAG.getNeutralElement(BaseOpc, dl, ElemVT, Flags);
8009 assert(NeutralElem && "Neutral element must exist");
8010
8011 // Pad the vector with the neutral element.
8012 unsigned OrigElts = OrigVT.getVectorMinNumElements();
8013 unsigned WideElts = WideVT.getVectorMinNumElements();
8014
8015 // Generate a vp.reduce_op if it is custom/legal for the target. This avoids
8016 // needing to pad the source vector, because the inactive lanes can simply be
8017 // disabled and not contribute to the result.
8018 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opc);
8019 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WideVT)) {
8020 SDValue Start = NeutralElem;
8021 if (VT.isInteger())
8022 Start = DAG.getNode(getExtendForIntVecReduction(Opc), dl, VT, Start);
8023 assert(Start.getValueType() == VT);
8024 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8025 WideVT.getVectorElementCount());
8026 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
8027 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8028 OrigVT.getVectorElementCount());
8029 return DAG.getNode(*VPOpcode, dl, VT, {Start, Op, Mask, EVL}, Flags);
8030 }
8031
8032 if (WideVT.isScalableVector()) {
8033 unsigned GCD = std::gcd(OrigElts, WideElts);
8034 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
8036 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
8037 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
8038 Op = DAG.getInsertSubvector(dl, Op, SplatNeutral, Idx);
8039 return DAG.getNode(Opc, dl, VT, Op, Flags);
8040 }
8041
8042 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
8043 Op = DAG.getInsertVectorElt(dl, Op, NeutralElem, Idx);
8044
8045 return DAG.getNode(Opc, dl, VT, Op, Flags);
8046}
8047
8048SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE_SEQ(SDNode *N) {
8049 SDLoc dl(N);
8050 SDValue AccOp = N->getOperand(0);
8051 SDValue VecOp = N->getOperand(1);
8052 SDValue Op = GetWidenedVector(VecOp);
8053
8054 EVT VT = N->getValueType(0);
8055 EVT OrigVT = VecOp.getValueType();
8056 EVT WideVT = Op.getValueType();
8057 EVT ElemVT = OrigVT.getVectorElementType();
8058 SDNodeFlags Flags = N->getFlags();
8059
8060 unsigned Opc = N->getOpcode();
8061 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
8062 SDValue NeutralElem = DAG.getNeutralElement(BaseOpc, dl, ElemVT, Flags);
8063
8064 // Pad the vector with the neutral element.
8065 unsigned OrigElts = OrigVT.getVectorMinNumElements();
8066 unsigned WideElts = WideVT.getVectorMinNumElements();
8067
8068 // Generate a vp.reduce_op if it is custom/legal for the target. This avoids
8069 // needing to pad the source vector, because the inactive lanes can simply be
8070 // disabled and not contribute to the result.
8071 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opc);
8072 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WideVT)) {
8073 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8074 WideVT.getVectorElementCount());
8075 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
8076 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8077 OrigVT.getVectorElementCount());
8078 return DAG.getNode(*VPOpcode, dl, VT, {AccOp, Op, Mask, EVL}, Flags);
8079 }
8080
8081 if (WideVT.isScalableVector()) {
8082 unsigned GCD = std::gcd(OrigElts, WideElts);
8083 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
8085 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
8086 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
8087 Op = DAG.getInsertSubvector(dl, Op, SplatNeutral, Idx);
8088 return DAG.getNode(Opc, dl, VT, AccOp, Op, Flags);
8089 }
8090
8091 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
8092 Op = DAG.getInsertVectorElt(dl, Op, NeutralElem, Idx);
8093
8094 return DAG.getNode(Opc, dl, VT, AccOp, Op, Flags);
8095}
8096
8097SDValue DAGTypeLegalizer::WidenVecOp_VP_REDUCE(SDNode *N) {
8098 assert(N->isVPOpcode() && "Expected VP opcode");
8099
8100 SDLoc dl(N);
8101 SDValue Op = GetWidenedVector(N->getOperand(1));
8102 SDValue Mask = GetWidenedMask(N->getOperand(2),
8103 Op.getValueType().getVectorElementCount());
8104
8105 return DAG.getNode(N->getOpcode(), dl, N->getValueType(0),
8106 {N->getOperand(0), Op, Mask, N->getOperand(3)},
8107 N->getFlags());
8108}
8109
8110SDValue DAGTypeLegalizer::WidenVecOp_VSELECT(SDNode *N) {
8111 // This only gets called in the case that the left and right inputs and
8112 // result are of a legal odd vector type, and the condition is illegal i1 of
8113 // the same odd width that needs widening.
8114 EVT VT = N->getValueType(0);
8115 assert(VT.isVector() && !VT.isPow2VectorType() && isTypeLegal(VT));
8116
8117 SDValue Cond = GetWidenedVector(N->getOperand(0));
8118 SDValue LeftIn = DAG.WidenVector(N->getOperand(1), SDLoc(N));
8119 SDValue RightIn = DAG.WidenVector(N->getOperand(2), SDLoc(N));
8120 SDLoc DL(N);
8121
8122 SDValue Select = DAG.getNode(N->getOpcode(), DL, LeftIn.getValueType(), Cond,
8123 LeftIn, RightIn);
8124 return DAG.getExtractSubvector(DL, VT, Select, 0);
8125}
8126
8127SDValue DAGTypeLegalizer::WidenVecOp_VP_CttzElements(SDNode *N) {
8128 SDLoc DL(N);
8129 SDValue Source = GetWidenedVector(N->getOperand(0));
8130 EVT SrcVT = Source.getValueType();
8131 SDValue Mask =
8132 GetWidenedMask(N->getOperand(1), SrcVT.getVectorElementCount());
8133
8134 return DAG.getNode(N->getOpcode(), DL, N->getValueType(0),
8135 {Source, Mask, N->getOperand(2)}, N->getFlags());
8136}
8137
8138//===----------------------------------------------------------------------===//
8139// Vector Widening Utilities
8140//===----------------------------------------------------------------------===//
8141
8142// Utility function to find the type to chop up a widen vector for load/store
8143// TLI: Target lowering used to determine legal types.
8144// Width: Width left need to load/store.
8145// WidenVT: The widen vector type to load to/store from
8146// Align: If 0, don't allow use of a wider type
8147// WidenEx: If Align is not 0, the amount additional we can load/store from.
8148
8149static std::optional<EVT> findMemType(SelectionDAG &DAG,
8150 const TargetLowering &TLI, unsigned Width,
8151 EVT WidenVT, unsigned Align = 0,
8152 unsigned WidenEx = 0) {
8153 EVT WidenEltVT = WidenVT.getVectorElementType();
8154 const bool Scalable = WidenVT.isScalableVector();
8155 unsigned WidenWidth = WidenVT.getSizeInBits().getKnownMinValue();
8156 unsigned WidenEltWidth = WidenEltVT.getSizeInBits();
8157 unsigned AlignInBits = Align*8;
8158
8159 EVT RetVT = WidenEltVT;
8160 // Don't bother looking for an integer type if the vector is scalable, skip
8161 // to vector types.
8162 if (!Scalable) {
8163 // If we have one element to load/store, return it.
8164 if (Width == WidenEltWidth)
8165 return RetVT;
8166
8167 // See if there is larger legal integer than the element type to load/store.
8168 for (EVT MemVT : reverse(MVT::integer_valuetypes())) {
8169 unsigned MemVTWidth = MemVT.getSizeInBits();
8170 if (MemVT.getSizeInBits() <= WidenEltWidth)
8171 break;
8172 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
8173 if ((Action == TargetLowering::TypeLegal ||
8175 (WidenWidth % MemVTWidth) == 0 &&
8176 isPowerOf2_32(WidenWidth / MemVTWidth) &&
8177 (MemVTWidth <= Width ||
8178 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
8179 if (MemVTWidth == WidenWidth)
8180 return MemVT;
8181 RetVT = MemVT;
8182 break;
8183 }
8184 }
8185 }
8186
8187 // See if there is a larger vector type to load/store that has the same vector
8188 // element type and is evenly divisible with the WidenVT.
8189 for (EVT MemVT : reverse(MVT::vector_valuetypes())) {
8190 // Skip vector MVTs which don't match the scalable property of WidenVT.
8191 if (Scalable != MemVT.isScalableVector())
8192 continue;
8193 unsigned MemVTWidth = MemVT.getSizeInBits().getKnownMinValue();
8194 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
8195 if ((Action == TargetLowering::TypeLegal ||
8197 WidenEltVT == MemVT.getVectorElementType() &&
8198 (WidenWidth % MemVTWidth) == 0 &&
8199 isPowerOf2_32(WidenWidth / MemVTWidth) &&
8200 (MemVTWidth <= Width ||
8201 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
8202 if (RetVT.getFixedSizeInBits() < MemVTWidth || MemVT == WidenVT)
8203 return MemVT;
8204 }
8205 }
8206
8207 // Using element-wise loads and stores for widening operations is not
8208 // supported for scalable vectors
8209 if (Scalable)
8210 return std::nullopt;
8211
8212 return RetVT;
8213}
8214
8215// Builds a vector type from scalar loads
8216// VecTy: Resulting Vector type
8217// LDOps: Load operators to build a vector type
8218// [Start,End) the list of loads to use.
8221 unsigned Start, unsigned End) {
8222 SDLoc dl(LdOps[Start]);
8223 EVT LdTy = LdOps[Start].getValueType();
8224 unsigned Width = VecTy.getSizeInBits();
8225 unsigned NumElts = Width / LdTy.getSizeInBits();
8226 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), LdTy, NumElts);
8227
8228 unsigned Idx = 1;
8229 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT,LdOps[Start]);
8230
8231 for (unsigned i = Start + 1; i != End; ++i) {
8232 EVT NewLdTy = LdOps[i].getValueType();
8233 if (NewLdTy != LdTy) {
8234 NumElts = Width / NewLdTy.getSizeInBits();
8235 NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewLdTy, NumElts);
8236 VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, VecOp);
8237 // Readjust position and vector position based on new load type.
8238 Idx = Idx * LdTy.getSizeInBits() / NewLdTy.getSizeInBits();
8239 LdTy = NewLdTy;
8240 }
8241 VecOp = DAG.getInsertVectorElt(dl, VecOp, LdOps[i], Idx++);
8242 }
8243 return DAG.getNode(ISD::BITCAST, dl, VecTy, VecOp);
8244}
8245
8246SDValue DAGTypeLegalizer::GenWidenVectorLoads(SmallVectorImpl<SDValue> &LdChain,
8247 LoadSDNode *LD) {
8248 // The strategy assumes that we can efficiently load power-of-two widths.
8249 // The routine chops the vector into the largest vector loads with the same
8250 // element type or scalar loads and then recombines it to the widen vector
8251 // type.
8252 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
8253 EVT LdVT = LD->getMemoryVT();
8254 SDLoc dl(LD);
8255 assert(LdVT.isVector() && WidenVT.isVector());
8256 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
8258
8259 // Load information
8260 SDValue Chain = LD->getChain();
8261 SDValue BasePtr = LD->getBasePtr();
8262 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
8263 AAMDNodes AAInfo = LD->getAAInfo();
8264
8265 TypeSize LdWidth = LdVT.getSizeInBits();
8266 TypeSize WidenWidth = WidenVT.getSizeInBits();
8267 TypeSize WidthDiff = WidenWidth - LdWidth;
8268 // Allow wider loads if they are sufficiently aligned to avoid memory faults
8269 // and if the original load is simple.
8270 unsigned LdAlign =
8271 (!LD->isSimple() || LdVT.isScalableVector()) ? 0 : LD->getAlign().value();
8272
8273 // Find the vector type that can load from.
8274 std::optional<EVT> FirstVT =
8275 findMemType(DAG, TLI, LdWidth.getKnownMinValue(), WidenVT, LdAlign,
8276 WidthDiff.getKnownMinValue());
8277
8278 if (!FirstVT)
8279 return SDValue();
8280
8281 SmallVector<EVT, 8> MemVTs;
8282 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
8283
8284 // Unless we're able to load in one instruction we must work out how to load
8285 // the remainder.
8286 if (!TypeSize::isKnownLE(LdWidth, FirstVTWidth)) {
8287 std::optional<EVT> NewVT = FirstVT;
8288 TypeSize RemainingWidth = LdWidth;
8289 TypeSize NewVTWidth = FirstVTWidth;
8290 do {
8291 RemainingWidth -= NewVTWidth;
8292 if (TypeSize::isKnownLT(RemainingWidth, NewVTWidth)) {
8293 // The current type we are using is too large. Find a better size.
8294 NewVT = findMemType(DAG, TLI, RemainingWidth.getKnownMinValue(),
8295 WidenVT, LdAlign, WidthDiff.getKnownMinValue());
8296 if (!NewVT)
8297 return SDValue();
8298 NewVTWidth = NewVT->getSizeInBits();
8299 }
8300 MemVTs.push_back(*NewVT);
8301 } while (TypeSize::isKnownGT(RemainingWidth, NewVTWidth));
8302 }
8303
8304 SDValue LdOp = DAG.getLoad(*FirstVT, dl, Chain, BasePtr, LD->getPointerInfo(),
8305 LD->getBaseAlign(), MMOFlags, AAInfo);
8306 LdChain.push_back(LdOp.getValue(1));
8307
8308 // Check if we can load the element with one instruction.
8309 if (MemVTs.empty()) {
8310 assert(TypeSize::isKnownLE(LdWidth, FirstVTWidth));
8311 if (!FirstVT->isVector()) {
8312 unsigned NumElts =
8313 WidenWidth.getFixedValue() / FirstVTWidth.getFixedValue();
8314 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), *FirstVT, NumElts);
8315 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT, LdOp);
8316 return DAG.getNode(ISD::BITCAST, dl, WidenVT, VecOp);
8317 }
8318 if (FirstVT == WidenVT)
8319 return LdOp;
8320
8321 // TODO: We don't currently have any tests that exercise this code path.
8322 assert(WidenWidth.getFixedValue() % FirstVTWidth.getFixedValue() == 0);
8323 unsigned NumConcat =
8324 WidenWidth.getFixedValue() / FirstVTWidth.getFixedValue();
8325 SmallVector<SDValue, 16> ConcatOps(NumConcat);
8326 SDValue UndefVal = DAG.getUNDEF(*FirstVT);
8327 ConcatOps[0] = LdOp;
8328 for (unsigned i = 1; i != NumConcat; ++i)
8329 ConcatOps[i] = UndefVal;
8330 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, ConcatOps);
8331 }
8332
8333 // Load vector by using multiple loads from largest vector to scalar.
8335 LdOps.push_back(LdOp);
8336
8337 uint64_t ScaledOffset = 0;
8338 MachinePointerInfo MPI = LD->getPointerInfo();
8339
8340 // First incremement past the first load.
8341 IncrementPointer(cast<LoadSDNode>(LdOp), *FirstVT, MPI, BasePtr,
8342 &ScaledOffset);
8343
8344 for (EVT MemVT : MemVTs) {
8345 Align NewAlign = ScaledOffset == 0
8346 ? LD->getBaseAlign()
8347 : commonAlignment(LD->getAlign(), ScaledOffset);
8348 SDValue L =
8349 DAG.getLoad(MemVT, dl, Chain, BasePtr, MPI, NewAlign, MMOFlags, AAInfo);
8350
8351 LdOps.push_back(L);
8352 LdChain.push_back(L.getValue(1));
8353 IncrementPointer(cast<LoadSDNode>(L), MemVT, MPI, BasePtr, &ScaledOffset);
8354 }
8355
8356 // Build the vector from the load operations.
8357 unsigned End = LdOps.size();
8358 if (!LdOps[0].getValueType().isVector())
8359 // All the loads are scalar loads.
8360 return BuildVectorFromScalar(DAG, WidenVT, LdOps, 0, End);
8361
8362 // If the load contains vectors, build the vector using concat vector.
8363 // All of the vectors used to load are power-of-2, and the scalar loads can be
8364 // combined to make a power-of-2 vector.
8365 SmallVector<SDValue, 16> ConcatOps(End);
8366 int i = End - 1;
8367 int Idx = End;
8368 EVT LdTy = LdOps[i].getValueType();
8369 // First, combine the scalar loads to a vector.
8370 if (!LdTy.isVector()) {
8371 for (--i; i >= 0; --i) {
8372 LdTy = LdOps[i].getValueType();
8373 if (LdTy.isVector())
8374 break;
8375 }
8376 ConcatOps[--Idx] = BuildVectorFromScalar(DAG, LdTy, LdOps, i + 1, End);
8377 }
8378
8379 ConcatOps[--Idx] = LdOps[i];
8380 for (--i; i >= 0; --i) {
8381 EVT NewLdTy = LdOps[i].getValueType();
8382 if (NewLdTy != LdTy) {
8383 // Create a larger vector.
8384 TypeSize LdTySize = LdTy.getSizeInBits();
8385 TypeSize NewLdTySize = NewLdTy.getSizeInBits();
8386 assert(NewLdTySize.isScalable() == LdTySize.isScalable() &&
8387 NewLdTySize.isKnownMultipleOf(LdTySize.getKnownMinValue()));
8388 unsigned NumOps =
8389 NewLdTySize.getKnownMinValue() / LdTySize.getKnownMinValue();
8391 unsigned j = 0;
8392 for (; j != End-Idx; ++j)
8393 WidenOps[j] = ConcatOps[Idx+j];
8394 for (; j != NumOps; ++j)
8395 WidenOps[j] = DAG.getUNDEF(LdTy);
8396
8397 ConcatOps[End-1] = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewLdTy,
8398 WidenOps);
8399 Idx = End - 1;
8400 LdTy = NewLdTy;
8401 }
8402 ConcatOps[--Idx] = LdOps[i];
8403 }
8404
8405 if (WidenWidth == LdTy.getSizeInBits() * (End - Idx))
8406 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
8407 ArrayRef(&ConcatOps[Idx], End - Idx));
8408
8409 // We need to fill the rest with undefs to build the vector.
8410 unsigned NumOps =
8411 WidenWidth.getKnownMinValue() / LdTy.getSizeInBits().getKnownMinValue();
8413 SDValue UndefVal = DAG.getUNDEF(LdTy);
8414 {
8415 unsigned i = 0;
8416 for (; i != End-Idx; ++i)
8417 WidenOps[i] = ConcatOps[Idx+i];
8418 for (; i != NumOps; ++i)
8419 WidenOps[i] = UndefVal;
8420 }
8421 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, WidenOps);
8422}
8423
8424SDValue
8425DAGTypeLegalizer::GenWidenVectorExtLoads(SmallVectorImpl<SDValue> &LdChain,
8426 LoadSDNode *LD,
8427 ISD::LoadExtType ExtType) {
8428 // For extension loads, it may not be more efficient to chop up the vector
8429 // and then extend it. Instead, we unroll the load and build a new vector.
8430 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
8431 EVT LdVT = LD->getMemoryVT();
8432 SDLoc dl(LD);
8433 assert(LdVT.isVector() && WidenVT.isVector());
8434 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
8435
8436 // Load information
8437 SDValue Chain = LD->getChain();
8438 SDValue BasePtr = LD->getBasePtr();
8439 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
8440 AAMDNodes AAInfo = LD->getAAInfo();
8441
8442 if (LdVT.isScalableVector())
8443 return SDValue();
8444
8445 EVT EltVT = WidenVT.getVectorElementType();
8446 EVT LdEltVT = LdVT.getVectorElementType();
8447 unsigned NumElts = LdVT.getVectorNumElements();
8448
8449 // Load each element and widen.
8450 unsigned WidenNumElts = WidenVT.getVectorNumElements();
8451 SmallVector<SDValue, 16> Ops(WidenNumElts);
8452 unsigned Increment = LdEltVT.getSizeInBits() / 8;
8453 Ops[0] =
8454 DAG.getExtLoad(ExtType, dl, EltVT, Chain, BasePtr, LD->getPointerInfo(),
8455 LdEltVT, LD->getBaseAlign(), MMOFlags, AAInfo);
8456 LdChain.push_back(Ops[0].getValue(1));
8457 unsigned i = 0, Offset = Increment;
8458 for (i=1; i < NumElts; ++i, Offset += Increment) {
8459 SDValue NewBasePtr =
8460 DAG.getObjectPtrOffset(dl, BasePtr, TypeSize::getFixed(Offset));
8461 Ops[i] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, NewBasePtr,
8462 LD->getPointerInfo().getWithOffset(Offset), LdEltVT,
8463 LD->getBaseAlign(), MMOFlags, AAInfo);
8464 LdChain.push_back(Ops[i].getValue(1));
8465 }
8466
8467 // Fill the rest with undefs.
8468 SDValue UndefVal = DAG.getUNDEF(EltVT);
8469 for (; i != WidenNumElts; ++i)
8470 Ops[i] = UndefVal;
8471
8472 return DAG.getBuildVector(WidenVT, dl, Ops);
8473}
8474
8475bool DAGTypeLegalizer::GenWidenVectorStores(SmallVectorImpl<SDValue> &StChain,
8476 StoreSDNode *ST) {
8477 // The strategy assumes that we can efficiently store power-of-two widths.
8478 // The routine chops the vector into the largest vector stores with the same
8479 // element type or scalar stores.
8480 SDValue Chain = ST->getChain();
8481 SDValue BasePtr = ST->getBasePtr();
8482 MachineMemOperand::Flags MMOFlags = ST->getMemOperand()->getFlags();
8483 AAMDNodes AAInfo = ST->getAAInfo();
8484 SDValue ValOp = GetWidenedVector(ST->getValue());
8485 SDLoc dl(ST);
8486
8487 EVT StVT = ST->getMemoryVT();
8488 TypeSize StWidth = StVT.getSizeInBits();
8489 EVT ValVT = ValOp.getValueType();
8490 TypeSize ValWidth = ValVT.getSizeInBits();
8491 EVT ValEltVT = ValVT.getVectorElementType();
8492 unsigned ValEltWidth = ValEltVT.getFixedSizeInBits();
8493 assert(StVT.getVectorElementType() == ValEltVT);
8494 assert(StVT.isScalableVector() == ValVT.isScalableVector() &&
8495 "Mismatch between store and value types");
8496
8497 int Idx = 0; // current index to store
8498
8499 MachinePointerInfo MPI = ST->getPointerInfo();
8500 uint64_t ScaledOffset = 0;
8501
8502 // A breakdown of how to widen this vector store. Each element of the vector
8503 // is a memory VT combined with the number of times it is to be stored to,
8504 // e,g., v5i32 -> {{v2i32,2},{i32,1}}
8506
8507 while (StWidth.isNonZero()) {
8508 // Find the largest vector type we can store with.
8509 std::optional<EVT> NewVT =
8510 findMemType(DAG, TLI, StWidth.getKnownMinValue(), ValVT);
8511 if (!NewVT)
8512 return false;
8513 MemVTs.push_back({*NewVT, 0});
8514 TypeSize NewVTWidth = NewVT->getSizeInBits();
8515
8516 do {
8517 StWidth -= NewVTWidth;
8518 MemVTs.back().second++;
8519 } while (StWidth.isNonZero() && TypeSize::isKnownGE(StWidth, NewVTWidth));
8520 }
8521
8522 for (const auto &Pair : MemVTs) {
8523 EVT NewVT = Pair.first;
8524 unsigned Count = Pair.second;
8525 TypeSize NewVTWidth = NewVT.getSizeInBits();
8526
8527 if (NewVT.isVector()) {
8528 unsigned NumVTElts = NewVT.getVectorMinNumElements();
8529 do {
8530 Align NewAlign = ScaledOffset == 0
8531 ? ST->getBaseAlign()
8532 : commonAlignment(ST->getAlign(), ScaledOffset);
8533 SDValue EOp = DAG.getExtractSubvector(dl, NewVT, ValOp, Idx);
8534 SDValue PartStore = DAG.getStore(Chain, dl, EOp, BasePtr, MPI, NewAlign,
8535 MMOFlags, AAInfo);
8536 StChain.push_back(PartStore);
8537
8538 Idx += NumVTElts;
8539 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr,
8540 &ScaledOffset);
8541 } while (--Count);
8542 } else {
8543 // Cast the vector to the scalar type we can store.
8544 unsigned NumElts = ValWidth.getFixedValue() / NewVTWidth.getFixedValue();
8545 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewVT, NumElts);
8546 SDValue VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, ValOp);
8547 // Readjust index position based on new vector type.
8548 Idx = Idx * ValEltWidth / NewVTWidth.getFixedValue();
8549 do {
8550 SDValue EOp = DAG.getExtractVectorElt(dl, NewVT, VecOp, Idx++);
8551 SDValue PartStore = DAG.getStore(Chain, dl, EOp, BasePtr, MPI,
8552 ST->getBaseAlign(), MMOFlags, AAInfo);
8553 StChain.push_back(PartStore);
8554
8555 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr);
8556 } while (--Count);
8557 // Restore index back to be relative to the original widen element type.
8558 Idx = Idx * NewVTWidth.getFixedValue() / ValEltWidth;
8559 }
8560 }
8561
8562 return true;
8563}
8564
8565/// Modifies a vector input (widen or narrows) to a vector of NVT. The
8566/// input vector must have the same element type as NVT.
8567/// FillWithZeroes specifies that the vector should be widened with zeroes.
8568SDValue DAGTypeLegalizer::ModifyToType(SDValue InOp, EVT NVT,
8569 bool FillWithZeroes) {
8570 // Note that InOp might have been widened so it might already have
8571 // the right width or it might need be narrowed.
8572 EVT InVT = InOp.getValueType();
8574 "input and widen element type must match");
8575 assert(InVT.isScalableVector() == NVT.isScalableVector() &&
8576 "cannot modify scalable vectors in this way");
8577 SDLoc dl(InOp);
8578
8579 // Check if InOp already has the right width.
8580 if (InVT == NVT)
8581 return InOp;
8582
8583 ElementCount InEC = InVT.getVectorElementCount();
8584 ElementCount WidenEC = NVT.getVectorElementCount();
8585 if (WidenEC.hasKnownScalarFactor(InEC)) {
8586 unsigned NumConcat = WidenEC.getKnownScalarFactor(InEC);
8587 SmallVector<SDValue, 16> Ops(NumConcat);
8588 SDValue FillVal = FillWithZeroes ? DAG.getConstant(0, dl, InVT) :
8589 DAG.getUNDEF(InVT);
8590 Ops[0] = InOp;
8591 for (unsigned i = 1; i != NumConcat; ++i)
8592 Ops[i] = FillVal;
8593
8594 return DAG.getNode(ISD::CONCAT_VECTORS, dl, NVT, Ops);
8595 }
8596
8597 if (InEC.hasKnownScalarFactor(WidenEC))
8598 return DAG.getExtractSubvector(dl, NVT, InOp, 0);
8599
8600 assert(!InVT.isScalableVector() && !NVT.isScalableVector() &&
8601 "Scalable vectors should have been handled already.");
8602
8603 unsigned InNumElts = InEC.getFixedValue();
8604 unsigned WidenNumElts = WidenEC.getFixedValue();
8605
8606 // Fall back to extract and build (+ mask, if padding with zeros).
8607 SmallVector<SDValue, 16> Ops(WidenNumElts);
8608 EVT EltVT = NVT.getVectorElementType();
8609 unsigned MinNumElts = std::min(WidenNumElts, InNumElts);
8610 unsigned Idx;
8611 for (Idx = 0; Idx < MinNumElts; ++Idx)
8612 Ops[Idx] = DAG.getExtractVectorElt(dl, EltVT, InOp, Idx);
8613
8614 SDValue UndefVal = DAG.getUNDEF(EltVT);
8615 for (; Idx < WidenNumElts; ++Idx)
8616 Ops[Idx] = UndefVal;
8617
8618 SDValue Widened = DAG.getBuildVector(NVT, dl, Ops);
8619 if (!FillWithZeroes)
8620 return Widened;
8621
8622 assert(NVT.isInteger() &&
8623 "We expect to never want to FillWithZeroes for non-integral types.");
8624
8626 MaskOps.append(MinNumElts, DAG.getAllOnesConstant(dl, EltVT));
8627 MaskOps.append(WidenNumElts - MinNumElts, DAG.getConstant(0, dl, EltVT));
8628
8629 return DAG.getNode(ISD::AND, dl, NVT, Widened,
8630 DAG.getBuildVector(NVT, dl, MaskOps));
8631}
return SDValue()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static unsigned getExtendForIntVecReduction(SDNode *N)
static SDValue BuildVectorFromScalar(SelectionDAG &DAG, EVT VecTy, SmallVectorImpl< SDValue > &LdOps, unsigned Start, unsigned End)
static EVT getSETCCOperandType(SDValue N)
static bool isSETCCOp(unsigned Opcode)
static bool isLogicalMaskOp(unsigned Opcode)
static bool isSETCCorConvertedSETCC(SDValue N)
static SDValue CollectOpsToWiden(SelectionDAG &DAG, const TargetLowering &TLI, SmallVectorImpl< SDValue > &ConcatOps, unsigned ConcatEnd, EVT VT, EVT MaxVT, EVT WidenVT)
static std::optional< EVT > findMemType(SelectionDAG &DAG, const TargetLowering &TLI, unsigned Width, EVT WidenVT, unsigned Align=0, unsigned WidenEx=0)
#define I(x, y, z)
Definition MD5.cpp:57
static bool isUndef(const MachineInstr &MI)
This file provides utility analysis objects describing memory locations.
MachineInstr unsigned OpIdx
uint64_t High
#define P(N)
const SmallVectorImpl< MachineOperand > & Cond
static Type * getValueType(Value *V)
Returns the type of the given value/instruction V.
This file implements the SmallBitVector class.
#define LLVM_DEBUG(...)
Definition Debug.h:114
static std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
Definition VPlanSLP.cpp:247
Value * RHS
Value * LHS
This is an SDNode representing atomic operations.
LLVM_ABI unsigned getVScaleRangeMin() const
Returns the minimum value for the vscale_range attribute.
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition Attributes.h:223
static constexpr ElementCount getScalable(ScalarTy MinVal)
Definition TypeSize.h:312
static constexpr ElementCount get(ScalarTy MinVal, bool Scalable)
Definition TypeSize.h:315
This class is used to represent ISD::LOAD nodes.
static constexpr LocationSize beforeOrAfterPointer()
Any location before or after the base pointer (but still within the underlying object).
static auto integer_valuetypes()
static auto vector_valuetypes()
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
Flags
Flags values. These may be or'd together.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
This class is used to represent an MGATHER node.
const SDValue & getBasePtr() const
ISD::MemIndexType getIndexType() const
How is Index applied to BasePtr when computing addresses.
const SDValue & getInc() const
const SDValue & getScale() const
const SDValue & getMask() const
const SDValue & getIntID() const
const SDValue & getIndex() const
const SDValue & getBasePtr() const
ISD::MemIndexType getIndexType() const
This class is used to represent an MLOAD node.
const SDValue & getBasePtr() const
ISD::LoadExtType getExtensionType() const
const SDValue & getMask() const
const SDValue & getPassThru() const
const SDValue & getOffset() const
bool isUnindexed() const
Return true if this is NOT a pre/post inc/dec load/store.
ISD::MemIndexedMode getAddressingMode() const
Return the addressing mode for this load or store: unindexed, pre-inc, pre-dec, post-inc,...
const SDValue & getValue() const
bool isTruncatingStore() const
Return true if the op does a truncation before store.
This class is used to represent an MSTORE node.
bool isCompressingStore() const
Returns true if the op does a compression to the vector before storing.
const SDValue & getOffset() const
const SDValue & getBasePtr() const
const SDValue & getMask() const
const SDValue & getValue() const
This is an abstract virtual class for memory operations.
Align getBaseAlign() const
Returns alignment and volatility of the memory access.
const MDNode * getRanges() const
Returns the Ranges that describes the dereference.
AAMDNodes getAAInfo() const
Returns the AA info that describes the dereference.
MachineMemOperand * getMemOperand() const
Return a MachineMemOperand object describing the memory reference performed by operation.
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
bool isStrictFPOpcode()
Test if this node is a strict floating point pseudo-op.
const APInt & getAsAPIntVal() const
Helper method returns the APInt value of a ConstantSDNode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
bool isUndef() const
SDNode * getNode() const
get the SDNode which holds the desired result
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getInsertVectorElt(const SDLoc &DL, SDValue Vec, SDValue Elt, unsigned Idx)
Insert Elt into Vec at offset Idx.
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
LLVMContext * getContext() const
size_type size() const
Determine the number of elements in the SetVector.
Definition SetVector.h:103
Vector takeVector()
Clear the SetVector and return the underlying vector.
Definition SetVector.h:94
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:151
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
pointer data()
Return a pointer to the vector's buffer, even if empty().
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
BooleanContent
Enum that describes how the target represents true/false values.
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
static ISD::NodeType getExtendForContent(BooleanContent Content)
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:343
ISD::MemIndexedMode getAddressingMode() const
Return the addressing mode for this load or store: unindexed, pre-inc, pre-dec, post-inc,...
bool isUnindexed() const
Return true if this is NOT a pre/post inc/dec load/store.
This class is used to represent an VP_GATHER node.
const SDValue & getScale() const
ISD::MemIndexType getIndexType() const
How is Index applied to BasePtr when computing addresses.
const SDValue & getVectorLength() const
const SDValue & getIndex() const
const SDValue & getBasePtr() const
const SDValue & getMask() const
This class is used to represent a VP_LOAD node.
const SDValue & getValue() const
This class is used to represent a VP_STORE node.
This class is used to represent an EXPERIMENTAL_VP_STRIDED_LOAD node.
const SDValue & getMask() const
ISD::LoadExtType getExtensionType() const
const SDValue & getStride() const
const SDValue & getOffset() const
const SDValue & getVectorLength() const
const SDValue & getBasePtr() const
This class is used to represent an EXPERIMENTAL_VP_STRIDED_STORE node.
const SDValue & getBasePtr() const
const SDValue & getMask() const
const SDValue & getValue() const
bool isTruncatingStore() const
Return true if this is a truncating store.
const SDValue & getOffset() const
const SDValue & getVectorLength() const
const SDValue & getStride() const
bool isCompressingStore() const
Returns true if the op does a compression to the vector before storing.
constexpr bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
Definition TypeSize.h:180
constexpr bool hasKnownScalarFactor(const FixedOrScalableQuantity &RHS) const
Returns true if there exists a value X where RHS.multiplyCoefficientBy(X) will result in a value whos...
Definition TypeSize.h:269
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:200
static constexpr bool isKnownLE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:230
constexpr bool isNonZero() const
Definition TypeSize.h:155
constexpr ScalarTy getKnownScalarFactor(const FixedOrScalableQuantity &RHS) const
Returns a value X where RHS.multiplyCoefficientBy(X) will result in a value whose quantity matches ou...
Definition TypeSize.h:277
static constexpr bool isKnownLT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:216
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:168
constexpr bool isKnownEven() const
A return value of true indicates we know at compile time that the number of elements (vscale * Min) i...
Definition TypeSize.h:176
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:165
static constexpr bool isKnownGT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:223
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
Definition TypeSize.h:252
static constexpr bool isKnownGE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:237
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
Definition ISDOpcodes.h:41
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
Definition ISDOpcodes.h:813
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
Definition ISDOpcodes.h:256
@ CTLZ_ZERO_UNDEF
Definition ISDOpcodes.h:782
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
Definition ISDOpcodes.h:506
@ POISON
POISON - A poison node.
Definition ISDOpcodes.h:231
@ PARTIAL_REDUCE_SMLA
PARTIAL_REDUCE_[U|S]MLA(Accumulator, Input1, Input2) The partial reduction nodes sign or zero extend ...
@ LOOP_DEPENDENCE_RAW_MASK
@ VECREDUCE_SEQ_FADD
Generic reduction nodes.
@ MLOAD
Masked load and store - consecutive vector load and store operations with additional mask operand tha...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
Definition ISDOpcodes.h:595
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:773
@ SMULFIX
RESULT = [US]MULFIX(LHS, RHS, SCALE) - Perform fixed point multiplication on 2 integers with the same...
Definition ISDOpcodes.h:389
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:259
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ SMULFIXSAT
Same as the corresponding unsaturated fixed point instructions, but the result is clamped between the...
Definition ISDOpcodes.h:395
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition ISDOpcodes.h:847
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
Definition ISDOpcodes.h:513
@ FMODF
FMODF - Decomposes the operand into integral and fractional parts, each having the same type and sign...
@ FATAN2
FATAN2 - atan2, inspired by libm.
@ FSINCOSPI
FSINCOSPI - Compute both the sine and cosine times pi more accurately than FSINCOS(pi*x),...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Definition ISDOpcodes.h:874
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
Definition ISDOpcodes.h:579
@ VECREDUCE_FMAX
FMIN/FMAX nodes can have flags, for NaN/NoNaN variants.
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:412
@ VECREDUCE_FMAXIMUM
FMINIMUM/FMAXIMUM nodes propatate NaNs and signed zeroes using the llvm.minimum and llvm....
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
Definition ISDOpcodes.h:741
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
Definition ISDOpcodes.h:904
@ FPTRUNC_ROUND
FPTRUNC_ROUND - This corresponds to the fptrunc_round intrinsic.
Definition ISDOpcodes.h:510
@ FAKE_USE
FAKE_USE represents a use of the operand but does not do anything.
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
Definition ISDOpcodes.h:987
@ CLMUL
Carry-less multiplication operations.
Definition ISDOpcodes.h:768
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ SDIVFIX
RESULT = [US]DIVFIX(LHS, RHS, SCALE) - Perform fixed point division on 2 integers with the same width...
Definition ISDOpcodes.h:402
@ PARTIAL_REDUCE_UMLA
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:838
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
Definition ISDOpcodes.h:709
@ STRICT_UINT_TO_FP
Definition ISDOpcodes.h:480
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
Definition ISDOpcodes.h:659
@ VECREDUCE_FADD
These reductions have relaxed evaluation order semantics, and have a single vector operand.
@ CTTZ_ZERO_UNDEF
Bit counting operators with an undefined result for zero inputs.
Definition ISDOpcodes.h:781
@ PARTIAL_REDUCE_FMLA
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ SSUBO
Same for subtraction.
Definition ISDOpcodes.h:347
@ VECTOR_INTERLEAVE
VECTOR_INTERLEAVE(VEC1, VEC2, ...) - Returns N vectors from N input vectors, where N is the factor to...
Definition ISDOpcodes.h:630
@ STEP_VECTOR
STEP_VECTOR(IMM) - Returns a scalable vector whose lanes are comprised of a linear sequence of unsign...
Definition ISDOpcodes.h:685
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
Definition ISDOpcodes.h:536
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
Definition ISDOpcodes.h:543
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
Definition ISDOpcodes.h:369
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:790
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
Definition ISDOpcodes.h:228
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
Definition ISDOpcodes.h:666
@ GET_ACTIVE_LANE_MASK
GET_ACTIVE_LANE_MASK - this corrosponds to the llvm.get.active.lane.mask intrinsic.
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
Definition ISDOpcodes.h:343
@ ARITH_FENCE
ARITH_FENCE - This corresponds to a arithmetic fence intrinsic.
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition ISDOpcodes.h:698
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:759
@ AssertNoFPClass
AssertNoFPClass - These nodes record if a register contains a float value that is known to be not som...
Definition ISDOpcodes.h:78
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition ISDOpcodes.h:644
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition ISDOpcodes.h:609
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimumNumber or maximumNumber on two values,...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:571
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:844
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:805
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ SSHLSAT
RESULT = [US]SHLSAT(LHS, RHS) - Perform saturation left shift.
Definition ISDOpcodes.h:381
@ SMULO
Same for multiplication.
Definition ISDOpcodes.h:351
@ VECTOR_SPLICE_LEFT
VECTOR_SPLICE_LEFT(VEC1, VEC2, IMM) - Shifts CONCAT_VECTORS(VEC1, VEC2) left by IMM elements and retu...
Definition ISDOpcodes.h:648
@ ANY_EXTEND_VECTOR_INREG
ANY_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register any-extension of the low la...
Definition ISDOpcodes.h:893
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition ISDOpcodes.h:882
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:721
@ VECTOR_REVERSE
VECTOR_REVERSE(VECTOR) - Returns a vector, of the same type as VECTOR, whose elements are shuffled us...
Definition ISDOpcodes.h:635
@ SDIVFIXSAT
Same as the corresponding unsaturated fixed point instructions, but the result is clamped between the...
Definition ISDOpcodes.h:408
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:972
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition ISDOpcodes.h:799
@ STRICT_SINT_TO_FP
STRICT_[US]INT_TO_FP - Convert a signed or unsigned integer to a floating point value.
Definition ISDOpcodes.h:479
@ MGATHER
Masked gather and scatter - load and store operations for a vector of random addresses with additiona...
@ STRICT_FP_TO_UINT
Definition ISDOpcodes.h:473
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
Definition ISDOpcodes.h:495
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:472
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:920
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:500
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:733
@ SCMP
[US]CMP - 3-way comparison of signed or unsigned integers.
Definition ISDOpcodes.h:729
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
Definition ISDOpcodes.h:704
@ VECTOR_SPLICE_RIGHT
VECTOR_SPLICE_RIGHT(VEC1, VEC2, IMM) - Shifts CONCAT_VECTORS(VEC1, VEC2) right by IMM elements and re...
Definition ISDOpcodes.h:651
@ FREEZE
FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or is evaluated to UNDEF),...
Definition ISDOpcodes.h:236
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
Definition ISDOpcodes.h:560
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition ISDOpcodes.h:53
@ 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:953
@ VECTOR_COMPRESS
VECTOR_COMPRESS(Vec, Mask, Passthru) consecutively place vector elements based on mask e....
Definition ISDOpcodes.h:693
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
Definition ISDOpcodes.h:915
@ ADDRSPACECAST
ADDRSPACECAST - This operator converts between pointers of different address spaces.
Definition ISDOpcodes.h:991
@ 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:939
@ VECREDUCE_FMINIMUM
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:850
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ VECREDUCE_SEQ_FMUL
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
Definition ISDOpcodes.h:62
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
Definition ISDOpcodes.h:529
@ PARTIAL_REDUCE_SUMLA
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
Definition ISDOpcodes.h:360
@ VECTOR_DEINTERLEAVE
VECTOR_DEINTERLEAVE(VEC1, VEC2, ...) - Returns N vectors from N input vectors, where N is the factor ...
Definition ISDOpcodes.h:619
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - minimumnum/maximumnum that is same with FMINNUM_IEEE and FMAXNUM_IEEE besid...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
Definition ISDOpcodes.h:716
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition ISDOpcodes.h:551
@ LOOP_DEPENDENCE_WAR_MASK
The llvm.loop.dependence.
LLVM_ABI bool isBuildVectorOfConstantSDNodes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR node of all ConstantSDNode or undef.
bool isUNINDEXEDLoad(const SDNode *N)
Returns true if the specified node is an unindexed load.
LLVM_ABI std::optional< unsigned > getVPForBaseOpcode(unsigned Opcode)
Translate this non-VP Opcode to its corresponding VP Opcode.
MemIndexType
MemIndexType enum - This enum defines how to interpret MGATHER/SCATTER's index parameter when calcula...
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
LLVM_ABI NodeType getVecReduceBaseOpcode(unsigned VecReduceOpcode)
Get underlying scalar opcode for VECREDUCE opcode.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
LLVM_ABI LegalityPredicate isVector(unsigned TypeIdx)
True iff the specified type index is a vector.
constexpr double e
Context & getContext() const
Definition BasicBlock.h:99
This is an optimization pass for GlobalISel generic memory operations.
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:167
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr int PoisonMaskElem
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:189
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
Definition STLExtras.h:1883
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1770
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1945
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Definition Alignment.h:201
LLVM_ABI void processShuffleMasks(ArrayRef< int > Mask, unsigned NumOfSrcRegs, unsigned NumOfDestRegs, unsigned NumOfUsedRegs, function_ref< void()> NoInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned)> SingleInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned, bool)> ManyInputsAction)
Splits and processes shuffle mask depending on the number of input and output registers.
@ Increment
Incrementally increasing token ID.
Definition AllocToken.h:26
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:872
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77
Extended Value Type.
Definition ValueTypes.h:35
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
Definition ValueTypes.h:94
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
Definition ValueTypes.h:395
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
Definition ValueTypes.h:74
EVT changeTypeToInteger() const
Return the type converted to an equivalently sized integer or vector with integer element type.
Definition ValueTypes.h:121
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
Definition ValueTypes.h:284
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
Definition ValueTypes.h:147
ElementCount getVectorElementCount() const
Definition ValueTypes.h:350
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:373
bool isByteSized() const
Return true if the bit size is a multiple of 8.
Definition ValueTypes.h:243
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.