LLVM 24.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"
40#include "llvm/IR/DataLayout.h"
43#include "llvm/Support/Debug.h"
45#include <cassert>
46#include <cstdint>
47#include <iterator>
48#include <utility>
49
50using namespace llvm;
51
52#define DEBUG_TYPE "legalizevectorops"
53
54namespace {
55
56class VectorLegalizer {
57 SelectionDAG& DAG;
58 const TargetLowering &TLI;
59 bool Changed = false; // Keep track of whether anything changed
60
61 /// For nodes that are of legal width, and that have more than one use, this
62 /// map indicates what regularized operand to use. This allows us to avoid
63 /// legalizing the same thing more than once.
65
66 /// Adds a node to the translation cache.
67 void AddLegalizedOperand(SDValue From, SDValue To) {
68 LegalizedNodes.insert(std::make_pair(From, To));
69 // If someone requests legalization of the new node, return itself.
70 if (From != To)
71 LegalizedNodes.insert(std::make_pair(To, To));
72 }
73
74 /// Legalizes the given node.
75 SDValue LegalizeOp(SDValue Op);
76
77 /// Assuming the node is legal, "legalize" the results.
78 SDValue TranslateLegalizeResults(SDValue Op, SDNode *Result);
79
80 /// Make sure Results are legal and update the translation cache.
81 SDValue RecursivelyLegalizeResults(SDValue Op,
83
84 /// Wrapper to interface LowerOperation with a vector of Results.
85 /// Returns false if the target wants to use default expansion. Otherwise
86 /// returns true. If return is true and the Results are empty, then the
87 /// target wants to keep the input node as is.
88 bool LowerOperationWrapper(SDNode *N, SmallVectorImpl<SDValue> &Results);
89
90 /// Implements unrolling a VSETCC.
91 SDValue UnrollVSETCC(SDNode *Node);
92
93 /// Implement expand-based legalization of vector operations.
94 ///
95 /// This is just a high-level routine to dispatch to specific code paths for
96 /// operations to legalize them.
98
99 /// Implements expansion for FP_TO_UINT; falls back to UnrollVectorOp if
100 /// FP_TO_SINT isn't legal.
101 void ExpandFP_TO_UINT(SDNode *Node, SmallVectorImpl<SDValue> &Results);
102
103 /// Implements expansion for UINT_TO_FLOAT; falls back to UnrollVectorOp if
104 /// SINT_TO_FLOAT and SHR on vectors isn't legal.
105 void ExpandUINT_TO_FLOAT(SDNode *Node, SmallVectorImpl<SDValue> &Results);
106
107 /// Implement expansion for SIGN_EXTEND_INREG using SRL and SRA.
108 SDValue ExpandSEXTINREG(SDNode *Node);
109
110 /// Implement expansion for ANY_EXTEND_VECTOR_INREG.
111 ///
112 /// Shuffles the low lanes of the operand into place and bitcasts to the proper
113 /// type. The contents of the bits in the extended part of each element are
114 /// undef.
115 SDValue ExpandANY_EXTEND_VECTOR_INREG(SDNode *Node);
116
117 /// Implement expansion for SIGN_EXTEND_VECTOR_INREG.
118 ///
119 /// Shuffles the low lanes of the operand into place, bitcasts to the proper
120 /// type, then shifts left and arithmetic shifts right to introduce a sign
121 /// extension.
122 SDValue ExpandSIGN_EXTEND_VECTOR_INREG(SDNode *Node);
123
124 /// Implement expansion for ZERO_EXTEND_VECTOR_INREG.
125 ///
126 /// Shuffles the low lanes of the operand into place and blends zeros into
127 /// the remaining lanes, finally bitcasting to the proper type.
128 SDValue ExpandZERO_EXTEND_VECTOR_INREG(SDNode *Node);
129
130 /// Expand bswap of vectors into a shuffle if legal.
131 SDValue ExpandBSWAP(SDNode *Node);
132
133 /// Implement vselect in terms of XOR, AND, OR when blend is not
134 /// supported by the target.
135 SDValue ExpandVSELECT(SDNode *Node);
136 SDValue ExpandVP_MERGE(SDNode *Node);
137 SDValue ExpandVP_REM(SDNode *Node);
138 SDValue ExpandLOOP_DEPENDENCE_MASK(SDNode *N);
139 SDValue ExpandMASK_BEFOREFIRST(SDNode *N);
140 SDValue ExpandMaskedBinOp(SDNode *N);
141 SDValue ExpandSELECT(SDNode *Node);
142 std::pair<SDValue, SDValue> ExpandLoad(SDNode *N);
143 SDValue ExpandStore(SDNode *N);
144 SDValue ExpandFNEG(SDNode *Node);
145 SDValue ExpandFABS(SDNode *Node);
146 SDValue ExpandFCOPYSIGN(SDNode *Node);
147 void ExpandFSUB(SDNode *Node, SmallVectorImpl<SDValue> &Results);
148 void ExpandSETCC(SDNode *Node, SmallVectorImpl<SDValue> &Results);
149 SDValue ExpandBITREVERSE(SDNode *Node);
150 void ExpandUADDSUBO(SDNode *Node, SmallVectorImpl<SDValue> &Results);
151 void ExpandSADDSUBO(SDNode *Node, SmallVectorImpl<SDValue> &Results);
152 void ExpandMULO(SDNode *Node, SmallVectorImpl<SDValue> &Results);
153 void ExpandFixedPointDiv(SDNode *Node, SmallVectorImpl<SDValue> &Results);
154 void ExpandStrictFPOp(SDNode *Node, SmallVectorImpl<SDValue> &Results);
155 void ExpandREM(SDNode *Node, SmallVectorImpl<SDValue> &Results);
156
157 bool tryExpandVecMathCall(SDNode *Node,
158 function_ref<RTLIB::Libcall(EVT)> GetLibcall,
160
161 void UnrollStrictFPOp(SDNode *Node, SmallVectorImpl<SDValue> &Results);
162
163 /// Implements vector promotion.
164 ///
165 /// This is essentially just bitcasting the operands to a different type and
166 /// bitcasting the result back to the original type.
168
169 /// Implements [SU]INT_TO_FP vector promotion.
170 ///
171 /// This is a [zs]ext of the input operand to a larger integer type.
172 void PromoteINT_TO_FP(SDNode *Node, SmallVectorImpl<SDValue> &Results);
173
174 /// Implements FP_TO_[SU]INT vector promotion of the result type.
175 ///
176 /// It is promoted to a larger integer type. The result is then
177 /// truncated back to the original type.
178 void PromoteFP_TO_INT(SDNode *Node, SmallVectorImpl<SDValue> &Results);
179
180 /// Implements vector setcc operation promotion.
181 ///
182 /// All vector operands are promoted to a vector type with larger element
183 /// type.
184 void PromoteSETCC(SDNode *Node, SmallVectorImpl<SDValue> &Results);
185
186 void PromoteSTRICT(SDNode *Node, SmallVectorImpl<SDValue> &Results);
187
188 /// Calculate the reduction using a type of higher precision and round the
189 /// result to match the original type. Setting NonArithmetic signifies the
190 /// rounding of the result does not affect its value.
191 void PromoteFloatVECREDUCE(SDNode *Node, SmallVectorImpl<SDValue> &Results,
192 bool NonArithmetic);
193
194 void PromoteVECTOR_COMPRESS(SDNode *Node, SmallVectorImpl<SDValue> &Results);
195
196public:
197 VectorLegalizer(SelectionDAG& dag) :
198 DAG(dag), TLI(dag.getTargetLoweringInfo()) {}
199
200 /// Begin legalizer the vector operations in the DAG.
201 bool Run();
202};
203
204} // end anonymous namespace
205
206bool VectorLegalizer::Run() {
207 // Before we start legalizing vector nodes, check if there are any vectors.
208 bool HasVectors = false;
210 E = std::prev(DAG.allnodes_end()); I != std::next(E); ++I) {
211 // Check if the values of the nodes contain vectors. We don't need to check
212 // the operands because we are going to check their values at some point.
213 HasVectors = llvm::any_of(I->values(), [](EVT T) { return T.isVector(); });
214
215 // If we found a vector node we can start the legalization.
216 if (HasVectors)
217 break;
218 }
219
220 // If this basic block has no vectors then no need to legalize vectors.
221 if (!HasVectors)
222 return false;
223
224 // The legalize process is inherently a bottom-up recursive process (users
225 // legalize their uses before themselves). Given infinite stack space, we
226 // could just start legalizing on the root and traverse the whole graph. In
227 // practice however, this causes us to run out of stack space on large basic
228 // blocks. To avoid this problem, compute an ordering of the nodes where each
229 // node is only legalized after all of its operands are legalized.
232 E = std::prev(DAG.allnodes_end()); I != std::next(E); ++I)
233 LegalizeOp(SDValue(&*I, 0));
234
235 // Finally, it's possible the root changed. Get the new root.
236 SDValue OldRoot = DAG.getRoot();
237 assert(LegalizedNodes.count(OldRoot) && "Root didn't get legalized?");
238 DAG.setRoot(LegalizedNodes[OldRoot]);
239
240 LegalizedNodes.clear();
241
242 // Remove dead nodes now.
243 DAG.RemoveDeadNodes();
244
245 return Changed;
246}
247
248SDValue VectorLegalizer::TranslateLegalizeResults(SDValue Op, SDNode *Result) {
249 assert(Op->getNumValues() == Result->getNumValues() &&
250 "Unexpected number of results");
251 // Generic legalization: just pass the operand through.
252 for (unsigned i = 0, e = Op->getNumValues(); i != e; ++i)
253 AddLegalizedOperand(Op.getValue(i), SDValue(Result, i));
254 return SDValue(Result, Op.getResNo());
255}
256
257SDValue
258VectorLegalizer::RecursivelyLegalizeResults(SDValue Op,
260 assert(Results.size() == Op->getNumValues() &&
261 "Unexpected number of results");
262 // Make sure that the generated code is itself legal.
263 for (unsigned i = 0, e = Results.size(); i != e; ++i) {
264 Results[i] = LegalizeOp(Results[i]);
265 AddLegalizedOperand(Op.getValue(i), Results[i]);
266 }
267
268 return Results[Op.getResNo()];
269}
270
271SDValue VectorLegalizer::LegalizeOp(SDValue Op) {
272 // Note that LegalizeOp may be reentered even from single-use nodes, which
273 // means that we always must cache transformed nodes.
274 auto I = LegalizedNodes.find(Op);
275 if (I != LegalizedNodes.end()) return I->second;
276
277 // Legalize the operands
279 for (const SDValue &Oper : Op->op_values())
280 Ops.push_back(LegalizeOp(Oper));
281
282 SDNode *Node = DAG.UpdateNodeOperands(Op.getNode(), Ops);
283
284 bool HasVectorValueOrOp =
285 llvm::any_of(Node->values(), [](EVT T) { return T.isVector(); }) ||
286 llvm::any_of(Node->op_values(),
287 [](SDValue O) { return O.getValueType().isVector(); });
288 if (!HasVectorValueOrOp)
289 return TranslateLegalizeResults(Op, Node);
290
291 TargetLowering::LegalizeAction Action = TargetLowering::Legal;
292 EVT ValVT;
293 switch (Op.getOpcode()) {
294 default:
295 return TranslateLegalizeResults(Op, Node);
296 case ISD::LOAD: {
297 LoadSDNode *LD = cast<LoadSDNode>(Node);
298 ISD::LoadExtType ExtType = LD->getExtensionType();
299 EVT LoadedVT = LD->getMemoryVT();
300 if (LoadedVT.isVector() && ExtType != ISD::NON_EXTLOAD)
301 Action = TLI.getLoadAction(LD->getValueType(0), LoadedVT, LD->getAlign(),
302 LD->getAddressSpace(), ExtType, false);
303 break;
304 }
305 case ISD::STORE: {
306 StoreSDNode *ST = cast<StoreSDNode>(Node);
307 EVT StVT = ST->getMemoryVT();
308 MVT ValVT = ST->getValue().getSimpleValueType();
309 if (StVT.isVector() && ST->isTruncatingStore())
310 Action = TLI.getTruncStoreAction(ValVT, StVT, ST->getAlign(),
311 ST->getAddressSpace());
312 break;
313 }
315 Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
316 // This operation lies about being legal: when it claims to be legal,
317 // it should actually be expanded.
318 if (Action == TargetLowering::Legal)
319 Action = TargetLowering::Expand;
320 break;
321#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
322 case ISD::STRICT_##DAGN:
323#include "llvm/IR/ConstrainedOps.def"
324 ValVT = Node->getValueType(0);
325 if (Op.getOpcode() == ISD::STRICT_SINT_TO_FP ||
326 Op.getOpcode() == ISD::STRICT_UINT_TO_FP)
327 ValVT = Node->getOperand(1).getValueType();
328 if (Op.getOpcode() == ISD::STRICT_FSETCC ||
329 Op.getOpcode() == ISD::STRICT_FSETCCS) {
330 MVT OpVT = Node->getOperand(1).getSimpleValueType();
331 ISD::CondCode CCCode = cast<CondCodeSDNode>(Node->getOperand(3))->get();
332 Action = TLI.getCondCodeAction(CCCode, OpVT);
333 if (Action == TargetLowering::Legal)
334 Action = TLI.getOperationAction(Node->getOpcode(), OpVT);
335 } else {
336 Action = TLI.getOperationAction(Node->getOpcode(), ValVT);
337 }
338 // If we're asked to expand a strict vector floating-point operation,
339 // by default we're going to simply unroll it. That is usually the
340 // best approach, except in the case where the resulting strict (scalar)
341 // operations would themselves use the fallback mutation to non-strict.
342 // In that specific case, just do the fallback on the vector op.
343 if (Action == TargetLowering::Expand && !TLI.isStrictFPEnabled() &&
344 TLI.getStrictFPOperationAction(Node->getOpcode(), ValVT) ==
345 TargetLowering::Legal) {
346 EVT EltVT = ValVT.getVectorElementType();
347 if (TLI.getOperationAction(Node->getOpcode(), EltVT)
348 == TargetLowering::Expand &&
349 TLI.getStrictFPOperationAction(Node->getOpcode(), EltVT)
350 == TargetLowering::Legal)
351 Action = TargetLowering::Legal;
352 }
353 break;
354 case ISD::ADD:
355 case ISD::SUB:
356 case ISD::MUL:
357 case ISD::MULHS:
358 case ISD::MULHU:
359 case ISD::SDIV:
360 case ISD::UDIV:
361 case ISD::SREM:
362 case ISD::UREM:
363 case ISD::SDIVREM:
364 case ISD::UDIVREM:
365 case ISD::FADD:
366 case ISD::FSUB:
367 case ISD::FMUL:
368 case ISD::FDIV:
369 case ISD::FREM:
370 case ISD::AND:
371 case ISD::OR:
372 case ISD::XOR:
373 case ISD::SHL:
374 case ISD::SRA:
375 case ISD::SRL:
376 case ISD::FSHL:
377 case ISD::FSHR:
378 case ISD::ROTL:
379 case ISD::ROTR:
380 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:
390 case ISD::BSWAP:
391 case ISD::BITREVERSE:
392 case ISD::CTLZ:
393 case ISD::CTTZ:
396 case ISD::CTPOP:
397 case ISD::CLMUL:
398 case ISD::CLMULH:
399 case ISD::CLMULR:
400 case ISD::SELECT:
401 case ISD::VSELECT:
402 case ISD::SELECT_CC:
403 case ISD::ZERO_EXTEND:
404 case ISD::ANY_EXTEND:
405 case ISD::TRUNCATE:
406 case ISD::SIGN_EXTEND:
407 case ISD::FP_TO_SINT:
408 case ISD::FP_TO_UINT:
409 case ISD::FNEG:
410 case ISD::FABS:
411 case ISD::FMINNUM:
412 case ISD::FMAXNUM:
415 case ISD::FMINIMUM:
416 case ISD::FMAXIMUM:
417 case ISD::FMINIMUMNUM:
418 case ISD::FMAXIMUMNUM:
419 case ISD::FCOPYSIGN:
420 case ISD::FSQRT:
421 case ISD::FSIN:
422 case ISD::FCOS:
423 case ISD::FTAN:
424 case ISD::FASIN:
425 case ISD::FACOS:
426 case ISD::FATAN:
427 case ISD::FATAN2:
428 case ISD::FSINH:
429 case ISD::FCOSH:
430 case ISD::FTANH:
431 case ISD::FLDEXP:
432 case ISD::FPOWI:
433 case ISD::FPOW:
434 case ISD::FCBRT:
435 case ISD::FLOG:
436 case ISD::FLOG2:
437 case ISD::FLOG10:
438 case ISD::FEXP:
439 case ISD::FEXP2:
440 case ISD::FEXP10:
441 case ISD::FCEIL:
442 case ISD::FTRUNC:
443 case ISD::FRINT:
444 case ISD::FNEARBYINT:
445 case ISD::FROUND:
446 case ISD::FROUNDEVEN:
447 case ISD::FFLOOR:
448 case ISD::FP_ROUND:
449 case ISD::FP_EXTEND:
451 case ISD::FMA:
456 case ISD::SMIN:
457 case ISD::SMAX:
458 case ISD::UMIN:
459 case ISD::UMAX:
460 case ISD::SMUL_LOHI:
461 case ISD::UMUL_LOHI:
462 case ISD::SADDO:
463 case ISD::UADDO:
464 case ISD::SSUBO:
465 case ISD::USUBO:
466 case ISD::SMULO:
467 case ISD::UMULO:
471 case ISD::FFREXP:
472 case ISD::FMODF:
473 case ISD::FSINCOS:
474 case ISD::FSINCOSPI:
475 case ISD::SADDSAT:
476 case ISD::UADDSAT:
477 case ISD::SSUBSAT:
478 case ISD::USUBSAT:
479 case ISD::SSHLSAT:
480 case ISD::USHLSAT:
483 case ISD::MGATHER:
485 case ISD::SCMP:
486 case ISD::UCMP:
491 case ISD::MASKED_UDIV:
492 case ISD::MASKED_SDIV:
493 case ISD::MASKED_UREM:
494 case ISD::MASKED_SREM:
496 Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
497 break;
500 EVT VT = Node->getValueType(0);
501 unsigned Factor = Node->getNumOperands();
502 Action = TLI.getVectorInterleaveAction(Node->getOpcode(), Factor, VT);
503 // Early Custom Lowering causes RISC-V regressions.
504 if (Action == TargetLowering::Custom &&
505 (VT.isScalableVector() || Factor != 2)) {
506 Action = TargetLowering::Legal;
507 }
508 break;
509 }
510 case ISD::SMULFIX:
511 case ISD::SMULFIXSAT:
512 case ISD::UMULFIX:
513 case ISD::UMULFIXSAT:
514 case ISD::SDIVFIX:
515 case ISD::SDIVFIXSAT:
516 case ISD::UDIVFIX:
517 case ISD::UDIVFIXSAT: {
518 unsigned Scale = Node->getConstantOperandVal(2);
519 Action = TLI.getFixedPointOperationAction(Node->getOpcode(),
520 Node->getValueType(0), Scale);
521 break;
522 }
523 case ISD::LROUND:
524 case ISD::LLROUND:
525 case ISD::LRINT:
526 case ISD::LLRINT:
527 case ISD::SINT_TO_FP:
528 case ISD::UINT_TO_FP:
546 case ISD::CTTZ_ELTS:
549 Action = TLI.getOperationAction(Node->getOpcode(),
550 Node->getOperand(0).getValueType());
551 break;
554 Action = TLI.getOperationAction(Node->getOpcode(),
555 Node->getOperand(1).getValueType());
556 break;
557 case ISD::SETCC: {
558 MVT OpVT = Node->getOperand(0).getSimpleValueType();
559 ISD::CondCode CCCode = cast<CondCodeSDNode>(Node->getOperand(2))->get();
560 Action = TLI.getCondCodeAction(CCCode, OpVT);
561 if (Action == TargetLowering::Legal)
562 Action = TLI.getOperationAction(Node->getOpcode(), OpVT);
563 break;
564 }
569 Action =
570 TLI.getPartialReduceMLAAction(Op.getOpcode(), Node->getValueType(0),
571 Node->getOperand(1).getValueType());
572 break;
573
574#define BEGIN_REGISTER_VP_SDNODE(VPID, LEGALPOS, ...) \
575 case ISD::VPID: { \
576 EVT LegalizeVT = LEGALPOS < 0 ? Node->getValueType(-(1 + LEGALPOS)) \
577 : Node->getOperand(LEGALPOS).getValueType(); \
578 /* Defer non-vector results to LegalizeDAG. */ \
579 if (!Node->getValueType(0).isVector() && \
580 Node->getValueType(0) != MVT::Other) { \
581 Action = TargetLowering::Legal; \
582 break; \
583 } \
584 Action = TLI.getOperationAction(Node->getOpcode(), LegalizeVT); \
585 } break;
586#include "llvm/IR/VPIntrinsics.def"
587 }
588
589 LLVM_DEBUG(dbgs() << "\nLegalizing vector op: "; Node->dump(&DAG));
590
591 SmallVector<SDValue, 8> ResultVals;
592 switch (Action) {
593 default: llvm_unreachable("This action is not supported yet!");
594 case TargetLowering::Promote:
595 assert((Op.getOpcode() != ISD::LOAD && Op.getOpcode() != ISD::STORE) &&
596 "This action is not supported yet!");
597 LLVM_DEBUG(dbgs() << "Promoting\n");
598 Promote(Node, ResultVals);
599 assert(!ResultVals.empty() && "No results for promotion?");
600 break;
601 case TargetLowering::Legal:
602 LLVM_DEBUG(dbgs() << "Legal node: nothing to do\n");
603 break;
604 case TargetLowering::Custom:
605 LLVM_DEBUG(dbgs() << "Trying custom legalization\n");
606 if (LowerOperationWrapper(Node, ResultVals))
607 break;
608 LLVM_DEBUG(dbgs() << "Could not custom legalize node\n");
609 [[fallthrough]];
610 case TargetLowering::Expand:
611 LLVM_DEBUG(dbgs() << "Expanding\n");
612 Expand(Node, ResultVals);
613 break;
614 }
615
616 if (ResultVals.empty())
617 return TranslateLegalizeResults(Op, Node);
618
619 Changed = true;
620 return RecursivelyLegalizeResults(Op, ResultVals);
621}
622
623// FIXME: This is very similar to TargetLowering::LowerOperationWrapper. Can we
624// merge them somehow?
625bool VectorLegalizer::LowerOperationWrapper(SDNode *Node,
626 SmallVectorImpl<SDValue> &Results) {
627 SDValue Res = TLI.LowerOperation(SDValue(Node, 0), DAG);
628
629 if (!Res.getNode())
630 return false;
631
632 if (Res == SDValue(Node, 0))
633 return true;
634
635 // If the original node has one result, take the return value from
636 // LowerOperation as is. It might not be result number 0.
637 if (Node->getNumValues() == 1) {
638 Results.push_back(Res);
639 return true;
640 }
641
642 // If the original node has multiple results, then the return node should
643 // have the same number of results.
644 assert((Node->getNumValues() == Res->getNumValues()) &&
645 "Lowering returned the wrong number of results!");
646
647 // Places new result values base on N result number.
648 for (unsigned I = 0, E = Node->getNumValues(); I != E; ++I)
649 Results.push_back(Res.getValue(I));
650
651 return true;
652}
653
654void VectorLegalizer::PromoteSETCC(SDNode *Node,
655 SmallVectorImpl<SDValue> &Results) {
656 MVT VecVT = Node->getOperand(0).getSimpleValueType();
657 MVT NewVecVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VecVT);
658
659 unsigned ExtOp = VecVT.isFloatingPoint() ? ISD::FP_EXTEND : ISD::ANY_EXTEND;
660
661 SDLoc DL(Node);
662 SmallVector<SDValue, 5> Operands(Node->getNumOperands());
663
664 Operands[0] = DAG.getNode(ExtOp, DL, NewVecVT, Node->getOperand(0));
665 Operands[1] = DAG.getNode(ExtOp, DL, NewVecVT, Node->getOperand(1));
666 Operands[2] = Node->getOperand(2);
667
668 EVT ResVT =
669 TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), NewVecVT);
670 SDValue Res =
671 DAG.getNode(Node->getOpcode(), DL, ResVT, Operands, Node->getFlags());
672 if (ResVT != Node->getValueType(0))
673 Res = DAG.getBoolExtOrTrunc(Res, DL, Node->getValueType(0), NewVecVT);
674 Results.push_back(Res);
675}
676
677void VectorLegalizer::PromoteSTRICT(SDNode *Node,
678 SmallVectorImpl<SDValue> &Results) {
679 MVT VecVT = Node->getOperand(1).getSimpleValueType();
680 MVT NewVecVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VecVT);
681
682 assert(VecVT.isFloatingPoint());
683
684 SDLoc DL(Node);
685 SmallVector<SDValue, 5> Operands(Node->getNumOperands());
687
688 for (unsigned j = 1; j != Node->getNumOperands(); ++j)
689 if (Node->getOperand(j).getValueType().isVector() &&
690 !(ISD::isVPOpcode(Node->getOpcode()) &&
691 ISD::getVPMaskIdx(Node->getOpcode()) == j)) // Skip mask operand.
692 {
693 // promote the vector operand.
694 SDValue Ext =
695 DAG.getNode(ISD::STRICT_FP_EXTEND, DL, {NewVecVT, MVT::Other},
696 {Node->getOperand(0), Node->getOperand(j)});
697 Operands[j] = Ext.getValue(0);
698 Chains.push_back(Ext.getValue(1));
699 } else
700 Operands[j] = Node->getOperand(j); // Skip no vector operand.
701
702 SDVTList VTs = DAG.getVTList(NewVecVT, Node->getValueType(1));
703
704 Operands[0] = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
705
706 SDValue Res =
707 DAG.getNode(Node->getOpcode(), DL, VTs, Operands, Node->getFlags());
708
709 SDValue Round =
710 DAG.getNode(ISD::STRICT_FP_ROUND, DL, {VecVT, MVT::Other},
711 {Res.getValue(1), Res.getValue(0),
712 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true)});
713
714 Results.push_back(Round.getValue(0));
715 Results.push_back(Round.getValue(1));
716}
717
718void VectorLegalizer::PromoteFloatVECREDUCE(SDNode *Node,
719 SmallVectorImpl<SDValue> &Results,
720 bool NonArithmetic) {
721 MVT OpVT = Node->getOperand(0).getSimpleValueType();
722 assert(OpVT.isFloatingPoint() && "Expected floating point reduction!");
723 MVT NewOpVT = TLI.getTypeToPromoteTo(Node->getOpcode(), OpVT);
724
725 SDLoc DL(Node);
726 SDValue NewOp = DAG.getNode(ISD::FP_EXTEND, DL, NewOpVT, Node->getOperand(0));
727 SDValue Rdx =
728 DAG.getNode(Node->getOpcode(), DL, NewOpVT.getVectorElementType(), NewOp,
729 Node->getFlags());
730 SDValue Res =
731 DAG.getNode(ISD::FP_ROUND, DL, Node->getValueType(0), Rdx,
732 DAG.getIntPtrConstant(NonArithmetic, DL, /*isTarget=*/true));
733 Results.push_back(Res);
734}
735
736void VectorLegalizer::PromoteVECTOR_COMPRESS(
737 SDNode *Node, SmallVectorImpl<SDValue> &Results) {
738 SDLoc DL(Node);
739 EVT VT = Node->getValueType(0);
740 MVT PromotedVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VT.getSimpleVT());
741 assert((VT.isInteger() || VT.getSizeInBits() == PromotedVT.getSizeInBits()) &&
742 "Only integer promotion or bitcasts between types is supported");
743
744 SDValue Vec = Node->getOperand(0);
745 SDValue Mask = Node->getOperand(1);
746 SDValue Passthru = Node->getOperand(2);
747 if (VT.isInteger()) {
748 Vec = DAG.getNode(ISD::ANY_EXTEND, DL, PromotedVT, Vec);
749 Mask = TLI.promoteTargetBoolean(DAG, Mask, PromotedVT);
750 Passthru = DAG.getNode(ISD::ANY_EXTEND, DL, PromotedVT, Passthru);
751 } else {
752 Vec = DAG.getBitcast(PromotedVT, Vec);
753 Passthru = DAG.getBitcast(PromotedVT, Passthru);
754 }
755
756 SDValue Result =
757 DAG.getNode(ISD::VECTOR_COMPRESS, DL, PromotedVT, Vec, Mask, Passthru);
758 Result = VT.isInteger() ? DAG.getNode(ISD::TRUNCATE, DL, VT, Result)
759 : DAG.getBitcast(VT, Result);
760 Results.push_back(Result);
761}
762
763void VectorLegalizer::Promote(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
764 // For a few operations there is a specific concept for promotion based on
765 // the operand's type.
766 switch (Node->getOpcode()) {
767 case ISD::SINT_TO_FP:
768 case ISD::UINT_TO_FP:
771 // "Promote" the operation by extending the operand.
772 PromoteINT_TO_FP(Node, Results);
773 return;
774 case ISD::FP_TO_UINT:
775 case ISD::FP_TO_SINT:
778 // Promote the operation by extending the operand.
779 PromoteFP_TO_INT(Node, Results);
780 return;
781 case ISD::SETCC:
782 // Promote the operation by extending the operand.
783 PromoteSETCC(Node, Results);
784 return;
785 case ISD::STRICT_FADD:
787 case ISD::STRICT_FDIV:
789 case ISD::STRICT_FMA:
794 case ISD::STRICT_FMUL:
800 case ISD::STRICT_FSUB:
802 PromoteSTRICT(Node, Results);
803 return;
806 PromoteFloatVECREDUCE(Node, Results, /*NonArithmetic=*/false);
807 return;
814 PromoteFloatVECREDUCE(Node, Results, /*NonArithmetic=*/true);
815 return;
817 PromoteVECTOR_COMPRESS(Node, Results);
818 return;
819
820 case ISD::FP_ROUND:
821 case ISD::FP_EXTEND:
822 // These operations are used to do promotion so they can't be promoted
823 // themselves.
824 llvm_unreachable("Don't know how to promote this operation!");
825 }
826
827 // There are currently two cases of vector promotion:
828 // 1) Bitcasting a vector of integers to a different type to a vector of the
829 // same overall length. For example, x86 promotes ISD::AND v2i32 to v1i64.
830 // 2) Extending a vector of floats to a vector of the same number of larger
831 // floats. For example, AArch64 promotes ISD::FADD on v4f16 to v4f32.
832 assert(Node->getNumValues() == 1 &&
833 "Can't promote a vector with multiple results!");
834 MVT VT = Node->getSimpleValueType(0);
835 MVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VT);
836 SDLoc dl(Node);
837 SmallVector<SDValue, 4> Operands(Node->getNumOperands());
838
839 for (unsigned j = 0; j != Node->getNumOperands(); ++j) {
840 // Do not promote the mask operand of a VP OP.
841 bool SkipPromote = ISD::isVPOpcode(Node->getOpcode()) &&
842 ISD::getVPMaskIdx(Node->getOpcode()) == j;
843 if (Node->getOperand(j).getValueType().isVector() && !SkipPromote)
844 if (Node->getOperand(j)
845 .getValueType()
846 .getVectorElementType()
847 .isFloatingPoint() &&
849 Operands[j] = DAG.getNode(ISD::FP_EXTEND, dl, NVT, Node->getOperand(j));
850 else
851 Operands[j] = DAG.getNode(ISD::BITCAST, dl, NVT, Node->getOperand(j));
852 else
853 Operands[j] = Node->getOperand(j);
854 }
855
856 SDValue Res =
857 DAG.getNode(Node->getOpcode(), dl, NVT, Operands, Node->getFlags());
858
859 if ((VT.isFloatingPoint() && NVT.isFloatingPoint()) ||
862 Res = DAG.getNode(ISD::FP_ROUND, dl, VT, Res,
863 DAG.getIntPtrConstant(0, dl, /*isTarget=*/true));
864 else
865 Res = DAG.getNode(ISD::BITCAST, dl, VT, Res);
866
867 Results.push_back(Res);
868}
869
870void VectorLegalizer::PromoteINT_TO_FP(SDNode *Node,
871 SmallVectorImpl<SDValue> &Results) {
872 // INT_TO_FP operations may require the input operand be promoted even
873 // when the type is otherwise legal.
874 bool IsStrict = Node->isStrictFPOpcode();
875 MVT VT = Node->getOperand(IsStrict ? 1 : 0).getSimpleValueType();
876 MVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VT);
878 "Vectors have different number of elements!");
879
880 SDLoc dl(Node);
881 SmallVector<SDValue, 4> Operands(Node->getNumOperands());
882
883 unsigned Opc = (Node->getOpcode() == ISD::UINT_TO_FP ||
884 Node->getOpcode() == ISD::STRICT_UINT_TO_FP)
887 for (unsigned j = 0; j != Node->getNumOperands(); ++j) {
888 if (Node->getOperand(j).getValueType().isVector())
889 Operands[j] = DAG.getNode(Opc, dl, NVT, Node->getOperand(j));
890 else
891 Operands[j] = Node->getOperand(j);
892 }
893
894 if (IsStrict) {
895 SDValue Res = DAG.getNode(Node->getOpcode(), dl,
896 {Node->getValueType(0), MVT::Other}, Operands);
897 Results.push_back(Res);
898 Results.push_back(Res.getValue(1));
899 return;
900 }
901
902 SDValue Res =
903 DAG.getNode(Node->getOpcode(), dl, Node->getValueType(0), Operands);
904 Results.push_back(Res);
905}
906
907// For FP_TO_INT we promote the result type to a vector type with wider
908// elements and then truncate the result. This is different from the default
909// PromoteVector which uses bitcast to promote thus assumning that the
910// promoted vector type has the same overall size.
911void VectorLegalizer::PromoteFP_TO_INT(SDNode *Node,
912 SmallVectorImpl<SDValue> &Results) {
913 MVT VT = Node->getSimpleValueType(0);
914 MVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VT);
915 bool IsStrict = Node->isStrictFPOpcode();
917 "Vectors have different number of elements!");
918
919 unsigned NewOpc = Node->getOpcode();
920 // Change FP_TO_UINT to FP_TO_SINT if possible.
921 // TODO: Should we only do this if FP_TO_UINT itself isn't legal?
922 if (NewOpc == ISD::FP_TO_UINT &&
924 NewOpc = ISD::FP_TO_SINT;
925
926 if (NewOpc == ISD::STRICT_FP_TO_UINT &&
928 NewOpc = ISD::STRICT_FP_TO_SINT;
929
930 SDLoc dl(Node);
931 SDValue Promoted, Chain;
932 if (IsStrict) {
933 Promoted = DAG.getNode(NewOpc, dl, {NVT, MVT::Other},
934 {Node->getOperand(0), Node->getOperand(1)});
935 Chain = Promoted.getValue(1);
936 } else
937 Promoted = DAG.getNode(NewOpc, dl, NVT, Node->getOperand(0));
938
939 // Assert that the converted value fits in the original type. If it doesn't
940 // (eg: because the value being converted is too big), then the result of the
941 // original operation was undefined anyway, so the assert is still correct.
942 if (Node->getOpcode() == ISD::FP_TO_UINT ||
943 Node->getOpcode() == ISD::STRICT_FP_TO_UINT)
944 NewOpc = ISD::AssertZext;
945 else
946 NewOpc = ISD::AssertSext;
947
948 Promoted = DAG.getNode(NewOpc, dl, NVT, Promoted,
949 DAG.getValueType(VT.getScalarType()));
950 Promoted = DAG.getNode(ISD::TRUNCATE, dl, VT, Promoted);
951 Results.push_back(Promoted);
952 if (IsStrict)
953 Results.push_back(Chain);
954}
955
956std::pair<SDValue, SDValue> VectorLegalizer::ExpandLoad(SDNode *N) {
957 LoadSDNode *LD = cast<LoadSDNode>(N);
958 return TLI.scalarizeVectorLoad(LD, DAG);
959}
960
961SDValue VectorLegalizer::ExpandStore(SDNode *N) {
962 StoreSDNode *ST = cast<StoreSDNode>(N);
963 SDValue TF = TLI.scalarizeVectorStore(ST, DAG);
964 return TF;
965}
966
967void VectorLegalizer::Expand(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
968 switch (Node->getOpcode()) {
969 case ISD::LOAD: {
970 std::pair<SDValue, SDValue> Tmp = ExpandLoad(Node);
971 Results.push_back(Tmp.first);
972 Results.push_back(Tmp.second);
973 return;
974 }
975 case ISD::STORE:
976 Results.push_back(ExpandStore(Node));
977 return;
979 for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i)
980 Results.push_back(Node->getOperand(i));
981 return;
983 TLI.expandVectorInterleave(Node, Results, DAG);
984 return;
986 TLI.expandVectorDeinterleave(Node, Results, DAG);
987 return;
989 if (SDValue Expanded = ExpandSEXTINREG(Node)) {
990 Results.push_back(Expanded);
991 return;
992 }
993 break;
995 Results.push_back(ExpandANY_EXTEND_VECTOR_INREG(Node));
996 return;
998 Results.push_back(ExpandSIGN_EXTEND_VECTOR_INREG(Node));
999 return;
1001 Results.push_back(ExpandZERO_EXTEND_VECTOR_INREG(Node));
1002 return;
1003 case ISD::BSWAP:
1004 if (SDValue Expanded = ExpandBSWAP(Node)) {
1005 Results.push_back(Expanded);
1006 return;
1007 }
1008 break;
1009 case ISD::VSELECT:
1010 if (SDValue Expanded = ExpandVSELECT(Node)) {
1011 Results.push_back(Expanded);
1012 return;
1013 }
1014 break;
1015 case ISD::VP_SREM:
1016 case ISD::VP_UREM:
1017 if (SDValue Expanded = ExpandVP_REM(Node)) {
1018 Results.push_back(Expanded);
1019 return;
1020 }
1021 break;
1022 case ISD::SELECT:
1023 if (SDValue Expanded = ExpandSELECT(Node)) {
1024 Results.push_back(Expanded);
1025 return;
1026 }
1027 break;
1028 case ISD::SELECT_CC: {
1029 if (Node->getValueType(0).isScalableVector()) {
1030 EVT CondVT = TLI.getSetCCResultType(
1031 DAG.getDataLayout(), *DAG.getContext(), Node->getValueType(0));
1032 SDValue SetCC =
1033 DAG.getNode(ISD::SETCC, SDLoc(Node), CondVT, Node->getOperand(0),
1034 Node->getOperand(1), Node->getOperand(4));
1035 Results.push_back(DAG.getSelect(SDLoc(Node), Node->getValueType(0), SetCC,
1036 Node->getOperand(2),
1037 Node->getOperand(3)));
1038 return;
1039 }
1040 break;
1041 }
1042 case ISD::FP_TO_UINT:
1043 ExpandFP_TO_UINT(Node, Results);
1044 return;
1045 case ISD::UINT_TO_FP:
1046 ExpandUINT_TO_FLOAT(Node, Results);
1047 return;
1048 case ISD::FNEG:
1049 if (SDValue Expanded = ExpandFNEG(Node)) {
1050 Results.push_back(Expanded);
1051 return;
1052 }
1053 break;
1054 case ISD::FABS:
1055 if (SDValue Expanded = ExpandFABS(Node)) {
1056 Results.push_back(Expanded);
1057 return;
1058 }
1059 break;
1060 case ISD::FCOPYSIGN:
1061 if (SDValue Expanded = ExpandFCOPYSIGN(Node)) {
1062 Results.push_back(Expanded);
1063 return;
1064 }
1065 break;
1066 case ISD::FCANONICALIZE: {
1067 // If the scalar element type has a
1068 // Legal/Custom FCANONICALIZE, don't
1069 // mess with the vector, fall back.
1070 EVT VT = Node->getValueType(0);
1071 EVT EltVT = VT.getVectorElementType();
1072 if (!VT.isScalableVector() &&
1074 TargetLowering::Expand)
1075 break;
1076 // Otherwise canonicalize the whole vector.
1077 SDValue Mul = TLI.expandFCANONICALIZE(Node, DAG);
1078 Results.push_back(Mul);
1079 return;
1080 }
1081 case ISD::FSUB:
1082 ExpandFSUB(Node, Results);
1083 return;
1084 case ISD::SETCC:
1085 ExpandSETCC(Node, Results);
1086 return;
1087 case ISD::ABS:
1089 if (SDValue Expanded = TLI.expandABS(Node, DAG)) {
1090 Results.push_back(Expanded);
1091 return;
1092 }
1093 break;
1094 case ISD::ABDS:
1095 case ISD::ABDU:
1096 if (SDValue Expanded = TLI.expandABD(Node, DAG)) {
1097 Results.push_back(Expanded);
1098 return;
1099 }
1100 break;
1101 case ISD::AVGCEILS:
1102 case ISD::AVGCEILU:
1103 case ISD::AVGFLOORS:
1104 case ISD::AVGFLOORU:
1105 if (SDValue Expanded = TLI.expandAVG(Node, DAG)) {
1106 Results.push_back(Expanded);
1107 return;
1108 }
1109 break;
1110 case ISD::BITREVERSE:
1111 if (SDValue Expanded = ExpandBITREVERSE(Node)) {
1112 Results.push_back(Expanded);
1113 return;
1114 }
1115 break;
1116 case ISD::CTPOP:
1117 if (SDValue Expanded = TLI.expandCTPOP(Node, DAG)) {
1118 Results.push_back(Expanded);
1119 return;
1120 }
1121 break;
1122 case ISD::CTLZ:
1124 if (SDValue Expanded = TLI.expandCTLZ(Node, DAG)) {
1125 Results.push_back(Expanded);
1126 return;
1127 }
1128 break;
1129 case ISD::CTTZ:
1131 if (SDValue Expanded = TLI.expandCTTZ(Node, DAG)) {
1132 Results.push_back(Expanded);
1133 return;
1134 }
1135 break;
1136 case ISD::FSHL:
1137 case ISD::FSHR:
1138 if (SDValue Expanded = TLI.expandFunnelShift(Node, DAG)) {
1139 Results.push_back(Expanded);
1140 return;
1141 }
1142 break;
1143 case ISD::CLMUL:
1144 case ISD::CLMULR:
1145 case ISD::CLMULH:
1146 if (SDValue Expanded = TLI.expandCLMUL(Node, DAG)) {
1147 Results.push_back(Expanded);
1148 return;
1149 }
1150 break;
1151 case ISD::PEXT:
1152 Results.push_back(TLI.expandPEXT(Node, DAG));
1153 return;
1154 case ISD::PDEP:
1155 Results.push_back(TLI.expandPDEP(Node, DAG));
1156 return;
1157 case ISD::ROTL:
1158 case ISD::ROTR:
1159 if (SDValue Expanded = TLI.expandROT(Node, false /*AllowVectorOps*/, DAG)) {
1160 Results.push_back(Expanded);
1161 return;
1162 }
1163 break;
1164 case ISD::FMINNUM:
1165 case ISD::FMAXNUM:
1166 if (SDValue Expanded = TLI.expandFMINNUM_FMAXNUM(Node, DAG)) {
1167 Results.push_back(Expanded);
1168 return;
1169 }
1170 break;
1171 case ISD::FMINIMUM:
1172 case ISD::FMAXIMUM:
1173 Results.push_back(TLI.expandFMINIMUM_FMAXIMUM(Node, DAG));
1174 return;
1175 case ISD::FMINIMUMNUM:
1176 case ISD::FMAXIMUMNUM:
1177 Results.push_back(TLI.expandFMINIMUMNUM_FMAXIMUMNUM(Node, DAG));
1178 return;
1179 case ISD::SMIN:
1180 case ISD::SMAX:
1181 case ISD::UMIN:
1182 case ISD::UMAX:
1183 if (SDValue Expanded = TLI.expandIntMINMAX(Node, DAG)) {
1184 Results.push_back(Expanded);
1185 return;
1186 }
1187 break;
1188 case ISD::UADDO:
1189 case ISD::USUBO:
1190 ExpandUADDSUBO(Node, Results);
1191 return;
1192 case ISD::SADDO:
1193 case ISD::SSUBO:
1194 ExpandSADDSUBO(Node, Results);
1195 return;
1196 case ISD::UMULO:
1197 case ISD::SMULO:
1198 ExpandMULO(Node, Results);
1199 return;
1200 case ISD::MULHS:
1201 case ISD::MULHU:
1202 if (SDValue Expanded = TLI.expandMULH(Node, DAG)) {
1203 Results.push_back(Expanded);
1204 return;
1205 }
1206 break;
1207 case ISD::USUBSAT:
1208 case ISD::SSUBSAT:
1209 case ISD::UADDSAT:
1210 case ISD::SADDSAT:
1211 if (SDValue Expanded = TLI.expandAddSubSat(Node, DAG)) {
1212 Results.push_back(Expanded);
1213 return;
1214 }
1215 break;
1216 case ISD::USHLSAT:
1217 case ISD::SSHLSAT:
1218 if (SDValue Expanded = TLI.expandShlSat(Node, DAG)) {
1219 Results.push_back(Expanded);
1220 return;
1221 }
1222 break;
1225 // Expand the fpsosisat if it is scalable to prevent it from unrolling below.
1226 if (Node->getValueType(0).isScalableVector()) {
1227 if (SDValue Expanded = TLI.expandFP_TO_INT_SAT(Node, DAG)) {
1228 Results.push_back(Expanded);
1229 return;
1230 }
1231 }
1232 break;
1233 case ISD::SMULFIX:
1234 case ISD::UMULFIX:
1235 case ISD::SMULFIXSAT:
1236 case ISD::UMULFIXSAT:
1237 if (SDValue Expanded = TLI.expandFixedPointMul(Node, DAG)) {
1238 Results.push_back(Expanded);
1239 return;
1240 }
1241 break;
1242 case ISD::SDIVFIX:
1243 case ISD::UDIVFIX:
1244 ExpandFixedPointDiv(Node, Results);
1245 return;
1246 case ISD::SDIVFIXSAT:
1247 case ISD::UDIVFIXSAT:
1248 break;
1249#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
1250 case ISD::STRICT_##DAGN:
1251#include "llvm/IR/ConstrainedOps.def"
1252 ExpandStrictFPOp(Node, Results);
1253 return;
1254 case ISD::VECREDUCE_ADD:
1255 case ISD::VECREDUCE_MUL:
1256 case ISD::VECREDUCE_AND:
1257 case ISD::VECREDUCE_OR:
1258 case ISD::VECREDUCE_XOR:
1271 Results.push_back(TLI.expandVecReduce(Node, DAG));
1272 return;
1277 Results.push_back(TLI.expandPartialReduceMLA(Node, DAG));
1278 return;
1281 Results.push_back(TLI.expandVecReduceSeq(Node, DAG));
1282 return;
1283 case ISD::VECTOR_MATCH:
1284 Results.push_back(TLI.expandVectorMatch(Node, DAG));
1285 return;
1286 case ISD::SREM:
1287 case ISD::UREM:
1288 ExpandREM(Node, Results);
1289 return;
1290 case ISD::VP_MERGE:
1291 if (SDValue Expanded = ExpandVP_MERGE(Node)) {
1292 Results.push_back(Expanded);
1293 return;
1294 }
1295 break;
1296 case ISD::FREM:
1297 if (tryExpandVecMathCall(Node, RTLIB::getREM, Results))
1298 return;
1299 break;
1300 case ISD::FSINCOS:
1301 case ISD::FSINCOSPI: {
1302 EVT VT = Node->getValueType(0);
1303 RTLIB::Libcall LC = Node->getOpcode() == ISD::FSINCOS
1304 ? RTLIB::getSINCOS(VT)
1305 : RTLIB::getSINCOSPI(VT);
1306 if (LC != RTLIB::UNKNOWN_LIBCALL &&
1307 TLI.expandMultipleResultFPLibCall(DAG, LC, Node, Results))
1308 return;
1309
1310 // TODO: Try to see if there's a narrower call available to use before
1311 // scalarizing.
1312 break;
1313 }
1314 case ISD::FPOW:
1315 if (tryExpandVecMathCall(Node, RTLIB::getPOW, Results))
1316 return;
1317
1318 // TODO: Try to see if there's a narrower call available to use before
1319 // scalarizing.
1320 break;
1321 case ISD::FCBRT:
1322 if (tryExpandVecMathCall(Node, RTLIB::getCBRT, Results))
1323 return;
1324
1325 // TODO: Try to see if there's a narrower call available to use before
1326 // scalarizing.
1327 break;
1328 case ISD::FMODF: {
1329 EVT VT = Node->getValueType(0);
1330 RTLIB::Libcall LC = RTLIB::getMODF(VT);
1331 if (LC != RTLIB::UNKNOWN_LIBCALL &&
1332 TLI.expandMultipleResultFPLibCall(DAG, LC, Node, Results,
1333 /*CallRetResNo=*/0))
1334 return;
1335 break;
1336 }
1338 Results.push_back(TLI.expandVECTOR_COMPRESS(Node, DAG));
1339 return;
1340 case ISD::CTTZ_ELTS:
1342 Results.push_back(TLI.expandCttzElts(Node, DAG));
1343 return;
1345 Results.push_back(TLI.expandVectorFindLastActive(Node, DAG));
1346 return;
1347 case ISD::SCMP:
1348 case ISD::UCMP:
1349 Results.push_back(TLI.expandCMP(Node, DAG));
1350 return;
1352 if (SDValue R = TLI.expandGetActiveLaneMask(Node, DAG))
1353 Results.push_back(R);
1354 return;
1357 Results.push_back(ExpandLOOP_DEPENDENCE_MASK(Node));
1358 return;
1360 Results.push_back(ExpandMASK_BEFOREFIRST(Node));
1361 return;
1362
1363 case ISD::FADD:
1364 case ISD::FMUL:
1365 case ISD::FMA:
1366 case ISD::FDIV:
1367 case ISD::FCEIL:
1368 case ISD::FFLOOR:
1369 case ISD::FNEARBYINT:
1370 case ISD::FRINT:
1371 case ISD::FROUND:
1372 case ISD::FROUNDEVEN:
1373 case ISD::FTRUNC:
1374 case ISD::FSQRT:
1375 if (SDValue Expanded = TLI.expandVectorNaryOpBySplitting(Node, DAG)) {
1376 Results.push_back(Expanded);
1377 return;
1378 }
1379 break;
1381 if (SDValue Expanded = TLI.expandCONVERT_TO_ARBITRARY_FP(Node, DAG))
1382 Results.push_back(Expanded);
1383 else
1384 Results.push_back(DAG.getPOISON(Node->getValueType(0)));
1385 return;
1387 if (SDValue Expanded = TLI.expandCONVERT_FROM_ARBITRARY_FP(Node, DAG))
1388 Results.push_back(Expanded);
1389 else
1390 Results.push_back(DAG.getPOISON(Node->getValueType(0)));
1391 return;
1392 case ISD::MASKED_UDIV:
1393 case ISD::MASKED_SDIV:
1394 case ISD::MASKED_UREM:
1395 case ISD::MASKED_SREM:
1396 Results.push_back(ExpandMaskedBinOp(Node));
1397 return;
1398 }
1399
1400 SDValue Unrolled = DAG.UnrollVectorOp(Node);
1401 if (Node->getNumValues() == 1) {
1402 Results.push_back(Unrolled);
1403 } else {
1404 assert(Node->getNumValues() == Unrolled->getNumValues() &&
1405 "VectorLegalizer Expand returned wrong number of results!");
1406 for (unsigned I = 0, E = Unrolled->getNumValues(); I != E; ++I)
1407 Results.push_back(Unrolled.getValue(I));
1408 }
1409}
1410
1411SDValue VectorLegalizer::ExpandSELECT(SDNode *Node) {
1412 // Lower a select instruction where the condition is a scalar and the
1413 // operands are vectors. Lower this select to VSELECT and implement it
1414 // using XOR AND OR. The selector bit is broadcasted.
1415 EVT VT = Node->getValueType(0);
1416 SDLoc DL(Node);
1417
1418 SDValue Mask = Node->getOperand(0);
1419 SDValue Op1 = Node->getOperand(1);
1420 SDValue Op2 = Node->getOperand(2);
1421
1422 assert(VT.isVector() && !Mask.getValueType().isVector()
1423 && Op1.getValueType() == Op2.getValueType() && "Invalid type");
1424
1425 // If we can't even use the basic vector operations of
1426 // AND,OR,XOR, we will have to scalarize the op.
1427 // Notice that the operation may be 'promoted' which means that it is
1428 // 'bitcasted' to another type which is handled.
1429 // Also, we need to be able to construct a splat vector using either
1430 // BUILD_VECTOR or SPLAT_VECTOR.
1431 // FIXME: Should we also permit fixed-length SPLAT_VECTOR as a fallback to
1432 // BUILD_VECTOR?
1433 if (TLI.getOperationAction(ISD::AND, VT) == TargetLowering::Expand ||
1434 TLI.getOperationAction(ISD::XOR, VT) == TargetLowering::Expand ||
1435 TLI.getOperationAction(ISD::OR, VT) == TargetLowering::Expand ||
1438 VT) == TargetLowering::Expand)
1439 return SDValue();
1440
1441 // Generate a mask operand.
1442 EVT MaskTy = VT.changeVectorElementTypeToInteger();
1443
1444 // What is the size of each element in the vector mask.
1445 EVT BitTy = MaskTy.getScalarType();
1446
1447 Mask = DAG.getSelect(DL, BitTy, Mask, DAG.getAllOnesConstant(DL, BitTy),
1448 DAG.getConstant(0, DL, BitTy));
1449
1450 // Broadcast the mask so that the entire vector is all one or all zero.
1451 Mask = DAG.getSplat(MaskTy, DL, Mask);
1452
1453 // Bitcast the operands to be the same type as the mask.
1454 // This is needed when we select between FP types because
1455 // the mask is a vector of integers.
1456 Op1 = DAG.getNode(ISD::BITCAST, DL, MaskTy, Op1);
1457 Op2 = DAG.getNode(ISD::BITCAST, DL, MaskTy, Op2);
1458
1459 SDValue NotMask = DAG.getNOT(DL, Mask, MaskTy);
1460
1461 Op1 = DAG.getNode(ISD::AND, DL, MaskTy, Op1, Mask);
1462 Op2 = DAG.getNode(ISD::AND, DL, MaskTy, Op2, NotMask);
1463 SDValue Val = DAG.getNode(ISD::OR, DL, MaskTy, Op1, Op2);
1464 return DAG.getNode(ISD::BITCAST, DL, Node->getValueType(0), Val);
1465}
1466
1467SDValue VectorLegalizer::ExpandSEXTINREG(SDNode *Node) {
1468 EVT VT = Node->getValueType(0);
1469
1470 // Make sure that the SRA and SHL instructions are available.
1471 if (TLI.getOperationAction(ISD::SRA, VT) == TargetLowering::Expand ||
1472 TLI.getOperationAction(ISD::SHL, VT) == TargetLowering::Expand)
1473 return SDValue();
1474
1475 SDLoc DL(Node);
1476 EVT OrigTy = cast<VTSDNode>(Node->getOperand(1))->getVT();
1477
1478 unsigned BW = VT.getScalarSizeInBits();
1479 unsigned OrigBW = OrigTy.getScalarSizeInBits();
1480 SDValue ShiftSz = DAG.getConstant(BW - OrigBW, DL, VT);
1481
1482 SDValue Op = DAG.getNode(ISD::SHL, DL, VT, Node->getOperand(0), ShiftSz);
1483 return DAG.getNode(ISD::SRA, DL, VT, Op, ShiftSz);
1484}
1485
1486// Generically expand a vector anyext in register to a shuffle of the relevant
1487// lanes into the appropriate locations, with other lanes left undef.
1488SDValue VectorLegalizer::ExpandANY_EXTEND_VECTOR_INREG(SDNode *Node) {
1489 SDLoc DL(Node);
1490 EVT VT = Node->getValueType(0);
1491 int NumElements = VT.getVectorNumElements();
1492 SDValue Src = Node->getOperand(0);
1493 EVT SrcVT = Src.getValueType();
1494 int NumSrcElements = SrcVT.getVectorNumElements();
1495
1496 // *_EXTEND_VECTOR_INREG SrcVT can be smaller than VT - so insert the vector
1497 // into a larger vector type.
1498 if (SrcVT.bitsLE(VT)) {
1499 assert((VT.getSizeInBits() % SrcVT.getScalarSizeInBits()) == 0 &&
1500 "ANY_EXTEND_VECTOR_INREG vector size mismatch");
1501 NumSrcElements = VT.getSizeInBits() / SrcVT.getScalarSizeInBits();
1502 SrcVT = EVT::getVectorVT(*DAG.getContext(), SrcVT.getScalarType(),
1503 NumSrcElements);
1504 Src = DAG.getInsertSubvector(DL, DAG.getUNDEF(SrcVT), Src, 0);
1505 }
1506
1507 // Build a base mask of undef shuffles.
1508 SmallVector<int, 16> ShuffleMask;
1509 ShuffleMask.resize(NumSrcElements, -1);
1510
1511 // Place the extended lanes into the correct locations.
1512 int ExtLaneScale = NumSrcElements / NumElements;
1513 int EndianOffset = DAG.getDataLayout().isBigEndian() ? ExtLaneScale - 1 : 0;
1514 for (int i = 0; i < NumElements; ++i)
1515 ShuffleMask[i * ExtLaneScale + EndianOffset] = i;
1516
1517 return DAG.getNode(
1518 ISD::BITCAST, DL, VT,
1519 DAG.getVectorShuffle(SrcVT, DL, Src, DAG.getPOISON(SrcVT), ShuffleMask));
1520}
1521
1522SDValue VectorLegalizer::ExpandSIGN_EXTEND_VECTOR_INREG(SDNode *Node) {
1523 SDLoc DL(Node);
1524 EVT VT = Node->getValueType(0);
1525 SDValue Src = Node->getOperand(0);
1526 EVT SrcVT = Src.getValueType();
1527
1528 // First build an any-extend node which can be legalized above when we
1529 // recurse through it.
1530 SDValue Op = DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, VT, Src);
1531
1532 // Now we need sign extend. This will be exanded to shifts if it isn't
1533 // supported.
1534 EVT ExtVT = EVT::getVectorVT(*DAG.getContext(), SrcVT.getVectorElementType(),
1536 return DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, VT, Op,
1537 DAG.getValueType(ExtVT));
1538}
1539
1540// Generically expand a vector zext in register to a shuffle of the relevant
1541// lanes into the appropriate locations, a blend of zero into the high bits,
1542// and a bitcast to the wider element type.
1543SDValue VectorLegalizer::ExpandZERO_EXTEND_VECTOR_INREG(SDNode *Node) {
1544 SDLoc DL(Node);
1545 EVT VT = Node->getValueType(0);
1546 int NumElements = VT.getVectorNumElements();
1547 SDValue Src = Node->getOperand(0);
1548 EVT SrcVT = Src.getValueType();
1549 int NumSrcElements = SrcVT.getVectorNumElements();
1550
1551 // *_EXTEND_VECTOR_INREG SrcVT can be smaller than VT - so insert the vector
1552 // into a larger vector type.
1553 if (SrcVT.bitsLE(VT)) {
1554 assert((VT.getSizeInBits() % SrcVT.getScalarSizeInBits()) == 0 &&
1555 "ZERO_EXTEND_VECTOR_INREG vector size mismatch");
1556 NumSrcElements = VT.getSizeInBits() / SrcVT.getScalarSizeInBits();
1557 SrcVT = EVT::getVectorVT(*DAG.getContext(), SrcVT.getScalarType(),
1558 NumSrcElements);
1559 Src = DAG.getInsertSubvector(DL, DAG.getUNDEF(SrcVT), Src, 0);
1560 }
1561
1562 // Build up a zero vector to blend into this one.
1563 SDValue Zero = DAG.getConstant(0, DL, SrcVT);
1564
1565 // Shuffle the incoming lanes into the correct position, and pull all other
1566 // lanes from the zero vector.
1567 auto ShuffleMask = llvm::to_vector<16>(llvm::seq<int>(0, NumSrcElements));
1568
1569 int ExtLaneScale = NumSrcElements / NumElements;
1570 int EndianOffset = DAG.getDataLayout().isBigEndian() ? ExtLaneScale - 1 : 0;
1571 for (int i = 0; i < NumElements; ++i)
1572 ShuffleMask[i * ExtLaneScale + EndianOffset] = NumSrcElements + i;
1573
1574 return DAG.getNode(ISD::BITCAST, DL, VT,
1575 DAG.getVectorShuffle(SrcVT, DL, Zero, Src, ShuffleMask));
1576}
1577
1578static void createBSWAPShuffleMask(EVT VT, SmallVectorImpl<int> &ShuffleMask) {
1579 int ScalarSizeInBytes = VT.getScalarSizeInBits() / 8;
1580 for (int I = 0, E = VT.getVectorNumElements(); I != E; ++I)
1581 for (int J = ScalarSizeInBytes - 1; J >= 0; --J)
1582 ShuffleMask.push_back((I * ScalarSizeInBytes) + J);
1583}
1584
1585SDValue VectorLegalizer::ExpandBSWAP(SDNode *Node) {
1586 EVT VT = Node->getValueType(0);
1587
1588 // Scalable vectors can't use shuffle expansion.
1589 if (VT.isScalableVector())
1590 return TLI.expandBSWAP(Node, DAG);
1591
1592 // Generate a byte wise shuffle mask for the BSWAP.
1593 SmallVector<int, 16> ShuffleMask;
1594 createBSWAPShuffleMask(VT, ShuffleMask);
1595 EVT ByteVT = EVT::getVectorVT(*DAG.getContext(), MVT::i8, ShuffleMask.size());
1596
1597 // Only emit a shuffle if the mask is legal.
1598 if (TLI.isShuffleMaskLegal(ShuffleMask, ByteVT)) {
1599 SDLoc DL(Node);
1600 SDValue Op = DAG.getNode(ISD::BITCAST, DL, ByteVT, Node->getOperand(0));
1601 Op = DAG.getVectorShuffle(ByteVT, DL, Op, DAG.getPOISON(ByteVT),
1602 ShuffleMask);
1603 return DAG.getNode(ISD::BITCAST, DL, VT, Op);
1604 }
1605
1606 // If we have the appropriate vector bit operations, it is better to use them
1607 // than unrolling and expanding each component.
1608 if (TLI.isOperationLegalOrCustom(ISD::SHL, VT) &&
1612 return TLI.expandBSWAP(Node, DAG);
1613
1614 // Otherwise let the caller unroll.
1615 return SDValue();
1616}
1617
1618SDValue VectorLegalizer::ExpandBITREVERSE(SDNode *Node) {
1619 EVT VT = Node->getValueType(0);
1620
1621 // We can't unroll or use shuffles for scalable vectors.
1622 if (VT.isScalableVector())
1623 return TLI.expandBITREVERSE(Node, DAG);
1624
1625 // If we have the scalar operation, it's probably cheaper to unroll it.
1627 return SDValue();
1628
1629 // If the vector element width is a whole number of bytes, test if its legal
1630 // to BSWAP shuffle the bytes and then perform the BITREVERSE on the byte
1631 // vector. This greatly reduces the number of bit shifts necessary.
1632 unsigned ScalarSizeInBits = VT.getScalarSizeInBits();
1633 if (ScalarSizeInBits > 8 && (ScalarSizeInBits % 8) == 0) {
1634 SmallVector<int, 16> BSWAPMask;
1635 createBSWAPShuffleMask(VT, BSWAPMask);
1636
1637 EVT ByteVT = EVT::getVectorVT(*DAG.getContext(), MVT::i8, BSWAPMask.size());
1638 if (TLI.isShuffleMaskLegal(BSWAPMask, ByteVT) &&
1640 (TLI.isOperationLegalOrCustom(ISD::SHL, ByteVT) &&
1641 TLI.isOperationLegalOrCustom(ISD::SRL, ByteVT) &&
1644 SDLoc DL(Node);
1645 SDValue Op = DAG.getNode(ISD::BITCAST, DL, ByteVT, Node->getOperand(0));
1646 Op = DAG.getVectorShuffle(ByteVT, DL, Op, DAG.getPOISON(ByteVT),
1647 BSWAPMask);
1648 Op = DAG.getNode(ISD::BITREVERSE, DL, ByteVT, Op);
1649 Op = DAG.getNode(ISD::BITCAST, DL, VT, Op);
1650 return Op;
1651 }
1652 }
1653
1654 // If we have the appropriate vector bit operations, it is better to use them
1655 // than unrolling and expanding each component.
1656 if (TLI.isOperationLegalOrCustom(ISD::SHL, VT) &&
1660 return TLI.expandBITREVERSE(Node, DAG);
1661
1662 // Otherwise unroll.
1663 return SDValue();
1664}
1665
1666SDValue VectorLegalizer::ExpandVSELECT(SDNode *Node) {
1667 // Implement VSELECT in terms of XOR, AND, OR
1668 // on platforms which do not support blend natively.
1669 SDLoc DL(Node);
1670
1671 SDValue Mask = Node->getOperand(0);
1672 SDValue Op1 = Node->getOperand(1);
1673 SDValue Op2 = Node->getOperand(2);
1674
1675 EVT VT = Mask.getValueType();
1676
1677 // If we can't even use the basic vector operations of
1678 // AND,OR,XOR, we will have to scalarize the op.
1679 // Notice that the operation may be 'promoted' which means that it is
1680 // 'bitcasted' to another type which is handled.
1681 if (TLI.getOperationAction(ISD::AND, VT) == TargetLowering::Expand ||
1682 TLI.getOperationAction(ISD::XOR, VT) == TargetLowering::Expand ||
1683 TLI.getOperationAction(ISD::OR, VT) == TargetLowering::Expand)
1684 return SDValue();
1685
1686 // This operation also isn't safe with AND, OR, XOR when the boolean type is
1687 // 0/1 and the select operands aren't also booleans, as we need an all-ones
1688 // vector constant to mask with.
1689 // FIXME: Sign extend 1 to all ones if that's legal on the target.
1690 auto BoolContents = TLI.getBooleanContents(Op1.getValueType());
1691 if (BoolContents != TargetLowering::ZeroOrNegativeOneBooleanContent &&
1692 !(BoolContents == TargetLowering::ZeroOrOneBooleanContent &&
1693 Op1.getValueType().getVectorElementType() == MVT::i1))
1694 return SDValue();
1695
1696 // If the mask and the type are different sizes, unroll the vector op. This
1697 // can occur when getSetCCResultType returns something that is different in
1698 // size from the operand types. For example, v4i8 = select v4i32, v4i8, v4i8.
1699 if (VT.getSizeInBits() != Op1.getValueSizeInBits())
1700 return SDValue();
1701
1702 // Bitcast the operands to be the same type as the mask.
1703 // This is needed when we select between FP types because
1704 // the mask is a vector of integers.
1705 Op1 = DAG.getNode(ISD::BITCAST, DL, VT, Op1);
1706 Op2 = DAG.getNode(ISD::BITCAST, DL, VT, Op2);
1707
1708 SDValue NotMask = DAG.getNOT(DL, Mask, VT);
1709
1710 Op1 = DAG.getNode(ISD::AND, DL, VT, Op1, Mask);
1711 Op2 = DAG.getNode(ISD::AND, DL, VT, Op2, NotMask);
1712 SDValue Val = DAG.getNode(ISD::OR, DL, VT, Op1, Op2);
1713 return DAG.getNode(ISD::BITCAST, DL, Node->getValueType(0), Val);
1714}
1715
1716SDValue VectorLegalizer::ExpandVP_MERGE(SDNode *Node) {
1717 // Implement VP_MERGE in terms of VSELECT. Construct a mask where vector
1718 // indices less than the EVL/pivot are true. Combine that with the original
1719 // mask for a full-length mask. Use a full-length VSELECT to select between
1720 // the true and false values.
1721 SDLoc DL(Node);
1722
1723 SDValue Mask = Node->getOperand(0);
1724 SDValue Op1 = Node->getOperand(1);
1725 SDValue Op2 = Node->getOperand(2);
1726 SDValue EVL = Node->getOperand(3);
1727
1728 EVT MaskVT = Mask.getValueType();
1729 bool IsFixedLen = MaskVT.isFixedLengthVector();
1730
1731 EVT EVLVecVT = EVT::getVectorVT(*DAG.getContext(), EVL.getValueType(),
1732 MaskVT.getVectorElementCount());
1733
1734 // If we can't construct the EVL mask efficiently, it's better to unroll.
1735 if ((IsFixedLen &&
1737 (!IsFixedLen &&
1738 (!TLI.isOperationLegalOrCustom(ISD::STEP_VECTOR, EVLVecVT) ||
1740 return SDValue();
1741
1742 // If using a SETCC would result in a different type than the mask type,
1743 // unroll.
1744 if (TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(),
1745 EVLVecVT) != MaskVT)
1746 return SDValue();
1747
1748 SDValue StepVec = DAG.getStepVector(DL, EVLVecVT);
1749 SDValue SplatEVL = DAG.getSplat(EVLVecVT, DL, EVL);
1750 SDValue EVLMask =
1751 DAG.getSetCC(DL, MaskVT, StepVec, SplatEVL, ISD::CondCode::SETULT);
1752
1753 SDValue FullMask = DAG.getNode(ISD::AND, DL, MaskVT, Mask, EVLMask);
1754 return DAG.getSelect(DL, Node->getValueType(0), FullMask, Op1, Op2);
1755}
1756
1757SDValue VectorLegalizer::ExpandVP_REM(SDNode *Node) {
1758 // Implement VP_SREM/UREM in terms of VP_SDIV/VP_UDIV, MUL, SUB.
1759 EVT VT = Node->getValueType(0);
1760
1761 unsigned DivOpc = Node->getOpcode() == ISD::VP_SREM ? ISD::VP_SDIV : ISD::VP_UDIV;
1762
1763 if (!TLI.isOperationLegalOrCustom(DivOpc, VT) ||
1766 return SDValue();
1767
1768 SDLoc DL(Node);
1769
1770 SDValue Dividend = Node->getOperand(0);
1771 SDValue Divisor = Node->getOperand(1);
1772 SDValue Mask = Node->getOperand(2);
1773 SDValue EVL = Node->getOperand(3);
1774
1775 // X % Y -> X-X/Y*Y
1776 SDValue Div = DAG.getNode(DivOpc, DL, VT, Dividend, Divisor, Mask, EVL);
1777 SDValue Mul = DAG.getNode(ISD::MUL, DL, VT, Divisor, Div);
1778 return DAG.getNode(ISD::SUB, DL, VT, Dividend, Mul);
1779}
1780
1781SDValue VectorLegalizer::ExpandLOOP_DEPENDENCE_MASK(SDNode *N) {
1782 return TLI.expandLoopDependenceMask(N, DAG);
1783}
1784
1785SDValue VectorLegalizer::ExpandMASK_BEFOREFIRST(SDNode *N) {
1786 // Expand to (get_active_lane_mask 0, (cttz_elts x))
1787 SDLoc DL(N);
1788 EVT VT = N->getValueType(0);
1789 EVT VecIdxVT = TLI.getVectorIdxTy(DAG.getDataLayout());
1790 SDValue CttzElts =
1791 DAG.getNode(ISD::CTTZ_ELTS, DL, VecIdxVT, N->getOperand(0));
1792 return DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, DL, VT,
1793 DAG.getConstant(0, DL, VecIdxVT), CttzElts);
1794}
1795
1796SDValue VectorLegalizer::ExpandMaskedBinOp(SDNode *N) {
1797 // Masked bin ops don't have undefined behaviour when dividing by zero
1798 // on disabled lanes and produce poison instead. Replace the divisor on the
1799 // disabled lanes with 1 to avoid division by zero or overflow.
1800 SDLoc dl(N);
1801 EVT VT = N->getValueType(0);
1802 SDValue SafeDivisor = DAG.getSelect(
1803 dl, VT, N->getOperand(2), N->getOperand(1), DAG.getConstant(1, dl, VT));
1804 return DAG.getNode(ISD::getUnmaskedBinOpOpcode(N->getOpcode()), dl, VT,
1805 N->getOperand(0), SafeDivisor);
1806}
1807
1808void VectorLegalizer::ExpandFP_TO_UINT(SDNode *Node,
1809 SmallVectorImpl<SDValue> &Results) {
1810 // Attempt to expand using TargetLowering.
1811 SDValue Result, Chain;
1812 if (TLI.expandFP_TO_UINT(Node, Result, Chain, DAG)) {
1813 Results.push_back(Result);
1814 if (Node->isStrictFPOpcode())
1815 Results.push_back(Chain);
1816 return;
1817 }
1818
1819 // Otherwise go ahead and unroll.
1820 if (Node->isStrictFPOpcode()) {
1821 UnrollStrictFPOp(Node, Results);
1822 return;
1823 }
1824
1825 Results.push_back(DAG.UnrollVectorOp(Node));
1826}
1827
1828void VectorLegalizer::ExpandUINT_TO_FLOAT(SDNode *Node,
1829 SmallVectorImpl<SDValue> &Results) {
1830 bool IsStrict = Node->isStrictFPOpcode();
1831 unsigned OpNo = IsStrict ? 1 : 0;
1832 SDValue Src = Node->getOperand(OpNo);
1833 EVT SrcVT = Src.getValueType();
1834 EVT DstVT = Node->getValueType(0);
1835 SDLoc DL(Node);
1836
1837 // Attempt to expand using TargetLowering.
1838 SDValue Result;
1839 SDValue Chain;
1840 if (TLI.expandUINT_TO_FP(Node, Result, Chain, DAG)) {
1841 Results.push_back(Result);
1842 if (IsStrict)
1843 Results.push_back(Chain);
1844 return;
1845 }
1846
1847 // Make sure that the SINT_TO_FP and SRL instructions are available.
1848 if (((!IsStrict && TLI.getOperationAction(ISD::SINT_TO_FP, SrcVT) ==
1849 TargetLowering::Expand) ||
1850 (IsStrict && TLI.getOperationAction(ISD::STRICT_SINT_TO_FP, SrcVT) ==
1851 TargetLowering::Expand)) ||
1852 TLI.getOperationAction(ISD::SRL, SrcVT) == TargetLowering::Expand) {
1853 if (IsStrict) {
1854 UnrollStrictFPOp(Node, Results);
1855 return;
1856 }
1857
1858 Results.push_back(DAG.UnrollVectorOp(Node));
1859 return;
1860 }
1861
1862 unsigned BW = SrcVT.getScalarSizeInBits();
1863 assert((BW == 64 || BW == 32) &&
1864 "Elements in vector-UINT_TO_FP must be 32 or 64 bits wide");
1865
1866 // If STRICT_/FMUL is not supported by the target (in case of f16) replace the
1867 // UINT_TO_FP with a larger float and round to the smaller type
1868 if ((!IsStrict && !TLI.isOperationLegalOrCustom(ISD::FMUL, DstVT)) ||
1869 (IsStrict && !TLI.isOperationLegalOrCustom(ISD::STRICT_FMUL, DstVT))) {
1870 EVT FPVT = BW == 32 ? MVT::f32 : MVT::f64;
1871 SDValue UIToFP;
1872 SDValue Result;
1873 SDValue TargetZero = DAG.getIntPtrConstant(0, DL, /*isTarget=*/true);
1874 EVT FloatVecVT = SrcVT.changeVectorElementType(*DAG.getContext(), FPVT);
1875 if (IsStrict) {
1876 UIToFP = DAG.getNode(ISD::STRICT_UINT_TO_FP, DL, {FloatVecVT, MVT::Other},
1877 {Node->getOperand(0), Src});
1878 Result = DAG.getNode(ISD::STRICT_FP_ROUND, DL, {DstVT, MVT::Other},
1879 {Node->getOperand(0), UIToFP, TargetZero});
1880 Results.push_back(Result);
1881 Results.push_back(Result.getValue(1));
1882 } else {
1883 UIToFP = DAG.getNode(ISD::UINT_TO_FP, DL, FloatVecVT, Src);
1884 Result = DAG.getNode(ISD::FP_ROUND, DL, DstVT, UIToFP, TargetZero);
1885 Results.push_back(Result);
1886 }
1887
1888 return;
1889 }
1890
1891 SDValue HalfWord = DAG.getConstant(BW / 2, DL, SrcVT);
1892
1893 // Constants to clear the upper part of the word.
1894 // Notice that we can also use SHL+SHR, but using a constant is slightly
1895 // faster on x86.
1896 uint64_t HWMask = (BW == 64) ? 0x00000000FFFFFFFF : 0x0000FFFF;
1897 SDValue HalfWordMask = DAG.getConstant(HWMask, DL, SrcVT);
1898
1899 // Two to the power of half-word-size.
1900 SDValue TWOHW = DAG.getConstantFP(1ULL << (BW / 2), DL, DstVT);
1901
1902 // Clear upper part of LO, lower HI
1903 SDValue HI = DAG.getNode(ISD::SRL, DL, SrcVT, Src, HalfWord);
1904 SDValue LO = DAG.getNode(ISD::AND, DL, SrcVT, Src, HalfWordMask);
1905
1906 if (IsStrict) {
1907 // Convert hi and lo to floats
1908 // Convert the hi part back to the upper values
1909 // TODO: Can any fast-math-flags be set on these nodes?
1910 SDValue fHI = DAG.getNode(ISD::STRICT_SINT_TO_FP, DL, {DstVT, MVT::Other},
1911 {Node->getOperand(0), HI});
1912 fHI = DAG.getNode(ISD::STRICT_FMUL, DL, {DstVT, MVT::Other},
1913 {fHI.getValue(1), fHI, TWOHW});
1914 SDValue fLO = DAG.getNode(ISD::STRICT_SINT_TO_FP, DL, {DstVT, MVT::Other},
1915 {Node->getOperand(0), LO});
1916
1917 SDValue TF = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, fHI.getValue(1),
1918 fLO.getValue(1));
1919
1920 // Add the two halves
1921 SDValue Result =
1922 DAG.getNode(ISD::STRICT_FADD, DL, {DstVT, MVT::Other}, {TF, fHI, fLO});
1923
1924 Results.push_back(Result);
1925 Results.push_back(Result.getValue(1));
1926 return;
1927 }
1928
1929 // Convert hi and lo to floats
1930 // Convert the hi part back to the upper values
1931 // TODO: Can any fast-math-flags be set on these nodes?
1932 SDValue fHI = DAG.getNode(ISD::SINT_TO_FP, DL, DstVT, HI);
1933 fHI = DAG.getNode(ISD::FMUL, DL, DstVT, fHI, TWOHW);
1934 SDValue fLO = DAG.getNode(ISD::SINT_TO_FP, DL, DstVT, LO);
1935
1936 // Add the two halves
1937 Results.push_back(DAG.getNode(ISD::FADD, DL, DstVT, fHI, fLO));
1938}
1939
1940SDValue VectorLegalizer::ExpandFNEG(SDNode *Node) {
1941 EVT VT = Node->getValueType(0);
1942 EVT IntVT = VT.changeVectorElementTypeToInteger();
1943
1944 if (!TLI.isOperationLegalOrCustom(ISD::XOR, IntVT))
1945 return SDValue();
1946
1947 // Heuristic check to determine whether vector should be expanded to integer
1948 // operations or unrolled to scalar operations.
1949 // 1. Scalable vector is never unrolled.
1950 // 2. Fixed vector is unrolled if one of followings is true:
1951 // a. Vector only has 1 element and target knows how to handle scalar
1952 // FNEG (either legal or custom expand or promote).
1953 // b. Vector has more than 1 element and target supports scalar
1954 // FNEG natively and vector length <= 2(1 XOR + 1 CONST).
1955 // FIXME: Scalar construction instruction count varies in every architecture,
1956 // here we assume 1 instruction for now.
1957 if (VT.isFixedLengthVector()) {
1958 EVT EltVT = VT.getVectorElementType();
1959 unsigned NumElts = VT.getVectorNumElements();
1960 if ((NumElts == 1 &&
1962 (NumElts < 3 && TLI.isOperationLegal(ISD::FNEG, EltVT) &&
1963 TLI.isExtractVecEltCheap(VT, 0) &&
1964 (NumElts == 1 || TLI.isExtractVecEltCheap(VT, 1))))
1965 return SDValue();
1966 }
1967
1968 SDLoc DL(Node);
1969 SDValue Cast = DAG.getNode(ISD::BITCAST, DL, IntVT, Node->getOperand(0));
1970 SDValue SignMask = DAG.getConstant(
1971 APInt::getSignMask(IntVT.getScalarSizeInBits()), DL, IntVT);
1972 SDValue Xor = DAG.getNode(ISD::XOR, DL, IntVT, Cast, SignMask);
1973 return DAG.getNode(ISD::BITCAST, DL, VT, Xor);
1974}
1975
1976SDValue VectorLegalizer::ExpandFABS(SDNode *Node) {
1977 EVT VT = Node->getValueType(0);
1978 EVT IntVT = VT.changeVectorElementTypeToInteger();
1979
1980 if (!TLI.isOperationLegalOrCustom(ISD::AND, IntVT))
1981 return SDValue();
1982
1983 // Heuristic check to determine whether vector should be expanded to integer
1984 // operations or unrolled to scalar operations.
1985 // 1. Scalable vector is never unrolled.
1986 // 2. Fixed vector is unrolled if one of followings is true:
1987 // a. Vector only has 1 element and target knows how to handle scalar
1988 // FABS(either legal or custom expand or promote).
1989 // b. Vector has more than 1 element and target supports scalar
1990 // FABS natively and vector length <= 2(1 AND + 1 CONST).
1991 // FIXME: Scalar construction instruction count varies in every architecture,
1992 // here we assume 1 instruction for now.
1993 if (VT.isFixedLengthVector()) {
1994 EVT EltVT = VT.getVectorElementType();
1995 unsigned NumElts = VT.getVectorNumElements();
1996 if ((NumElts == 1 &&
1998 (NumElts < 3 && TLI.isOperationLegal(ISD::FABS, EltVT) &&
1999 TLI.isExtractVecEltCheap(VT, 0) &&
2000 (NumElts == 1 || TLI.isExtractVecEltCheap(VT, 1))))
2001 return SDValue();
2002 }
2003
2004 SDLoc DL(Node);
2005 SDValue Cast = DAG.getNode(ISD::BITCAST, DL, IntVT, Node->getOperand(0));
2006 SDValue ClearSignMask = DAG.getConstant(
2008 SDValue ClearedSign = DAG.getNode(ISD::AND, DL, IntVT, Cast, ClearSignMask);
2009 return DAG.getNode(ISD::BITCAST, DL, VT, ClearedSign);
2010}
2011
2012SDValue VectorLegalizer::ExpandFCOPYSIGN(SDNode *Node) {
2013 EVT VT = Node->getValueType(0);
2014 EVT IntVT = VT.changeVectorElementTypeToInteger();
2015
2016 if (VT != Node->getOperand(1).getValueType() ||
2017 !TLI.isOperationLegalOrCustom(ISD::AND, IntVT) ||
2018 !TLI.isOperationLegalOrCustom(ISD::OR, IntVT))
2019 return SDValue();
2020
2021 // Heuristic check to determine whether vector should be expanded to integer
2022 // operations or unrolled to scalar operations.
2023 // 1. Scalable vector is never unrolled.
2024 // 2. Fixed vector is unrolled if one of followings is true:
2025 // a. Vector only has 1 element and target knows how to handle scalar
2026 // FCOPYSIGN(either legal or custom expand or promote).
2027 // b. Vector has more than 1 element and target supports scalar
2028 // FCOPYSIGN natively and vector length <= 5(2 AND + 1 OR + 2 CONST).
2029 // FIXME: Scalar construction instruction count varies in every architecture,
2030 // here we assume 1 instruction for now.
2031 if (VT.isFixedLengthVector()) {
2032 EVT EltVT = VT.getVectorElementType();
2033 unsigned NumElts = VT.getVectorNumElements();
2034 if ((NumElts == 1 &&
2036 (NumElts < 6 && TLI.isOperationLegal(ISD::FCOPYSIGN, EltVT) &&
2037 TLI.isExtractVecEltCheap(VT, 0) &&
2038 (NumElts == 1 || TLI.isExtractVecEltCheap(VT, 1))))
2039 return SDValue();
2040 }
2041
2042 SDLoc DL(Node);
2043 SDValue Mag = DAG.getNode(ISD::BITCAST, DL, IntVT, Node->getOperand(0));
2044 SDValue Sign = DAG.getNode(ISD::BITCAST, DL, IntVT, Node->getOperand(1));
2045
2046 SDValue SignMask = DAG.getConstant(
2047 APInt::getSignMask(IntVT.getScalarSizeInBits()), DL, IntVT);
2048 SDValue SignBit = DAG.getNode(ISD::AND, DL, IntVT, Sign, SignMask);
2049
2050 SDValue ClearSignMask = DAG.getConstant(
2052 SDValue ClearedSign = DAG.getNode(ISD::AND, DL, IntVT, Mag, ClearSignMask);
2053
2054 SDValue CopiedSign = DAG.getNode(ISD::OR, DL, IntVT, ClearedSign, SignBit,
2056
2057 return DAG.getNode(ISD::BITCAST, DL, VT, CopiedSign);
2058}
2059
2060void VectorLegalizer::ExpandFSUB(SDNode *Node,
2061 SmallVectorImpl<SDValue> &Results) {
2062 // For floating-point values, (a-b) is the same as a+(-b). If FNEG is legal,
2063 // we can defer this to operation legalization where it will be lowered as
2064 // a+(-b).
2065 EVT VT = Node->getValueType(0);
2066 if (TLI.isOperationLegalOrCustom(ISD::FNEG, VT) &&
2068 return; // Defer to LegalizeDAG
2069
2070 if (SDValue Expanded = TLI.expandVectorNaryOpBySplitting(Node, DAG)) {
2071 Results.push_back(Expanded);
2072 return;
2073 }
2074
2075 SDValue Tmp = DAG.UnrollVectorOp(Node);
2076 Results.push_back(Tmp);
2077}
2078
2079void VectorLegalizer::ExpandSETCC(SDNode *Node,
2080 SmallVectorImpl<SDValue> &Results) {
2081 bool NeedInvert = false;
2082 bool IsStrict = Node->getOpcode() == ISD::STRICT_FSETCC ||
2083 Node->getOpcode() == ISD::STRICT_FSETCCS;
2084 bool IsSignaling = Node->getOpcode() == ISD::STRICT_FSETCCS;
2085 unsigned Offset = IsStrict ? 1 : 0;
2086
2087 SDValue Chain = IsStrict ? Node->getOperand(0) : SDValue();
2088 SDValue LHS = Node->getOperand(0 + Offset);
2089 SDValue RHS = Node->getOperand(1 + Offset);
2090 SDValue CC = Node->getOperand(2 + Offset);
2091
2092 MVT OpVT = LHS.getSimpleValueType();
2093 ISD::CondCode CCCode = cast<CondCodeSDNode>(CC)->get();
2094
2095 if (TLI.getCondCodeAction(CCCode, OpVT) != TargetLowering::Expand) {
2096 if (IsStrict) {
2097 UnrollStrictFPOp(Node, Results);
2098 return;
2099 }
2100 Results.push_back(UnrollVSETCC(Node));
2101 return;
2102 }
2103
2104 SDLoc dl(Node);
2105 bool Legalized =
2106 TLI.LegalizeSetCCCondCode(DAG, Node->getValueType(0), LHS, RHS, CC,
2107 NeedInvert, dl, Chain, IsSignaling);
2108
2109 if (Legalized) {
2110 // If we expanded the SETCC by swapping LHS and RHS, or by inverting the
2111 // condition code, create a new SETCC node.
2112 if (CC.getNode()) {
2113 if (IsStrict) {
2114 LHS = DAG.getNode(Node->getOpcode(), dl, Node->getVTList(),
2115 {Chain, LHS, RHS, CC}, Node->getFlags());
2116 Chain = LHS.getValue(1);
2117 } else {
2118 LHS = DAG.getNode(ISD::SETCC, dl, Node->getValueType(0), LHS, RHS, CC,
2119 Node->getFlags());
2120 }
2121 }
2122
2123 // If we expanded the SETCC by inverting the condition code, then wrap
2124 // the existing SETCC in a NOT to restore the intended condition.
2125 if (NeedInvert)
2126 LHS = DAG.getLogicalNOT(dl, LHS, LHS->getValueType(0));
2127 } else {
2128 assert(!IsStrict && "Don't know how to expand for strict nodes.");
2129
2130 // Otherwise, SETCC for the given comparison type must be completely
2131 // illegal; expand it into a SELECT_CC.
2132 EVT VT = Node->getValueType(0);
2133 LHS = DAG.getNode(ISD::SELECT_CC, dl, VT, LHS, RHS,
2134 DAG.getBoolConstant(true, dl, VT, LHS.getValueType()),
2135 DAG.getBoolConstant(false, dl, VT, LHS.getValueType()),
2136 CC, Node->getFlags());
2137 }
2138
2139 Results.push_back(LHS);
2140 if (IsStrict)
2141 Results.push_back(Chain);
2142}
2143
2144void VectorLegalizer::ExpandUADDSUBO(SDNode *Node,
2145 SmallVectorImpl<SDValue> &Results) {
2146 SDValue Result, Overflow;
2147 TLI.expandUADDSUBO(Node, Result, Overflow, DAG);
2148 Results.push_back(Result);
2149 Results.push_back(Overflow);
2150}
2151
2152void VectorLegalizer::ExpandSADDSUBO(SDNode *Node,
2153 SmallVectorImpl<SDValue> &Results) {
2154 SDValue Result, Overflow;
2155 TLI.expandSADDSUBO(Node, Result, Overflow, DAG);
2156 Results.push_back(Result);
2157 Results.push_back(Overflow);
2158}
2159
2160void VectorLegalizer::ExpandMULO(SDNode *Node,
2161 SmallVectorImpl<SDValue> &Results) {
2162 SDValue Result, Overflow;
2163 if (!TLI.expandMULO(Node, Result, Overflow, DAG))
2164 std::tie(Result, Overflow) = DAG.UnrollVectorOverflowOp(Node);
2165
2166 Results.push_back(Result);
2167 Results.push_back(Overflow);
2168}
2169
2170void VectorLegalizer::ExpandFixedPointDiv(SDNode *Node,
2171 SmallVectorImpl<SDValue> &Results) {
2172 SDNode *N = Node;
2173 if (SDValue Expanded = TLI.expandFixedPointDiv(N->getOpcode(), SDLoc(N),
2174 N->getOperand(0), N->getOperand(1), N->getConstantOperandVal(2), DAG))
2175 Results.push_back(Expanded);
2176}
2177
2178void VectorLegalizer::ExpandStrictFPOp(SDNode *Node,
2179 SmallVectorImpl<SDValue> &Results) {
2180 switch (Node->getOpcode()) {
2181 default:
2182 break;
2184 ExpandUINT_TO_FLOAT(Node, Results);
2185 return;
2187 ExpandFP_TO_UINT(Node, Results);
2188 return;
2189 case ISD::STRICT_FSETCC:
2191 ExpandSETCC(Node, Results);
2192 return;
2193 case ISD::STRICT_FADD:
2194 case ISD::STRICT_FCEIL:
2195 case ISD::STRICT_FDIV:
2196 case ISD::STRICT_FFLOOR:
2197 case ISD::STRICT_FMA:
2198 case ISD::STRICT_FMUL:
2200 case ISD::STRICT_FRINT:
2201 case ISD::STRICT_FROUND:
2203 case ISD::STRICT_FTRUNC:
2204 case ISD::STRICT_FSQRT:
2205 case ISD::STRICT_FSUB: {
2206 if (SDValue Expanded = TLI.expandVectorNaryOpBySplitting(Node, DAG)) {
2207 Results.push_back(Expanded.getValue(0));
2208 Results.push_back(Expanded.getValue(1));
2209 return;
2210 }
2211 break;
2212 }
2213 }
2214
2215 UnrollStrictFPOp(Node, Results);
2216}
2217
2218void VectorLegalizer::ExpandREM(SDNode *Node,
2219 SmallVectorImpl<SDValue> &Results) {
2220 assert((Node->getOpcode() == ISD::SREM || Node->getOpcode() == ISD::UREM) &&
2221 "Expected REM node");
2222
2223 SDValue Result;
2224 if (!TLI.expandREM(Node, Result, DAG))
2225 Result = DAG.UnrollVectorOp(Node);
2226 Results.push_back(Result);
2227}
2228
2229// Try to expand libm nodes into vector math routine calls. Callers provide the
2230// RTLIB::get<OP>(EVT) selector of the node's libcall family, which is used to
2231// look up mappings within RuntimeLibcallsInfo. The only mappings considered are
2232// those where the result and all operands are the same vector type. While
2233// predicated nodes are not supported, we will emit calls to masked routines by
2234// passing in a mask that is true for the lanes computed by the node.
2235bool VectorLegalizer::tryExpandVecMathCall(
2236 SDNode *Node, function_ref<RTLIB::Libcall(EVT)> GetLibcall,
2237 SmallVectorImpl<SDValue> &Results) {
2238 // Chain must be propagated but currently strict fp operations are down
2239 // converted to their none strict counterpart.
2240 assert(!Node->isStrictFPOpcode() && "Unexpected strict fp operation!");
2241
2242 EVT VT = Node->getValueType(0);
2243 LLVMContext &Ctx = *DAG.getContext();
2244 const LibcallLoweringInfo &Libcalls = DAG.getLibcalls();
2245
2246 // Try to widen the vector type when no libcall is available at that width.
2247 EVT CallVT = VT;
2248 RTLIB::LibcallImpl LCImpl =
2249 Libcalls.getVectorLibcallImplOrMasked(GetLibcall(CallVT));
2250 if (LCImpl == RTLIB::Unsupported && VT.getVectorElementCount().isScalar())
2251 return false;
2252 while (LCImpl == RTLIB::Unsupported) {
2253 CallVT = CallVT.getDoubleNumVectorElementsVT(Ctx);
2254 if (!CallVT.isSimple())
2255 return false;
2256 if (TLI.isTypeLegal(CallVT))
2257 LCImpl = Libcalls.getVectorLibcallImplOrMasked(GetLibcall(CallVT));
2258 }
2259
2260 const RTLIB::RuntimeLibcallsInfo &RTLCI = TLI.getRuntimeLibcallsInfo();
2261
2262 auto [FuncTy, FuncAttrs] = RTLCI.getFunctionTy(
2263 Ctx, DAG.getSubtarget().getTargetTriple(), DAG.getDataLayout(), LCImpl);
2264
2265 SDLoc DL(Node);
2266 TargetLowering::ArgListTy Args;
2267
2268 bool HasMaskArg = RTLCI.hasVectorMaskArgument(LCImpl);
2269
2270 // Sanity check just in case function has unexpected parameters.
2271 assert(FuncTy->getNumParams() == Node->getNumOperands() + HasMaskArg &&
2272 EVT::getEVT(FuncTy->getReturnType(), true) == CallVT &&
2273 "mismatch in value type and call signature type");
2274
2275 for (unsigned I = 0, E = FuncTy->getNumParams(); I != E; ++I) {
2276 Type *ParamTy = FuncTy->getParamType(I);
2277
2278 if (HasMaskArg && I == E - 1) {
2279 assert(cast<VectorType>(ParamTy)->getElementType()->isIntegerTy(1) &&
2280 cast<VectorType>(ParamTy)->getElementCount() ==
2281 CallVT.getVectorElementCount() &&
2282 "unexpected vector mask type");
2283 EVT MaskVT = EVT::getEVT(ParamTy, /*HandleUnknown=*/true);
2284 EVT SubMaskVT =
2286 SDValue Mask = DAG.getBoolConstant(true, DL, SubMaskVT, VT);
2287 // Only the lanes holding the node's elements need to be active.
2288 if (CallVT != VT)
2290 DL, DAG.getBoolConstant(false, DL, MaskVT, CallVT), Mask, 0);
2291 Args.emplace_back(Mask, ParamTy);
2292 } else {
2293 SDValue Op = Node->getOperand(I);
2294 assert(Op.getValueType() == VT && "mismatch in vector types");
2295 if (CallVT != VT) {
2296 unsigned NumConcat =
2298 SmallVector<SDValue, 4> Ops(NumConcat, Op);
2299 Op = DAG.getNode(ISD::CONCAT_VECTORS, DL, CallVT, Ops);
2300 }
2301 assert(Op.getValueType() == EVT::getEVT(ParamTy, true) &&
2302 "mismatch in value type and call argument type");
2303 Args.emplace_back(Op, ParamTy);
2304 }
2305 }
2306
2307 // Emit a call to the vector function.
2308 SDValue Callee =
2309 DAG.getExternalSymbol(LCImpl, TLI.getPointerTy(DAG.getDataLayout()));
2310 CallingConv::ID CC = RTLCI.getLibcallImplCallingConv(LCImpl);
2311
2312 TargetLowering::CallLoweringInfo CLI(DAG);
2313 CLI.setDebugLoc(DL)
2314 .setChain(DAG.getEntryNode())
2315 .setLibCallee(CC, FuncTy->getReturnType(), Callee, std::move(Args));
2316
2317 std::pair<SDValue, SDValue> CallResult = TLI.LowerCallTo(CLI);
2318 SDValue Result = CallResult.first;
2319 if (CallVT != VT)
2320 Result = DAG.getExtractSubvector(DL, VT, Result, 0);
2321 Results.push_back(Result);
2322 return true;
2323}
2324
2325void VectorLegalizer::UnrollStrictFPOp(SDNode *Node,
2326 SmallVectorImpl<SDValue> &Results) {
2327 EVT VT = Node->getValueType(0);
2328
2329 // Cannot unroll a scalable vector. Delay error reporting until the final
2330 // operation legalisation phase to maximise the chances of removing the node.
2331 if (VT.isScalableVector())
2332 return;
2333
2334 EVT EltVT = VT.getVectorElementType();
2335 unsigned NumElems = VT.getVectorNumElements();
2336 unsigned NumOpers = Node->getNumOperands();
2337 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
2338
2339 EVT TmpEltVT = EltVT;
2340 if (Node->getOpcode() == ISD::STRICT_FSETCC ||
2341 Node->getOpcode() == ISD::STRICT_FSETCCS)
2342 TmpEltVT = TLI.getSetCCResultType(DAG.getDataLayout(),
2343 *DAG.getContext(), TmpEltVT);
2344
2345 EVT ValueVTs[] = {TmpEltVT, MVT::Other};
2346 SDValue Chain = Node->getOperand(0);
2347 SDLoc dl(Node);
2348
2349 SmallVector<SDValue, 32> OpValues;
2350 SmallVector<SDValue, 32> OpChains;
2351 for (unsigned i = 0; i < NumElems; ++i) {
2353 SDValue Idx = DAG.getVectorIdxConstant(i, dl);
2354
2355 // The Chain is the first operand.
2356 Opers.push_back(Chain);
2357
2358 // Now process the remaining operands.
2359 for (unsigned j = 1; j < NumOpers; ++j) {
2360 SDValue Oper = Node->getOperand(j);
2361 EVT OperVT = Oper.getValueType();
2362
2363 if (OperVT.isVector())
2364 Oper = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl,
2365 OperVT.getVectorElementType(), Oper, Idx);
2366
2367 Opers.push_back(Oper);
2368 }
2369
2370 SDValue ScalarOp = DAG.getNode(Node->getOpcode(), dl, ValueVTs, Opers);
2371 SDValue ScalarResult = ScalarOp.getValue(0);
2372 SDValue ScalarChain = ScalarOp.getValue(1);
2373
2374 if (Node->getOpcode() == ISD::STRICT_FSETCC ||
2375 Node->getOpcode() == ISD::STRICT_FSETCCS)
2376 ScalarResult = DAG.getSelect(dl, EltVT, ScalarResult,
2377 DAG.getAllOnesConstant(dl, EltVT),
2378 DAG.getConstant(0, dl, EltVT));
2379
2380 OpValues.push_back(ScalarResult);
2381 OpChains.push_back(ScalarChain);
2382 }
2383
2384 SDValue Result = DAG.getBuildVector(VT, dl, OpValues);
2385 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OpChains);
2386
2387 Results.push_back(Result);
2388 Results.push_back(NewChain);
2389}
2390
2391SDValue VectorLegalizer::UnrollVSETCC(SDNode *Node) {
2392 EVT VT = Node->getValueType(0);
2393 unsigned NumElems = VT.getVectorNumElements();
2394 EVT EltVT = VT.getVectorElementType();
2395 SDValue LHS = Node->getOperand(0);
2396 SDValue RHS = Node->getOperand(1);
2397 SDValue CC = Node->getOperand(2);
2398 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
2399 SDLoc dl(Node);
2400 SmallVector<SDValue, 8> Ops(NumElems);
2401 for (unsigned i = 0; i < NumElems; ++i) {
2402 SDValue LHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, LHS,
2403 DAG.getVectorIdxConstant(i, dl));
2404 SDValue RHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, RHS,
2405 DAG.getVectorIdxConstant(i, dl));
2406 // FIXME: We should use i1 setcc + boolext here, but it causes regressions.
2407 Ops[i] = DAG.getNode(ISD::SETCC, dl,
2409 *DAG.getContext(), TmpEltVT),
2410 LHSElem, RHSElem, CC);
2411 Ops[i] = DAG.getSelect(dl, EltVT, Ops[i],
2412 DAG.getBoolConstant(true, dl, EltVT, VT),
2413 DAG.getConstant(0, dl, EltVT));
2414 }
2415 return DAG.getBuildVector(VT, dl, Ops);
2416}
2417
2419 return VectorLegalizer(*this).Run();
2420}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t uint64_t
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:57
#define T
RISCVCC::CondCode CC
SI Fold Operands
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:225
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
Definition APInt.h:205
bool isBigEndian() const
Definition DataLayout.h:218
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:827
constexpr bool isScalar() const
Exactly one element.
Definition TypeSize.h:317
size_t size() const
Definition Function.h:843
RTLIB::LibcallImpl getVectorLibcallImplOrMasked(RTLIB::Libcall Call) const
Return the implementation for Call, or for its masked variant if Call has no implementation.
const Triple & getTargetTriple() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
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.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:294
Represents one node in the SelectionDAG.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
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.
const TargetSubtargetInfo & getSubtarget() const
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 ...
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 getExtractSubvector(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Return the VT typed sub-vector of Vec at Idx.
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,...
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
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
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
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 getBoolExtOrTrunc(SDValue Op, const SDLoc &SL, EVT VT, EVT OpVT)
Convert Op, which must be of integer type, to the integer type VT, by using an extension appropriate ...
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const LibcallLoweringInfo & getLibcalls() const
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...
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)
SDValue getPOISON(EVT VT)
Return a POISON node. POISON does not have a useful SDLoc.
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)
virtual bool isShuffleMaskLegal(ArrayRef< int >, EVT) const
Targets can use this to indicate that they only support some VECTOR_SHUFFLE operations,...
SDValue promoteTargetBoolean(SelectionDAG &DAG, SDValue Bool, EVT ValVT) const
Promote the given target boolean to a target boolean of the given type.
MVT getVectorIdxTy(const DataLayout &DL) const
Returns the type to be used for the index operand of: ISD::INSERT_VECTOR_ELT, ISD::EXTRACT_VECTOR_ELT...
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 getTruncStoreAction(EVT ValVT, EVT MemVT, Align Alignment, unsigned AddrSpace) const
Return how this store with truncation should be treated: either it is legal, needs to be promoted to ...
virtual bool isExtractVecEltCheap(EVT VT, unsigned Index) const
Return true if extraction of a scalar element from the given vector type at the given index is cheap.
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...
LegalizeAction getVectorInterleaveAction(unsigned Opc, unsigned Factor, EVT VT) const
Return how a VECTOR_INTERLEAVE or VECTOR_DEINTERLEAVE node with the given interleave factor and VT sh...
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
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...
bool isOperationLegal(unsigned Op, EVT VT) const
Return true if the specified operation is legal on this target.
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 getLoadAction(EVT ValVT, EVT MemVT, Align Alignment, unsigned AddrSpace, unsigned ExtType, bool Atomic) const
Return how this load with extension should be treated: either it is legal, needs to be promoted to a ...
LegalizeAction getStrictFPOperationAction(unsigned Op, EVT VT) const
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...
const RTLIB::RuntimeLibcallsInfo & getRuntimeLibcallsInfo() const
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.
void expandVectorDeinterleave(SDNode *Node, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const
Expand a VECTOR_DEINTERLEAVE without introducing wider vector types.
bool expandMultipleResultFPLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, SDNode *Node, SmallVectorImpl< SDValue > &Results, std::optional< unsigned > CallRetResNo={}) const
Expands a node with multiple results to an FP or vector libcall.
bool expandMULO(SDNode *Node, SDValue &Result, SDValue &Overflow, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::[US]MULO.
bool LegalizeSetCCCondCode(SelectionDAG &DAG, EVT VT, SDValue &LHS, SDValue &RHS, SDValue &CC, bool &NeedInvert, const SDLoc &dl, SDValue &Chain, bool IsSignaling=false) const
Legalize a SETCC with given LHS and RHS and condition code CC on the current target.
SDValue scalarizeVectorStore(StoreSDNode *ST, SelectionDAG &DAG) const
SDValue expandVecReduceSeq(SDNode *Node, SelectionDAG &DAG) const
Expand a VECREDUCE_SEQ_* into an explicit ordered calculation.
SDValue expandFCANONICALIZE(SDNode *Node, SelectionDAG &DAG) const
Expand FCANONICALIZE to FMUL with 1.
SDValue expandCTLZ(SDNode *N, SelectionDAG &DAG) const
Expand CTLZ/CTLZ_ZERO_POISON nodes.
SDValue expandBITREVERSE(SDNode *N, SelectionDAG &DAG) const
Expand BITREVERSE nodes.
SDValue expandCTTZ(SDNode *N, SelectionDAG &DAG) const
Expand CTTZ/CTTZ_ZERO_POISON nodes.
SDValue expandABD(SDNode *N, SelectionDAG &DAG) const
Expand ABDS/ABDU nodes.
SDValue expandGetActiveLaneMask(SDNode *N, SelectionDAG &DAG) const
Expand GET_ACTIVE_LANE_MASK nodes.
SDValue expandCLMUL(SDNode *N, SelectionDAG &DAG) const
Expand carryless multiply.
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.
SDValue expandCttzElts(SDNode *Node, SelectionDAG &DAG) const
Expand a CTTZ_ELTS or CTTZ_ELTS_ZERO_POISON by calculating (VL - i) for each active lane (i),...
void expandSADDSUBO(SDNode *Node, SDValue &Result, SDValue &Overflow, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::S(ADD|SUB)O.
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.
SDValue expandMULH(SDNode *Node, SelectionDAG &DAG) const
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.
void expandVectorInterleave(SDNode *Node, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const
Expand a VECTOR_INTERLEAVE without introducing wider vector types.
SDValue expandLoopDependenceMask(SDNode *N, SelectionDAG &DAG) const
Expand LOOP_DEPENDENCE_MASK nodes.
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 expandVectorMatch(SDNode *N, SelectionDAG &DAG) const
Expand VECTOR_MATCH nodes.
SDValue expandCONVERT_TO_ARBITRARY_FP(SDNode *Node, SelectionDAG &DAG) const
Expand CONVERT_TO_ARBITRARY_FP using bit manipulation.
SDValue expandFunnelShift(SDNode *N, SelectionDAG &DAG) const
Expand funnel shift.
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 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 expandPEXT(SDNode *N, SelectionDAG &DAG) const
Expand parallel bit extract (compress).
SDValue expandVECTOR_COMPRESS(SDNode *Node, SelectionDAG &DAG) const
Expand a vector VECTOR_COMPRESS into a sequence of extract element, store temporarily,...
SDValue expandCONVERT_FROM_ARBITRARY_FP(SDNode *Node, SelectionDAG &DAG) const
Expand CONVERT_FROM_ARBITRARY_FP using bit manipulation.
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.
SDValue expandPDEP(SDNode *N, SelectionDAG &DAG) const
Expand parallel bit deposit (expand).
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.
An efficient, type-erasing, non-owning reference to a callable.
#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:845
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
Definition ISDOpcodes.h:263
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
Definition ISDOpcodes.h:516
@ PARTIAL_REDUCE_SMLA
PARTIAL_REDUCE_[U|S]MLA(Accumulator, Input1, Input2) The partial reduction nodes sign or zero extend ...
@ LOOP_DEPENDENCE_RAW_MASK
@ MASK_BEFOREFIRST
Has one mask vector operand.
@ VECREDUCE_SEQ_FADD
Generic reduction nodes.
@ VECREDUCE_FMINIMUMNUM
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
Definition ISDOpcodes.h:277
@ AVGSUBFLOORS
AVGSUBFLOORS/AVGSUBFLOORU - Averaging subtract - Subtract two integers using an integer of type i[N+1...
Definition ISDOpcodes.h:733
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:805
@ SMULFIX
RESULT = [US]MULFIX(LHS, RHS, SCALE) - Perform fixed point multiplication on 2 integers with the same...
Definition ISDOpcodes.h:397
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:266
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ SMULFIXSAT
Same as the corresponding unsaturated fixed point instructions, but the result is clamped between the...
Definition ISDOpcodes.h:403
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition ISDOpcodes.h:879
@ CTTZ_ELTS
Returns the number of number of trailing (least significant) zero elements in a vector.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
Definition ISDOpcodes.h:523
@ VECTOR_FIND_LAST_ACTIVE
Finds the index of the last active mask element Operands: Mask.
@ FMODF
FMODF - Decomposes the operand into integral and fractional parts, each having the same type and sign...
@ FATAN2
FATAN2 - atan2, inspired by libm.
@ FSINCOSPI
FSINCOSPI - Compute both the sine and cosine times pi more accurately than FSINCOS(pi*x),...
@ STRICT_FMINIMUM
Definition ISDOpcodes.h:476
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Definition ISDOpcodes.h:906
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
Definition ISDOpcodes.h:589
@ VECREDUCE_FMAX
FMIN/FMAX nodes can have flags, for NaN/NoNaN variants.
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:420
@ VECREDUCE_FMAXIMUM
FMINIMUM/FMAXIMUM nodes propatate NaNs and signed zeroes using the llvm.minimum and llvm....
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
Definition ISDOpcodes.h:765
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
Definition ISDOpcodes.h:936
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
Definition ISDOpcodes.h:282
@ FPTRUNC_ROUND
FPTRUNC_ROUND - This corresponds to the fptrunc_round intrinsic.
Definition ISDOpcodes.h:520
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ CLMUL
Carry-less multiplication operations.
Definition ISDOpcodes.h:796
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ SDIVFIX
RESULT = [US]DIVFIX(LHS, RHS, SCALE) - Perform fixed point division on 2 integers with the same width...
Definition ISDOpcodes.h:410
@ STRICT_FSQRT
Constrained versions of libm-equivalent floating point intrinsics.
Definition ISDOpcodes.h:441
@ CONVERT_FROM_ARBITRARY_FP
CONVERT_FROM_ARBITRARY_FP - This operator converts from an arbitrary floating-point represented as an...
@ CTLZ_ZERO_POISON
Definition ISDOpcodes.h:814
@ PARTIAL_REDUCE_UMLA
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:870
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
Definition ISDOpcodes.h:725
@ STRICT_UINT_TO_FP
Definition ISDOpcodes.h:490
@ VECREDUCE_FADD
These reductions have relaxed evaluation order semantics, and have a single vector operand.
@ PARTIAL_REDUCE_FMLA
@ VECREDUCE_FMAXIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM nodes do not propagate NaNs and order signed zeroes using the llvm....
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ SSUBO
Same for subtraction.
Definition ISDOpcodes.h:355
@ VECTOR_INTERLEAVE
VECTOR_INTERLEAVE(VEC1, VEC2, ...) - Returns N vectors from N input vectors, where N is the factor to...
Definition ISDOpcodes.h:640
@ STEP_VECTOR
STEP_VECTOR(IMM) - Returns a scalable vector whose lanes are comprised of a linear sequence of unsign...
Definition ISDOpcodes.h:701
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
Definition ISDOpcodes.h:546
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
Definition ISDOpcodes.h:377
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:822
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
Definition ISDOpcodes.h:682
@ GET_ACTIVE_LANE_MASK
GET_ACTIVE_LANE_MASK - this corrosponds to the llvm.get.active.lane.mask intrinsic.
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
Definition ISDOpcodes.h:351
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition ISDOpcodes.h:714
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:787
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Same as FMINNUM/FMAXNUM, except that a signaling NaN operand deterministi...
@ STRICT_FMAXIMUM
Definition ISDOpcodes.h:475
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:581
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:876
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:837
@ FMINNUM
FMINNUM/FMAXNUM - Same semantics as the llvm.minnum/maxnum intrinsics.
@ SSHLSAT
RESULT = [US]SHLSAT(LHS, RHS) - Perform saturation left shift.
Definition ISDOpcodes.h:389
@ SMULO
Same for multiplication.
Definition ISDOpcodes.h:359
@ ANY_EXTEND_VECTOR_INREG
ANY_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register any-extension of the low la...
Definition ISDOpcodes.h:925
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition ISDOpcodes.h:914
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:745
@ MASKED_UDIV
Masked vector arithmetic that returns poison on disabled lanes.
@ SDIVFIXSAT
Same as the corresponding unsaturated fixed point instructions, but the result is clamped between the...
Definition ISDOpcodes.h:416
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition ISDOpcodes.h:831
@ STRICT_SINT_TO_FP
STRICT_[US]INT_TO_FP - Convert a signed or unsigned integer to a floating point value.
Definition ISDOpcodes.h:489
@ MGATHER
Masked gather and scatter - load and store operations for a vector of random addresses with additiona...
@ STRICT_FROUNDEVEN
Definition ISDOpcodes.h:469
@ STRICT_FP_TO_UINT
Definition ISDOpcodes.h:483
@ PEXT
Parallel bit extract (compress) and parallel bit deposit (expand).
Definition ISDOpcodes.h:801
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
Definition ISDOpcodes.h:505
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:482
@ FMINIMUM
FMINIMUM/FMAXIMUM - Same semantics as the llvm.minimum/maximum intrinsics.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:952
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:510
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:757
@ SCMP
[US]CMP - 3-way comparison of signed or unsigned integers.
Definition ISDOpcodes.h:753
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
Definition ISDOpcodes.h:720
@ VECTOR_MATCH
VECTOR_MATCH - this corresponds to the llvm.experimental.vector.match intrinsic.
@ STRICT_FADD
Constrained versions of the binary floating point operators.
Definition ISDOpcodes.h:430
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition ISDOpcodes.h:55
@ CTTZ_ZERO_POISON
Bit counting operators with a poisoned result for zero inputs.
Definition ISDOpcodes.h:813
@ FFREXP
FFREXP - frexp, extract fractional and exponent component of a floating-point value.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
Definition ISDOpcodes.h:985
@ VECTOR_COMPRESS
VECTOR_COMPRESS(Vec, Mask, Passthru) consecutively place vector elements based on mask e....
Definition ISDOpcodes.h:709
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
Definition ISDOpcodes.h:947
@ STRICT_FNEARBYINT
Definition ISDOpcodes.h:461
@ 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:971
@ VECREDUCE_FMINIMUM
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:882
@ VECREDUCE_SEQ_FMUL
@ CONVERT_TO_ARBITRARY_FP
CONVERT_TO_ARBITRARY_FP - Converts a native FP value to an arbitrary floating-point format,...
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
Definition ISDOpcodes.h:64
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
Definition ISDOpcodes.h:539
@ PARTIAL_REDUCE_SUMLA
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
Definition ISDOpcodes.h:368
@ VECTOR_DEINTERLEAVE
VECTOR_DEINTERLEAVE(VEC1, VEC2, ...) - Returns N vectors from N input vectors, where N is the factor ...
Definition ISDOpcodes.h:629
@ CTTZ_ELTS_ZERO_POISON
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - Same semantics as the llvm.minimumnum/maximumnum intrinsics.
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
Definition ISDOpcodes.h:740
@ ABS_MIN_POISON
ABS with a poison result for INT_MIN.
Definition ISDOpcodes.h:769
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition ISDOpcodes.h:561
@ LOOP_DEPENDENCE_WAR_MASK
The llvm.loop.dependence.
LLVM_ABI NodeType getUnmaskedBinOpOpcode(unsigned MaskedOpc)
Given a MaskedOpc of ISD::MASKED_(U|S)(DIV|REM), returns the unmasked ISD::(U|S)(DIV|REM).
LLVM_ABI std::optional< unsigned > getVPMaskIdx(unsigned Opcode)
The operand position of the vector mask.
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.
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:381
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
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:1762
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
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:559
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition Sequence.h:341
#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:90
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
Definition ValueTypes.h:145
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:70
ElementCount getVectorElementCount() const
Definition ValueTypes.h:373
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
Definition ValueTypes.h:494
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:396
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
Definition ValueTypes.h:382
uint64_t getScalarSizeInBits() const
Definition ValueTypes.h:408
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
EVT changeVectorElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
Definition ValueTypes.h:98
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition ValueTypes.h:339
EVT changeVectorElementCount(LLVMContext &Context, ElementCount EC) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element coun...
Definition ValueTypes.h:109
bool isFixedLengthVector() const
Definition ValueTypes.h:199
bool isVector() const
Return true if this is a vector value type.
Definition ValueTypes.h:176
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
Definition ValueTypes.h:346
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
Definition ValueTypes.h:187
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition ValueTypes.h:351
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Definition ValueTypes.h:359
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
Definition ValueTypes.h:331
bool isInteger() const
Return true if this is an integer or a vector integer type.
Definition ValueTypes.h:160
CallingConv::ID getLibcallImplCallingConv(RTLIB::LibcallImpl Call) const
Get the CallingConv that should be used for the specified libcall.
static bool hasVectorMaskArgument(RTLIB::LibcallImpl Impl)
Returns true if the function has a vector mask argument, which is assumed to be the last argument.
LLVM_ABI std::pair< FunctionType *, AttributeList > getFunctionTy(LLVMContext &Ctx, const Triple &TT, const DataLayout &DL, RTLIB::LibcallImpl LibcallImpl) const