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"
23 #include "llvm/ADT/SmallBitVector.h"
24 #include "llvm/Analysis/MemoryLocation.h"
25 #include "llvm/Analysis/VectorUtils.h"
26 #include "llvm/IR/DataLayout.h"
27 #include "llvm/Support/ErrorHandling.h"
28 #include "llvm/Support/TypeSize.h"
29 #include "llvm/Support/raw_ostream.h"
30 #include <numeric>
31
32 using namespace llvm;
33
34 #define DEBUG_TYPE "legalize-types"
35
36 //===----------------------------------------------------------------------===//
37 // Result Vector Scalarization: <1 x ty> -> ty.
38 //===----------------------------------------------------------------------===//
39
ScalarizeVectorResult(SDNode * N,unsigned ResNo)40 void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) {
41 LLVM_DEBUG(dbgs() << "Scalarize node result " << ResNo << ": "; N->dump(&DAG);
42 dbgs() << "\n");
43 SDValue R = SDValue();
44
45 switch (N->getOpcode()) {
46 default:
47 #ifndef NDEBUG
48 dbgs() << "ScalarizeVectorResult #" << ResNo << ": ";
49 N->dump(&DAG);
50 dbgs() << "\n";
51 #endif
52 report_fatal_error("Do not know how to scalarize the result of this "
53 "operator!\n");
54
55 case ISD::MERGE_VALUES: R = ScalarizeVecRes_MERGE_VALUES(N, ResNo);break;
56 case ISD::BITCAST: R = ScalarizeVecRes_BITCAST(N); break;
57 case ISD::BUILD_VECTOR: R = ScalarizeVecRes_BUILD_VECTOR(N); break;
58 case ISD::EXTRACT_SUBVECTOR: R = ScalarizeVecRes_EXTRACT_SUBVECTOR(N); break;
59 case ISD::FP_ROUND: R = ScalarizeVecRes_FP_ROUND(N); break;
60 case ISD::FPOWI: R = ScalarizeVecRes_FPOWI(N); break;
61 case ISD::INSERT_VECTOR_ELT: R = ScalarizeVecRes_INSERT_VECTOR_ELT(N); break;
62 case ISD::LOAD: R = ScalarizeVecRes_LOAD(cast<LoadSDNode>(N));break;
63 case ISD::SCALAR_TO_VECTOR: R = ScalarizeVecRes_SCALAR_TO_VECTOR(N); break;
64 case ISD::SIGN_EXTEND_INREG: R = ScalarizeVecRes_InregOp(N); break;
65 case ISD::VSELECT: R = ScalarizeVecRes_VSELECT(N); break;
66 case ISD::SELECT: R = ScalarizeVecRes_SELECT(N); break;
67 case ISD::SELECT_CC: R = ScalarizeVecRes_SELECT_CC(N); break;
68 case ISD::SETCC: R = ScalarizeVecRes_SETCC(N); break;
69 case ISD::UNDEF: R = ScalarizeVecRes_UNDEF(N); break;
70 case ISD::VECTOR_SHUFFLE: R = ScalarizeVecRes_VECTOR_SHUFFLE(N); break;
71 case ISD::IS_FPCLASS: R = ScalarizeVecRes_IS_FPCLASS(N); break;
72 case ISD::ANY_EXTEND_VECTOR_INREG:
73 case ISD::SIGN_EXTEND_VECTOR_INREG:
74 case ISD::ZERO_EXTEND_VECTOR_INREG:
75 R = ScalarizeVecRes_VecInregOp(N);
76 break;
77 case ISD::ABS:
78 case ISD::ANY_EXTEND:
79 case ISD::BITREVERSE:
80 case ISD::BSWAP:
81 case ISD::CTLZ:
82 case ISD::CTLZ_ZERO_UNDEF:
83 case ISD::CTPOP:
84 case ISD::CTTZ:
85 case ISD::CTTZ_ZERO_UNDEF:
86 case ISD::FABS:
87 case ISD::FCEIL:
88 case ISD::FCOS:
89 case ISD::FEXP:
90 case ISD::FEXP2:
91 case ISD::FFLOOR:
92 case ISD::FLOG:
93 case ISD::FLOG10:
94 case ISD::FLOG2:
95 case ISD::FNEARBYINT:
96 case ISD::FNEG:
97 case ISD::FREEZE:
98 case ISD::ARITH_FENCE:
99 case ISD::FP_EXTEND:
100 case ISD::FP_TO_SINT:
101 case ISD::FP_TO_UINT:
102 case ISD::FRINT:
103 case ISD::FROUND:
104 case ISD::FROUNDEVEN:
105 case ISD::FSIN:
106 case ISD::FSQRT:
107 case ISD::FTRUNC:
108 case ISD::SIGN_EXTEND:
109 case ISD::SINT_TO_FP:
110 case ISD::TRUNCATE:
111 case ISD::UINT_TO_FP:
112 case ISD::ZERO_EXTEND:
113 case ISD::FCANONICALIZE:
114 R = ScalarizeVecRes_UnaryOp(N);
115 break;
116
117 case ISD::ADD:
118 case ISD::AND:
119 case ISD::FADD:
120 case ISD::FCOPYSIGN:
121 case ISD::FDIV:
122 case ISD::FMUL:
123 case ISD::FMINNUM:
124 case ISD::FMAXNUM:
125 case ISD::FMINNUM_IEEE:
126 case ISD::FMAXNUM_IEEE:
127 case ISD::FMINIMUM:
128 case ISD::FMAXIMUM:
129 case ISD::SMIN:
130 case ISD::SMAX:
131 case ISD::UMIN:
132 case ISD::UMAX:
133
134 case ISD::SADDSAT:
135 case ISD::UADDSAT:
136 case ISD::SSUBSAT:
137 case ISD::USUBSAT:
138 case ISD::SSHLSAT:
139 case ISD::USHLSAT:
140
141 case ISD::FPOW:
142 case ISD::FREM:
143 case ISD::FSUB:
144 case ISD::MUL:
145 case ISD::OR:
146 case ISD::SDIV:
147 case ISD::SREM:
148 case ISD::SUB:
149 case ISD::UDIV:
150 case ISD::UREM:
151 case ISD::XOR:
152 case ISD::SHL:
153 case ISD::SRA:
154 case ISD::SRL:
155 case ISD::ROTL:
156 case ISD::ROTR:
157 R = ScalarizeVecRes_BinOp(N);
158 break;
159 case ISD::FMA:
160 case ISD::FSHL:
161 case ISD::FSHR:
162 R = ScalarizeVecRes_TernaryOp(N);
163 break;
164
165 #define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
166 case ISD::STRICT_##DAGN:
167 #include "llvm/IR/ConstrainedOps.def"
168 R = ScalarizeVecRes_StrictFPOp(N);
169 break;
170
171 case ISD::FP_TO_UINT_SAT:
172 case ISD::FP_TO_SINT_SAT:
173 R = ScalarizeVecRes_FP_TO_XINT_SAT(N);
174 break;
175
176 case ISD::UADDO:
177 case ISD::SADDO:
178 case ISD::USUBO:
179 case ISD::SSUBO:
180 case ISD::UMULO:
181 case ISD::SMULO:
182 R = ScalarizeVecRes_OverflowOp(N, ResNo);
183 break;
184 case ISD::SMULFIX:
185 case ISD::SMULFIXSAT:
186 case ISD::UMULFIX:
187 case ISD::UMULFIXSAT:
188 case ISD::SDIVFIX:
189 case ISD::SDIVFIXSAT:
190 case ISD::UDIVFIX:
191 case ISD::UDIVFIXSAT:
192 R = ScalarizeVecRes_FIX(N);
193 break;
194 }
195
196 // If R is null, the sub-method took care of registering the result.
197 if (R.getNode())
198 SetScalarizedVector(SDValue(N, ResNo), R);
199 }
200
ScalarizeVecRes_BinOp(SDNode * N)201 SDValue DAGTypeLegalizer::ScalarizeVecRes_BinOp(SDNode *N) {
202 SDValue LHS = GetScalarizedVector(N->getOperand(0));
203 SDValue RHS = GetScalarizedVector(N->getOperand(1));
204 return DAG.getNode(N->getOpcode(), SDLoc(N),
205 LHS.getValueType(), LHS, RHS, N->getFlags());
206 }
207
ScalarizeVecRes_TernaryOp(SDNode * N)208 SDValue DAGTypeLegalizer::ScalarizeVecRes_TernaryOp(SDNode *N) {
209 SDValue Op0 = GetScalarizedVector(N->getOperand(0));
210 SDValue Op1 = GetScalarizedVector(N->getOperand(1));
211 SDValue Op2 = GetScalarizedVector(N->getOperand(2));
212 return DAG.getNode(N->getOpcode(), SDLoc(N), Op0.getValueType(), Op0, Op1,
213 Op2, N->getFlags());
214 }
215
ScalarizeVecRes_FIX(SDNode * N)216 SDValue DAGTypeLegalizer::ScalarizeVecRes_FIX(SDNode *N) {
217 SDValue Op0 = GetScalarizedVector(N->getOperand(0));
218 SDValue Op1 = GetScalarizedVector(N->getOperand(1));
219 SDValue Op2 = N->getOperand(2);
220 return DAG.getNode(N->getOpcode(), SDLoc(N), Op0.getValueType(), Op0, Op1,
221 Op2, N->getFlags());
222 }
223
ScalarizeVecRes_StrictFPOp(SDNode * N)224 SDValue DAGTypeLegalizer::ScalarizeVecRes_StrictFPOp(SDNode *N) {
225 EVT VT = N->getValueType(0).getVectorElementType();
226 unsigned NumOpers = N->getNumOperands();
227 SDValue Chain = N->getOperand(0);
228 EVT ValueVTs[] = {VT, MVT::Other};
229 SDLoc dl(N);
230
231 SmallVector<SDValue, 4> Opers(NumOpers);
232
233 // The Chain is the first operand.
234 Opers[0] = Chain;
235
236 // Now process the remaining operands.
237 for (unsigned i = 1; i < NumOpers; ++i) {
238 SDValue Oper = N->getOperand(i);
239 EVT OperVT = Oper.getValueType();
240
241 if (OperVT.isVector()) {
242 if (getTypeAction(OperVT) == TargetLowering::TypeScalarizeVector)
243 Oper = GetScalarizedVector(Oper);
244 else
245 Oper = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl,
246 OperVT.getVectorElementType(), Oper,
247 DAG.getVectorIdxConstant(0, dl));
248 }
249
250 Opers[i] = Oper;
251 }
252
253 SDValue Result = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(ValueVTs),
254 Opers, N->getFlags());
255
256 // Legalize the chain result - switch anything that used the old chain to
257 // use the new one.
258 ReplaceValueWith(SDValue(N, 1), Result.getValue(1));
259 return Result;
260 }
261
ScalarizeVecRes_OverflowOp(SDNode * N,unsigned ResNo)262 SDValue DAGTypeLegalizer::ScalarizeVecRes_OverflowOp(SDNode *N,
263 unsigned ResNo) {
264 SDLoc DL(N);
265 EVT ResVT = N->getValueType(0);
266 EVT OvVT = N->getValueType(1);
267
268 SDValue ScalarLHS, ScalarRHS;
269 if (getTypeAction(ResVT) == TargetLowering::TypeScalarizeVector) {
270 ScalarLHS = GetScalarizedVector(N->getOperand(0));
271 ScalarRHS = GetScalarizedVector(N->getOperand(1));
272 } else {
273 SmallVector<SDValue, 1> ElemsLHS, ElemsRHS;
274 DAG.ExtractVectorElements(N->getOperand(0), ElemsLHS);
275 DAG.ExtractVectorElements(N->getOperand(1), ElemsRHS);
276 ScalarLHS = ElemsLHS[0];
277 ScalarRHS = ElemsRHS[0];
278 }
279
280 SDVTList ScalarVTs = DAG.getVTList(
281 ResVT.getVectorElementType(), OvVT.getVectorElementType());
282 SDNode *ScalarNode = DAG.getNode(
283 N->getOpcode(), DL, ScalarVTs, ScalarLHS, ScalarRHS).getNode();
284 ScalarNode->setFlags(N->getFlags());
285
286 // Replace the other vector result not being explicitly scalarized here.
287 unsigned OtherNo = 1 - ResNo;
288 EVT OtherVT = N->getValueType(OtherNo);
289 if (getTypeAction(OtherVT) == TargetLowering::TypeScalarizeVector) {
290 SetScalarizedVector(SDValue(N, OtherNo), SDValue(ScalarNode, OtherNo));
291 } else {
292 SDValue OtherVal = DAG.getNode(
293 ISD::SCALAR_TO_VECTOR, DL, OtherVT, SDValue(ScalarNode, OtherNo));
294 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
295 }
296
297 return SDValue(ScalarNode, ResNo);
298 }
299
ScalarizeVecRes_MERGE_VALUES(SDNode * N,unsigned ResNo)300 SDValue DAGTypeLegalizer::ScalarizeVecRes_MERGE_VALUES(SDNode *N,
301 unsigned ResNo) {
302 SDValue Op = DisintegrateMERGE_VALUES(N, ResNo);
303 return GetScalarizedVector(Op);
304 }
305
ScalarizeVecRes_BITCAST(SDNode * N)306 SDValue DAGTypeLegalizer::ScalarizeVecRes_BITCAST(SDNode *N) {
307 SDValue Op = N->getOperand(0);
308 if (Op.getValueType().isVector()
309 && Op.getValueType().getVectorNumElements() == 1
310 && !isSimpleLegalType(Op.getValueType()))
311 Op = GetScalarizedVector(Op);
312 EVT NewVT = N->getValueType(0).getVectorElementType();
313 return DAG.getNode(ISD::BITCAST, SDLoc(N),
314 NewVT, Op);
315 }
316
ScalarizeVecRes_BUILD_VECTOR(SDNode * N)317 SDValue DAGTypeLegalizer::ScalarizeVecRes_BUILD_VECTOR(SDNode *N) {
318 EVT EltVT = N->getValueType(0).getVectorElementType();
319 SDValue InOp = N->getOperand(0);
320 // The BUILD_VECTOR operands may be of wider element types and
321 // we may need to truncate them back to the requested return type.
322 if (EltVT.isInteger())
323 return DAG.getNode(ISD::TRUNCATE, SDLoc(N), EltVT, InOp);
324 return InOp;
325 }
326
ScalarizeVecRes_EXTRACT_SUBVECTOR(SDNode * N)327 SDValue DAGTypeLegalizer::ScalarizeVecRes_EXTRACT_SUBVECTOR(SDNode *N) {
328 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
329 N->getValueType(0).getVectorElementType(),
330 N->getOperand(0), N->getOperand(1));
331 }
332
ScalarizeVecRes_FP_ROUND(SDNode * N)333 SDValue DAGTypeLegalizer::ScalarizeVecRes_FP_ROUND(SDNode *N) {
334 SDLoc DL(N);
335 SDValue Op = N->getOperand(0);
336 EVT OpVT = Op.getValueType();
337 // The result needs scalarizing, but it's not a given that the source does.
338 // See similar logic in ScalarizeVecRes_UnaryOp.
339 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
340 Op = GetScalarizedVector(Op);
341 } else {
342 EVT VT = OpVT.getVectorElementType();
343 Op = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, Op,
344 DAG.getVectorIdxConstant(0, DL));
345 }
346 return DAG.getNode(ISD::FP_ROUND, DL,
347 N->getValueType(0).getVectorElementType(), Op,
348 N->getOperand(1));
349 }
350
ScalarizeVecRes_FPOWI(SDNode * N)351 SDValue DAGTypeLegalizer::ScalarizeVecRes_FPOWI(SDNode *N) {
352 SDValue Op = GetScalarizedVector(N->getOperand(0));
353 return DAG.getNode(ISD::FPOWI, SDLoc(N),
354 Op.getValueType(), Op, N->getOperand(1));
355 }
356
ScalarizeVecRes_INSERT_VECTOR_ELT(SDNode * N)357 SDValue DAGTypeLegalizer::ScalarizeVecRes_INSERT_VECTOR_ELT(SDNode *N) {
358 // The value to insert may have a wider type than the vector element type,
359 // so be sure to truncate it to the element type if necessary.
360 SDValue Op = N->getOperand(1);
361 EVT EltVT = N->getValueType(0).getVectorElementType();
362 if (Op.getValueType() != EltVT)
363 // FIXME: Can this happen for floating point types?
364 Op = DAG.getNode(ISD::TRUNCATE, SDLoc(N), EltVT, Op);
365 return Op;
366 }
367
ScalarizeVecRes_LOAD(LoadSDNode * N)368 SDValue DAGTypeLegalizer::ScalarizeVecRes_LOAD(LoadSDNode *N) {
369 assert(N->isUnindexed() && "Indexed vector load?");
370
371 SDValue Result = DAG.getLoad(
372 ISD::UNINDEXED, N->getExtensionType(),
373 N->getValueType(0).getVectorElementType(), SDLoc(N), N->getChain(),
374 N->getBasePtr(), DAG.getUNDEF(N->getBasePtr().getValueType()),
375 N->getPointerInfo(), N->getMemoryVT().getVectorElementType(),
376 N->getOriginalAlign(), N->getMemOperand()->getFlags(), N->getAAInfo());
377
378 // Legalize the chain result - switch anything that used the old chain to
379 // use the new one.
380 ReplaceValueWith(SDValue(N, 1), Result.getValue(1));
381 return Result;
382 }
383
ScalarizeVecRes_UnaryOp(SDNode * N)384 SDValue DAGTypeLegalizer::ScalarizeVecRes_UnaryOp(SDNode *N) {
385 // Get the dest type - it doesn't always match the input type, e.g. int_to_fp.
386 EVT DestVT = N->getValueType(0).getVectorElementType();
387 SDValue Op = N->getOperand(0);
388 EVT OpVT = Op.getValueType();
389 SDLoc DL(N);
390 // The result needs scalarizing, but it's not a given that the source does.
391 // This is a workaround for targets where it's impossible to scalarize the
392 // result of a conversion, because the source type is legal.
393 // For instance, this happens on AArch64: v1i1 is illegal but v1i{8,16,32}
394 // are widened to v8i8, v4i16, and v2i32, which is legal, because v1i64 is
395 // legal and was not scalarized.
396 // See the similar logic in ScalarizeVecRes_SETCC
397 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
398 Op = GetScalarizedVector(Op);
399 } else {
400 EVT VT = OpVT.getVectorElementType();
401 Op = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, Op,
402 DAG.getVectorIdxConstant(0, DL));
403 }
404 return DAG.getNode(N->getOpcode(), SDLoc(N), DestVT, Op, N->getFlags());
405 }
406
ScalarizeVecRes_InregOp(SDNode * N)407 SDValue DAGTypeLegalizer::ScalarizeVecRes_InregOp(SDNode *N) {
408 EVT EltVT = N->getValueType(0).getVectorElementType();
409 EVT ExtVT = cast<VTSDNode>(N->getOperand(1))->getVT().getVectorElementType();
410 SDValue LHS = GetScalarizedVector(N->getOperand(0));
411 return DAG.getNode(N->getOpcode(), SDLoc(N), EltVT,
412 LHS, DAG.getValueType(ExtVT));
413 }
414
ScalarizeVecRes_VecInregOp(SDNode * N)415 SDValue DAGTypeLegalizer::ScalarizeVecRes_VecInregOp(SDNode *N) {
416 SDLoc DL(N);
417 SDValue Op = N->getOperand(0);
418
419 EVT OpVT = Op.getValueType();
420 EVT OpEltVT = OpVT.getVectorElementType();
421 EVT EltVT = N->getValueType(0).getVectorElementType();
422
423 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
424 Op = GetScalarizedVector(Op);
425 } else {
426 Op = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, OpEltVT, Op,
427 DAG.getVectorIdxConstant(0, DL));
428 }
429
430 switch (N->getOpcode()) {
431 case ISD::ANY_EXTEND_VECTOR_INREG:
432 return DAG.getNode(ISD::ANY_EXTEND, DL, EltVT, Op);
433 case ISD::SIGN_EXTEND_VECTOR_INREG:
434 return DAG.getNode(ISD::SIGN_EXTEND, DL, EltVT, Op);
435 case ISD::ZERO_EXTEND_VECTOR_INREG:
436 return DAG.getNode(ISD::ZERO_EXTEND, DL, EltVT, Op);
437 }
438
439 llvm_unreachable("Illegal extend_vector_inreg opcode");
440 }
441
ScalarizeVecRes_SCALAR_TO_VECTOR(SDNode * N)442 SDValue DAGTypeLegalizer::ScalarizeVecRes_SCALAR_TO_VECTOR(SDNode *N) {
443 // If the operand is wider than the vector element type then it is implicitly
444 // truncated. Make that explicit here.
445 EVT EltVT = N->getValueType(0).getVectorElementType();
446 SDValue InOp = N->getOperand(0);
447 if (InOp.getValueType() != EltVT)
448 return DAG.getNode(ISD::TRUNCATE, SDLoc(N), EltVT, InOp);
449 return InOp;
450 }
451
ScalarizeVecRes_VSELECT(SDNode * N)452 SDValue DAGTypeLegalizer::ScalarizeVecRes_VSELECT(SDNode *N) {
453 SDValue Cond = N->getOperand(0);
454 EVT OpVT = Cond.getValueType();
455 SDLoc DL(N);
456 // The vselect result and true/value operands needs scalarizing, but it's
457 // not a given that the Cond does. For instance, in AVX512 v1i1 is legal.
458 // See the similar logic in ScalarizeVecRes_SETCC
459 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
460 Cond = GetScalarizedVector(Cond);
461 } else {
462 EVT VT = OpVT.getVectorElementType();
463 Cond = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, Cond,
464 DAG.getVectorIdxConstant(0, DL));
465 }
466
467 SDValue LHS = GetScalarizedVector(N->getOperand(1));
468 TargetLowering::BooleanContent ScalarBool =
469 TLI.getBooleanContents(false, false);
470 TargetLowering::BooleanContent VecBool = TLI.getBooleanContents(true, false);
471
472 // If integer and float booleans have different contents then we can't
473 // reliably optimize in all cases. There is a full explanation for this in
474 // DAGCombiner::visitSELECT() where the same issue affects folding
475 // (select C, 0, 1) to (xor C, 1).
476 if (TLI.getBooleanContents(false, false) !=
477 TLI.getBooleanContents(false, true)) {
478 // At least try the common case where the boolean is generated by a
479 // comparison.
480 if (Cond->getOpcode() == ISD::SETCC) {
481 EVT OpVT = Cond->getOperand(0).getValueType();
482 ScalarBool = TLI.getBooleanContents(OpVT.getScalarType());
483 VecBool = TLI.getBooleanContents(OpVT);
484 } else
485 ScalarBool = TargetLowering::UndefinedBooleanContent;
486 }
487
488 EVT CondVT = Cond.getValueType();
489 if (ScalarBool != VecBool) {
490 switch (ScalarBool) {
491 case TargetLowering::UndefinedBooleanContent:
492 break;
493 case TargetLowering::ZeroOrOneBooleanContent:
494 assert(VecBool == TargetLowering::UndefinedBooleanContent ||
495 VecBool == TargetLowering::ZeroOrNegativeOneBooleanContent);
496 // Vector read from all ones, scalar expects a single 1 so mask.
497 Cond = DAG.getNode(ISD::AND, SDLoc(N), CondVT,
498 Cond, DAG.getConstant(1, SDLoc(N), CondVT));
499 break;
500 case TargetLowering::ZeroOrNegativeOneBooleanContent:
501 assert(VecBool == TargetLowering::UndefinedBooleanContent ||
502 VecBool == TargetLowering::ZeroOrOneBooleanContent);
503 // Vector reads from a one, scalar from all ones so sign extend.
504 Cond = DAG.getNode(ISD::SIGN_EXTEND_INREG, SDLoc(N), CondVT,
505 Cond, DAG.getValueType(MVT::i1));
506 break;
507 }
508 }
509
510 // Truncate the condition if needed
511 auto BoolVT = getSetCCResultType(CondVT);
512 if (BoolVT.bitsLT(CondVT))
513 Cond = DAG.getNode(ISD::TRUNCATE, SDLoc(N), BoolVT, Cond);
514
515 return DAG.getSelect(SDLoc(N),
516 LHS.getValueType(), Cond, LHS,
517 GetScalarizedVector(N->getOperand(2)));
518 }
519
ScalarizeVecRes_SELECT(SDNode * N)520 SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT(SDNode *N) {
521 SDValue LHS = GetScalarizedVector(N->getOperand(1));
522 return DAG.getSelect(SDLoc(N),
523 LHS.getValueType(), N->getOperand(0), LHS,
524 GetScalarizedVector(N->getOperand(2)));
525 }
526
ScalarizeVecRes_SELECT_CC(SDNode * N)527 SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT_CC(SDNode *N) {
528 SDValue LHS = GetScalarizedVector(N->getOperand(2));
529 return DAG.getNode(ISD::SELECT_CC, SDLoc(N), LHS.getValueType(),
530 N->getOperand(0), N->getOperand(1),
531 LHS, GetScalarizedVector(N->getOperand(3)),
532 N->getOperand(4));
533 }
534
ScalarizeVecRes_UNDEF(SDNode * N)535 SDValue DAGTypeLegalizer::ScalarizeVecRes_UNDEF(SDNode *N) {
536 return DAG.getUNDEF(N->getValueType(0).getVectorElementType());
537 }
538
ScalarizeVecRes_VECTOR_SHUFFLE(SDNode * N)539 SDValue DAGTypeLegalizer::ScalarizeVecRes_VECTOR_SHUFFLE(SDNode *N) {
540 // Figure out if the scalar is the LHS or RHS and return it.
541 SDValue Arg = N->getOperand(2).getOperand(0);
542 if (Arg.isUndef())
543 return DAG.getUNDEF(N->getValueType(0).getVectorElementType());
544 unsigned Op = !cast<ConstantSDNode>(Arg)->isZero();
545 return GetScalarizedVector(N->getOperand(Op));
546 }
547
ScalarizeVecRes_FP_TO_XINT_SAT(SDNode * N)548 SDValue DAGTypeLegalizer::ScalarizeVecRes_FP_TO_XINT_SAT(SDNode *N) {
549 SDValue Src = N->getOperand(0);
550 EVT SrcVT = Src.getValueType();
551 SDLoc dl(N);
552
553 // Handle case where result is scalarized but operand is not
554 if (getTypeAction(SrcVT) == TargetLowering::TypeScalarizeVector)
555 Src = GetScalarizedVector(Src);
556 else
557 Src = DAG.getNode(
558 ISD::EXTRACT_VECTOR_ELT, dl, SrcVT.getVectorElementType(), Src,
559 DAG.getConstant(0, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
560
561 EVT DstVT = N->getValueType(0).getVectorElementType();
562 return DAG.getNode(N->getOpcode(), dl, DstVT, Src, N->getOperand(1));
563 }
564
ScalarizeVecRes_SETCC(SDNode * N)565 SDValue DAGTypeLegalizer::ScalarizeVecRes_SETCC(SDNode *N) {
566 assert(N->getValueType(0).isVector() &&
567 N->getOperand(0).getValueType().isVector() &&
568 "Operand types must be vectors");
569 SDValue LHS = N->getOperand(0);
570 SDValue RHS = N->getOperand(1);
571 EVT OpVT = LHS.getValueType();
572 EVT NVT = N->getValueType(0).getVectorElementType();
573 SDLoc DL(N);
574
575 // The result needs scalarizing, but it's not a given that the source does.
576 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
577 LHS = GetScalarizedVector(LHS);
578 RHS = GetScalarizedVector(RHS);
579 } else {
580 EVT VT = OpVT.getVectorElementType();
581 LHS = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, LHS,
582 DAG.getVectorIdxConstant(0, DL));
583 RHS = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, RHS,
584 DAG.getVectorIdxConstant(0, DL));
585 }
586
587 // Turn it into a scalar SETCC.
588 SDValue Res = DAG.getNode(ISD::SETCC, DL, MVT::i1, LHS, RHS,
589 N->getOperand(2));
590 // Vectors may have a different boolean contents to scalars. Promote the
591 // value appropriately.
592 ISD::NodeType ExtendCode =
593 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
594 return DAG.getNode(ExtendCode, DL, NVT, Res);
595 }
596
ScalarizeVecRes_IS_FPCLASS(SDNode * N)597 SDValue DAGTypeLegalizer::ScalarizeVecRes_IS_FPCLASS(SDNode *N) {
598 SDLoc DL(N);
599 SDValue Arg = N->getOperand(0);
600 SDValue Test = N->getOperand(1);
601 EVT ArgVT = Arg.getValueType();
602 EVT ResultVT = N->getValueType(0).getVectorElementType();
603
604 if (getTypeAction(ArgVT) == TargetLowering::TypeScalarizeVector) {
605 Arg = GetScalarizedVector(Arg);
606 } else {
607 EVT VT = ArgVT.getVectorElementType();
608 Arg = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, Arg,
609 DAG.getVectorIdxConstant(0, DL));
610 }
611
612 SDValue Res =
613 DAG.getNode(ISD::IS_FPCLASS, DL, MVT::i1, {Arg, Test}, N->getFlags());
614 // Vectors may have a different boolean contents to scalars. Promote the
615 // value appropriately.
616 ISD::NodeType ExtendCode =
617 TargetLowering::getExtendForContent(TLI.getBooleanContents(ArgVT));
618 return DAG.getNode(ExtendCode, DL, ResultVT, Res);
619 }
620
621 //===----------------------------------------------------------------------===//
622 // Operand Vector Scalarization <1 x ty> -> ty.
623 //===----------------------------------------------------------------------===//
624
ScalarizeVectorOperand(SDNode * N,unsigned OpNo)625 bool DAGTypeLegalizer::ScalarizeVectorOperand(SDNode *N, unsigned OpNo) {
626 LLVM_DEBUG(dbgs() << "Scalarize node operand " << OpNo << ": "; N->dump(&DAG);
627 dbgs() << "\n");
628 SDValue Res = SDValue();
629
630 switch (N->getOpcode()) {
631 default:
632 #ifndef NDEBUG
633 dbgs() << "ScalarizeVectorOperand Op #" << OpNo << ": ";
634 N->dump(&DAG);
635 dbgs() << "\n";
636 #endif
637 report_fatal_error("Do not know how to scalarize this operator's "
638 "operand!\n");
639 case ISD::BITCAST:
640 Res = ScalarizeVecOp_BITCAST(N);
641 break;
642 case ISD::ANY_EXTEND:
643 case ISD::ZERO_EXTEND:
644 case ISD::SIGN_EXTEND:
645 case ISD::TRUNCATE:
646 case ISD::FP_TO_SINT:
647 case ISD::FP_TO_UINT:
648 case ISD::SINT_TO_FP:
649 case ISD::UINT_TO_FP:
650 Res = ScalarizeVecOp_UnaryOp(N);
651 break;
652 case ISD::STRICT_SINT_TO_FP:
653 case ISD::STRICT_UINT_TO_FP:
654 case ISD::STRICT_FP_TO_SINT:
655 case ISD::STRICT_FP_TO_UINT:
656 Res = ScalarizeVecOp_UnaryOp_StrictFP(N);
657 break;
658 case ISD::CONCAT_VECTORS:
659 Res = ScalarizeVecOp_CONCAT_VECTORS(N);
660 break;
661 case ISD::EXTRACT_VECTOR_ELT:
662 Res = ScalarizeVecOp_EXTRACT_VECTOR_ELT(N);
663 break;
664 case ISD::VSELECT:
665 Res = ScalarizeVecOp_VSELECT(N);
666 break;
667 case ISD::SETCC:
668 Res = ScalarizeVecOp_VSETCC(N);
669 break;
670 case ISD::STORE:
671 Res = ScalarizeVecOp_STORE(cast<StoreSDNode>(N), OpNo);
672 break;
673 case ISD::STRICT_FP_ROUND:
674 Res = ScalarizeVecOp_STRICT_FP_ROUND(N, OpNo);
675 break;
676 case ISD::FP_ROUND:
677 Res = ScalarizeVecOp_FP_ROUND(N, OpNo);
678 break;
679 case ISD::STRICT_FP_EXTEND:
680 Res = ScalarizeVecOp_STRICT_FP_EXTEND(N);
681 break;
682 case ISD::FP_EXTEND:
683 Res = ScalarizeVecOp_FP_EXTEND(N);
684 break;
685 case ISD::VECREDUCE_FADD:
686 case ISD::VECREDUCE_FMUL:
687 case ISD::VECREDUCE_ADD:
688 case ISD::VECREDUCE_MUL:
689 case ISD::VECREDUCE_AND:
690 case ISD::VECREDUCE_OR:
691 case ISD::VECREDUCE_XOR:
692 case ISD::VECREDUCE_SMAX:
693 case ISD::VECREDUCE_SMIN:
694 case ISD::VECREDUCE_UMAX:
695 case ISD::VECREDUCE_UMIN:
696 case ISD::VECREDUCE_FMAX:
697 case ISD::VECREDUCE_FMIN:
698 Res = ScalarizeVecOp_VECREDUCE(N);
699 break;
700 case ISD::VECREDUCE_SEQ_FADD:
701 case ISD::VECREDUCE_SEQ_FMUL:
702 Res = ScalarizeVecOp_VECREDUCE_SEQ(N);
703 break;
704 }
705
706 // If the result is null, the sub-method took care of registering results etc.
707 if (!Res.getNode()) return false;
708
709 // If the result is N, the sub-method updated N in place. Tell the legalizer
710 // core about this.
711 if (Res.getNode() == N)
712 return true;
713
714 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
715 "Invalid operand expansion");
716
717 ReplaceValueWith(SDValue(N, 0), Res);
718 return false;
719 }
720
721 /// If the value to convert is a vector that needs to be scalarized, it must be
722 /// <1 x ty>. Convert the element instead.
ScalarizeVecOp_BITCAST(SDNode * N)723 SDValue DAGTypeLegalizer::ScalarizeVecOp_BITCAST(SDNode *N) {
724 SDValue Elt = GetScalarizedVector(N->getOperand(0));
725 return DAG.getNode(ISD::BITCAST, SDLoc(N),
726 N->getValueType(0), Elt);
727 }
728
729 /// If the input is a vector that needs to be scalarized, it must be <1 x ty>.
730 /// Do the operation on the element instead.
ScalarizeVecOp_UnaryOp(SDNode * N)731 SDValue DAGTypeLegalizer::ScalarizeVecOp_UnaryOp(SDNode *N) {
732 assert(N->getValueType(0).getVectorNumElements() == 1 &&
733 "Unexpected vector type!");
734 SDValue Elt = GetScalarizedVector(N->getOperand(0));
735 SDValue Op = DAG.getNode(N->getOpcode(), SDLoc(N),
736 N->getValueType(0).getScalarType(), Elt);
737 // Revectorize the result so the types line up with what the uses of this
738 // expression expect.
739 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Op);
740 }
741
742 /// If the input is a vector that needs to be scalarized, it must be <1 x ty>.
743 /// Do the strict FP operation on the element instead.
ScalarizeVecOp_UnaryOp_StrictFP(SDNode * N)744 SDValue DAGTypeLegalizer::ScalarizeVecOp_UnaryOp_StrictFP(SDNode *N) {
745 assert(N->getValueType(0).getVectorNumElements() == 1 &&
746 "Unexpected vector type!");
747 SDValue Elt = GetScalarizedVector(N->getOperand(1));
748 SDValue Res = DAG.getNode(N->getOpcode(), SDLoc(N),
749 { N->getValueType(0).getScalarType(), MVT::Other },
750 { N->getOperand(0), Elt });
751 // Legalize the chain result - switch anything that used the old chain to
752 // use the new one.
753 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
754 // Revectorize the result so the types line up with what the uses of this
755 // expression expect.
756 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
757
758 // Do our own replacement and return SDValue() to tell the caller that we
759 // handled all replacements since caller can only handle a single result.
760 ReplaceValueWith(SDValue(N, 0), Res);
761 return SDValue();
762 }
763
764 /// The vectors to concatenate have length one - use a BUILD_VECTOR instead.
ScalarizeVecOp_CONCAT_VECTORS(SDNode * N)765 SDValue DAGTypeLegalizer::ScalarizeVecOp_CONCAT_VECTORS(SDNode *N) {
766 SmallVector<SDValue, 8> Ops(N->getNumOperands());
767 for (unsigned i = 0, e = N->getNumOperands(); i < e; ++i)
768 Ops[i] = GetScalarizedVector(N->getOperand(i));
769 return DAG.getBuildVector(N->getValueType(0), SDLoc(N), Ops);
770 }
771
772 /// If the input is a vector that needs to be scalarized, it must be <1 x ty>,
773 /// so just return the element, ignoring the index.
ScalarizeVecOp_EXTRACT_VECTOR_ELT(SDNode * N)774 SDValue DAGTypeLegalizer::ScalarizeVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
775 EVT VT = N->getValueType(0);
776 SDValue Res = GetScalarizedVector(N->getOperand(0));
777 if (Res.getValueType() != VT)
778 Res = VT.isFloatingPoint()
779 ? DAG.getNode(ISD::FP_EXTEND, SDLoc(N), VT, Res)
780 : DAG.getNode(ISD::ANY_EXTEND, SDLoc(N), VT, Res);
781 return Res;
782 }
783
784 /// If the input condition is a vector that needs to be scalarized, it must be
785 /// <1 x i1>, so just convert to a normal ISD::SELECT
786 /// (still with vector output type since that was acceptable if we got here).
ScalarizeVecOp_VSELECT(SDNode * N)787 SDValue DAGTypeLegalizer::ScalarizeVecOp_VSELECT(SDNode *N) {
788 SDValue ScalarCond = GetScalarizedVector(N->getOperand(0));
789 EVT VT = N->getValueType(0);
790
791 return DAG.getNode(ISD::SELECT, SDLoc(N), VT, ScalarCond, N->getOperand(1),
792 N->getOperand(2));
793 }
794
795 /// If the operand is a vector that needs to be scalarized then the
796 /// result must be v1i1, so just convert to a scalar SETCC and wrap
797 /// with a scalar_to_vector since the res type is legal if we got here
ScalarizeVecOp_VSETCC(SDNode * N)798 SDValue DAGTypeLegalizer::ScalarizeVecOp_VSETCC(SDNode *N) {
799 assert(N->getValueType(0).isVector() &&
800 N->getOperand(0).getValueType().isVector() &&
801 "Operand types must be vectors");
802 assert(N->getValueType(0) == MVT::v1i1 && "Expected v1i1 type");
803
804 EVT VT = N->getValueType(0);
805 SDValue LHS = GetScalarizedVector(N->getOperand(0));
806 SDValue RHS = GetScalarizedVector(N->getOperand(1));
807
808 EVT OpVT = N->getOperand(0).getValueType();
809 EVT NVT = VT.getVectorElementType();
810 SDLoc DL(N);
811 // Turn it into a scalar SETCC.
812 SDValue Res = DAG.getNode(ISD::SETCC, DL, MVT::i1, LHS, RHS,
813 N->getOperand(2));
814
815 // Vectors may have a different boolean contents to scalars. Promote the
816 // value appropriately.
817 ISD::NodeType ExtendCode =
818 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
819
820 Res = DAG.getNode(ExtendCode, DL, NVT, Res);
821
822 return DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, VT, Res);
823 }
824
825 /// If the value to store is a vector that needs to be scalarized, it must be
826 /// <1 x ty>. Just store the element.
ScalarizeVecOp_STORE(StoreSDNode * N,unsigned OpNo)827 SDValue DAGTypeLegalizer::ScalarizeVecOp_STORE(StoreSDNode *N, unsigned OpNo){
828 assert(N->isUnindexed() && "Indexed store of one-element vector?");
829 assert(OpNo == 1 && "Do not know how to scalarize this operand!");
830 SDLoc dl(N);
831
832 if (N->isTruncatingStore())
833 return DAG.getTruncStore(
834 N->getChain(), dl, GetScalarizedVector(N->getOperand(1)),
835 N->getBasePtr(), N->getPointerInfo(),
836 N->getMemoryVT().getVectorElementType(), N->getOriginalAlign(),
837 N->getMemOperand()->getFlags(), N->getAAInfo());
838
839 return DAG.getStore(N->getChain(), dl, GetScalarizedVector(N->getOperand(1)),
840 N->getBasePtr(), N->getPointerInfo(),
841 N->getOriginalAlign(), N->getMemOperand()->getFlags(),
842 N->getAAInfo());
843 }
844
845 /// If the value to round is a vector that needs to be scalarized, it must be
846 /// <1 x ty>. Convert the element instead.
ScalarizeVecOp_FP_ROUND(SDNode * N,unsigned OpNo)847 SDValue DAGTypeLegalizer::ScalarizeVecOp_FP_ROUND(SDNode *N, unsigned OpNo) {
848 assert(OpNo == 0 && "Wrong operand for scalarization!");
849 SDValue Elt = GetScalarizedVector(N->getOperand(0));
850 SDValue Res = DAG.getNode(ISD::FP_ROUND, SDLoc(N),
851 N->getValueType(0).getVectorElementType(), Elt,
852 N->getOperand(1));
853 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
854 }
855
ScalarizeVecOp_STRICT_FP_ROUND(SDNode * N,unsigned OpNo)856 SDValue DAGTypeLegalizer::ScalarizeVecOp_STRICT_FP_ROUND(SDNode *N,
857 unsigned OpNo) {
858 assert(OpNo == 1 && "Wrong operand for scalarization!");
859 SDValue Elt = GetScalarizedVector(N->getOperand(1));
860 SDValue Res = DAG.getNode(ISD::STRICT_FP_ROUND, SDLoc(N),
861 { N->getValueType(0).getVectorElementType(),
862 MVT::Other },
863 { N->getOperand(0), Elt, N->getOperand(2) });
864 // Legalize the chain result - switch anything that used the old chain to
865 // use the new one.
866 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
867
868 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
869
870 // Do our own replacement and return SDValue() to tell the caller that we
871 // handled all replacements since caller can only handle a single result.
872 ReplaceValueWith(SDValue(N, 0), Res);
873 return SDValue();
874 }
875
876 /// If the value to extend is a vector that needs to be scalarized, it must be
877 /// <1 x ty>. Convert the element instead.
ScalarizeVecOp_FP_EXTEND(SDNode * N)878 SDValue DAGTypeLegalizer::ScalarizeVecOp_FP_EXTEND(SDNode *N) {
879 SDValue Elt = GetScalarizedVector(N->getOperand(0));
880 SDValue Res = DAG.getNode(ISD::FP_EXTEND, SDLoc(N),
881 N->getValueType(0).getVectorElementType(), Elt);
882 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
883 }
884
885 /// If the value to extend is a vector that needs to be scalarized, it must be
886 /// <1 x ty>. Convert the element instead.
ScalarizeVecOp_STRICT_FP_EXTEND(SDNode * N)887 SDValue DAGTypeLegalizer::ScalarizeVecOp_STRICT_FP_EXTEND(SDNode *N) {
888 SDValue Elt = GetScalarizedVector(N->getOperand(1));
889 SDValue Res =
890 DAG.getNode(ISD::STRICT_FP_EXTEND, SDLoc(N),
891 {N->getValueType(0).getVectorElementType(), MVT::Other},
892 {N->getOperand(0), Elt});
893 // Legalize the chain result - switch anything that used the old chain to
894 // use the new one.
895 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
896
897 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
898
899 // Do our own replacement and return SDValue() to tell the caller that we
900 // handled all replacements since caller can only handle a single result.
901 ReplaceValueWith(SDValue(N, 0), Res);
902 return SDValue();
903 }
904
ScalarizeVecOp_VECREDUCE(SDNode * N)905 SDValue DAGTypeLegalizer::ScalarizeVecOp_VECREDUCE(SDNode *N) {
906 SDValue Res = GetScalarizedVector(N->getOperand(0));
907 // Result type may be wider than element type.
908 if (Res.getValueType() != N->getValueType(0))
909 Res = DAG.getNode(ISD::ANY_EXTEND, SDLoc(N), N->getValueType(0), Res);
910 return Res;
911 }
912
ScalarizeVecOp_VECREDUCE_SEQ(SDNode * N)913 SDValue DAGTypeLegalizer::ScalarizeVecOp_VECREDUCE_SEQ(SDNode *N) {
914 SDValue AccOp = N->getOperand(0);
915 SDValue VecOp = N->getOperand(1);
916
917 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(N->getOpcode());
918
919 SDValue Op = GetScalarizedVector(VecOp);
920 return DAG.getNode(BaseOpc, SDLoc(N), N->getValueType(0),
921 AccOp, Op, N->getFlags());
922 }
923
924 //===----------------------------------------------------------------------===//
925 // Result Vector Splitting
926 //===----------------------------------------------------------------------===//
927
928 /// This method is called when the specified result of the specified node is
929 /// found to need vector splitting. At this point, the node may also have
930 /// invalid operands or may have other results that need legalization, we just
931 /// know that (at least) one result needs vector splitting.
SplitVectorResult(SDNode * N,unsigned ResNo)932 void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
933 LLVM_DEBUG(dbgs() << "Split node result: "; N->dump(&DAG); dbgs() << "\n");
934 SDValue Lo, Hi;
935
936 // See if the target wants to custom expand this node.
937 if (CustomLowerNode(N, N->getValueType(ResNo), true))
938 return;
939
940 switch (N->getOpcode()) {
941 default:
942 #ifndef NDEBUG
943 dbgs() << "SplitVectorResult #" << ResNo << ": ";
944 N->dump(&DAG);
945 dbgs() << "\n";
946 #endif
947 report_fatal_error("Do not know how to split the result of this "
948 "operator!\n");
949
950 case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, ResNo, Lo, Hi); break;
951 case ISD::VSELECT:
952 case ISD::SELECT:
953 case ISD::VP_MERGE:
954 case ISD::VP_SELECT: SplitRes_Select(N, Lo, Hi); break;
955 case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break;
956 case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break;
957 case ISD::BITCAST: SplitVecRes_BITCAST(N, Lo, Hi); break;
958 case ISD::BUILD_VECTOR: SplitVecRes_BUILD_VECTOR(N, Lo, Hi); break;
959 case ISD::CONCAT_VECTORS: SplitVecRes_CONCAT_VECTORS(N, Lo, Hi); break;
960 case ISD::EXTRACT_SUBVECTOR: SplitVecRes_EXTRACT_SUBVECTOR(N, Lo, Hi); break;
961 case ISD::INSERT_SUBVECTOR: SplitVecRes_INSERT_SUBVECTOR(N, Lo, Hi); break;
962 case ISD::FPOWI: SplitVecRes_FPOWI(N, Lo, Hi); break;
963 case ISD::FCOPYSIGN: SplitVecRes_FCOPYSIGN(N, Lo, Hi); break;
964 case ISD::IS_FPCLASS: SplitVecRes_IS_FPCLASS(N, Lo, Hi); break;
965 case ISD::INSERT_VECTOR_ELT: SplitVecRes_INSERT_VECTOR_ELT(N, Lo, Hi); break;
966 case ISD::SPLAT_VECTOR:
967 case ISD::SCALAR_TO_VECTOR:
968 SplitVecRes_ScalarOp(N, Lo, Hi);
969 break;
970 case ISD::STEP_VECTOR:
971 SplitVecRes_STEP_VECTOR(N, Lo, Hi);
972 break;
973 case ISD::SIGN_EXTEND_INREG: SplitVecRes_InregOp(N, Lo, Hi); break;
974 case ISD::LOAD:
975 SplitVecRes_LOAD(cast<LoadSDNode>(N), Lo, Hi);
976 break;
977 case ISD::VP_LOAD:
978 SplitVecRes_VP_LOAD(cast<VPLoadSDNode>(N), Lo, Hi);
979 break;
980 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
981 SplitVecRes_VP_STRIDED_LOAD(cast<VPStridedLoadSDNode>(N), Lo, Hi);
982 break;
983 case ISD::MLOAD:
984 SplitVecRes_MLOAD(cast<MaskedLoadSDNode>(N), Lo, Hi);
985 break;
986 case ISD::MGATHER:
987 case ISD::VP_GATHER:
988 SplitVecRes_Gather(cast<MemSDNode>(N), Lo, Hi, /*SplitSETCC*/ true);
989 break;
990 case ISD::SETCC:
991 case ISD::VP_SETCC:
992 SplitVecRes_SETCC(N, Lo, Hi);
993 break;
994 case ISD::VECTOR_REVERSE:
995 SplitVecRes_VECTOR_REVERSE(N, Lo, Hi);
996 break;
997 case ISD::VECTOR_SHUFFLE:
998 SplitVecRes_VECTOR_SHUFFLE(cast<ShuffleVectorSDNode>(N), Lo, Hi);
999 break;
1000 case ISD::VECTOR_SPLICE:
1001 SplitVecRes_VECTOR_SPLICE(N, Lo, Hi);
1002 break;
1003 case ISD::VAARG:
1004 SplitVecRes_VAARG(N, Lo, Hi);
1005 break;
1006
1007 case ISD::ANY_EXTEND_VECTOR_INREG:
1008 case ISD::SIGN_EXTEND_VECTOR_INREG:
1009 case ISD::ZERO_EXTEND_VECTOR_INREG:
1010 SplitVecRes_ExtVecInRegOp(N, Lo, Hi);
1011 break;
1012
1013 case ISD::ABS:
1014 case ISD::VP_ABS:
1015 case ISD::BITREVERSE:
1016 case ISD::VP_BITREVERSE:
1017 case ISD::BSWAP:
1018 case ISD::VP_BSWAP:
1019 case ISD::CTLZ:
1020 case ISD::VP_CTLZ:
1021 case ISD::CTTZ:
1022 case ISD::VP_CTTZ:
1023 case ISD::CTLZ_ZERO_UNDEF:
1024 case ISD::VP_CTLZ_ZERO_UNDEF:
1025 case ISD::CTTZ_ZERO_UNDEF:
1026 case ISD::VP_CTTZ_ZERO_UNDEF:
1027 case ISD::CTPOP:
1028 case ISD::VP_CTPOP:
1029 case ISD::FABS: case ISD::VP_FABS:
1030 case ISD::FCEIL:
1031 case ISD::VP_FCEIL:
1032 case ISD::FCOS:
1033 case ISD::FEXP:
1034 case ISD::FEXP2:
1035 case ISD::FFLOOR:
1036 case ISD::VP_FFLOOR:
1037 case ISD::FLOG:
1038 case ISD::FLOG10:
1039 case ISD::FLOG2:
1040 case ISD::FNEARBYINT:
1041 case ISD::VP_FNEARBYINT:
1042 case ISD::FNEG: case ISD::VP_FNEG:
1043 case ISD::FREEZE:
1044 case ISD::ARITH_FENCE:
1045 case ISD::FP_EXTEND:
1046 case ISD::VP_FP_EXTEND:
1047 case ISD::FP_ROUND:
1048 case ISD::VP_FP_ROUND:
1049 case ISD::FP_TO_SINT:
1050 case ISD::VP_FP_TO_SINT:
1051 case ISD::FP_TO_UINT:
1052 case ISD::VP_FP_TO_UINT:
1053 case ISD::FRINT:
1054 case ISD::VP_FRINT:
1055 case ISD::FROUND:
1056 case ISD::VP_FROUND:
1057 case ISD::FROUNDEVEN:
1058 case ISD::VP_FROUNDEVEN:
1059 case ISD::FSIN:
1060 case ISD::FSQRT: case ISD::VP_SQRT:
1061 case ISD::FTRUNC:
1062 case ISD::VP_FROUNDTOZERO:
1063 case ISD::SINT_TO_FP:
1064 case ISD::VP_SINT_TO_FP:
1065 case ISD::TRUNCATE:
1066 case ISD::VP_TRUNCATE:
1067 case ISD::UINT_TO_FP:
1068 case ISD::VP_UINT_TO_FP:
1069 case ISD::FCANONICALIZE:
1070 SplitVecRes_UnaryOp(N, Lo, Hi);
1071 break;
1072
1073 case ISD::ANY_EXTEND:
1074 case ISD::SIGN_EXTEND:
1075 case ISD::ZERO_EXTEND:
1076 case ISD::VP_SIGN_EXTEND:
1077 case ISD::VP_ZERO_EXTEND:
1078 SplitVecRes_ExtendOp(N, Lo, Hi);
1079 break;
1080
1081 case ISD::ADD: case ISD::VP_ADD:
1082 case ISD::SUB: case ISD::VP_SUB:
1083 case ISD::MUL: case ISD::VP_MUL:
1084 case ISD::MULHS:
1085 case ISD::MULHU:
1086 case ISD::FADD: case ISD::VP_FADD:
1087 case ISD::FSUB: case ISD::VP_FSUB:
1088 case ISD::FMUL: case ISD::VP_FMUL:
1089 case ISD::FMINNUM: case ISD::VP_FMINNUM:
1090 case ISD::FMAXNUM: case ISD::VP_FMAXNUM:
1091 case ISD::FMINIMUM:
1092 case ISD::FMAXIMUM:
1093 case ISD::SDIV: case ISD::VP_SDIV:
1094 case ISD::UDIV: case ISD::VP_UDIV:
1095 case ISD::FDIV: case ISD::VP_FDIV:
1096 case ISD::FPOW:
1097 case ISD::AND: case ISD::VP_AND:
1098 case ISD::OR: case ISD::VP_OR:
1099 case ISD::XOR: case ISD::VP_XOR:
1100 case ISD::SHL: case ISD::VP_SHL:
1101 case ISD::SRA: case ISD::VP_ASHR:
1102 case ISD::SRL: case ISD::VP_LSHR:
1103 case ISD::UREM: case ISD::VP_UREM:
1104 case ISD::SREM: case ISD::VP_SREM:
1105 case ISD::FREM: case ISD::VP_FREM:
1106 case ISD::SMIN: case ISD::VP_SMIN:
1107 case ISD::SMAX: case ISD::VP_SMAX:
1108 case ISD::UMIN: case ISD::VP_UMIN:
1109 case ISD::UMAX: case ISD::VP_UMAX:
1110 case ISD::SADDSAT:
1111 case ISD::UADDSAT:
1112 case ISD::SSUBSAT:
1113 case ISD::USUBSAT:
1114 case ISD::SSHLSAT:
1115 case ISD::USHLSAT:
1116 case ISD::ROTL:
1117 case ISD::ROTR:
1118 case ISD::VP_FCOPYSIGN:
1119 SplitVecRes_BinOp(N, Lo, Hi);
1120 break;
1121 case ISD::FMA: case ISD::VP_FMA:
1122 case ISD::FSHL:
1123 case ISD::VP_FSHL:
1124 case ISD::FSHR:
1125 case ISD::VP_FSHR:
1126 SplitVecRes_TernaryOp(N, Lo, Hi);
1127 break;
1128
1129 #define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
1130 case ISD::STRICT_##DAGN:
1131 #include "llvm/IR/ConstrainedOps.def"
1132 SplitVecRes_StrictFPOp(N, Lo, Hi);
1133 break;
1134
1135 case ISD::FP_TO_UINT_SAT:
1136 case ISD::FP_TO_SINT_SAT:
1137 SplitVecRes_FP_TO_XINT_SAT(N, Lo, Hi);
1138 break;
1139
1140 case ISD::UADDO:
1141 case ISD::SADDO:
1142 case ISD::USUBO:
1143 case ISD::SSUBO:
1144 case ISD::UMULO:
1145 case ISD::SMULO:
1146 SplitVecRes_OverflowOp(N, ResNo, Lo, Hi);
1147 break;
1148 case ISD::SMULFIX:
1149 case ISD::SMULFIXSAT:
1150 case ISD::UMULFIX:
1151 case ISD::UMULFIXSAT:
1152 case ISD::SDIVFIX:
1153 case ISD::SDIVFIXSAT:
1154 case ISD::UDIVFIX:
1155 case ISD::UDIVFIXSAT:
1156 SplitVecRes_FIX(N, Lo, Hi);
1157 break;
1158 }
1159
1160 // If Lo/Hi is null, the sub-method took care of registering results etc.
1161 if (Lo.getNode())
1162 SetSplitVector(SDValue(N, ResNo), Lo, Hi);
1163 }
1164
IncrementPointer(MemSDNode * N,EVT MemVT,MachinePointerInfo & MPI,SDValue & Ptr,uint64_t * ScaledOffset)1165 void DAGTypeLegalizer::IncrementPointer(MemSDNode *N, EVT MemVT,
1166 MachinePointerInfo &MPI, SDValue &Ptr,
1167 uint64_t *ScaledOffset) {
1168 SDLoc DL(N);
1169 unsigned IncrementSize = MemVT.getSizeInBits().getKnownMinValue() / 8;
1170
1171 if (MemVT.isScalableVector()) {
1172 SDNodeFlags Flags;
1173 SDValue BytesIncrement = DAG.getVScale(
1174 DL, Ptr.getValueType(),
1175 APInt(Ptr.getValueSizeInBits().getFixedValue(), IncrementSize));
1176 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
1177 Flags.setNoUnsignedWrap(true);
1178 if (ScaledOffset)
1179 *ScaledOffset += IncrementSize;
1180 Ptr = DAG.getNode(ISD::ADD, DL, Ptr.getValueType(), Ptr, BytesIncrement,
1181 Flags);
1182 } else {
1183 MPI = N->getPointerInfo().getWithOffset(IncrementSize);
1184 // Increment the pointer to the other half.
1185 Ptr = DAG.getObjectPtrOffset(DL, Ptr, TypeSize::Fixed(IncrementSize));
1186 }
1187 }
1188
SplitMask(SDValue Mask)1189 std::pair<SDValue, SDValue> DAGTypeLegalizer::SplitMask(SDValue Mask) {
1190 return SplitMask(Mask, SDLoc(Mask));
1191 }
1192
SplitMask(SDValue Mask,const SDLoc & DL)1193 std::pair<SDValue, SDValue> DAGTypeLegalizer::SplitMask(SDValue Mask,
1194 const SDLoc &DL) {
1195 SDValue MaskLo, MaskHi;
1196 EVT MaskVT = Mask.getValueType();
1197 if (getTypeAction(MaskVT) == TargetLowering::TypeSplitVector)
1198 GetSplitVector(Mask, MaskLo, MaskHi);
1199 else
1200 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
1201 return std::make_pair(MaskLo, MaskHi);
1202 }
1203
SplitVecRes_BinOp(SDNode * N,SDValue & Lo,SDValue & Hi)1204 void DAGTypeLegalizer::SplitVecRes_BinOp(SDNode *N, SDValue &Lo, SDValue &Hi) {
1205 SDValue LHSLo, LHSHi;
1206 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1207 SDValue RHSLo, RHSHi;
1208 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
1209 SDLoc dl(N);
1210
1211 const SDNodeFlags Flags = N->getFlags();
1212 unsigned Opcode = N->getOpcode();
1213 if (N->getNumOperands() == 2) {
1214 Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(), LHSLo, RHSLo, Flags);
1215 Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(), LHSHi, RHSHi, Flags);
1216 return;
1217 }
1218
1219 assert(N->getNumOperands() == 4 && "Unexpected number of operands!");
1220 assert(N->isVPOpcode() && "Expected VP opcode");
1221
1222 SDValue MaskLo, MaskHi;
1223 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(2));
1224
1225 SDValue EVLLo, EVLHi;
1226 std::tie(EVLLo, EVLHi) =
1227 DAG.SplitEVL(N->getOperand(3), N->getValueType(0), dl);
1228
1229 Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(),
1230 {LHSLo, RHSLo, MaskLo, EVLLo}, Flags);
1231 Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(),
1232 {LHSHi, RHSHi, MaskHi, EVLHi}, Flags);
1233 }
1234
SplitVecRes_TernaryOp(SDNode * N,SDValue & Lo,SDValue & Hi)1235 void DAGTypeLegalizer::SplitVecRes_TernaryOp(SDNode *N, SDValue &Lo,
1236 SDValue &Hi) {
1237 SDValue Op0Lo, Op0Hi;
1238 GetSplitVector(N->getOperand(0), Op0Lo, Op0Hi);
1239 SDValue Op1Lo, Op1Hi;
1240 GetSplitVector(N->getOperand(1), Op1Lo, Op1Hi);
1241 SDValue Op2Lo, Op2Hi;
1242 GetSplitVector(N->getOperand(2), Op2Lo, Op2Hi);
1243 SDLoc dl(N);
1244
1245 const SDNodeFlags Flags = N->getFlags();
1246 unsigned Opcode = N->getOpcode();
1247 if (N->getNumOperands() == 3) {
1248 Lo = DAG.getNode(Opcode, dl, Op0Lo.getValueType(), Op0Lo, Op1Lo, Op2Lo, Flags);
1249 Hi = DAG.getNode(Opcode, dl, Op0Hi.getValueType(), Op0Hi, Op1Hi, Op2Hi, Flags);
1250 return;
1251 }
1252
1253 assert(N->getNumOperands() == 5 && "Unexpected number of operands!");
1254 assert(N->isVPOpcode() && "Expected VP opcode");
1255
1256 SDValue MaskLo, MaskHi;
1257 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(3));
1258
1259 SDValue EVLLo, EVLHi;
1260 std::tie(EVLLo, EVLHi) =
1261 DAG.SplitEVL(N->getOperand(4), N->getValueType(0), dl);
1262
1263 Lo = DAG.getNode(Opcode, dl, Op0Lo.getValueType(),
1264 {Op0Lo, Op1Lo, Op2Lo, MaskLo, EVLLo}, Flags);
1265 Hi = DAG.getNode(Opcode, dl, Op0Hi.getValueType(),
1266 {Op0Hi, Op1Hi, Op2Hi, MaskHi, EVLHi}, Flags);
1267 }
1268
SplitVecRes_FIX(SDNode * N,SDValue & Lo,SDValue & Hi)1269 void DAGTypeLegalizer::SplitVecRes_FIX(SDNode *N, SDValue &Lo, SDValue &Hi) {
1270 SDValue LHSLo, LHSHi;
1271 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1272 SDValue RHSLo, RHSHi;
1273 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
1274 SDLoc dl(N);
1275 SDValue Op2 = N->getOperand(2);
1276
1277 unsigned Opcode = N->getOpcode();
1278 Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(), LHSLo, RHSLo, Op2,
1279 N->getFlags());
1280 Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(), LHSHi, RHSHi, Op2,
1281 N->getFlags());
1282 }
1283
SplitVecRes_BITCAST(SDNode * N,SDValue & Lo,SDValue & Hi)1284 void DAGTypeLegalizer::SplitVecRes_BITCAST(SDNode *N, SDValue &Lo,
1285 SDValue &Hi) {
1286 // We know the result is a vector. The input may be either a vector or a
1287 // scalar value.
1288 EVT LoVT, HiVT;
1289 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1290 SDLoc dl(N);
1291
1292 SDValue InOp = N->getOperand(0);
1293 EVT InVT = InOp.getValueType();
1294
1295 // Handle some special cases efficiently.
1296 switch (getTypeAction(InVT)) {
1297 case TargetLowering::TypeLegal:
1298 case TargetLowering::TypePromoteInteger:
1299 case TargetLowering::TypePromoteFloat:
1300 case TargetLowering::TypeSoftPromoteHalf:
1301 case TargetLowering::TypeSoftenFloat:
1302 case TargetLowering::TypeScalarizeVector:
1303 case TargetLowering::TypeWidenVector:
1304 break;
1305 case TargetLowering::TypeExpandInteger:
1306 case TargetLowering::TypeExpandFloat:
1307 // A scalar to vector conversion, where the scalar needs expansion.
1308 // If the vector is being split in two then we can just convert the
1309 // expanded pieces.
1310 if (LoVT == HiVT) {
1311 GetExpandedOp(InOp, Lo, Hi);
1312 if (DAG.getDataLayout().isBigEndian())
1313 std::swap(Lo, Hi);
1314 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
1315 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
1316 return;
1317 }
1318 break;
1319 case TargetLowering::TypeSplitVector:
1320 // If the input is a vector that needs to be split, convert each split
1321 // piece of the input now.
1322 GetSplitVector(InOp, Lo, Hi);
1323 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
1324 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
1325 return;
1326 case TargetLowering::TypeScalarizeScalableVector:
1327 report_fatal_error("Scalarization of scalable vectors is not supported.");
1328 }
1329
1330 // In the general case, convert the input to an integer and split it by hand.
1331 EVT LoIntVT = EVT::getIntegerVT(*DAG.getContext(), LoVT.getSizeInBits());
1332 EVT HiIntVT = EVT::getIntegerVT(*DAG.getContext(), HiVT.getSizeInBits());
1333 if (DAG.getDataLayout().isBigEndian())
1334 std::swap(LoIntVT, HiIntVT);
1335
1336 SplitInteger(BitConvertToInteger(InOp), LoIntVT, HiIntVT, Lo, Hi);
1337
1338 if (DAG.getDataLayout().isBigEndian())
1339 std::swap(Lo, Hi);
1340 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
1341 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
1342 }
1343
SplitVecRes_BUILD_VECTOR(SDNode * N,SDValue & Lo,SDValue & Hi)1344 void DAGTypeLegalizer::SplitVecRes_BUILD_VECTOR(SDNode *N, SDValue &Lo,
1345 SDValue &Hi) {
1346 EVT LoVT, HiVT;
1347 SDLoc dl(N);
1348 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1349 unsigned LoNumElts = LoVT.getVectorNumElements();
1350 SmallVector<SDValue, 8> LoOps(N->op_begin(), N->op_begin()+LoNumElts);
1351 Lo = DAG.getBuildVector(LoVT, dl, LoOps);
1352
1353 SmallVector<SDValue, 8> HiOps(N->op_begin()+LoNumElts, N->op_end());
1354 Hi = DAG.getBuildVector(HiVT, dl, HiOps);
1355 }
1356
SplitVecRes_CONCAT_VECTORS(SDNode * N,SDValue & Lo,SDValue & Hi)1357 void DAGTypeLegalizer::SplitVecRes_CONCAT_VECTORS(SDNode *N, SDValue &Lo,
1358 SDValue &Hi) {
1359 assert(!(N->getNumOperands() & 1) && "Unsupported CONCAT_VECTORS");
1360 SDLoc dl(N);
1361 unsigned NumSubvectors = N->getNumOperands() / 2;
1362 if (NumSubvectors == 1) {
1363 Lo = N->getOperand(0);
1364 Hi = N->getOperand(1);
1365 return;
1366 }
1367
1368 EVT LoVT, HiVT;
1369 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1370
1371 SmallVector<SDValue, 8> LoOps(N->op_begin(), N->op_begin()+NumSubvectors);
1372 Lo = DAG.getNode(ISD::CONCAT_VECTORS, dl, LoVT, LoOps);
1373
1374 SmallVector<SDValue, 8> HiOps(N->op_begin()+NumSubvectors, N->op_end());
1375 Hi = DAG.getNode(ISD::CONCAT_VECTORS, dl, HiVT, HiOps);
1376 }
1377
SplitVecRes_EXTRACT_SUBVECTOR(SDNode * N,SDValue & Lo,SDValue & Hi)1378 void DAGTypeLegalizer::SplitVecRes_EXTRACT_SUBVECTOR(SDNode *N, SDValue &Lo,
1379 SDValue &Hi) {
1380 SDValue Vec = N->getOperand(0);
1381 SDValue Idx = N->getOperand(1);
1382 SDLoc dl(N);
1383
1384 EVT LoVT, HiVT;
1385 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1386
1387 Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, LoVT, Vec, Idx);
1388 uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getZExtValue();
1389 Hi = DAG.getNode(
1390 ISD::EXTRACT_SUBVECTOR, dl, HiVT, Vec,
1391 DAG.getVectorIdxConstant(IdxVal + LoVT.getVectorMinNumElements(), dl));
1392 }
1393
SplitVecRes_INSERT_SUBVECTOR(SDNode * N,SDValue & Lo,SDValue & Hi)1394 void DAGTypeLegalizer::SplitVecRes_INSERT_SUBVECTOR(SDNode *N, SDValue &Lo,
1395 SDValue &Hi) {
1396 SDValue Vec = N->getOperand(0);
1397 SDValue SubVec = N->getOperand(1);
1398 SDValue Idx = N->getOperand(2);
1399 SDLoc dl(N);
1400 GetSplitVector(Vec, Lo, Hi);
1401
1402 EVT VecVT = Vec.getValueType();
1403 EVT LoVT = Lo.getValueType();
1404 EVT SubVecVT = SubVec.getValueType();
1405 unsigned VecElems = VecVT.getVectorMinNumElements();
1406 unsigned SubElems = SubVecVT.getVectorMinNumElements();
1407 unsigned LoElems = LoVT.getVectorMinNumElements();
1408
1409 // If we know the index is in the first half, and we know the subvector
1410 // doesn't cross the boundary between the halves, we can avoid spilling the
1411 // vector, and insert into the lower half of the split vector directly.
1412 unsigned IdxVal = cast<ConstantSDNode>(Idx)->getZExtValue();
1413 if (IdxVal + SubElems <= LoElems) {
1414 Lo = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, LoVT, Lo, SubVec, Idx);
1415 return;
1416 }
1417 // Similarly if the subvector is fully in the high half, but mind that we
1418 // can't tell whether a fixed-length subvector is fully within the high half
1419 // of a scalable vector.
1420 if (VecVT.isScalableVector() == SubVecVT.isScalableVector() &&
1421 IdxVal >= LoElems && IdxVal + SubElems <= VecElems) {
1422 Hi = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, Hi.getValueType(), Hi, SubVec,
1423 DAG.getVectorIdxConstant(IdxVal - LoElems, dl));
1424 return;
1425 }
1426
1427 // Spill the vector to the stack.
1428 // In cases where the vector is illegal it will be broken down into parts
1429 // and stored in parts - we should use the alignment for the smallest part.
1430 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
1431 SDValue StackPtr =
1432 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
1433 auto &MF = DAG.getMachineFunction();
1434 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
1435 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
1436
1437 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
1438 SmallestAlign);
1439
1440 // Store the new subvector into the specified index.
1441 SDValue SubVecPtr =
1442 TLI.getVectorSubVecPointer(DAG, StackPtr, VecVT, SubVecVT, Idx);
1443 Store = DAG.getStore(Store, dl, SubVec, SubVecPtr,
1444 MachinePointerInfo::getUnknownStack(MF));
1445
1446 // Load the Lo part from the stack slot.
1447 Lo = DAG.getLoad(Lo.getValueType(), dl, Store, StackPtr, PtrInfo,
1448 SmallestAlign);
1449
1450 // Increment the pointer to the other part.
1451 auto *Load = cast<LoadSDNode>(Lo);
1452 MachinePointerInfo MPI = Load->getPointerInfo();
1453 IncrementPointer(Load, LoVT, MPI, StackPtr);
1454
1455 // Load the Hi part from the stack slot.
1456 Hi = DAG.getLoad(Hi.getValueType(), dl, Store, StackPtr, MPI, SmallestAlign);
1457 }
1458
SplitVecRes_FPOWI(SDNode * N,SDValue & Lo,SDValue & Hi)1459 void DAGTypeLegalizer::SplitVecRes_FPOWI(SDNode *N, SDValue &Lo,
1460 SDValue &Hi) {
1461 SDLoc dl(N);
1462 GetSplitVector(N->getOperand(0), Lo, Hi);
1463 Lo = DAG.getNode(ISD::FPOWI, dl, Lo.getValueType(), Lo, N->getOperand(1));
1464 Hi = DAG.getNode(ISD::FPOWI, dl, Hi.getValueType(), Hi, N->getOperand(1));
1465 }
1466
SplitVecRes_FCOPYSIGN(SDNode * N,SDValue & Lo,SDValue & Hi)1467 void DAGTypeLegalizer::SplitVecRes_FCOPYSIGN(SDNode *N, SDValue &Lo,
1468 SDValue &Hi) {
1469 SDValue LHSLo, LHSHi;
1470 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1471 SDLoc DL(N);
1472
1473 SDValue RHSLo, RHSHi;
1474 SDValue RHS = N->getOperand(1);
1475 EVT RHSVT = RHS.getValueType();
1476 if (getTypeAction(RHSVT) == TargetLowering::TypeSplitVector)
1477 GetSplitVector(RHS, RHSLo, RHSHi);
1478 else
1479 std::tie(RHSLo, RHSHi) = DAG.SplitVector(RHS, SDLoc(RHS));
1480
1481
1482 Lo = DAG.getNode(ISD::FCOPYSIGN, DL, LHSLo.getValueType(), LHSLo, RHSLo);
1483 Hi = DAG.getNode(ISD::FCOPYSIGN, DL, LHSHi.getValueType(), LHSHi, RHSHi);
1484 }
1485
SplitVecRes_IS_FPCLASS(SDNode * N,SDValue & Lo,SDValue & Hi)1486 void DAGTypeLegalizer::SplitVecRes_IS_FPCLASS(SDNode *N, SDValue &Lo,
1487 SDValue &Hi) {
1488 SDLoc DL(N);
1489 SDValue ArgLo, ArgHi;
1490 SDValue Test = N->getOperand(1);
1491 SDValue FpValue = N->getOperand(0);
1492 if (getTypeAction(FpValue.getValueType()) == TargetLowering::TypeSplitVector)
1493 GetSplitVector(FpValue, ArgLo, ArgHi);
1494 else
1495 std::tie(ArgLo, ArgHi) = DAG.SplitVector(FpValue, SDLoc(FpValue));
1496 EVT LoVT, HiVT;
1497 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1498
1499 Lo = DAG.getNode(ISD::IS_FPCLASS, DL, LoVT, ArgLo, Test, N->getFlags());
1500 Hi = DAG.getNode(ISD::IS_FPCLASS, DL, HiVT, ArgHi, Test, N->getFlags());
1501 }
1502
SplitVecRes_InregOp(SDNode * N,SDValue & Lo,SDValue & Hi)1503 void DAGTypeLegalizer::SplitVecRes_InregOp(SDNode *N, SDValue &Lo,
1504 SDValue &Hi) {
1505 SDValue LHSLo, LHSHi;
1506 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1507 SDLoc dl(N);
1508
1509 EVT LoVT, HiVT;
1510 std::tie(LoVT, HiVT) =
1511 DAG.GetSplitDestVTs(cast<VTSDNode>(N->getOperand(1))->getVT());
1512
1513 Lo = DAG.getNode(N->getOpcode(), dl, LHSLo.getValueType(), LHSLo,
1514 DAG.getValueType(LoVT));
1515 Hi = DAG.getNode(N->getOpcode(), dl, LHSHi.getValueType(), LHSHi,
1516 DAG.getValueType(HiVT));
1517 }
1518
SplitVecRes_ExtVecInRegOp(SDNode * N,SDValue & Lo,SDValue & Hi)1519 void DAGTypeLegalizer::SplitVecRes_ExtVecInRegOp(SDNode *N, SDValue &Lo,
1520 SDValue &Hi) {
1521 unsigned Opcode = N->getOpcode();
1522 SDValue N0 = N->getOperand(0);
1523
1524 SDLoc dl(N);
1525 SDValue InLo, InHi;
1526
1527 if (getTypeAction(N0.getValueType()) == TargetLowering::TypeSplitVector)
1528 GetSplitVector(N0, InLo, InHi);
1529 else
1530 std::tie(InLo, InHi) = DAG.SplitVectorOperand(N, 0);
1531
1532 EVT InLoVT = InLo.getValueType();
1533 unsigned InNumElements = InLoVT.getVectorNumElements();
1534
1535 EVT OutLoVT, OutHiVT;
1536 std::tie(OutLoVT, OutHiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1537 unsigned OutNumElements = OutLoVT.getVectorNumElements();
1538 assert((2 * OutNumElements) <= InNumElements &&
1539 "Illegal extend vector in reg split");
1540
1541 // *_EXTEND_VECTOR_INREG instructions extend the lowest elements of the
1542 // input vector (i.e. we only use InLo):
1543 // OutLo will extend the first OutNumElements from InLo.
1544 // OutHi will extend the next OutNumElements from InLo.
1545
1546 // Shuffle the elements from InLo for OutHi into the bottom elements to
1547 // create a 'fake' InHi.
1548 SmallVector<int, 8> SplitHi(InNumElements, -1);
1549 for (unsigned i = 0; i != OutNumElements; ++i)
1550 SplitHi[i] = i + OutNumElements;
1551 InHi = DAG.getVectorShuffle(InLoVT, dl, InLo, DAG.getUNDEF(InLoVT), SplitHi);
1552
1553 Lo = DAG.getNode(Opcode, dl, OutLoVT, InLo);
1554 Hi = DAG.getNode(Opcode, dl, OutHiVT, InHi);
1555 }
1556
SplitVecRes_StrictFPOp(SDNode * N,SDValue & Lo,SDValue & Hi)1557 void DAGTypeLegalizer::SplitVecRes_StrictFPOp(SDNode *N, SDValue &Lo,
1558 SDValue &Hi) {
1559 unsigned NumOps = N->getNumOperands();
1560 SDValue Chain = N->getOperand(0);
1561 EVT LoVT, HiVT;
1562 SDLoc dl(N);
1563 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1564
1565 SmallVector<SDValue, 4> OpsLo(NumOps);
1566 SmallVector<SDValue, 4> OpsHi(NumOps);
1567
1568 // The Chain is the first operand.
1569 OpsLo[0] = Chain;
1570 OpsHi[0] = Chain;
1571
1572 // Now process the remaining operands.
1573 for (unsigned i = 1; i < NumOps; ++i) {
1574 SDValue Op = N->getOperand(i);
1575 SDValue OpLo = Op;
1576 SDValue OpHi = Op;
1577
1578 EVT InVT = Op.getValueType();
1579 if (InVT.isVector()) {
1580 // If the input also splits, handle it directly for a
1581 // compile time speedup. Otherwise split it by hand.
1582 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
1583 GetSplitVector(Op, OpLo, OpHi);
1584 else
1585 std::tie(OpLo, OpHi) = DAG.SplitVectorOperand(N, i);
1586 }
1587
1588 OpsLo[i] = OpLo;
1589 OpsHi[i] = OpHi;
1590 }
1591
1592 EVT LoValueVTs[] = {LoVT, MVT::Other};
1593 EVT HiValueVTs[] = {HiVT, MVT::Other};
1594 Lo = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(LoValueVTs), OpsLo,
1595 N->getFlags());
1596 Hi = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(HiValueVTs), OpsHi,
1597 N->getFlags());
1598
1599 // Build a factor node to remember that this Op is independent of the
1600 // other one.
1601 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
1602 Lo.getValue(1), Hi.getValue(1));
1603
1604 // Legalize the chain result - switch anything that used the old chain to
1605 // use the new one.
1606 ReplaceValueWith(SDValue(N, 1), Chain);
1607 }
1608
UnrollVectorOp_StrictFP(SDNode * N,unsigned ResNE)1609 SDValue DAGTypeLegalizer::UnrollVectorOp_StrictFP(SDNode *N, unsigned ResNE) {
1610 SDValue Chain = N->getOperand(0);
1611 EVT VT = N->getValueType(0);
1612 unsigned NE = VT.getVectorNumElements();
1613 EVT EltVT = VT.getVectorElementType();
1614 SDLoc dl(N);
1615
1616 SmallVector<SDValue, 8> Scalars;
1617 SmallVector<SDValue, 4> Operands(N->getNumOperands());
1618
1619 // If ResNE is 0, fully unroll the vector op.
1620 if (ResNE == 0)
1621 ResNE = NE;
1622 else if (NE > ResNE)
1623 NE = ResNE;
1624
1625 //The results of each unrolled operation, including the chain.
1626 EVT ChainVTs[] = {EltVT, MVT::Other};
1627 SmallVector<SDValue, 8> Chains;
1628
1629 unsigned i;
1630 for (i = 0; i != NE; ++i) {
1631 Operands[0] = Chain;
1632 for (unsigned j = 1, e = N->getNumOperands(); j != e; ++j) {
1633 SDValue Operand = N->getOperand(j);
1634 EVT OperandVT = Operand.getValueType();
1635 if (OperandVT.isVector()) {
1636 EVT OperandEltVT = OperandVT.getVectorElementType();
1637 Operands[j] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, OperandEltVT,
1638 Operand, DAG.getVectorIdxConstant(i, dl));
1639 } else {
1640 Operands[j] = Operand;
1641 }
1642 }
1643 SDValue Scalar = DAG.getNode(N->getOpcode(), dl, ChainVTs, Operands);
1644 Scalar.getNode()->setFlags(N->getFlags());
1645
1646 //Add in the scalar as well as its chain value to the
1647 //result vectors.
1648 Scalars.push_back(Scalar);
1649 Chains.push_back(Scalar.getValue(1));
1650 }
1651
1652 for (; i < ResNE; ++i)
1653 Scalars.push_back(DAG.getUNDEF(EltVT));
1654
1655 // Build a new factor node to connect the chain back together.
1656 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
1657 ReplaceValueWith(SDValue(N, 1), Chain);
1658
1659 // Create a new BUILD_VECTOR node
1660 EVT VecVT = EVT::getVectorVT(*DAG.getContext(), EltVT, ResNE);
1661 return DAG.getBuildVector(VecVT, dl, Scalars);
1662 }
1663
SplitVecRes_OverflowOp(SDNode * N,unsigned ResNo,SDValue & Lo,SDValue & Hi)1664 void DAGTypeLegalizer::SplitVecRes_OverflowOp(SDNode *N, unsigned ResNo,
1665 SDValue &Lo, SDValue &Hi) {
1666 SDLoc dl(N);
1667 EVT ResVT = N->getValueType(0);
1668 EVT OvVT = N->getValueType(1);
1669 EVT LoResVT, HiResVT, LoOvVT, HiOvVT;
1670 std::tie(LoResVT, HiResVT) = DAG.GetSplitDestVTs(ResVT);
1671 std::tie(LoOvVT, HiOvVT) = DAG.GetSplitDestVTs(OvVT);
1672
1673 SDValue LoLHS, HiLHS, LoRHS, HiRHS;
1674 if (getTypeAction(ResVT) == TargetLowering::TypeSplitVector) {
1675 GetSplitVector(N->getOperand(0), LoLHS, HiLHS);
1676 GetSplitVector(N->getOperand(1), LoRHS, HiRHS);
1677 } else {
1678 std::tie(LoLHS, HiLHS) = DAG.SplitVectorOperand(N, 0);
1679 std::tie(LoRHS, HiRHS) = DAG.SplitVectorOperand(N, 1);
1680 }
1681
1682 unsigned Opcode = N->getOpcode();
1683 SDVTList LoVTs = DAG.getVTList(LoResVT, LoOvVT);
1684 SDVTList HiVTs = DAG.getVTList(HiResVT, HiOvVT);
1685 SDNode *LoNode = DAG.getNode(Opcode, dl, LoVTs, LoLHS, LoRHS).getNode();
1686 SDNode *HiNode = DAG.getNode(Opcode, dl, HiVTs, HiLHS, HiRHS).getNode();
1687 LoNode->setFlags(N->getFlags());
1688 HiNode->setFlags(N->getFlags());
1689
1690 Lo = SDValue(LoNode, ResNo);
1691 Hi = SDValue(HiNode, ResNo);
1692
1693 // Replace the other vector result not being explicitly split here.
1694 unsigned OtherNo = 1 - ResNo;
1695 EVT OtherVT = N->getValueType(OtherNo);
1696 if (getTypeAction(OtherVT) == TargetLowering::TypeSplitVector) {
1697 SetSplitVector(SDValue(N, OtherNo),
1698 SDValue(LoNode, OtherNo), SDValue(HiNode, OtherNo));
1699 } else {
1700 SDValue OtherVal = DAG.getNode(
1701 ISD::CONCAT_VECTORS, dl, OtherVT,
1702 SDValue(LoNode, OtherNo), SDValue(HiNode, OtherNo));
1703 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
1704 }
1705 }
1706
SplitVecRes_INSERT_VECTOR_ELT(SDNode * N,SDValue & Lo,SDValue & Hi)1707 void DAGTypeLegalizer::SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo,
1708 SDValue &Hi) {
1709 SDValue Vec = N->getOperand(0);
1710 SDValue Elt = N->getOperand(1);
1711 SDValue Idx = N->getOperand(2);
1712 SDLoc dl(N);
1713 GetSplitVector(Vec, Lo, Hi);
1714
1715 if (ConstantSDNode *CIdx = dyn_cast<ConstantSDNode>(Idx)) {
1716 unsigned IdxVal = CIdx->getZExtValue();
1717 unsigned LoNumElts = Lo.getValueType().getVectorMinNumElements();
1718 if (IdxVal < LoNumElts) {
1719 Lo = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl,
1720 Lo.getValueType(), Lo, Elt, Idx);
1721 return;
1722 } else if (!Vec.getValueType().isScalableVector()) {
1723 Hi = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, Hi.getValueType(), Hi, Elt,
1724 DAG.getVectorIdxConstant(IdxVal - LoNumElts, dl));
1725 return;
1726 }
1727 }
1728
1729 // See if the target wants to custom expand this node.
1730 if (CustomLowerNode(N, N->getValueType(0), true))
1731 return;
1732
1733 // Make the vector elements byte-addressable if they aren't already.
1734 EVT VecVT = Vec.getValueType();
1735 EVT EltVT = VecVT.getVectorElementType();
1736 if (VecVT.getScalarSizeInBits() < 8) {
1737 EltVT = MVT::i8;
1738 VecVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
1739 VecVT.getVectorElementCount());
1740 Vec = DAG.getNode(ISD::ANY_EXTEND, dl, VecVT, Vec);
1741 // Extend the element type to match if needed.
1742 if (EltVT.bitsGT(Elt.getValueType()))
1743 Elt = DAG.getNode(ISD::ANY_EXTEND, dl, EltVT, Elt);
1744 }
1745
1746 // Spill the vector to the stack.
1747 // In cases where the vector is illegal it will be broken down into parts
1748 // and stored in parts - we should use the alignment for the smallest part.
1749 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
1750 SDValue StackPtr =
1751 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
1752 auto &MF = DAG.getMachineFunction();
1753 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
1754 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
1755
1756 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
1757 SmallestAlign);
1758
1759 // Store the new element. This may be larger than the vector element type,
1760 // so use a truncating store.
1761 SDValue EltPtr = TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Idx);
1762 Store = DAG.getTruncStore(
1763 Store, dl, Elt, EltPtr, MachinePointerInfo::getUnknownStack(MF), EltVT,
1764 commonAlignment(SmallestAlign,
1765 EltVT.getFixedSizeInBits() / 8));
1766
1767 EVT LoVT, HiVT;
1768 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(VecVT);
1769
1770 // Load the Lo part from the stack slot.
1771 Lo = DAG.getLoad(LoVT, dl, Store, StackPtr, PtrInfo, SmallestAlign);
1772
1773 // Increment the pointer to the other part.
1774 auto Load = cast<LoadSDNode>(Lo);
1775 MachinePointerInfo MPI = Load->getPointerInfo();
1776 IncrementPointer(Load, LoVT, MPI, StackPtr);
1777
1778 Hi = DAG.getLoad(HiVT, dl, Store, StackPtr, MPI, SmallestAlign);
1779
1780 // If we adjusted the original type, we need to truncate the results.
1781 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1782 if (LoVT != Lo.getValueType())
1783 Lo = DAG.getNode(ISD::TRUNCATE, dl, LoVT, Lo);
1784 if (HiVT != Hi.getValueType())
1785 Hi = DAG.getNode(ISD::TRUNCATE, dl, HiVT, Hi);
1786 }
1787
SplitVecRes_STEP_VECTOR(SDNode * N,SDValue & Lo,SDValue & Hi)1788 void DAGTypeLegalizer::SplitVecRes_STEP_VECTOR(SDNode *N, SDValue &Lo,
1789 SDValue &Hi) {
1790 EVT LoVT, HiVT;
1791 SDLoc dl(N);
1792 assert(N->getValueType(0).isScalableVector() &&
1793 "Only scalable vectors are supported for STEP_VECTOR");
1794 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1795 SDValue Step = N->getOperand(0);
1796
1797 Lo = DAG.getNode(ISD::STEP_VECTOR, dl, LoVT, Step);
1798
1799 // Hi = Lo + (EltCnt * Step)
1800 EVT EltVT = Step.getValueType();
1801 APInt StepVal = cast<ConstantSDNode>(Step)->getAPIntValue();
1802 SDValue StartOfHi =
1803 DAG.getVScale(dl, EltVT, StepVal * LoVT.getVectorMinNumElements());
1804 StartOfHi = DAG.getSExtOrTrunc(StartOfHi, dl, HiVT.getVectorElementType());
1805 StartOfHi = DAG.getNode(ISD::SPLAT_VECTOR, dl, HiVT, StartOfHi);
1806
1807 Hi = DAG.getNode(ISD::STEP_VECTOR, dl, HiVT, Step);
1808 Hi = DAG.getNode(ISD::ADD, dl, HiVT, Hi, StartOfHi);
1809 }
1810
SplitVecRes_ScalarOp(SDNode * N,SDValue & Lo,SDValue & Hi)1811 void DAGTypeLegalizer::SplitVecRes_ScalarOp(SDNode *N, SDValue &Lo,
1812 SDValue &Hi) {
1813 EVT LoVT, HiVT;
1814 SDLoc dl(N);
1815 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1816 Lo = DAG.getNode(N->getOpcode(), dl, LoVT, N->getOperand(0));
1817 if (N->getOpcode() == ISD::SCALAR_TO_VECTOR) {
1818 Hi = DAG.getUNDEF(HiVT);
1819 } else {
1820 assert(N->getOpcode() == ISD::SPLAT_VECTOR && "Unexpected opcode");
1821 Hi = Lo;
1822 }
1823 }
1824
SplitVecRes_LOAD(LoadSDNode * LD,SDValue & Lo,SDValue & Hi)1825 void DAGTypeLegalizer::SplitVecRes_LOAD(LoadSDNode *LD, SDValue &Lo,
1826 SDValue &Hi) {
1827 assert(ISD::isUNINDEXEDLoad(LD) && "Indexed load during type legalization!");
1828 EVT LoVT, HiVT;
1829 SDLoc dl(LD);
1830 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(LD->getValueType(0));
1831
1832 ISD::LoadExtType ExtType = LD->getExtensionType();
1833 SDValue Ch = LD->getChain();
1834 SDValue Ptr = LD->getBasePtr();
1835 SDValue Offset = DAG.getUNDEF(Ptr.getValueType());
1836 EVT MemoryVT = LD->getMemoryVT();
1837 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
1838 AAMDNodes AAInfo = LD->getAAInfo();
1839
1840 EVT LoMemVT, HiMemVT;
1841 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
1842
1843 if (!LoMemVT.isByteSized() || !HiMemVT.isByteSized()) {
1844 SDValue Value, NewChain;
1845 std::tie(Value, NewChain) = TLI.scalarizeVectorLoad(LD, DAG);
1846 std::tie(Lo, Hi) = DAG.SplitVector(Value, dl);
1847 ReplaceValueWith(SDValue(LD, 1), NewChain);
1848 return;
1849 }
1850
1851 Lo = DAG.getLoad(ISD::UNINDEXED, ExtType, LoVT, dl, Ch, Ptr, Offset,
1852 LD->getPointerInfo(), LoMemVT, LD->getOriginalAlign(),
1853 MMOFlags, AAInfo);
1854
1855 MachinePointerInfo MPI;
1856 IncrementPointer(LD, LoMemVT, MPI, Ptr);
1857
1858 Hi = DAG.getLoad(ISD::UNINDEXED, ExtType, HiVT, dl, Ch, Ptr, Offset, MPI,
1859 HiMemVT, LD->getOriginalAlign(), MMOFlags, AAInfo);
1860
1861 // Build a factor node to remember that this load is independent of the
1862 // other one.
1863 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
1864 Hi.getValue(1));
1865
1866 // Legalize the chain result - switch anything that used the old chain to
1867 // use the new one.
1868 ReplaceValueWith(SDValue(LD, 1), Ch);
1869 }
1870
SplitVecRes_VP_LOAD(VPLoadSDNode * LD,SDValue & Lo,SDValue & Hi)1871 void DAGTypeLegalizer::SplitVecRes_VP_LOAD(VPLoadSDNode *LD, SDValue &Lo,
1872 SDValue &Hi) {
1873 assert(LD->isUnindexed() && "Indexed VP load during type legalization!");
1874 EVT LoVT, HiVT;
1875 SDLoc dl(LD);
1876 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(LD->getValueType(0));
1877
1878 ISD::LoadExtType ExtType = LD->getExtensionType();
1879 SDValue Ch = LD->getChain();
1880 SDValue Ptr = LD->getBasePtr();
1881 SDValue Offset = LD->getOffset();
1882 assert(Offset.isUndef() && "Unexpected indexed variable-length load offset");
1883 Align Alignment = LD->getOriginalAlign();
1884 SDValue Mask = LD->getMask();
1885 SDValue EVL = LD->getVectorLength();
1886 EVT MemoryVT = LD->getMemoryVT();
1887
1888 EVT LoMemVT, HiMemVT;
1889 bool HiIsEmpty = false;
1890 std::tie(LoMemVT, HiMemVT) =
1891 DAG.GetDependentSplitDestVTs(MemoryVT, LoVT, &HiIsEmpty);
1892
1893 // Split Mask operand
1894 SDValue MaskLo, MaskHi;
1895 if (Mask.getOpcode() == ISD::SETCC) {
1896 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
1897 } else {
1898 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
1899 GetSplitVector(Mask, MaskLo, MaskHi);
1900 else
1901 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, dl);
1902 }
1903
1904 // Split EVL operand
1905 SDValue EVLLo, EVLHi;
1906 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(EVL, LD->getValueType(0), dl);
1907
1908 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
1909 LD->getPointerInfo(), MachineMemOperand::MOLoad,
1910 MemoryLocation::UnknownSize, Alignment, LD->getAAInfo(), LD->getRanges());
1911
1912 Lo =
1913 DAG.getLoadVP(LD->getAddressingMode(), ExtType, LoVT, dl, Ch, Ptr, Offset,
1914 MaskLo, EVLLo, LoMemVT, MMO, LD->isExpandingLoad());
1915
1916 if (HiIsEmpty) {
1917 // The hi vp_load has zero storage size. We therefore simply set it to
1918 // the low vp_load and rely on subsequent removal from the chain.
1919 Hi = Lo;
1920 } else {
1921 // Generate hi vp_load.
1922 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, dl, LoMemVT, DAG,
1923 LD->isExpandingLoad());
1924
1925 MachinePointerInfo MPI;
1926 if (LoMemVT.isScalableVector())
1927 MPI = MachinePointerInfo(LD->getPointerInfo().getAddrSpace());
1928 else
1929 MPI = LD->getPointerInfo().getWithOffset(
1930 LoMemVT.getStoreSize().getFixedValue());
1931
1932 MMO = DAG.getMachineFunction().getMachineMemOperand(
1933 MPI, MachineMemOperand::MOLoad, MemoryLocation::UnknownSize, Alignment,
1934 LD->getAAInfo(), LD->getRanges());
1935
1936 Hi = DAG.getLoadVP(LD->getAddressingMode(), ExtType, HiVT, dl, Ch, Ptr,
1937 Offset, MaskHi, EVLHi, HiMemVT, MMO,
1938 LD->isExpandingLoad());
1939 }
1940
1941 // Build a factor node to remember that this load is independent of the
1942 // other one.
1943 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
1944 Hi.getValue(1));
1945
1946 // Legalize the chain result - switch anything that used the old chain to
1947 // use the new one.
1948 ReplaceValueWith(SDValue(LD, 1), Ch);
1949 }
1950
SplitVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode * SLD,SDValue & Lo,SDValue & Hi)1951 void DAGTypeLegalizer::SplitVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode *SLD,
1952 SDValue &Lo, SDValue &Hi) {
1953 assert(SLD->isUnindexed() &&
1954 "Indexed VP strided load during type legalization!");
1955 assert(SLD->getOffset().isUndef() &&
1956 "Unexpected indexed variable-length load offset");
1957
1958 SDLoc DL(SLD);
1959
1960 EVT LoVT, HiVT;
1961 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(SLD->getValueType(0));
1962
1963 EVT LoMemVT, HiMemVT;
1964 bool HiIsEmpty = false;
1965 std::tie(LoMemVT, HiMemVT) =
1966 DAG.GetDependentSplitDestVTs(SLD->getMemoryVT(), LoVT, &HiIsEmpty);
1967
1968 SDValue Mask = SLD->getMask();
1969 SDValue LoMask, HiMask;
1970 if (Mask.getOpcode() == ISD::SETCC) {
1971 SplitVecRes_SETCC(Mask.getNode(), LoMask, HiMask);
1972 } else {
1973 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
1974 GetSplitVector(Mask, LoMask, HiMask);
1975 else
1976 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
1977 }
1978
1979 SDValue LoEVL, HiEVL;
1980 std::tie(LoEVL, HiEVL) =
1981 DAG.SplitEVL(SLD->getVectorLength(), SLD->getValueType(0), DL);
1982
1983 // Generate the low vp_strided_load
1984 Lo = DAG.getStridedLoadVP(
1985 SLD->getAddressingMode(), SLD->getExtensionType(), LoVT, DL,
1986 SLD->getChain(), SLD->getBasePtr(), SLD->getOffset(), SLD->getStride(),
1987 LoMask, LoEVL, LoMemVT, SLD->getMemOperand(), SLD->isExpandingLoad());
1988
1989 if (HiIsEmpty) {
1990 // The high vp_strided_load has zero storage size. We therefore simply set
1991 // it to the low vp_strided_load and rely on subsequent removal from the
1992 // chain.
1993 Hi = Lo;
1994 } else {
1995 // Generate the high vp_strided_load.
1996 // To calculate the high base address, we need to sum to the low base
1997 // address stride number of bytes for each element already loaded by low,
1998 // that is: Ptr = Ptr + (LoEVL * Stride)
1999 EVT PtrVT = SLD->getBasePtr().getValueType();
2000 SDValue Increment =
2001 DAG.getNode(ISD::MUL, DL, PtrVT, LoEVL,
2002 DAG.getSExtOrTrunc(SLD->getStride(), DL, PtrVT));
2003 SDValue Ptr =
2004 DAG.getNode(ISD::ADD, DL, PtrVT, SLD->getBasePtr(), Increment);
2005
2006 Align Alignment = SLD->getOriginalAlign();
2007 if (LoMemVT.isScalableVector())
2008 Alignment = commonAlignment(
2009 Alignment, LoMemVT.getSizeInBits().getKnownMinValue() / 8);
2010
2011 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
2012 MachinePointerInfo(SLD->getPointerInfo().getAddrSpace()),
2013 MachineMemOperand::MOLoad, MemoryLocation::UnknownSize, Alignment,
2014 SLD->getAAInfo(), SLD->getRanges());
2015
2016 Hi = DAG.getStridedLoadVP(SLD->getAddressingMode(), SLD->getExtensionType(),
2017 HiVT, DL, SLD->getChain(), Ptr, SLD->getOffset(),
2018 SLD->getStride(), HiMask, HiEVL, HiMemVT, MMO,
2019 SLD->isExpandingLoad());
2020 }
2021
2022 // Build a factor node to remember that this load is independent of the
2023 // other one.
2024 SDValue Ch = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo.getValue(1),
2025 Hi.getValue(1));
2026
2027 // Legalize the chain result - switch anything that used the old chain to
2028 // use the new one.
2029 ReplaceValueWith(SDValue(SLD, 1), Ch);
2030 }
2031
SplitVecRes_MLOAD(MaskedLoadSDNode * MLD,SDValue & Lo,SDValue & Hi)2032 void DAGTypeLegalizer::SplitVecRes_MLOAD(MaskedLoadSDNode *MLD,
2033 SDValue &Lo, SDValue &Hi) {
2034 assert(MLD->isUnindexed() && "Indexed masked load during type legalization!");
2035 EVT LoVT, HiVT;
2036 SDLoc dl(MLD);
2037 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(MLD->getValueType(0));
2038
2039 SDValue Ch = MLD->getChain();
2040 SDValue Ptr = MLD->getBasePtr();
2041 SDValue Offset = MLD->getOffset();
2042 assert(Offset.isUndef() && "Unexpected indexed masked load offset");
2043 SDValue Mask = MLD->getMask();
2044 SDValue PassThru = MLD->getPassThru();
2045 Align Alignment = MLD->getOriginalAlign();
2046 ISD::LoadExtType ExtType = MLD->getExtensionType();
2047
2048 // Split Mask operand
2049 SDValue MaskLo, MaskHi;
2050 if (Mask.getOpcode() == ISD::SETCC) {
2051 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
2052 } else {
2053 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
2054 GetSplitVector(Mask, MaskLo, MaskHi);
2055 else
2056 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, dl);
2057 }
2058
2059 EVT MemoryVT = MLD->getMemoryVT();
2060 EVT LoMemVT, HiMemVT;
2061 bool HiIsEmpty = false;
2062 std::tie(LoMemVT, HiMemVT) =
2063 DAG.GetDependentSplitDestVTs(MemoryVT, LoVT, &HiIsEmpty);
2064
2065 SDValue PassThruLo, PassThruHi;
2066 if (getTypeAction(PassThru.getValueType()) == TargetLowering::TypeSplitVector)
2067 GetSplitVector(PassThru, PassThruLo, PassThruHi);
2068 else
2069 std::tie(PassThruLo, PassThruHi) = DAG.SplitVector(PassThru, dl);
2070
2071 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
2072 MLD->getPointerInfo(), MachineMemOperand::MOLoad,
2073 MemoryLocation::UnknownSize, Alignment, MLD->getAAInfo(),
2074 MLD->getRanges());
2075
2076 Lo = DAG.getMaskedLoad(LoVT, dl, Ch, Ptr, Offset, MaskLo, PassThruLo, LoMemVT,
2077 MMO, MLD->getAddressingMode(), ExtType,
2078 MLD->isExpandingLoad());
2079
2080 if (HiIsEmpty) {
2081 // The hi masked load has zero storage size. We therefore simply set it to
2082 // the low masked load and rely on subsequent removal from the chain.
2083 Hi = Lo;
2084 } else {
2085 // Generate hi masked load.
2086 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, dl, LoMemVT, DAG,
2087 MLD->isExpandingLoad());
2088
2089 MachinePointerInfo MPI;
2090 if (LoMemVT.isScalableVector())
2091 MPI = MachinePointerInfo(MLD->getPointerInfo().getAddrSpace());
2092 else
2093 MPI = MLD->getPointerInfo().getWithOffset(
2094 LoMemVT.getStoreSize().getFixedValue());
2095
2096 MMO = DAG.getMachineFunction().getMachineMemOperand(
2097 MPI, MachineMemOperand::MOLoad, MemoryLocation::UnknownSize, Alignment,
2098 MLD->getAAInfo(), MLD->getRanges());
2099
2100 Hi = DAG.getMaskedLoad(HiVT, dl, Ch, Ptr, Offset, MaskHi, PassThruHi,
2101 HiMemVT, MMO, MLD->getAddressingMode(), ExtType,
2102 MLD->isExpandingLoad());
2103 }
2104
2105 // Build a factor node to remember that this load is independent of the
2106 // other one.
2107 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2108 Hi.getValue(1));
2109
2110 // Legalize the chain result - switch anything that used the old chain to
2111 // use the new one.
2112 ReplaceValueWith(SDValue(MLD, 1), Ch);
2113
2114 }
2115
SplitVecRes_Gather(MemSDNode * N,SDValue & Lo,SDValue & Hi,bool SplitSETCC)2116 void DAGTypeLegalizer::SplitVecRes_Gather(MemSDNode *N, SDValue &Lo,
2117 SDValue &Hi, bool SplitSETCC) {
2118 EVT LoVT, HiVT;
2119 SDLoc dl(N);
2120 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2121
2122 SDValue Ch = N->getChain();
2123 SDValue Ptr = N->getBasePtr();
2124 struct Operands {
2125 SDValue Mask;
2126 SDValue Index;
2127 SDValue Scale;
2128 } Ops = [&]() -> Operands {
2129 if (auto *MSC = dyn_cast<MaskedGatherSDNode>(N)) {
2130 return {MSC->getMask(), MSC->getIndex(), MSC->getScale()};
2131 }
2132 auto *VPSC = cast<VPGatherSDNode>(N);
2133 return {VPSC->getMask(), VPSC->getIndex(), VPSC->getScale()};
2134 }();
2135
2136 EVT MemoryVT = N->getMemoryVT();
2137 Align Alignment = N->getOriginalAlign();
2138
2139 // Split Mask operand
2140 SDValue MaskLo, MaskHi;
2141 if (SplitSETCC && Ops.Mask.getOpcode() == ISD::SETCC) {
2142 SplitVecRes_SETCC(Ops.Mask.getNode(), MaskLo, MaskHi);
2143 } else {
2144 std::tie(MaskLo, MaskHi) = SplitMask(Ops.Mask, dl);
2145 }
2146
2147 EVT LoMemVT, HiMemVT;
2148 // Split MemoryVT
2149 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
2150
2151 SDValue IndexHi, IndexLo;
2152 if (getTypeAction(Ops.Index.getValueType()) ==
2153 TargetLowering::TypeSplitVector)
2154 GetSplitVector(Ops.Index, IndexLo, IndexHi);
2155 else
2156 std::tie(IndexLo, IndexHi) = DAG.SplitVector(Ops.Index, dl);
2157
2158 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
2159 N->getPointerInfo(), MachineMemOperand::MOLoad,
2160 MemoryLocation::UnknownSize, Alignment, N->getAAInfo(), N->getRanges());
2161
2162 if (auto *MGT = dyn_cast<MaskedGatherSDNode>(N)) {
2163 SDValue PassThru = MGT->getPassThru();
2164 SDValue PassThruLo, PassThruHi;
2165 if (getTypeAction(PassThru.getValueType()) ==
2166 TargetLowering::TypeSplitVector)
2167 GetSplitVector(PassThru, PassThruLo, PassThruHi);
2168 else
2169 std::tie(PassThruLo, PassThruHi) = DAG.SplitVector(PassThru, dl);
2170
2171 ISD::LoadExtType ExtType = MGT->getExtensionType();
2172 ISD::MemIndexType IndexTy = MGT->getIndexType();
2173
2174 SDValue OpsLo[] = {Ch, PassThruLo, MaskLo, Ptr, IndexLo, Ops.Scale};
2175 Lo = DAG.getMaskedGather(DAG.getVTList(LoVT, MVT::Other), LoMemVT, dl,
2176 OpsLo, MMO, IndexTy, ExtType);
2177
2178 SDValue OpsHi[] = {Ch, PassThruHi, MaskHi, Ptr, IndexHi, Ops.Scale};
2179 Hi = DAG.getMaskedGather(DAG.getVTList(HiVT, MVT::Other), HiMemVT, dl,
2180 OpsHi, MMO, IndexTy, ExtType);
2181 } else {
2182 auto *VPGT = cast<VPGatherSDNode>(N);
2183 SDValue EVLLo, EVLHi;
2184 std::tie(EVLLo, EVLHi) =
2185 DAG.SplitEVL(VPGT->getVectorLength(), MemoryVT, dl);
2186
2187 SDValue OpsLo[] = {Ch, Ptr, IndexLo, Ops.Scale, MaskLo, EVLLo};
2188 Lo = DAG.getGatherVP(DAG.getVTList(LoVT, MVT::Other), LoMemVT, dl, OpsLo,
2189 MMO, VPGT->getIndexType());
2190
2191 SDValue OpsHi[] = {Ch, Ptr, IndexHi, Ops.Scale, MaskHi, EVLHi};
2192 Hi = DAG.getGatherVP(DAG.getVTList(HiVT, MVT::Other), HiMemVT, dl, OpsHi,
2193 MMO, VPGT->getIndexType());
2194 }
2195
2196 // Build a factor node to remember that this load is independent of the
2197 // other one.
2198 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2199 Hi.getValue(1));
2200
2201 // Legalize the chain result - switch anything that used the old chain to
2202 // use the new one.
2203 ReplaceValueWith(SDValue(N, 1), Ch);
2204 }
2205
SplitVecRes_SETCC(SDNode * N,SDValue & Lo,SDValue & Hi)2206 void DAGTypeLegalizer::SplitVecRes_SETCC(SDNode *N, SDValue &Lo, SDValue &Hi) {
2207 assert(N->getValueType(0).isVector() &&
2208 N->getOperand(0).getValueType().isVector() &&
2209 "Operand types must be vectors");
2210
2211 EVT LoVT, HiVT;
2212 SDLoc DL(N);
2213 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2214
2215 // If the input also splits, handle it directly. Otherwise split it by hand.
2216 SDValue LL, LH, RL, RH;
2217 if (getTypeAction(N->getOperand(0).getValueType()) ==
2218 TargetLowering::TypeSplitVector)
2219 GetSplitVector(N->getOperand(0), LL, LH);
2220 else
2221 std::tie(LL, LH) = DAG.SplitVectorOperand(N, 0);
2222
2223 if (getTypeAction(N->getOperand(1).getValueType()) ==
2224 TargetLowering::TypeSplitVector)
2225 GetSplitVector(N->getOperand(1), RL, RH);
2226 else
2227 std::tie(RL, RH) = DAG.SplitVectorOperand(N, 1);
2228
2229 if (N->getOpcode() == ISD::SETCC) {
2230 Lo = DAG.getNode(N->getOpcode(), DL, LoVT, LL, RL, N->getOperand(2));
2231 Hi = DAG.getNode(N->getOpcode(), DL, HiVT, LH, RH, N->getOperand(2));
2232 } else {
2233 assert(N->getOpcode() == ISD::VP_SETCC && "Expected VP_SETCC opcode");
2234 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
2235 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(3));
2236 std::tie(EVLLo, EVLHi) =
2237 DAG.SplitEVL(N->getOperand(4), N->getValueType(0), DL);
2238 Lo = DAG.getNode(N->getOpcode(), DL, LoVT, LL, RL, N->getOperand(2), MaskLo,
2239 EVLLo);
2240 Hi = DAG.getNode(N->getOpcode(), DL, HiVT, LH, RH, N->getOperand(2), MaskHi,
2241 EVLHi);
2242 }
2243 }
2244
SplitVecRes_UnaryOp(SDNode * N,SDValue & Lo,SDValue & Hi)2245 void DAGTypeLegalizer::SplitVecRes_UnaryOp(SDNode *N, SDValue &Lo,
2246 SDValue &Hi) {
2247 // Get the dest types - they may not match the input types, e.g. int_to_fp.
2248 EVT LoVT, HiVT;
2249 SDLoc dl(N);
2250 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2251
2252 // If the input also splits, handle it directly for a compile time speedup.
2253 // Otherwise split it by hand.
2254 EVT InVT = N->getOperand(0).getValueType();
2255 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
2256 GetSplitVector(N->getOperand(0), Lo, Hi);
2257 else
2258 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
2259
2260 const SDNodeFlags Flags = N->getFlags();
2261 unsigned Opcode = N->getOpcode();
2262 if (N->getNumOperands() <= 2) {
2263 if (Opcode == ISD::FP_ROUND) {
2264 Lo = DAG.getNode(Opcode, dl, LoVT, Lo, N->getOperand(1), Flags);
2265 Hi = DAG.getNode(Opcode, dl, HiVT, Hi, N->getOperand(1), Flags);
2266 } else {
2267 Lo = DAG.getNode(Opcode, dl, LoVT, Lo, Flags);
2268 Hi = DAG.getNode(Opcode, dl, HiVT, Hi, Flags);
2269 }
2270 return;
2271 }
2272
2273 assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
2274 assert(N->isVPOpcode() && "Expected VP opcode");
2275
2276 SDValue MaskLo, MaskHi;
2277 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
2278
2279 SDValue EVLLo, EVLHi;
2280 std::tie(EVLLo, EVLHi) =
2281 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), dl);
2282
2283 Lo = DAG.getNode(Opcode, dl, LoVT, {Lo, MaskLo, EVLLo}, Flags);
2284 Hi = DAG.getNode(Opcode, dl, HiVT, {Hi, MaskHi, EVLHi}, Flags);
2285 }
2286
SplitVecRes_ExtendOp(SDNode * N,SDValue & Lo,SDValue & Hi)2287 void DAGTypeLegalizer::SplitVecRes_ExtendOp(SDNode *N, SDValue &Lo,
2288 SDValue &Hi) {
2289 SDLoc dl(N);
2290 EVT SrcVT = N->getOperand(0).getValueType();
2291 EVT DestVT = N->getValueType(0);
2292 EVT LoVT, HiVT;
2293 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(DestVT);
2294
2295 // We can do better than a generic split operation if the extend is doing
2296 // more than just doubling the width of the elements and the following are
2297 // true:
2298 // - The number of vector elements is even,
2299 // - the source type is legal,
2300 // - the type of a split source is illegal,
2301 // - the type of an extended (by doubling element size) source is legal, and
2302 // - the type of that extended source when split is legal.
2303 //
2304 // This won't necessarily completely legalize the operation, but it will
2305 // more effectively move in the right direction and prevent falling down
2306 // to scalarization in many cases due to the input vector being split too
2307 // far.
2308 if (SrcVT.getVectorElementCount().isKnownEven() &&
2309 SrcVT.getScalarSizeInBits() * 2 < DestVT.getScalarSizeInBits()) {
2310 LLVMContext &Ctx = *DAG.getContext();
2311 EVT NewSrcVT = SrcVT.widenIntegerVectorElementType(Ctx);
2312 EVT SplitSrcVT = SrcVT.getHalfNumVectorElementsVT(Ctx);
2313
2314 EVT SplitLoVT, SplitHiVT;
2315 std::tie(SplitLoVT, SplitHiVT) = DAG.GetSplitDestVTs(NewSrcVT);
2316 if (TLI.isTypeLegal(SrcVT) && !TLI.isTypeLegal(SplitSrcVT) &&
2317 TLI.isTypeLegal(NewSrcVT) && TLI.isTypeLegal(SplitLoVT)) {
2318 LLVM_DEBUG(dbgs() << "Split vector extend via incremental extend:";
2319 N->dump(&DAG); dbgs() << "\n");
2320 if (!N->isVPOpcode()) {
2321 // Extend the source vector by one step.
2322 SDValue NewSrc =
2323 DAG.getNode(N->getOpcode(), dl, NewSrcVT, N->getOperand(0));
2324 // Get the low and high halves of the new, extended one step, vector.
2325 std::tie(Lo, Hi) = DAG.SplitVector(NewSrc, dl);
2326 // Extend those vector halves the rest of the way.
2327 Lo = DAG.getNode(N->getOpcode(), dl, LoVT, Lo);
2328 Hi = DAG.getNode(N->getOpcode(), dl, HiVT, Hi);
2329 return;
2330 }
2331
2332 // Extend the source vector by one step.
2333 SDValue NewSrc =
2334 DAG.getNode(N->getOpcode(), dl, NewSrcVT, N->getOperand(0),
2335 N->getOperand(1), N->getOperand(2));
2336 // Get the low and high halves of the new, extended one step, vector.
2337 std::tie(Lo, Hi) = DAG.SplitVector(NewSrc, dl);
2338
2339 SDValue MaskLo, MaskHi;
2340 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
2341
2342 SDValue EVLLo, EVLHi;
2343 std::tie(EVLLo, EVLHi) =
2344 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), dl);
2345 // Extend those vector halves the rest of the way.
2346 Lo = DAG.getNode(N->getOpcode(), dl, LoVT, {Lo, MaskLo, EVLLo});
2347 Hi = DAG.getNode(N->getOpcode(), dl, HiVT, {Hi, MaskHi, EVLHi});
2348 return;
2349 }
2350 }
2351 // Fall back to the generic unary operator splitting otherwise.
2352 SplitVecRes_UnaryOp(N, Lo, Hi);
2353 }
2354
SplitVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode * N,SDValue & Lo,SDValue & Hi)2355 void DAGTypeLegalizer::SplitVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N,
2356 SDValue &Lo, SDValue &Hi) {
2357 // The low and high parts of the original input give four input vectors.
2358 SDValue Inputs[4];
2359 SDLoc DL(N);
2360 GetSplitVector(N->getOperand(0), Inputs[0], Inputs[1]);
2361 GetSplitVector(N->getOperand(1), Inputs[2], Inputs[3]);
2362 EVT NewVT = Inputs[0].getValueType();
2363 unsigned NewElts = NewVT.getVectorNumElements();
2364
2365 auto &&IsConstant = [](const SDValue &N) {
2366 APInt SplatValue;
2367 return N.getResNo() == 0 &&
2368 (ISD::isConstantSplatVector(N.getNode(), SplatValue) ||
2369 ISD::isBuildVectorOfConstantSDNodes(N.getNode()));
2370 };
2371 auto &&BuildVector = [NewElts, &DAG = DAG, NewVT, &DL](SDValue &Input1,
2372 SDValue &Input2,
2373 ArrayRef<int> Mask) {
2374 assert(Input1->getOpcode() == ISD::BUILD_VECTOR &&
2375 Input2->getOpcode() == ISD::BUILD_VECTOR &&
2376 "Expected build vector node.");
2377 EVT EltVT = NewVT.getVectorElementType();
2378 SmallVector<SDValue> Ops(NewElts, DAG.getUNDEF(EltVT));
2379 for (unsigned I = 0; I < NewElts; ++I) {
2380 if (Mask[I] == UndefMaskElem)
2381 continue;
2382 unsigned Idx = Mask[I];
2383 if (Idx >= NewElts)
2384 Ops[I] = Input2.getOperand(Idx - NewElts);
2385 else
2386 Ops[I] = Input1.getOperand(Idx);
2387 // Make the type of all elements the same as the element type.
2388 if (Ops[I].getValueType().bitsGT(EltVT))
2389 Ops[I] = DAG.getNode(ISD::TRUNCATE, DL, EltVT, Ops[I]);
2390 }
2391 return DAG.getBuildVector(NewVT, DL, Ops);
2392 };
2393
2394 // If Lo or Hi uses elements from at most two of the four input vectors, then
2395 // express it as a vector shuffle of those two inputs. Otherwise extract the
2396 // input elements by hand and construct the Lo/Hi output using a BUILD_VECTOR.
2397 SmallVector<int> OrigMask(N->getMask());
2398 // Try to pack incoming shuffles/inputs.
2399 auto &&TryPeekThroughShufflesInputs = [&Inputs, &NewVT, this, NewElts,
2400 &DL](SmallVectorImpl<int> &Mask) {
2401 // Check if all inputs are shuffles of the same operands or non-shuffles.
2402 MapVector<std::pair<SDValue, SDValue>, SmallVector<unsigned>> ShufflesIdxs;
2403 for (unsigned Idx = 0; Idx < std::size(Inputs); ++Idx) {
2404 SDValue Input = Inputs[Idx];
2405 auto *Shuffle = dyn_cast<ShuffleVectorSDNode>(Input.getNode());
2406 if (!Shuffle ||
2407 Input.getOperand(0).getValueType() != Input.getValueType())
2408 continue;
2409 ShufflesIdxs[std::make_pair(Input.getOperand(0), Input.getOperand(1))]
2410 .push_back(Idx);
2411 ShufflesIdxs[std::make_pair(Input.getOperand(1), Input.getOperand(0))]
2412 .push_back(Idx);
2413 }
2414 for (auto &P : ShufflesIdxs) {
2415 if (P.second.size() < 2)
2416 continue;
2417 // Use shuffles operands instead of shuffles themselves.
2418 // 1. Adjust mask.
2419 for (int &Idx : Mask) {
2420 if (Idx == UndefMaskElem)
2421 continue;
2422 unsigned SrcRegIdx = Idx / NewElts;
2423 if (Inputs[SrcRegIdx].isUndef()) {
2424 Idx = UndefMaskElem;
2425 continue;
2426 }
2427 auto *Shuffle =
2428 dyn_cast<ShuffleVectorSDNode>(Inputs[SrcRegIdx].getNode());
2429 if (!Shuffle || !is_contained(P.second, SrcRegIdx))
2430 continue;
2431 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
2432 if (MaskElt == UndefMaskElem) {
2433 Idx = UndefMaskElem;
2434 continue;
2435 }
2436 Idx = MaskElt % NewElts +
2437 P.second[Shuffle->getOperand(MaskElt / NewElts) == P.first.first
2438 ? 0
2439 : 1] *
2440 NewElts;
2441 }
2442 // 2. Update inputs.
2443 Inputs[P.second[0]] = P.first.first;
2444 Inputs[P.second[1]] = P.first.second;
2445 // Clear the pair data.
2446 P.second.clear();
2447 ShufflesIdxs[std::make_pair(P.first.second, P.first.first)].clear();
2448 }
2449 // Check if any concat_vectors can be simplified.
2450 SmallBitVector UsedSubVector(2 * std::size(Inputs));
2451 for (int &Idx : Mask) {
2452 if (Idx == UndefMaskElem)
2453 continue;
2454 unsigned SrcRegIdx = Idx / NewElts;
2455 if (Inputs[SrcRegIdx].isUndef()) {
2456 Idx = UndefMaskElem;
2457 continue;
2458 }
2459 TargetLowering::LegalizeTypeAction TypeAction =
2460 getTypeAction(Inputs[SrcRegIdx].getValueType());
2461 if (Inputs[SrcRegIdx].getOpcode() == ISD::CONCAT_VECTORS &&
2462 Inputs[SrcRegIdx].getNumOperands() == 2 &&
2463 !Inputs[SrcRegIdx].getOperand(1).isUndef() &&
2464 (TypeAction == TargetLowering::TypeLegal ||
2465 TypeAction == TargetLowering::TypeWidenVector))
2466 UsedSubVector.set(2 * SrcRegIdx + (Idx % NewElts) / (NewElts / 2));
2467 }
2468 if (UsedSubVector.count() > 1) {
2469 SmallVector<SmallVector<std::pair<unsigned, int>, 2>> Pairs;
2470 for (unsigned I = 0; I < std::size(Inputs); ++I) {
2471 if (UsedSubVector.test(2 * I) == UsedSubVector.test(2 * I + 1))
2472 continue;
2473 if (Pairs.empty() || Pairs.back().size() == 2)
2474 Pairs.emplace_back();
2475 if (UsedSubVector.test(2 * I)) {
2476 Pairs.back().emplace_back(I, 0);
2477 } else {
2478 assert(UsedSubVector.test(2 * I + 1) &&
2479 "Expected to be used one of the subvectors.");
2480 Pairs.back().emplace_back(I, 1);
2481 }
2482 }
2483 if (!Pairs.empty() && Pairs.front().size() > 1) {
2484 // Adjust mask.
2485 for (int &Idx : Mask) {
2486 if (Idx == UndefMaskElem)
2487 continue;
2488 unsigned SrcRegIdx = Idx / NewElts;
2489 auto *It = find_if(
2490 Pairs, [SrcRegIdx](ArrayRef<std::pair<unsigned, int>> Idxs) {
2491 return Idxs.front().first == SrcRegIdx ||
2492 Idxs.back().first == SrcRegIdx;
2493 });
2494 if (It == Pairs.end())
2495 continue;
2496 Idx = It->front().first * NewElts + (Idx % NewElts) % (NewElts / 2) +
2497 (SrcRegIdx == It->front().first ? 0 : (NewElts / 2));
2498 }
2499 // Adjust inputs.
2500 for (ArrayRef<std::pair<unsigned, int>> Idxs : Pairs) {
2501 Inputs[Idxs.front().first] = DAG.getNode(
2502 ISD::CONCAT_VECTORS, DL,
2503 Inputs[Idxs.front().first].getValueType(),
2504 Inputs[Idxs.front().first].getOperand(Idxs.front().second),
2505 Inputs[Idxs.back().first].getOperand(Idxs.back().second));
2506 }
2507 }
2508 }
2509 bool Changed;
2510 do {
2511 // Try to remove extra shuffles (except broadcasts) and shuffles with the
2512 // reused operands.
2513 Changed = false;
2514 for (unsigned I = 0; I < std::size(Inputs); ++I) {
2515 auto *Shuffle = dyn_cast<ShuffleVectorSDNode>(Inputs[I].getNode());
2516 if (!Shuffle)
2517 continue;
2518 if (Shuffle->getOperand(0).getValueType() != NewVT)
2519 continue;
2520 int Op = -1;
2521 if (!Inputs[I].hasOneUse() && Shuffle->getOperand(1).isUndef() &&
2522 !Shuffle->isSplat()) {
2523 Op = 0;
2524 } else if (!Inputs[I].hasOneUse() &&
2525 !Shuffle->getOperand(1).isUndef()) {
2526 // Find the only used operand, if possible.
2527 for (int &Idx : Mask) {
2528 if (Idx == UndefMaskElem)
2529 continue;
2530 unsigned SrcRegIdx = Idx / NewElts;
2531 if (SrcRegIdx != I)
2532 continue;
2533 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
2534 if (MaskElt == UndefMaskElem) {
2535 Idx = UndefMaskElem;
2536 continue;
2537 }
2538 int OpIdx = MaskElt / NewElts;
2539 if (Op == -1) {
2540 Op = OpIdx;
2541 continue;
2542 }
2543 if (Op != OpIdx) {
2544 Op = -1;
2545 break;
2546 }
2547 }
2548 }
2549 if (Op < 0) {
2550 // Try to check if one of the shuffle operands is used already.
2551 for (int OpIdx = 0; OpIdx < 2; ++OpIdx) {
2552 if (Shuffle->getOperand(OpIdx).isUndef())
2553 continue;
2554 auto *It = find(Inputs, Shuffle->getOperand(OpIdx));
2555 if (It == std::end(Inputs))
2556 continue;
2557 int FoundOp = std::distance(std::begin(Inputs), It);
2558 // Found that operand is used already.
2559 // 1. Fix the mask for the reused operand.
2560 for (int &Idx : Mask) {
2561 if (Idx == UndefMaskElem)
2562 continue;
2563 unsigned SrcRegIdx = Idx / NewElts;
2564 if (SrcRegIdx != I)
2565 continue;
2566 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
2567 if (MaskElt == UndefMaskElem) {
2568 Idx = UndefMaskElem;
2569 continue;
2570 }
2571 int MaskIdx = MaskElt / NewElts;
2572 if (OpIdx == MaskIdx)
2573 Idx = MaskElt % NewElts + FoundOp * NewElts;
2574 }
2575 // 2. Set Op to the unused OpIdx.
2576 Op = (OpIdx + 1) % 2;
2577 break;
2578 }
2579 }
2580 if (Op >= 0) {
2581 Changed = true;
2582 Inputs[I] = Shuffle->getOperand(Op);
2583 // Adjust mask.
2584 for (int &Idx : Mask) {
2585 if (Idx == UndefMaskElem)
2586 continue;
2587 unsigned SrcRegIdx = Idx / NewElts;
2588 if (SrcRegIdx != I)
2589 continue;
2590 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
2591 int OpIdx = MaskElt / NewElts;
2592 if (OpIdx != Op)
2593 continue;
2594 Idx = MaskElt % NewElts + SrcRegIdx * NewElts;
2595 }
2596 }
2597 }
2598 } while (Changed);
2599 };
2600 TryPeekThroughShufflesInputs(OrigMask);
2601 // Proces unique inputs.
2602 auto &&MakeUniqueInputs = [&Inputs, &IsConstant,
2603 NewElts](SmallVectorImpl<int> &Mask) {
2604 SetVector<SDValue> UniqueInputs;
2605 SetVector<SDValue> UniqueConstantInputs;
2606 for (const auto &I : Inputs) {
2607 if (IsConstant(I))
2608 UniqueConstantInputs.insert(I);
2609 else if (!I.isUndef())
2610 UniqueInputs.insert(I);
2611 }
2612 // Adjust mask in case of reused inputs. Also, need to insert constant
2613 // inputs at first, otherwise it affects the final outcome.
2614 if (UniqueInputs.size() != std::size(Inputs)) {
2615 auto &&UniqueVec = UniqueInputs.takeVector();
2616 auto &&UniqueConstantVec = UniqueConstantInputs.takeVector();
2617 unsigned ConstNum = UniqueConstantVec.size();
2618 for (int &Idx : Mask) {
2619 if (Idx == UndefMaskElem)
2620 continue;
2621 unsigned SrcRegIdx = Idx / NewElts;
2622 if (Inputs[SrcRegIdx].isUndef()) {
2623 Idx = UndefMaskElem;
2624 continue;
2625 }
2626 const auto It = find(UniqueConstantVec, Inputs[SrcRegIdx]);
2627 if (It != UniqueConstantVec.end()) {
2628 Idx = (Idx % NewElts) +
2629 NewElts * std::distance(UniqueConstantVec.begin(), It);
2630 assert(Idx >= 0 && "Expected defined mask idx.");
2631 continue;
2632 }
2633 const auto RegIt = find(UniqueVec, Inputs[SrcRegIdx]);
2634 assert(RegIt != UniqueVec.end() && "Cannot find non-const value.");
2635 Idx = (Idx % NewElts) +
2636 NewElts * (std::distance(UniqueVec.begin(), RegIt) + ConstNum);
2637 assert(Idx >= 0 && "Expected defined mask idx.");
2638 }
2639 copy(UniqueConstantVec, std::begin(Inputs));
2640 copy(UniqueVec, std::next(std::begin(Inputs), ConstNum));
2641 }
2642 };
2643 MakeUniqueInputs(OrigMask);
2644 SDValue OrigInputs[4];
2645 copy(Inputs, std::begin(OrigInputs));
2646 for (unsigned High = 0; High < 2; ++High) {
2647 SDValue &Output = High ? Hi : Lo;
2648
2649 // Build a shuffle mask for the output, discovering on the fly which
2650 // input vectors to use as shuffle operands.
2651 unsigned FirstMaskIdx = High * NewElts;
2652 SmallVector<int> Mask(NewElts * std::size(Inputs), UndefMaskElem);
2653 copy(ArrayRef(OrigMask).slice(FirstMaskIdx, NewElts), Mask.begin());
2654 assert(!Output && "Expected default initialized initial value.");
2655 TryPeekThroughShufflesInputs(Mask);
2656 MakeUniqueInputs(Mask);
2657 SDValue TmpInputs[4];
2658 copy(Inputs, std::begin(TmpInputs));
2659 // Track changes in the output registers.
2660 int UsedIdx = -1;
2661 bool SecondIteration = false;
2662 auto &&AccumulateResults = [&UsedIdx, &SecondIteration](unsigned Idx) {
2663 if (UsedIdx < 0) {
2664 UsedIdx = Idx;
2665 return false;
2666 }
2667 if (UsedIdx >= 0 && static_cast<unsigned>(UsedIdx) == Idx)
2668 SecondIteration = true;
2669 return SecondIteration;
2670 };
2671 processShuffleMasks(
2672 Mask, std::size(Inputs), std::size(Inputs),
2673 /*NumOfUsedRegs=*/1,
2674 [&Output, &DAG = DAG, NewVT]() { Output = DAG.getUNDEF(NewVT); },
2675 [&Output, &DAG = DAG, NewVT, &DL, &Inputs,
2676 &BuildVector](ArrayRef<int> Mask, unsigned Idx, unsigned /*Unused*/) {
2677 if (Inputs[Idx]->getOpcode() == ISD::BUILD_VECTOR)
2678 Output = BuildVector(Inputs[Idx], Inputs[Idx], Mask);
2679 else
2680 Output = DAG.getVectorShuffle(NewVT, DL, Inputs[Idx],
2681 DAG.getUNDEF(NewVT), Mask);
2682 Inputs[Idx] = Output;
2683 },
2684 [&AccumulateResults, &Output, &DAG = DAG, NewVT, &DL, &Inputs,
2685 &TmpInputs,
2686 &BuildVector](ArrayRef<int> Mask, unsigned Idx1, unsigned Idx2) {
2687 if (AccumulateResults(Idx1)) {
2688 if (Inputs[Idx1]->getOpcode() == ISD::BUILD_VECTOR &&
2689 Inputs[Idx2]->getOpcode() == ISD::BUILD_VECTOR)
2690 Output = BuildVector(Inputs[Idx1], Inputs[Idx2], Mask);
2691 else
2692 Output = DAG.getVectorShuffle(NewVT, DL, Inputs[Idx1],
2693 Inputs[Idx2], Mask);
2694 } else {
2695 if (TmpInputs[Idx1]->getOpcode() == ISD::BUILD_VECTOR &&
2696 TmpInputs[Idx2]->getOpcode() == ISD::BUILD_VECTOR)
2697 Output = BuildVector(TmpInputs[Idx1], TmpInputs[Idx2], Mask);
2698 else
2699 Output = DAG.getVectorShuffle(NewVT, DL, TmpInputs[Idx1],
2700 TmpInputs[Idx2], Mask);
2701 }
2702 Inputs[Idx1] = Output;
2703 });
2704 copy(OrigInputs, std::begin(Inputs));
2705 }
2706 }
2707
SplitVecRes_VAARG(SDNode * N,SDValue & Lo,SDValue & Hi)2708 void DAGTypeLegalizer::SplitVecRes_VAARG(SDNode *N, SDValue &Lo, SDValue &Hi) {
2709 EVT OVT = N->getValueType(0);
2710 EVT NVT = OVT.getHalfNumVectorElementsVT(*DAG.getContext());
2711 SDValue Chain = N->getOperand(0);
2712 SDValue Ptr = N->getOperand(1);
2713 SDValue SV = N->getOperand(2);
2714 SDLoc dl(N);
2715
2716 const Align Alignment =
2717 DAG.getDataLayout().getABITypeAlign(NVT.getTypeForEVT(*DAG.getContext()));
2718
2719 Lo = DAG.getVAArg(NVT, dl, Chain, Ptr, SV, Alignment.value());
2720 Hi = DAG.getVAArg(NVT, dl, Lo.getValue(1), Ptr, SV, Alignment.value());
2721 Chain = Hi.getValue(1);
2722
2723 // Modified the chain - switch anything that used the old chain to use
2724 // the new one.
2725 ReplaceValueWith(SDValue(N, 1), Chain);
2726 }
2727
SplitVecRes_FP_TO_XINT_SAT(SDNode * N,SDValue & Lo,SDValue & Hi)2728 void DAGTypeLegalizer::SplitVecRes_FP_TO_XINT_SAT(SDNode *N, SDValue &Lo,
2729 SDValue &Hi) {
2730 EVT DstVTLo, DstVTHi;
2731 std::tie(DstVTLo, DstVTHi) = DAG.GetSplitDestVTs(N->getValueType(0));
2732 SDLoc dl(N);
2733
2734 SDValue SrcLo, SrcHi;
2735 EVT SrcVT = N->getOperand(0).getValueType();
2736 if (getTypeAction(SrcVT) == TargetLowering::TypeSplitVector)
2737 GetSplitVector(N->getOperand(0), SrcLo, SrcHi);
2738 else
2739 std::tie(SrcLo, SrcHi) = DAG.SplitVectorOperand(N, 0);
2740
2741 Lo = DAG.getNode(N->getOpcode(), dl, DstVTLo, SrcLo, N->getOperand(1));
2742 Hi = DAG.getNode(N->getOpcode(), dl, DstVTHi, SrcHi, N->getOperand(1));
2743 }
2744
SplitVecRes_VECTOR_REVERSE(SDNode * N,SDValue & Lo,SDValue & Hi)2745 void DAGTypeLegalizer::SplitVecRes_VECTOR_REVERSE(SDNode *N, SDValue &Lo,
2746 SDValue &Hi) {
2747 SDValue InLo, InHi;
2748 GetSplitVector(N->getOperand(0), InLo, InHi);
2749 SDLoc DL(N);
2750
2751 Lo = DAG.getNode(ISD::VECTOR_REVERSE, DL, InHi.getValueType(), InHi);
2752 Hi = DAG.getNode(ISD::VECTOR_REVERSE, DL, InLo.getValueType(), InLo);
2753 }
2754
SplitVecRes_VECTOR_SPLICE(SDNode * N,SDValue & Lo,SDValue & Hi)2755 void DAGTypeLegalizer::SplitVecRes_VECTOR_SPLICE(SDNode *N, SDValue &Lo,
2756 SDValue &Hi) {
2757 EVT VT = N->getValueType(0);
2758 SDLoc DL(N);
2759
2760 EVT LoVT, HiVT;
2761 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(VT);
2762
2763 SDValue Expanded = TLI.expandVectorSplice(N, DAG);
2764 Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, LoVT, Expanded,
2765 DAG.getVectorIdxConstant(0, DL));
2766 Hi =
2767 DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, HiVT, Expanded,
2768 DAG.getVectorIdxConstant(LoVT.getVectorMinNumElements(), DL));
2769 }
2770
2771 //===----------------------------------------------------------------------===//
2772 // Operand Vector Splitting
2773 //===----------------------------------------------------------------------===//
2774
2775 /// This method is called when the specified operand of the specified node is
2776 /// found to need vector splitting. At this point, all of the result types of
2777 /// the node are known to be legal, but other operands of the node may need
2778 /// legalization as well as the specified one.
SplitVectorOperand(SDNode * N,unsigned OpNo)2779 bool DAGTypeLegalizer::SplitVectorOperand(SDNode *N, unsigned OpNo) {
2780 LLVM_DEBUG(dbgs() << "Split node operand: "; N->dump(&DAG); dbgs() << "\n");
2781 SDValue Res = SDValue();
2782
2783 // See if the target wants to custom split this node.
2784 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
2785 return false;
2786
2787 switch (N->getOpcode()) {
2788 default:
2789 #ifndef NDEBUG
2790 dbgs() << "SplitVectorOperand Op #" << OpNo << ": ";
2791 N->dump(&DAG);
2792 dbgs() << "\n";
2793 #endif
2794 report_fatal_error("Do not know how to split this operator's "
2795 "operand!\n");
2796
2797 case ISD::VP_SETCC:
2798 case ISD::SETCC: Res = SplitVecOp_VSETCC(N); break;
2799 case ISD::BITCAST: Res = SplitVecOp_BITCAST(N); break;
2800 case ISD::EXTRACT_SUBVECTOR: Res = SplitVecOp_EXTRACT_SUBVECTOR(N); break;
2801 case ISD::INSERT_SUBVECTOR: Res = SplitVecOp_INSERT_SUBVECTOR(N, OpNo); break;
2802 case ISD::EXTRACT_VECTOR_ELT:Res = SplitVecOp_EXTRACT_VECTOR_ELT(N); break;
2803 case ISD::CONCAT_VECTORS: Res = SplitVecOp_CONCAT_VECTORS(N); break;
2804 case ISD::VP_TRUNCATE:
2805 case ISD::TRUNCATE:
2806 Res = SplitVecOp_TruncateHelper(N);
2807 break;
2808 case ISD::STRICT_FP_ROUND:
2809 case ISD::VP_FP_ROUND:
2810 case ISD::FP_ROUND: Res = SplitVecOp_FP_ROUND(N); break;
2811 case ISD::FCOPYSIGN: Res = SplitVecOp_FCOPYSIGN(N); break;
2812 case ISD::STORE:
2813 Res = SplitVecOp_STORE(cast<StoreSDNode>(N), OpNo);
2814 break;
2815 case ISD::VP_STORE:
2816 Res = SplitVecOp_VP_STORE(cast<VPStoreSDNode>(N), OpNo);
2817 break;
2818 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
2819 Res = SplitVecOp_VP_STRIDED_STORE(cast<VPStridedStoreSDNode>(N), OpNo);
2820 break;
2821 case ISD::MSTORE:
2822 Res = SplitVecOp_MSTORE(cast<MaskedStoreSDNode>(N), OpNo);
2823 break;
2824 case ISD::MSCATTER:
2825 case ISD::VP_SCATTER:
2826 Res = SplitVecOp_Scatter(cast<MemSDNode>(N), OpNo);
2827 break;
2828 case ISD::MGATHER:
2829 case ISD::VP_GATHER:
2830 Res = SplitVecOp_Gather(cast<MemSDNode>(N), OpNo);
2831 break;
2832 case ISD::VSELECT:
2833 Res = SplitVecOp_VSELECT(N, OpNo);
2834 break;
2835 case ISD::STRICT_SINT_TO_FP:
2836 case ISD::STRICT_UINT_TO_FP:
2837 case ISD::SINT_TO_FP:
2838 case ISD::UINT_TO_FP:
2839 case ISD::VP_SINT_TO_FP:
2840 case ISD::VP_UINT_TO_FP:
2841 if (N->getValueType(0).bitsLT(
2842 N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType()))
2843 Res = SplitVecOp_TruncateHelper(N);
2844 else
2845 Res = SplitVecOp_UnaryOp(N);
2846 break;
2847 case ISD::FP_TO_SINT_SAT:
2848 case ISD::FP_TO_UINT_SAT:
2849 Res = SplitVecOp_FP_TO_XINT_SAT(N);
2850 break;
2851 case ISD::FP_TO_SINT:
2852 case ISD::FP_TO_UINT:
2853 case ISD::VP_FP_TO_SINT:
2854 case ISD::VP_FP_TO_UINT:
2855 case ISD::STRICT_FP_TO_SINT:
2856 case ISD::STRICT_FP_TO_UINT:
2857 case ISD::STRICT_FP_EXTEND:
2858 case ISD::FP_EXTEND:
2859 case ISD::SIGN_EXTEND:
2860 case ISD::ZERO_EXTEND:
2861 case ISD::ANY_EXTEND:
2862 case ISD::FTRUNC:
2863 Res = SplitVecOp_UnaryOp(N);
2864 break;
2865
2866 case ISD::ANY_EXTEND_VECTOR_INREG:
2867 case ISD::SIGN_EXTEND_VECTOR_INREG:
2868 case ISD::ZERO_EXTEND_VECTOR_INREG:
2869 Res = SplitVecOp_ExtVecInRegOp(N);
2870 break;
2871
2872 case ISD::VECREDUCE_FADD:
2873 case ISD::VECREDUCE_FMUL:
2874 case ISD::VECREDUCE_ADD:
2875 case ISD::VECREDUCE_MUL:
2876 case ISD::VECREDUCE_AND:
2877 case ISD::VECREDUCE_OR:
2878 case ISD::VECREDUCE_XOR:
2879 case ISD::VECREDUCE_SMAX:
2880 case ISD::VECREDUCE_SMIN:
2881 case ISD::VECREDUCE_UMAX:
2882 case ISD::VECREDUCE_UMIN:
2883 case ISD::VECREDUCE_FMAX:
2884 case ISD::VECREDUCE_FMIN:
2885 Res = SplitVecOp_VECREDUCE(N, OpNo);
2886 break;
2887 case ISD::VECREDUCE_SEQ_FADD:
2888 case ISD::VECREDUCE_SEQ_FMUL:
2889 Res = SplitVecOp_VECREDUCE_SEQ(N);
2890 break;
2891 case ISD::VP_REDUCE_FADD:
2892 case ISD::VP_REDUCE_SEQ_FADD:
2893 case ISD::VP_REDUCE_FMUL:
2894 case ISD::VP_REDUCE_SEQ_FMUL:
2895 case ISD::VP_REDUCE_ADD:
2896 case ISD::VP_REDUCE_MUL:
2897 case ISD::VP_REDUCE_AND:
2898 case ISD::VP_REDUCE_OR:
2899 case ISD::VP_REDUCE_XOR:
2900 case ISD::VP_REDUCE_SMAX:
2901 case ISD::VP_REDUCE_SMIN:
2902 case ISD::VP_REDUCE_UMAX:
2903 case ISD::VP_REDUCE_UMIN:
2904 case ISD::VP_REDUCE_FMAX:
2905 case ISD::VP_REDUCE_FMIN:
2906 Res = SplitVecOp_VP_REDUCE(N, OpNo);
2907 break;
2908 }
2909
2910 // If the result is null, the sub-method took care of registering results etc.
2911 if (!Res.getNode()) return false;
2912
2913 // If the result is N, the sub-method updated N in place. Tell the legalizer
2914 // core about this.
2915 if (Res.getNode() == N)
2916 return true;
2917
2918 if (N->isStrictFPOpcode())
2919 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
2920 "Invalid operand expansion");
2921 else
2922 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
2923 "Invalid operand expansion");
2924
2925 ReplaceValueWith(SDValue(N, 0), Res);
2926 return false;
2927 }
2928
SplitVecOp_VSELECT(SDNode * N,unsigned OpNo)2929 SDValue DAGTypeLegalizer::SplitVecOp_VSELECT(SDNode *N, unsigned OpNo) {
2930 // The only possibility for an illegal operand is the mask, since result type
2931 // legalization would have handled this node already otherwise.
2932 assert(OpNo == 0 && "Illegal operand must be mask");
2933
2934 SDValue Mask = N->getOperand(0);
2935 SDValue Src0 = N->getOperand(1);
2936 SDValue Src1 = N->getOperand(2);
2937 EVT Src0VT = Src0.getValueType();
2938 SDLoc DL(N);
2939 assert(Mask.getValueType().isVector() && "VSELECT without a vector mask?");
2940
2941 SDValue Lo, Hi;
2942 GetSplitVector(N->getOperand(0), Lo, Hi);
2943 assert(Lo.getValueType() == Hi.getValueType() &&
2944 "Lo and Hi have differing types");
2945
2946 EVT LoOpVT, HiOpVT;
2947 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(Src0VT);
2948 assert(LoOpVT == HiOpVT && "Asymmetric vector split?");
2949
2950 SDValue LoOp0, HiOp0, LoOp1, HiOp1, LoMask, HiMask;
2951 std::tie(LoOp0, HiOp0) = DAG.SplitVector(Src0, DL);
2952 std::tie(LoOp1, HiOp1) = DAG.SplitVector(Src1, DL);
2953 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
2954
2955 SDValue LoSelect =
2956 DAG.getNode(ISD::VSELECT, DL, LoOpVT, LoMask, LoOp0, LoOp1);
2957 SDValue HiSelect =
2958 DAG.getNode(ISD::VSELECT, DL, HiOpVT, HiMask, HiOp0, HiOp1);
2959
2960 return DAG.getNode(ISD::CONCAT_VECTORS, DL, Src0VT, LoSelect, HiSelect);
2961 }
2962
SplitVecOp_VECREDUCE(SDNode * N,unsigned OpNo)2963 SDValue DAGTypeLegalizer::SplitVecOp_VECREDUCE(SDNode *N, unsigned OpNo) {
2964 EVT ResVT = N->getValueType(0);
2965 SDValue Lo, Hi;
2966 SDLoc dl(N);
2967
2968 SDValue VecOp = N->getOperand(OpNo);
2969 EVT VecVT = VecOp.getValueType();
2970 assert(VecVT.isVector() && "Can only split reduce vector operand");
2971 GetSplitVector(VecOp, Lo, Hi);
2972 EVT LoOpVT, HiOpVT;
2973 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(VecVT);
2974
2975 // Use the appropriate scalar instruction on the split subvectors before
2976 // reducing the now partially reduced smaller vector.
2977 unsigned CombineOpc = ISD::getVecReduceBaseOpcode(N->getOpcode());
2978 SDValue Partial = DAG.getNode(CombineOpc, dl, LoOpVT, Lo, Hi, N->getFlags());
2979 return DAG.getNode(N->getOpcode(), dl, ResVT, Partial, N->getFlags());
2980 }
2981
SplitVecOp_VECREDUCE_SEQ(SDNode * N)2982 SDValue DAGTypeLegalizer::SplitVecOp_VECREDUCE_SEQ(SDNode *N) {
2983 EVT ResVT = N->getValueType(0);
2984 SDValue Lo, Hi;
2985 SDLoc dl(N);
2986
2987 SDValue AccOp = N->getOperand(0);
2988 SDValue VecOp = N->getOperand(1);
2989 SDNodeFlags Flags = N->getFlags();
2990
2991 EVT VecVT = VecOp.getValueType();
2992 assert(VecVT.isVector() && "Can only split reduce vector operand");
2993 GetSplitVector(VecOp, Lo, Hi);
2994 EVT LoOpVT, HiOpVT;
2995 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(VecVT);
2996
2997 // Reduce low half.
2998 SDValue Partial = DAG.getNode(N->getOpcode(), dl, ResVT, AccOp, Lo, Flags);
2999
3000 // Reduce high half, using low half result as initial value.
3001 return DAG.getNode(N->getOpcode(), dl, ResVT, Partial, Hi, Flags);
3002 }
3003
SplitVecOp_VP_REDUCE(SDNode * N,unsigned OpNo)3004 SDValue DAGTypeLegalizer::SplitVecOp_VP_REDUCE(SDNode *N, unsigned OpNo) {
3005 assert(N->isVPOpcode() && "Expected VP opcode");
3006 assert(OpNo == 1 && "Can only split reduce vector operand");
3007
3008 unsigned Opc = N->getOpcode();
3009 EVT ResVT = N->getValueType(0);
3010 SDValue Lo, Hi;
3011 SDLoc dl(N);
3012
3013 SDValue VecOp = N->getOperand(OpNo);
3014 EVT VecVT = VecOp.getValueType();
3015 assert(VecVT.isVector() && "Can only split reduce vector operand");
3016 GetSplitVector(VecOp, Lo, Hi);
3017
3018 SDValue MaskLo, MaskHi;
3019 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(2));
3020
3021 SDValue EVLLo, EVLHi;
3022 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(N->getOperand(3), VecVT, dl);
3023
3024 const SDNodeFlags Flags = N->getFlags();
3025
3026 SDValue ResLo =
3027 DAG.getNode(Opc, dl, ResVT, {N->getOperand(0), Lo, MaskLo, EVLLo}, Flags);
3028 return DAG.getNode(Opc, dl, ResVT, {ResLo, Hi, MaskHi, EVLHi}, Flags);
3029 }
3030
SplitVecOp_UnaryOp(SDNode * N)3031 SDValue DAGTypeLegalizer::SplitVecOp_UnaryOp(SDNode *N) {
3032 // The result has a legal vector type, but the input needs splitting.
3033 EVT ResVT = N->getValueType(0);
3034 SDValue Lo, Hi;
3035 SDLoc dl(N);
3036 GetSplitVector(N->getOperand(N->isStrictFPOpcode() ? 1 : 0), Lo, Hi);
3037 EVT InVT = Lo.getValueType();
3038
3039 EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
3040 InVT.getVectorElementCount());
3041
3042 if (N->isStrictFPOpcode()) {
3043 Lo = DAG.getNode(N->getOpcode(), dl, { OutVT, MVT::Other },
3044 { N->getOperand(0), Lo });
3045 Hi = DAG.getNode(N->getOpcode(), dl, { OutVT, MVT::Other },
3046 { N->getOperand(0), Hi });
3047
3048 // Build a factor node to remember that this operation is independent
3049 // of the other one.
3050 SDValue Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
3051 Hi.getValue(1));
3052
3053 // Legalize the chain result - switch anything that used the old chain to
3054 // use the new one.
3055 ReplaceValueWith(SDValue(N, 1), Ch);
3056 } else if (N->getNumOperands() == 3) {
3057 assert(N->isVPOpcode() && "Expected VP opcode");
3058 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
3059 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
3060 std::tie(EVLLo, EVLHi) =
3061 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), dl);
3062 Lo = DAG.getNode(N->getOpcode(), dl, OutVT, Lo, MaskLo, EVLLo);
3063 Hi = DAG.getNode(N->getOpcode(), dl, OutVT, Hi, MaskHi, EVLHi);
3064 } else {
3065 Lo = DAG.getNode(N->getOpcode(), dl, OutVT, Lo);
3066 Hi = DAG.getNode(N->getOpcode(), dl, OutVT, Hi);
3067 }
3068
3069 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
3070 }
3071
SplitVecOp_BITCAST(SDNode * N)3072 SDValue DAGTypeLegalizer::SplitVecOp_BITCAST(SDNode *N) {
3073 // For example, i64 = BITCAST v4i16 on alpha. Typically the vector will
3074 // end up being split all the way down to individual components. Convert the
3075 // split pieces into integers and reassemble.
3076 SDValue Lo, Hi;
3077 GetSplitVector(N->getOperand(0), Lo, Hi);
3078 Lo = BitConvertToInteger(Lo);
3079 Hi = BitConvertToInteger(Hi);
3080
3081 if (DAG.getDataLayout().isBigEndian())
3082 std::swap(Lo, Hi);
3083
3084 return DAG.getNode(ISD::BITCAST, SDLoc(N), N->getValueType(0),
3085 JoinIntegers(Lo, Hi));
3086 }
3087
SplitVecOp_INSERT_SUBVECTOR(SDNode * N,unsigned OpNo)3088 SDValue DAGTypeLegalizer::SplitVecOp_INSERT_SUBVECTOR(SDNode *N,
3089 unsigned OpNo) {
3090 assert(OpNo == 1 && "Invalid OpNo; can only split SubVec.");
3091 // We know that the result type is legal.
3092 EVT ResVT = N->getValueType(0);
3093
3094 SDValue Vec = N->getOperand(0);
3095 SDValue SubVec = N->getOperand(1);
3096 SDValue Idx = N->getOperand(2);
3097 SDLoc dl(N);
3098
3099 SDValue Lo, Hi;
3100 GetSplitVector(SubVec, Lo, Hi);
3101
3102 uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getZExtValue();
3103 uint64_t LoElts = Lo.getValueType().getVectorMinNumElements();
3104
3105 SDValue FirstInsertion =
3106 DAG.getNode(ISD::INSERT_SUBVECTOR, dl, ResVT, Vec, Lo, Idx);
3107 SDValue SecondInsertion =
3108 DAG.getNode(ISD::INSERT_SUBVECTOR, dl, ResVT, FirstInsertion, Hi,
3109 DAG.getVectorIdxConstant(IdxVal + LoElts, dl));
3110
3111 return SecondInsertion;
3112 }
3113
SplitVecOp_EXTRACT_SUBVECTOR(SDNode * N)3114 SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
3115 // We know that the extracted result type is legal.
3116 EVT SubVT = N->getValueType(0);
3117 SDValue Idx = N->getOperand(1);
3118 SDLoc dl(N);
3119 SDValue Lo, Hi;
3120
3121 GetSplitVector(N->getOperand(0), Lo, Hi);
3122
3123 uint64_t LoEltsMin = Lo.getValueType().getVectorMinNumElements();
3124 uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getZExtValue();
3125
3126 if (IdxVal < LoEltsMin) {
3127 assert(IdxVal + SubVT.getVectorMinNumElements() <= LoEltsMin &&
3128 "Extracted subvector crosses vector split!");
3129 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, SubVT, Lo, Idx);
3130 } else if (SubVT.isScalableVector() ==
3131 N->getOperand(0).getValueType().isScalableVector())
3132 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, SubVT, Hi,
3133 DAG.getVectorIdxConstant(IdxVal - LoEltsMin, dl));
3134
3135 // After this point the DAG node only permits extracting fixed-width
3136 // subvectors from scalable vectors.
3137 assert(SubVT.isFixedLengthVector() &&
3138 "Extracting scalable subvector from fixed-width unsupported");
3139
3140 // If the element type is i1 and we're not promoting the result, then we may
3141 // end up loading the wrong data since the bits are packed tightly into
3142 // bytes. For example, if we extract a v4i1 (legal) from a nxv4i1 (legal)
3143 // type at index 4, then we will load a byte starting at index 0.
3144 if (SubVT.getScalarType() == MVT::i1)
3145 report_fatal_error("Don't know how to extract fixed-width predicate "
3146 "subvector from a scalable predicate vector");
3147
3148 // Spill the vector to the stack. We should use the alignment for
3149 // the smallest part.
3150 SDValue Vec = N->getOperand(0);
3151 EVT VecVT = Vec.getValueType();
3152 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
3153 SDValue StackPtr =
3154 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
3155 auto &MF = DAG.getMachineFunction();
3156 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
3157 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
3158
3159 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
3160 SmallestAlign);
3161
3162 // Extract the subvector by loading the correct part.
3163 StackPtr = TLI.getVectorSubVecPointer(DAG, StackPtr, VecVT, SubVT, Idx);
3164
3165 return DAG.getLoad(
3166 SubVT, dl, Store, StackPtr,
3167 MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()));
3168 }
3169
SplitVecOp_EXTRACT_VECTOR_ELT(SDNode * N)3170 SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
3171 SDValue Vec = N->getOperand(0);
3172 SDValue Idx = N->getOperand(1);
3173 EVT VecVT = Vec.getValueType();
3174
3175 if (const ConstantSDNode *Index = dyn_cast<ConstantSDNode>(Idx)) {
3176 uint64_t IdxVal = Index->getZExtValue();
3177
3178 SDValue Lo, Hi;
3179 GetSplitVector(Vec, Lo, Hi);
3180
3181 uint64_t LoElts = Lo.getValueType().getVectorMinNumElements();
3182
3183 if (IdxVal < LoElts)
3184 return SDValue(DAG.UpdateNodeOperands(N, Lo, Idx), 0);
3185 else if (!Vec.getValueType().isScalableVector())
3186 return SDValue(DAG.UpdateNodeOperands(N, Hi,
3187 DAG.getConstant(IdxVal - LoElts, SDLoc(N),
3188 Idx.getValueType())), 0);
3189 }
3190
3191 // See if the target wants to custom expand this node.
3192 if (CustomLowerNode(N, N->getValueType(0), true))
3193 return SDValue();
3194
3195 // Make the vector elements byte-addressable if they aren't already.
3196 SDLoc dl(N);
3197 EVT EltVT = VecVT.getVectorElementType();
3198 if (VecVT.getScalarSizeInBits() < 8) {
3199 EltVT = MVT::i8;
3200 VecVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
3201 VecVT.getVectorElementCount());
3202 Vec = DAG.getNode(ISD::ANY_EXTEND, dl, VecVT, Vec);
3203 }
3204
3205 // Store the vector to the stack.
3206 // In cases where the vector is illegal it will be broken down into parts
3207 // and stored in parts - we should use the alignment for the smallest part.
3208 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
3209 SDValue StackPtr =
3210 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
3211 auto &MF = DAG.getMachineFunction();
3212 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
3213 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
3214 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
3215 SmallestAlign);
3216
3217 // Load back the required element.
3218 StackPtr = TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Idx);
3219
3220 // FIXME: This is to handle i1 vectors with elements promoted to i8.
3221 // i1 vector handling needs general improvement.
3222 if (N->getValueType(0).bitsLT(EltVT)) {
3223 SDValue Load = DAG.getLoad(EltVT, dl, Store, StackPtr,
3224 MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()));
3225 return DAG.getZExtOrTrunc(Load, dl, N->getValueType(0));
3226 }
3227
3228 return DAG.getExtLoad(
3229 ISD::EXTLOAD, dl, N->getValueType(0), Store, StackPtr,
3230 MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()), EltVT,
3231 commonAlignment(SmallestAlign, EltVT.getFixedSizeInBits() / 8));
3232 }
3233
SplitVecOp_ExtVecInRegOp(SDNode * N)3234 SDValue DAGTypeLegalizer::SplitVecOp_ExtVecInRegOp(SDNode *N) {
3235 SDValue Lo, Hi;
3236
3237 // *_EXTEND_VECTOR_INREG only reference the lower half of the input, so
3238 // splitting the result has the same effect as splitting the input operand.
3239 SplitVecRes_ExtVecInRegOp(N, Lo, Hi);
3240
3241 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), N->getValueType(0), Lo, Hi);
3242 }
3243
SplitVecOp_Gather(MemSDNode * N,unsigned OpNo)3244 SDValue DAGTypeLegalizer::SplitVecOp_Gather(MemSDNode *N, unsigned OpNo) {
3245 (void)OpNo;
3246 SDValue Lo, Hi;
3247 SplitVecRes_Gather(N, Lo, Hi);
3248
3249 SDValue Res = DAG.getNode(ISD::CONCAT_VECTORS, N, N->getValueType(0), Lo, Hi);
3250 ReplaceValueWith(SDValue(N, 0), Res);
3251 return SDValue();
3252 }
3253
SplitVecOp_VP_STORE(VPStoreSDNode * N,unsigned OpNo)3254 SDValue DAGTypeLegalizer::SplitVecOp_VP_STORE(VPStoreSDNode *N, unsigned OpNo) {
3255 assert(N->isUnindexed() && "Indexed vp_store of vector?");
3256 SDValue Ch = N->getChain();
3257 SDValue Ptr = N->getBasePtr();
3258 SDValue Offset = N->getOffset();
3259 assert(Offset.isUndef() && "Unexpected VP store offset");
3260 SDValue Mask = N->getMask();
3261 SDValue EVL = N->getVectorLength();
3262 SDValue Data = N->getValue();
3263 Align Alignment = N->getOriginalAlign();
3264 SDLoc DL(N);
3265
3266 SDValue DataLo, DataHi;
3267 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
3268 // Split Data operand
3269 GetSplitVector(Data, DataLo, DataHi);
3270 else
3271 std::tie(DataLo, DataHi) = DAG.SplitVector(Data, DL);
3272
3273 // Split Mask operand
3274 SDValue MaskLo, MaskHi;
3275 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC) {
3276 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
3277 } else {
3278 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
3279 GetSplitVector(Mask, MaskLo, MaskHi);
3280 else
3281 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
3282 }
3283
3284 EVT MemoryVT = N->getMemoryVT();
3285 EVT LoMemVT, HiMemVT;
3286 bool HiIsEmpty = false;
3287 std::tie(LoMemVT, HiMemVT) =
3288 DAG.GetDependentSplitDestVTs(MemoryVT, DataLo.getValueType(), &HiIsEmpty);
3289
3290 // Split EVL
3291 SDValue EVLLo, EVLHi;
3292 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(EVL, Data.getValueType(), DL);
3293
3294 SDValue Lo, Hi;
3295 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
3296 N->getPointerInfo(), MachineMemOperand::MOStore,
3297 MemoryLocation::UnknownSize, Alignment, N->getAAInfo(), N->getRanges());
3298
3299 Lo = DAG.getStoreVP(Ch, DL, DataLo, Ptr, Offset, MaskLo, EVLLo, LoMemVT, MMO,
3300 N->getAddressingMode(), N->isTruncatingStore(),
3301 N->isCompressingStore());
3302
3303 // If the hi vp_store has zero storage size, only the lo vp_store is needed.
3304 if (HiIsEmpty)
3305 return Lo;
3306
3307 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, DL, LoMemVT, DAG,
3308 N->isCompressingStore());
3309
3310 MachinePointerInfo MPI;
3311 if (LoMemVT.isScalableVector()) {
3312 Alignment = commonAlignment(Alignment,
3313 LoMemVT.getSizeInBits().getKnownMinValue() / 8);
3314 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
3315 } else
3316 MPI = N->getPointerInfo().getWithOffset(
3317 LoMemVT.getStoreSize().getFixedValue());
3318
3319 MMO = DAG.getMachineFunction().getMachineMemOperand(
3320 MPI, MachineMemOperand::MOStore, MemoryLocation::UnknownSize, Alignment,
3321 N->getAAInfo(), N->getRanges());
3322
3323 Hi = DAG.getStoreVP(Ch, DL, DataHi, Ptr, Offset, MaskHi, EVLHi, HiMemVT, MMO,
3324 N->getAddressingMode(), N->isTruncatingStore(),
3325 N->isCompressingStore());
3326
3327 // Build a factor node to remember that this store is independent of the
3328 // other one.
3329 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
3330 }
3331
SplitVecOp_VP_STRIDED_STORE(VPStridedStoreSDNode * N,unsigned OpNo)3332 SDValue DAGTypeLegalizer::SplitVecOp_VP_STRIDED_STORE(VPStridedStoreSDNode *N,
3333 unsigned OpNo) {
3334 assert(N->isUnindexed() && "Indexed vp_strided_store of a vector?");
3335 assert(N->getOffset().isUndef() && "Unexpected VP strided store offset");
3336
3337 SDLoc DL(N);
3338
3339 SDValue Data = N->getValue();
3340 SDValue LoData, HiData;
3341 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
3342 GetSplitVector(Data, LoData, HiData);
3343 else
3344 std::tie(LoData, HiData) = DAG.SplitVector(Data, DL);
3345
3346 EVT LoMemVT, HiMemVT;
3347 bool HiIsEmpty = false;
3348 std::tie(LoMemVT, HiMemVT) = DAG.GetDependentSplitDestVTs(
3349 N->getMemoryVT(), LoData.getValueType(), &HiIsEmpty);
3350
3351 SDValue Mask = N->getMask();
3352 SDValue LoMask, HiMask;
3353 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC)
3354 SplitVecRes_SETCC(Mask.getNode(), LoMask, HiMask);
3355 else if (getTypeAction(Mask.getValueType()) ==
3356 TargetLowering::TypeSplitVector)
3357 GetSplitVector(Mask, LoMask, HiMask);
3358 else
3359 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
3360
3361 SDValue LoEVL, HiEVL;
3362 std::tie(LoEVL, HiEVL) =
3363 DAG.SplitEVL(N->getVectorLength(), Data.getValueType(), DL);
3364
3365 // Generate the low vp_strided_store
3366 SDValue Lo = DAG.getStridedStoreVP(
3367 N->getChain(), DL, LoData, N->getBasePtr(), N->getOffset(),
3368 N->getStride(), LoMask, LoEVL, LoMemVT, N->getMemOperand(),
3369 N->getAddressingMode(), N->isTruncatingStore(), N->isCompressingStore());
3370
3371 // If the high vp_strided_store has zero storage size, only the low
3372 // vp_strided_store is needed.
3373 if (HiIsEmpty)
3374 return Lo;
3375
3376 // Generate the high vp_strided_store.
3377 // To calculate the high base address, we need to sum to the low base
3378 // address stride number of bytes for each element already stored by low,
3379 // that is: Ptr = Ptr + (LoEVL * Stride)
3380 EVT PtrVT = N->getBasePtr().getValueType();
3381 SDValue Increment =
3382 DAG.getNode(ISD::MUL, DL, PtrVT, LoEVL,
3383 DAG.getSExtOrTrunc(N->getStride(), DL, PtrVT));
3384 SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, N->getBasePtr(), Increment);
3385
3386 Align Alignment = N->getOriginalAlign();
3387 if (LoMemVT.isScalableVector())
3388 Alignment = commonAlignment(Alignment,
3389 LoMemVT.getSizeInBits().getKnownMinValue() / 8);
3390
3391 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
3392 MachinePointerInfo(N->getPointerInfo().getAddrSpace()),
3393 MachineMemOperand::MOStore, MemoryLocation::UnknownSize, Alignment,
3394 N->getAAInfo(), N->getRanges());
3395
3396 SDValue Hi = DAG.getStridedStoreVP(
3397 N->getChain(), DL, HiData, Ptr, N->getOffset(), N->getStride(), HiMask,
3398 HiEVL, HiMemVT, MMO, N->getAddressingMode(), N->isTruncatingStore(),
3399 N->isCompressingStore());
3400
3401 // Build a factor node to remember that this store is independent of the
3402 // other one.
3403 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
3404 }
3405
SplitVecOp_MSTORE(MaskedStoreSDNode * N,unsigned OpNo)3406 SDValue DAGTypeLegalizer::SplitVecOp_MSTORE(MaskedStoreSDNode *N,
3407 unsigned OpNo) {
3408 assert(N->isUnindexed() && "Indexed masked store of vector?");
3409 SDValue Ch = N->getChain();
3410 SDValue Ptr = N->getBasePtr();
3411 SDValue Offset = N->getOffset();
3412 assert(Offset.isUndef() && "Unexpected indexed masked store offset");
3413 SDValue Mask = N->getMask();
3414 SDValue Data = N->getValue();
3415 Align Alignment = N->getOriginalAlign();
3416 SDLoc DL(N);
3417
3418 SDValue DataLo, DataHi;
3419 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
3420 // Split Data operand
3421 GetSplitVector(Data, DataLo, DataHi);
3422 else
3423 std::tie(DataLo, DataHi) = DAG.SplitVector(Data, DL);
3424
3425 // Split Mask operand
3426 SDValue MaskLo, MaskHi;
3427 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC) {
3428 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
3429 } else {
3430 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
3431 GetSplitVector(Mask, MaskLo, MaskHi);
3432 else
3433 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
3434 }
3435
3436 EVT MemoryVT = N->getMemoryVT();
3437 EVT LoMemVT, HiMemVT;
3438 bool HiIsEmpty = false;
3439 std::tie(LoMemVT, HiMemVT) =
3440 DAG.GetDependentSplitDestVTs(MemoryVT, DataLo.getValueType(), &HiIsEmpty);
3441
3442 SDValue Lo, Hi, Res;
3443 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
3444 N->getPointerInfo(), MachineMemOperand::MOStore,
3445 MemoryLocation::UnknownSize, Alignment, N->getAAInfo(), N->getRanges());
3446
3447 Lo = DAG.getMaskedStore(Ch, DL, DataLo, Ptr, Offset, MaskLo, LoMemVT, MMO,
3448 N->getAddressingMode(), N->isTruncatingStore(),
3449 N->isCompressingStore());
3450
3451 if (HiIsEmpty) {
3452 // The hi masked store has zero storage size.
3453 // Only the lo masked store is needed.
3454 Res = Lo;
3455 } else {
3456
3457 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, DL, LoMemVT, DAG,
3458 N->isCompressingStore());
3459
3460 MachinePointerInfo MPI;
3461 if (LoMemVT.isScalableVector()) {
3462 Alignment = commonAlignment(
3463 Alignment, LoMemVT.getSizeInBits().getKnownMinValue() / 8);
3464 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
3465 } else
3466 MPI = N->getPointerInfo().getWithOffset(
3467 LoMemVT.getStoreSize().getFixedValue());
3468
3469 MMO = DAG.getMachineFunction().getMachineMemOperand(
3470 MPI, MachineMemOperand::MOStore, MemoryLocation::UnknownSize, Alignment,
3471 N->getAAInfo(), N->getRanges());
3472
3473 Hi = DAG.getMaskedStore(Ch, DL, DataHi, Ptr, Offset, MaskHi, HiMemVT, MMO,
3474 N->getAddressingMode(), N->isTruncatingStore(),
3475 N->isCompressingStore());
3476
3477 // Build a factor node to remember that this store is independent of the
3478 // other one.
3479 Res = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
3480 }
3481
3482 return Res;
3483 }
3484
SplitVecOp_Scatter(MemSDNode * N,unsigned OpNo)3485 SDValue DAGTypeLegalizer::SplitVecOp_Scatter(MemSDNode *N, unsigned OpNo) {
3486 SDValue Ch = N->getChain();
3487 SDValue Ptr = N->getBasePtr();
3488 EVT MemoryVT = N->getMemoryVT();
3489 Align Alignment = N->getOriginalAlign();
3490 SDLoc DL(N);
3491 struct Operands {
3492 SDValue Mask;
3493 SDValue Index;
3494 SDValue Scale;
3495 SDValue Data;
3496 } Ops = [&]() -> Operands {
3497 if (auto *MSC = dyn_cast<MaskedScatterSDNode>(N)) {
3498 return {MSC->getMask(), MSC->getIndex(), MSC->getScale(),
3499 MSC->getValue()};
3500 }
3501 auto *VPSC = cast<VPScatterSDNode>(N);
3502 return {VPSC->getMask(), VPSC->getIndex(), VPSC->getScale(),
3503 VPSC->getValue()};
3504 }();
3505 // Split all operands
3506
3507 EVT LoMemVT, HiMemVT;
3508 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
3509
3510 SDValue DataLo, DataHi;
3511 if (getTypeAction(Ops.Data.getValueType()) == TargetLowering::TypeSplitVector)
3512 // Split Data operand
3513 GetSplitVector(Ops.Data, DataLo, DataHi);
3514 else
3515 std::tie(DataLo, DataHi) = DAG.SplitVector(Ops.Data, DL);
3516
3517 // Split Mask operand
3518 SDValue MaskLo, MaskHi;
3519 if (OpNo == 1 && Ops.Mask.getOpcode() == ISD::SETCC) {
3520 SplitVecRes_SETCC(Ops.Mask.getNode(), MaskLo, MaskHi);
3521 } else {
3522 std::tie(MaskLo, MaskHi) = SplitMask(Ops.Mask, DL);
3523 }
3524
3525 SDValue IndexHi, IndexLo;
3526 if (getTypeAction(Ops.Index.getValueType()) ==
3527 TargetLowering::TypeSplitVector)
3528 GetSplitVector(Ops.Index, IndexLo, IndexHi);
3529 else
3530 std::tie(IndexLo, IndexHi) = DAG.SplitVector(Ops.Index, DL);
3531
3532 SDValue Lo;
3533 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
3534 N->getPointerInfo(), MachineMemOperand::MOStore,
3535 MemoryLocation::UnknownSize, Alignment, N->getAAInfo(), N->getRanges());
3536
3537 if (auto *MSC = dyn_cast<MaskedScatterSDNode>(N)) {
3538 SDValue OpsLo[] = {Ch, DataLo, MaskLo, Ptr, IndexLo, Ops.Scale};
3539 Lo =
3540 DAG.getMaskedScatter(DAG.getVTList(MVT::Other), LoMemVT, DL, OpsLo, MMO,
3541 MSC->getIndexType(), MSC->isTruncatingStore());
3542
3543 // The order of the Scatter operation after split is well defined. The "Hi"
3544 // part comes after the "Lo". So these two operations should be chained one
3545 // after another.
3546 SDValue OpsHi[] = {Lo, DataHi, MaskHi, Ptr, IndexHi, Ops.Scale};
3547 return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), HiMemVT, DL, OpsHi,
3548 MMO, MSC->getIndexType(),
3549 MSC->isTruncatingStore());
3550 }
3551 auto *VPSC = cast<VPScatterSDNode>(N);
3552 SDValue EVLLo, EVLHi;
3553 std::tie(EVLLo, EVLHi) =
3554 DAG.SplitEVL(VPSC->getVectorLength(), Ops.Data.getValueType(), DL);
3555
3556 SDValue OpsLo[] = {Ch, DataLo, Ptr, IndexLo, Ops.Scale, MaskLo, EVLLo};
3557 Lo = DAG.getScatterVP(DAG.getVTList(MVT::Other), LoMemVT, DL, OpsLo, MMO,
3558 VPSC->getIndexType());
3559
3560 // The order of the Scatter operation after split is well defined. The "Hi"
3561 // part comes after the "Lo". So these two operations should be chained one
3562 // after another.
3563 SDValue OpsHi[] = {Lo, DataHi, Ptr, IndexHi, Ops.Scale, MaskHi, EVLHi};
3564 return DAG.getScatterVP(DAG.getVTList(MVT::Other), HiMemVT, DL, OpsHi, MMO,
3565 VPSC->getIndexType());
3566 }
3567
SplitVecOp_STORE(StoreSDNode * N,unsigned OpNo)3568 SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) {
3569 assert(N->isUnindexed() && "Indexed store of vector?");
3570 assert(OpNo == 1 && "Can only split the stored value");
3571 SDLoc DL(N);
3572
3573 bool isTruncating = N->isTruncatingStore();
3574 SDValue Ch = N->getChain();
3575 SDValue Ptr = N->getBasePtr();
3576 EVT MemoryVT = N->getMemoryVT();
3577 Align Alignment = N->getOriginalAlign();
3578 MachineMemOperand::Flags MMOFlags = N->getMemOperand()->getFlags();
3579 AAMDNodes AAInfo = N->getAAInfo();
3580 SDValue Lo, Hi;
3581 GetSplitVector(N->getOperand(1), Lo, Hi);
3582
3583 EVT LoMemVT, HiMemVT;
3584 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
3585
3586 // Scalarize if the split halves are not byte-sized.
3587 if (!LoMemVT.isByteSized() || !HiMemVT.isByteSized())
3588 return TLI.scalarizeVectorStore(N, DAG);
3589
3590 if (isTruncating)
3591 Lo = DAG.getTruncStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), LoMemVT,
3592 Alignment, MMOFlags, AAInfo);
3593 else
3594 Lo = DAG.getStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), Alignment, MMOFlags,
3595 AAInfo);
3596
3597 MachinePointerInfo MPI;
3598 IncrementPointer(N, LoMemVT, MPI, Ptr);
3599
3600 if (isTruncating)
3601 Hi = DAG.getTruncStore(Ch, DL, Hi, Ptr, MPI,
3602 HiMemVT, Alignment, MMOFlags, AAInfo);
3603 else
3604 Hi = DAG.getStore(Ch, DL, Hi, Ptr, MPI, Alignment, MMOFlags, AAInfo);
3605
3606 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
3607 }
3608
SplitVecOp_CONCAT_VECTORS(SDNode * N)3609 SDValue DAGTypeLegalizer::SplitVecOp_CONCAT_VECTORS(SDNode *N) {
3610 SDLoc DL(N);
3611
3612 // The input operands all must have the same type, and we know the result
3613 // type is valid. Convert this to a buildvector which extracts all the
3614 // input elements.
3615 // TODO: If the input elements are power-two vectors, we could convert this to
3616 // a new CONCAT_VECTORS node with elements that are half-wide.
3617 SmallVector<SDValue, 32> Elts;
3618 EVT EltVT = N->getValueType(0).getVectorElementType();
3619 for (const SDValue &Op : N->op_values()) {
3620 for (unsigned i = 0, e = Op.getValueType().getVectorNumElements();
3621 i != e; ++i) {
3622 Elts.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltVT, Op,
3623 DAG.getVectorIdxConstant(i, DL)));
3624 }
3625 }
3626
3627 return DAG.getBuildVector(N->getValueType(0), DL, Elts);
3628 }
3629
SplitVecOp_TruncateHelper(SDNode * N)3630 SDValue DAGTypeLegalizer::SplitVecOp_TruncateHelper(SDNode *N) {
3631 // The result type is legal, but the input type is illegal. If splitting
3632 // ends up with the result type of each half still being legal, just
3633 // do that. If, however, that would result in an illegal result type,
3634 // we can try to get more clever with power-two vectors. Specifically,
3635 // split the input type, but also widen the result element size, then
3636 // concatenate the halves and truncate again. For example, consider a target
3637 // where v8i8 is legal and v8i32 is not (ARM, which doesn't have 256-bit
3638 // vectors). To perform a "%res = v8i8 trunc v8i32 %in" we do:
3639 // %inlo = v4i32 extract_subvector %in, 0
3640 // %inhi = v4i32 extract_subvector %in, 4
3641 // %lo16 = v4i16 trunc v4i32 %inlo
3642 // %hi16 = v4i16 trunc v4i32 %inhi
3643 // %in16 = v8i16 concat_vectors v4i16 %lo16, v4i16 %hi16
3644 // %res = v8i8 trunc v8i16 %in16
3645 //
3646 // Without this transform, the original truncate would end up being
3647 // scalarized, which is pretty much always a last resort.
3648 unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
3649 SDValue InVec = N->getOperand(OpNo);
3650 EVT InVT = InVec->getValueType(0);
3651 EVT OutVT = N->getValueType(0);
3652 ElementCount NumElements = OutVT.getVectorElementCount();
3653 bool IsFloat = OutVT.isFloatingPoint();
3654
3655 unsigned InElementSize = InVT.getScalarSizeInBits();
3656 unsigned OutElementSize = OutVT.getScalarSizeInBits();
3657
3658 // Determine the split output VT. If its legal we can just split dirctly.
3659 EVT LoOutVT, HiOutVT;
3660 std::tie(LoOutVT, HiOutVT) = DAG.GetSplitDestVTs(OutVT);
3661 assert(LoOutVT == HiOutVT && "Unequal split?");
3662
3663 // If the input elements are only 1/2 the width of the result elements,
3664 // just use the normal splitting. Our trick only work if there's room
3665 // to split more than once.
3666 if (isTypeLegal(LoOutVT) ||
3667 InElementSize <= OutElementSize * 2)
3668 return SplitVecOp_UnaryOp(N);
3669 SDLoc DL(N);
3670
3671 // Don't touch if this will be scalarized.
3672 EVT FinalVT = InVT;
3673 while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
3674 FinalVT = FinalVT.getHalfNumVectorElementsVT(*DAG.getContext());
3675
3676 if (getTypeAction(FinalVT) == TargetLowering::TypeScalarizeVector)
3677 return SplitVecOp_UnaryOp(N);
3678
3679 // Get the split input vector.
3680 SDValue InLoVec, InHiVec;
3681 GetSplitVector(InVec, InLoVec, InHiVec);
3682
3683 // Truncate them to 1/2 the element size.
3684 //
3685 // This assumes the number of elements is a power of two; any vector that
3686 // isn't should be widened, not split.
3687 EVT HalfElementVT = IsFloat ?
3688 EVT::getFloatingPointVT(InElementSize/2) :
3689 EVT::getIntegerVT(*DAG.getContext(), InElementSize/2);
3690 EVT HalfVT = EVT::getVectorVT(*DAG.getContext(), HalfElementVT,
3691 NumElements.divideCoefficientBy(2));
3692
3693 SDValue HalfLo;
3694 SDValue HalfHi;
3695 SDValue Chain;
3696 if (N->isStrictFPOpcode()) {
3697 HalfLo = DAG.getNode(N->getOpcode(), DL, {HalfVT, MVT::Other},
3698 {N->getOperand(0), InLoVec});
3699 HalfHi = DAG.getNode(N->getOpcode(), DL, {HalfVT, MVT::Other},
3700 {N->getOperand(0), InHiVec});
3701 // Legalize the chain result - switch anything that used the old chain to
3702 // use the new one.
3703 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, HalfLo.getValue(1),
3704 HalfHi.getValue(1));
3705 } else {
3706 HalfLo = DAG.getNode(N->getOpcode(), DL, HalfVT, InLoVec);
3707 HalfHi = DAG.getNode(N->getOpcode(), DL, HalfVT, InHiVec);
3708 }
3709
3710 // Concatenate them to get the full intermediate truncation result.
3711 EVT InterVT = EVT::getVectorVT(*DAG.getContext(), HalfElementVT, NumElements);
3712 SDValue InterVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InterVT, HalfLo,
3713 HalfHi);
3714 // Now finish up by truncating all the way down to the original result
3715 // type. This should normally be something that ends up being legal directly,
3716 // but in theory if a target has very wide vectors and an annoyingly
3717 // restricted set of legal types, this split can chain to build things up.
3718
3719 if (N->isStrictFPOpcode()) {
3720 SDValue Res = DAG.getNode(
3721 ISD::STRICT_FP_ROUND, DL, {OutVT, MVT::Other},
3722 {Chain, InterVec,
3723 DAG.getTargetConstant(0, DL, TLI.getPointerTy(DAG.getDataLayout()))});
3724 // Relink the chain
3725 ReplaceValueWith(SDValue(N, 1), SDValue(Res.getNode(), 1));
3726 return Res;
3727 }
3728
3729 return IsFloat
3730 ? DAG.getNode(ISD::FP_ROUND, DL, OutVT, InterVec,
3731 DAG.getTargetConstant(
3732 0, DL, TLI.getPointerTy(DAG.getDataLayout())))
3733 : DAG.getNode(ISD::TRUNCATE, DL, OutVT, InterVec);
3734 }
3735
SplitVecOp_VSETCC(SDNode * N)3736 SDValue DAGTypeLegalizer::SplitVecOp_VSETCC(SDNode *N) {
3737 assert(N->getValueType(0).isVector() &&
3738 N->getOperand(0).getValueType().isVector() &&
3739 "Operand types must be vectors");
3740 // The result has a legal vector type, but the input needs splitting.
3741 SDValue Lo0, Hi0, Lo1, Hi1, LoRes, HiRes;
3742 SDLoc DL(N);
3743 GetSplitVector(N->getOperand(0), Lo0, Hi0);
3744 GetSplitVector(N->getOperand(1), Lo1, Hi1);
3745 auto PartEltCnt = Lo0.getValueType().getVectorElementCount();
3746
3747 LLVMContext &Context = *DAG.getContext();
3748 EVT PartResVT = EVT::getVectorVT(Context, MVT::i1, PartEltCnt);
3749 EVT WideResVT = EVT::getVectorVT(Context, MVT::i1, PartEltCnt*2);
3750
3751 if (N->getOpcode() == ISD::SETCC) {
3752 LoRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Lo0, Lo1, N->getOperand(2));
3753 HiRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Hi0, Hi1, N->getOperand(2));
3754 } else {
3755 assert(N->getOpcode() == ISD::VP_SETCC && "Expected VP_SETCC opcode");
3756 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
3757 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(3));
3758 std::tie(EVLLo, EVLHi) =
3759 DAG.SplitEVL(N->getOperand(4), N->getValueType(0), DL);
3760 LoRes = DAG.getNode(ISD::VP_SETCC, DL, PartResVT, Lo0, Lo1,
3761 N->getOperand(2), MaskLo, EVLLo);
3762 HiRes = DAG.getNode(ISD::VP_SETCC, DL, PartResVT, Hi0, Hi1,
3763 N->getOperand(2), MaskHi, EVLHi);
3764 }
3765 SDValue Con = DAG.getNode(ISD::CONCAT_VECTORS, DL, WideResVT, LoRes, HiRes);
3766
3767 EVT OpVT = N->getOperand(0).getValueType();
3768 ISD::NodeType ExtendCode =
3769 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
3770 return DAG.getNode(ExtendCode, DL, N->getValueType(0), Con);
3771 }
3772
3773
SplitVecOp_FP_ROUND(SDNode * N)3774 SDValue DAGTypeLegalizer::SplitVecOp_FP_ROUND(SDNode *N) {
3775 // The result has a legal vector type, but the input needs splitting.
3776 EVT ResVT = N->getValueType(0);
3777 SDValue Lo, Hi;
3778 SDLoc DL(N);
3779 GetSplitVector(N->getOperand(N->isStrictFPOpcode() ? 1 : 0), Lo, Hi);
3780 EVT InVT = Lo.getValueType();
3781
3782 EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
3783 InVT.getVectorElementCount());
3784
3785 if (N->isStrictFPOpcode()) {
3786 Lo = DAG.getNode(N->getOpcode(), DL, { OutVT, MVT::Other },
3787 { N->getOperand(0), Lo, N->getOperand(2) });
3788 Hi = DAG.getNode(N->getOpcode(), DL, { OutVT, MVT::Other },
3789 { N->getOperand(0), Hi, N->getOperand(2) });
3790 // Legalize the chain result - switch anything that used the old chain to
3791 // use the new one.
3792 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
3793 Lo.getValue(1), Hi.getValue(1));
3794 ReplaceValueWith(SDValue(N, 1), NewChain);
3795 } else if (N->getOpcode() == ISD::VP_FP_ROUND) {
3796 SDValue MaskLo, MaskHi, EVLLo, EVLHi;
3797 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));
3798 std::tie(EVLLo, EVLHi) =
3799 DAG.SplitEVL(N->getOperand(2), N->getValueType(0), DL);
3800 Lo = DAG.getNode(ISD::VP_FP_ROUND, DL, OutVT, Lo, MaskLo, EVLLo);
3801 Hi = DAG.getNode(ISD::VP_FP_ROUND, DL, OutVT, Hi, MaskHi, EVLHi);
3802 } else {
3803 Lo = DAG.getNode(ISD::FP_ROUND, DL, OutVT, Lo, N->getOperand(1));
3804 Hi = DAG.getNode(ISD::FP_ROUND, DL, OutVT, Hi, N->getOperand(1));
3805 }
3806
3807 return DAG.getNode(ISD::CONCAT_VECTORS, DL, ResVT, Lo, Hi);
3808 }
3809
SplitVecOp_FCOPYSIGN(SDNode * N)3810 SDValue DAGTypeLegalizer::SplitVecOp_FCOPYSIGN(SDNode *N) {
3811 // The result (and the first input) has a legal vector type, but the second
3812 // input needs splitting.
3813
3814 SDLoc DL(N);
3815
3816 EVT LHSLoVT, LHSHiVT;
3817 std::tie(LHSLoVT, LHSHiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
3818
3819 if (!isTypeLegal(LHSLoVT) || !isTypeLegal(LHSHiVT))
3820 return DAG.UnrollVectorOp(N, N->getValueType(0).getVectorNumElements());
3821
3822 SDValue LHSLo, LHSHi;
3823 std::tie(LHSLo, LHSHi) =
3824 DAG.SplitVector(N->getOperand(0), DL, LHSLoVT, LHSHiVT);
3825
3826 SDValue RHSLo, RHSHi;
3827 std::tie(RHSLo, RHSHi) = DAG.SplitVector(N->getOperand(1), DL);
3828
3829 SDValue Lo = DAG.getNode(ISD::FCOPYSIGN, DL, LHSLoVT, LHSLo, RHSLo);
3830 SDValue Hi = DAG.getNode(ISD::FCOPYSIGN, DL, LHSHiVT, LHSHi, RHSHi);
3831
3832 return DAG.getNode(ISD::CONCAT_VECTORS, DL, N->getValueType(0), Lo, Hi);
3833 }
3834
SplitVecOp_FP_TO_XINT_SAT(SDNode * N)3835 SDValue DAGTypeLegalizer::SplitVecOp_FP_TO_XINT_SAT(SDNode *N) {
3836 EVT ResVT = N->getValueType(0);
3837 SDValue Lo, Hi;
3838 SDLoc dl(N);
3839 GetSplitVector(N->getOperand(0), Lo, Hi);
3840 EVT InVT = Lo.getValueType();
3841
3842 EVT NewResVT =
3843 EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
3844 InVT.getVectorElementCount());
3845
3846 Lo = DAG.getNode(N->getOpcode(), dl, NewResVT, Lo, N->getOperand(1));
3847 Hi = DAG.getNode(N->getOpcode(), dl, NewResVT, Hi, N->getOperand(1));
3848
3849 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
3850 }
3851
3852 //===----------------------------------------------------------------------===//
3853 // Result Vector Widening
3854 //===----------------------------------------------------------------------===//
3855
WidenVectorResult(SDNode * N,unsigned ResNo)3856 void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
3857 LLVM_DEBUG(dbgs() << "Widen node result " << ResNo << ": "; N->dump(&DAG);
3858 dbgs() << "\n");
3859
3860 // See if the target wants to custom widen this node.
3861 if (CustomWidenLowerNode(N, N->getValueType(ResNo)))
3862 return;
3863
3864 SDValue Res = SDValue();
3865
3866 auto unrollExpandedOp = [&]() {
3867 // We're going to widen this vector op to a legal type by padding with undef
3868 // elements. If the wide vector op is eventually going to be expanded to
3869 // scalar libcalls, then unroll into scalar ops now to avoid unnecessary
3870 // libcalls on the undef elements.
3871 EVT VT = N->getValueType(0);
3872 EVT WideVecVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
3873 if (!TLI.isOperationLegalOrCustom(N->getOpcode(), WideVecVT) &&
3874 TLI.isOperationExpand(N->getOpcode(), VT.getScalarType())) {
3875 Res = DAG.UnrollVectorOp(N, WideVecVT.getVectorNumElements());
3876 return true;
3877 }
3878 return false;
3879 };
3880
3881 switch (N->getOpcode()) {
3882 default:
3883 #ifndef NDEBUG
3884 dbgs() << "WidenVectorResult #" << ResNo << ": ";
3885 N->dump(&DAG);
3886 dbgs() << "\n";
3887 #endif
3888 llvm_unreachable("Do not know how to widen the result of this operator!");
3889
3890 case ISD::MERGE_VALUES: Res = WidenVecRes_MERGE_VALUES(N, ResNo); break;
3891 case ISD::BITCAST: Res = WidenVecRes_BITCAST(N); break;
3892 case ISD::BUILD_VECTOR: Res = WidenVecRes_BUILD_VECTOR(N); break;
3893 case ISD::CONCAT_VECTORS: Res = WidenVecRes_CONCAT_VECTORS(N); break;
3894 case ISD::INSERT_SUBVECTOR:
3895 Res = WidenVecRes_INSERT_SUBVECTOR(N);
3896 break;
3897 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecRes_EXTRACT_SUBVECTOR(N); break;
3898 case ISD::INSERT_VECTOR_ELT: Res = WidenVecRes_INSERT_VECTOR_ELT(N); break;
3899 case ISD::LOAD: Res = WidenVecRes_LOAD(N); break;
3900 case ISD::STEP_VECTOR:
3901 case ISD::SPLAT_VECTOR:
3902 case ISD::SCALAR_TO_VECTOR:
3903 Res = WidenVecRes_ScalarOp(N);
3904 break;
3905 case ISD::SIGN_EXTEND_INREG: Res = WidenVecRes_InregOp(N); break;
3906 case ISD::VSELECT:
3907 case ISD::SELECT:
3908 case ISD::VP_SELECT:
3909 case ISD::VP_MERGE:
3910 Res = WidenVecRes_Select(N);
3911 break;
3912 case ISD::SELECT_CC: Res = WidenVecRes_SELECT_CC(N); break;
3913 case ISD::VP_SETCC:
3914 case ISD::SETCC: Res = WidenVecRes_SETCC(N); break;
3915 case ISD::UNDEF: Res = WidenVecRes_UNDEF(N); break;
3916 case ISD::VECTOR_SHUFFLE:
3917 Res = WidenVecRes_VECTOR_SHUFFLE(cast<ShuffleVectorSDNode>(N));
3918 break;
3919 case ISD::VP_LOAD:
3920 Res = WidenVecRes_VP_LOAD(cast<VPLoadSDNode>(N));
3921 break;
3922 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
3923 Res = WidenVecRes_VP_STRIDED_LOAD(cast<VPStridedLoadSDNode>(N));
3924 break;
3925 case ISD::MLOAD:
3926 Res = WidenVecRes_MLOAD(cast<MaskedLoadSDNode>(N));
3927 break;
3928 case ISD::MGATHER:
3929 Res = WidenVecRes_MGATHER(cast<MaskedGatherSDNode>(N));
3930 break;
3931 case ISD::VP_GATHER:
3932 Res = WidenVecRes_VP_GATHER(cast<VPGatherSDNode>(N));
3933 break;
3934 case ISD::VECTOR_REVERSE:
3935 Res = WidenVecRes_VECTOR_REVERSE(N);
3936 break;
3937
3938 case ISD::ADD: case ISD::VP_ADD:
3939 case ISD::AND: case ISD::VP_AND:
3940 case ISD::MUL: case ISD::VP_MUL:
3941 case ISD::MULHS:
3942 case ISD::MULHU:
3943 case ISD::OR: case ISD::VP_OR:
3944 case ISD::SUB: case ISD::VP_SUB:
3945 case ISD::XOR: case ISD::VP_XOR:
3946 case ISD::SHL: case ISD::VP_SHL:
3947 case ISD::SRA: case ISD::VP_ASHR:
3948 case ISD::SRL: case ISD::VP_LSHR:
3949 case ISD::FMINNUM: case ISD::VP_FMINNUM:
3950 case ISD::FMAXNUM: case ISD::VP_FMAXNUM:
3951 case ISD::FMINIMUM:
3952 case ISD::FMAXIMUM:
3953 case ISD::SMIN: case ISD::VP_SMIN:
3954 case ISD::SMAX: case ISD::VP_SMAX:
3955 case ISD::UMIN: case ISD::VP_UMIN:
3956 case ISD::UMAX: case ISD::VP_UMAX:
3957 case ISD::UADDSAT:
3958 case ISD::SADDSAT:
3959 case ISD::USUBSAT:
3960 case ISD::SSUBSAT:
3961 case ISD::SSHLSAT:
3962 case ISD::USHLSAT:
3963 case ISD::ROTL:
3964 case ISD::ROTR:
3965 case ISD::AVGFLOORS:
3966 case ISD::AVGFLOORU:
3967 case ISD::AVGCEILS:
3968 case ISD::AVGCEILU:
3969 // Vector-predicated binary op widening. Note that -- unlike the
3970 // unpredicated versions -- we don't have to worry about trapping on
3971 // operations like UDIV, FADD, etc., as we pass on the original vector
3972 // length parameter. This means the widened elements containing garbage
3973 // aren't active.
3974 case ISD::VP_SDIV:
3975 case ISD::VP_UDIV:
3976 case ISD::VP_SREM:
3977 case ISD::VP_UREM:
3978 case ISD::VP_FADD:
3979 case ISD::VP_FSUB:
3980 case ISD::VP_FMUL:
3981 case ISD::VP_FDIV:
3982 case ISD::VP_FREM:
3983 case ISD::VP_FCOPYSIGN:
3984 Res = WidenVecRes_Binary(N);
3985 break;
3986
3987 case ISD::FPOW:
3988 case ISD::FREM:
3989 if (unrollExpandedOp())
3990 break;
3991 // If the target has custom/legal support for the scalar FP intrinsic ops
3992 // (they are probably not destined to become libcalls), then widen those
3993 // like any other binary ops.
3994 [[fallthrough]];
3995
3996 case ISD::FADD:
3997 case ISD::FMUL:
3998 case ISD::FSUB:
3999 case ISD::FDIV:
4000 case ISD::SDIV:
4001 case ISD::UDIV:
4002 case ISD::SREM:
4003 case ISD::UREM:
4004 Res = WidenVecRes_BinaryCanTrap(N);
4005 break;
4006
4007 case ISD::SMULFIX:
4008 case ISD::SMULFIXSAT:
4009 case ISD::UMULFIX:
4010 case ISD::UMULFIXSAT:
4011 // These are binary operations, but with an extra operand that shouldn't
4012 // be widened (the scale).
4013 Res = WidenVecRes_BinaryWithExtraScalarOp(N);
4014 break;
4015
4016 #define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
4017 case ISD::STRICT_##DAGN:
4018 #include "llvm/IR/ConstrainedOps.def"
4019 Res = WidenVecRes_StrictFP(N);
4020 break;
4021
4022 case ISD::UADDO:
4023 case ISD::SADDO:
4024 case ISD::USUBO:
4025 case ISD::SSUBO:
4026 case ISD::UMULO:
4027 case ISD::SMULO:
4028 Res = WidenVecRes_OverflowOp(N, ResNo);
4029 break;
4030
4031 case ISD::FCOPYSIGN:
4032 Res = WidenVecRes_FCOPYSIGN(N);
4033 break;
4034
4035 case ISD::IS_FPCLASS:
4036 Res = WidenVecRes_IS_FPCLASS(N);
4037 break;
4038
4039 case ISD::FPOWI:
4040 Res = WidenVecRes_POWI(N);
4041 break;
4042
4043 case ISD::ANY_EXTEND_VECTOR_INREG:
4044 case ISD::SIGN_EXTEND_VECTOR_INREG:
4045 case ISD::ZERO_EXTEND_VECTOR_INREG:
4046 Res = WidenVecRes_EXTEND_VECTOR_INREG(N);
4047 break;
4048
4049 case ISD::ANY_EXTEND:
4050 case ISD::FP_EXTEND:
4051 case ISD::VP_FP_EXTEND:
4052 case ISD::FP_ROUND:
4053 case ISD::VP_FP_ROUND:
4054 case ISD::FP_TO_SINT:
4055 case ISD::VP_FP_TO_SINT:
4056 case ISD::FP_TO_UINT:
4057 case ISD::VP_FP_TO_UINT:
4058 case ISD::SIGN_EXTEND:
4059 case ISD::VP_SIGN_EXTEND:
4060 case ISD::SINT_TO_FP:
4061 case ISD::VP_SINT_TO_FP:
4062 case ISD::VP_TRUNCATE:
4063 case ISD::TRUNCATE:
4064 case ISD::UINT_TO_FP:
4065 case ISD::VP_UINT_TO_FP:
4066 case ISD::ZERO_EXTEND:
4067 case ISD::VP_ZERO_EXTEND:
4068 Res = WidenVecRes_Convert(N);
4069 break;
4070
4071 case ISD::FP_TO_SINT_SAT:
4072 case ISD::FP_TO_UINT_SAT:
4073 Res = WidenVecRes_FP_TO_XINT_SAT(N);
4074 break;
4075
4076 case ISD::FABS:
4077 case ISD::FCEIL:
4078 case ISD::FCOS:
4079 case ISD::FEXP:
4080 case ISD::FEXP2:
4081 case ISD::FFLOOR:
4082 case ISD::FLOG:
4083 case ISD::FLOG10:
4084 case ISD::FLOG2:
4085 case ISD::FNEARBYINT:
4086 case ISD::FRINT:
4087 case ISD::FROUND:
4088 case ISD::FROUNDEVEN:
4089 case ISD::FSIN:
4090 case ISD::FSQRT:
4091 case ISD::FTRUNC:
4092 if (unrollExpandedOp())
4093 break;
4094 // If the target has custom/legal support for the scalar FP intrinsic ops
4095 // (they are probably not destined to become libcalls), then widen those
4096 // like any other unary ops.
4097 [[fallthrough]];
4098
4099 case ISD::ABS:
4100 case ISD::VP_ABS:
4101 case ISD::BITREVERSE:
4102 case ISD::VP_BITREVERSE:
4103 case ISD::BSWAP:
4104 case ISD::VP_BSWAP:
4105 case ISD::CTLZ:
4106 case ISD::VP_CTLZ:
4107 case ISD::CTLZ_ZERO_UNDEF:
4108 case ISD::VP_CTLZ_ZERO_UNDEF:
4109 case ISD::CTPOP:
4110 case ISD::VP_CTPOP:
4111 case ISD::CTTZ:
4112 case ISD::VP_CTTZ:
4113 case ISD::CTTZ_ZERO_UNDEF:
4114 case ISD::VP_CTTZ_ZERO_UNDEF:
4115 case ISD::FNEG: case ISD::VP_FNEG:
4116 case ISD::VP_FABS:
4117 case ISD::VP_SQRT:
4118 case ISD::VP_FCEIL:
4119 case ISD::VP_FFLOOR:
4120 case ISD::VP_FRINT:
4121 case ISD::VP_FNEARBYINT:
4122 case ISD::VP_FROUND:
4123 case ISD::VP_FROUNDEVEN:
4124 case ISD::VP_FROUNDTOZERO:
4125 case ISD::FREEZE:
4126 case ISD::ARITH_FENCE:
4127 case ISD::FCANONICALIZE:
4128 Res = WidenVecRes_Unary(N);
4129 break;
4130 case ISD::FMA: case ISD::VP_FMA:
4131 case ISD::FSHL:
4132 case ISD::VP_FSHL:
4133 case ISD::FSHR:
4134 case ISD::VP_FSHR:
4135 Res = WidenVecRes_Ternary(N);
4136 break;
4137 }
4138
4139 // If Res is null, the sub-method took care of registering the result.
4140 if (Res.getNode())
4141 SetWidenedVector(SDValue(N, ResNo), Res);
4142 }
4143
WidenVecRes_Ternary(SDNode * N)4144 SDValue DAGTypeLegalizer::WidenVecRes_Ternary(SDNode *N) {
4145 // Ternary op widening.
4146 SDLoc dl(N);
4147 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
4148 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
4149 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
4150 SDValue InOp3 = GetWidenedVector(N->getOperand(2));
4151 if (N->getNumOperands() == 3)
4152 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3);
4153
4154 assert(N->getNumOperands() == 5 && "Unexpected number of operands!");
4155 assert(N->isVPOpcode() && "Expected VP opcode");
4156
4157 SDValue Mask =
4158 GetWidenedMask(N->getOperand(3), WidenVT.getVectorElementCount());
4159 return DAG.getNode(N->getOpcode(), dl, WidenVT,
4160 {InOp1, InOp2, InOp3, Mask, N->getOperand(4)});
4161 }
4162
WidenVecRes_Binary(SDNode * N)4163 SDValue DAGTypeLegalizer::WidenVecRes_Binary(SDNode *N) {
4164 // Binary op widening.
4165 SDLoc dl(N);
4166 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
4167 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
4168 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
4169 if (N->getNumOperands() == 2)
4170 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2,
4171 N->getFlags());
4172
4173 assert(N->getNumOperands() == 4 && "Unexpected number of operands!");
4174 assert(N->isVPOpcode() && "Expected VP opcode");
4175
4176 SDValue Mask =
4177 GetWidenedMask(N->getOperand(2), WidenVT.getVectorElementCount());
4178 return DAG.getNode(N->getOpcode(), dl, WidenVT,
4179 {InOp1, InOp2, Mask, N->getOperand(3)}, N->getFlags());
4180 }
4181
WidenVecRes_BinaryWithExtraScalarOp(SDNode * N)4182 SDValue DAGTypeLegalizer::WidenVecRes_BinaryWithExtraScalarOp(SDNode *N) {
4183 // Binary op widening, but with an extra operand that shouldn't be widened.
4184 SDLoc dl(N);
4185 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
4186 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
4187 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
4188 SDValue InOp3 = N->getOperand(2);
4189 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3,
4190 N->getFlags());
4191 }
4192
4193 // Given a vector of operations that have been broken up to widen, see
4194 // if we can collect them together into the next widest legal VT. This
4195 // implementation is trap-safe.
CollectOpsToWiden(SelectionDAG & DAG,const TargetLowering & TLI,SmallVectorImpl<SDValue> & ConcatOps,unsigned ConcatEnd,EVT VT,EVT MaxVT,EVT WidenVT)4196 static SDValue CollectOpsToWiden(SelectionDAG &DAG, const TargetLowering &TLI,
4197 SmallVectorImpl<SDValue> &ConcatOps,
4198 unsigned ConcatEnd, EVT VT, EVT MaxVT,
4199 EVT WidenVT) {
4200 // Check to see if we have a single operation with the widen type.
4201 if (ConcatEnd == 1) {
4202 VT = ConcatOps[0].getValueType();
4203 if (VT == WidenVT)
4204 return ConcatOps[0];
4205 }
4206
4207 SDLoc dl(ConcatOps[0]);
4208 EVT WidenEltVT = WidenVT.getVectorElementType();
4209
4210 // while (Some element of ConcatOps is not of type MaxVT) {
4211 // From the end of ConcatOps, collect elements of the same type and put
4212 // them into an op of the next larger supported type
4213 // }
4214 while (ConcatOps[ConcatEnd-1].getValueType() != MaxVT) {
4215 int Idx = ConcatEnd - 1;
4216 VT = ConcatOps[Idx--].getValueType();
4217 while (Idx >= 0 && ConcatOps[Idx].getValueType() == VT)
4218 Idx--;
4219
4220 int NextSize = VT.isVector() ? VT.getVectorNumElements() : 1;
4221 EVT NextVT;
4222 do {
4223 NextSize *= 2;
4224 NextVT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NextSize);
4225 } while (!TLI.isTypeLegal(NextVT));
4226
4227 if (!VT.isVector()) {
4228 // Scalar type, create an INSERT_VECTOR_ELEMENT of type NextVT
4229 SDValue VecOp = DAG.getUNDEF(NextVT);
4230 unsigned NumToInsert = ConcatEnd - Idx - 1;
4231 for (unsigned i = 0, OpIdx = Idx+1; i < NumToInsert; i++, OpIdx++) {
4232 VecOp = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, NextVT, VecOp,
4233 ConcatOps[OpIdx], DAG.getVectorIdxConstant(i, dl));
4234 }
4235 ConcatOps[Idx+1] = VecOp;
4236 ConcatEnd = Idx + 2;
4237 } else {
4238 // Vector type, create a CONCAT_VECTORS of type NextVT
4239 SDValue undefVec = DAG.getUNDEF(VT);
4240 unsigned OpsToConcat = NextSize/VT.getVectorNumElements();
4241 SmallVector<SDValue, 16> SubConcatOps(OpsToConcat);
4242 unsigned RealVals = ConcatEnd - Idx - 1;
4243 unsigned SubConcatEnd = 0;
4244 unsigned SubConcatIdx = Idx + 1;
4245 while (SubConcatEnd < RealVals)
4246 SubConcatOps[SubConcatEnd++] = ConcatOps[++Idx];
4247 while (SubConcatEnd < OpsToConcat)
4248 SubConcatOps[SubConcatEnd++] = undefVec;
4249 ConcatOps[SubConcatIdx] = DAG.getNode(ISD::CONCAT_VECTORS, dl,
4250 NextVT, SubConcatOps);
4251 ConcatEnd = SubConcatIdx + 1;
4252 }
4253 }
4254
4255 // Check to see if we have a single operation with the widen type.
4256 if (ConcatEnd == 1) {
4257 VT = ConcatOps[0].getValueType();
4258 if (VT == WidenVT)
4259 return ConcatOps[0];
4260 }
4261
4262 // add undefs of size MaxVT until ConcatOps grows to length of WidenVT
4263 unsigned NumOps = WidenVT.getVectorNumElements()/MaxVT.getVectorNumElements();
4264 if (NumOps != ConcatEnd ) {
4265 SDValue UndefVal = DAG.getUNDEF(MaxVT);
4266 for (unsigned j = ConcatEnd; j < NumOps; ++j)
4267 ConcatOps[j] = UndefVal;
4268 }
4269 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
4270 ArrayRef(ConcatOps.data(), NumOps));
4271 }
4272
WidenVecRes_BinaryCanTrap(SDNode * N)4273 SDValue DAGTypeLegalizer::WidenVecRes_BinaryCanTrap(SDNode *N) {
4274 // Binary op widening for operations that can trap.
4275 unsigned Opcode = N->getOpcode();
4276 SDLoc dl(N);
4277 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
4278 EVT WidenEltVT = WidenVT.getVectorElementType();
4279 EVT VT = WidenVT;
4280 unsigned NumElts = VT.getVectorMinNumElements();
4281 const SDNodeFlags Flags = N->getFlags();
4282 while (!TLI.isTypeLegal(VT) && NumElts != 1) {
4283 NumElts = NumElts / 2;
4284 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
4285 }
4286
4287 if (NumElts != 1 && !TLI.canOpTrap(N->getOpcode(), VT)) {
4288 // Operation doesn't trap so just widen as normal.
4289 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
4290 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
4291 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, Flags);
4292 }
4293
4294 // FIXME: Improve support for scalable vectors.
4295 assert(!VT.isScalableVector() && "Scalable vectors not handled yet.");
4296
4297 // No legal vector version so unroll the vector operation and then widen.
4298 if (NumElts == 1)
4299 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
4300
4301 // Since the operation can trap, apply operation on the original vector.
4302 EVT MaxVT = VT;
4303 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
4304 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
4305 unsigned CurNumElts = N->getValueType(0).getVectorNumElements();
4306
4307 SmallVector<SDValue, 16> ConcatOps(CurNumElts);
4308 unsigned ConcatEnd = 0; // Current ConcatOps index.
4309 int Idx = 0; // Current Idx into input vectors.
4310
4311 // NumElts := greatest legal vector size (at most WidenVT)
4312 // while (orig. vector has unhandled elements) {
4313 // take munches of size NumElts from the beginning and add to ConcatOps
4314 // NumElts := next smaller supported vector size or 1
4315 // }
4316 while (CurNumElts != 0) {
4317 while (CurNumElts >= NumElts) {
4318 SDValue EOp1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, InOp1,
4319 DAG.getVectorIdxConstant(Idx, dl));
4320 SDValue EOp2 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, InOp2,
4321 DAG.getVectorIdxConstant(Idx, dl));
4322 ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, VT, EOp1, EOp2, Flags);
4323 Idx += NumElts;
4324 CurNumElts -= NumElts;
4325 }
4326 do {
4327 NumElts = NumElts / 2;
4328 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
4329 } while (!TLI.isTypeLegal(VT) && NumElts != 1);
4330
4331 if (NumElts == 1) {
4332 for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
4333 SDValue EOp1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, WidenEltVT,
4334 InOp1, DAG.getVectorIdxConstant(Idx, dl));
4335 SDValue EOp2 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, WidenEltVT,
4336 InOp2, DAG.getVectorIdxConstant(Idx, dl));
4337 ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, WidenEltVT,
4338 EOp1, EOp2, Flags);
4339 }
4340 CurNumElts = 0;
4341 }
4342 }
4343
4344 return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
4345 }
4346
WidenVecRes_StrictFP(SDNode * N)4347 SDValue DAGTypeLegalizer::WidenVecRes_StrictFP(SDNode *N) {
4348 switch (N->getOpcode()) {
4349 case ISD::STRICT_FSETCC:
4350 case ISD::STRICT_FSETCCS:
4351 return WidenVecRes_STRICT_FSETCC(N);
4352 case ISD::STRICT_FP_EXTEND:
4353 case ISD::STRICT_FP_ROUND:
4354 case ISD::STRICT_FP_TO_SINT:
4355 case ISD::STRICT_FP_TO_UINT:
4356 case ISD::STRICT_SINT_TO_FP:
4357 case ISD::STRICT_UINT_TO_FP:
4358 return WidenVecRes_Convert_StrictFP(N);
4359 default:
4360 break;
4361 }
4362
4363 // StrictFP op widening for operations that can trap.
4364 unsigned NumOpers = N->getNumOperands();
4365 unsigned Opcode = N->getOpcode();
4366 SDLoc dl(N);
4367 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
4368 EVT WidenEltVT = WidenVT.getVectorElementType();
4369 EVT VT = WidenVT;
4370 unsigned NumElts = VT.getVectorNumElements();
4371 while (!TLI.isTypeLegal(VT) && NumElts != 1) {
4372 NumElts = NumElts / 2;
4373 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
4374 }
4375
4376 // No legal vector version so unroll the vector operation and then widen.
4377 if (NumElts == 1)
4378 return UnrollVectorOp_StrictFP(N, WidenVT.getVectorNumElements());
4379
4380 // Since the operation can trap, apply operation on the original vector.
4381 EVT MaxVT = VT;
4382 SmallVector<SDValue, 4> InOps;
4383 unsigned CurNumElts = N->getValueType(0).getVectorNumElements();
4384
4385 SmallVector<SDValue, 16> ConcatOps(CurNumElts);
4386 SmallVector<SDValue, 16> Chains;
4387 unsigned ConcatEnd = 0; // Current ConcatOps index.
4388 int Idx = 0; // Current Idx into input vectors.
4389
4390 // The Chain is the first operand.
4391 InOps.push_back(N->getOperand(0));
4392
4393 // Now process the remaining operands.
4394 for (unsigned i = 1; i < NumOpers; ++i) {
4395 SDValue Oper = N->getOperand(i);
4396
4397 if (Oper.getValueType().isVector()) {
4398 assert(Oper.getValueType() == N->getValueType(0) &&
4399 "Invalid operand type to widen!");
4400 Oper = GetWidenedVector(Oper);
4401 }
4402
4403 InOps.push_back(Oper);
4404 }
4405
4406 // NumElts := greatest legal vector size (at most WidenVT)
4407 // while (orig. vector has unhandled elements) {
4408 // take munches of size NumElts from the beginning and add to ConcatOps
4409 // NumElts := next smaller supported vector size or 1
4410 // }
4411 while (CurNumElts != 0) {
4412 while (CurNumElts >= NumElts) {
4413 SmallVector<SDValue, 4> EOps;
4414
4415 for (unsigned i = 0; i < NumOpers; ++i) {
4416 SDValue Op = InOps[i];
4417
4418 if (Op.getValueType().isVector())
4419 Op = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, Op,
4420 DAG.getVectorIdxConstant(Idx, dl));
4421
4422 EOps.push_back(Op);
4423 }
4424
4425 EVT OperVT[] = {VT, MVT::Other};
4426 SDValue Oper = DAG.getNode(Opcode, dl, OperVT, EOps);
4427 ConcatOps[ConcatEnd++] = Oper;
4428 Chains.push_back(Oper.getValue(1));
4429 Idx += NumElts;
4430 CurNumElts -= NumElts;
4431 }
4432 do {
4433 NumElts = NumElts / 2;
4434 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
4435 } while (!TLI.isTypeLegal(VT) && NumElts != 1);
4436
4437 if (NumElts == 1) {
4438 for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
4439 SmallVector<SDValue, 4> EOps;
4440
4441 for (unsigned i = 0; i < NumOpers; ++i) {
4442 SDValue Op = InOps[i];
4443
4444 if (Op.getValueType().isVector())
4445 Op = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, WidenEltVT, Op,
4446 DAG.getVectorIdxConstant(Idx, dl));
4447
4448 EOps.push_back(Op);
4449 }
4450
4451 EVT WidenVT[] = {WidenEltVT, MVT::Other};
4452 SDValue Oper = DAG.getNode(Opcode, dl, WidenVT, EOps);
4453 ConcatOps[ConcatEnd++] = Oper;
4454 Chains.push_back(Oper.getValue(1));
4455 }
4456 CurNumElts = 0;
4457 }
4458 }
4459
4460 // Build a factor node to remember all the Ops that have been created.
4461 SDValue NewChain;
4462 if (Chains.size() == 1)
4463 NewChain = Chains[0];
4464 else
4465 NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
4466 ReplaceValueWith(SDValue(N, 1), NewChain);
4467
4468 return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
4469 }
4470
WidenVecRes_OverflowOp(SDNode * N,unsigned ResNo)4471 SDValue DAGTypeLegalizer::WidenVecRes_OverflowOp(SDNode *N, unsigned ResNo) {
4472 SDLoc DL(N);
4473 EVT ResVT = N->getValueType(0);
4474 EVT OvVT = N->getValueType(1);
4475 EVT WideResVT, WideOvVT;
4476 SDValue WideLHS, WideRHS;
4477
4478 // TODO: This might result in a widen/split loop.
4479 if (ResNo == 0) {
4480 WideResVT = TLI.getTypeToTransformTo(*DAG.getContext(), ResVT);
4481 WideOvVT = EVT::getVectorVT(
4482 *DAG.getContext(), OvVT.getVectorElementType(),
4483 WideResVT.getVectorNumElements());
4484
4485 WideLHS = GetWidenedVector(N->getOperand(0));
4486 WideRHS = GetWidenedVector(N->getOperand(1));
4487 } else {
4488 WideOvVT = TLI.getTypeToTransformTo(*DAG.getContext(), OvVT);
4489 WideResVT = EVT::getVectorVT(
4490 *DAG.getContext(), ResVT.getVectorElementType(),
4491 WideOvVT.getVectorNumElements());
4492
4493 SDValue Zero = DAG.getVectorIdxConstant(0, DL);
4494 WideLHS = DAG.getNode(
4495 ISD::INSERT_SUBVECTOR, DL, WideResVT, DAG.getUNDEF(WideResVT),
4496 N->getOperand(0), Zero);
4497 WideRHS = DAG.getNode(
4498 ISD::INSERT_SUBVECTOR, DL, WideResVT, DAG.getUNDEF(WideResVT),
4499 N->getOperand(1), Zero);
4500 }
4501
4502 SDVTList WideVTs = DAG.getVTList(WideResVT, WideOvVT);
4503 SDNode *WideNode = DAG.getNode(
4504 N->getOpcode(), DL, WideVTs, WideLHS, WideRHS).getNode();
4505
4506 // Replace the other vector result not being explicitly widened here.
4507 unsigned OtherNo = 1 - ResNo;
4508 EVT OtherVT = N->getValueType(OtherNo);
4509 if (getTypeAction(OtherVT) == TargetLowering::TypeWidenVector) {
4510 SetWidenedVector(SDValue(N, OtherNo), SDValue(WideNode, OtherNo));
4511 } else {
4512 SDValue Zero = DAG.getVectorIdxConstant(0, DL);
4513 SDValue OtherVal = DAG.getNode(
4514 ISD::EXTRACT_SUBVECTOR, DL, OtherVT, SDValue(WideNode, OtherNo), Zero);
4515 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
4516 }
4517
4518 return SDValue(WideNode, ResNo);
4519 }
4520
WidenVecRes_Convert(SDNode * N)4521 SDValue DAGTypeLegalizer::WidenVecRes_Convert(SDNode *N) {
4522 LLVMContext &Ctx = *DAG.getContext();
4523 SDValue InOp = N->getOperand(0);
4524 SDLoc DL(N);
4525
4526 EVT WidenVT = TLI.getTypeToTransformTo(Ctx, N->getValueType(0));
4527 ElementCount WidenEC = WidenVT.getVectorElementCount();
4528
4529 EVT InVT = InOp.getValueType();
4530
4531 unsigned Opcode = N->getOpcode();
4532 const SDNodeFlags Flags = N->getFlags();
4533
4534 // Handle the case of ZERO_EXTEND where the promoted InVT element size does
4535 // not equal that of WidenVT.
4536 if (N->getOpcode() == ISD::ZERO_EXTEND &&
4537 getTypeAction(InVT) == TargetLowering::TypePromoteInteger &&
4538 TLI.getTypeToTransformTo(Ctx, InVT).getScalarSizeInBits() !=
4539 WidenVT.getScalarSizeInBits()) {
4540 InOp = ZExtPromotedInteger(InOp);
4541 InVT = InOp.getValueType();
4542 if (WidenVT.getScalarSizeInBits() < InVT.getScalarSizeInBits())
4543 Opcode = ISD::TRUNCATE;
4544 }
4545
4546 EVT InEltVT = InVT.getVectorElementType();
4547 EVT InWidenVT = EVT::getVectorVT(Ctx, InEltVT, WidenEC);
4548 ElementCount InVTEC = InVT.getVectorElementCount();
4549
4550 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
4551 InOp = GetWidenedVector(N->getOperand(0));
4552 InVT = InOp.getValueType();
4553 InVTEC = InVT.getVectorElementCount();
4554 if (InVTEC == WidenEC) {
4555 if (N->getNumOperands() == 1)
4556 return DAG.getNode(Opcode, DL, WidenVT, InOp);
4557 if (N->getNumOperands() == 3) {
4558 assert(N->isVPOpcode() && "Expected VP opcode");
4559 SDValue Mask =
4560 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
4561 return DAG.getNode(Opcode, DL, WidenVT, InOp, Mask, N->getOperand(2));
4562 }
4563 return DAG.getNode(Opcode, DL, WidenVT, InOp, N->getOperand(1), Flags);
4564 }
4565 if (WidenVT.getSizeInBits() == InVT.getSizeInBits()) {
4566 // If both input and result vector types are of same width, extend
4567 // operations should be done with SIGN/ZERO_EXTEND_VECTOR_INREG, which
4568 // accepts fewer elements in the result than in the input.
4569 if (Opcode == ISD::ANY_EXTEND)
4570 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
4571 if (Opcode == ISD::SIGN_EXTEND)
4572 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
4573 if (Opcode == ISD::ZERO_EXTEND)
4574 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
4575 }
4576 }
4577
4578 if (TLI.isTypeLegal(InWidenVT)) {
4579 // Because the result and the input are different vector types, widening
4580 // the result could create a legal type but widening the input might make
4581 // it an illegal type that might lead to repeatedly splitting the input
4582 // and then widening it. To avoid this, we widen the input only if
4583 // it results in a legal type.
4584 if (WidenEC.isKnownMultipleOf(InVTEC.getKnownMinValue())) {
4585 // Widen the input and call convert on the widened input vector.
4586 unsigned NumConcat =
4587 WidenEC.getKnownMinValue() / InVTEC.getKnownMinValue();
4588 SmallVector<SDValue, 16> Ops(NumConcat, DAG.getUNDEF(InVT));
4589 Ops[0] = InOp;
4590 SDValue InVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InWidenVT, Ops);
4591 if (N->getNumOperands() == 1)
4592 return DAG.getNode(Opcode, DL, WidenVT, InVec);
4593 return DAG.getNode(Opcode, DL, WidenVT, InVec, N->getOperand(1), Flags);
4594 }
4595
4596 if (InVTEC.isKnownMultipleOf(WidenEC.getKnownMinValue())) {
4597 SDValue InVal = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, InWidenVT, InOp,
4598 DAG.getVectorIdxConstant(0, DL));
4599 // Extract the input and convert the shorten input vector.
4600 if (N->getNumOperands() == 1)
4601 return DAG.getNode(Opcode, DL, WidenVT, InVal);
4602 return DAG.getNode(Opcode, DL, WidenVT, InVal, N->getOperand(1), Flags);
4603 }
4604 }
4605
4606 // Otherwise unroll into some nasty scalar code and rebuild the vector.
4607 EVT EltVT = WidenVT.getVectorElementType();
4608 SmallVector<SDValue, 16> Ops(WidenEC.getFixedValue(), DAG.getUNDEF(EltVT));
4609 // Use the original element count so we don't do more scalar opts than
4610 // necessary.
4611 unsigned MinElts = N->getValueType(0).getVectorNumElements();
4612 for (unsigned i=0; i < MinElts; ++i) {
4613 SDValue Val = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, InEltVT, InOp,
4614 DAG.getVectorIdxConstant(i, DL));
4615 if (N->getNumOperands() == 1)
4616 Ops[i] = DAG.getNode(Opcode, DL, EltVT, Val);
4617 else
4618 Ops[i] = DAG.getNode(Opcode, DL, EltVT, Val, N->getOperand(1), Flags);
4619 }
4620
4621 return DAG.getBuildVector(WidenVT, DL, Ops);
4622 }
4623
WidenVecRes_FP_TO_XINT_SAT(SDNode * N)4624 SDValue DAGTypeLegalizer::WidenVecRes_FP_TO_XINT_SAT(SDNode *N) {
4625 SDLoc dl(N);
4626 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
4627 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
4628
4629 SDValue Src = N->getOperand(0);
4630 EVT SrcVT = Src.getValueType();
4631
4632 // Also widen the input.
4633 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
4634 Src = GetWidenedVector(Src);
4635 SrcVT = Src.getValueType();
4636 }
4637
4638 // Input and output not widened to the same size, give up.
4639 if (WidenNumElts != SrcVT.getVectorElementCount())
4640 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
4641
4642 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src, N->getOperand(1));
4643 }
4644
WidenVecRes_Convert_StrictFP(SDNode * N)4645 SDValue DAGTypeLegalizer::WidenVecRes_Convert_StrictFP(SDNode *N) {
4646 SDValue InOp = N->getOperand(1);
4647 SDLoc DL(N);
4648 SmallVector<SDValue, 4> NewOps(N->op_begin(), N->op_end());
4649
4650 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
4651 unsigned WidenNumElts = WidenVT.getVectorNumElements();
4652
4653 EVT InVT = InOp.getValueType();
4654 EVT InEltVT = InVT.getVectorElementType();
4655
4656 unsigned Opcode = N->getOpcode();
4657
4658 // FIXME: Optimizations need to be implemented here.
4659
4660 // Otherwise unroll into some nasty scalar code and rebuild the vector.
4661 EVT EltVT = WidenVT.getVectorElementType();
4662 std::array<EVT, 2> EltVTs = {{EltVT, MVT::Other}};
4663 SmallVector<SDValue, 16> Ops(WidenNumElts, DAG.getUNDEF(EltVT));
4664 SmallVector<SDValue, 32> OpChains;
4665 // Use the original element count so we don't do more scalar opts than
4666 // necessary.
4667 unsigned MinElts = N->getValueType(0).getVectorNumElements();
4668 for (unsigned i=0; i < MinElts; ++i) {
4669 NewOps[1] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, InEltVT, InOp,
4670 DAG.getVectorIdxConstant(i, DL));
4671 Ops[i] = DAG.getNode(Opcode, DL, EltVTs, NewOps);
4672 OpChains.push_back(Ops[i].getValue(1));
4673 }
4674 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OpChains);
4675 ReplaceValueWith(SDValue(N, 1), NewChain);
4676
4677 return DAG.getBuildVector(WidenVT, DL, Ops);
4678 }
4679
WidenVecRes_EXTEND_VECTOR_INREG(SDNode * N)4680 SDValue DAGTypeLegalizer::WidenVecRes_EXTEND_VECTOR_INREG(SDNode *N) {
4681 unsigned Opcode = N->getOpcode();
4682 SDValue InOp = N->getOperand(0);
4683 SDLoc DL(N);
4684
4685 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
4686 EVT WidenSVT = WidenVT.getVectorElementType();
4687 unsigned WidenNumElts = WidenVT.getVectorNumElements();
4688
4689 EVT InVT = InOp.getValueType();
4690 EVT InSVT = InVT.getVectorElementType();
4691 unsigned InVTNumElts = InVT.getVectorNumElements();
4692
4693 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
4694 InOp = GetWidenedVector(InOp);
4695 InVT = InOp.getValueType();
4696 if (InVT.getSizeInBits() == WidenVT.getSizeInBits()) {
4697 switch (Opcode) {
4698 case ISD::ANY_EXTEND_VECTOR_INREG:
4699 case ISD::SIGN_EXTEND_VECTOR_INREG:
4700 case ISD::ZERO_EXTEND_VECTOR_INREG:
4701 return DAG.getNode(Opcode, DL, WidenVT, InOp);
4702 }
4703 }
4704 }
4705
4706 // Unroll, extend the scalars and rebuild the vector.
4707 SmallVector<SDValue, 16> Ops;
4708 for (unsigned i = 0, e = std::min(InVTNumElts, WidenNumElts); i != e; ++i) {
4709 SDValue Val = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, InSVT, InOp,
4710 DAG.getVectorIdxConstant(i, DL));
4711 switch (Opcode) {
4712 case ISD::ANY_EXTEND_VECTOR_INREG:
4713 Val = DAG.getNode(ISD::ANY_EXTEND, DL, WidenSVT, Val);
4714 break;
4715 case ISD::SIGN_EXTEND_VECTOR_INREG:
4716 Val = DAG.getNode(ISD::SIGN_EXTEND, DL, WidenSVT, Val);
4717 break;
4718 case ISD::ZERO_EXTEND_VECTOR_INREG:
4719 Val = DAG.getNode(ISD::ZERO_EXTEND, DL, WidenSVT, Val);
4720 break;
4721 default:
4722 llvm_unreachable("A *_EXTEND_VECTOR_INREG node was expected");
4723 }
4724 Ops.push_back(Val);
4725 }
4726
4727 while (Ops.size() != WidenNumElts)
4728 Ops.push_back(DAG.getUNDEF(WidenSVT));
4729
4730 return DAG.getBuildVector(WidenVT, DL, Ops);
4731 }
4732
WidenVecRes_FCOPYSIGN(SDNode * N)4733 SDValue DAGTypeLegalizer::WidenVecRes_FCOPYSIGN(SDNode *N) {
4734 // If this is an FCOPYSIGN with same input types, we can treat it as a
4735 // normal (can trap) binary op.
4736 if (N->getOperand(0).getValueType() == N->getOperand(1).getValueType())
4737 return WidenVecRes_BinaryCanTrap(N);
4738
4739 // If the types are different, fall back to unrolling.
4740 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
4741 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
4742 }
4743
WidenVecRes_IS_FPCLASS(SDNode * N)4744 SDValue DAGTypeLegalizer::WidenVecRes_IS_FPCLASS(SDNode *N) {
4745 SDValue FpValue = N->getOperand(0);
4746 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
4747 if (getTypeAction(FpValue.getValueType()) != TargetLowering::TypeWidenVector)
4748 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
4749 SDValue Arg = GetWidenedVector(FpValue);
4750 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, {Arg, N->getOperand(1)},
4751 N->getFlags());
4752 }
4753
WidenVecRes_POWI(SDNode * N)4754 SDValue DAGTypeLegalizer::WidenVecRes_POWI(SDNode *N) {
4755 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
4756 SDValue InOp = GetWidenedVector(N->getOperand(0));
4757 SDValue ShOp = N->getOperand(1);
4758 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, ShOp);
4759 }
4760
WidenVecRes_Unary(SDNode * N)4761 SDValue DAGTypeLegalizer::WidenVecRes_Unary(SDNode *N) {
4762 // Unary op widening.
4763 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
4764 SDValue InOp = GetWidenedVector(N->getOperand(0));
4765 if (N->getNumOperands() == 1)
4766 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp);
4767
4768 assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
4769 assert(N->isVPOpcode() && "Expected VP opcode");
4770
4771 SDValue Mask =
4772 GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
4773 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT,
4774 {InOp, Mask, N->getOperand(2)});
4775 }
4776
WidenVecRes_InregOp(SDNode * N)4777 SDValue DAGTypeLegalizer::WidenVecRes_InregOp(SDNode *N) {
4778 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
4779 EVT ExtVT = EVT::getVectorVT(*DAG.getContext(),
4780 cast<VTSDNode>(N->getOperand(1))->getVT()
4781 .getVectorElementType(),
4782 WidenVT.getVectorNumElements());
4783 SDValue WidenLHS = GetWidenedVector(N->getOperand(0));
4784 return DAG.getNode(N->getOpcode(), SDLoc(N),
4785 WidenVT, WidenLHS, DAG.getValueType(ExtVT));
4786 }
4787
WidenVecRes_MERGE_VALUES(SDNode * N,unsigned ResNo)4788 SDValue DAGTypeLegalizer::WidenVecRes_MERGE_VALUES(SDNode *N, unsigned ResNo) {
4789 SDValue WidenVec = DisintegrateMERGE_VALUES(N, ResNo);
4790 return GetWidenedVector(WidenVec);
4791 }
4792
WidenVecRes_BITCAST(SDNode * N)4793 SDValue DAGTypeLegalizer::WidenVecRes_BITCAST(SDNode *N) {
4794 SDValue InOp = N->getOperand(0);
4795 EVT InVT = InOp.getValueType();
4796 EVT VT = N->getValueType(0);
4797 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
4798 SDLoc dl(N);
4799
4800 switch (getTypeAction(InVT)) {
4801 case TargetLowering::TypeLegal:
4802 break;
4803 case TargetLowering::TypeScalarizeScalableVector:
4804 report_fatal_error("Scalarization of scalable vectors is not supported.");
4805 case TargetLowering::TypePromoteInteger: {
4806 // If the incoming type is a vector that is being promoted, then
4807 // we know that the elements are arranged differently and that we
4808 // must perform the conversion using a stack slot.
4809 if (InVT.isVector())
4810 break;
4811
4812 // If the InOp is promoted to the same size, convert it. Otherwise,
4813 // fall out of the switch and widen the promoted input.
4814 SDValue NInOp = GetPromotedInteger(InOp);
4815 EVT NInVT = NInOp.getValueType();
4816 if (WidenVT.bitsEq(NInVT)) {
4817 // For big endian targets we need to shift the input integer or the
4818 // interesting bits will end up at the wrong place.
4819 if (DAG.getDataLayout().isBigEndian()) {
4820 unsigned ShiftAmt = NInVT.getSizeInBits() - InVT.getSizeInBits();
4821 EVT ShiftAmtTy = TLI.getShiftAmountTy(NInVT, DAG.getDataLayout());
4822 assert(ShiftAmt < WidenVT.getSizeInBits() && "Too large shift amount!");
4823 NInOp = DAG.getNode(ISD::SHL, dl, NInVT, NInOp,
4824 DAG.getConstant(ShiftAmt, dl, ShiftAmtTy));
4825 }
4826 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NInOp);
4827 }
4828 InOp = NInOp;
4829 InVT = NInVT;
4830 break;
4831 }
4832 case TargetLowering::TypeSoftenFloat:
4833 case TargetLowering::TypePromoteFloat:
4834 case TargetLowering::TypeSoftPromoteHalf:
4835 case TargetLowering::TypeExpandInteger:
4836 case TargetLowering::TypeExpandFloat:
4837 case TargetLowering::TypeScalarizeVector:
4838 case TargetLowering::TypeSplitVector:
4839 break;
4840 case TargetLowering::TypeWidenVector:
4841 // If the InOp is widened to the same size, convert it. Otherwise, fall
4842 // out of the switch and widen the widened input.
4843 InOp = GetWidenedVector(InOp);
4844 InVT = InOp.getValueType();
4845 if (WidenVT.bitsEq(InVT))
4846 // The input widens to the same size. Convert to the widen value.
4847 return DAG.getNode(ISD::BITCAST, dl, WidenVT, InOp);
4848 break;
4849 }
4850
4851 unsigned WidenSize = WidenVT.getSizeInBits();
4852 unsigned InSize = InVT.getSizeInBits();
4853 unsigned InScalarSize = InVT.getScalarSizeInBits();
4854 // x86mmx is not an acceptable vector element type, so don't try.
4855 if (WidenSize % InScalarSize == 0 && InVT != MVT::x86mmx) {
4856 // Determine new input vector type. The new input vector type will use
4857 // the same element type (if its a vector) or use the input type as a
4858 // vector. It is the same size as the type to widen to.
4859 EVT NewInVT;
4860 unsigned NewNumParts = WidenSize / InSize;
4861 if (InVT.isVector()) {
4862 EVT InEltVT = InVT.getVectorElementType();
4863 NewInVT = EVT::getVectorVT(*DAG.getContext(), InEltVT,
4864 WidenSize / InEltVT.getSizeInBits());
4865 } else {
4866 NewInVT = EVT::getVectorVT(*DAG.getContext(), InVT, NewNumParts);
4867 }
4868
4869 if (TLI.isTypeLegal(NewInVT)) {
4870 SDValue NewVec;
4871 if (InVT.isVector()) {
4872 // Because the result and the input are different vector types, widening
4873 // the result could create a legal type but widening the input might
4874 // make it an illegal type that might lead to repeatedly splitting the
4875 // input and then widening it. To avoid this, we widen the input only if
4876 // it results in a legal type.
4877 if (WidenSize % InSize == 0) {
4878 SmallVector<SDValue, 16> Ops(NewNumParts, DAG.getUNDEF(InVT));
4879 Ops[0] = InOp;
4880
4881 NewVec = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewInVT, Ops);
4882 } else {
4883 SmallVector<SDValue, 16> Ops;
4884 DAG.ExtractVectorElements(InOp, Ops);
4885 Ops.append(WidenSize / InScalarSize - Ops.size(),
4886 DAG.getUNDEF(InVT.getVectorElementType()));
4887
4888 NewVec = DAG.getNode(ISD::BUILD_VECTOR, dl, NewInVT, Ops);
4889 }
4890 } else {
4891 NewVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewInVT, InOp);
4892 }
4893 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NewVec);
4894 }
4895 }
4896
4897 return CreateStackStoreLoad(InOp, WidenVT);
4898 }
4899
WidenVecRes_BUILD_VECTOR(SDNode * N)4900 SDValue DAGTypeLegalizer::WidenVecRes_BUILD_VECTOR(SDNode *N) {
4901 SDLoc dl(N);
4902 // Build a vector with undefined for the new nodes.
4903 EVT VT = N->getValueType(0);
4904
4905 // Integer BUILD_VECTOR operands may be larger than the node's vector element
4906 // type. The UNDEFs need to have the same type as the existing operands.
4907 EVT EltVT = N->getOperand(0).getValueType();
4908 unsigned NumElts = VT.getVectorNumElements();
4909
4910 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
4911 unsigned WidenNumElts = WidenVT.getVectorNumElements();
4912
4913 SmallVector<SDValue, 16> NewOps(N->op_begin(), N->op_end());
4914 assert(WidenNumElts >= NumElts && "Shrinking vector instead of widening!");
4915 NewOps.append(WidenNumElts - NumElts, DAG.getUNDEF(EltVT));
4916
4917 return DAG.getBuildVector(WidenVT, dl, NewOps);
4918 }
4919
WidenVecRes_CONCAT_VECTORS(SDNode * N)4920 SDValue DAGTypeLegalizer::WidenVecRes_CONCAT_VECTORS(SDNode *N) {
4921 EVT InVT = N->getOperand(0).getValueType();
4922 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
4923 SDLoc dl(N);
4924 unsigned NumOperands = N->getNumOperands();
4925
4926 bool InputWidened = false; // Indicates we need to widen the input.
4927 if (getTypeAction(InVT) != TargetLowering::TypeWidenVector) {
4928 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
4929 unsigned NumInElts = InVT.getVectorMinNumElements();
4930 if (WidenNumElts % NumInElts == 0) {
4931 // Add undef vectors to widen to correct length.
4932 unsigned NumConcat = WidenNumElts / NumInElts;
4933 SDValue UndefVal = DAG.getUNDEF(InVT);
4934 SmallVector<SDValue, 16> Ops(NumConcat);
4935 for (unsigned i=0; i < NumOperands; ++i)
4936 Ops[i] = N->getOperand(i);
4937 for (unsigned i = NumOperands; i != NumConcat; ++i)
4938 Ops[i] = UndefVal;
4939 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Ops);
4940 }
4941 } else {
4942 InputWidened = true;
4943 if (WidenVT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
4944 // The inputs and the result are widen to the same value.
4945 unsigned i;
4946 for (i=1; i < NumOperands; ++i)
4947 if (!N->getOperand(i).isUndef())
4948 break;
4949
4950 if (i == NumOperands)
4951 // Everything but the first operand is an UNDEF so just return the
4952 // widened first operand.
4953 return GetWidenedVector(N->getOperand(0));
4954
4955 if (NumOperands == 2) {
4956 assert(!WidenVT.isScalableVector() &&
4957 "Cannot use vector shuffles to widen CONCAT_VECTOR result");
4958 unsigned WidenNumElts = WidenVT.getVectorNumElements();
4959 unsigned NumInElts = InVT.getVectorNumElements();
4960
4961 // Replace concat of two operands with a shuffle.
4962 SmallVector<int, 16> MaskOps(WidenNumElts, -1);
4963 for (unsigned i = 0; i < NumInElts; ++i) {
4964 MaskOps[i] = i;
4965 MaskOps[i + NumInElts] = i + WidenNumElts;
4966 }
4967 return DAG.getVectorShuffle(WidenVT, dl,
4968 GetWidenedVector(N->getOperand(0)),
4969 GetWidenedVector(N->getOperand(1)),
4970 MaskOps);
4971 }
4972 }
4973 }
4974
4975 assert(!WidenVT.isScalableVector() &&
4976 "Cannot use build vectors to widen CONCAT_VECTOR result");
4977 unsigned WidenNumElts = WidenVT.getVectorNumElements();
4978 unsigned NumInElts = InVT.getVectorNumElements();
4979
4980 // Fall back to use extracts and build vector.
4981 EVT EltVT = WidenVT.getVectorElementType();
4982 SmallVector<SDValue, 16> Ops(WidenNumElts);
4983 unsigned Idx = 0;
4984 for (unsigned i=0; i < NumOperands; ++i) {
4985 SDValue InOp = N->getOperand(i);
4986 if (InputWidened)
4987 InOp = GetWidenedVector(InOp);
4988 for (unsigned j = 0; j < NumInElts; ++j)
4989 Ops[Idx++] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp,
4990 DAG.getVectorIdxConstant(j, dl));
4991 }
4992 SDValue UndefVal = DAG.getUNDEF(EltVT);
4993 for (; Idx < WidenNumElts; ++Idx)
4994 Ops[Idx] = UndefVal;
4995 return DAG.getBuildVector(WidenVT, dl, Ops);
4996 }
4997
WidenVecRes_INSERT_SUBVECTOR(SDNode * N)4998 SDValue DAGTypeLegalizer::WidenVecRes_INSERT_SUBVECTOR(SDNode *N) {
4999 EVT VT = N->getValueType(0);
5000 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
5001 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5002 SDValue InOp2 = N->getOperand(1);
5003 SDValue Idx = N->getOperand(2);
5004 SDLoc dl(N);
5005 return DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WidenVT, InOp1, InOp2, Idx);
5006 }
5007
WidenVecRes_EXTRACT_SUBVECTOR(SDNode * N)5008 SDValue DAGTypeLegalizer::WidenVecRes_EXTRACT_SUBVECTOR(SDNode *N) {
5009 EVT VT = N->getValueType(0);
5010 EVT EltVT = VT.getVectorElementType();
5011 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
5012 SDValue InOp = N->getOperand(0);
5013 SDValue Idx = N->getOperand(1);
5014 SDLoc dl(N);
5015
5016 auto InOpTypeAction = getTypeAction(InOp.getValueType());
5017 if (InOpTypeAction == TargetLowering::TypeWidenVector)
5018 InOp = GetWidenedVector(InOp);
5019
5020 EVT InVT = InOp.getValueType();
5021
5022 // Check if we can just return the input vector after widening.
5023 uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getZExtValue();
5024 if (IdxVal == 0 && InVT == WidenVT)
5025 return InOp;
5026
5027 // Check if we can extract from the vector.
5028 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
5029 unsigned InNumElts = InVT.getVectorMinNumElements();
5030 unsigned VTNumElts = VT.getVectorMinNumElements();
5031 assert(IdxVal % VTNumElts == 0 &&
5032 "Expected Idx to be a multiple of subvector minimum vector length");
5033 if (IdxVal % WidenNumElts == 0 && IdxVal + WidenNumElts < InNumElts)
5034 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, WidenVT, InOp, Idx);
5035
5036 if (VT.isScalableVector()) {
5037 // Try to split the operation up into smaller extracts and concat the
5038 // results together, e.g.
5039 // nxv6i64 extract_subvector(nxv12i64, 6)
5040 // <->
5041 // nxv8i64 concat(
5042 // nxv2i64 extract_subvector(nxv16i64, 6)
5043 // nxv2i64 extract_subvector(nxv16i64, 8)
5044 // nxv2i64 extract_subvector(nxv16i64, 10)
5045 // undef)
5046 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
5047 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
5048 "down type's element count");
5049 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
5050 ElementCount::getScalable(GCD));
5051 // Avoid recursion around e.g. nxv1i8.
5052 if (getTypeAction(PartVT) != TargetLowering::TypeWidenVector) {
5053 SmallVector<SDValue> Parts;
5054 unsigned I = 0;
5055 for (; I < VTNumElts / GCD; ++I)
5056 Parts.push_back(
5057 DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, PartVT, InOp,
5058 DAG.getVectorIdxConstant(IdxVal + I * GCD, dl)));
5059 for (; I < WidenNumElts / GCD; ++I)
5060 Parts.push_back(DAG.getUNDEF(PartVT));
5061
5062 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
5063 }
5064
5065 report_fatal_error("Don't know how to widen the result of "
5066 "EXTRACT_SUBVECTOR for scalable vectors");
5067 }
5068
5069 // We could try widening the input to the right length but for now, extract
5070 // the original elements, fill the rest with undefs and build a vector.
5071 SmallVector<SDValue, 16> Ops(WidenNumElts);
5072 unsigned i;
5073 for (i = 0; i < VTNumElts; ++i)
5074 Ops[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp,
5075 DAG.getVectorIdxConstant(IdxVal + i, dl));
5076
5077 SDValue UndefVal = DAG.getUNDEF(EltVT);
5078 for (; i < WidenNumElts; ++i)
5079 Ops[i] = UndefVal;
5080 return DAG.getBuildVector(WidenVT, dl, Ops);
5081 }
5082
WidenVecRes_INSERT_VECTOR_ELT(SDNode * N)5083 SDValue DAGTypeLegalizer::WidenVecRes_INSERT_VECTOR_ELT(SDNode *N) {
5084 SDValue InOp = GetWidenedVector(N->getOperand(0));
5085 return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(N),
5086 InOp.getValueType(), InOp,
5087 N->getOperand(1), N->getOperand(2));
5088 }
5089
WidenVecRes_LOAD(SDNode * N)5090 SDValue DAGTypeLegalizer::WidenVecRes_LOAD(SDNode *N) {
5091 LoadSDNode *LD = cast<LoadSDNode>(N);
5092 ISD::LoadExtType ExtType = LD->getExtensionType();
5093
5094 // A vector must always be stored in memory as-is, i.e. without any padding
5095 // between the elements, since various code depend on it, e.g. in the
5096 // handling of a bitcast of a vector type to int, which may be done with a
5097 // vector store followed by an integer load. A vector that does not have
5098 // elements that are byte-sized must therefore be stored as an integer
5099 // built out of the extracted vector elements.
5100 if (!LD->getMemoryVT().isByteSized()) {
5101 SDValue Value, NewChain;
5102 std::tie(Value, NewChain) = TLI.scalarizeVectorLoad(LD, DAG);
5103 ReplaceValueWith(SDValue(LD, 0), Value);
5104 ReplaceValueWith(SDValue(LD, 1), NewChain);
5105 return SDValue();
5106 }
5107
5108 SDValue Result;
5109 SmallVector<SDValue, 16> LdChain; // Chain for the series of load
5110 if (ExtType != ISD::NON_EXTLOAD)
5111 Result = GenWidenVectorExtLoads(LdChain, LD, ExtType);
5112 else
5113 Result = GenWidenVectorLoads(LdChain, LD);
5114
5115 if (Result) {
5116 // If we generate a single load, we can use that for the chain. Otherwise,
5117 // build a factor node to remember the multiple loads are independent and
5118 // chain to that.
5119 SDValue NewChain;
5120 if (LdChain.size() == 1)
5121 NewChain = LdChain[0];
5122 else
5123 NewChain = DAG.getNode(ISD::TokenFactor, SDLoc(LD), MVT::Other, LdChain);
5124
5125 // Modified the chain - switch anything that used the old chain to use
5126 // the new one.
5127 ReplaceValueWith(SDValue(N, 1), NewChain);
5128
5129 return Result;
5130 }
5131
5132 // Generate a vector-predicated load if it is custom/legal on the target. To
5133 // avoid possible recursion, only do this if the widened mask type is legal.
5134 // FIXME: Not all targets may support EVL in VP_LOAD. These will have been
5135 // removed from the IR by the ExpandVectorPredication pass but we're
5136 // reintroducing them here.
5137 EVT LdVT = LD->getMemoryVT();
5138 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), LdVT);
5139 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
5140 WideVT.getVectorElementCount());
5141 if (ExtType == ISD::NON_EXTLOAD && WideVT.isScalableVector() &&
5142 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WideVT) &&
5143 TLI.isTypeLegal(WideMaskVT)) {
5144 SDLoc DL(N);
5145 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
5146 MVT EVLVT = TLI.getVPExplicitVectorLengthTy();
5147 unsigned NumVTElts = LdVT.getVectorMinNumElements();
5148 SDValue EVL =
5149 DAG.getVScale(DL, EVLVT, APInt(EVLVT.getScalarSizeInBits(), NumVTElts));
5150 const auto *MMO = LD->getMemOperand();
5151 SDValue NewLoad =
5152 DAG.getLoadVP(WideVT, DL, LD->getChain(), LD->getBasePtr(), Mask, EVL,
5153 MMO->getPointerInfo(), MMO->getAlign(), MMO->getFlags(),
5154 MMO->getAAInfo());
5155
5156 // Modified the chain - switch anything that used the old chain to use
5157 // the new one.
5158 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
5159
5160 return NewLoad;
5161 }
5162
5163 report_fatal_error("Unable to widen vector load");
5164 }
5165
WidenVecRes_VP_LOAD(VPLoadSDNode * N)5166 SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD(VPLoadSDNode *N) {
5167 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5168 SDValue Mask = N->getMask();
5169 SDValue EVL = N->getVectorLength();
5170 ISD::LoadExtType ExtType = N->getExtensionType();
5171 SDLoc dl(N);
5172
5173 // The mask should be widened as well
5174 assert(getTypeAction(Mask.getValueType()) ==
5175 TargetLowering::TypeWidenVector &&
5176 "Unable to widen binary VP op");
5177 Mask = GetWidenedVector(Mask);
5178 assert(Mask.getValueType().getVectorElementCount() ==
5179 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
5180 .getVectorElementCount() &&
5181 "Unable to widen vector load");
5182
5183 SDValue Res =
5184 DAG.getLoadVP(N->getAddressingMode(), ExtType, WidenVT, dl, N->getChain(),
5185 N->getBasePtr(), N->getOffset(), Mask, EVL,
5186 N->getMemoryVT(), N->getMemOperand(), N->isExpandingLoad());
5187 // Legalize the chain result - switch anything that used the old chain to
5188 // use the new one.
5189 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
5190 return Res;
5191 }
5192
WidenVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode * N)5193 SDValue DAGTypeLegalizer::WidenVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode *N) {
5194 SDLoc DL(N);
5195
5196 // The mask should be widened as well
5197 SDValue Mask = N->getMask();
5198 assert(getTypeAction(Mask.getValueType()) ==
5199 TargetLowering::TypeWidenVector &&
5200 "Unable to widen VP strided load");
5201 Mask = GetWidenedVector(Mask);
5202
5203 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5204 assert(Mask.getValueType().getVectorElementCount() ==
5205 WidenVT.getVectorElementCount() &&
5206 "Data and mask vectors should have the same number of elements");
5207
5208 SDValue Res = DAG.getStridedLoadVP(
5209 N->getAddressingMode(), N->getExtensionType(), WidenVT, DL, N->getChain(),
5210 N->getBasePtr(), N->getOffset(), N->getStride(), Mask,
5211 N->getVectorLength(), N->getMemoryVT(), N->getMemOperand(),
5212 N->isExpandingLoad());
5213
5214 // Legalize the chain result - switch anything that used the old chain to
5215 // use the new one.
5216 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
5217 return Res;
5218 }
5219
WidenVecRes_MLOAD(MaskedLoadSDNode * N)5220 SDValue DAGTypeLegalizer::WidenVecRes_MLOAD(MaskedLoadSDNode *N) {
5221
5222 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),N->getValueType(0));
5223 SDValue Mask = N->getMask();
5224 EVT MaskVT = Mask.getValueType();
5225 SDValue PassThru = GetWidenedVector(N->getPassThru());
5226 ISD::LoadExtType ExtType = N->getExtensionType();
5227 SDLoc dl(N);
5228
5229 // The mask should be widened as well
5230 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
5231 MaskVT.getVectorElementType(),
5232 WidenVT.getVectorNumElements());
5233 Mask = ModifyToType(Mask, WideMaskVT, true);
5234
5235 SDValue Res = DAG.getMaskedLoad(
5236 WidenVT, dl, N->getChain(), N->getBasePtr(), N->getOffset(), Mask,
5237 PassThru, N->getMemoryVT(), N->getMemOperand(), N->getAddressingMode(),
5238 ExtType, N->isExpandingLoad());
5239 // Legalize the chain result - switch anything that used the old chain to
5240 // use the new one.
5241 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
5242 return Res;
5243 }
5244
WidenVecRes_MGATHER(MaskedGatherSDNode * N)5245 SDValue DAGTypeLegalizer::WidenVecRes_MGATHER(MaskedGatherSDNode *N) {
5246
5247 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5248 SDValue Mask = N->getMask();
5249 EVT MaskVT = Mask.getValueType();
5250 SDValue PassThru = GetWidenedVector(N->getPassThru());
5251 SDValue Scale = N->getScale();
5252 unsigned NumElts = WideVT.getVectorNumElements();
5253 SDLoc dl(N);
5254
5255 // The mask should be widened as well
5256 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
5257 MaskVT.getVectorElementType(),
5258 WideVT.getVectorNumElements());
5259 Mask = ModifyToType(Mask, WideMaskVT, true);
5260
5261 // Widen the Index operand
5262 SDValue Index = N->getIndex();
5263 EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
5264 Index.getValueType().getScalarType(),
5265 NumElts);
5266 Index = ModifyToType(Index, WideIndexVT);
5267 SDValue Ops[] = { N->getChain(), PassThru, Mask, N->getBasePtr(), Index,
5268 Scale };
5269
5270 // Widen the MemoryType
5271 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
5272 N->getMemoryVT().getScalarType(), NumElts);
5273 SDValue Res = DAG.getMaskedGather(DAG.getVTList(WideVT, MVT::Other),
5274 WideMemVT, dl, Ops, N->getMemOperand(),
5275 N->getIndexType(), N->getExtensionType());
5276
5277 // Legalize the chain result - switch anything that used the old chain to
5278 // use the new one.
5279 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
5280 return Res;
5281 }
5282
WidenVecRes_VP_GATHER(VPGatherSDNode * N)5283 SDValue DAGTypeLegalizer::WidenVecRes_VP_GATHER(VPGatherSDNode *N) {
5284 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5285 SDValue Mask = N->getMask();
5286 SDValue Scale = N->getScale();
5287 ElementCount WideEC = WideVT.getVectorElementCount();
5288 SDLoc dl(N);
5289
5290 SDValue Index = GetWidenedVector(N->getIndex());
5291 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
5292 N->getMemoryVT().getScalarType(), WideEC);
5293 Mask = GetWidenedMask(Mask, WideEC);
5294
5295 SDValue Ops[] = {N->getChain(), N->getBasePtr(), Index, Scale,
5296 Mask, N->getVectorLength()};
5297 SDValue Res = DAG.getGatherVP(DAG.getVTList(WideVT, MVT::Other), WideMemVT,
5298 dl, Ops, N->getMemOperand(), N->getIndexType());
5299
5300 // Legalize the chain result - switch anything that used the old chain to
5301 // use the new one.
5302 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
5303 return Res;
5304 }
5305
WidenVecRes_ScalarOp(SDNode * N)5306 SDValue DAGTypeLegalizer::WidenVecRes_ScalarOp(SDNode *N) {
5307 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5308 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, N->getOperand(0));
5309 }
5310
5311 // Return true is this is a SETCC node or a strict version of it.
isSETCCOp(unsigned Opcode)5312 static inline bool isSETCCOp(unsigned Opcode) {
5313 switch (Opcode) {
5314 case ISD::SETCC:
5315 case ISD::STRICT_FSETCC:
5316 case ISD::STRICT_FSETCCS:
5317 return true;
5318 }
5319 return false;
5320 }
5321
5322 // Return true if this is a node that could have two SETCCs as operands.
isLogicalMaskOp(unsigned Opcode)5323 static inline bool isLogicalMaskOp(unsigned Opcode) {
5324 switch (Opcode) {
5325 case ISD::AND:
5326 case ISD::OR:
5327 case ISD::XOR:
5328 return true;
5329 }
5330 return false;
5331 }
5332
5333 // If N is a SETCC or a strict variant of it, return the type
5334 // of the compare operands.
getSETCCOperandType(SDValue N)5335 static inline EVT getSETCCOperandType(SDValue N) {
5336 unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
5337 return N->getOperand(OpNo).getValueType();
5338 }
5339
5340 // This is used just for the assert in convertMask(). Check that this either
5341 // a SETCC or a previously handled SETCC by convertMask().
5342 #ifndef NDEBUG
isSETCCorConvertedSETCC(SDValue N)5343 static inline bool isSETCCorConvertedSETCC(SDValue N) {
5344 if (N.getOpcode() == ISD::EXTRACT_SUBVECTOR)
5345 N = N.getOperand(0);
5346 else if (N.getOpcode() == ISD::CONCAT_VECTORS) {
5347 for (unsigned i = 1; i < N->getNumOperands(); ++i)
5348 if (!N->getOperand(i)->isUndef())
5349 return false;
5350 N = N.getOperand(0);
5351 }
5352
5353 if (N.getOpcode() == ISD::TRUNCATE)
5354 N = N.getOperand(0);
5355 else if (N.getOpcode() == ISD::SIGN_EXTEND)
5356 N = N.getOperand(0);
5357
5358 if (isLogicalMaskOp(N.getOpcode()))
5359 return isSETCCorConvertedSETCC(N.getOperand(0)) &&
5360 isSETCCorConvertedSETCC(N.getOperand(1));
5361
5362 return (isSETCCOp(N.getOpcode()) ||
5363 ISD::isBuildVectorOfConstantSDNodes(N.getNode()));
5364 }
5365 #endif
5366
5367 // Return a mask of vector type MaskVT to replace InMask. Also adjust MaskVT
5368 // to ToMaskVT if needed with vector extension or truncation.
convertMask(SDValue InMask,EVT MaskVT,EVT ToMaskVT)5369 SDValue DAGTypeLegalizer::convertMask(SDValue InMask, EVT MaskVT,
5370 EVT ToMaskVT) {
5371 // Currently a SETCC or a AND/OR/XOR with two SETCCs are handled.
5372 // FIXME: This code seems to be too restrictive, we might consider
5373 // generalizing it or dropping it.
5374 assert(isSETCCorConvertedSETCC(InMask) && "Unexpected mask argument.");
5375
5376 // Make a new Mask node, with a legal result VT.
5377 SDValue Mask;
5378 SmallVector<SDValue, 4> Ops;
5379 for (unsigned i = 0, e = InMask->getNumOperands(); i < e; ++i)
5380 Ops.push_back(InMask->getOperand(i));
5381 if (InMask->isStrictFPOpcode()) {
5382 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask),
5383 { MaskVT, MVT::Other }, Ops);
5384 ReplaceValueWith(InMask.getValue(1), Mask.getValue(1));
5385 }
5386 else
5387 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask), MaskVT, Ops);
5388
5389 // If MaskVT has smaller or bigger elements than ToMaskVT, a vector sign
5390 // extend or truncate is needed.
5391 LLVMContext &Ctx = *DAG.getContext();
5392 unsigned MaskScalarBits = MaskVT.getScalarSizeInBits();
5393 unsigned ToMaskScalBits = ToMaskVT.getScalarSizeInBits();
5394 if (MaskScalarBits < ToMaskScalBits) {
5395 EVT ExtVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
5396 MaskVT.getVectorNumElements());
5397 Mask = DAG.getNode(ISD::SIGN_EXTEND, SDLoc(Mask), ExtVT, Mask);
5398 } else if (MaskScalarBits > ToMaskScalBits) {
5399 EVT TruncVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
5400 MaskVT.getVectorNumElements());
5401 Mask = DAG.getNode(ISD::TRUNCATE, SDLoc(Mask), TruncVT, Mask);
5402 }
5403
5404 assert(Mask->getValueType(0).getScalarSizeInBits() ==
5405 ToMaskVT.getScalarSizeInBits() &&
5406 "Mask should have the right element size by now.");
5407
5408 // Adjust Mask to the right number of elements.
5409 unsigned CurrMaskNumEls = Mask->getValueType(0).getVectorNumElements();
5410 if (CurrMaskNumEls > ToMaskVT.getVectorNumElements()) {
5411 SDValue ZeroIdx = DAG.getVectorIdxConstant(0, SDLoc(Mask));
5412 Mask = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SDLoc(Mask), ToMaskVT, Mask,
5413 ZeroIdx);
5414 } else if (CurrMaskNumEls < ToMaskVT.getVectorNumElements()) {
5415 unsigned NumSubVecs = (ToMaskVT.getVectorNumElements() / CurrMaskNumEls);
5416 EVT SubVT = Mask->getValueType(0);
5417 SmallVector<SDValue, 16> SubOps(NumSubVecs, DAG.getUNDEF(SubVT));
5418 SubOps[0] = Mask;
5419 Mask = DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Mask), ToMaskVT, SubOps);
5420 }
5421
5422 assert((Mask->getValueType(0) == ToMaskVT) &&
5423 "A mask of ToMaskVT should have been produced by now.");
5424
5425 return Mask;
5426 }
5427
5428 // This method tries to handle some special cases for the vselect mask
5429 // and if needed adjusting the mask vector type to match that of the VSELECT.
5430 // Without it, many cases end up with scalarization of the SETCC, with many
5431 // unnecessary instructions.
WidenVSELECTMask(SDNode * N)5432 SDValue DAGTypeLegalizer::WidenVSELECTMask(SDNode *N) {
5433 LLVMContext &Ctx = *DAG.getContext();
5434 SDValue Cond = N->getOperand(0);
5435
5436 if (N->getOpcode() != ISD::VSELECT)
5437 return SDValue();
5438
5439 if (!isSETCCOp(Cond->getOpcode()) && !isLogicalMaskOp(Cond->getOpcode()))
5440 return SDValue();
5441
5442 // If this is a splitted VSELECT that was previously already handled, do
5443 // nothing.
5444 EVT CondVT = Cond->getValueType(0);
5445 if (CondVT.getScalarSizeInBits() != 1)
5446 return SDValue();
5447
5448 EVT VSelVT = N->getValueType(0);
5449
5450 // This method can't handle scalable vector types.
5451 // FIXME: This support could be added in the future.
5452 if (VSelVT.isScalableVector())
5453 return SDValue();
5454
5455 // Only handle vector types which are a power of 2.
5456 if (!isPowerOf2_64(VSelVT.getSizeInBits()))
5457 return SDValue();
5458
5459 // Don't touch if this will be scalarized.
5460 EVT FinalVT = VSelVT;
5461 while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
5462 FinalVT = FinalVT.getHalfNumVectorElementsVT(Ctx);
5463
5464 if (FinalVT.getVectorNumElements() == 1)
5465 return SDValue();
5466
5467 // If there is support for an i1 vector mask, don't touch.
5468 if (isSETCCOp(Cond.getOpcode())) {
5469 EVT SetCCOpVT = getSETCCOperandType(Cond);
5470 while (TLI.getTypeAction(Ctx, SetCCOpVT) != TargetLowering::TypeLegal)
5471 SetCCOpVT = TLI.getTypeToTransformTo(Ctx, SetCCOpVT);
5472 EVT SetCCResVT = getSetCCResultType(SetCCOpVT);
5473 if (SetCCResVT.getScalarSizeInBits() == 1)
5474 return SDValue();
5475 } else if (CondVT.getScalarType() == MVT::i1) {
5476 // If there is support for an i1 vector mask (or only scalar i1 conditions),
5477 // don't touch.
5478 while (TLI.getTypeAction(Ctx, CondVT) != TargetLowering::TypeLegal)
5479 CondVT = TLI.getTypeToTransformTo(Ctx, CondVT);
5480
5481 if (CondVT.getScalarType() == MVT::i1)
5482 return SDValue();
5483 }
5484
5485 // Widen the vselect result type if needed.
5486 if (getTypeAction(VSelVT) == TargetLowering::TypeWidenVector)
5487 VSelVT = TLI.getTypeToTransformTo(Ctx, VSelVT);
5488
5489 // The mask of the VSELECT should have integer elements.
5490 EVT ToMaskVT = VSelVT;
5491 if (!ToMaskVT.getScalarType().isInteger())
5492 ToMaskVT = ToMaskVT.changeVectorElementTypeToInteger();
5493
5494 SDValue Mask;
5495 if (isSETCCOp(Cond->getOpcode())) {
5496 EVT MaskVT = getSetCCResultType(getSETCCOperandType(Cond));
5497 Mask = convertMask(Cond, MaskVT, ToMaskVT);
5498 } else if (isLogicalMaskOp(Cond->getOpcode()) &&
5499 isSETCCOp(Cond->getOperand(0).getOpcode()) &&
5500 isSETCCOp(Cond->getOperand(1).getOpcode())) {
5501 // Cond is (AND/OR/XOR (SETCC, SETCC))
5502 SDValue SETCC0 = Cond->getOperand(0);
5503 SDValue SETCC1 = Cond->getOperand(1);
5504 EVT VT0 = getSetCCResultType(getSETCCOperandType(SETCC0));
5505 EVT VT1 = getSetCCResultType(getSETCCOperandType(SETCC1));
5506 unsigned ScalarBits0 = VT0.getScalarSizeInBits();
5507 unsigned ScalarBits1 = VT1.getScalarSizeInBits();
5508 unsigned ScalarBits_ToMask = ToMaskVT.getScalarSizeInBits();
5509 EVT MaskVT;
5510 // If the two SETCCs have different VTs, either extend/truncate one of
5511 // them to the other "towards" ToMaskVT, or truncate one and extend the
5512 // other to ToMaskVT.
5513 if (ScalarBits0 != ScalarBits1) {
5514 EVT NarrowVT = ((ScalarBits0 < ScalarBits1) ? VT0 : VT1);
5515 EVT WideVT = ((NarrowVT == VT0) ? VT1 : VT0);
5516 if (ScalarBits_ToMask >= WideVT.getScalarSizeInBits())
5517 MaskVT = WideVT;
5518 else if (ScalarBits_ToMask <= NarrowVT.getScalarSizeInBits())
5519 MaskVT = NarrowVT;
5520 else
5521 MaskVT = ToMaskVT;
5522 } else
5523 // If the two SETCCs have the same VT, don't change it.
5524 MaskVT = VT0;
5525
5526 // Make new SETCCs and logical nodes.
5527 SETCC0 = convertMask(SETCC0, VT0, MaskVT);
5528 SETCC1 = convertMask(SETCC1, VT1, MaskVT);
5529 Cond = DAG.getNode(Cond->getOpcode(), SDLoc(Cond), MaskVT, SETCC0, SETCC1);
5530
5531 // Convert the logical op for VSELECT if needed.
5532 Mask = convertMask(Cond, MaskVT, ToMaskVT);
5533 } else
5534 return SDValue();
5535
5536 return Mask;
5537 }
5538
WidenVecRes_Select(SDNode * N)5539 SDValue DAGTypeLegalizer::WidenVecRes_Select(SDNode *N) {
5540 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5541 ElementCount WidenEC = WidenVT.getVectorElementCount();
5542
5543 SDValue Cond1 = N->getOperand(0);
5544 EVT CondVT = Cond1.getValueType();
5545 unsigned Opcode = N->getOpcode();
5546 if (CondVT.isVector()) {
5547 if (SDValue WideCond = WidenVSELECTMask(N)) {
5548 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
5549 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
5550 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
5551 return DAG.getNode(Opcode, SDLoc(N), WidenVT, WideCond, InOp1, InOp2);
5552 }
5553
5554 EVT CondEltVT = CondVT.getVectorElementType();
5555 EVT CondWidenVT = EVT::getVectorVT(*DAG.getContext(), CondEltVT, WidenEC);
5556 if (getTypeAction(CondVT) == TargetLowering::TypeWidenVector)
5557 Cond1 = GetWidenedVector(Cond1);
5558
5559 // If we have to split the condition there is no point in widening the
5560 // select. This would result in an cycle of widening the select ->
5561 // widening the condition operand -> splitting the condition operand ->
5562 // splitting the select -> widening the select. Instead split this select
5563 // further and widen the resulting type.
5564 if (getTypeAction(CondVT) == TargetLowering::TypeSplitVector) {
5565 SDValue SplitSelect = SplitVecOp_VSELECT(N, 0);
5566 SDValue Res = ModifyToType(SplitSelect, WidenVT);
5567 return Res;
5568 }
5569
5570 if (Cond1.getValueType() != CondWidenVT)
5571 Cond1 = ModifyToType(Cond1, CondWidenVT);
5572 }
5573
5574 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
5575 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
5576 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
5577 if (Opcode == ISD::VP_SELECT || Opcode == ISD::VP_MERGE)
5578 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2,
5579 N->getOperand(3));
5580 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2);
5581 }
5582
WidenVecRes_SELECT_CC(SDNode * N)5583 SDValue DAGTypeLegalizer::WidenVecRes_SELECT_CC(SDNode *N) {
5584 SDValue InOp1 = GetWidenedVector(N->getOperand(2));
5585 SDValue InOp2 = GetWidenedVector(N->getOperand(3));
5586 return DAG.getNode(ISD::SELECT_CC, SDLoc(N),
5587 InOp1.getValueType(), N->getOperand(0),
5588 N->getOperand(1), InOp1, InOp2, N->getOperand(4));
5589 }
5590
WidenVecRes_UNDEF(SDNode * N)5591 SDValue DAGTypeLegalizer::WidenVecRes_UNDEF(SDNode *N) {
5592 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5593 return DAG.getUNDEF(WidenVT);
5594 }
5595
WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode * N)5596 SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N) {
5597 EVT VT = N->getValueType(0);
5598 SDLoc dl(N);
5599
5600 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
5601 unsigned NumElts = VT.getVectorNumElements();
5602 unsigned WidenNumElts = WidenVT.getVectorNumElements();
5603
5604 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5605 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5606
5607 // Adjust mask based on new input vector length.
5608 SmallVector<int, 16> NewMask;
5609 for (unsigned i = 0; i != NumElts; ++i) {
5610 int Idx = N->getMaskElt(i);
5611 if (Idx < (int)NumElts)
5612 NewMask.push_back(Idx);
5613 else
5614 NewMask.push_back(Idx - NumElts + WidenNumElts);
5615 }
5616 for (unsigned i = NumElts; i != WidenNumElts; ++i)
5617 NewMask.push_back(-1);
5618 return DAG.getVectorShuffle(WidenVT, dl, InOp1, InOp2, NewMask);
5619 }
5620
WidenVecRes_VECTOR_REVERSE(SDNode * N)5621 SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_REVERSE(SDNode *N) {
5622 EVT VT = N->getValueType(0);
5623 EVT EltVT = VT.getVectorElementType();
5624 SDLoc dl(N);
5625
5626 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
5627 SDValue OpValue = GetWidenedVector(N->getOperand(0));
5628 assert(WidenVT == OpValue.getValueType() && "Unexpected widened vector type");
5629
5630 SDValue ReverseVal = DAG.getNode(ISD::VECTOR_REVERSE, dl, WidenVT, OpValue);
5631 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
5632 unsigned VTNumElts = VT.getVectorMinNumElements();
5633 unsigned IdxVal = WidenNumElts - VTNumElts;
5634
5635 if (VT.isScalableVector()) {
5636 // Try to split the 'Widen ReverseVal' into smaller extracts and concat the
5637 // results together, e.g.(nxv6i64 -> nxv8i64)
5638 // nxv8i64 vector_reverse
5639 // <->
5640 // nxv8i64 concat(
5641 // nxv2i64 extract_subvector(nxv8i64, 2)
5642 // nxv2i64 extract_subvector(nxv8i64, 4)
5643 // nxv2i64 extract_subvector(nxv8i64, 6)
5644 // nxv2i64 undef)
5645
5646 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
5647 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
5648 ElementCount::getScalable(GCD));
5649 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
5650 "down type's element count");
5651 SmallVector<SDValue> Parts;
5652 unsigned i = 0;
5653 for (; i < VTNumElts / GCD; ++i)
5654 Parts.push_back(
5655 DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, PartVT, ReverseVal,
5656 DAG.getVectorIdxConstant(IdxVal + i * GCD, dl)));
5657 for (; i < WidenNumElts / GCD; ++i)
5658 Parts.push_back(DAG.getUNDEF(PartVT));
5659
5660 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
5661 }
5662
5663 // Use VECTOR_SHUFFLE to combine new vector from 'ReverseVal' for
5664 // fixed-vectors.
5665 SmallVector<int, 16> Mask;
5666 for (unsigned i = 0; i != VTNumElts; ++i) {
5667 Mask.push_back(IdxVal + i);
5668 }
5669 for (unsigned i = VTNumElts; i != WidenNumElts; ++i)
5670 Mask.push_back(-1);
5671
5672 return DAG.getVectorShuffle(WidenVT, dl, ReverseVal, DAG.getUNDEF(WidenVT),
5673 Mask);
5674 }
5675
WidenVecRes_SETCC(SDNode * N)5676 SDValue DAGTypeLegalizer::WidenVecRes_SETCC(SDNode *N) {
5677 assert(N->getValueType(0).isVector() &&
5678 N->getOperand(0).getValueType().isVector() &&
5679 "Operands must be vectors");
5680 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5681 ElementCount WidenEC = WidenVT.getVectorElementCount();
5682
5683 SDValue InOp1 = N->getOperand(0);
5684 EVT InVT = InOp1.getValueType();
5685 assert(InVT.isVector() && "can not widen non-vector type");
5686 EVT WidenInVT =
5687 EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), WidenEC);
5688
5689 // The input and output types often differ here, and it could be that while
5690 // we'd prefer to widen the result type, the input operands have been split.
5691 // In this case, we also need to split the result of this node as well.
5692 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector) {
5693 SDValue SplitVSetCC = SplitVecOp_VSETCC(N);
5694 SDValue Res = ModifyToType(SplitVSetCC, WidenVT);
5695 return Res;
5696 }
5697
5698 // If the inputs also widen, handle them directly. Otherwise widen by hand.
5699 SDValue InOp2 = N->getOperand(1);
5700 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
5701 InOp1 = GetWidenedVector(InOp1);
5702 InOp2 = GetWidenedVector(InOp2);
5703 } else {
5704 InOp1 = DAG.WidenVector(InOp1, SDLoc(N));
5705 InOp2 = DAG.WidenVector(InOp2, SDLoc(N));
5706 }
5707
5708 // Assume that the input and output will be widen appropriately. If not,
5709 // we will have to unroll it at some point.
5710 assert(InOp1.getValueType() == WidenInVT &&
5711 InOp2.getValueType() == WidenInVT &&
5712 "Input not widened to expected type!");
5713 (void)WidenInVT;
5714 if (N->getOpcode() == ISD::VP_SETCC) {
5715 SDValue Mask =
5716 GetWidenedMask(N->getOperand(3), WidenVT.getVectorElementCount());
5717 return DAG.getNode(ISD::VP_SETCC, SDLoc(N), WidenVT, InOp1, InOp2,
5718 N->getOperand(2), Mask, N->getOperand(4));
5719 }
5720 return DAG.getNode(ISD::SETCC, SDLoc(N), WidenVT, InOp1, InOp2,
5721 N->getOperand(2));
5722 }
5723
WidenVecRes_STRICT_FSETCC(SDNode * N)5724 SDValue DAGTypeLegalizer::WidenVecRes_STRICT_FSETCC(SDNode *N) {
5725 assert(N->getValueType(0).isVector() &&
5726 N->getOperand(1).getValueType().isVector() &&
5727 "Operands must be vectors");
5728 EVT VT = N->getValueType(0);
5729 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
5730 unsigned WidenNumElts = WidenVT.getVectorNumElements();
5731 unsigned NumElts = VT.getVectorNumElements();
5732 EVT EltVT = VT.getVectorElementType();
5733
5734 SDLoc dl(N);
5735 SDValue Chain = N->getOperand(0);
5736 SDValue LHS = N->getOperand(1);
5737 SDValue RHS = N->getOperand(2);
5738 SDValue CC = N->getOperand(3);
5739 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
5740
5741 // Fully unroll and reassemble.
5742 SmallVector<SDValue, 8> Scalars(WidenNumElts, DAG.getUNDEF(EltVT));
5743 SmallVector<SDValue, 8> Chains(NumElts);
5744 for (unsigned i = 0; i != NumElts; ++i) {
5745 SDValue LHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, LHS,
5746 DAG.getVectorIdxConstant(i, dl));
5747 SDValue RHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, RHS,
5748 DAG.getVectorIdxConstant(i, dl));
5749
5750 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
5751 {Chain, LHSElem, RHSElem, CC});
5752 Chains[i] = Scalars[i].getValue(1);
5753 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
5754 DAG.getBoolConstant(true, dl, EltVT, VT),
5755 DAG.getBoolConstant(false, dl, EltVT, VT));
5756 }
5757
5758 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
5759 ReplaceValueWith(SDValue(N, 1), NewChain);
5760
5761 return DAG.getBuildVector(WidenVT, dl, Scalars);
5762 }
5763
5764 //===----------------------------------------------------------------------===//
5765 // Widen Vector Operand
5766 //===----------------------------------------------------------------------===//
WidenVectorOperand(SDNode * N,unsigned OpNo)5767 bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned OpNo) {
5768 LLVM_DEBUG(dbgs() << "Widen node operand " << OpNo << ": "; N->dump(&DAG);
5769 dbgs() << "\n");
5770 SDValue Res = SDValue();
5771
5772 // See if the target wants to custom widen this node.
5773 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
5774 return false;
5775
5776 switch (N->getOpcode()) {
5777 default:
5778 #ifndef NDEBUG
5779 dbgs() << "WidenVectorOperand op #" << OpNo << ": ";
5780 N->dump(&DAG);
5781 dbgs() << "\n";
5782 #endif
5783 llvm_unreachable("Do not know how to widen this operator's operand!");
5784
5785 case ISD::BITCAST: Res = WidenVecOp_BITCAST(N); break;
5786 case ISD::CONCAT_VECTORS: Res = WidenVecOp_CONCAT_VECTORS(N); break;
5787 case ISD::INSERT_SUBVECTOR: Res = WidenVecOp_INSERT_SUBVECTOR(N); break;
5788 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecOp_EXTRACT_SUBVECTOR(N); break;
5789 case ISD::EXTRACT_VECTOR_ELT: Res = WidenVecOp_EXTRACT_VECTOR_ELT(N); break;
5790 case ISD::STORE: Res = WidenVecOp_STORE(N); break;
5791 case ISD::VP_STORE: Res = WidenVecOp_VP_STORE(N, OpNo); break;
5792 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
5793 Res = WidenVecOp_VP_STRIDED_STORE(N, OpNo);
5794 break;
5795 case ISD::MSTORE: Res = WidenVecOp_MSTORE(N, OpNo); break;
5796 case ISD::MGATHER: Res = WidenVecOp_MGATHER(N, OpNo); break;
5797 case ISD::MSCATTER: Res = WidenVecOp_MSCATTER(N, OpNo); break;
5798 case ISD::VP_SCATTER: Res = WidenVecOp_VP_SCATTER(N, OpNo); break;
5799 case ISD::SETCC: Res = WidenVecOp_SETCC(N); break;
5800 case ISD::STRICT_FSETCC:
5801 case ISD::STRICT_FSETCCS: Res = WidenVecOp_STRICT_FSETCC(N); break;
5802 case ISD::VSELECT: Res = WidenVecOp_VSELECT(N); break;
5803 case ISD::FCOPYSIGN: Res = WidenVecOp_FCOPYSIGN(N); break;
5804 case ISD::IS_FPCLASS: Res = WidenVecOp_IS_FPCLASS(N); break;
5805
5806 case ISD::ANY_EXTEND:
5807 case ISD::SIGN_EXTEND:
5808 case ISD::ZERO_EXTEND:
5809 Res = WidenVecOp_EXTEND(N);
5810 break;
5811
5812 case ISD::FP_EXTEND:
5813 case ISD::STRICT_FP_EXTEND:
5814 case ISD::FP_ROUND:
5815 case ISD::STRICT_FP_ROUND:
5816 case ISD::FP_TO_SINT:
5817 case ISD::STRICT_FP_TO_SINT:
5818 case ISD::FP_TO_UINT:
5819 case ISD::STRICT_FP_TO_UINT:
5820 case ISD::SINT_TO_FP:
5821 case ISD::STRICT_SINT_TO_FP:
5822 case ISD::UINT_TO_FP:
5823 case ISD::STRICT_UINT_TO_FP:
5824 case ISD::TRUNCATE:
5825 Res = WidenVecOp_Convert(N);
5826 break;
5827
5828 case ISD::FP_TO_SINT_SAT:
5829 case ISD::FP_TO_UINT_SAT:
5830 Res = WidenVecOp_FP_TO_XINT_SAT(N);
5831 break;
5832
5833 case ISD::VECREDUCE_FADD:
5834 case ISD::VECREDUCE_FMUL:
5835 case ISD::VECREDUCE_ADD:
5836 case ISD::VECREDUCE_MUL:
5837 case ISD::VECREDUCE_AND:
5838 case ISD::VECREDUCE_OR:
5839 case ISD::VECREDUCE_XOR:
5840 case ISD::VECREDUCE_SMAX:
5841 case ISD::VECREDUCE_SMIN:
5842 case ISD::VECREDUCE_UMAX:
5843 case ISD::VECREDUCE_UMIN:
5844 case ISD::VECREDUCE_FMAX:
5845 case ISD::VECREDUCE_FMIN:
5846 Res = WidenVecOp_VECREDUCE(N);
5847 break;
5848 case ISD::VECREDUCE_SEQ_FADD:
5849 case ISD::VECREDUCE_SEQ_FMUL:
5850 Res = WidenVecOp_VECREDUCE_SEQ(N);
5851 break;
5852 case ISD::VP_REDUCE_FADD:
5853 case ISD::VP_REDUCE_SEQ_FADD:
5854 case ISD::VP_REDUCE_FMUL:
5855 case ISD::VP_REDUCE_SEQ_FMUL:
5856 case ISD::VP_REDUCE_ADD:
5857 case ISD::VP_REDUCE_MUL:
5858 case ISD::VP_REDUCE_AND:
5859 case ISD::VP_REDUCE_OR:
5860 case ISD::VP_REDUCE_XOR:
5861 case ISD::VP_REDUCE_SMAX:
5862 case ISD::VP_REDUCE_SMIN:
5863 case ISD::VP_REDUCE_UMAX:
5864 case ISD::VP_REDUCE_UMIN:
5865 case ISD::VP_REDUCE_FMAX:
5866 case ISD::VP_REDUCE_FMIN:
5867 Res = WidenVecOp_VP_REDUCE(N);
5868 break;
5869 }
5870
5871 // If Res is null, the sub-method took care of registering the result.
5872 if (!Res.getNode()) return false;
5873
5874 // If the result is N, the sub-method updated N in place. Tell the legalizer
5875 // core about this.
5876 if (Res.getNode() == N)
5877 return true;
5878
5879
5880 if (N->isStrictFPOpcode())
5881 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
5882 "Invalid operand expansion");
5883 else
5884 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
5885 "Invalid operand expansion");
5886
5887 ReplaceValueWith(SDValue(N, 0), Res);
5888 return false;
5889 }
5890
WidenVecOp_EXTEND(SDNode * N)5891 SDValue DAGTypeLegalizer::WidenVecOp_EXTEND(SDNode *N) {
5892 SDLoc DL(N);
5893 EVT VT = N->getValueType(0);
5894
5895 SDValue InOp = N->getOperand(0);
5896 assert(getTypeAction(InOp.getValueType()) ==
5897 TargetLowering::TypeWidenVector &&
5898 "Unexpected type action");
5899 InOp = GetWidenedVector(InOp);
5900 assert(VT.getVectorNumElements() <
5901 InOp.getValueType().getVectorNumElements() &&
5902 "Input wasn't widened!");
5903
5904 // We may need to further widen the operand until it has the same total
5905 // vector size as the result.
5906 EVT InVT = InOp.getValueType();
5907 if (InVT.getSizeInBits() != VT.getSizeInBits()) {
5908 EVT InEltVT = InVT.getVectorElementType();
5909 for (EVT FixedVT : MVT::vector_valuetypes()) {
5910 EVT FixedEltVT = FixedVT.getVectorElementType();
5911 if (TLI.isTypeLegal(FixedVT) &&
5912 FixedVT.getSizeInBits() == VT.getSizeInBits() &&
5913 FixedEltVT == InEltVT) {
5914 assert(FixedVT.getVectorNumElements() >= VT.getVectorNumElements() &&
5915 "Not enough elements in the fixed type for the operand!");
5916 assert(FixedVT.getVectorNumElements() != InVT.getVectorNumElements() &&
5917 "We can't have the same type as we started with!");
5918 if (FixedVT.getVectorNumElements() > InVT.getVectorNumElements())
5919 InOp = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, FixedVT,
5920 DAG.getUNDEF(FixedVT), InOp,
5921 DAG.getVectorIdxConstant(0, DL));
5922 else
5923 InOp = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, FixedVT, InOp,
5924 DAG.getVectorIdxConstant(0, DL));
5925 break;
5926 }
5927 }
5928 InVT = InOp.getValueType();
5929 if (InVT.getSizeInBits() != VT.getSizeInBits())
5930 // We couldn't find a legal vector type that was a widening of the input
5931 // and could be extended in-register to the result type, so we have to
5932 // scalarize.
5933 return WidenVecOp_Convert(N);
5934 }
5935
5936 // Use special DAG nodes to represent the operation of extending the
5937 // low lanes.
5938 switch (N->getOpcode()) {
5939 default:
5940 llvm_unreachable("Extend legalization on extend operation!");
5941 case ISD::ANY_EXTEND:
5942 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, VT, InOp);
5943 case ISD::SIGN_EXTEND:
5944 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, VT, InOp);
5945 case ISD::ZERO_EXTEND:
5946 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, VT, InOp);
5947 }
5948 }
5949
WidenVecOp_FCOPYSIGN(SDNode * N)5950 SDValue DAGTypeLegalizer::WidenVecOp_FCOPYSIGN(SDNode *N) {
5951 // The result (and first input) is legal, but the second input is illegal.
5952 // We can't do much to fix that, so just unroll and let the extracts off of
5953 // the second input be widened as needed later.
5954 return DAG.UnrollVectorOp(N);
5955 }
5956
WidenVecOp_IS_FPCLASS(SDNode * N)5957 SDValue DAGTypeLegalizer::WidenVecOp_IS_FPCLASS(SDNode *N) {
5958 SDLoc DL(N);
5959 EVT ResultVT = N->getValueType(0);
5960 SDValue Test = N->getOperand(1);
5961 SDValue WideArg = GetWidenedVector(N->getOperand(0));
5962
5963 // Process this node similarly to SETCC.
5964 EVT WideResultVT = getSetCCResultType(WideArg.getValueType());
5965 if (ResultVT.getScalarType() == MVT::i1)
5966 WideResultVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
5967 WideResultVT.getVectorNumElements());
5968
5969 SDValue WideNode = DAG.getNode(ISD::IS_FPCLASS, DL, WideResultVT,
5970 {WideArg, Test}, N->getFlags());
5971
5972 // Extract the needed results from the result vector.
5973 EVT ResVT =
5974 EVT::getVectorVT(*DAG.getContext(), WideResultVT.getVectorElementType(),
5975 ResultVT.getVectorNumElements());
5976 SDValue CC = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, ResVT, WideNode,
5977 DAG.getVectorIdxConstant(0, DL));
5978
5979 EVT OpVT = N->getOperand(0).getValueType();
5980 ISD::NodeType ExtendCode =
5981 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
5982 return DAG.getNode(ExtendCode, DL, ResultVT, CC);
5983 }
5984
WidenVecOp_Convert(SDNode * N)5985 SDValue DAGTypeLegalizer::WidenVecOp_Convert(SDNode *N) {
5986 // Since the result is legal and the input is illegal.
5987 EVT VT = N->getValueType(0);
5988 EVT EltVT = VT.getVectorElementType();
5989 SDLoc dl(N);
5990 SDValue InOp = N->getOperand(N->isStrictFPOpcode() ? 1 : 0);
5991 assert(getTypeAction(InOp.getValueType()) ==
5992 TargetLowering::TypeWidenVector &&
5993 "Unexpected type action");
5994 InOp = GetWidenedVector(InOp);
5995 EVT InVT = InOp.getValueType();
5996 unsigned Opcode = N->getOpcode();
5997
5998 // See if a widened result type would be legal, if so widen the node.
5999 // FIXME: This isn't safe for StrictFP. Other optimization here is needed.
6000 EVT WideVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
6001 InVT.getVectorElementCount());
6002 if (TLI.isTypeLegal(WideVT) && !N->isStrictFPOpcode()) {
6003 SDValue Res;
6004 if (N->isStrictFPOpcode()) {
6005 if (Opcode == ISD::STRICT_FP_ROUND)
6006 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
6007 { N->getOperand(0), InOp, N->getOperand(2) });
6008 else
6009 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
6010 { N->getOperand(0), InOp });
6011 // Legalize the chain result - switch anything that used the old chain to
6012 // use the new one.
6013 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6014 } else {
6015 if (Opcode == ISD::FP_ROUND)
6016 Res = DAG.getNode(Opcode, dl, WideVT, InOp, N->getOperand(1));
6017 else
6018 Res = DAG.getNode(Opcode, dl, WideVT, InOp);
6019 }
6020 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, Res,
6021 DAG.getVectorIdxConstant(0, dl));
6022 }
6023
6024 EVT InEltVT = InVT.getVectorElementType();
6025
6026 // Unroll the convert into some scalar code and create a nasty build vector.
6027 unsigned NumElts = VT.getVectorNumElements();
6028 SmallVector<SDValue, 16> Ops(NumElts);
6029 if (N->isStrictFPOpcode()) {
6030 SmallVector<SDValue, 4> NewOps(N->op_begin(), N->op_end());
6031 SmallVector<SDValue, 32> OpChains;
6032 for (unsigned i=0; i < NumElts; ++i) {
6033 NewOps[1] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, InEltVT, InOp,
6034 DAG.getVectorIdxConstant(i, dl));
6035 Ops[i] = DAG.getNode(Opcode, dl, { EltVT, MVT::Other }, NewOps);
6036 OpChains.push_back(Ops[i].getValue(1));
6037 }
6038 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OpChains);
6039 ReplaceValueWith(SDValue(N, 1), NewChain);
6040 } else {
6041 for (unsigned i = 0; i < NumElts; ++i)
6042 Ops[i] = DAG.getNode(Opcode, dl, EltVT,
6043 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, InEltVT,
6044 InOp, DAG.getVectorIdxConstant(i, dl)));
6045 }
6046
6047 return DAG.getBuildVector(VT, dl, Ops);
6048 }
6049
WidenVecOp_FP_TO_XINT_SAT(SDNode * N)6050 SDValue DAGTypeLegalizer::WidenVecOp_FP_TO_XINT_SAT(SDNode *N) {
6051 EVT DstVT = N->getValueType(0);
6052 SDValue Src = GetWidenedVector(N->getOperand(0));
6053 EVT SrcVT = Src.getValueType();
6054 ElementCount WideNumElts = SrcVT.getVectorElementCount();
6055 SDLoc dl(N);
6056
6057 // See if a widened result type would be legal, if so widen the node.
6058 EVT WideDstVT = EVT::getVectorVT(*DAG.getContext(),
6059 DstVT.getVectorElementType(), WideNumElts);
6060 if (TLI.isTypeLegal(WideDstVT)) {
6061 SDValue Res =
6062 DAG.getNode(N->getOpcode(), dl, WideDstVT, Src, N->getOperand(1));
6063 return DAG.getNode(
6064 ISD::EXTRACT_SUBVECTOR, dl, DstVT, Res,
6065 DAG.getConstant(0, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
6066 }
6067
6068 // Give up and unroll.
6069 return DAG.UnrollVectorOp(N);
6070 }
6071
WidenVecOp_BITCAST(SDNode * N)6072 SDValue DAGTypeLegalizer::WidenVecOp_BITCAST(SDNode *N) {
6073 EVT VT = N->getValueType(0);
6074 SDValue InOp = GetWidenedVector(N->getOperand(0));
6075 EVT InWidenVT = InOp.getValueType();
6076 SDLoc dl(N);
6077
6078 // Check if we can convert between two legal vector types and extract.
6079 TypeSize InWidenSize = InWidenVT.getSizeInBits();
6080 TypeSize Size = VT.getSizeInBits();
6081 // x86mmx is not an acceptable vector element type, so don't try.
6082 if (!VT.isVector() && VT != MVT::x86mmx &&
6083 InWidenSize.hasKnownScalarFactor(Size)) {
6084 unsigned NewNumElts = InWidenSize.getKnownScalarFactor(Size);
6085 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), VT, NewNumElts);
6086 if (TLI.isTypeLegal(NewVT)) {
6087 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
6088 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, VT, BitOp,
6089 DAG.getVectorIdxConstant(0, dl));
6090 }
6091 }
6092
6093 // Handle a case like bitcast v12i8 -> v3i32. Normally that would get widened
6094 // to v16i8 -> v4i32, but for a target where v3i32 is legal but v12i8 is not,
6095 // we end up here. Handling the case here with EXTRACT_SUBVECTOR avoids
6096 // having to copy via memory.
6097 if (VT.isVector()) {
6098 EVT EltVT = VT.getVectorElementType();
6099 unsigned EltSize = EltVT.getFixedSizeInBits();
6100 if (InWidenSize.isKnownMultipleOf(EltSize)) {
6101 ElementCount NewNumElts =
6102 (InWidenVT.getVectorElementCount() * InWidenVT.getScalarSizeInBits())
6103 .divideCoefficientBy(EltSize);
6104 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NewNumElts);
6105 if (TLI.isTypeLegal(NewVT)) {
6106 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
6107 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, BitOp,
6108 DAG.getVectorIdxConstant(0, dl));
6109 }
6110 }
6111 }
6112
6113 return CreateStackStoreLoad(InOp, VT);
6114 }
6115
WidenVecOp_CONCAT_VECTORS(SDNode * N)6116 SDValue DAGTypeLegalizer::WidenVecOp_CONCAT_VECTORS(SDNode *N) {
6117 EVT VT = N->getValueType(0);
6118 EVT EltVT = VT.getVectorElementType();
6119 EVT InVT = N->getOperand(0).getValueType();
6120 SDLoc dl(N);
6121
6122 // If the widen width for this operand is the same as the width of the concat
6123 // and all but the first operand is undef, just use the widened operand.
6124 unsigned NumOperands = N->getNumOperands();
6125 if (VT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
6126 unsigned i;
6127 for (i = 1; i < NumOperands; ++i)
6128 if (!N->getOperand(i).isUndef())
6129 break;
6130
6131 if (i == NumOperands)
6132 return GetWidenedVector(N->getOperand(0));
6133 }
6134
6135 // Otherwise, fall back to a nasty build vector.
6136 unsigned NumElts = VT.getVectorNumElements();
6137 SmallVector<SDValue, 16> Ops(NumElts);
6138
6139 unsigned NumInElts = InVT.getVectorNumElements();
6140
6141 unsigned Idx = 0;
6142 for (unsigned i=0; i < NumOperands; ++i) {
6143 SDValue InOp = N->getOperand(i);
6144 assert(getTypeAction(InOp.getValueType()) ==
6145 TargetLowering::TypeWidenVector &&
6146 "Unexpected type action");
6147 InOp = GetWidenedVector(InOp);
6148 for (unsigned j = 0; j < NumInElts; ++j)
6149 Ops[Idx++] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp,
6150 DAG.getVectorIdxConstant(j, dl));
6151 }
6152 return DAG.getBuildVector(VT, dl, Ops);
6153 }
6154
WidenVecOp_INSERT_SUBVECTOR(SDNode * N)6155 SDValue DAGTypeLegalizer::WidenVecOp_INSERT_SUBVECTOR(SDNode *N) {
6156 EVT VT = N->getValueType(0);
6157 SDValue SubVec = N->getOperand(1);
6158 SDValue InVec = N->getOperand(0);
6159
6160 if (getTypeAction(SubVec.getValueType()) == TargetLowering::TypeWidenVector)
6161 SubVec = GetWidenedVector(SubVec);
6162
6163 if (SubVec.getValueType().knownBitsLE(VT) && InVec.isUndef() &&
6164 N->getConstantOperandVal(2) == 0)
6165 return DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), VT, InVec, SubVec,
6166 N->getOperand(2));
6167
6168 report_fatal_error("Don't know how to widen the operands for "
6169 "INSERT_SUBVECTOR");
6170 }
6171
WidenVecOp_EXTRACT_SUBVECTOR(SDNode * N)6172 SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
6173 SDValue InOp = GetWidenedVector(N->getOperand(0));
6174 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SDLoc(N),
6175 N->getValueType(0), InOp, N->getOperand(1));
6176 }
6177
WidenVecOp_EXTRACT_VECTOR_ELT(SDNode * N)6178 SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
6179 SDValue InOp = GetWidenedVector(N->getOperand(0));
6180 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
6181 N->getValueType(0), InOp, N->getOperand(1));
6182 }
6183
WidenVecOp_STORE(SDNode * N)6184 SDValue DAGTypeLegalizer::WidenVecOp_STORE(SDNode *N) {
6185 // We have to widen the value, but we want only to store the original
6186 // vector type.
6187 StoreSDNode *ST = cast<StoreSDNode>(N);
6188
6189 if (!ST->getMemoryVT().getScalarType().isByteSized())
6190 return TLI.scalarizeVectorStore(ST, DAG);
6191
6192 if (ST->isTruncatingStore())
6193 return TLI.scalarizeVectorStore(ST, DAG);
6194
6195 SmallVector<SDValue, 16> StChain;
6196 if (GenWidenVectorStores(StChain, ST)) {
6197 if (StChain.size() == 1)
6198 return StChain[0];
6199
6200 return DAG.getNode(ISD::TokenFactor, SDLoc(ST), MVT::Other, StChain);
6201 }
6202
6203 // Generate a vector-predicated store if it is custom/legal on the target.
6204 // To avoid possible recursion, only do this if the widened mask type is
6205 // legal.
6206 // FIXME: Not all targets may support EVL in VP_STORE. These will have been
6207 // removed from the IR by the ExpandVectorPredication pass but we're
6208 // reintroducing them here.
6209 SDValue StVal = ST->getValue();
6210 EVT StVT = StVal.getValueType();
6211 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), StVT);
6212 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
6213 WideVT.getVectorElementCount());
6214 if (WideVT.isScalableVector() &&
6215 TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
6216 TLI.isTypeLegal(WideMaskVT)) {
6217 // Widen the value.
6218 SDLoc DL(N);
6219 StVal = GetWidenedVector(StVal);
6220 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
6221 MVT EVLVT = TLI.getVPExplicitVectorLengthTy();
6222 unsigned NumVTElts = StVT.getVectorMinNumElements();
6223 SDValue EVL =
6224 DAG.getVScale(DL, EVLVT, APInt(EVLVT.getScalarSizeInBits(), NumVTElts));
6225 return DAG.getStoreVP(ST->getChain(), DL, StVal, ST->getBasePtr(),
6226 DAG.getUNDEF(ST->getBasePtr().getValueType()), Mask,
6227 EVL, StVal.getValueType(), ST->getMemOperand(),
6228 ST->getAddressingMode());
6229 }
6230
6231 report_fatal_error("Unable to widen vector store");
6232 }
6233
WidenVecOp_VP_STORE(SDNode * N,unsigned OpNo)6234 SDValue DAGTypeLegalizer::WidenVecOp_VP_STORE(SDNode *N, unsigned OpNo) {
6235 assert((OpNo == 1 || OpNo == 3) &&
6236 "Can widen only data or mask operand of vp_store");
6237 VPStoreSDNode *ST = cast<VPStoreSDNode>(N);
6238 SDValue Mask = ST->getMask();
6239 SDValue StVal = ST->getValue();
6240 SDLoc dl(N);
6241
6242 if (OpNo == 1) {
6243 // Widen the value.
6244 StVal = GetWidenedVector(StVal);
6245
6246 // We only handle the case where the mask needs widening to an
6247 // identically-sized type as the vector inputs.
6248 assert(getTypeAction(Mask.getValueType()) ==
6249 TargetLowering::TypeWidenVector &&
6250 "Unable to widen VP store");
6251 Mask = GetWidenedVector(Mask);
6252 } else {
6253 Mask = GetWidenedVector(Mask);
6254
6255 // We only handle the case where the stored value needs widening to an
6256 // identically-sized type as the mask.
6257 assert(getTypeAction(StVal.getValueType()) ==
6258 TargetLowering::TypeWidenVector &&
6259 "Unable to widen VP store");
6260 StVal = GetWidenedVector(StVal);
6261 }
6262
6263 assert(Mask.getValueType().getVectorElementCount() ==
6264 StVal.getValueType().getVectorElementCount() &&
6265 "Mask and data vectors should have the same number of elements");
6266 return DAG.getStoreVP(ST->getChain(), dl, StVal, ST->getBasePtr(),
6267 ST->getOffset(), Mask, ST->getVectorLength(),
6268 ST->getMemoryVT(), ST->getMemOperand(),
6269 ST->getAddressingMode(), ST->isTruncatingStore(),
6270 ST->isCompressingStore());
6271 }
6272
WidenVecOp_VP_STRIDED_STORE(SDNode * N,unsigned OpNo)6273 SDValue DAGTypeLegalizer::WidenVecOp_VP_STRIDED_STORE(SDNode *N,
6274 unsigned OpNo) {
6275 assert((OpNo == 1 || OpNo == 4) &&
6276 "Can widen only data or mask operand of vp_strided_store");
6277 VPStridedStoreSDNode *SST = cast<VPStridedStoreSDNode>(N);
6278 SDValue Mask = SST->getMask();
6279 SDValue StVal = SST->getValue();
6280 SDLoc DL(N);
6281
6282 if (OpNo == 1)
6283 assert(getTypeAction(Mask.getValueType()) ==
6284 TargetLowering::TypeWidenVector &&
6285 "Unable to widen VP strided store");
6286 else
6287 assert(getTypeAction(StVal.getValueType()) ==
6288 TargetLowering::TypeWidenVector &&
6289 "Unable to widen VP strided store");
6290
6291 StVal = GetWidenedVector(StVal);
6292 Mask = GetWidenedVector(Mask);
6293
6294 assert(StVal.getValueType().getVectorElementCount() ==
6295 Mask.getValueType().getVectorElementCount() &&
6296 "Data and mask vectors should have the same number of elements");
6297
6298 return DAG.getStridedStoreVP(
6299 SST->getChain(), DL, StVal, SST->getBasePtr(), SST->getOffset(),
6300 SST->getStride(), Mask, SST->getVectorLength(), SST->getMemoryVT(),
6301 SST->getMemOperand(), SST->getAddressingMode(), SST->isTruncatingStore(),
6302 SST->isCompressingStore());
6303 }
6304
WidenVecOp_MSTORE(SDNode * N,unsigned OpNo)6305 SDValue DAGTypeLegalizer::WidenVecOp_MSTORE(SDNode *N, unsigned OpNo) {
6306 assert((OpNo == 1 || OpNo == 3) &&
6307 "Can widen only data or mask operand of mstore");
6308 MaskedStoreSDNode *MST = cast<MaskedStoreSDNode>(N);
6309 SDValue Mask = MST->getMask();
6310 EVT MaskVT = Mask.getValueType();
6311 SDValue StVal = MST->getValue();
6312 SDLoc dl(N);
6313
6314 if (OpNo == 1) {
6315 // Widen the value.
6316 StVal = GetWidenedVector(StVal);
6317
6318 // The mask should be widened as well.
6319 EVT WideVT = StVal.getValueType();
6320 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
6321 MaskVT.getVectorElementType(),
6322 WideVT.getVectorNumElements());
6323 Mask = ModifyToType(Mask, WideMaskVT, true);
6324 } else {
6325 // Widen the mask.
6326 EVT WideMaskVT = TLI.getTypeToTransformTo(*DAG.getContext(), MaskVT);
6327 Mask = ModifyToType(Mask, WideMaskVT, true);
6328
6329 EVT ValueVT = StVal.getValueType();
6330 EVT WideVT = EVT::getVectorVT(*DAG.getContext(),
6331 ValueVT.getVectorElementType(),
6332 WideMaskVT.getVectorNumElements());
6333 StVal = ModifyToType(StVal, WideVT);
6334 }
6335
6336 assert(Mask.getValueType().getVectorNumElements() ==
6337 StVal.getValueType().getVectorNumElements() &&
6338 "Mask and data vectors should have the same number of elements");
6339 return DAG.getMaskedStore(MST->getChain(), dl, StVal, MST->getBasePtr(),
6340 MST->getOffset(), Mask, MST->getMemoryVT(),
6341 MST->getMemOperand(), MST->getAddressingMode(),
6342 false, MST->isCompressingStore());
6343 }
6344
WidenVecOp_MGATHER(SDNode * N,unsigned OpNo)6345 SDValue DAGTypeLegalizer::WidenVecOp_MGATHER(SDNode *N, unsigned OpNo) {
6346 assert(OpNo == 4 && "Can widen only the index of mgather");
6347 auto *MG = cast<MaskedGatherSDNode>(N);
6348 SDValue DataOp = MG->getPassThru();
6349 SDValue Mask = MG->getMask();
6350 SDValue Scale = MG->getScale();
6351
6352 // Just widen the index. It's allowed to have extra elements.
6353 SDValue Index = GetWidenedVector(MG->getIndex());
6354
6355 SDLoc dl(N);
6356 SDValue Ops[] = {MG->getChain(), DataOp, Mask, MG->getBasePtr(), Index,
6357 Scale};
6358 SDValue Res = DAG.getMaskedGather(MG->getVTList(), MG->getMemoryVT(), dl, Ops,
6359 MG->getMemOperand(), MG->getIndexType(),
6360 MG->getExtensionType());
6361 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
6362 ReplaceValueWith(SDValue(N, 0), Res.getValue(0));
6363 return SDValue();
6364 }
6365
WidenVecOp_MSCATTER(SDNode * N,unsigned OpNo)6366 SDValue DAGTypeLegalizer::WidenVecOp_MSCATTER(SDNode *N, unsigned OpNo) {
6367 MaskedScatterSDNode *MSC = cast<MaskedScatterSDNode>(N);
6368 SDValue DataOp = MSC->getValue();
6369 SDValue Mask = MSC->getMask();
6370 SDValue Index = MSC->getIndex();
6371 SDValue Scale = MSC->getScale();
6372 EVT WideMemVT = MSC->getMemoryVT();
6373
6374 if (OpNo == 1) {
6375 DataOp = GetWidenedVector(DataOp);
6376 unsigned NumElts = DataOp.getValueType().getVectorNumElements();
6377
6378 // Widen index.
6379 EVT IndexVT = Index.getValueType();
6380 EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
6381 IndexVT.getVectorElementType(), NumElts);
6382 Index = ModifyToType(Index, WideIndexVT);
6383
6384 // The mask should be widened as well.
6385 EVT MaskVT = Mask.getValueType();
6386 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
6387 MaskVT.getVectorElementType(), NumElts);
6388 Mask = ModifyToType(Mask, WideMaskVT, true);
6389
6390 // Widen the MemoryType
6391 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
6392 MSC->getMemoryVT().getScalarType(), NumElts);
6393 } else if (OpNo == 4) {
6394 // Just widen the index. It's allowed to have extra elements.
6395 Index = GetWidenedVector(Index);
6396 } else
6397 llvm_unreachable("Can't widen this operand of mscatter");
6398
6399 SDValue Ops[] = {MSC->getChain(), DataOp, Mask, MSC->getBasePtr(), Index,
6400 Scale};
6401 return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N),
6402 Ops, MSC->getMemOperand(), MSC->getIndexType(),
6403 MSC->isTruncatingStore());
6404 }
6405
WidenVecOp_VP_SCATTER(SDNode * N,unsigned OpNo)6406 SDValue DAGTypeLegalizer::WidenVecOp_VP_SCATTER(SDNode *N, unsigned OpNo) {
6407 VPScatterSDNode *VPSC = cast<VPScatterSDNode>(N);
6408 SDValue DataOp = VPSC->getValue();
6409 SDValue Mask = VPSC->getMask();
6410 SDValue Index = VPSC->getIndex();
6411 SDValue Scale = VPSC->getScale();
6412 EVT WideMemVT = VPSC->getMemoryVT();
6413
6414 if (OpNo == 1) {
6415 DataOp = GetWidenedVector(DataOp);
6416 Index = GetWidenedVector(Index);
6417 const auto WideEC = DataOp.getValueType().getVectorElementCount();
6418 Mask = GetWidenedMask(Mask, WideEC);
6419 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
6420 VPSC->getMemoryVT().getScalarType(), WideEC);
6421 } else if (OpNo == 3) {
6422 // Just widen the index. It's allowed to have extra elements.
6423 Index = GetWidenedVector(Index);
6424 } else
6425 llvm_unreachable("Can't widen this operand of VP_SCATTER");
6426
6427 SDValue Ops[] = {
6428 VPSC->getChain(), DataOp, VPSC->getBasePtr(), Index, Scale, Mask,
6429 VPSC->getVectorLength()};
6430 return DAG.getScatterVP(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N), Ops,
6431 VPSC->getMemOperand(), VPSC->getIndexType());
6432 }
6433
WidenVecOp_SETCC(SDNode * N)6434 SDValue DAGTypeLegalizer::WidenVecOp_SETCC(SDNode *N) {
6435 SDValue InOp0 = GetWidenedVector(N->getOperand(0));
6436 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
6437 SDLoc dl(N);
6438 EVT VT = N->getValueType(0);
6439
6440 // WARNING: In this code we widen the compare instruction with garbage.
6441 // This garbage may contain denormal floats which may be slow. Is this a real
6442 // concern ? Should we zero the unused lanes if this is a float compare ?
6443
6444 // Get a new SETCC node to compare the newly widened operands.
6445 // Only some of the compared elements are legal.
6446 EVT SVT = getSetCCResultType(InOp0.getValueType());
6447 // The result type is legal, if its vXi1, keep vXi1 for the new SETCC.
6448 if (VT.getScalarType() == MVT::i1)
6449 SVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
6450 SVT.getVectorElementCount());
6451
6452 SDValue WideSETCC = DAG.getNode(ISD::SETCC, SDLoc(N),
6453 SVT, InOp0, InOp1, N->getOperand(2));
6454
6455 // Extract the needed results from the result vector.
6456 EVT ResVT = EVT::getVectorVT(*DAG.getContext(),
6457 SVT.getVectorElementType(),
6458 VT.getVectorElementCount());
6459 SDValue CC = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, ResVT, WideSETCC,
6460 DAG.getVectorIdxConstant(0, dl));
6461
6462 EVT OpVT = N->getOperand(0).getValueType();
6463 ISD::NodeType ExtendCode =
6464 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
6465 return DAG.getNode(ExtendCode, dl, VT, CC);
6466 }
6467
WidenVecOp_STRICT_FSETCC(SDNode * N)6468 SDValue DAGTypeLegalizer::WidenVecOp_STRICT_FSETCC(SDNode *N) {
6469 SDValue Chain = N->getOperand(0);
6470 SDValue LHS = GetWidenedVector(N->getOperand(1));
6471 SDValue RHS = GetWidenedVector(N->getOperand(2));
6472 SDValue CC = N->getOperand(3);
6473 SDLoc dl(N);
6474
6475 EVT VT = N->getValueType(0);
6476 EVT EltVT = VT.getVectorElementType();
6477 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
6478 unsigned NumElts = VT.getVectorNumElements();
6479
6480 // Unroll into a build vector.
6481 SmallVector<SDValue, 8> Scalars(NumElts);
6482 SmallVector<SDValue, 8> Chains(NumElts);
6483
6484 for (unsigned i = 0; i != NumElts; ++i) {
6485 SDValue LHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, LHS,
6486 DAG.getVectorIdxConstant(i, dl));
6487 SDValue RHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, RHS,
6488 DAG.getVectorIdxConstant(i, dl));
6489
6490 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
6491 {Chain, LHSElem, RHSElem, CC});
6492 Chains[i] = Scalars[i].getValue(1);
6493 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
6494 DAG.getBoolConstant(true, dl, EltVT, VT),
6495 DAG.getBoolConstant(false, dl, EltVT, VT));
6496 }
6497
6498 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
6499 ReplaceValueWith(SDValue(N, 1), NewChain);
6500
6501 return DAG.getBuildVector(VT, dl, Scalars);
6502 }
6503
WidenVecOp_VECREDUCE(SDNode * N)6504 SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE(SDNode *N) {
6505 SDLoc dl(N);
6506 SDValue Op = GetWidenedVector(N->getOperand(0));
6507 EVT OrigVT = N->getOperand(0).getValueType();
6508 EVT WideVT = Op.getValueType();
6509 EVT ElemVT = OrigVT.getVectorElementType();
6510 SDNodeFlags Flags = N->getFlags();
6511
6512 unsigned Opc = N->getOpcode();
6513 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
6514 SDValue NeutralElem = DAG.getNeutralElement(BaseOpc, dl, ElemVT, Flags);
6515 assert(NeutralElem && "Neutral element must exist");
6516
6517 // Pad the vector with the neutral element.
6518 unsigned OrigElts = OrigVT.getVectorMinNumElements();
6519 unsigned WideElts = WideVT.getVectorMinNumElements();
6520
6521 if (WideVT.isScalableVector()) {
6522 unsigned GCD = std::gcd(OrigElts, WideElts);
6523 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
6524 ElementCount::getScalable(GCD));
6525 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
6526 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
6527 Op = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WideVT, Op, SplatNeutral,
6528 DAG.getVectorIdxConstant(Idx, dl));
6529 return DAG.getNode(Opc, dl, N->getValueType(0), Op, Flags);
6530 }
6531
6532 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
6533 Op = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, WideVT, Op, NeutralElem,
6534 DAG.getVectorIdxConstant(Idx, dl));
6535
6536 return DAG.getNode(Opc, dl, N->getValueType(0), Op, Flags);
6537 }
6538
WidenVecOp_VECREDUCE_SEQ(SDNode * N)6539 SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE_SEQ(SDNode *N) {
6540 SDLoc dl(N);
6541 SDValue AccOp = N->getOperand(0);
6542 SDValue VecOp = N->getOperand(1);
6543 SDValue Op = GetWidenedVector(VecOp);
6544
6545 EVT OrigVT = VecOp.getValueType();
6546 EVT WideVT = Op.getValueType();
6547 EVT ElemVT = OrigVT.getVectorElementType();
6548 SDNodeFlags Flags = N->getFlags();
6549
6550 unsigned Opc = N->getOpcode();
6551 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
6552 SDValue NeutralElem = DAG.getNeutralElement(BaseOpc, dl, ElemVT, Flags);
6553
6554 // Pad the vector with the neutral element.
6555 unsigned OrigElts = OrigVT.getVectorMinNumElements();
6556 unsigned WideElts = WideVT.getVectorMinNumElements();
6557
6558 if (WideVT.isScalableVector()) {
6559 unsigned GCD = std::gcd(OrigElts, WideElts);
6560 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
6561 ElementCount::getScalable(GCD));
6562 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
6563 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
6564 Op = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WideVT, Op, SplatNeutral,
6565 DAG.getVectorIdxConstant(Idx, dl));
6566 return DAG.getNode(Opc, dl, N->getValueType(0), AccOp, Op, Flags);
6567 }
6568
6569 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
6570 Op = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, WideVT, Op, NeutralElem,
6571 DAG.getVectorIdxConstant(Idx, dl));
6572
6573 return DAG.getNode(Opc, dl, N->getValueType(0), AccOp, Op, Flags);
6574 }
6575
WidenVecOp_VP_REDUCE(SDNode * N)6576 SDValue DAGTypeLegalizer::WidenVecOp_VP_REDUCE(SDNode *N) {
6577 assert(N->isVPOpcode() && "Expected VP opcode");
6578
6579 SDLoc dl(N);
6580 SDValue Op = GetWidenedVector(N->getOperand(1));
6581 SDValue Mask = GetWidenedMask(N->getOperand(2),
6582 Op.getValueType().getVectorElementCount());
6583
6584 return DAG.getNode(N->getOpcode(), dl, N->getValueType(0),
6585 {N->getOperand(0), Op, Mask, N->getOperand(3)},
6586 N->getFlags());
6587 }
6588
WidenVecOp_VSELECT(SDNode * N)6589 SDValue DAGTypeLegalizer::WidenVecOp_VSELECT(SDNode *N) {
6590 // This only gets called in the case that the left and right inputs and
6591 // result are of a legal odd vector type, and the condition is illegal i1 of
6592 // the same odd width that needs widening.
6593 EVT VT = N->getValueType(0);
6594 assert(VT.isVector() && !VT.isPow2VectorType() && isTypeLegal(VT));
6595
6596 SDValue Cond = GetWidenedVector(N->getOperand(0));
6597 SDValue LeftIn = DAG.WidenVector(N->getOperand(1), SDLoc(N));
6598 SDValue RightIn = DAG.WidenVector(N->getOperand(2), SDLoc(N));
6599 SDLoc DL(N);
6600
6601 SDValue Select = DAG.getNode(N->getOpcode(), DL, LeftIn.getValueType(), Cond,
6602 LeftIn, RightIn);
6603 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, Select,
6604 DAG.getVectorIdxConstant(0, DL));
6605 }
6606
6607 //===----------------------------------------------------------------------===//
6608 // Vector Widening Utilities
6609 //===----------------------------------------------------------------------===//
6610
6611 // Utility function to find the type to chop up a widen vector for load/store
6612 // TLI: Target lowering used to determine legal types.
6613 // Width: Width left need to load/store.
6614 // WidenVT: The widen vector type to load to/store from
6615 // Align: If 0, don't allow use of a wider type
6616 // WidenEx: If Align is not 0, the amount additional we can load/store from.
6617
findMemType(SelectionDAG & DAG,const TargetLowering & TLI,unsigned Width,EVT WidenVT,unsigned Align=0,unsigned WidenEx=0)6618 static std::optional<EVT> findMemType(SelectionDAG &DAG,
6619 const TargetLowering &TLI, unsigned Width,
6620 EVT WidenVT, unsigned Align = 0,
6621 unsigned WidenEx = 0) {
6622 EVT WidenEltVT = WidenVT.getVectorElementType();
6623 const bool Scalable = WidenVT.isScalableVector();
6624 unsigned WidenWidth = WidenVT.getSizeInBits().getKnownMinValue();
6625 unsigned WidenEltWidth = WidenEltVT.getSizeInBits();
6626 unsigned AlignInBits = Align*8;
6627
6628 // If we have one element to load/store, return it.
6629 EVT RetVT = WidenEltVT;
6630 if (!Scalable && Width == WidenEltWidth)
6631 return RetVT;
6632
6633 // Don't bother looking for an integer type if the vector is scalable, skip
6634 // to vector types.
6635 if (!Scalable) {
6636 // See if there is larger legal integer than the element type to load/store.
6637 for (EVT MemVT : reverse(MVT::integer_valuetypes())) {
6638 unsigned MemVTWidth = MemVT.getSizeInBits();
6639 if (MemVT.getSizeInBits() <= WidenEltWidth)
6640 break;
6641 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
6642 if ((Action == TargetLowering::TypeLegal ||
6643 Action == TargetLowering::TypePromoteInteger) &&
6644 (WidenWidth % MemVTWidth) == 0 &&
6645 isPowerOf2_32(WidenWidth / MemVTWidth) &&
6646 (MemVTWidth <= Width ||
6647 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
6648 if (MemVTWidth == WidenWidth)
6649 return MemVT;
6650 RetVT = MemVT;
6651 break;
6652 }
6653 }
6654 }
6655
6656 // See if there is a larger vector type to load/store that has the same vector
6657 // element type and is evenly divisible with the WidenVT.
6658 for (EVT MemVT : reverse(MVT::vector_valuetypes())) {
6659 // Skip vector MVTs which don't match the scalable property of WidenVT.
6660 if (Scalable != MemVT.isScalableVector())
6661 continue;
6662 unsigned MemVTWidth = MemVT.getSizeInBits().getKnownMinValue();
6663 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
6664 if ((Action == TargetLowering::TypeLegal ||
6665 Action == TargetLowering::TypePromoteInteger) &&
6666 WidenEltVT == MemVT.getVectorElementType() &&
6667 (WidenWidth % MemVTWidth) == 0 &&
6668 isPowerOf2_32(WidenWidth / MemVTWidth) &&
6669 (MemVTWidth <= Width ||
6670 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
6671 if (RetVT.getFixedSizeInBits() < MemVTWidth || MemVT == WidenVT)
6672 return MemVT;
6673 }
6674 }
6675
6676 // Using element-wise loads and stores for widening operations is not
6677 // supported for scalable vectors
6678 if (Scalable)
6679 return std::nullopt;
6680
6681 return RetVT;
6682 }
6683
6684 // Builds a vector type from scalar loads
6685 // VecTy: Resulting Vector type
6686 // LDOps: Load operators to build a vector type
6687 // [Start,End) the list of loads to use.
BuildVectorFromScalar(SelectionDAG & DAG,EVT VecTy,SmallVectorImpl<SDValue> & LdOps,unsigned Start,unsigned End)6688 static SDValue BuildVectorFromScalar(SelectionDAG& DAG, EVT VecTy,
6689 SmallVectorImpl<SDValue> &LdOps,
6690 unsigned Start, unsigned End) {
6691 SDLoc dl(LdOps[Start]);
6692 EVT LdTy = LdOps[Start].getValueType();
6693 unsigned Width = VecTy.getSizeInBits();
6694 unsigned NumElts = Width / LdTy.getSizeInBits();
6695 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), LdTy, NumElts);
6696
6697 unsigned Idx = 1;
6698 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT,LdOps[Start]);
6699
6700 for (unsigned i = Start + 1; i != End; ++i) {
6701 EVT NewLdTy = LdOps[i].getValueType();
6702 if (NewLdTy != LdTy) {
6703 NumElts = Width / NewLdTy.getSizeInBits();
6704 NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewLdTy, NumElts);
6705 VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, VecOp);
6706 // Readjust position and vector position based on new load type.
6707 Idx = Idx * LdTy.getSizeInBits() / NewLdTy.getSizeInBits();
6708 LdTy = NewLdTy;
6709 }
6710 VecOp = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, NewVecVT, VecOp, LdOps[i],
6711 DAG.getVectorIdxConstant(Idx++, dl));
6712 }
6713 return DAG.getNode(ISD::BITCAST, dl, VecTy, VecOp);
6714 }
6715
GenWidenVectorLoads(SmallVectorImpl<SDValue> & LdChain,LoadSDNode * LD)6716 SDValue DAGTypeLegalizer::GenWidenVectorLoads(SmallVectorImpl<SDValue> &LdChain,
6717 LoadSDNode *LD) {
6718 // The strategy assumes that we can efficiently load power-of-two widths.
6719 // The routine chops the vector into the largest vector loads with the same
6720 // element type or scalar loads and then recombines it to the widen vector
6721 // type.
6722 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
6723 EVT LdVT = LD->getMemoryVT();
6724 SDLoc dl(LD);
6725 assert(LdVT.isVector() && WidenVT.isVector());
6726 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
6727 assert(LdVT.getVectorElementType() == WidenVT.getVectorElementType());
6728
6729 // Load information
6730 SDValue Chain = LD->getChain();
6731 SDValue BasePtr = LD->getBasePtr();
6732 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
6733 AAMDNodes AAInfo = LD->getAAInfo();
6734
6735 TypeSize LdWidth = LdVT.getSizeInBits();
6736 TypeSize WidenWidth = WidenVT.getSizeInBits();
6737 TypeSize WidthDiff = WidenWidth - LdWidth;
6738 // Allow wider loads if they are sufficiently aligned to avoid memory faults
6739 // and if the original load is simple.
6740 unsigned LdAlign =
6741 (!LD->isSimple() || LdVT.isScalableVector()) ? 0 : LD->getAlign().value();
6742
6743 // Find the vector type that can load from.
6744 std::optional<EVT> FirstVT =
6745 findMemType(DAG, TLI, LdWidth.getKnownMinValue(), WidenVT, LdAlign,
6746 WidthDiff.getKnownMinValue());
6747
6748 if (!FirstVT)
6749 return SDValue();
6750
6751 SmallVector<EVT, 8> MemVTs;
6752 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
6753
6754 // Unless we're able to load in one instruction we must work out how to load
6755 // the remainder.
6756 if (!TypeSize::isKnownLE(LdWidth, FirstVTWidth)) {
6757 std::optional<EVT> NewVT = FirstVT;
6758 TypeSize RemainingWidth = LdWidth;
6759 TypeSize NewVTWidth = FirstVTWidth;
6760 do {
6761 RemainingWidth -= NewVTWidth;
6762 if (TypeSize::isKnownLT(RemainingWidth, NewVTWidth)) {
6763 // The current type we are using is too large. Find a better size.
6764 NewVT = findMemType(DAG, TLI, RemainingWidth.getKnownMinValue(),
6765 WidenVT, LdAlign, WidthDiff.getKnownMinValue());
6766 if (!NewVT)
6767 return SDValue();
6768 NewVTWidth = NewVT->getSizeInBits();
6769 }
6770 MemVTs.push_back(*NewVT);
6771 } while (TypeSize::isKnownGT(RemainingWidth, NewVTWidth));
6772 }
6773
6774 SDValue LdOp = DAG.getLoad(*FirstVT, dl, Chain, BasePtr, LD->getPointerInfo(),
6775 LD->getOriginalAlign(), MMOFlags, AAInfo);
6776 LdChain.push_back(LdOp.getValue(1));
6777
6778 // Check if we can load the element with one instruction.
6779 if (MemVTs.empty()) {
6780 assert(TypeSize::isKnownLE(LdWidth, FirstVTWidth));
6781 if (!FirstVT->isVector()) {
6782 unsigned NumElts =
6783 WidenWidth.getFixedValue() / FirstVTWidth.getFixedValue();
6784 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), *FirstVT, NumElts);
6785 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT, LdOp);
6786 return DAG.getNode(ISD::BITCAST, dl, WidenVT, VecOp);
6787 }
6788 if (FirstVT == WidenVT)
6789 return LdOp;
6790
6791 // TODO: We don't currently have any tests that exercise this code path.
6792 assert(WidenWidth.getFixedValue() % FirstVTWidth.getFixedValue() == 0);
6793 unsigned NumConcat =
6794 WidenWidth.getFixedValue() / FirstVTWidth.getFixedValue();
6795 SmallVector<SDValue, 16> ConcatOps(NumConcat);
6796 SDValue UndefVal = DAG.getUNDEF(*FirstVT);
6797 ConcatOps[0] = LdOp;
6798 for (unsigned i = 1; i != NumConcat; ++i)
6799 ConcatOps[i] = UndefVal;
6800 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, ConcatOps);
6801 }
6802
6803 // Load vector by using multiple loads from largest vector to scalar.
6804 SmallVector<SDValue, 16> LdOps;
6805 LdOps.push_back(LdOp);
6806
6807 uint64_t ScaledOffset = 0;
6808 MachinePointerInfo MPI = LD->getPointerInfo();
6809
6810 // First incremement past the first load.
6811 IncrementPointer(cast<LoadSDNode>(LdOp), *FirstVT, MPI, BasePtr,
6812 &ScaledOffset);
6813
6814 for (EVT MemVT : MemVTs) {
6815 Align NewAlign = ScaledOffset == 0
6816 ? LD->getOriginalAlign()
6817 : commonAlignment(LD->getAlign(), ScaledOffset);
6818 SDValue L =
6819 DAG.getLoad(MemVT, dl, Chain, BasePtr, MPI, NewAlign, MMOFlags, AAInfo);
6820
6821 LdOps.push_back(L);
6822 LdChain.push_back(L.getValue(1));
6823 IncrementPointer(cast<LoadSDNode>(L), MemVT, MPI, BasePtr, &ScaledOffset);
6824 }
6825
6826 // Build the vector from the load operations.
6827 unsigned End = LdOps.size();
6828 if (!LdOps[0].getValueType().isVector())
6829 // All the loads are scalar loads.
6830 return BuildVectorFromScalar(DAG, WidenVT, LdOps, 0, End);
6831
6832 // If the load contains vectors, build the vector using concat vector.
6833 // All of the vectors used to load are power-of-2, and the scalar loads can be
6834 // combined to make a power-of-2 vector.
6835 SmallVector<SDValue, 16> ConcatOps(End);
6836 int i = End - 1;
6837 int Idx = End;
6838 EVT LdTy = LdOps[i].getValueType();
6839 // First, combine the scalar loads to a vector.
6840 if (!LdTy.isVector()) {
6841 for (--i; i >= 0; --i) {
6842 LdTy = LdOps[i].getValueType();
6843 if (LdTy.isVector())
6844 break;
6845 }
6846 ConcatOps[--Idx] = BuildVectorFromScalar(DAG, LdTy, LdOps, i + 1, End);
6847 }
6848
6849 ConcatOps[--Idx] = LdOps[i];
6850 for (--i; i >= 0; --i) {
6851 EVT NewLdTy = LdOps[i].getValueType();
6852 if (NewLdTy != LdTy) {
6853 // Create a larger vector.
6854 TypeSize LdTySize = LdTy.getSizeInBits();
6855 TypeSize NewLdTySize = NewLdTy.getSizeInBits();
6856 assert(NewLdTySize.isScalable() == LdTySize.isScalable() &&
6857 NewLdTySize.isKnownMultipleOf(LdTySize.getKnownMinValue()));
6858 unsigned NumOps =
6859 NewLdTySize.getKnownMinValue() / LdTySize.getKnownMinValue();
6860 SmallVector<SDValue, 16> WidenOps(NumOps);
6861 unsigned j = 0;
6862 for (; j != End-Idx; ++j)
6863 WidenOps[j] = ConcatOps[Idx+j];
6864 for (; j != NumOps; ++j)
6865 WidenOps[j] = DAG.getUNDEF(LdTy);
6866
6867 ConcatOps[End-1] = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewLdTy,
6868 WidenOps);
6869 Idx = End - 1;
6870 LdTy = NewLdTy;
6871 }
6872 ConcatOps[--Idx] = LdOps[i];
6873 }
6874
6875 if (WidenWidth == LdTy.getSizeInBits() * (End - Idx))
6876 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
6877 ArrayRef(&ConcatOps[Idx], End - Idx));
6878
6879 // We need to fill the rest with undefs to build the vector.
6880 unsigned NumOps =
6881 WidenWidth.getKnownMinValue() / LdTy.getSizeInBits().getKnownMinValue();
6882 SmallVector<SDValue, 16> WidenOps(NumOps);
6883 SDValue UndefVal = DAG.getUNDEF(LdTy);
6884 {
6885 unsigned i = 0;
6886 for (; i != End-Idx; ++i)
6887 WidenOps[i] = ConcatOps[Idx+i];
6888 for (; i != NumOps; ++i)
6889 WidenOps[i] = UndefVal;
6890 }
6891 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, WidenOps);
6892 }
6893
6894 SDValue
GenWidenVectorExtLoads(SmallVectorImpl<SDValue> & LdChain,LoadSDNode * LD,ISD::LoadExtType ExtType)6895 DAGTypeLegalizer::GenWidenVectorExtLoads(SmallVectorImpl<SDValue> &LdChain,
6896 LoadSDNode *LD,
6897 ISD::LoadExtType ExtType) {
6898 // For extension loads, it may not be more efficient to chop up the vector
6899 // and then extend it. Instead, we unroll the load and build a new vector.
6900 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
6901 EVT LdVT = LD->getMemoryVT();
6902 SDLoc dl(LD);
6903 assert(LdVT.isVector() && WidenVT.isVector());
6904 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
6905
6906 // Load information
6907 SDValue Chain = LD->getChain();
6908 SDValue BasePtr = LD->getBasePtr();
6909 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
6910 AAMDNodes AAInfo = LD->getAAInfo();
6911
6912 if (LdVT.isScalableVector())
6913 report_fatal_error("Generating widen scalable extending vector loads is "
6914 "not yet supported");
6915
6916 EVT EltVT = WidenVT.getVectorElementType();
6917 EVT LdEltVT = LdVT.getVectorElementType();
6918 unsigned NumElts = LdVT.getVectorNumElements();
6919
6920 // Load each element and widen.
6921 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6922 SmallVector<SDValue, 16> Ops(WidenNumElts);
6923 unsigned Increment = LdEltVT.getSizeInBits() / 8;
6924 Ops[0] =
6925 DAG.getExtLoad(ExtType, dl, EltVT, Chain, BasePtr, LD->getPointerInfo(),
6926 LdEltVT, LD->getOriginalAlign(), MMOFlags, AAInfo);
6927 LdChain.push_back(Ops[0].getValue(1));
6928 unsigned i = 0, Offset = Increment;
6929 for (i=1; i < NumElts; ++i, Offset += Increment) {
6930 SDValue NewBasePtr =
6931 DAG.getObjectPtrOffset(dl, BasePtr, TypeSize::Fixed(Offset));
6932 Ops[i] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, NewBasePtr,
6933 LD->getPointerInfo().getWithOffset(Offset), LdEltVT,
6934 LD->getOriginalAlign(), MMOFlags, AAInfo);
6935 LdChain.push_back(Ops[i].getValue(1));
6936 }
6937
6938 // Fill the rest with undefs.
6939 SDValue UndefVal = DAG.getUNDEF(EltVT);
6940 for (; i != WidenNumElts; ++i)
6941 Ops[i] = UndefVal;
6942
6943 return DAG.getBuildVector(WidenVT, dl, Ops);
6944 }
6945
GenWidenVectorStores(SmallVectorImpl<SDValue> & StChain,StoreSDNode * ST)6946 bool DAGTypeLegalizer::GenWidenVectorStores(SmallVectorImpl<SDValue> &StChain,
6947 StoreSDNode *ST) {
6948 // The strategy assumes that we can efficiently store power-of-two widths.
6949 // The routine chops the vector into the largest vector stores with the same
6950 // element type or scalar stores.
6951 SDValue Chain = ST->getChain();
6952 SDValue BasePtr = ST->getBasePtr();
6953 MachineMemOperand::Flags MMOFlags = ST->getMemOperand()->getFlags();
6954 AAMDNodes AAInfo = ST->getAAInfo();
6955 SDValue ValOp = GetWidenedVector(ST->getValue());
6956 SDLoc dl(ST);
6957
6958 EVT StVT = ST->getMemoryVT();
6959 TypeSize StWidth = StVT.getSizeInBits();
6960 EVT ValVT = ValOp.getValueType();
6961 TypeSize ValWidth = ValVT.getSizeInBits();
6962 EVT ValEltVT = ValVT.getVectorElementType();
6963 unsigned ValEltWidth = ValEltVT.getFixedSizeInBits();
6964 assert(StVT.getVectorElementType() == ValEltVT);
6965 assert(StVT.isScalableVector() == ValVT.isScalableVector() &&
6966 "Mismatch between store and value types");
6967
6968 int Idx = 0; // current index to store
6969
6970 MachinePointerInfo MPI = ST->getPointerInfo();
6971 uint64_t ScaledOffset = 0;
6972
6973 // A breakdown of how to widen this vector store. Each element of the vector
6974 // is a memory VT combined with the number of times it is to be stored to,
6975 // e,g., v5i32 -> {{v2i32,2},{i32,1}}
6976 SmallVector<std::pair<EVT, unsigned>, 4> MemVTs;
6977
6978 while (StWidth.isNonZero()) {
6979 // Find the largest vector type we can store with.
6980 std::optional<EVT> NewVT =
6981 findMemType(DAG, TLI, StWidth.getKnownMinValue(), ValVT);
6982 if (!NewVT)
6983 return false;
6984 MemVTs.push_back({*NewVT, 0});
6985 TypeSize NewVTWidth = NewVT->getSizeInBits();
6986
6987 do {
6988 StWidth -= NewVTWidth;
6989 MemVTs.back().second++;
6990 } while (StWidth.isNonZero() && TypeSize::isKnownGE(StWidth, NewVTWidth));
6991 }
6992
6993 for (const auto &Pair : MemVTs) {
6994 EVT NewVT = Pair.first;
6995 unsigned Count = Pair.second;
6996 TypeSize NewVTWidth = NewVT.getSizeInBits();
6997
6998 if (NewVT.isVector()) {
6999 unsigned NumVTElts = NewVT.getVectorMinNumElements();
7000 do {
7001 Align NewAlign = ScaledOffset == 0
7002 ? ST->getOriginalAlign()
7003 : commonAlignment(ST->getAlign(), ScaledOffset);
7004 SDValue EOp = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, NewVT, ValOp,
7005 DAG.getVectorIdxConstant(Idx, dl));
7006 SDValue PartStore = DAG.getStore(Chain, dl, EOp, BasePtr, MPI, NewAlign,
7007 MMOFlags, AAInfo);
7008 StChain.push_back(PartStore);
7009
7010 Idx += NumVTElts;
7011 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr,
7012 &ScaledOffset);
7013 } while (--Count);
7014 } else {
7015 // Cast the vector to the scalar type we can store.
7016 unsigned NumElts = ValWidth.getFixedValue() / NewVTWidth.getFixedValue();
7017 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewVT, NumElts);
7018 SDValue VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, ValOp);
7019 // Readjust index position based on new vector type.
7020 Idx = Idx * ValEltWidth / NewVTWidth.getFixedValue();
7021 do {
7022 SDValue EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NewVT, VecOp,
7023 DAG.getVectorIdxConstant(Idx++, dl));
7024 SDValue PartStore =
7025 DAG.getStore(Chain, dl, EOp, BasePtr, MPI, ST->getOriginalAlign(),
7026 MMOFlags, AAInfo);
7027 StChain.push_back(PartStore);
7028
7029 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr);
7030 } while (--Count);
7031 // Restore index back to be relative to the original widen element type.
7032 Idx = Idx * NewVTWidth.getFixedValue() / ValEltWidth;
7033 }
7034 }
7035
7036 return true;
7037 }
7038
7039 /// Modifies a vector input (widen or narrows) to a vector of NVT. The
7040 /// input vector must have the same element type as NVT.
7041 /// FillWithZeroes specifies that the vector should be widened with zeroes.
ModifyToType(SDValue InOp,EVT NVT,bool FillWithZeroes)7042 SDValue DAGTypeLegalizer::ModifyToType(SDValue InOp, EVT NVT,
7043 bool FillWithZeroes) {
7044 // Note that InOp might have been widened so it might already have
7045 // the right width or it might need be narrowed.
7046 EVT InVT = InOp.getValueType();
7047 assert(InVT.getVectorElementType() == NVT.getVectorElementType() &&
7048 "input and widen element type must match");
7049 assert(InVT.isScalableVector() == NVT.isScalableVector() &&
7050 "cannot modify scalable vectors in this way");
7051 SDLoc dl(InOp);
7052
7053 // Check if InOp already has the right width.
7054 if (InVT == NVT)
7055 return InOp;
7056
7057 ElementCount InEC = InVT.getVectorElementCount();
7058 ElementCount WidenEC = NVT.getVectorElementCount();
7059 if (WidenEC.hasKnownScalarFactor(InEC)) {
7060 unsigned NumConcat = WidenEC.getKnownScalarFactor(InEC);
7061 SmallVector<SDValue, 16> Ops(NumConcat);
7062 SDValue FillVal = FillWithZeroes ? DAG.getConstant(0, dl, InVT) :
7063 DAG.getUNDEF(InVT);
7064 Ops[0] = InOp;
7065 for (unsigned i = 1; i != NumConcat; ++i)
7066 Ops[i] = FillVal;
7067
7068 return DAG.getNode(ISD::CONCAT_VECTORS, dl, NVT, Ops);
7069 }
7070
7071 if (InEC.hasKnownScalarFactor(WidenEC))
7072 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, NVT, InOp,
7073 DAG.getVectorIdxConstant(0, dl));
7074
7075 assert(!InVT.isScalableVector() && !NVT.isScalableVector() &&
7076 "Scalable vectors should have been handled already.");
7077
7078 unsigned InNumElts = InEC.getFixedValue();
7079 unsigned WidenNumElts = WidenEC.getFixedValue();
7080
7081 // Fall back to extract and build (+ mask, if padding with zeros).
7082 SmallVector<SDValue, 16> Ops(WidenNumElts);
7083 EVT EltVT = NVT.getVectorElementType();
7084 unsigned MinNumElts = std::min(WidenNumElts, InNumElts);
7085 unsigned Idx;
7086 for (Idx = 0; Idx < MinNumElts; ++Idx)
7087 Ops[Idx] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp,
7088 DAG.getVectorIdxConstant(Idx, dl));
7089
7090 SDValue UndefVal = DAG.getUNDEF(EltVT);
7091 for (; Idx < WidenNumElts; ++Idx)
7092 Ops[Idx] = UndefVal;
7093
7094 SDValue Widened = DAG.getBuildVector(NVT, dl, Ops);
7095 if (!FillWithZeroes)
7096 return Widened;
7097
7098 assert(NVT.isInteger() &&
7099 "We expect to never want to FillWithZeroes for non-integral types.");
7100
7101 SmallVector<SDValue, 16> MaskOps;
7102 MaskOps.append(MinNumElts, DAG.getAllOnesConstant(dl, EltVT));
7103 MaskOps.append(WidenNumElts - MinNumElts, DAG.getConstant(0, dl, EltVT));
7104
7105 return DAG.getNode(ISD::AND, dl, NVT, Widened,
7106 DAG.getBuildVector(NVT, dl, MaskOps));
7107 }
7108