LLVM 22.0.0git
LegalizeVectorOps.cpp
Go to the documentation of this file.
1//===- LegalizeVectorOps.cpp - Implement SelectionDAG::LegalizeVectors ----===//
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 implements the SelectionDAG::LegalizeVectors method.
10//
11// The vector legalizer looks for vector operations which might need to be
12// scalarized and legalizes them. This is a separate step from Legalize because
13// scalarizing can introduce illegal types. For example, suppose we have an
14// ISD::SDIV of type v2i64 on x86-32. The type is legal (for example, addition
15// on a v2i64 is legal), but ISD::SDIV isn't legal, so we have to unroll the
16// operation, which introduces nodes with the illegal type i64 which must be
17// expanded. Similarly, suppose we have an ISD::SRA of type v16i8 on PowerPC;
18// the operation must be unrolled, which introduces nodes with the illegal
19// type i8 which must be promoted.
20//
21// This does not legalize vector manipulations like ISD::BUILD_VECTOR,
22// or operations that happen to take a vector which are custom-lowered;
23// the legalization for such operations never produces nodes
24// with illegal types, so it's okay to put off legalizing them until
25// SelectionDAG::Legalize runs.
26//
27//===----------------------------------------------------------------------===//
28
29#include "llvm/ADT/DenseMap.h"
39#include "llvm/IR/DataLayout.h"
42#include "llvm/Support/Debug.h"
44#include <cassert>
45#include <cstdint>
46#include <iterator>
47#include <utility>
48
49using namespace llvm;
50
51#define DEBUG_TYPE "legalizevectorops"
52
53namespace {
54
55class VectorLegalizer {
56 SelectionDAG& DAG;
57 const TargetLowering &TLI;
58 bool Changed = false; // Keep track of whether anything changed
59
60 /// For nodes that are of legal width, and that have more than one use, this
61 /// map indicates what regularized operand to use. This allows us to avoid
62 /// legalizing the same thing more than once.
64
65 /// Adds a node to the translation cache.
66 void AddLegalizedOperand(SDValue From, SDValue To) {
67 LegalizedNodes.insert(std::make_pair(From, To));
68 // If someone requests legalization of the new node, return itself.
69 if (From != To)
70 LegalizedNodes.insert(std::make_pair(To, To));
71 }
72
73 /// Legalizes the given node.
74 SDValue LegalizeOp(SDValue Op);
75
76 /// Assuming the node is legal, "legalize" the results.
77 SDValue TranslateLegalizeResults(SDValue Op, SDNode *Result);
78
79 /// Make sure Results are legal and update the translation cache.
80 SDValue RecursivelyLegalizeResults(SDValue Op,
82
83 /// Wrapper to interface LowerOperation with a vector of Results.
84 /// Returns false if the target wants to use default expansion. Otherwise
85 /// returns true. If return is true and the Results are empty, then the
86 /// target wants to keep the input node as is.
87 bool LowerOperationWrapper(SDNode *N, SmallVectorImpl<SDValue> &Results);
88
89 /// Implements unrolling a VSETCC.
90 SDValue UnrollVSETCC(SDNode *Node);
91
92 /// Implement expand-based legalization of vector operations.
93 ///
94 /// This is just a high-level routine to dispatch to specific code paths for
95 /// operations to legalize them.
97
98 /// Implements expansion for FP_TO_UINT; falls back to UnrollVectorOp if
99 /// FP_TO_SINT isn't legal.
100 void ExpandFP_TO_UINT(SDNode *Node, SmallVectorImpl<SDValue> &Results);
101
102 /// Implements expansion for UINT_TO_FLOAT; falls back to UnrollVectorOp if
103 /// SINT_TO_FLOAT and SHR on vectors isn't legal.
104 void ExpandUINT_TO_FLOAT(SDNode *Node, SmallVectorImpl<SDValue> &Results);
105
106 /// Implement expansion for SIGN_EXTEND_INREG using SRL and SRA.
107 SDValue ExpandSEXTINREG(SDNode *Node);
108
109 /// Implement expansion for ANY_EXTEND_VECTOR_INREG.
110 ///
111 /// Shuffles the low lanes of the operand into place and bitcasts to the proper
112 /// type. The contents of the bits in the extended part of each element are
113 /// undef.
114 SDValue ExpandANY_EXTEND_VECTOR_INREG(SDNode *Node);
115
116 /// Implement expansion for SIGN_EXTEND_VECTOR_INREG.
117 ///
118 /// Shuffles the low lanes of the operand into place, bitcasts to the proper
119 /// type, then shifts left and arithmetic shifts right to introduce a sign
120 /// extension.
121 SDValue ExpandSIGN_EXTEND_VECTOR_INREG(SDNode *Node);
122
123 /// Implement expansion for ZERO_EXTEND_VECTOR_INREG.
124 ///
125 /// Shuffles the low lanes of the operand into place and blends zeros into
126 /// the remaining lanes, finally bitcasting to the proper type.
127 SDValue ExpandZERO_EXTEND_VECTOR_INREG(SDNode *Node);
128
129 /// Expand bswap of vectors into a shuffle if legal.
130 SDValue ExpandBSWAP(SDNode *Node);
131
132 /// Implement vselect in terms of XOR, AND, OR when blend is not
133 /// supported by the target.
134 SDValue ExpandVSELECT(SDNode *Node);
135 SDValue ExpandVP_SELECT(SDNode *Node);
136 SDValue ExpandVP_MERGE(SDNode *Node);
137 SDValue ExpandVP_REM(SDNode *Node);
138 SDValue ExpandVP_FNEG(SDNode *Node);
139 SDValue ExpandVP_FABS(SDNode *Node);
140 SDValue ExpandVP_FCOPYSIGN(SDNode *Node);
141 SDValue ExpandLOOP_DEPENDENCE_MASK(SDNode *N);
142 SDValue ExpandSELECT(SDNode *Node);
143 std::pair<SDValue, SDValue> ExpandLoad(SDNode *N);
144 SDValue ExpandStore(SDNode *N);
145 SDValue ExpandFNEG(SDNode *Node);
146 SDValue ExpandFABS(SDNode *Node);
147 SDValue ExpandFCOPYSIGN(SDNode *Node);
148 void ExpandFSUB(SDNode *Node, SmallVectorImpl<SDValue> &Results);
149 void ExpandSETCC(SDNode *Node, SmallVectorImpl<SDValue> &Results);
150 SDValue ExpandBITREVERSE(SDNode *Node);
151 void ExpandUADDSUBO(SDNode *Node, SmallVectorImpl<SDValue> &Results);
152 void ExpandSADDSUBO(SDNode *Node, SmallVectorImpl<SDValue> &Results);
153 void ExpandMULO(SDNode *Node, SmallVectorImpl<SDValue> &Results);
154 void ExpandFixedPointDiv(SDNode *Node, SmallVectorImpl<SDValue> &Results);
155 void ExpandStrictFPOp(SDNode *Node, SmallVectorImpl<SDValue> &Results);
156 void ExpandREM(SDNode *Node, SmallVectorImpl<SDValue> &Results);
157
158 bool tryExpandVecMathCall(SDNode *Node, RTLIB::Libcall LC,
160 bool tryExpandVecMathCall(SDNode *Node, RTLIB::Libcall Call_F32,
161 RTLIB::Libcall Call_F64, RTLIB::Libcall Call_F80,
162 RTLIB::Libcall Call_F128,
163 RTLIB::Libcall Call_PPCF128,
165
166 void UnrollStrictFPOp(SDNode *Node, SmallVectorImpl<SDValue> &Results);
167
168 /// Implements vector promotion.
169 ///
170 /// This is essentially just bitcasting the operands to a different type and
171 /// bitcasting the result back to the original type.
173
174 /// Implements [SU]INT_TO_FP vector promotion.
175 ///
176 /// This is a [zs]ext of the input operand to a larger integer type.
177 void PromoteINT_TO_FP(SDNode *Node, SmallVectorImpl<SDValue> &Results);
178
179 /// Implements FP_TO_[SU]INT vector promotion of the result type.
180 ///
181 /// It is promoted to a larger integer type. The result is then
182 /// truncated back to the original type.
183 void PromoteFP_TO_INT(SDNode *Node, SmallVectorImpl<SDValue> &Results);
184
185 /// Implements vector setcc operation promotion.
186 ///
187 /// All vector operands are promoted to a vector type with larger element
188 /// type.
189 void PromoteSETCC(SDNode *Node, SmallVectorImpl<SDValue> &Results);
190
191 void PromoteSTRICT(SDNode *Node, SmallVectorImpl<SDValue> &Results);
192
193 /// Calculate the reduction using a type of higher precision and round the
194 /// result to match the original type. Setting NonArithmetic signifies the
195 /// rounding of the result does not affect its value.
196 void PromoteFloatVECREDUCE(SDNode *Node, SmallVectorImpl<SDValue> &Results,
197 bool NonArithmetic);
198
199public:
200 VectorLegalizer(SelectionDAG& dag) :
201 DAG(dag), TLI(dag.getTargetLoweringInfo()) {}
202
203 /// Begin legalizer the vector operations in the DAG.
204 bool Run();
205};
206
207} // end anonymous namespace
208
209bool VectorLegalizer::Run() {
210 // Before we start legalizing vector nodes, check if there are any vectors.
211 bool HasVectors = false;
213 E = std::prev(DAG.allnodes_end()); I != std::next(E); ++I) {
214 // Check if the values of the nodes contain vectors. We don't need to check
215 // the operands because we are going to check their values at some point.
216 HasVectors = llvm::any_of(I->values(), [](EVT T) { return T.isVector(); });
217
218 // If we found a vector node we can start the legalization.
219 if (HasVectors)
220 break;
221 }
222
223 // If this basic block has no vectors then no need to legalize vectors.
224 if (!HasVectors)
225 return false;
226
227 // The legalize process is inherently a bottom-up recursive process (users
228 // legalize their uses before themselves). Given infinite stack space, we
229 // could just start legalizing on the root and traverse the whole graph. In
230 // practice however, this causes us to run out of stack space on large basic
231 // blocks. To avoid this problem, compute an ordering of the nodes where each
232 // node is only legalized after all of its operands are legalized.
235 E = std::prev(DAG.allnodes_end()); I != std::next(E); ++I)
236 LegalizeOp(SDValue(&*I, 0));
237
238 // Finally, it's possible the root changed. Get the new root.
239 SDValue OldRoot = DAG.getRoot();
240 assert(LegalizedNodes.count(OldRoot) && "Root didn't get legalized?");
241 DAG.setRoot(LegalizedNodes[OldRoot]);
242
243 LegalizedNodes.clear();
244
245 // Remove dead nodes now.
246 DAG.RemoveDeadNodes();
247
248 return Changed;
249}
250
251SDValue VectorLegalizer::TranslateLegalizeResults(SDValue Op, SDNode *Result) {
252 assert(Op->getNumValues() == Result->getNumValues() &&
253 "Unexpected number of results");
254 // Generic legalization: just pass the operand through.
255 for (unsigned i = 0, e = Op->getNumValues(); i != e; ++i)
256 AddLegalizedOperand(Op.getValue(i), SDValue(Result, i));
257 return SDValue(Result, Op.getResNo());
258}
259
261VectorLegalizer::RecursivelyLegalizeResults(SDValue Op,
263 assert(Results.size() == Op->getNumValues() &&
264 "Unexpected number of results");
265 // Make sure that the generated code is itself legal.
266 for (unsigned i = 0, e = Results.size(); i != e; ++i) {
267 Results[i] = LegalizeOp(Results[i]);
268 AddLegalizedOperand(Op.getValue(i), Results[i]);
269 }
270
271 return Results[Op.getResNo()];
272}
273
274SDValue VectorLegalizer::LegalizeOp(SDValue Op) {
275 // Note that LegalizeOp may be reentered even from single-use nodes, which
276 // means that we always must cache transformed nodes.
277 DenseMap<SDValue, SDValue>::iterator I = LegalizedNodes.find(Op);
278 if (I != LegalizedNodes.end()) return I->second;
279
280 // Legalize the operands
282 for (const SDValue &Oper : Op->op_values())
283 Ops.push_back(LegalizeOp(Oper));
284
285 SDNode *Node = DAG.UpdateNodeOperands(Op.getNode(), Ops);
286
287 bool HasVectorValueOrOp =
288 llvm::any_of(Node->values(), [](EVT T) { return T.isVector(); }) ||
289 llvm::any_of(Node->op_values(),
290 [](SDValue O) { return O.getValueType().isVector(); });
291 if (!HasVectorValueOrOp)
292 return TranslateLegalizeResults(Op, Node);
293
294 TargetLowering::LegalizeAction Action = TargetLowering::Legal;
295 EVT ValVT;
296 switch (Op.getOpcode()) {
297 default:
298 return TranslateLegalizeResults(Op, Node);
299 case ISD::LOAD: {
300 LoadSDNode *LD = cast<LoadSDNode>(Node);
301 ISD::LoadExtType ExtType = LD->getExtensionType();
302 EVT LoadedVT = LD->getMemoryVT();
303 if (LoadedVT.isVector() && ExtType != ISD::NON_EXTLOAD)
304 Action = TLI.getLoadExtAction(ExtType, LD->getValueType(0), LoadedVT);
305 break;
306 }
307 case ISD::STORE: {
308 StoreSDNode *ST = cast<StoreSDNode>(Node);
309 EVT StVT = ST->getMemoryVT();
310 MVT ValVT = ST->getValue().getSimpleValueType();
311 if (StVT.isVector() && ST->isTruncatingStore())
312 Action = TLI.getTruncStoreAction(ValVT, StVT);
313 break;
314 }
316 Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
317 // This operation lies about being legal: when it claims to be legal,
318 // it should actually be expanded.
319 if (Action == TargetLowering::Legal)
320 Action = TargetLowering::Expand;
321 break;
322#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
323 case ISD::STRICT_##DAGN:
324#include "llvm/IR/ConstrainedOps.def"
325 ValVT = Node->getValueType(0);
326 if (Op.getOpcode() == ISD::STRICT_SINT_TO_FP ||
327 Op.getOpcode() == ISD::STRICT_UINT_TO_FP)
328 ValVT = Node->getOperand(1).getValueType();
329 if (Op.getOpcode() == ISD::STRICT_FSETCC ||
330 Op.getOpcode() == ISD::STRICT_FSETCCS) {
331 MVT OpVT = Node->getOperand(1).getSimpleValueType();
332 ISD::CondCode CCCode = cast<CondCodeSDNode>(Node->getOperand(3))->get();
333 Action = TLI.getCondCodeAction(CCCode, OpVT);
334 if (Action == TargetLowering::Legal)
335 Action = TLI.getOperationAction(Node->getOpcode(), OpVT);
336 } else {
337 Action = TLI.getOperationAction(Node->getOpcode(), ValVT);
338 }
339 // If we're asked to expand a strict vector floating-point operation,
340 // by default we're going to simply unroll it. That is usually the
341 // best approach, except in the case where the resulting strict (scalar)
342 // operations would themselves use the fallback mutation to non-strict.
343 // In that specific case, just do the fallback on the vector op.
344 if (Action == TargetLowering::Expand && !TLI.isStrictFPEnabled() &&
345 TLI.getStrictFPOperationAction(Node->getOpcode(), ValVT) ==
346 TargetLowering::Legal) {
347 EVT EltVT = ValVT.getVectorElementType();
348 if (TLI.getOperationAction(Node->getOpcode(), EltVT)
349 == TargetLowering::Expand &&
350 TLI.getStrictFPOperationAction(Node->getOpcode(), EltVT)
351 == TargetLowering::Legal)
352 Action = TargetLowering::Legal;
353 }
354 break;
355 case ISD::ADD:
356 case ISD::SUB:
357 case ISD::MUL:
358 case ISD::MULHS:
359 case ISD::MULHU:
360 case ISD::SDIV:
361 case ISD::UDIV:
362 case ISD::SREM:
363 case ISD::UREM:
364 case ISD::SDIVREM:
365 case ISD::UDIVREM:
366 case ISD::FADD:
367 case ISD::FSUB:
368 case ISD::FMUL:
369 case ISD::FDIV:
370 case ISD::FREM:
371 case ISD::AND:
372 case ISD::OR:
373 case ISD::XOR:
374 case ISD::SHL:
375 case ISD::SRA:
376 case ISD::SRL:
377 case ISD::FSHL:
378 case ISD::FSHR:
379 case ISD::ROTL:
380 case ISD::ROTR:
381 case ISD::ABS:
382 case ISD::ABDS:
383 case ISD::ABDU:
384 case ISD::AVGCEILS:
385 case ISD::AVGCEILU:
386 case ISD::AVGFLOORS:
387 case ISD::AVGFLOORU:
388 case ISD::BSWAP:
389 case ISD::BITREVERSE:
390 case ISD::CTLZ:
391 case ISD::CTTZ:
394 case ISD::CTPOP:
395 case ISD::SELECT:
396 case ISD::VSELECT:
397 case ISD::SELECT_CC:
398 case ISD::ZERO_EXTEND:
399 case ISD::ANY_EXTEND:
400 case ISD::TRUNCATE:
401 case ISD::SIGN_EXTEND:
402 case ISD::FP_TO_SINT:
403 case ISD::FP_TO_UINT:
404 case ISD::FNEG:
405 case ISD::FABS:
406 case ISD::FMINNUM:
407 case ISD::FMAXNUM:
408 case ISD::FMINNUM_IEEE:
409 case ISD::FMAXNUM_IEEE:
410 case ISD::FMINIMUM:
411 case ISD::FMAXIMUM:
412 case ISD::FMINIMUMNUM:
413 case ISD::FMAXIMUMNUM:
414 case ISD::FCOPYSIGN:
415 case ISD::FSQRT:
416 case ISD::FSIN:
417 case ISD::FCOS:
418 case ISD::FTAN:
419 case ISD::FASIN:
420 case ISD::FACOS:
421 case ISD::FATAN:
422 case ISD::FATAN2:
423 case ISD::FSINH:
424 case ISD::FCOSH:
425 case ISD::FTANH:
426 case ISD::FLDEXP:
427 case ISD::FPOWI:
428 case ISD::FPOW:
429 case ISD::FLOG:
430 case ISD::FLOG2:
431 case ISD::FLOG10:
432 case ISD::FEXP:
433 case ISD::FEXP2:
434 case ISD::FEXP10:
435 case ISD::FCEIL:
436 case ISD::FTRUNC:
437 case ISD::FRINT:
438 case ISD::FNEARBYINT:
439 case ISD::FROUND:
440 case ISD::FROUNDEVEN:
441 case ISD::FFLOOR:
442 case ISD::FP_ROUND:
443 case ISD::FP_EXTEND:
445 case ISD::FMA:
450 case ISD::SMIN:
451 case ISD::SMAX:
452 case ISD::UMIN:
453 case ISD::UMAX:
454 case ISD::SMUL_LOHI:
455 case ISD::UMUL_LOHI:
456 case ISD::SADDO:
457 case ISD::UADDO:
458 case ISD::SSUBO:
459 case ISD::USUBO:
460 case ISD::SMULO:
461 case ISD::UMULO:
463 case ISD::FFREXP:
464 case ISD::FMODF:
465 case ISD::FSINCOS:
466 case ISD::FSINCOSPI:
467 case ISD::SADDSAT:
468 case ISD::UADDSAT:
469 case ISD::SSUBSAT:
470 case ISD::USUBSAT:
471 case ISD::SSHLSAT:
472 case ISD::USHLSAT:
475 case ISD::MGATHER:
477 case ISD::SCMP:
478 case ISD::UCMP:
481 Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
482 break;
483 case ISD::SMULFIX:
484 case ISD::SMULFIXSAT:
485 case ISD::UMULFIX:
486 case ISD::UMULFIXSAT:
487 case ISD::SDIVFIX:
488 case ISD::SDIVFIXSAT:
489 case ISD::UDIVFIX:
490 case ISD::UDIVFIXSAT: {
491 unsigned Scale = Node->getConstantOperandVal(2);
492 Action = TLI.getFixedPointOperationAction(Node->getOpcode(),
493 Node->getValueType(0), Scale);
494 break;
495 }
496 case ISD::LROUND:
497 case ISD::LLROUND:
498 case ISD::LRINT:
499 case ISD::LLRINT:
500 case ISD::SINT_TO_FP:
501 case ISD::UINT_TO_FP:
502 case ISD::VECREDUCE_ADD:
503 case ISD::VECREDUCE_MUL:
504 case ISD::VECREDUCE_AND:
505 case ISD::VECREDUCE_OR:
506 case ISD::VECREDUCE_XOR:
507 case ISD::VECREDUCE_SMAX:
508 case ISD::VECREDUCE_SMIN:
509 case ISD::VECREDUCE_UMAX:
510 case ISD::VECREDUCE_UMIN:
511 case ISD::VECREDUCE_FADD:
512 case ISD::VECREDUCE_FMAX:
513 case ISD::VECREDUCE_FMAXIMUM:
514 case ISD::VECREDUCE_FMIN:
515 case ISD::VECREDUCE_FMINIMUM:
516 case ISD::VECREDUCE_FMUL:
517 case ISD::VECTOR_FIND_LAST_ACTIVE:
518 Action = TLI.getOperationAction(Node->getOpcode(),
519 Node->getOperand(0).getValueType());
520 break;
521 case ISD::VECREDUCE_SEQ_FADD:
522 case ISD::VECREDUCE_SEQ_FMUL:
523 Action = TLI.getOperationAction(Node->getOpcode(),
524 Node->getOperand(1).getValueType());
525 break;
526 case ISD::SETCC: {
527 MVT OpVT = Node->getOperand(0).getSimpleValueType();
528 ISD::CondCode CCCode = cast<CondCodeSDNode>(Node->getOperand(2))->get();
529 Action = TLI.getCondCodeAction(CCCode, OpVT);
530 if (Action == TargetLowering::Legal)
531 Action = TLI.getOperationAction(Node->getOpcode(), OpVT);
532 break;
533 }
534 case ISD::PARTIAL_REDUCE_UMLA:
535 case ISD::PARTIAL_REDUCE_SMLA:
536 case ISD::PARTIAL_REDUCE_SUMLA:
537 Action =
538 TLI.getPartialReduceMLAAction(Op.getOpcode(), Node->getValueType(0),
539 Node->getOperand(1).getValueType());
540 break;
541
542#define BEGIN_REGISTER_VP_SDNODE(VPID, LEGALPOS, ...) \
543 case ISD::VPID: { \
544 EVT LegalizeVT = LEGALPOS < 0 ? Node->getValueType(-(1 + LEGALPOS)) \
545 : Node->getOperand(LEGALPOS).getValueType(); \
546 if (ISD::VPID == ISD::VP_SETCC) { \
547 ISD::CondCode CCCode = cast<CondCodeSDNode>(Node->getOperand(2))->get(); \
548 Action = TLI.getCondCodeAction(CCCode, LegalizeVT.getSimpleVT()); \
549 if (Action != TargetLowering::Legal) \
550 break; \
551 } \
552 /* Defer non-vector results to LegalizeDAG. */ \
553 if (!Node->getValueType(0).isVector() && \
554 Node->getValueType(0) != MVT::Other) { \
555 Action = TargetLowering::Legal; \
556 break; \
557 } \
558 Action = TLI.getOperationAction(Node->getOpcode(), LegalizeVT); \
559 } break;
560#include "llvm/IR/VPIntrinsics.def"
561 }
562
563 LLVM_DEBUG(dbgs() << "\nLegalizing vector op: "; Node->dump(&DAG));
564
565 SmallVector<SDValue, 8> ResultVals;
566 switch (Action) {
567 default: llvm_unreachable("This action is not supported yet!");
568 case TargetLowering::Promote:
569 assert((Op.getOpcode() != ISD::LOAD && Op.getOpcode() != ISD::STORE) &&
570 "This action is not supported yet!");
571 LLVM_DEBUG(dbgs() << "Promoting\n");
572 Promote(Node, ResultVals);
573 assert(!ResultVals.empty() && "No results for promotion?");
574 break;
575 case TargetLowering::Legal:
576 LLVM_DEBUG(dbgs() << "Legal node: nothing to do\n");
577 break;
578 case TargetLowering::Custom:
579 LLVM_DEBUG(dbgs() << "Trying custom legalization\n");
580 if (LowerOperationWrapper(Node, ResultVals))
581 break;
582 LLVM_DEBUG(dbgs() << "Could not custom legalize node\n");
583 [[fallthrough]];
584 case TargetLowering::Expand:
585 LLVM_DEBUG(dbgs() << "Expanding\n");
586 Expand(Node, ResultVals);
587 break;
588 }
589
590 if (ResultVals.empty())
591 return TranslateLegalizeResults(Op, Node);
592
593 Changed = true;
594 return RecursivelyLegalizeResults(Op, ResultVals);
595}
596
597// FIXME: This is very similar to TargetLowering::LowerOperationWrapper. Can we
598// merge them somehow?
599bool VectorLegalizer::LowerOperationWrapper(SDNode *Node,
600 SmallVectorImpl<SDValue> &Results) {
601 SDValue Res = TLI.LowerOperation(SDValue(Node, 0), DAG);
602
603 if (!Res.getNode())
604 return false;
605
606 if (Res == SDValue(Node, 0))
607 return true;
608
609 // If the original node has one result, take the return value from
610 // LowerOperation as is. It might not be result number 0.
611 if (Node->getNumValues() == 1) {
612 Results.push_back(Res);
613 return true;
614 }
615
616 // If the original node has multiple results, then the return node should
617 // have the same number of results.
618 assert((Node->getNumValues() == Res->getNumValues()) &&
619 "Lowering returned the wrong number of results!");
620
621 // Places new result values base on N result number.
622 for (unsigned I = 0, E = Node->getNumValues(); I != E; ++I)
623 Results.push_back(Res.getValue(I));
624
625 return true;
626}
627
628void VectorLegalizer::PromoteSETCC(SDNode *Node,
629 SmallVectorImpl<SDValue> &Results) {
630 MVT VecVT = Node->getOperand(0).getSimpleValueType();
631 MVT NewVecVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VecVT);
632
633 unsigned ExtOp = VecVT.isFloatingPoint() ? ISD::FP_EXTEND : ISD::ANY_EXTEND;
634
635 SDLoc DL(Node);
636 SmallVector<SDValue, 5> Operands(Node->getNumOperands());
637
638 Operands[0] = DAG.getNode(ExtOp, DL, NewVecVT, Node->getOperand(0));
639 Operands[1] = DAG.getNode(ExtOp, DL, NewVecVT, Node->getOperand(1));
640 Operands[2] = Node->getOperand(2);
641
642 if (Node->getOpcode() == ISD::VP_SETCC) {
643 Operands[3] = Node->getOperand(3); // mask
644 Operands[4] = Node->getOperand(4); // evl
645 }
646
647 SDValue Res = DAG.getNode(Node->getOpcode(), DL, Node->getSimpleValueType(0),
648 Operands, Node->getFlags());
649
650 Results.push_back(Res);
651}
652
653void VectorLegalizer::PromoteSTRICT(SDNode *Node,
654 SmallVectorImpl<SDValue> &Results) {
655 MVT VecVT = Node->getOperand(1).getSimpleValueType();
656 MVT NewVecVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VecVT);
657
658 assert(VecVT.isFloatingPoint());
659
660 SDLoc DL(Node);
661 SmallVector<SDValue, 5> Operands(Node->getNumOperands());
663
664 for (unsigned j = 1; j != Node->getNumOperands(); ++j)
665 if (Node->getOperand(j).getValueType().isVector() &&
666 !(ISD::isVPOpcode(Node->getOpcode()) &&
667 ISD::getVPMaskIdx(Node->getOpcode()) == j)) // Skip mask operand.
668 {
669 // promote the vector operand.
670 SDValue Ext =
671 DAG.getNode(ISD::STRICT_FP_EXTEND, DL, {NewVecVT, MVT::Other},
672 {Node->getOperand(0), Node->getOperand(j)});
673 Operands[j] = Ext.getValue(0);
674 Chains.push_back(Ext.getValue(1));
675 } else
676 Operands[j] = Node->getOperand(j); // Skip no vector operand.
677
678 SDVTList VTs = DAG.getVTList(NewVecVT, Node->getValueType(1));
679
680 Operands[0] = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
681
682 SDValue Res =
683 DAG.getNode(Node->getOpcode(), DL, VTs, Operands, Node->getFlags());
684
685 SDValue Round =
686 DAG.getNode(ISD::STRICT_FP_ROUND, DL, {VecVT, MVT::Other},
687 {Res.getValue(1), Res.getValue(0),
688 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true)});
689
690 Results.push_back(Round.getValue(0));
691 Results.push_back(Round.getValue(1));
692}
693
694void VectorLegalizer::PromoteFloatVECREDUCE(SDNode *Node,
695 SmallVectorImpl<SDValue> &Results,
696 bool NonArithmetic) {
697 MVT OpVT = Node->getOperand(0).getSimpleValueType();
698 assert(OpVT.isFloatingPoint() && "Expected floating point reduction!");
699 MVT NewOpVT = TLI.getTypeToPromoteTo(Node->getOpcode(), OpVT);
700
701 SDLoc DL(Node);
702 SDValue NewOp = DAG.getNode(ISD::FP_EXTEND, DL, NewOpVT, Node->getOperand(0));
703 SDValue Rdx =
704 DAG.getNode(Node->getOpcode(), DL, NewOpVT.getVectorElementType(), NewOp,
705 Node->getFlags());
706 SDValue Res =
707 DAG.getNode(ISD::FP_ROUND, DL, Node->getValueType(0), Rdx,
708 DAG.getIntPtrConstant(NonArithmetic, DL, /*isTarget=*/true));
709 Results.push_back(Res);
710}
711
712void VectorLegalizer::Promote(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
713 // For a few operations there is a specific concept for promotion based on
714 // the operand's type.
715 switch (Node->getOpcode()) {
716 case ISD::SINT_TO_FP:
717 case ISD::UINT_TO_FP:
720 // "Promote" the operation by extending the operand.
721 PromoteINT_TO_FP(Node, Results);
722 return;
723 case ISD::FP_TO_UINT:
724 case ISD::FP_TO_SINT:
727 // Promote the operation by extending the operand.
728 PromoteFP_TO_INT(Node, Results);
729 return;
730 case ISD::VP_SETCC:
731 case ISD::SETCC:
732 // Promote the operation by extending the operand.
733 PromoteSETCC(Node, Results);
734 return;
735 case ISD::STRICT_FADD:
736 case ISD::STRICT_FSUB:
737 case ISD::STRICT_FMUL:
738 case ISD::STRICT_FDIV:
740 case ISD::STRICT_FMA:
741 PromoteSTRICT(Node, Results);
742 return;
743 case ISD::VECREDUCE_FADD:
744 PromoteFloatVECREDUCE(Node, Results, /*NonArithmetic=*/false);
745 return;
746 case ISD::VECREDUCE_FMAX:
747 case ISD::VECREDUCE_FMAXIMUM:
748 case ISD::VECREDUCE_FMIN:
749 case ISD::VECREDUCE_FMINIMUM:
750 PromoteFloatVECREDUCE(Node, Results, /*NonArithmetic=*/true);
751 return;
752 case ISD::FP_ROUND:
753 case ISD::FP_EXTEND:
754 // These operations are used to do promotion so they can't be promoted
755 // themselves.
756 llvm_unreachable("Don't know how to promote this operation!");
757 case ISD::VP_FABS:
758 case ISD::VP_FCOPYSIGN:
759 case ISD::VP_FNEG:
760 // Promoting fabs, fneg, and fcopysign changes their semantics.
761 llvm_unreachable("These operations should not be promoted");
762 }
763
764 // There are currently two cases of vector promotion:
765 // 1) Bitcasting a vector of integers to a different type to a vector of the
766 // same overall length. For example, x86 promotes ISD::AND v2i32 to v1i64.
767 // 2) Extending a vector of floats to a vector of the same number of larger
768 // floats. For example, AArch64 promotes ISD::FADD on v4f16 to v4f32.
769 assert(Node->getNumValues() == 1 &&
770 "Can't promote a vector with multiple results!");
771 MVT VT = Node->getSimpleValueType(0);
772 MVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VT);
773 SDLoc dl(Node);
774 SmallVector<SDValue, 4> Operands(Node->getNumOperands());
775
776 for (unsigned j = 0; j != Node->getNumOperands(); ++j) {
777 // Do not promote the mask operand of a VP OP.
778 bool SkipPromote = ISD::isVPOpcode(Node->getOpcode()) &&
779 ISD::getVPMaskIdx(Node->getOpcode()) == j;
780 if (Node->getOperand(j).getValueType().isVector() && !SkipPromote)
781 if (Node->getOperand(j)
782 .getValueType()
783 .getVectorElementType()
784 .isFloatingPoint() &&
786 if (ISD::isVPOpcode(Node->getOpcode())) {
787 unsigned EVLIdx =
789 unsigned MaskIdx = *ISD::getVPMaskIdx(Node->getOpcode());
790 Operands[j] =
791 DAG.getNode(ISD::VP_FP_EXTEND, dl, NVT, Node->getOperand(j),
792 Node->getOperand(MaskIdx), Node->getOperand(EVLIdx));
793 } else {
794 Operands[j] =
795 DAG.getNode(ISD::FP_EXTEND, dl, NVT, Node->getOperand(j));
796 }
797 else
798 Operands[j] = DAG.getNode(ISD::BITCAST, dl, NVT, Node->getOperand(j));
799 else
800 Operands[j] = Node->getOperand(j);
801 }
802
803 SDValue Res =
804 DAG.getNode(Node->getOpcode(), dl, NVT, Operands, Node->getFlags());
805
806 if ((VT.isFloatingPoint() && NVT.isFloatingPoint()) ||
809 if (ISD::isVPOpcode(Node->getOpcode())) {
810 unsigned EVLIdx = *ISD::getVPExplicitVectorLengthIdx(Node->getOpcode());
811 unsigned MaskIdx = *ISD::getVPMaskIdx(Node->getOpcode());
812 Res = DAG.getNode(ISD::VP_FP_ROUND, dl, VT, Res,
813 Node->getOperand(MaskIdx), Node->getOperand(EVLIdx));
814 } else {
815 Res = DAG.getNode(ISD::FP_ROUND, dl, VT, Res,
816 DAG.getIntPtrConstant(0, dl, /*isTarget=*/true));
817 }
818 else
819 Res = DAG.getNode(ISD::BITCAST, dl, VT, Res);
820
821 Results.push_back(Res);
822}
823
824void VectorLegalizer::PromoteINT_TO_FP(SDNode *Node,
825 SmallVectorImpl<SDValue> &Results) {
826 // INT_TO_FP operations may require the input operand be promoted even
827 // when the type is otherwise legal.
828 bool IsStrict = Node->isStrictFPOpcode();
829 MVT VT = Node->getOperand(IsStrict ? 1 : 0).getSimpleValueType();
830 MVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VT);
832 "Vectors have different number of elements!");
833
834 SDLoc dl(Node);
835 SmallVector<SDValue, 4> Operands(Node->getNumOperands());
836
837 unsigned Opc = (Node->getOpcode() == ISD::UINT_TO_FP ||
838 Node->getOpcode() == ISD::STRICT_UINT_TO_FP)
841 for (unsigned j = 0; j != Node->getNumOperands(); ++j) {
842 if (Node->getOperand(j).getValueType().isVector())
843 Operands[j] = DAG.getNode(Opc, dl, NVT, Node->getOperand(j));
844 else
845 Operands[j] = Node->getOperand(j);
846 }
847
848 if (IsStrict) {
849 SDValue Res = DAG.getNode(Node->getOpcode(), dl,
850 {Node->getValueType(0), MVT::Other}, Operands);
851 Results.push_back(Res);
852 Results.push_back(Res.getValue(1));
853 return;
854 }
855
856 SDValue Res =
857 DAG.getNode(Node->getOpcode(), dl, Node->getValueType(0), Operands);
858 Results.push_back(Res);
859}
860
861// For FP_TO_INT we promote the result type to a vector type with wider
862// elements and then truncate the result. This is different from the default
863// PromoteVector which uses bitcast to promote thus assumning that the
864// promoted vector type has the same overall size.
865void VectorLegalizer::PromoteFP_TO_INT(SDNode *Node,
866 SmallVectorImpl<SDValue> &Results) {
867 MVT VT = Node->getSimpleValueType(0);
868 MVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VT);
869 bool IsStrict = Node->isStrictFPOpcode();
871 "Vectors have different number of elements!");
872
873 unsigned NewOpc = Node->getOpcode();
874 // Change FP_TO_UINT to FP_TO_SINT if possible.
875 // TODO: Should we only do this if FP_TO_UINT itself isn't legal?
876 if (NewOpc == ISD::FP_TO_UINT &&
878 NewOpc = ISD::FP_TO_SINT;
879
880 if (NewOpc == ISD::STRICT_FP_TO_UINT &&
882 NewOpc = ISD::STRICT_FP_TO_SINT;
883
884 SDLoc dl(Node);
885 SDValue Promoted, Chain;
886 if (IsStrict) {
887 Promoted = DAG.getNode(NewOpc, dl, {NVT, MVT::Other},
888 {Node->getOperand(0), Node->getOperand(1)});
889 Chain = Promoted.getValue(1);
890 } else
891 Promoted = DAG.getNode(NewOpc, dl, NVT, Node->getOperand(0));
892
893 // Assert that the converted value fits in the original type. If it doesn't
894 // (eg: because the value being converted is too big), then the result of the
895 // original operation was undefined anyway, so the assert is still correct.
896 if (Node->getOpcode() == ISD::FP_TO_UINT ||
897 Node->getOpcode() == ISD::STRICT_FP_TO_UINT)
898 NewOpc = ISD::AssertZext;
899 else
900 NewOpc = ISD::AssertSext;
901
902 Promoted = DAG.getNode(NewOpc, dl, NVT, Promoted,
903 DAG.getValueType(VT.getScalarType()));
904 Promoted = DAG.getNode(ISD::TRUNCATE, dl, VT, Promoted);
905 Results.push_back(Promoted);
906 if (IsStrict)
907 Results.push_back(Chain);
908}
909
910std::pair<SDValue, SDValue> VectorLegalizer::ExpandLoad(SDNode *N) {
911 LoadSDNode *LD = cast<LoadSDNode>(N);
912 return TLI.scalarizeVectorLoad(LD, DAG);
913}
914
915SDValue VectorLegalizer::ExpandStore(SDNode *N) {
916 StoreSDNode *ST = cast<StoreSDNode>(N);
917 SDValue TF = TLI.scalarizeVectorStore(ST, DAG);
918 return TF;
919}
920
921void VectorLegalizer::Expand(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
922 switch (Node->getOpcode()) {
923 case ISD::LOAD: {
924 std::pair<SDValue, SDValue> Tmp = ExpandLoad(Node);
925 Results.push_back(Tmp.first);
926 Results.push_back(Tmp.second);
927 return;
928 }
929 case ISD::STORE:
930 Results.push_back(ExpandStore(Node));
931 return;
933 for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i)
934 Results.push_back(Node->getOperand(i));
935 return;
937 if (SDValue Expanded = ExpandSEXTINREG(Node)) {
938 Results.push_back(Expanded);
939 return;
940 }
941 break;
943 Results.push_back(ExpandANY_EXTEND_VECTOR_INREG(Node));
944 return;
946 Results.push_back(ExpandSIGN_EXTEND_VECTOR_INREG(Node));
947 return;
949 Results.push_back(ExpandZERO_EXTEND_VECTOR_INREG(Node));
950 return;
951 case ISD::BSWAP:
952 if (SDValue Expanded = ExpandBSWAP(Node)) {
953 Results.push_back(Expanded);
954 return;
955 }
956 break;
957 case ISD::VP_BSWAP:
958 Results.push_back(TLI.expandVPBSWAP(Node, DAG));
959 return;
960 case ISD::VSELECT:
961 if (SDValue Expanded = ExpandVSELECT(Node)) {
962 Results.push_back(Expanded);
963 return;
964 }
965 break;
966 case ISD::VP_SELECT:
967 if (SDValue Expanded = ExpandVP_SELECT(Node)) {
968 Results.push_back(Expanded);
969 return;
970 }
971 break;
972 case ISD::VP_SREM:
973 case ISD::VP_UREM:
974 if (SDValue Expanded = ExpandVP_REM(Node)) {
975 Results.push_back(Expanded);
976 return;
977 }
978 break;
979 case ISD::VP_FNEG:
980 if (SDValue Expanded = ExpandVP_FNEG(Node)) {
981 Results.push_back(Expanded);
982 return;
983 }
984 break;
985 case ISD::VP_FABS:
986 if (SDValue Expanded = ExpandVP_FABS(Node)) {
987 Results.push_back(Expanded);
988 return;
989 }
990 break;
991 case ISD::VP_FCOPYSIGN:
992 if (SDValue Expanded = ExpandVP_FCOPYSIGN(Node)) {
993 Results.push_back(Expanded);
994 return;
995 }
996 break;
997 case ISD::SELECT:
998 if (SDValue Expanded = ExpandSELECT(Node)) {
999 Results.push_back(Expanded);
1000 return;
1001 }
1002 break;
1003 case ISD::SELECT_CC: {
1004 if (Node->getValueType(0).isScalableVector()) {
1005 EVT CondVT = TLI.getSetCCResultType(
1006 DAG.getDataLayout(), *DAG.getContext(), Node->getValueType(0));
1007 SDValue SetCC =
1008 DAG.getNode(ISD::SETCC, SDLoc(Node), CondVT, Node->getOperand(0),
1009 Node->getOperand(1), Node->getOperand(4));
1010 Results.push_back(DAG.getSelect(SDLoc(Node), Node->getValueType(0), SetCC,
1011 Node->getOperand(2),
1012 Node->getOperand(3)));
1013 return;
1014 }
1015 break;
1016 }
1017 case ISD::FP_TO_UINT:
1018 ExpandFP_TO_UINT(Node, Results);
1019 return;
1020 case ISD::UINT_TO_FP:
1021 ExpandUINT_TO_FLOAT(Node, Results);
1022 return;
1023 case ISD::FNEG:
1024 if (SDValue Expanded = ExpandFNEG(Node)) {
1025 Results.push_back(Expanded);
1026 return;
1027 }
1028 break;
1029 case ISD::FABS:
1030 if (SDValue Expanded = ExpandFABS(Node)) {
1031 Results.push_back(Expanded);
1032 return;
1033 }
1034 break;
1035 case ISD::FCOPYSIGN:
1036 if (SDValue Expanded = ExpandFCOPYSIGN(Node)) {
1037 Results.push_back(Expanded);
1038 return;
1039 }
1040 break;
1041 case ISD::FSUB:
1042 ExpandFSUB(Node, Results);
1043 return;
1044 case ISD::SETCC:
1045 case ISD::VP_SETCC:
1046 ExpandSETCC(Node, Results);
1047 return;
1048 case ISD::ABS:
1049 if (SDValue Expanded = TLI.expandABS(Node, DAG)) {
1050 Results.push_back(Expanded);
1051 return;
1052 }
1053 break;
1054 case ISD::ABDS:
1055 case ISD::ABDU:
1056 if (SDValue Expanded = TLI.expandABD(Node, DAG)) {
1057 Results.push_back(Expanded);
1058 return;
1059 }
1060 break;
1061 case ISD::AVGCEILS:
1062 case ISD::AVGCEILU:
1063 case ISD::AVGFLOORS:
1064 case ISD::AVGFLOORU:
1065 if (SDValue Expanded = TLI.expandAVG(Node, DAG)) {
1066 Results.push_back(Expanded);
1067 return;
1068 }
1069 break;
1070 case ISD::BITREVERSE:
1071 if (SDValue Expanded = ExpandBITREVERSE(Node)) {
1072 Results.push_back(Expanded);
1073 return;
1074 }
1075 break;
1076 case ISD::VP_BITREVERSE:
1077 if (SDValue Expanded = TLI.expandVPBITREVERSE(Node, DAG)) {
1078 Results.push_back(Expanded);
1079 return;
1080 }
1081 break;
1082 case ISD::CTPOP:
1083 if (SDValue Expanded = TLI.expandCTPOP(Node, DAG)) {
1084 Results.push_back(Expanded);
1085 return;
1086 }
1087 break;
1088 case ISD::VP_CTPOP:
1089 if (SDValue Expanded = TLI.expandVPCTPOP(Node, DAG)) {
1090 Results.push_back(Expanded);
1091 return;
1092 }
1093 break;
1094 case ISD::CTLZ:
1096 if (SDValue Expanded = TLI.expandCTLZ(Node, DAG)) {
1097 Results.push_back(Expanded);
1098 return;
1099 }
1100 break;
1101 case ISD::VP_CTLZ:
1102 case ISD::VP_CTLZ_ZERO_UNDEF:
1103 if (SDValue Expanded = TLI.expandVPCTLZ(Node, DAG)) {
1104 Results.push_back(Expanded);
1105 return;
1106 }
1107 break;
1108 case ISD::CTTZ:
1110 if (SDValue Expanded = TLI.expandCTTZ(Node, DAG)) {
1111 Results.push_back(Expanded);
1112 return;
1113 }
1114 break;
1115 case ISD::VP_CTTZ:
1116 case ISD::VP_CTTZ_ZERO_UNDEF:
1117 if (SDValue Expanded = TLI.expandVPCTTZ(Node, DAG)) {
1118 Results.push_back(Expanded);
1119 return;
1120 }
1121 break;
1122 case ISD::FSHL:
1123 case ISD::VP_FSHL:
1124 case ISD::FSHR:
1125 case ISD::VP_FSHR:
1126 if (SDValue Expanded = TLI.expandFunnelShift(Node, DAG)) {
1127 Results.push_back(Expanded);
1128 return;
1129 }
1130 break;
1131 case ISD::ROTL:
1132 case ISD::ROTR:
1133 if (SDValue Expanded = TLI.expandROT(Node, false /*AllowVectorOps*/, DAG)) {
1134 Results.push_back(Expanded);
1135 return;
1136 }
1137 break;
1138 case ISD::FMINNUM:
1139 case ISD::FMAXNUM:
1140 if (SDValue Expanded = TLI.expandFMINNUM_FMAXNUM(Node, DAG)) {
1141 Results.push_back(Expanded);
1142 return;
1143 }
1144 break;
1145 case ISD::FMINIMUM:
1146 case ISD::FMAXIMUM:
1147 Results.push_back(TLI.expandFMINIMUM_FMAXIMUM(Node, DAG));
1148 return;
1149 case ISD::FMINIMUMNUM:
1150 case ISD::FMAXIMUMNUM:
1151 Results.push_back(TLI.expandFMINIMUMNUM_FMAXIMUMNUM(Node, DAG));
1152 return;
1153 case ISD::SMIN:
1154 case ISD::SMAX:
1155 case ISD::UMIN:
1156 case ISD::UMAX:
1157 if (SDValue Expanded = TLI.expandIntMINMAX(Node, DAG)) {
1158 Results.push_back(Expanded);
1159 return;
1160 }
1161 break;
1162 case ISD::UADDO:
1163 case ISD::USUBO:
1164 ExpandUADDSUBO(Node, Results);
1165 return;
1166 case ISD::SADDO:
1167 case ISD::SSUBO:
1168 ExpandSADDSUBO(Node, Results);
1169 return;
1170 case ISD::UMULO:
1171 case ISD::SMULO:
1172 ExpandMULO(Node, Results);
1173 return;
1174 case ISD::USUBSAT:
1175 case ISD::SSUBSAT:
1176 case ISD::UADDSAT:
1177 case ISD::SADDSAT:
1178 if (SDValue Expanded = TLI.expandAddSubSat(Node, DAG)) {
1179 Results.push_back(Expanded);
1180 return;
1181 }
1182 break;
1183 case ISD::USHLSAT:
1184 case ISD::SSHLSAT:
1185 if (SDValue Expanded = TLI.expandShlSat(Node, DAG)) {
1186 Results.push_back(Expanded);
1187 return;
1188 }
1189 break;
1192 // Expand the fpsosisat if it is scalable to prevent it from unrolling below.
1193 if (Node->getValueType(0).isScalableVector()) {
1194 if (SDValue Expanded = TLI.expandFP_TO_INT_SAT(Node, DAG)) {
1195 Results.push_back(Expanded);
1196 return;
1197 }
1198 }
1199 break;
1200 case ISD::SMULFIX:
1201 case ISD::UMULFIX:
1202 if (SDValue Expanded = TLI.expandFixedPointMul(Node, DAG)) {
1203 Results.push_back(Expanded);
1204 return;
1205 }
1206 break;
1207 case ISD::SMULFIXSAT:
1208 case ISD::UMULFIXSAT:
1209 // FIXME: We do not expand SMULFIXSAT/UMULFIXSAT here yet, not sure exactly
1210 // why. Maybe it results in worse codegen compared to the unroll for some
1211 // targets? This should probably be investigated. And if we still prefer to
1212 // unroll an explanation could be helpful.
1213 break;
1214 case ISD::SDIVFIX:
1215 case ISD::UDIVFIX:
1216 ExpandFixedPointDiv(Node, Results);
1217 return;
1218 case ISD::SDIVFIXSAT:
1219 case ISD::UDIVFIXSAT:
1220 break;
1221#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
1222 case ISD::STRICT_##DAGN:
1223#include "llvm/IR/ConstrainedOps.def"
1224 ExpandStrictFPOp(Node, Results);
1225 return;
1226 case ISD::VECREDUCE_ADD:
1227 case ISD::VECREDUCE_MUL:
1228 case ISD::VECREDUCE_AND:
1229 case ISD::VECREDUCE_OR:
1230 case ISD::VECREDUCE_XOR:
1231 case ISD::VECREDUCE_SMAX:
1232 case ISD::VECREDUCE_SMIN:
1233 case ISD::VECREDUCE_UMAX:
1234 case ISD::VECREDUCE_UMIN:
1235 case ISD::VECREDUCE_FADD:
1236 case ISD::VECREDUCE_FMUL:
1237 case ISD::VECREDUCE_FMAX:
1238 case ISD::VECREDUCE_FMIN:
1239 case ISD::VECREDUCE_FMAXIMUM:
1240 case ISD::VECREDUCE_FMINIMUM:
1241 Results.push_back(TLI.expandVecReduce(Node, DAG));
1242 return;
1243 case ISD::PARTIAL_REDUCE_UMLA:
1244 case ISD::PARTIAL_REDUCE_SMLA:
1245 case ISD::PARTIAL_REDUCE_SUMLA:
1246 Results.push_back(TLI.expandPartialReduceMLA(Node, DAG));
1247 return;
1248 case ISD::VECREDUCE_SEQ_FADD:
1249 case ISD::VECREDUCE_SEQ_FMUL:
1250 Results.push_back(TLI.expandVecReduceSeq(Node, DAG));
1251 return;
1252 case ISD::SREM:
1253 case ISD::UREM:
1254 ExpandREM(Node, Results);
1255 return;
1256 case ISD::VP_MERGE:
1257 if (SDValue Expanded = ExpandVP_MERGE(Node)) {
1258 Results.push_back(Expanded);
1259 return;
1260 }
1261 break;
1262 case ISD::FREM:
1263 if (tryExpandVecMathCall(Node, RTLIB::REM_F32, RTLIB::REM_F64,
1264 RTLIB::REM_F80, RTLIB::REM_F128,
1265 RTLIB::REM_PPCF128, Results))
1266 return;
1267
1268 break;
1269 case ISD::FSINCOS:
1270 case ISD::FSINCOSPI: {
1271 EVT VT = Node->getValueType(0).getVectorElementType();
1272 RTLIB::Libcall LC = Node->getOpcode() == ISD::FSINCOS
1273 ? RTLIB::getSINCOS(VT)
1274 : RTLIB::getSINCOSPI(VT);
1275 if (DAG.expandMultipleResultFPLibCall(LC, Node, Results))
1276 return;
1277 break;
1278 }
1279 case ISD::FMODF: {
1280 RTLIB::Libcall LC =
1281 RTLIB::getMODF(Node->getValueType(0).getVectorElementType());
1282 if (DAG.expandMultipleResultFPLibCall(LC, Node, Results,
1283 /*CallRetResNo=*/0))
1284 return;
1285 break;
1286 }
1288 Results.push_back(TLI.expandVECTOR_COMPRESS(Node, DAG));
1289 return;
1290 case ISD::VECTOR_FIND_LAST_ACTIVE:
1291 Results.push_back(TLI.expandVectorFindLastActive(Node, DAG));
1292 return;
1293 case ISD::SCMP:
1294 case ISD::UCMP:
1295 Results.push_back(TLI.expandCMP(Node, DAG));
1296 return;
1299 Results.push_back(ExpandLOOP_DEPENDENCE_MASK(Node));
1300 return;
1301
1302 case ISD::FADD:
1303 case ISD::FMUL:
1304 case ISD::FMA:
1305 case ISD::FDIV:
1306 case ISD::FCEIL:
1307 case ISD::FFLOOR:
1308 case ISD::FNEARBYINT:
1309 case ISD::FRINT:
1310 case ISD::FROUND:
1311 case ISD::FROUNDEVEN:
1312 case ISD::FTRUNC:
1313 case ISD::FSQRT:
1314 if (SDValue Expanded = TLI.expandVectorNaryOpBySplitting(Node, DAG)) {
1315 Results.push_back(Expanded);
1316 return;
1317 }
1318 break;
1319 }
1320
1321 SDValue Unrolled = DAG.UnrollVectorOp(Node);
1322 if (Node->getNumValues() == 1) {
1323 Results.push_back(Unrolled);
1324 } else {
1325 assert(Node->getNumValues() == Unrolled->getNumValues() &&
1326 "VectorLegalizer Expand returned wrong number of results!");
1327 for (unsigned I = 0, E = Unrolled->getNumValues(); I != E; ++I)
1328 Results.push_back(Unrolled.getValue(I));
1329 }
1330}
1331
1332SDValue VectorLegalizer::ExpandSELECT(SDNode *Node) {
1333 // Lower a select instruction where the condition is a scalar and the
1334 // operands are vectors. Lower this select to VSELECT and implement it
1335 // using XOR AND OR. The selector bit is broadcasted.
1336 EVT VT = Node->getValueType(0);
1337 SDLoc DL(Node);
1338
1339 SDValue Mask = Node->getOperand(0);
1340 SDValue Op1 = Node->getOperand(1);
1341 SDValue Op2 = Node->getOperand(2);
1342
1343 assert(VT.isVector() && !Mask.getValueType().isVector()
1344 && Op1.getValueType() == Op2.getValueType() && "Invalid type");
1345
1346 // If we can't even use the basic vector operations of
1347 // AND,OR,XOR, we will have to scalarize the op.
1348 // Notice that the operation may be 'promoted' which means that it is
1349 // 'bitcasted' to another type which is handled.
1350 // Also, we need to be able to construct a splat vector using either
1351 // BUILD_VECTOR or SPLAT_VECTOR.
1352 // FIXME: Should we also permit fixed-length SPLAT_VECTOR as a fallback to
1353 // BUILD_VECTOR?
1354 if (TLI.getOperationAction(ISD::AND, VT) == TargetLowering::Expand ||
1355 TLI.getOperationAction(ISD::XOR, VT) == TargetLowering::Expand ||
1356 TLI.getOperationAction(ISD::OR, VT) == TargetLowering::Expand ||
1359 VT) == TargetLowering::Expand)
1360 return SDValue();
1361
1362 // Generate a mask operand.
1363 EVT MaskTy = VT.changeVectorElementTypeToInteger();
1364
1365 // What is the size of each element in the vector mask.
1366 EVT BitTy = MaskTy.getScalarType();
1367
1368 Mask = DAG.getSelect(DL, BitTy, Mask, DAG.getAllOnesConstant(DL, BitTy),
1369 DAG.getConstant(0, DL, BitTy));
1370
1371 // Broadcast the mask so that the entire vector is all one or all zero.
1372 Mask = DAG.getSplat(MaskTy, DL, Mask);
1373
1374 // Bitcast the operands to be the same type as the mask.
1375 // This is needed when we select between FP types because
1376 // the mask is a vector of integers.
1377 Op1 = DAG.getNode(ISD::BITCAST, DL, MaskTy, Op1);
1378 Op2 = DAG.getNode(ISD::BITCAST, DL, MaskTy, Op2);
1379
1380 SDValue NotMask = DAG.getNOT(DL, Mask, MaskTy);
1381
1382 Op1 = DAG.getNode(ISD::AND, DL, MaskTy, Op1, Mask);
1383 Op2 = DAG.getNode(ISD::AND, DL, MaskTy, Op2, NotMask);
1384 SDValue Val = DAG.getNode(ISD::OR, DL, MaskTy, Op1, Op2);
1385 return DAG.getNode(ISD::BITCAST, DL, Node->getValueType(0), Val);
1386}
1387
1388SDValue VectorLegalizer::ExpandSEXTINREG(SDNode *Node) {
1389 EVT VT = Node->getValueType(0);
1390
1391 // Make sure that the SRA and SHL instructions are available.
1392 if (TLI.getOperationAction(ISD::SRA, VT) == TargetLowering::Expand ||
1393 TLI.getOperationAction(ISD::SHL, VT) == TargetLowering::Expand)
1394 return SDValue();
1395
1396 SDLoc DL(Node);
1397 EVT OrigTy = cast<VTSDNode>(Node->getOperand(1))->getVT();
1398
1399 unsigned BW = VT.getScalarSizeInBits();
1400 unsigned OrigBW = OrigTy.getScalarSizeInBits();
1401 SDValue ShiftSz = DAG.getConstant(BW - OrigBW, DL, VT);
1402
1403 SDValue Op = DAG.getNode(ISD::SHL, DL, VT, Node->getOperand(0), ShiftSz);
1404 return DAG.getNode(ISD::SRA, DL, VT, Op, ShiftSz);
1405}
1406
1407// Generically expand a vector anyext in register to a shuffle of the relevant
1408// lanes into the appropriate locations, with other lanes left undef.
1409SDValue VectorLegalizer::ExpandANY_EXTEND_VECTOR_INREG(SDNode *Node) {
1410 SDLoc DL(Node);
1411 EVT VT = Node->getValueType(0);
1412 int NumElements = VT.getVectorNumElements();
1413 SDValue Src = Node->getOperand(0);
1414 EVT SrcVT = Src.getValueType();
1415 int NumSrcElements = SrcVT.getVectorNumElements();
1416
1417 // *_EXTEND_VECTOR_INREG SrcVT can be smaller than VT - so insert the vector
1418 // into a larger vector type.
1419 if (SrcVT.bitsLE(VT)) {
1420 assert((VT.getSizeInBits() % SrcVT.getScalarSizeInBits()) == 0 &&
1421 "ANY_EXTEND_VECTOR_INREG vector size mismatch");
1422 NumSrcElements = VT.getSizeInBits() / SrcVT.getScalarSizeInBits();
1423 SrcVT = EVT::getVectorVT(*DAG.getContext(), SrcVT.getScalarType(),
1424 NumSrcElements);
1425 Src = DAG.getInsertSubvector(DL, DAG.getUNDEF(SrcVT), Src, 0);
1426 }
1427
1428 // Build a base mask of undef shuffles.
1429 SmallVector<int, 16> ShuffleMask;
1430 ShuffleMask.resize(NumSrcElements, -1);
1431
1432 // Place the extended lanes into the correct locations.
1433 int ExtLaneScale = NumSrcElements / NumElements;
1434 int EndianOffset = DAG.getDataLayout().isBigEndian() ? ExtLaneScale - 1 : 0;
1435 for (int i = 0; i < NumElements; ++i)
1436 ShuffleMask[i * ExtLaneScale + EndianOffset] = i;
1437
1438 return DAG.getNode(
1439 ISD::BITCAST, DL, VT,
1440 DAG.getVectorShuffle(SrcVT, DL, Src, DAG.getUNDEF(SrcVT), ShuffleMask));
1441}
1442
1443SDValue VectorLegalizer::ExpandSIGN_EXTEND_VECTOR_INREG(SDNode *Node) {
1444 SDLoc DL(Node);
1445 EVT VT = Node->getValueType(0);
1446 SDValue Src = Node->getOperand(0);
1447 EVT SrcVT = Src.getValueType();
1448
1449 // First build an any-extend node which can be legalized above when we
1450 // recurse through it.
1452
1453 // Now we need sign extend. Do this by shifting the elements. Even if these
1454 // aren't legal operations, they have a better chance of being legalized
1455 // without full scalarization than the sign extension does.
1456 unsigned EltWidth = VT.getScalarSizeInBits();
1457 unsigned SrcEltWidth = SrcVT.getScalarSizeInBits();
1458 SDValue ShiftAmount = DAG.getConstant(EltWidth - SrcEltWidth, DL, VT);
1459 return DAG.getNode(ISD::SRA, DL, VT,
1460 DAG.getNode(ISD::SHL, DL, VT, Op, ShiftAmount),
1461 ShiftAmount);
1462}
1463
1464// Generically expand a vector zext in register to a shuffle of the relevant
1465// lanes into the appropriate locations, a blend of zero into the high bits,
1466// and a bitcast to the wider element type.
1467SDValue VectorLegalizer::ExpandZERO_EXTEND_VECTOR_INREG(SDNode *Node) {
1468 SDLoc DL(Node);
1469 EVT VT = Node->getValueType(0);
1470 int NumElements = VT.getVectorNumElements();
1471 SDValue Src = Node->getOperand(0);
1472 EVT SrcVT = Src.getValueType();
1473 int NumSrcElements = SrcVT.getVectorNumElements();
1474
1475 // *_EXTEND_VECTOR_INREG SrcVT can be smaller than VT - so insert the vector
1476 // into a larger vector type.
1477 if (SrcVT.bitsLE(VT)) {
1478 assert((VT.getSizeInBits() % SrcVT.getScalarSizeInBits()) == 0 &&
1479 "ZERO_EXTEND_VECTOR_INREG vector size mismatch");
1480 NumSrcElements = VT.getSizeInBits() / SrcVT.getScalarSizeInBits();
1481 SrcVT = EVT::getVectorVT(*DAG.getContext(), SrcVT.getScalarType(),
1482 NumSrcElements);
1483 Src = DAG.getInsertSubvector(DL, DAG.getUNDEF(SrcVT), Src, 0);
1484 }
1485
1486 // Build up a zero vector to blend into this one.
1487 SDValue Zero = DAG.getConstant(0, DL, SrcVT);
1488
1489 // Shuffle the incoming lanes into the correct position, and pull all other
1490 // lanes from the zero vector.
1491 auto ShuffleMask = llvm::to_vector<16>(llvm::seq<int>(0, NumSrcElements));
1492
1493 int ExtLaneScale = NumSrcElements / NumElements;
1494 int EndianOffset = DAG.getDataLayout().isBigEndian() ? ExtLaneScale - 1 : 0;
1495 for (int i = 0; i < NumElements; ++i)
1496 ShuffleMask[i * ExtLaneScale + EndianOffset] = NumSrcElements + i;
1497
1498 return DAG.getNode(ISD::BITCAST, DL, VT,
1499 DAG.getVectorShuffle(SrcVT, DL, Zero, Src, ShuffleMask));
1500}
1501
1502static void createBSWAPShuffleMask(EVT VT, SmallVectorImpl<int> &ShuffleMask) {
1503 int ScalarSizeInBytes = VT.getScalarSizeInBits() / 8;
1504 for (int I = 0, E = VT.getVectorNumElements(); I != E; ++I)
1505 for (int J = ScalarSizeInBytes - 1; J >= 0; --J)
1506 ShuffleMask.push_back((I * ScalarSizeInBytes) + J);
1507}
1508
1509SDValue VectorLegalizer::ExpandBSWAP(SDNode *Node) {
1510 EVT VT = Node->getValueType(0);
1511
1512 // Scalable vectors can't use shuffle expansion.
1513 if (VT.isScalableVector())
1514 return TLI.expandBSWAP(Node, DAG);
1515
1516 // Generate a byte wise shuffle mask for the BSWAP.
1517 SmallVector<int, 16> ShuffleMask;
1518 createBSWAPShuffleMask(VT, ShuffleMask);
1519 EVT ByteVT = EVT::getVectorVT(*DAG.getContext(), MVT::i8, ShuffleMask.size());
1520
1521 // Only emit a shuffle if the mask is legal.
1522 if (TLI.isShuffleMaskLegal(ShuffleMask, ByteVT)) {
1523 SDLoc DL(Node);
1524 SDValue Op = DAG.getNode(ISD::BITCAST, DL, ByteVT, Node->getOperand(0));
1525 Op = DAG.getVectorShuffle(ByteVT, DL, Op, DAG.getUNDEF(ByteVT), ShuffleMask);
1526 return DAG.getNode(ISD::BITCAST, DL, VT, Op);
1527 }
1528
1529 // If we have the appropriate vector bit operations, it is better to use them
1530 // than unrolling and expanding each component.
1531 if (TLI.isOperationLegalOrCustom(ISD::SHL, VT) &&
1535 return TLI.expandBSWAP(Node, DAG);
1536
1537 // Otherwise let the caller unroll.
1538 return SDValue();
1539}
1540
1541SDValue VectorLegalizer::ExpandBITREVERSE(SDNode *Node) {
1542 EVT VT = Node->getValueType(0);
1543
1544 // We can't unroll or use shuffles for scalable vectors.
1545 if (VT.isScalableVector())
1546 return TLI.expandBITREVERSE(Node, DAG);
1547
1548 // If we have the scalar operation, it's probably cheaper to unroll it.
1550 return SDValue();
1551
1552 // If the vector element width is a whole number of bytes, test if its legal
1553 // to BSWAP shuffle the bytes and then perform the BITREVERSE on the byte
1554 // vector. This greatly reduces the number of bit shifts necessary.
1555 unsigned ScalarSizeInBits = VT.getScalarSizeInBits();
1556 if (ScalarSizeInBits > 8 && (ScalarSizeInBits % 8) == 0) {
1557 SmallVector<int, 16> BSWAPMask;
1558 createBSWAPShuffleMask(VT, BSWAPMask);
1559
1560 EVT ByteVT = EVT::getVectorVT(*DAG.getContext(), MVT::i8, BSWAPMask.size());
1561 if (TLI.isShuffleMaskLegal(BSWAPMask, ByteVT) &&
1563 (TLI.isOperationLegalOrCustom(ISD::SHL, ByteVT) &&
1564 TLI.isOperationLegalOrCustom(ISD::SRL, ByteVT) &&
1567 SDLoc DL(Node);
1568 SDValue Op = DAG.getNode(ISD::BITCAST, DL, ByteVT, Node->getOperand(0));
1569 Op = DAG.getVectorShuffle(ByteVT, DL, Op, DAG.getUNDEF(ByteVT),
1570 BSWAPMask);
1571 Op = DAG.getNode(ISD::BITREVERSE, DL, ByteVT, Op);
1572 Op = DAG.getNode(ISD::BITCAST, DL, VT, Op);
1573 return Op;
1574 }
1575 }
1576
1577 // If we have the appropriate vector bit operations, it is better to use them
1578 // than unrolling and expanding each component.
1579 if (TLI.isOperationLegalOrCustom(ISD::SHL, VT) &&
1583 return TLI.expandBITREVERSE(Node, DAG);
1584
1585 // Otherwise unroll.
1586 return SDValue();
1587}
1588
1589SDValue VectorLegalizer::ExpandVSELECT(SDNode *Node) {
1590 // Implement VSELECT in terms of XOR, AND, OR
1591 // on platforms which do not support blend natively.
1592 SDLoc DL(Node);
1593
1594 SDValue Mask = Node->getOperand(0);
1595 SDValue Op1 = Node->getOperand(1);
1596 SDValue Op2 = Node->getOperand(2);
1597
1598 EVT VT = Mask.getValueType();
1599
1600 // If we can't even use the basic vector operations of
1601 // AND,OR,XOR, we will have to scalarize the op.
1602 // Notice that the operation may be 'promoted' which means that it is
1603 // 'bitcasted' to another type which is handled.
1604 if (TLI.getOperationAction(ISD::AND, VT) == TargetLowering::Expand ||
1605 TLI.getOperationAction(ISD::XOR, VT) == TargetLowering::Expand ||
1606 TLI.getOperationAction(ISD::OR, VT) == TargetLowering::Expand)
1607 return SDValue();
1608
1609 // This operation also isn't safe with AND, OR, XOR when the boolean type is
1610 // 0/1 and the select operands aren't also booleans, as we need an all-ones
1611 // vector constant to mask with.
1612 // FIXME: Sign extend 1 to all ones if that's legal on the target.
1613 auto BoolContents = TLI.getBooleanContents(Op1.getValueType());
1614 if (BoolContents != TargetLowering::ZeroOrNegativeOneBooleanContent &&
1615 !(BoolContents == TargetLowering::ZeroOrOneBooleanContent &&
1616 Op1.getValueType().getVectorElementType() == MVT::i1))
1617 return SDValue();
1618
1619 // If the mask and the type are different sizes, unroll the vector op. This
1620 // can occur when getSetCCResultType returns something that is different in
1621 // size from the operand types. For example, v4i8 = select v4i32, v4i8, v4i8.
1622 if (VT.getSizeInBits() != Op1.getValueSizeInBits())
1623 return SDValue();
1624
1625 // Bitcast the operands to be the same type as the mask.
1626 // This is needed when we select between FP types because
1627 // the mask is a vector of integers.
1628 Op1 = DAG.getNode(ISD::BITCAST, DL, VT, Op1);
1629 Op2 = DAG.getNode(ISD::BITCAST, DL, VT, Op2);
1630
1631 SDValue NotMask = DAG.getNOT(DL, Mask, VT);
1632
1633 Op1 = DAG.getNode(ISD::AND, DL, VT, Op1, Mask);
1634 Op2 = DAG.getNode(ISD::AND, DL, VT, Op2, NotMask);
1635 SDValue Val = DAG.getNode(ISD::OR, DL, VT, Op1, Op2);
1636 return DAG.getNode(ISD::BITCAST, DL, Node->getValueType(0), Val);
1637}
1638
1639SDValue VectorLegalizer::ExpandVP_SELECT(SDNode *Node) {
1640 // Implement VP_SELECT in terms of VP_XOR, VP_AND and VP_OR on platforms which
1641 // do not support it natively.
1642 SDLoc DL(Node);
1643
1644 SDValue Mask = Node->getOperand(0);
1645 SDValue Op1 = Node->getOperand(1);
1646 SDValue Op2 = Node->getOperand(2);
1647 SDValue EVL = Node->getOperand(3);
1648
1649 EVT VT = Mask.getValueType();
1650
1651 // If we can't even use the basic vector operations of
1652 // VP_AND,VP_OR,VP_XOR, we will have to scalarize the op.
1653 if (TLI.getOperationAction(ISD::VP_AND, VT) == TargetLowering::Expand ||
1654 TLI.getOperationAction(ISD::VP_XOR, VT) == TargetLowering::Expand ||
1655 TLI.getOperationAction(ISD::VP_OR, VT) == TargetLowering::Expand)
1656 return SDValue();
1657
1658 // This operation also isn't safe when the operands aren't also booleans.
1659 if (Op1.getValueType().getVectorElementType() != MVT::i1)
1660 return SDValue();
1661
1662 SDValue Ones = DAG.getAllOnesConstant(DL, VT);
1663 SDValue NotMask = DAG.getNode(ISD::VP_XOR, DL, VT, Mask, Ones, Ones, EVL);
1664
1665 Op1 = DAG.getNode(ISD::VP_AND, DL, VT, Op1, Mask, Ones, EVL);
1666 Op2 = DAG.getNode(ISD::VP_AND, DL, VT, Op2, NotMask, Ones, EVL);
1667 return DAG.getNode(ISD::VP_OR, DL, VT, Op1, Op2, Ones, EVL);
1668}
1669
1670SDValue VectorLegalizer::ExpandVP_MERGE(SDNode *Node) {
1671 // Implement VP_MERGE in terms of VSELECT. Construct a mask where vector
1672 // indices less than the EVL/pivot are true. Combine that with the original
1673 // mask for a full-length mask. Use a full-length VSELECT to select between
1674 // the true and false values.
1675 SDLoc DL(Node);
1676
1677 SDValue Mask = Node->getOperand(0);
1678 SDValue Op1 = Node->getOperand(1);
1679 SDValue Op2 = Node->getOperand(2);
1680 SDValue EVL = Node->getOperand(3);
1681
1682 EVT MaskVT = Mask.getValueType();
1683 bool IsFixedLen = MaskVT.isFixedLengthVector();
1684
1685 EVT EVLVecVT = EVT::getVectorVT(*DAG.getContext(), EVL.getValueType(),
1686 MaskVT.getVectorElementCount());
1687
1688 // If we can't construct the EVL mask efficiently, it's better to unroll.
1689 if ((IsFixedLen &&
1691 (!IsFixedLen &&
1692 (!TLI.isOperationLegalOrCustom(ISD::STEP_VECTOR, EVLVecVT) ||
1694 return SDValue();
1695
1696 // If using a SETCC would result in a different type than the mask type,
1697 // unroll.
1698 if (TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(),
1699 EVLVecVT) != MaskVT)
1700 return SDValue();
1701
1702 SDValue StepVec = DAG.getStepVector(DL, EVLVecVT);
1703 SDValue SplatEVL = DAG.getSplat(EVLVecVT, DL, EVL);
1704 SDValue EVLMask =
1705 DAG.getSetCC(DL, MaskVT, StepVec, SplatEVL, ISD::CondCode::SETULT);
1706
1707 SDValue FullMask = DAG.getNode(ISD::AND, DL, MaskVT, Mask, EVLMask);
1708 return DAG.getSelect(DL, Node->getValueType(0), FullMask, Op1, Op2);
1709}
1710
1711SDValue VectorLegalizer::ExpandVP_REM(SDNode *Node) {
1712 // Implement VP_SREM/UREM in terms of VP_SDIV/VP_UDIV, VP_MUL, VP_SUB.
1713 EVT VT = Node->getValueType(0);
1714
1715 unsigned DivOpc = Node->getOpcode() == ISD::VP_SREM ? ISD::VP_SDIV : ISD::VP_UDIV;
1716
1717 if (!TLI.isOperationLegalOrCustom(DivOpc, VT) ||
1718 !TLI.isOperationLegalOrCustom(ISD::VP_MUL, VT) ||
1719 !TLI.isOperationLegalOrCustom(ISD::VP_SUB, VT))
1720 return SDValue();
1721
1722 SDLoc DL(Node);
1723
1724 SDValue Dividend = Node->getOperand(0);
1725 SDValue Divisor = Node->getOperand(1);
1726 SDValue Mask = Node->getOperand(2);
1727 SDValue EVL = Node->getOperand(3);
1728
1729 // X % Y -> X-X/Y*Y
1730 SDValue Div = DAG.getNode(DivOpc, DL, VT, Dividend, Divisor, Mask, EVL);
1731 SDValue Mul = DAG.getNode(ISD::VP_MUL, DL, VT, Divisor, Div, Mask, EVL);
1732 return DAG.getNode(ISD::VP_SUB, DL, VT, Dividend, Mul, Mask, EVL);
1733}
1734
1735SDValue VectorLegalizer::ExpandVP_FNEG(SDNode *Node) {
1736 EVT VT = Node->getValueType(0);
1737 EVT IntVT = VT.changeVectorElementTypeToInteger();
1738
1739 if (!TLI.isOperationLegalOrCustom(ISD::VP_XOR, IntVT))
1740 return SDValue();
1741
1742 SDValue Mask = Node->getOperand(1);
1743 SDValue EVL = Node->getOperand(2);
1744
1745 SDLoc DL(Node);
1746 SDValue Cast = DAG.getNode(ISD::BITCAST, DL, IntVT, Node->getOperand(0));
1747 SDValue SignMask = DAG.getConstant(
1748 APInt::getSignMask(IntVT.getScalarSizeInBits()), DL, IntVT);
1749 SDValue Xor = DAG.getNode(ISD::VP_XOR, DL, IntVT, Cast, SignMask, Mask, EVL);
1750 return DAG.getNode(ISD::BITCAST, DL, VT, Xor);
1751}
1752
1753SDValue VectorLegalizer::ExpandVP_FABS(SDNode *Node) {
1754 EVT VT = Node->getValueType(0);
1755 EVT IntVT = VT.changeVectorElementTypeToInteger();
1756
1757 if (!TLI.isOperationLegalOrCustom(ISD::VP_AND, IntVT))
1758 return SDValue();
1759
1760 SDValue Mask = Node->getOperand(1);
1761 SDValue EVL = Node->getOperand(2);
1762
1763 SDLoc DL(Node);
1764 SDValue Cast = DAG.getNode(ISD::BITCAST, DL, IntVT, Node->getOperand(0));
1765 SDValue ClearSignMask = DAG.getConstant(
1767 SDValue ClearSign =
1768 DAG.getNode(ISD::VP_AND, DL, IntVT, Cast, ClearSignMask, Mask, EVL);
1769 return DAG.getNode(ISD::BITCAST, DL, VT, ClearSign);
1770}
1771
1772SDValue VectorLegalizer::ExpandVP_FCOPYSIGN(SDNode *Node) {
1773 EVT VT = Node->getValueType(0);
1774
1775 if (VT != Node->getOperand(1).getValueType())
1776 return SDValue();
1777
1778 EVT IntVT = VT.changeVectorElementTypeToInteger();
1779 if (!TLI.isOperationLegalOrCustom(ISD::VP_AND, IntVT) ||
1780 !TLI.isOperationLegalOrCustom(ISD::VP_XOR, IntVT))
1781 return SDValue();
1782
1783 SDValue Mask = Node->getOperand(2);
1784 SDValue EVL = Node->getOperand(3);
1785
1786 SDLoc DL(Node);
1787 SDValue Mag = DAG.getNode(ISD::BITCAST, DL, IntVT, Node->getOperand(0));
1788 SDValue Sign = DAG.getNode(ISD::BITCAST, DL, IntVT, Node->getOperand(1));
1789
1790 SDValue SignMask = DAG.getConstant(
1791 APInt::getSignMask(IntVT.getScalarSizeInBits()), DL, IntVT);
1792 SDValue SignBit =
1793 DAG.getNode(ISD::VP_AND, DL, IntVT, Sign, SignMask, Mask, EVL);
1794
1795 SDValue ClearSignMask = DAG.getConstant(
1797 SDValue ClearedSign =
1798 DAG.getNode(ISD::VP_AND, DL, IntVT, Mag, ClearSignMask, Mask, EVL);
1799
1800 SDValue CopiedSign = DAG.getNode(ISD::VP_OR, DL, IntVT, ClearedSign, SignBit,
1801 Mask, EVL, SDNodeFlags::Disjoint);
1802
1803 return DAG.getNode(ISD::BITCAST, DL, VT, CopiedSign);
1804}
1805
1806SDValue VectorLegalizer::ExpandLOOP_DEPENDENCE_MASK(SDNode *N) {
1807 SDLoc DL(N);
1808 SDValue SourceValue = N->getOperand(0);
1809 SDValue SinkValue = N->getOperand(1);
1810 SDValue EltSize = N->getOperand(2);
1811
1812 bool IsReadAfterWrite = N->getOpcode() == ISD::LOOP_DEPENDENCE_RAW_MASK;
1813 EVT VT = N->getValueType(0);
1814 EVT PtrVT = SourceValue->getValueType(0);
1815
1816 SDValue Diff = DAG.getNode(ISD::SUB, DL, PtrVT, SinkValue, SourceValue);
1817 if (IsReadAfterWrite)
1818 Diff = DAG.getNode(ISD::ABS, DL, PtrVT, Diff);
1819
1820 Diff = DAG.getNode(ISD::SDIV, DL, PtrVT, Diff, EltSize);
1821
1822 // If the difference is positive then some elements may alias
1823 EVT CmpVT = TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(),
1824 Diff.getValueType());
1825 SDValue Zero = DAG.getTargetConstant(0, DL, PtrVT);
1826 SDValue Cmp = DAG.getSetCC(DL, CmpVT, Diff, Zero,
1827 IsReadAfterWrite ? ISD::SETEQ : ISD::SETLE);
1828
1829 // Create the lane mask
1830 EVT SplatVT = VT.changeElementType(PtrVT);
1831 SDValue DiffSplat = DAG.getSplat(SplatVT, DL, Diff);
1832 SDValue VectorStep = DAG.getStepVector(DL, SplatVT);
1833 EVT MaskVT = VT.changeElementType(MVT::i1);
1834 SDValue DiffMask =
1835 DAG.getSetCC(DL, MaskVT, VectorStep, DiffSplat, ISD::CondCode::SETULT);
1836
1837 EVT EltVT = VT.getVectorElementType();
1838 // Extend the diff setcc in case the intrinsic has been promoted to a vector
1839 // type with elements larger than i1
1840 if (EltVT.getScalarSizeInBits() > MaskVT.getScalarSizeInBits())
1841 DiffMask = DAG.getNode(ISD::ANY_EXTEND, DL, VT, DiffMask);
1842
1843 // Splat the compare result then OR it with the lane mask
1844 if (CmpVT.getScalarSizeInBits() < EltVT.getScalarSizeInBits())
1845 Cmp = DAG.getNode(ISD::ZERO_EXTEND, DL, EltVT, Cmp);
1846 SDValue Splat = DAG.getSplat(VT, DL, Cmp);
1847 return DAG.getNode(ISD::OR, DL, VT, DiffMask, Splat);
1848}
1849
1850void VectorLegalizer::ExpandFP_TO_UINT(SDNode *Node,
1851 SmallVectorImpl<SDValue> &Results) {
1852 // Attempt to expand using TargetLowering.
1853 SDValue Result, Chain;
1854 if (TLI.expandFP_TO_UINT(Node, Result, Chain, DAG)) {
1855 Results.push_back(Result);
1856 if (Node->isStrictFPOpcode())
1857 Results.push_back(Chain);
1858 return;
1859 }
1860
1861 // Otherwise go ahead and unroll.
1862 if (Node->isStrictFPOpcode()) {
1863 UnrollStrictFPOp(Node, Results);
1864 return;
1865 }
1866
1867 Results.push_back(DAG.UnrollVectorOp(Node));
1868}
1869
1870void VectorLegalizer::ExpandUINT_TO_FLOAT(SDNode *Node,
1871 SmallVectorImpl<SDValue> &Results) {
1872 bool IsStrict = Node->isStrictFPOpcode();
1873 unsigned OpNo = IsStrict ? 1 : 0;
1874 SDValue Src = Node->getOperand(OpNo);
1875 EVT SrcVT = Src.getValueType();
1876 EVT DstVT = Node->getValueType(0);
1877 SDLoc DL(Node);
1878
1879 // Attempt to expand using TargetLowering.
1881 SDValue Chain;
1882 if (TLI.expandUINT_TO_FP(Node, Result, Chain, DAG)) {
1883 Results.push_back(Result);
1884 if (IsStrict)
1885 Results.push_back(Chain);
1886 return;
1887 }
1888
1889 // Make sure that the SINT_TO_FP and SRL instructions are available.
1890 if (((!IsStrict && TLI.getOperationAction(ISD::SINT_TO_FP, SrcVT) ==
1891 TargetLowering::Expand) ||
1892 (IsStrict && TLI.getOperationAction(ISD::STRICT_SINT_TO_FP, SrcVT) ==
1893 TargetLowering::Expand)) ||
1894 TLI.getOperationAction(ISD::SRL, SrcVT) == TargetLowering::Expand) {
1895 if (IsStrict) {
1896 UnrollStrictFPOp(Node, Results);
1897 return;
1898 }
1899
1900 Results.push_back(DAG.UnrollVectorOp(Node));
1901 return;
1902 }
1903
1904 unsigned BW = SrcVT.getScalarSizeInBits();
1905 assert((BW == 64 || BW == 32) &&
1906 "Elements in vector-UINT_TO_FP must be 32 or 64 bits wide");
1907
1908 // If STRICT_/FMUL is not supported by the target (in case of f16) replace the
1909 // UINT_TO_FP with a larger float and round to the smaller type
1910 if ((!IsStrict && !TLI.isOperationLegalOrCustom(ISD::FMUL, DstVT)) ||
1911 (IsStrict && !TLI.isOperationLegalOrCustom(ISD::STRICT_FMUL, DstVT))) {
1912 EVT FPVT = BW == 32 ? MVT::f32 : MVT::f64;
1913 SDValue UIToFP;
1915 SDValue TargetZero = DAG.getIntPtrConstant(0, DL, /*isTarget=*/true);
1916 EVT FloatVecVT = SrcVT.changeVectorElementType(FPVT);
1917 if (IsStrict) {
1918 UIToFP = DAG.getNode(ISD::STRICT_UINT_TO_FP, DL, {FloatVecVT, MVT::Other},
1919 {Node->getOperand(0), Src});
1920 Result = DAG.getNode(ISD::STRICT_FP_ROUND, DL, {DstVT, MVT::Other},
1921 {Node->getOperand(0), UIToFP, TargetZero});
1922 Results.push_back(Result);
1923 Results.push_back(Result.getValue(1));
1924 } else {
1925 UIToFP = DAG.getNode(ISD::UINT_TO_FP, DL, FloatVecVT, Src);
1926 Result = DAG.getNode(ISD::FP_ROUND, DL, DstVT, UIToFP, TargetZero);
1927 Results.push_back(Result);
1928 }
1929
1930 return;
1931 }
1932
1933 SDValue HalfWord = DAG.getConstant(BW / 2, DL, SrcVT);
1934
1935 // Constants to clear the upper part of the word.
1936 // Notice that we can also use SHL+SHR, but using a constant is slightly
1937 // faster on x86.
1938 uint64_t HWMask = (BW == 64) ? 0x00000000FFFFFFFF : 0x0000FFFF;
1939 SDValue HalfWordMask = DAG.getConstant(HWMask, DL, SrcVT);
1940
1941 // Two to the power of half-word-size.
1942 SDValue TWOHW = DAG.getConstantFP(1ULL << (BW / 2), DL, DstVT);
1943
1944 // Clear upper part of LO, lower HI
1945 SDValue HI = DAG.getNode(ISD::SRL, DL, SrcVT, Src, HalfWord);
1946 SDValue LO = DAG.getNode(ISD::AND, DL, SrcVT, Src, HalfWordMask);
1947
1948 if (IsStrict) {
1949 // Convert hi and lo to floats
1950 // Convert the hi part back to the upper values
1951 // TODO: Can any fast-math-flags be set on these nodes?
1952 SDValue fHI = DAG.getNode(ISD::STRICT_SINT_TO_FP, DL, {DstVT, MVT::Other},
1953 {Node->getOperand(0), HI});
1954 fHI = DAG.getNode(ISD::STRICT_FMUL, DL, {DstVT, MVT::Other},
1955 {fHI.getValue(1), fHI, TWOHW});
1956 SDValue fLO = DAG.getNode(ISD::STRICT_SINT_TO_FP, DL, {DstVT, MVT::Other},
1957 {Node->getOperand(0), LO});
1958
1959 SDValue TF = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, fHI.getValue(1),
1960 fLO.getValue(1));
1961
1962 // Add the two halves
1963 SDValue Result =
1964 DAG.getNode(ISD::STRICT_FADD, DL, {DstVT, MVT::Other}, {TF, fHI, fLO});
1965
1966 Results.push_back(Result);
1967 Results.push_back(Result.getValue(1));
1968 return;
1969 }
1970
1971 // Convert hi and lo to floats
1972 // Convert the hi part back to the upper values
1973 // TODO: Can any fast-math-flags be set on these nodes?
1974 SDValue fHI = DAG.getNode(ISD::SINT_TO_FP, DL, DstVT, HI);
1975 fHI = DAG.getNode(ISD::FMUL, DL, DstVT, fHI, TWOHW);
1976 SDValue fLO = DAG.getNode(ISD::SINT_TO_FP, DL, DstVT, LO);
1977
1978 // Add the two halves
1979 Results.push_back(DAG.getNode(ISD::FADD, DL, DstVT, fHI, fLO));
1980}
1981
1982SDValue VectorLegalizer::ExpandFNEG(SDNode *Node) {
1983 EVT VT = Node->getValueType(0);
1984 EVT IntVT = VT.changeVectorElementTypeToInteger();
1985
1986 if (!TLI.isOperationLegalOrCustom(ISD::XOR, IntVT))
1987 return SDValue();
1988
1989 // FIXME: The FSUB check is here to force unrolling v1f64 vectors on AArch64.
1991 !VT.isScalableVector())
1992 return SDValue();
1993
1994 SDLoc DL(Node);
1995 SDValue Cast = DAG.getNode(ISD::BITCAST, DL, IntVT, Node->getOperand(0));
1996 SDValue SignMask = DAG.getConstant(
1997 APInt::getSignMask(IntVT.getScalarSizeInBits()), DL, IntVT);
1998 SDValue Xor = DAG.getNode(ISD::XOR, DL, IntVT, Cast, SignMask);
1999 return DAG.getNode(ISD::BITCAST, DL, VT, Xor);
2000}
2001
2002SDValue VectorLegalizer::ExpandFABS(SDNode *Node) {
2003 EVT VT = Node->getValueType(0);
2004 EVT IntVT = VT.changeVectorElementTypeToInteger();
2005
2006 if (!TLI.isOperationLegalOrCustom(ISD::AND, IntVT))
2007 return SDValue();
2008
2009 // FIXME: The FSUB check is here to force unrolling v1f64 vectors on AArch64.
2011 !VT.isScalableVector())
2012 return SDValue();
2013
2014 SDLoc DL(Node);
2015 SDValue Cast = DAG.getNode(ISD::BITCAST, DL, IntVT, Node->getOperand(0));
2016 SDValue ClearSignMask = DAG.getConstant(
2018 SDValue ClearedSign = DAG.getNode(ISD::AND, DL, IntVT, Cast, ClearSignMask);
2019 return DAG.getNode(ISD::BITCAST, DL, VT, ClearedSign);
2020}
2021
2022SDValue VectorLegalizer::ExpandFCOPYSIGN(SDNode *Node) {
2023 EVT VT = Node->getValueType(0);
2024 EVT IntVT = VT.changeVectorElementTypeToInteger();
2025
2026 if (VT != Node->getOperand(1).getValueType() ||
2027 !TLI.isOperationLegalOrCustom(ISD::AND, IntVT) ||
2028 !TLI.isOperationLegalOrCustom(ISD::OR, IntVT))
2029 return SDValue();
2030
2031 // FIXME: The FSUB check is here to force unrolling v1f64 vectors on AArch64.
2033 !VT.isScalableVector())
2034 return SDValue();
2035
2036 SDLoc DL(Node);
2037 SDValue Mag = DAG.getNode(ISD::BITCAST, DL, IntVT, Node->getOperand(0));
2038 SDValue Sign = DAG.getNode(ISD::BITCAST, DL, IntVT, Node->getOperand(1));
2039
2040 SDValue SignMask = DAG.getConstant(
2041 APInt::getSignMask(IntVT.getScalarSizeInBits()), DL, IntVT);
2042 SDValue SignBit = DAG.getNode(ISD::AND, DL, IntVT, Sign, SignMask);
2043
2044 SDValue ClearSignMask = DAG.getConstant(
2046 SDValue ClearedSign = DAG.getNode(ISD::AND, DL, IntVT, Mag, ClearSignMask);
2047
2048 SDValue CopiedSign = DAG.getNode(ISD::OR, DL, IntVT, ClearedSign, SignBit,
2050
2051 return DAG.getNode(ISD::BITCAST, DL, VT, CopiedSign);
2052}
2053
2054void VectorLegalizer::ExpandFSUB(SDNode *Node,
2055 SmallVectorImpl<SDValue> &Results) {
2056 // For floating-point values, (a-b) is the same as a+(-b). If FNEG is legal,
2057 // we can defer this to operation legalization where it will be lowered as
2058 // a+(-b).
2059 EVT VT = Node->getValueType(0);
2060 if (TLI.isOperationLegalOrCustom(ISD::FNEG, VT) &&
2062 return; // Defer to LegalizeDAG
2063
2064 if (SDValue Expanded = TLI.expandVectorNaryOpBySplitting(Node, DAG)) {
2065 Results.push_back(Expanded);
2066 return;
2067 }
2068
2069 SDValue Tmp = DAG.UnrollVectorOp(Node);
2070 Results.push_back(Tmp);
2071}
2072
2073void VectorLegalizer::ExpandSETCC(SDNode *Node,
2074 SmallVectorImpl<SDValue> &Results) {
2075 bool NeedInvert = false;
2076 bool IsVP = Node->getOpcode() == ISD::VP_SETCC;
2077 bool IsStrict = Node->getOpcode() == ISD::STRICT_FSETCC ||
2078 Node->getOpcode() == ISD::STRICT_FSETCCS;
2079 bool IsSignaling = Node->getOpcode() == ISD::STRICT_FSETCCS;
2080 unsigned Offset = IsStrict ? 1 : 0;
2081
2082 SDValue Chain = IsStrict ? Node->getOperand(0) : SDValue();
2083 SDValue LHS = Node->getOperand(0 + Offset);
2084 SDValue RHS = Node->getOperand(1 + Offset);
2085 SDValue CC = Node->getOperand(2 + Offset);
2086
2087 MVT OpVT = LHS.getSimpleValueType();
2088 ISD::CondCode CCCode = cast<CondCodeSDNode>(CC)->get();
2089
2090 if (TLI.getCondCodeAction(CCCode, OpVT) != TargetLowering::Expand) {
2091 if (IsStrict) {
2092 UnrollStrictFPOp(Node, Results);
2093 return;
2094 }
2095 Results.push_back(UnrollVSETCC(Node));
2096 return;
2097 }
2098
2099 SDValue Mask, EVL;
2100 if (IsVP) {
2101 Mask = Node->getOperand(3 + Offset);
2102 EVL = Node->getOperand(4 + Offset);
2103 }
2104
2105 SDLoc dl(Node);
2106 bool Legalized =
2107 TLI.LegalizeSetCCCondCode(DAG, Node->getValueType(0), LHS, RHS, CC, Mask,
2108 EVL, NeedInvert, dl, Chain, IsSignaling);
2109
2110 if (Legalized) {
2111 // If we expanded the SETCC by swapping LHS and RHS, or by inverting the
2112 // condition code, create a new SETCC node.
2113 if (CC.getNode()) {
2114 if (IsStrict) {
2115 LHS = DAG.getNode(Node->getOpcode(), dl, Node->getVTList(),
2116 {Chain, LHS, RHS, CC}, Node->getFlags());
2117 Chain = LHS.getValue(1);
2118 } else if (IsVP) {
2119 LHS = DAG.getNode(ISD::VP_SETCC, dl, Node->getValueType(0),
2120 {LHS, RHS, CC, Mask, EVL}, Node->getFlags());
2121 } else {
2122 LHS = DAG.getNode(ISD::SETCC, dl, Node->getValueType(0), LHS, RHS, CC,
2123 Node->getFlags());
2124 }
2125 }
2126
2127 // If we expanded the SETCC by inverting the condition code, then wrap
2128 // the existing SETCC in a NOT to restore the intended condition.
2129 if (NeedInvert) {
2130 if (!IsVP)
2131 LHS = DAG.getLogicalNOT(dl, LHS, LHS->getValueType(0));
2132 else
2133 LHS = DAG.getVPLogicalNOT(dl, LHS, Mask, EVL, LHS->getValueType(0));
2134 }
2135 } else {
2136 assert(!IsStrict && "Don't know how to expand for strict nodes.");
2137
2138 // Otherwise, SETCC for the given comparison type must be completely
2139 // illegal; expand it into a SELECT_CC.
2140 EVT VT = Node->getValueType(0);
2141 LHS = DAG.getNode(ISD::SELECT_CC, dl, VT, LHS, RHS,
2142 DAG.getBoolConstant(true, dl, VT, LHS.getValueType()),
2143 DAG.getBoolConstant(false, dl, VT, LHS.getValueType()),
2144 CC, Node->getFlags());
2145 }
2146
2147 Results.push_back(LHS);
2148 if (IsStrict)
2149 Results.push_back(Chain);
2150}
2151
2152void VectorLegalizer::ExpandUADDSUBO(SDNode *Node,
2153 SmallVectorImpl<SDValue> &Results) {
2154 SDValue Result, Overflow;
2155 TLI.expandUADDSUBO(Node, Result, Overflow, DAG);
2156 Results.push_back(Result);
2157 Results.push_back(Overflow);
2158}
2159
2160void VectorLegalizer::ExpandSADDSUBO(SDNode *Node,
2161 SmallVectorImpl<SDValue> &Results) {
2162 SDValue Result, Overflow;
2163 TLI.expandSADDSUBO(Node, Result, Overflow, DAG);
2164 Results.push_back(Result);
2165 Results.push_back(Overflow);
2166}
2167
2168void VectorLegalizer::ExpandMULO(SDNode *Node,
2169 SmallVectorImpl<SDValue> &Results) {
2170 SDValue Result, Overflow;
2171 if (!TLI.expandMULO(Node, Result, Overflow, DAG))
2172 std::tie(Result, Overflow) = DAG.UnrollVectorOverflowOp(Node);
2173
2174 Results.push_back(Result);
2175 Results.push_back(Overflow);
2176}
2177
2178void VectorLegalizer::ExpandFixedPointDiv(SDNode *Node,
2179 SmallVectorImpl<SDValue> &Results) {
2180 SDNode *N = Node;
2181 if (SDValue Expanded = TLI.expandFixedPointDiv(N->getOpcode(), SDLoc(N),
2182 N->getOperand(0), N->getOperand(1), N->getConstantOperandVal(2), DAG))
2183 Results.push_back(Expanded);
2184}
2185
2186void VectorLegalizer::ExpandStrictFPOp(SDNode *Node,
2187 SmallVectorImpl<SDValue> &Results) {
2188 if (Node->getOpcode() == ISD::STRICT_UINT_TO_FP) {
2189 ExpandUINT_TO_FLOAT(Node, Results);
2190 return;
2191 }
2192 if (Node->getOpcode() == ISD::STRICT_FP_TO_UINT) {
2193 ExpandFP_TO_UINT(Node, Results);
2194 return;
2195 }
2196
2197 if (Node->getOpcode() == ISD::STRICT_FSETCC ||
2198 Node->getOpcode() == ISD::STRICT_FSETCCS) {
2199 ExpandSETCC(Node, Results);
2200 return;
2201 }
2202
2203 UnrollStrictFPOp(Node, Results);
2204}
2205
2206void VectorLegalizer::ExpandREM(SDNode *Node,
2207 SmallVectorImpl<SDValue> &Results) {
2208 assert((Node->getOpcode() == ISD::SREM || Node->getOpcode() == ISD::UREM) &&
2209 "Expected REM node");
2210
2212 if (!TLI.expandREM(Node, Result, DAG))
2213 Result = DAG.UnrollVectorOp(Node);
2214 Results.push_back(Result);
2215}
2216
2217// Try to expand libm nodes into vector math routine calls. Callers provide the
2218// LibFunc equivalent of the passed in Node, which is used to lookup mappings
2219// within TargetLibraryInfo. The only mappings considered are those where the
2220// result and all operands are the same vector type. While predicated nodes are
2221// not supported, we will emit calls to masked routines by passing in an all
2222// true mask.
2223bool VectorLegalizer::tryExpandVecMathCall(SDNode *Node, RTLIB::Libcall LC,
2224 SmallVectorImpl<SDValue> &Results) {
2225 // Chain must be propagated but currently strict fp operations are down
2226 // converted to their none strict counterpart.
2227 assert(!Node->isStrictFPOpcode() && "Unexpected strict fp operation!");
2228
2229 const char *LCName = TLI.getLibcallName(LC);
2230 if (!LCName)
2231 return false;
2232 LLVM_DEBUG(dbgs() << "Looking for vector variant of " << LCName << "\n");
2233
2234 EVT VT = Node->getValueType(0);
2235 ElementCount VL = VT.getVectorElementCount();
2236
2237 // Lookup a vector function equivalent to the specified libcall. Prefer
2238 // unmasked variants but we will generate a mask if need be.
2239 const TargetLibraryInfo &TLibInfo = DAG.getLibInfo();
2240 const VecDesc *VD = TLibInfo.getVectorMappingInfo(LCName, VL, false);
2241 if (!VD)
2242 VD = TLibInfo.getVectorMappingInfo(LCName, VL, /*Masked=*/true);
2243 if (!VD)
2244 return false;
2245
2246 LLVMContext *Ctx = DAG.getContext();
2247 Type *Ty = VT.getTypeForEVT(*Ctx);
2248 Type *ScalarTy = Ty->getScalarType();
2249
2250 // Construct a scalar function type based on Node's operands.
2252 for (unsigned i = 0; i < Node->getNumOperands(); ++i) {
2253 assert(Node->getOperand(i).getValueType() == VT &&
2254 "Expected matching vector types!");
2255 ArgTys.push_back(ScalarTy);
2256 }
2257 FunctionType *ScalarFTy = FunctionType::get(ScalarTy, ArgTys, false);
2258
2259 // Generate call information for the vector function.
2260 const std::string MangledName = VD->getVectorFunctionABIVariantString();
2261 auto OptVFInfo = VFABI::tryDemangleForVFABI(MangledName, ScalarFTy);
2262 if (!OptVFInfo)
2263 return false;
2264
2265 LLVM_DEBUG(dbgs() << "Found vector variant " << VD->getVectorFnName()
2266 << "\n");
2267
2268 // Sanity check just in case OptVFInfo has unexpected parameters.
2269 if (OptVFInfo->Shape.Parameters.size() !=
2270 Node->getNumOperands() + VD->isMasked())
2271 return false;
2272
2273 // Collect vector call operands.
2274
2275 SDLoc DL(Node);
2276 TargetLowering::ArgListTy Args;
2277
2278 unsigned OpNum = 0;
2279 for (auto &VFParam : OptVFInfo->Shape.Parameters) {
2280 if (VFParam.ParamKind == VFParamKind::GlobalPredicate) {
2281 EVT MaskVT = TLI.getSetCCResultType(DAG.getDataLayout(), *Ctx, VT);
2282 Args.emplace_back(DAG.getBoolConstant(true, DL, MaskVT, VT),
2283 MaskVT.getTypeForEVT(*Ctx));
2284 continue;
2285 }
2286
2287 // Only vector operands are supported.
2288 if (VFParam.ParamKind != VFParamKind::Vector)
2289 return false;
2290
2291 Args.emplace_back(Node->getOperand(OpNum++), Ty);
2292 }
2293
2294 // Emit a call to the vector function.
2296 TLI.getPointerTy(DAG.getDataLayout()));
2297 TargetLowering::CallLoweringInfo CLI(DAG);
2298 CLI.setDebugLoc(DL)
2299 .setChain(DAG.getEntryNode())
2300 .setLibCallee(CallingConv::C, Ty, Callee, std::move(Args));
2301
2302 std::pair<SDValue, SDValue> CallResult = TLI.LowerCallTo(CLI);
2303 Results.push_back(CallResult.first);
2304 return true;
2305}
2306
2307/// Try to expand the node to a vector libcall based on the result type.
2308bool VectorLegalizer::tryExpandVecMathCall(
2309 SDNode *Node, RTLIB::Libcall Call_F32, RTLIB::Libcall Call_F64,
2310 RTLIB::Libcall Call_F80, RTLIB::Libcall Call_F128,
2311 RTLIB::Libcall Call_PPCF128, SmallVectorImpl<SDValue> &Results) {
2312 RTLIB::Libcall LC = RTLIB::getFPLibCall(
2313 Node->getValueType(0).getVectorElementType(), Call_F32, Call_F64,
2314 Call_F80, Call_F128, Call_PPCF128);
2315
2316 if (LC == RTLIB::UNKNOWN_LIBCALL)
2317 return false;
2318
2319 return tryExpandVecMathCall(Node, LC, Results);
2320}
2321
2322void VectorLegalizer::UnrollStrictFPOp(SDNode *Node,
2323 SmallVectorImpl<SDValue> &Results) {
2324 EVT VT = Node->getValueType(0);
2325 EVT EltVT = VT.getVectorElementType();
2326 unsigned NumElems = VT.getVectorNumElements();
2327 unsigned NumOpers = Node->getNumOperands();
2328 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
2329
2330 EVT TmpEltVT = EltVT;
2331 if (Node->getOpcode() == ISD::STRICT_FSETCC ||
2332 Node->getOpcode() == ISD::STRICT_FSETCCS)
2333 TmpEltVT = TLI.getSetCCResultType(DAG.getDataLayout(),
2334 *DAG.getContext(), TmpEltVT);
2335
2336 EVT ValueVTs[] = {TmpEltVT, MVT::Other};
2337 SDValue Chain = Node->getOperand(0);
2338 SDLoc dl(Node);
2339
2340 SmallVector<SDValue, 32> OpValues;
2341 SmallVector<SDValue, 32> OpChains;
2342 for (unsigned i = 0; i < NumElems; ++i) {
2344 SDValue Idx = DAG.getVectorIdxConstant(i, dl);
2345
2346 // The Chain is the first operand.
2347 Opers.push_back(Chain);
2348
2349 // Now process the remaining operands.
2350 for (unsigned j = 1; j < NumOpers; ++j) {
2351 SDValue Oper = Node->getOperand(j);
2352 EVT OperVT = Oper.getValueType();
2353
2354 if (OperVT.isVector())
2355 Oper = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl,
2356 OperVT.getVectorElementType(), Oper, Idx);
2357
2358 Opers.push_back(Oper);
2359 }
2360
2361 SDValue ScalarOp = DAG.getNode(Node->getOpcode(), dl, ValueVTs, Opers);
2362 SDValue ScalarResult = ScalarOp.getValue(0);
2363 SDValue ScalarChain = ScalarOp.getValue(1);
2364
2365 if (Node->getOpcode() == ISD::STRICT_FSETCC ||
2366 Node->getOpcode() == ISD::STRICT_FSETCCS)
2367 ScalarResult = DAG.getSelect(dl, EltVT, ScalarResult,
2368 DAG.getAllOnesConstant(dl, EltVT),
2369 DAG.getConstant(0, dl, EltVT));
2370
2371 OpValues.push_back(ScalarResult);
2372 OpChains.push_back(ScalarChain);
2373 }
2374
2375 SDValue Result = DAG.getBuildVector(VT, dl, OpValues);
2376 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OpChains);
2377
2378 Results.push_back(Result);
2379 Results.push_back(NewChain);
2380}
2381
2382SDValue VectorLegalizer::UnrollVSETCC(SDNode *Node) {
2383 EVT VT = Node->getValueType(0);
2384 unsigned NumElems = VT.getVectorNumElements();
2385 EVT EltVT = VT.getVectorElementType();
2386 SDValue LHS = Node->getOperand(0);
2387 SDValue RHS = Node->getOperand(1);
2388 SDValue CC = Node->getOperand(2);
2389 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
2390 SDLoc dl(Node);
2391 SmallVector<SDValue, 8> Ops(NumElems);
2392 for (unsigned i = 0; i < NumElems; ++i) {
2393 SDValue LHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, LHS,
2394 DAG.getVectorIdxConstant(i, dl));
2395 SDValue RHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, RHS,
2396 DAG.getVectorIdxConstant(i, dl));
2397 // FIXME: We should use i1 setcc + boolext here, but it causes regressions.
2398 Ops[i] = DAG.getNode(ISD::SETCC, dl,
2400 *DAG.getContext(), TmpEltVT),
2401 LHSElem, RHSElem, CC);
2402 Ops[i] = DAG.getSelect(dl, EltVT, Ops[i],
2403 DAG.getBoolConstant(true, dl, EltVT, VT),
2404 DAG.getConstant(0, dl, EltVT));
2405 }
2406 return DAG.getBuildVector(VT, dl, Ops);
2407}
2408
2410 return VectorLegalizer(*this).Run();
2411}
return SDValue()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static void createBSWAPShuffleMask(EVT VT, SmallVectorImpl< int > &ShuffleMask)
#define I(x, y, z)
Definition MD5.cpp:58
mir Rename Register Operands
#define T
This file defines the SmallVector class.
#define LLVM_DEBUG(...)
Definition Debug.h:119
This file describes how to lower LLVM code to machine code.
Value * RHS
Value * LHS
BinaryOperator * Mul
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
Definition APInt.h:229
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
Definition APInt.h:209
bool isBigEndian() const
Definition DataLayout.h:199
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:214
size_t size() const
Definition Function.h:856
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition ArrayRef.h:303
Represents one node in the SelectionDAG.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
const SDValue & getRoot() const
Return the root tag of the SelectionDAG.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI bool LegalizeVectors()
This transforms the SelectionDAG into a SelectionDAG that only uses vector math operations supported ...
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false)
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI SDValue UnrollVectorOp(SDNode *N, unsigned ResNE=0)
Utility function used by legalize and lowering to "unroll" a vector operation by splitting out the sc...
LLVM_ABI SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
SDValue getInsertSubvector(const SDLoc &DL, SDValue Vec, SDValue SubVec, unsigned Idx)
Insert SubVec at the Idx element of Vec.
LLVM_ABI SDValue getStepVector(const SDLoc &DL, EVT ResVT, const APInt &StepVal)
Returns a vector of type ResVT whose elements contain the linear sequence <0, Step,...
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
const TargetLowering & getTargetLoweringInfo() const
LLVM_ABI std::pair< SDValue, SDValue > UnrollVectorOverflowOp(SDNode *N, unsigned ResNE=0)
Like UnrollVectorOp(), but for the [US](ADD|SUB|MUL)O family of opcodes.
allnodes_const_iterator allnodes_begin() const
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
allnodes_const_iterator allnodes_end() const
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI void RemoveDeadNodes()
This method deletes all unreachable nodes in the SelectionDAG.
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
LLVM_ABI SDValue getVPLogicalNOT(const SDLoc &DL, SDValue Val, SDValue Mask, SDValue EVL, EVT VT)
Create a vector-predicated logical NOT operation as (VP_XOR Val, BooleanOne, Mask,...
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
LLVM_ABI unsigned AssignTopologicalOrder()
Topological-sort the AllNodes list and a assign a unique node id for each node in the DAG based on th...
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
const TargetLibraryInfo & getLibInfo() const
LLVM_ABI SDValue getBoolConstant(bool V, const SDLoc &DL, EVT VT, EVT OpVT)
Create a true or false constant of type VT using the target's BooleanContent for type OpVT.
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI bool expandMultipleResultFPLibCall(RTLIB::Libcall LC, SDNode *Node, SmallVectorImpl< SDValue > &Results, std::optional< unsigned > CallRetResNo={})
Expands a node with multiple results to an FP or vector libcall.
LLVMContext * getContext() const
const SDValue & setRoot(SDValue N)
Set the current root tag of the SelectionDAG.
LLVM_ABI SDNode * UpdateNodeOperands(SDNode *N, SDValue Op)
Mutate the specified node in-place to have the specified operands.
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
SDValue getSplat(EVT VT, const SDLoc &DL, SDValue Op)
Returns a node representing a splat of one value into all lanes of the provided vector type.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
LLVM_ABI SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a logical NOT operation as (XOR Val, BooleanOne).
ilist< SDNode >::iterator allnodes_iterator
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void resize(size_type N)
void push_back(const T &Elt)
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition StringRef.h:148
const VecDesc * getVectorMappingInfo(StringRef F, const ElementCount &VF, bool Masked) const
virtual bool isShuffleMaskLegal(ArrayRef< int >, EVT) const
Targets can use this to indicate that they only support some VECTOR_SHUFFLE operations,...
LegalizeAction getCondCodeAction(ISD::CondCode CC, MVT VT) const
Return how the condition code should be treated: either it is legal, needs to be expanded to some oth...
LegalizeAction getFixedPointOperationAction(unsigned Op, EVT VT, unsigned Scale) const
Some fixed point operations may be natively supported by the target but only for specific scales.
bool isStrictFPEnabled() const
Return true if the target support strict float operation.
virtual EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const
Return the ValueType of the result of SETCC operations.
BooleanContent getBooleanContents(bool isVec, bool isFloat) const
For targets without i1 registers, this gives the nature of the high-bits of boolean values held in ty...
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
LegalizeAction getTruncStoreAction(EVT ValVT, EVT MemVT) const
Return how this store with truncation should be treated: either it is legal, needs to be promoted to ...
LegalizeAction getLoadExtAction(unsigned ExtType, EVT ValVT, EVT MemVT) const
Return how this load with extension should be treated: either it is legal, needs to be promoted to a ...
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
LegalizeAction getPartialReduceMLAAction(unsigned Opc, EVT AccVT, EVT InputVT) const
Return how a PARTIAL_REDUCE_U/SMLA node with Acc type AccVT and Input type InputVT should be treated.
LegalizeAction getStrictFPOperationAction(unsigned Op, EVT VT) const
const char * getLibcallName(RTLIB::Libcall Call) const
Get the libcall routine name for the specified libcall.
LegalizeAction getOperationAction(unsigned Op, EVT VT) const
Return how this operation should be treated: either it is legal, needs to be promoted to a larger siz...
MVT getTypeToPromoteTo(unsigned Op, MVT VT) const
If the action for this operation is to promote, this method returns the ValueType to promote to.
bool isOperationLegalOrCustomOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
SDValue expandAddSubSat(SDNode *Node, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::[US][ADD|SUB]SAT.
SDValue expandVPCTLZ(SDNode *N, SelectionDAG &DAG) const
Expand VP_CTLZ/VP_CTLZ_ZERO_UNDEF nodes.
bool expandMULO(SDNode *Node, SDValue &Result, SDValue &Overflow, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::[US]MULO.
SDValue scalarizeVectorStore(StoreSDNode *ST, SelectionDAG &DAG) const
SDValue expandVPBSWAP(SDNode *N, SelectionDAG &DAG) const
Expand VP_BSWAP nodes.
SDValue expandVecReduceSeq(SDNode *Node, SelectionDAG &DAG) const
Expand a VECREDUCE_SEQ_* into an explicit ordered calculation.
SDValue expandCTLZ(SDNode *N, SelectionDAG &DAG) const
Expand CTLZ/CTLZ_ZERO_UNDEF nodes.
SDValue expandBITREVERSE(SDNode *N, SelectionDAG &DAG) const
Expand BITREVERSE nodes.
SDValue expandCTTZ(SDNode *N, SelectionDAG &DAG) const
Expand CTTZ/CTTZ_ZERO_UNDEF nodes.
SDValue expandABD(SDNode *N, SelectionDAG &DAG) const
Expand ABDS/ABDU nodes.
SDValue expandShlSat(SDNode *Node, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::[US]SHLSAT.
SDValue expandFP_TO_INT_SAT(SDNode *N, SelectionDAG &DAG) const
Expand FP_TO_[US]INT_SAT into FP_TO_[US]INT and selects or min/max.
void expandSADDSUBO(SDNode *Node, SDValue &Result, SDValue &Overflow, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::S(ADD|SUB)O.
SDValue expandVPBITREVERSE(SDNode *N, SelectionDAG &DAG) const
Expand VP_BITREVERSE nodes.
SDValue expandABS(SDNode *N, SelectionDAG &DAG, bool IsNegative=false) const
Expand ABS nodes.
SDValue expandVecReduce(SDNode *Node, SelectionDAG &DAG) const
Expand a VECREDUCE_* into an explicit calculation.
bool expandFP_TO_UINT(SDNode *N, SDValue &Result, SDValue &Chain, SelectionDAG &DAG) const
Expand float to UINT conversion.
bool expandREM(SDNode *Node, SDValue &Result, SelectionDAG &DAG) const
Expand an SREM or UREM using SDIV/UDIV or SDIVREM/UDIVREM, if legal.
SDValue expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *N, SelectionDAG &DAG) const
Expand fminimumnum/fmaximumnum into multiple comparison with selects.
SDValue expandCTPOP(SDNode *N, SelectionDAG &DAG) const
Expand CTPOP nodes.
SDValue expandVectorNaryOpBySplitting(SDNode *Node, SelectionDAG &DAG) const
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
SDValue expandBSWAP(SDNode *N, SelectionDAG &DAG) const
Expand BSWAP nodes.
SDValue expandFMINIMUM_FMAXIMUM(SDNode *N, SelectionDAG &DAG) const
Expand fminimum/fmaximum into multiple comparison with selects.
std::pair< SDValue, SDValue > scalarizeVectorLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Turn load of vector type into a load of the individual elements.
SDValue expandFunnelShift(SDNode *N, SelectionDAG &DAG) const
Expand funnel shift.
bool LegalizeSetCCCondCode(SelectionDAG &DAG, EVT VT, SDValue &LHS, SDValue &RHS, SDValue &CC, SDValue Mask, SDValue EVL, bool &NeedInvert, const SDLoc &dl, SDValue &Chain, bool IsSignaling=false) const
Legalize a SETCC or VP_SETCC with given LHS and RHS and condition code CC on the current target.
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const
This callback is invoked for operations that are unsupported by the target, which are registered to u...
SDValue expandVPCTPOP(SDNode *N, SelectionDAG &DAG) const
Expand VP_CTPOP nodes.
SDValue expandFixedPointDiv(unsigned Opcode, const SDLoc &dl, SDValue LHS, SDValue RHS, unsigned Scale, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::[US]DIVFIX[SAT].
SDValue expandVPCTTZ(SDNode *N, SelectionDAG &DAG) const
Expand VP_CTTZ/VP_CTTZ_ZERO_UNDEF nodes.
SDValue expandVECTOR_COMPRESS(SDNode *Node, SelectionDAG &DAG) const
Expand a vector VECTOR_COMPRESS into a sequence of extract element, store temporarily,...
SDValue expandROT(SDNode *N, bool AllowVectorOps, SelectionDAG &DAG) const
Expand rotations.
SDValue expandFMINNUM_FMAXNUM(SDNode *N, SelectionDAG &DAG) const
Expand fminnum/fmaxnum into fminnum_ieee/fmaxnum_ieee with quieted inputs.
SDValue expandCMP(SDNode *Node, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::[US]CMP.
SDValue expandFixedPointMul(SDNode *Node, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::[U|S]MULFIX[SAT].
SDValue expandIntMINMAX(SDNode *Node, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::[US][MIN|MAX].
SDValue expandVectorFindLastActive(SDNode *N, SelectionDAG &DAG) const
Expand VECTOR_FIND_LAST_ACTIVE nodes.
SDValue expandPartialReduceMLA(SDNode *Node, SelectionDAG &DAG) const
Expands PARTIAL_REDUCE_S/UMLA nodes to a series of simpler operations, consisting of zext/sext,...
void expandUADDSUBO(SDNode *Node, SDValue &Result, SDValue &Overflow, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::U(ADD|SUB)O.
bool expandUINT_TO_FP(SDNode *N, SDValue &Result, SDValue &Chain, SelectionDAG &DAG) const
Expand UINT(i64) to double(f64) conversion.
SDValue expandAVG(SDNode *N, SelectionDAG &DAG) const
Expand vector/scalar AVGCEILS/AVGCEILU/AVGFLOORS/AVGFLOORU nodes.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition Type.h:352
bool isMasked() const
LLVM_ABI std::string getVectorFunctionABIVariantString() const
Returns a vector function ABI variant string on the form: ZGV<isa><mask><vlen><vparams><scalarname>(<...
StringRef getVectorFnName() const
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
Definition ISDOpcodes.h:801
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
Definition ISDOpcodes.h:256
@ CTLZ_ZERO_UNDEF
Definition ISDOpcodes.h:774
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
Definition ISDOpcodes.h:504
@ LOOP_DEPENDENCE_RAW_MASK
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
Definition ISDOpcodes.h:270
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:765
@ SMULFIX
RESULT = [US]MULFIX(LHS, RHS, SCALE) - Perform fixed point multiplication on 2 integers with the same...
Definition ISDOpcodes.h:387
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:259
@ SMULFIXSAT
Same as the corresponding unsaturated fixed point instructions, but the result is clamped between the...
Definition ISDOpcodes.h:393
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition ISDOpcodes.h:835
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
Definition ISDOpcodes.h:511
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Definition ISDOpcodes.h:862
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:410
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
Definition ISDOpcodes.h:738
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
Definition ISDOpcodes.h:892
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
Definition ISDOpcodes.h:275
@ FPTRUNC_ROUND
FPTRUNC_ROUND - This corresponds to the fptrunc_round intrinsic.
Definition ISDOpcodes.h:508
@ SDIVFIX
RESULT = [US]DIVFIX(LHS, RHS, SCALE) - Perform fixed point division on 2 integers with the same width...
Definition ISDOpcodes.h:400
@ STRICT_FSQRT
Constrained versions of libm-equivalent floating point intrinsics.
Definition ISDOpcodes.h:431
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:826
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
Definition ISDOpcodes.h:706
@ STRICT_UINT_TO_FP
Definition ISDOpcodes.h:478
@ CTTZ_ZERO_UNDEF
Bit counting operators with an undefined result for zero inputs.
Definition ISDOpcodes.h:773
@ SSUBO
Same for subtraction.
Definition ISDOpcodes.h:347
@ STEP_VECTOR
STEP_VECTOR(IMM) - Returns a scalable vector whose lanes are comprised of a linear sequence of unsign...
Definition ISDOpcodes.h:682
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
Definition ISDOpcodes.h:528
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
Definition ISDOpcodes.h:369
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:778
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
Definition ISDOpcodes.h:663
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
Definition ISDOpcodes.h:343
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition ISDOpcodes.h:695
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:756
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:563
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:832
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:793
@ SSHLSAT
RESULT = [US]SHLSAT(LHS, RHS) - Perform saturation left shift.
Definition ISDOpcodes.h:379
@ SMULO
Same for multiplication.
Definition ISDOpcodes.h:351
@ ANY_EXTEND_VECTOR_INREG
ANY_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register any-extension of the low la...
Definition ISDOpcodes.h:881
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition ISDOpcodes.h:870
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:718
@ SDIVFIXSAT
Same as the corresponding unsaturated fixed point instructions, but the result is clamped between the...
Definition ISDOpcodes.h:406
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition ISDOpcodes.h:787
@ STRICT_SINT_TO_FP
STRICT_[US]INT_TO_FP - Convert a signed or unsigned integer to a floating point value.
Definition ISDOpcodes.h:477
@ STRICT_FP_TO_UINT
Definition ISDOpcodes.h:471
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
Definition ISDOpcodes.h:493
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:470
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:908
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:498
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:730
@ SCMP
[US]CMP - 3-way comparison of signed or unsigned integers.
Definition ISDOpcodes.h:726
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
Definition ISDOpcodes.h:701
@ STRICT_FADD
Constrained versions of the binary floating point operators.
Definition ISDOpcodes.h:420
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition ISDOpcodes.h:53
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
Definition ISDOpcodes.h:941
@ VECTOR_COMPRESS
VECTOR_COMPRESS(Vec, Mask, Passthru) consecutively place vector elements based on mask e....
Definition ISDOpcodes.h:690
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
Definition ISDOpcodes.h:903
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
Definition ISDOpcodes.h:927
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:838
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
Definition ISDOpcodes.h:62
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
Definition ISDOpcodes.h:521
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
Definition ISDOpcodes.h:360
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
Definition ISDOpcodes.h:713
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition ISDOpcodes.h:543
@ LOOP_DEPENDENCE_WAR_MASK
Set rounding mode.
LLVM_ABI std::optional< unsigned > getVPMaskIdx(unsigned Opcode)
The operand position of the vector mask.
LLVM_ABI std::optional< unsigned > getVPExplicitVectorLengthIdx(unsigned Opcode)
The operand position of the explicit vector length parameter.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
LLVM_ABI bool isVPOpcode(unsigned Opcode)
Whether this is a vector-predicated Opcode.
LLVM_ABI Libcall getSINCOSPI(EVT RetVT)
getSINCOSPI - Return the SINCOSPI_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getMODF(EVT RetVT)
getMODF - Return the MODF_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPLibCall(EVT VT, Libcall Call_F32, Libcall Call_F64, Libcall Call_F80, Libcall Call_F128, Libcall Call_PPCF128)
GetFPLibCall - Helper to return the right libcall for the given floating point type,...
LLVM_ABI Libcall getSINCOS(EVT RetVT)
getSINCOS - Return the SINCOS_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI std::optional< VFInfo > tryDemangleForVFABI(StringRef MangledName, const FunctionType *FTy)
Function to construct a VFInfo out of a mangled names in the following format:
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:381
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1734
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
@ Xor
Bitwise or logical XOR of integers.
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:565
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition Sequence.h:305
#define N
Extended Value Type.
Definition ValueTypes.h:35
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
Definition ValueTypes.h:94
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
Definition ValueTypes.h:74
ElementCount getVectorElementCount() const
Definition ValueTypes.h:345
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:368
EVT changeElementType(EVT EltVT) const
Return a VT for a type whose attributes match ourselves with the exception of the element type that i...
Definition ValueTypes.h:113
uint64_t getScalarSizeInBits() const
Definition ValueTypes.h:380
bool isFixedLengthVector() const
Definition ValueTypes.h:181
bool isVector() const
Return true if this is a vector value type.
Definition ValueTypes.h:168
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
Definition ValueTypes.h:318
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
Definition ValueTypes.h:174
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition ValueTypes.h:323
EVT changeVectorElementType(EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
Definition ValueTypes.h:102
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Definition ValueTypes.h:331
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
Definition ValueTypes.h:303