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 ExpandSubByteInsertExtractVectorElt(SDNode *Node);
145 SDValue ExpandFNEG(SDNode *Node);
146 SDValue ExpandFABS(SDNode *Node);
147 SDValue ExpandFCOPYSIGN(SDNode *Node);
148 void ExpandFSUB(SDNode *Node, SmallVectorImpl<SDValue> &Results);
149 void ExpandSETCC(SDNode *Node, SmallVectorImpl<SDValue> &Results);
150 SDValue ExpandBITREVERSE(SDNode *Node);
151 void ExpandUADDSUBO(SDNode *Node, SmallVectorImpl<SDValue> &Results);
152 void ExpandSADDSUBO(SDNode *Node, SmallVectorImpl<SDValue> &Results);
153 void ExpandMULO(SDNode *Node, SmallVectorImpl<SDValue> &Results);
154 void ExpandFixedPointDiv(SDNode *Node, SmallVectorImpl<SDValue> &Results);
155 void ExpandStrictFPOp(SDNode *Node, SmallVectorImpl<SDValue> &Results);
156 void ExpandREM(SDNode *Node, SmallVectorImpl<SDValue> &Results);
157
158 bool tryExpandVecMathCall(SDNode *Node,
159 function_ref<RTLIB::Libcall(EVT)> GetLibcall,
161
162 void UnrollStrictFPOp(SDNode *Node, SmallVectorImpl<SDValue> &Results);
163
164 /// Implements vector promotion.
165 ///
166 /// This is essentially just bitcasting the operands to a different type and
167 /// bitcasting the result back to the original type.
169
170 /// Implements [SU]INT_TO_FP vector promotion.
171 ///
172 /// This is a [zs]ext of the input operand to a larger integer type.
173 void PromoteINT_TO_FP(SDNode *Node, SmallVectorImpl<SDValue> &Results);
174
175 /// Implements FP_TO_[SU]INT vector promotion of the result type.
176 ///
177 /// It is promoted to a larger integer type. The result is then
178 /// truncated back to the original type.
179 void PromoteFP_TO_INT(SDNode *Node, SmallVectorImpl<SDValue> &Results);
180
181 /// Implements vector setcc operation promotion.
182 ///
183 /// All vector operands are promoted to a vector type with larger element
184 /// type.
185 void PromoteSETCC(SDNode *Node, SmallVectorImpl<SDValue> &Results);
186
187 void PromoteSTRICT(SDNode *Node, SmallVectorImpl<SDValue> &Results);
188
189 /// Calculate the reduction using a type of higher precision and round the
190 /// result to match the original type. Setting NonArithmetic signifies the
191 /// rounding of the result does not affect its value.
192 void PromoteFloatVECREDUCE(SDNode *Node, SmallVectorImpl<SDValue> &Results,
193 bool NonArithmetic);
194
195 void PromoteVECTOR_COMPRESS(SDNode *Node, SmallVectorImpl<SDValue> &Results);
196
197public:
198 VectorLegalizer(SelectionDAG& dag) :
199 DAG(dag), TLI(dag.getTargetLoweringInfo()) {}
200
201 /// Begin legalizer the vector operations in the DAG.
202 bool Run();
203};
204
205} // end anonymous namespace
206
207bool VectorLegalizer::Run() {
208 // Before we start legalizing vector nodes, check if there are any vectors.
209 bool HasVectors = false;
211 E = std::prev(DAG.allnodes_end()); I != std::next(E); ++I) {
212 // Check if the values of the nodes contain vectors. We don't need to check
213 // the operands because we are going to check their values at some point.
214 HasVectors = llvm::any_of(I->values(), [](EVT T) { return T.isVector(); });
215
216 // If we found a vector node we can start the legalization.
217 if (HasVectors)
218 break;
219 }
220
221 // If this basic block has no vectors then no need to legalize vectors.
222 if (!HasVectors)
223 return false;
224
225 // The legalize process is inherently a bottom-up recursive process (users
226 // legalize their uses before themselves). Given infinite stack space, we
227 // could just start legalizing on the root and traverse the whole graph. In
228 // practice however, this causes us to run out of stack space on large basic
229 // blocks. To avoid this problem, compute an ordering of the nodes where each
230 // node is only legalized after all of its operands are legalized.
233 E = std::prev(DAG.allnodes_end()); I != std::next(E); ++I)
234 LegalizeOp(SDValue(&*I, 0));
235
236 // Finally, it's possible the root changed. Get the new root.
237 SDValue OldRoot = DAG.getRoot();
238 assert(LegalizedNodes.count(OldRoot) && "Root didn't get legalized?");
239 DAG.setRoot(LegalizedNodes[OldRoot]);
240
241 LegalizedNodes.clear();
242
243 // Remove dead nodes now.
244 DAG.RemoveDeadNodes();
245
246 return Changed;
247}
248
249SDValue VectorLegalizer::TranslateLegalizeResults(SDValue Op, SDNode *Result) {
250 assert(Op->getNumValues() == Result->getNumValues() &&
251 "Unexpected number of results");
252 // Generic legalization: just pass the operand through.
253 for (unsigned i = 0, e = Op->getNumValues(); i != e; ++i)
254 AddLegalizedOperand(Op.getValue(i), SDValue(Result, i));
255 return SDValue(Result, Op.getResNo());
256}
257
259VectorLegalizer::RecursivelyLegalizeResults(SDValue Op,
261 assert(Results.size() == Op->getNumValues() &&
262 "Unexpected number of results");
263 // Make sure that the generated code is itself legal.
264 for (unsigned i = 0, e = Results.size(); i != e; ++i) {
265 Results[i] = LegalizeOp(Results[i]);
266 AddLegalizedOperand(Op.getValue(i), Results[i]);
267 }
268
269 return Results[Op.getResNo()];
270}
271
272SDValue VectorLegalizer::LegalizeOp(SDValue Op) {
273 // Note that LegalizeOp may be reentered even from single-use nodes, which
274 // means that we always must cache transformed nodes.
275 auto I = LegalizedNodes.find(Op);
276 if (I != LegalizedNodes.end()) return I->second;
277
278 // Legalize the operands
280 for (const SDValue &Oper : Op->op_values())
281 Ops.push_back(LegalizeOp(Oper));
282
283 SDNode *Node = DAG.UpdateNodeOperands(Op.getNode(), Ops);
284
285 bool HasVectorValueOrOp =
286 llvm::any_of(Node->values(), [](EVT T) { return T.isVector(); }) ||
287 llvm::any_of(Node->op_values(),
288 [](SDValue O) { return O.getValueType().isVector(); });
289 if (!HasVectorValueOrOp)
290 return TranslateLegalizeResults(Op, Node);
291
292 TargetLowering::LegalizeAction Action = TargetLowering::Legal;
293 EVT ValVT;
294 switch (Op.getOpcode()) {
295 default:
296 return TranslateLegalizeResults(Op, Node);
297 case ISD::LOAD: {
298 LoadSDNode *LD = cast<LoadSDNode>(Node);
299 ISD::LoadExtType ExtType = LD->getExtensionType();
300 EVT LoadedVT = LD->getMemoryVT();
301 if (LoadedVT.isVector() && ExtType != ISD::NON_EXTLOAD)
302 Action = TLI.getLoadAction(LD->getValueType(0), LoadedVT, LD->getAlign(),
303 LD->getAddressSpace(), ExtType, false);
304 break;
305 }
306 case ISD::STORE: {
307 StoreSDNode *ST = cast<StoreSDNode>(Node);
308 EVT StVT = ST->getMemoryVT();
309 MVT ValVT = ST->getValue().getSimpleValueType();
310 if (StVT.isVector() && ST->isTruncatingStore())
311 Action = TLI.getTruncStoreAction(ValVT, StVT, ST->getAlign(),
312 ST->getAddressSpace());
313 break;
314 }
317 // Expanding a variable index through the stack cannot address elements
318 // narrower than a byte. Constant indices are left to LegalizeDAG.
319 EVT VecVT = Node->getOperand(0).getValueType();
320 SDValue Idx = Node->getOperand(Node->getNumOperands() - 1);
321 if (!VecVT.getVectorElementType().isByteSized() &&
323 Action = TLI.getOperationAction(Node->getOpcode(), VecVT);
324 break;
325 }
327 Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
328 // This operation lies about being legal: when it claims to be legal,
329 // it should actually be expanded.
330 if (Action == TargetLowering::Legal)
331 Action = TargetLowering::Expand;
332 break;
333#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
334 case ISD::STRICT_##DAGN:
335#include "llvm/IR/ConstrainedOps.def"
336 ValVT = Node->getValueType(0);
337 if (Op.getOpcode() == ISD::STRICT_SINT_TO_FP ||
338 Op.getOpcode() == ISD::STRICT_UINT_TO_FP)
339 ValVT = Node->getOperand(1).getValueType();
340 if (Op.getOpcode() == ISD::STRICT_FSETCC ||
341 Op.getOpcode() == ISD::STRICT_FSETCCS) {
342 MVT OpVT = Node->getOperand(1).getSimpleValueType();
343 ISD::CondCode CCCode = Node->getOperandCondCode(3);
344 Action = TLI.getCondCodeAction(CCCode, OpVT);
345 if (Action == TargetLowering::Legal)
346 Action = TLI.getOperationAction(Node->getOpcode(), OpVT);
347 } else {
348 Action = TLI.getOperationAction(Node->getOpcode(), ValVT);
349 }
350 // If we're asked to expand a strict vector floating-point operation,
351 // by default we're going to simply unroll it. That is usually the
352 // best approach, except in the case where the resulting strict (scalar)
353 // operations would themselves use the fallback mutation to non-strict.
354 // In that specific case, just do the fallback on the vector op.
355 if (Action == TargetLowering::Expand && !TLI.isStrictFPEnabled() &&
356 TLI.getStrictFPOperationAction(Node->getOpcode(), ValVT) ==
357 TargetLowering::Legal) {
358 EVT EltVT = ValVT.getVectorElementType();
359 if (TLI.getOperationAction(Node->getOpcode(), EltVT)
360 == TargetLowering::Expand &&
361 TLI.getStrictFPOperationAction(Node->getOpcode(), EltVT)
362 == TargetLowering::Legal)
363 Action = TargetLowering::Legal;
364 }
365 break;
366 case ISD::ADD:
367 case ISD::SUB:
368 case ISD::MUL:
369 case ISD::MULHS:
370 case ISD::MULHU:
371 case ISD::SDIV:
372 case ISD::UDIV:
373 case ISD::SREM:
374 case ISD::UREM:
375 case ISD::SDIVREM:
376 case ISD::UDIVREM:
377 case ISD::FADD:
378 case ISD::FSUB:
379 case ISD::FMUL:
380 case ISD::FDIV:
381 case ISD::FREM:
382 case ISD::AND:
383 case ISD::OR:
384 case ISD::XOR:
385 case ISD::SHL:
386 case ISD::SRA:
387 case ISD::SRL:
388 case ISD::FSHL:
389 case ISD::FSHR:
390 case ISD::ROTL:
391 case ISD::ROTR:
392 case ISD::ABS:
394 case ISD::ABDS:
395 case ISD::ABDU:
396 case ISD::AVGCEILS:
397 case ISD::AVGCEILU:
398 case ISD::AVGFLOORS:
399 case ISD::AVGFLOORU:
402 case ISD::BSWAP:
403 case ISD::BITREVERSE:
404 case ISD::CTLZ:
405 case ISD::CTTZ:
408 case ISD::CTPOP:
409 case ISD::CLMUL:
410 case ISD::CLMULH:
411 case ISD::CLMULR:
412 case ISD::SELECT:
413 case ISD::VSELECT:
414 case ISD::SELECT_CC:
415 case ISD::ZERO_EXTEND:
416 case ISD::ANY_EXTEND:
417 case ISD::TRUNCATE:
418 case ISD::SIGN_EXTEND:
419 case ISD::FP_TO_SINT:
420 case ISD::FP_TO_UINT:
421 case ISD::FNEG:
422 case ISD::FABS:
423 case ISD::FMINNUM:
424 case ISD::FMAXNUM:
427 case ISD::FMINIMUM:
428 case ISD::FMAXIMUM:
429 case ISD::FMINIMUMNUM:
430 case ISD::FMAXIMUMNUM:
431 case ISD::FCOPYSIGN:
432 case ISD::FSQRT:
433 case ISD::FSIN:
434 case ISD::FCOS:
435 case ISD::FTAN:
436 case ISD::FASIN:
437 case ISD::FACOS:
438 case ISD::FATAN:
439 case ISD::FATAN2:
440 case ISD::FSINH:
441 case ISD::FCOSH:
442 case ISD::FTANH:
443 case ISD::FLDEXP:
444 case ISD::FPOWI:
445 case ISD::FPOW:
446 case ISD::FCBRT:
447 case ISD::FLOG:
448 case ISD::FLOG2:
449 case ISD::FLOG10:
450 case ISD::FEXP:
451 case ISD::FEXP2:
452 case ISD::FEXP10:
453 case ISD::FCEIL:
454 case ISD::FTRUNC:
455 case ISD::FRINT:
456 case ISD::FNEARBYINT:
457 case ISD::FROUND:
458 case ISD::FROUNDEVEN:
459 case ISD::FFLOOR:
460 case ISD::FP_ROUND:
461 case ISD::FP_EXTEND:
463 case ISD::FMA:
468 case ISD::SMIN:
469 case ISD::SMAX:
470 case ISD::UMIN:
471 case ISD::UMAX:
472 case ISD::SMUL_LOHI:
473 case ISD::UMUL_LOHI:
474 case ISD::SADDO:
475 case ISD::UADDO:
476 case ISD::SSUBO:
477 case ISD::USUBO:
478 case ISD::SMULO:
479 case ISD::UMULO:
483 case ISD::FFREXP:
484 case ISD::FMODF:
485 case ISD::FSINCOS:
486 case ISD::FSINCOSPI:
487 case ISD::SADDSAT:
488 case ISD::UADDSAT:
489 case ISD::SSUBSAT:
490 case ISD::USUBSAT:
491 case ISD::SSHLSAT:
492 case ISD::USHLSAT:
495 case ISD::MGATHER:
498 case ISD::SCMP:
499 case ISD::UCMP:
504 case ISD::MASKED_UDIV:
505 case ISD::MASKED_SDIV:
506 case ISD::MASKED_UREM:
507 case ISD::MASKED_SREM:
509 Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
510 break;
513 EVT VT = Node->getValueType(0);
514 unsigned Factor = Node->getNumOperands();
515 Action = TLI.getVectorInterleaveAction(Node->getOpcode(), Factor, VT);
516 // Early Custom Lowering causes RISC-V regressions.
517 if (Action == TargetLowering::Custom &&
518 (VT.isScalableVector() || Factor != 2)) {
519 Action = TargetLowering::Legal;
520 }
521 break;
522 }
523 case ISD::SMULFIX:
524 case ISD::SMULFIXSAT:
525 case ISD::UMULFIX:
526 case ISD::UMULFIXSAT:
527 case ISD::SDIVFIX:
528 case ISD::SDIVFIXSAT:
529 case ISD::UDIVFIX:
530 case ISD::UDIVFIXSAT: {
531 unsigned Scale = Node->getConstantOperandVal(2);
532 Action = TLI.getFixedPointOperationAction(Node->getOpcode(),
533 Node->getValueType(0), Scale);
534 break;
535 }
536 case ISD::LROUND:
537 case ISD::LLROUND:
538 case ISD::LRINT:
539 case ISD::LLRINT:
540 case ISD::SINT_TO_FP:
541 case ISD::UINT_TO_FP:
559 case ISD::CTTZ_ELTS:
562 Action = TLI.getOperationAction(Node->getOpcode(),
563 Node->getOperand(0).getValueType());
564 break;
567 Action = TLI.getOperationAction(Node->getOpcode(),
568 Node->getOperand(1).getValueType());
569 break;
570 case ISD::SETCC: {
571 MVT OpVT = Node->getOperand(0).getSimpleValueType();
572 ISD::CondCode CCCode = Node->getOperandCondCode(2);
573 Action = TLI.getCondCodeAction(CCCode, OpVT);
574 if (Action == TargetLowering::Legal)
575 Action = TLI.getOperationAction(Node->getOpcode(), OpVT);
576 break;
577 }
582 Action =
583 TLI.getPartialReduceMLAAction(Op.getOpcode(), Node->getValueType(0),
584 Node->getOperand(1).getValueType());
585 break;
586
587#define BEGIN_REGISTER_VP_SDNODE(VPID, LEGALPOS, ...) \
588 case ISD::VPID: { \
589 EVT LegalizeVT = LEGALPOS < 0 ? Node->getValueType(-(1 + LEGALPOS)) \
590 : Node->getOperand(LEGALPOS).getValueType(); \
591 /* Defer non-vector results to LegalizeDAG. */ \
592 if (!Node->getValueType(0).isVector() && \
593 Node->getValueType(0) != MVT::Other) { \
594 Action = TargetLowering::Legal; \
595 break; \
596 } \
597 Action = TLI.getOperationAction(Node->getOpcode(), LegalizeVT); \
598 } break;
599#include "llvm/IR/VPIntrinsics.def"
600 }
601
602 LLVM_DEBUG(dbgs() << "\nLegalizing vector op: "; Node->dump(&DAG));
603
604 SmallVector<SDValue, 8> ResultVals;
605 switch (Action) {
606 default: llvm_unreachable("This action is not supported yet!");
607 case TargetLowering::Promote:
608 assert((Op.getOpcode() != ISD::LOAD && Op.getOpcode() != ISD::STORE) &&
609 "This action is not supported yet!");
610 LLVM_DEBUG(dbgs() << "Promoting\n");
611 Promote(Node, ResultVals);
612 assert(!ResultVals.empty() && "No results for promotion?");
613 break;
614 case TargetLowering::Legal:
615 LLVM_DEBUG(dbgs() << "Legal node: nothing to do\n");
616 break;
617 case TargetLowering::Custom:
618 LLVM_DEBUG(dbgs() << "Trying custom legalization\n");
619 if (LowerOperationWrapper(Node, ResultVals))
620 break;
621 LLVM_DEBUG(dbgs() << "Could not custom legalize node\n");
622 [[fallthrough]];
623 case TargetLowering::Expand:
624 LLVM_DEBUG(dbgs() << "Expanding\n");
625 Expand(Node, ResultVals);
626 break;
627 }
628
629 if (ResultVals.empty())
630 return TranslateLegalizeResults(Op, Node);
631
632 Changed = true;
633 return RecursivelyLegalizeResults(Op, ResultVals);
634}
635
636// FIXME: This is very similar to TargetLowering::LowerOperationWrapper. Can we
637// merge them somehow?
638bool VectorLegalizer::LowerOperationWrapper(SDNode *Node,
639 SmallVectorImpl<SDValue> &Results) {
640 SDValue Res = TLI.LowerOperation(SDValue(Node, 0), DAG);
641
642 if (!Res.getNode())
643 return false;
644
645 if (Res == SDValue(Node, 0))
646 return true;
647
648 // If the original node has one result, take the return value from
649 // LowerOperation as is. It might not be result number 0.
650 if (Node->getNumValues() == 1) {
651 Results.push_back(Res);
652 return true;
653 }
654
655 // If the original node has multiple results, then the return node should
656 // have the same number of results.
657 assert((Node->getNumValues() == Res->getNumValues()) &&
658 "Lowering returned the wrong number of results!");
659
660 // Places new result values base on N result number.
661 for (unsigned I = 0, E = Node->getNumValues(); I != E; ++I)
662 Results.push_back(Res.getValue(I));
663
664 return true;
665}
666
667void VectorLegalizer::PromoteSETCC(SDNode *Node,
668 SmallVectorImpl<SDValue> &Results) {
669 MVT VecVT = Node->getOperand(0).getSimpleValueType();
670 MVT NewVecVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VecVT);
671
672 unsigned ExtOp = VecVT.isFloatingPoint() ? ISD::FP_EXTEND : ISD::ANY_EXTEND;
673
674 SDLoc DL(Node);
675 SmallVector<SDValue, 5> Operands(Node->getNumOperands());
676
677 Operands[0] = DAG.getNode(ExtOp, DL, NewVecVT, Node->getOperand(0));
678 Operands[1] = DAG.getNode(ExtOp, DL, NewVecVT, Node->getOperand(1));
679 Operands[2] = Node->getOperand(2);
680
681 EVT ResVT =
682 TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), NewVecVT);
683 SDValue Res =
684 DAG.getNode(Node->getOpcode(), DL, ResVT, Operands, Node->getFlags());
685 if (ResVT != Node->getValueType(0))
686 Res = DAG.getBoolExtOrTrunc(Res, DL, Node->getValueType(0), NewVecVT);
687 Results.push_back(Res);
688}
689
690void VectorLegalizer::PromoteSTRICT(SDNode *Node,
691 SmallVectorImpl<SDValue> &Results) {
692 MVT VecVT = Node->getOperand(1).getSimpleValueType();
693 MVT NewVecVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VecVT);
694
695 assert(VecVT.isFloatingPoint());
696
697 SDLoc DL(Node);
698 SmallVector<SDValue, 5> Operands(Node->getNumOperands());
700
701 for (unsigned j = 1; j != Node->getNumOperands(); ++j)
702 if (Node->getOperand(j).getValueType().isVector() &&
703 !(ISD::isVPOpcode(Node->getOpcode()) &&
704 ISD::getVPMaskIdx(Node->getOpcode()) == j)) // Skip mask operand.
705 {
706 // promote the vector operand.
707 SDValue Ext =
708 DAG.getNode(ISD::STRICT_FP_EXTEND, DL, {NewVecVT, MVT::Other},
709 {Node->getOperand(0), Node->getOperand(j)});
710 Operands[j] = Ext.getValue(0);
711 Chains.push_back(Ext.getValue(1));
712 } else
713 Operands[j] = Node->getOperand(j); // Skip no vector operand.
714
715 SDVTList VTs = DAG.getVTList(NewVecVT, Node->getValueType(1));
716
717 Operands[0] = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
718
719 SDValue Res =
720 DAG.getNode(Node->getOpcode(), DL, VTs, Operands, Node->getFlags());
721
722 SDValue Round =
723 DAG.getNode(ISD::STRICT_FP_ROUND, DL, {VecVT, MVT::Other},
724 {Res.getValue(1), Res.getValue(0),
725 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true)});
726
727 Results.push_back(Round.getValue(0));
728 Results.push_back(Round.getValue(1));
729}
730
731void VectorLegalizer::PromoteFloatVECREDUCE(SDNode *Node,
732 SmallVectorImpl<SDValue> &Results,
733 bool NonArithmetic) {
734 MVT OpVT = Node->getOperand(0).getSimpleValueType();
735 assert(OpVT.isFloatingPoint() && "Expected floating point reduction!");
736 MVT NewOpVT = TLI.getTypeToPromoteTo(Node->getOpcode(), OpVT);
737
738 SDLoc DL(Node);
739 SDValue NewOp = DAG.getNode(ISD::FP_EXTEND, DL, NewOpVT, Node->getOperand(0));
740 SDValue Rdx =
741 DAG.getNode(Node->getOpcode(), DL, NewOpVT.getVectorElementType(), NewOp,
742 Node->getFlags());
743 SDValue Res =
744 DAG.getNode(ISD::FP_ROUND, DL, Node->getValueType(0), Rdx,
745 DAG.getIntPtrConstant(NonArithmetic, DL, /*isTarget=*/true));
746 Results.push_back(Res);
747}
748
749void VectorLegalizer::PromoteVECTOR_COMPRESS(
750 SDNode *Node, SmallVectorImpl<SDValue> &Results) {
751 SDLoc DL(Node);
752 EVT VT = Node->getValueType(0);
753 MVT PromotedVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VT.getSimpleVT());
754 assert((VT.isInteger() || VT.getSizeInBits() == PromotedVT.getSizeInBits()) &&
755 "Only integer promotion or bitcasts between types is supported");
756
757 SDValue Vec = Node->getOperand(0);
758 SDValue Mask = Node->getOperand(1);
759 SDValue Passthru = Node->getOperand(2);
760 if (VT.isInteger()) {
761 Vec = DAG.getNode(ISD::ANY_EXTEND, DL, PromotedVT, Vec);
762 Mask = TLI.promoteTargetBoolean(DAG, Mask, PromotedVT);
763 Passthru = DAG.getNode(ISD::ANY_EXTEND, DL, PromotedVT, Passthru);
764 } else {
765 Vec = DAG.getBitcast(PromotedVT, Vec);
766 Passthru = DAG.getBitcast(PromotedVT, Passthru);
767 }
768
770 DAG.getNode(ISD::VECTOR_COMPRESS, DL, PromotedVT, Vec, Mask, Passthru);
771 Result = VT.isInteger() ? DAG.getNode(ISD::TRUNCATE, DL, VT, Result)
772 : DAG.getBitcast(VT, Result);
773 Results.push_back(Result);
774}
775
776void VectorLegalizer::Promote(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
777 // For a few operations there is a specific concept for promotion based on
778 // the operand's type.
779 switch (Node->getOpcode()) {
780 case ISD::SINT_TO_FP:
781 case ISD::UINT_TO_FP:
784 // "Promote" the operation by extending the operand.
785 PromoteINT_TO_FP(Node, Results);
786 return;
787 case ISD::FP_TO_UINT:
788 case ISD::FP_TO_SINT:
791 // Promote the operation by extending the operand.
792 PromoteFP_TO_INT(Node, Results);
793 return;
794 case ISD::SETCC:
795 // Promote the operation by extending the operand.
796 PromoteSETCC(Node, Results);
797 return;
798 case ISD::STRICT_FADD:
800 case ISD::STRICT_FDIV:
802 case ISD::STRICT_FMA:
807 case ISD::STRICT_FMUL:
813 case ISD::STRICT_FSUB:
815 PromoteSTRICT(Node, Results);
816 return;
819 PromoteFloatVECREDUCE(Node, Results, /*NonArithmetic=*/false);
820 return;
827 PromoteFloatVECREDUCE(Node, Results, /*NonArithmetic=*/true);
828 return;
830 PromoteVECTOR_COMPRESS(Node, Results);
831 return;
832
833 case ISD::FP_ROUND:
834 case ISD::FP_EXTEND:
835 // These operations are used to do promotion so they can't be promoted
836 // themselves.
837 llvm_unreachable("Don't know how to promote this operation!");
838 }
839
840 // There are currently two cases of vector promotion:
841 // 1) Bitcasting a vector of integers to a different type to a vector of the
842 // same overall length. For example, x86 promotes ISD::AND v2i32 to v1i64.
843 // 2) Extending a vector of floats to a vector of the same number of larger
844 // floats. For example, AArch64 promotes ISD::FADD on v4f16 to v4f32.
845 assert(Node->getNumValues() == 1 &&
846 "Can't promote a vector with multiple results!");
847 MVT VT = Node->getSimpleValueType(0);
848 MVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VT);
849 SDLoc dl(Node);
850 SmallVector<SDValue, 4> Operands(Node->getNumOperands());
851
852 for (unsigned j = 0; j != Node->getNumOperands(); ++j) {
853 // Do not promote the mask operand of a VP OP.
854 bool SkipPromote = ISD::isVPOpcode(Node->getOpcode()) &&
855 ISD::getVPMaskIdx(Node->getOpcode()) == j;
856 if (Node->getOperand(j).getValueType().isVector() && !SkipPromote)
857 if (Node->getOperand(j)
858 .getValueType()
859 .getVectorElementType()
860 .isFloatingPoint() &&
862 Operands[j] = DAG.getNode(ISD::FP_EXTEND, dl, NVT, Node->getOperand(j));
863 else
864 Operands[j] = DAG.getNode(ISD::BITCAST, dl, NVT, Node->getOperand(j));
865 else
866 Operands[j] = Node->getOperand(j);
867 }
868
869 SDValue Res =
870 DAG.getNode(Node->getOpcode(), dl, NVT, Operands, Node->getFlags());
871
872 if ((VT.isFloatingPoint() && NVT.isFloatingPoint()) ||
875 Res = DAG.getNode(ISD::FP_ROUND, dl, VT, Res,
876 DAG.getIntPtrConstant(0, dl, /*isTarget=*/true));
877 else
878 Res = DAG.getNode(ISD::BITCAST, dl, VT, Res);
879
880 Results.push_back(Res);
881}
882
883void VectorLegalizer::PromoteINT_TO_FP(SDNode *Node,
884 SmallVectorImpl<SDValue> &Results) {
885 // INT_TO_FP operations may require the input operand be promoted even
886 // when the type is otherwise legal.
887 bool IsStrict = Node->isStrictFPOpcode();
888 MVT VT = Node->getOperand(IsStrict ? 1 : 0).getSimpleValueType();
889 MVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VT);
891 "Vectors have different number of elements!");
892
893 SDLoc dl(Node);
894 SmallVector<SDValue, 4> Operands(Node->getNumOperands());
895
896 unsigned Opc = (Node->getOpcode() == ISD::UINT_TO_FP ||
897 Node->getOpcode() == ISD::STRICT_UINT_TO_FP)
900 for (unsigned j = 0; j != Node->getNumOperands(); ++j) {
901 if (Node->getOperand(j).getValueType().isVector())
902 Operands[j] = DAG.getNode(Opc, dl, NVT, Node->getOperand(j));
903 else
904 Operands[j] = Node->getOperand(j);
905 }
906
907 if (IsStrict) {
908 SDValue Res = DAG.getNode(Node->getOpcode(), dl,
909 {Node->getValueType(0), MVT::Other}, Operands);
910 Results.push_back(Res);
911 Results.push_back(Res.getValue(1));
912 return;
913 }
914
915 SDValue Res =
916 DAG.getNode(Node->getOpcode(), dl, Node->getValueType(0), Operands);
917 Results.push_back(Res);
918}
919
920// For FP_TO_INT we promote the result type to a vector type with wider
921// elements and then truncate the result. This is different from the default
922// PromoteVector which uses bitcast to promote thus assumning that the
923// promoted vector type has the same overall size.
924void VectorLegalizer::PromoteFP_TO_INT(SDNode *Node,
925 SmallVectorImpl<SDValue> &Results) {
926 MVT VT = Node->getSimpleValueType(0);
927 MVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VT);
928 bool IsStrict = Node->isStrictFPOpcode();
930 "Vectors have different number of elements!");
931
932 unsigned NewOpc = Node->getOpcode();
933 // Change FP_TO_UINT to FP_TO_SINT if possible.
934 // TODO: Should we only do this if FP_TO_UINT itself isn't legal?
935 if (NewOpc == ISD::FP_TO_UINT &&
937 NewOpc = ISD::FP_TO_SINT;
938
939 if (NewOpc == ISD::STRICT_FP_TO_UINT &&
941 NewOpc = ISD::STRICT_FP_TO_SINT;
942
943 SDLoc dl(Node);
944 SDValue Promoted, Chain;
945 if (IsStrict) {
946 Promoted = DAG.getNode(NewOpc, dl, {NVT, MVT::Other},
947 {Node->getOperand(0), Node->getOperand(1)});
948 Chain = Promoted.getValue(1);
949 } else
950 Promoted = DAG.getNode(NewOpc, dl, NVT, Node->getOperand(0));
951
952 // Assert that the converted value fits in the original type. If it doesn't
953 // (eg: because the value being converted is too big), then the result of the
954 // original operation was undefined anyway, so the assert is still correct.
955 if (Node->getOpcode() == ISD::FP_TO_UINT ||
956 Node->getOpcode() == ISD::STRICT_FP_TO_UINT)
957 NewOpc = ISD::AssertZext;
958 else
959 NewOpc = ISD::AssertSext;
960
961 Promoted = DAG.getNode(NewOpc, dl, NVT, Promoted,
962 DAG.getValueType(VT.getScalarType()));
963 Promoted = DAG.getNode(ISD::TRUNCATE, dl, VT, Promoted);
964 Results.push_back(Promoted);
965 if (IsStrict)
966 Results.push_back(Chain);
967}
968
969std::pair<SDValue, SDValue> VectorLegalizer::ExpandLoad(SDNode *N) {
970 LoadSDNode *LD = cast<LoadSDNode>(N);
971 return TLI.scalarizeVectorLoad(LD, DAG);
972}
973
974SDValue VectorLegalizer::ExpandSubByteInsertExtractVectorElt(SDNode *Node) {
975 SDLoc DL(Node);
976 LLVMContext &Ctx = *DAG.getContext();
977 SDValue Vec = Node->getOperand(0);
978 EVT VecVT = Vec.getValueType();
979 EVT EltVT = VecVT.getVectorElementType().getRoundIntegerType(Ctx);
980 EVT WideVT = VecVT.changeElementType(Ctx, EltVT);
981 Vec = DAG.getNode(ISD::ANY_EXTEND, DL, WideVT, Vec);
982
983 if (Node->getOpcode() == ISD::EXTRACT_VECTOR_ELT) {
984 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltVT, Vec,
985 Node->getOperand(1));
986 return DAG.getAnyExtOrTrunc(Elt, DL, Node->getValueType(0));
987 }
988
989 SDValue Elt = DAG.getAnyExtOrTrunc(Node->getOperand(1), DL, EltVT);
990 SDValue Ins = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, WideVT, Vec, Elt,
991 Node->getOperand(2));
992 return DAG.getNode(ISD::TRUNCATE, DL, VecVT, Ins);
993}
994
995SDValue VectorLegalizer::ExpandStore(SDNode *N) {
996 StoreSDNode *ST = cast<StoreSDNode>(N);
997 SDValue TF = TLI.scalarizeVectorStore(ST, DAG);
998 return TF;
999}
1000
1001void VectorLegalizer::Expand(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
1002 switch (Node->getOpcode()) {
1003 case ISD::LOAD: {
1004 std::pair<SDValue, SDValue> Tmp = ExpandLoad(Node);
1005 Results.push_back(Tmp.first);
1006 Results.push_back(Tmp.second);
1007 return;
1008 }
1009 case ISD::STORE:
1010 Results.push_back(ExpandStore(Node));
1011 return;
1012 case ISD::MERGE_VALUES:
1013 for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i)
1014 Results.push_back(Node->getOperand(i));
1015 return;
1018 Results.push_back(ExpandSubByteInsertExtractVectorElt(Node));
1019 return;
1022 return;
1025 return;
1027 if (SDValue Expanded = ExpandSEXTINREG(Node)) {
1028 Results.push_back(Expanded);
1029 return;
1030 }
1031 break;
1033 Results.push_back(ExpandANY_EXTEND_VECTOR_INREG(Node));
1034 return;
1036 Results.push_back(ExpandSIGN_EXTEND_VECTOR_INREG(Node));
1037 return;
1039 Results.push_back(ExpandZERO_EXTEND_VECTOR_INREG(Node));
1040 return;
1041 case ISD::BSWAP:
1042 if (SDValue Expanded = ExpandBSWAP(Node)) {
1043 Results.push_back(Expanded);
1044 return;
1045 }
1046 break;
1047 case ISD::VSELECT:
1048 if (SDValue Expanded = ExpandVSELECT(Node)) {
1049 Results.push_back(Expanded);
1050 return;
1051 }
1052 break;
1053 case ISD::VP_SREM:
1054 case ISD::VP_UREM:
1055 if (SDValue Expanded = ExpandVP_REM(Node)) {
1056 Results.push_back(Expanded);
1057 return;
1058 }
1059 break;
1060 case ISD::SELECT:
1061 if (SDValue Expanded = ExpandSELECT(Node)) {
1062 Results.push_back(Expanded);
1063 return;
1064 }
1065 break;
1066 case ISD::SELECT_CC: {
1067 if (Node->getValueType(0).isScalableVector()) {
1068 EVT CondVT = TLI.getSetCCResultType(
1069 DAG.getDataLayout(), *DAG.getContext(), Node->getValueType(0));
1070 SDValue SetCC =
1071 DAG.getNode(ISD::SETCC, SDLoc(Node), CondVT, Node->getOperand(0),
1072 Node->getOperand(1), Node->getOperand(4));
1073 Results.push_back(DAG.getSelect(SDLoc(Node), Node->getValueType(0), SetCC,
1074 Node->getOperand(2),
1075 Node->getOperand(3)));
1076 return;
1077 }
1078 break;
1079 }
1080 case ISD::FP_TO_UINT:
1081 ExpandFP_TO_UINT(Node, Results);
1082 return;
1083 case ISD::UINT_TO_FP:
1084 ExpandUINT_TO_FLOAT(Node, Results);
1085 return;
1086 case ISD::FNEG:
1087 if (SDValue Expanded = ExpandFNEG(Node)) {
1088 Results.push_back(Expanded);
1089 return;
1090 }
1091 break;
1092 case ISD::FABS:
1093 if (SDValue Expanded = ExpandFABS(Node)) {
1094 Results.push_back(Expanded);
1095 return;
1096 }
1097 break;
1098 case ISD::FCOPYSIGN:
1099 if (SDValue Expanded = ExpandFCOPYSIGN(Node)) {
1100 Results.push_back(Expanded);
1101 return;
1102 }
1103 break;
1104 case ISD::FCANONICALIZE: {
1105 // If the scalar element type has a
1106 // Legal/Custom FCANONICALIZE, don't
1107 // mess with the vector, fall back.
1108 EVT VT = Node->getValueType(0);
1109 EVT EltVT = VT.getVectorElementType();
1110 if (!VT.isScalableVector() &&
1112 TargetLowering::Expand)
1113 break;
1114 // Otherwise canonicalize the whole vector.
1115 SDValue Mul = TLI.expandFCANONICALIZE(Node, DAG);
1116 Results.push_back(Mul);
1117 return;
1118 }
1119 case ISD::FSUB:
1120 ExpandFSUB(Node, Results);
1121 return;
1122 case ISD::SETCC:
1123 ExpandSETCC(Node, Results);
1124 return;
1125 case ISD::ABS:
1127 if (SDValue Expanded = TLI.expandABS(Node, DAG)) {
1128 Results.push_back(Expanded);
1129 return;
1130 }
1131 break;
1132 case ISD::ABDS:
1133 case ISD::ABDU:
1134 if (SDValue Expanded = TLI.expandABD(Node, DAG)) {
1135 Results.push_back(Expanded);
1136 return;
1137 }
1138 break;
1139 case ISD::AVGCEILS:
1140 case ISD::AVGCEILU:
1141 case ISD::AVGFLOORS:
1142 case ISD::AVGFLOORU:
1143 if (SDValue Expanded = TLI.expandAVG(Node, DAG)) {
1144 Results.push_back(Expanded);
1145 return;
1146 }
1147 break;
1148 case ISD::BITREVERSE:
1149 if (SDValue Expanded = ExpandBITREVERSE(Node)) {
1150 Results.push_back(Expanded);
1151 return;
1152 }
1153 break;
1154 case ISD::CTPOP:
1155 if (SDValue Expanded = TLI.expandCTPOP(Node, DAG)) {
1156 Results.push_back(Expanded);
1157 return;
1158 }
1159 break;
1160 case ISD::CTLZ:
1162 if (SDValue Expanded = TLI.expandCTLZ(Node, DAG)) {
1163 Results.push_back(Expanded);
1164 return;
1165 }
1166 break;
1167 case ISD::CTTZ:
1169 if (SDValue Expanded = TLI.expandCTTZ(Node, DAG)) {
1170 Results.push_back(Expanded);
1171 return;
1172 }
1173 break;
1174 case ISD::FSHL:
1175 case ISD::FSHR:
1176 if (SDValue Expanded = TLI.expandFunnelShift(Node, DAG)) {
1177 Results.push_back(Expanded);
1178 return;
1179 }
1180 break;
1181 case ISD::CLMUL:
1182 case ISD::CLMULR:
1183 case ISD::CLMULH:
1184 if (SDValue Expanded = TLI.expandCLMUL(Node, DAG)) {
1185 Results.push_back(Expanded);
1186 return;
1187 }
1188 break;
1189 case ISD::PEXT:
1190 Results.push_back(TLI.expandPEXT(Node, DAG));
1191 return;
1192 case ISD::PDEP:
1193 Results.push_back(TLI.expandPDEP(Node, DAG));
1194 return;
1195 case ISD::ROTL:
1196 case ISD::ROTR:
1197 if (SDValue Expanded = TLI.expandROT(Node, false /*AllowVectorOps*/, DAG)) {
1198 Results.push_back(Expanded);
1199 return;
1200 }
1201 break;
1202 case ISD::FMINNUM:
1203 case ISD::FMAXNUM:
1204 if (SDValue Expanded = TLI.expandFMINNUM_FMAXNUM(Node, DAG)) {
1205 Results.push_back(Expanded);
1206 return;
1207 }
1208 break;
1209 case ISD::FMINIMUM:
1210 case ISD::FMAXIMUM:
1211 Results.push_back(TLI.expandFMINIMUM_FMAXIMUM(Node, DAG));
1212 return;
1213 case ISD::FMINIMUMNUM:
1214 case ISD::FMAXIMUMNUM:
1215 Results.push_back(TLI.expandFMINIMUMNUM_FMAXIMUMNUM(Node, DAG));
1216 return;
1217 case ISD::SMIN:
1218 case ISD::SMAX:
1219 case ISD::UMIN:
1220 case ISD::UMAX:
1221 if (SDValue Expanded = TLI.expandIntMINMAX(Node, DAG)) {
1222 Results.push_back(Expanded);
1223 return;
1224 }
1225 break;
1226 case ISD::UADDO:
1227 case ISD::USUBO:
1228 ExpandUADDSUBO(Node, Results);
1229 return;
1230 case ISD::SADDO:
1231 case ISD::SSUBO:
1232 ExpandSADDSUBO(Node, Results);
1233 return;
1234 case ISD::UMULO:
1235 case ISD::SMULO:
1236 ExpandMULO(Node, Results);
1237 return;
1238 case ISD::MULHS:
1239 case ISD::MULHU:
1240 if (SDValue Expanded = TLI.expandMULH(Node, DAG)) {
1241 Results.push_back(Expanded);
1242 return;
1243 }
1244 break;
1245 case ISD::USUBSAT:
1246 case ISD::SSUBSAT:
1247 case ISD::UADDSAT:
1248 case ISD::SADDSAT:
1249 if (SDValue Expanded = TLI.expandAddSubSat(Node, DAG)) {
1250 Results.push_back(Expanded);
1251 return;
1252 }
1253 break;
1254 case ISD::USHLSAT:
1255 case ISD::SSHLSAT:
1256 if (SDValue Expanded = TLI.expandShlSat(Node, DAG)) {
1257 Results.push_back(Expanded);
1258 return;
1259 }
1260 break;
1263 // Expand the fpsosisat if it is scalable to prevent it from unrolling below.
1264 if (Node->getValueType(0).isScalableVector()) {
1265 if (SDValue Expanded = TLI.expandFP_TO_INT_SAT(Node, DAG)) {
1266 Results.push_back(Expanded);
1267 return;
1268 }
1269 }
1270 break;
1271 case ISD::SMULFIX:
1272 case ISD::UMULFIX:
1273 case ISD::SMULFIXSAT:
1274 case ISD::UMULFIXSAT:
1275 if (SDValue Expanded = TLI.expandFixedPointMul(Node, DAG)) {
1276 Results.push_back(Expanded);
1277 return;
1278 }
1279 break;
1280 case ISD::SDIVFIX:
1281 case ISD::UDIVFIX:
1282 ExpandFixedPointDiv(Node, Results);
1283 return;
1284 case ISD::SDIVFIXSAT:
1285 case ISD::UDIVFIXSAT:
1286 break;
1287#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
1288 case ISD::STRICT_##DAGN:
1289#include "llvm/IR/ConstrainedOps.def"
1290 ExpandStrictFPOp(Node, Results);
1291 return;
1292 case ISD::VECREDUCE_ADD:
1293 case ISD::VECREDUCE_MUL:
1294 case ISD::VECREDUCE_AND:
1295 case ISD::VECREDUCE_OR:
1296 case ISD::VECREDUCE_XOR:
1309 Results.push_back(TLI.expandVecReduce(Node, DAG));
1310 return;
1315 Results.push_back(TLI.expandPartialReduceMLA(Node, DAG));
1316 return;
1319 Results.push_back(TLI.expandVecReduceSeq(Node, DAG));
1320 return;
1321 case ISD::VECTOR_MATCH:
1322 Results.push_back(TLI.expandVectorMatch(Node, DAG));
1323 return;
1324 case ISD::SREM:
1325 case ISD::UREM:
1326 ExpandREM(Node, Results);
1327 return;
1328 case ISD::VP_MERGE:
1329 if (SDValue Expanded = ExpandVP_MERGE(Node)) {
1330 Results.push_back(Expanded);
1331 return;
1332 }
1333 break;
1334 case ISD::FREM:
1335 if (tryExpandVecMathCall(Node, RTLIB::getREM, Results))
1336 return;
1337 break;
1338 case ISD::FSINCOS:
1339 case ISD::FSINCOSPI: {
1340 EVT VT = Node->getValueType(0);
1341 RTLIB::Libcall LC = Node->getOpcode() == ISD::FSINCOS
1342 ? RTLIB::getSINCOS(VT)
1343 : RTLIB::getSINCOSPI(VT);
1344 if (LC != RTLIB::UNKNOWN_LIBCALL &&
1346 return;
1347
1348 // TODO: Try to see if there's a narrower call available to use before
1349 // scalarizing.
1350 break;
1351 }
1352 case ISD::FPOW:
1353 if (tryExpandVecMathCall(Node, RTLIB::getPOW, Results))
1354 return;
1355
1356 // TODO: Try to see if there's a narrower call available to use before
1357 // scalarizing.
1358 break;
1359 case ISD::FCBRT:
1360 if (tryExpandVecMathCall(Node, RTLIB::getCBRT, Results))
1361 return;
1362
1363 // TODO: Try to see if there's a narrower call available to use before
1364 // scalarizing.
1365 break;
1366 case ISD::FMODF: {
1367 EVT VT = Node->getValueType(0);
1368 RTLIB::Libcall LC = RTLIB::getMODF(VT);
1369 if (LC != RTLIB::UNKNOWN_LIBCALL &&
1371 /*CallRetResNo=*/0))
1372 return;
1373 break;
1374 }
1376 Results.push_back(TLI.expandVECTOR_COMPRESS(Node, DAG));
1377 return;
1379 Results.push_back(TLI.expandVECTOR_SHUFFLE_VAR(Node, DAG));
1380 return;
1381 case ISD::CTTZ_ELTS:
1383 Results.push_back(TLI.expandCttzElts(Node, DAG));
1384 return;
1386 Results.push_back(TLI.expandVectorFindLastActive(Node, DAG));
1387 return;
1388 case ISD::SCMP:
1389 case ISD::UCMP:
1390 Results.push_back(TLI.expandCMP(Node, DAG));
1391 return;
1393 if (SDValue R = TLI.expandGetActiveLaneMask(Node, DAG))
1394 Results.push_back(R);
1395 return;
1398 Results.push_back(ExpandLOOP_DEPENDENCE_MASK(Node));
1399 return;
1401 Results.push_back(ExpandMASK_BEFOREFIRST(Node));
1402 return;
1403
1404 case ISD::FADD:
1405 case ISD::FMUL:
1406 case ISD::FMA:
1407 case ISD::FDIV:
1408 case ISD::FCEIL:
1409 case ISD::FFLOOR:
1410 case ISD::FNEARBYINT:
1411 case ISD::FRINT:
1412 case ISD::FROUND:
1413 case ISD::FROUNDEVEN:
1414 case ISD::FTRUNC:
1415 case ISD::FSQRT:
1416 if (SDValue Expanded = TLI.expandVectorNaryOpBySplitting(Node, DAG)) {
1417 Results.push_back(Expanded);
1418 return;
1419 }
1420 break;
1422 if (SDValue Expanded = TLI.expandCONVERT_TO_ARBITRARY_FP(Node, DAG))
1423 Results.push_back(Expanded);
1424 else
1425 Results.push_back(DAG.getPOISON(Node->getValueType(0)));
1426 return;
1428 if (SDValue Expanded = TLI.expandCONVERT_FROM_ARBITRARY_FP(Node, DAG))
1429 Results.push_back(Expanded);
1430 else
1431 Results.push_back(DAG.getPOISON(Node->getValueType(0)));
1432 return;
1433 case ISD::MASKED_UDIV:
1434 case ISD::MASKED_SDIV:
1435 case ISD::MASKED_UREM:
1436 case ISD::MASKED_SREM:
1437 Results.push_back(ExpandMaskedBinOp(Node));
1438 return;
1439 }
1440
1441 SDValue Unrolled = DAG.UnrollVectorOp(Node);
1442 if (Node->getNumValues() == 1) {
1443 Results.push_back(Unrolled);
1444 } else {
1445 assert(Node->getNumValues() == Unrolled->getNumValues() &&
1446 "VectorLegalizer Expand returned wrong number of results!");
1447 for (unsigned I = 0, E = Unrolled->getNumValues(); I != E; ++I)
1448 Results.push_back(Unrolled.getValue(I));
1449 }
1450}
1451
1452SDValue VectorLegalizer::ExpandSELECT(SDNode *Node) {
1453 // Lower a select instruction where the condition is a scalar and the
1454 // operands are vectors. Lower this select to VSELECT and implement it
1455 // using XOR AND OR. The selector bit is broadcasted.
1456 EVT VT = Node->getValueType(0);
1457 SDLoc DL(Node);
1458
1459 SDValue Mask = Node->getOperand(0);
1460 SDValue Op1 = Node->getOperand(1);
1461 SDValue Op2 = Node->getOperand(2);
1462
1463 assert(VT.isVector() && !Mask.getValueType().isVector()
1464 && Op1.getValueType() == Op2.getValueType() && "Invalid type");
1465
1466 // If we can't even use the basic vector operations of
1467 // AND,OR,XOR, we will have to scalarize the op.
1468 // Notice that the operation may be 'promoted' which means that it is
1469 // 'bitcasted' to another type which is handled.
1470 // Also, we need to be able to construct a splat vector using either
1471 // BUILD_VECTOR or SPLAT_VECTOR.
1472 // FIXME: Should we also permit fixed-length SPLAT_VECTOR as a fallback to
1473 // BUILD_VECTOR?
1474 if (TLI.getOperationAction(ISD::AND, VT) == TargetLowering::Expand ||
1475 TLI.getOperationAction(ISD::XOR, VT) == TargetLowering::Expand ||
1476 TLI.getOperationAction(ISD::OR, VT) == TargetLowering::Expand ||
1479 VT) == TargetLowering::Expand)
1480 return SDValue();
1481
1482 // Generate a mask operand.
1483 EVT MaskTy = VT.changeVectorElementTypeToInteger();
1484
1485 // What is the size of each element in the vector mask.
1486 EVT BitTy = MaskTy.getScalarType();
1487
1488 Mask = DAG.getSelect(DL, BitTy, Mask, DAG.getAllOnesConstant(DL, BitTy),
1489 DAG.getConstant(0, DL, BitTy));
1490
1491 // Broadcast the mask so that the entire vector is all one or all zero.
1492 Mask = DAG.getSplat(MaskTy, DL, Mask);
1493
1494 // Bitcast the operands to be the same type as the mask.
1495 // This is needed when we select between FP types because
1496 // the mask is a vector of integers.
1497 Op1 = DAG.getNode(ISD::BITCAST, DL, MaskTy, Op1);
1498 Op2 = DAG.getNode(ISD::BITCAST, DL, MaskTy, Op2);
1499
1500 SDValue NotMask = DAG.getNOT(DL, Mask, MaskTy);
1501
1502 Op1 = DAG.getNode(ISD::AND, DL, MaskTy, Op1, Mask);
1503 Op2 = DAG.getNode(ISD::AND, DL, MaskTy, Op2, NotMask);
1504 SDValue Val = DAG.getNode(ISD::OR, DL, MaskTy, Op1, Op2);
1505 return DAG.getNode(ISD::BITCAST, DL, Node->getValueType(0), Val);
1506}
1507
1508SDValue VectorLegalizer::ExpandSEXTINREG(SDNode *Node) {
1509 EVT VT = Node->getValueType(0);
1510
1511 // Make sure that the SRA and SHL instructions are available.
1512 if (TLI.getOperationAction(ISD::SRA, VT) == TargetLowering::Expand ||
1513 TLI.getOperationAction(ISD::SHL, VT) == TargetLowering::Expand)
1514 return SDValue();
1515
1516 SDLoc DL(Node);
1517 EVT OrigTy = cast<VTSDNode>(Node->getOperand(1))->getVT();
1518
1519 unsigned BW = VT.getScalarSizeInBits();
1520 unsigned OrigBW = OrigTy.getScalarSizeInBits();
1521 SDValue ShiftSz = DAG.getConstant(BW - OrigBW, DL, VT);
1522
1523 SDValue Op = DAG.getNode(ISD::SHL, DL, VT, Node->getOperand(0), ShiftSz);
1524 return DAG.getNode(ISD::SRA, DL, VT, Op, ShiftSz);
1525}
1526
1527// Generically expand a vector anyext in register to a shuffle of the relevant
1528// lanes into the appropriate locations, with other lanes left undef.
1529SDValue VectorLegalizer::ExpandANY_EXTEND_VECTOR_INREG(SDNode *Node) {
1530 SDLoc DL(Node);
1531 EVT VT = Node->getValueType(0);
1532 int NumElements = VT.getVectorNumElements();
1533 SDValue Src = Node->getOperand(0);
1534 EVT SrcVT = Src.getValueType();
1535 int NumSrcElements = SrcVT.getVectorNumElements();
1536
1537 // *_EXTEND_VECTOR_INREG SrcVT can be smaller than VT - so insert the vector
1538 // into a larger vector type.
1539 if (SrcVT.bitsLE(VT)) {
1540 assert((VT.getSizeInBits() % SrcVT.getScalarSizeInBits()) == 0 &&
1541 "ANY_EXTEND_VECTOR_INREG vector size mismatch");
1542 NumSrcElements = VT.getSizeInBits() / SrcVT.getScalarSizeInBits();
1543 SrcVT = EVT::getVectorVT(*DAG.getContext(), SrcVT.getScalarType(),
1544 NumSrcElements);
1545 Src = DAG.getInsertSubvector(DL, DAG.getUNDEF(SrcVT), Src, 0);
1546 }
1547
1548 // Build a base mask of undef shuffles.
1549 SmallVector<int, 16> ShuffleMask;
1550 ShuffleMask.resize(NumSrcElements, -1);
1551
1552 // Place the extended lanes into the correct locations.
1553 int ExtLaneScale = NumSrcElements / NumElements;
1554 int EndianOffset = DAG.getDataLayout().isBigEndian() ? ExtLaneScale - 1 : 0;
1555 for (int i = 0; i < NumElements; ++i)
1556 ShuffleMask[i * ExtLaneScale + EndianOffset] = i;
1557
1558 return DAG.getNode(
1559 ISD::BITCAST, DL, VT,
1560 DAG.getVectorShuffle(SrcVT, DL, Src, DAG.getPOISON(SrcVT), ShuffleMask));
1561}
1562
1563SDValue VectorLegalizer::ExpandSIGN_EXTEND_VECTOR_INREG(SDNode *Node) {
1564 SDLoc DL(Node);
1565 EVT VT = Node->getValueType(0);
1566 SDValue Src = Node->getOperand(0);
1567 EVT SrcVT = Src.getValueType();
1568
1569 // First build an any-extend node which can be legalized above when we
1570 // recurse through it.
1572
1573 // Now we need sign extend. This will be exanded to shifts if it isn't
1574 // supported.
1575 EVT ExtVT = EVT::getVectorVT(*DAG.getContext(), SrcVT.getVectorElementType(),
1577 return DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, VT, Op,
1578 DAG.getValueType(ExtVT));
1579}
1580
1581// Generically expand a vector zext in register to a shuffle of the relevant
1582// lanes into the appropriate locations, a blend of zero into the high bits,
1583// and a bitcast to the wider element type.
1584SDValue VectorLegalizer::ExpandZERO_EXTEND_VECTOR_INREG(SDNode *Node) {
1585 SDLoc DL(Node);
1586 EVT VT = Node->getValueType(0);
1587 int NumElements = VT.getVectorNumElements();
1588 SDValue Src = Node->getOperand(0);
1589 EVT SrcVT = Src.getValueType();
1590 int NumSrcElements = SrcVT.getVectorNumElements();
1591
1592 // *_EXTEND_VECTOR_INREG SrcVT can be smaller than VT - so insert the vector
1593 // into a larger vector type.
1594 if (SrcVT.bitsLE(VT)) {
1595 assert((VT.getSizeInBits() % SrcVT.getScalarSizeInBits()) == 0 &&
1596 "ZERO_EXTEND_VECTOR_INREG vector size mismatch");
1597 NumSrcElements = VT.getSizeInBits() / SrcVT.getScalarSizeInBits();
1598 SrcVT = EVT::getVectorVT(*DAG.getContext(), SrcVT.getScalarType(),
1599 NumSrcElements);
1600 Src = DAG.getInsertSubvector(DL, DAG.getUNDEF(SrcVT), Src, 0);
1601 }
1602
1603 // Build up a zero vector to blend into this one.
1604 SDValue Zero = DAG.getConstant(0, DL, SrcVT);
1605
1606 // Shuffle the incoming lanes into the correct position, and pull all other
1607 // lanes from the zero vector.
1608 auto ShuffleMask = llvm::to_vector<16>(llvm::seq<int>(0, NumSrcElements));
1609
1610 int ExtLaneScale = NumSrcElements / NumElements;
1611 int EndianOffset = DAG.getDataLayout().isBigEndian() ? ExtLaneScale - 1 : 0;
1612 for (int i = 0; i < NumElements; ++i)
1613 ShuffleMask[i * ExtLaneScale + EndianOffset] = NumSrcElements + i;
1614
1615 return DAG.getNode(ISD::BITCAST, DL, VT,
1616 DAG.getVectorShuffle(SrcVT, DL, Zero, Src, ShuffleMask));
1617}
1618
1619static void createBSWAPShuffleMask(EVT VT, SmallVectorImpl<int> &ShuffleMask) {
1620 int ScalarSizeInBytes = VT.getScalarSizeInBits() / 8;
1621 for (int I = 0, E = VT.getVectorNumElements(); I != E; ++I)
1622 for (int J = ScalarSizeInBytes - 1; J >= 0; --J)
1623 ShuffleMask.push_back((I * ScalarSizeInBytes) + J);
1624}
1625
1626SDValue VectorLegalizer::ExpandBSWAP(SDNode *Node) {
1627 EVT VT = Node->getValueType(0);
1628
1629 // Scalable vectors can't use shuffle expansion.
1630 if (VT.isScalableVector())
1631 return TLI.expandBSWAP(Node, DAG);
1632
1633 // Generate a byte wise shuffle mask for the BSWAP.
1634 SmallVector<int, 16> ShuffleMask;
1635 createBSWAPShuffleMask(VT, ShuffleMask);
1636 EVT ByteVT = EVT::getVectorVT(*DAG.getContext(), MVT::i8, ShuffleMask.size());
1637
1638 // Only emit a shuffle if the mask is legal.
1639 if (TLI.isShuffleMaskLegal(ShuffleMask, ByteVT)) {
1640 SDLoc DL(Node);
1641 SDValue Op = DAG.getNode(ISD::BITCAST, DL, ByteVT, Node->getOperand(0));
1642 Op = DAG.getVectorShuffle(ByteVT, DL, Op, DAG.getPOISON(ByteVT),
1643 ShuffleMask);
1644 return DAG.getNode(ISD::BITCAST, DL, VT, Op);
1645 }
1646
1647 // If we have the appropriate vector bit operations, it is better to use them
1648 // than unrolling and expanding each component.
1653 return TLI.expandBSWAP(Node, DAG);
1654
1655 // Otherwise let the caller unroll.
1656 return SDValue();
1657}
1658
1659SDValue VectorLegalizer::ExpandBITREVERSE(SDNode *Node) {
1660 EVT VT = Node->getValueType(0);
1661
1662 // We can't unroll or use shuffles for scalable vectors.
1663 if (VT.isScalableVector())
1664 return TLI.expandBITREVERSE(Node, DAG);
1665
1666 // If we have the scalar operation, it's probably cheaper to unroll it.
1668 return SDValue();
1669
1670 // If the vector element width is a whole number of bytes, test if its legal
1671 // to BSWAP shuffle the bytes and then perform the BITREVERSE on the byte
1672 // vector. This greatly reduces the number of bit shifts necessary.
1673 unsigned ScalarSizeInBits = VT.getScalarSizeInBits();
1674 if (ScalarSizeInBits > 8 && (ScalarSizeInBits % 8) == 0) {
1675 SmallVector<int, 16> BSWAPMask;
1676 createBSWAPShuffleMask(VT, BSWAPMask);
1677
1678 EVT ByteVT = EVT::getVectorVT(*DAG.getContext(), MVT::i8, BSWAPMask.size());
1679 if (TLI.isShuffleMaskLegal(BSWAPMask, ByteVT) &&
1685 SDLoc DL(Node);
1686 SDValue Op = DAG.getNode(ISD::BITCAST, DL, ByteVT, Node->getOperand(0));
1687 Op = DAG.getVectorShuffle(ByteVT, DL, Op, DAG.getPOISON(ByteVT),
1688 BSWAPMask);
1689 Op = DAG.getNode(ISD::BITREVERSE, DL, ByteVT, Op);
1690 Op = DAG.getNode(ISD::BITCAST, DL, VT, Op);
1691 return Op;
1692 }
1693 }
1694
1695 // If we have the appropriate vector bit operations, it is better to use them
1696 // than unrolling and expanding each component.
1701 return TLI.expandBITREVERSE(Node, DAG);
1702
1703 // Otherwise unroll.
1704 return SDValue();
1705}
1706
1707SDValue VectorLegalizer::ExpandVSELECT(SDNode *Node) {
1708 // Implement VSELECT in terms of XOR, AND, OR
1709 // on platforms which do not support blend natively.
1710 SDLoc DL(Node);
1711
1712 SDValue Mask = Node->getOperand(0);
1713 SDValue Op1 = Node->getOperand(1);
1714 SDValue Op2 = Node->getOperand(2);
1715
1716 EVT VT = Mask.getValueType();
1717
1718 // If we can't even use the basic vector operations of
1719 // AND,OR,XOR, we will have to scalarize the op.
1720 // Notice that the operation may be 'promoted' which means that it is
1721 // 'bitcasted' to another type which is handled.
1722 if (TLI.getOperationAction(ISD::AND, VT) == TargetLowering::Expand ||
1723 TLI.getOperationAction(ISD::XOR, VT) == TargetLowering::Expand ||
1724 TLI.getOperationAction(ISD::OR, VT) == TargetLowering::Expand)
1725 return SDValue();
1726
1727 // This operation also isn't safe with AND, OR, XOR when the boolean type is
1728 // 0/1 and the select operands aren't also booleans, as we need an all-ones
1729 // vector constant to mask with.
1730 // FIXME: Sign extend 1 to all ones if that's legal on the target.
1731 auto BoolContents = TLI.getBooleanContents(Op1.getValueType());
1732 if (BoolContents != TargetLowering::ZeroOrNegativeOneBooleanContent &&
1733 !(BoolContents == TargetLowering::ZeroOrOneBooleanContent &&
1734 Op1.getValueType().getVectorElementType() == MVT::i1))
1735 return SDValue();
1736
1737 // If the mask and the type are different sizes, unroll the vector op. This
1738 // can occur when getSetCCResultType returns something that is different in
1739 // size from the operand types. For example, v4i8 = select v4i32, v4i8, v4i8.
1740 if (VT.getSizeInBits() != Op1.getValueSizeInBits())
1741 return SDValue();
1742
1743 // Bitcast the operands to be the same type as the mask.
1744 // This is needed when we select between FP types because
1745 // the mask is a vector of integers.
1746 Op1 = DAG.getNode(ISD::BITCAST, DL, VT, Op1);
1747 Op2 = DAG.getNode(ISD::BITCAST, DL, VT, Op2);
1748
1749 SDValue NotMask = DAG.getNOT(DL, Mask, VT);
1750
1751 Op1 = DAG.getNode(ISD::AND, DL, VT, Op1, Mask);
1752 Op2 = DAG.getNode(ISD::AND, DL, VT, Op2, NotMask);
1753 SDValue Val = DAG.getNode(ISD::OR, DL, VT, Op1, Op2);
1754 return DAG.getNode(ISD::BITCAST, DL, Node->getValueType(0), Val);
1755}
1756
1757SDValue VectorLegalizer::ExpandVP_MERGE(SDNode *Node) {
1758 // Implement VP_MERGE in terms of VSELECT. Construct a mask where vector
1759 // indices less than the EVL/pivot are true. Combine that with the original
1760 // mask for a full-length mask. Use a full-length VSELECT to select between
1761 // the true and false values.
1762 SDLoc DL(Node);
1763
1764 SDValue Mask = Node->getOperand(0);
1765 SDValue Op1 = Node->getOperand(1);
1766 SDValue Op2 = Node->getOperand(2);
1767 SDValue EVL = Node->getOperand(3);
1768
1769 EVT MaskVT = Mask.getValueType();
1770 bool IsFixedLen = MaskVT.isFixedLengthVector();
1771
1772 EVT EVLVecVT = EVT::getVectorVT(*DAG.getContext(), EVL.getValueType(),
1773 MaskVT.getVectorElementCount());
1774
1775 // If we can't construct the EVL mask efficiently, it's better to unroll.
1776 if ((IsFixedLen &&
1778 (!IsFixedLen &&
1781 return SDValue();
1782
1783 // If using a SETCC would result in a different type than the mask type,
1784 // unroll.
1786 EVLVecVT) != MaskVT)
1787 return SDValue();
1788
1789 SDValue StepVec = DAG.getStepVector(DL, EVLVecVT);
1790 SDValue SplatEVL = DAG.getSplat(EVLVecVT, DL, EVL);
1791 SDValue EVLMask =
1792 DAG.getSetCC(DL, MaskVT, StepVec, SplatEVL, ISD::CondCode::SETULT);
1793
1794 SDValue FullMask =
1795 DAG.getNode(ISD::AND, DL, MaskVT, DAG.getFreeze(Mask), EVLMask);
1796 return DAG.getSelect(DL, Node->getValueType(0), FullMask, Op1, Op2);
1797}
1798
1799SDValue VectorLegalizer::ExpandVP_REM(SDNode *Node) {
1800 // Implement VP_SREM/UREM in terms of VP_SDIV/VP_UDIV, MUL, SUB.
1801 EVT VT = Node->getValueType(0);
1802
1803 unsigned DivOpc = Node->getOpcode() == ISD::VP_SREM ? ISD::VP_SDIV : ISD::VP_UDIV;
1804
1805 if (!TLI.isOperationLegalOrCustom(DivOpc, VT) ||
1808 return SDValue();
1809
1810 SDLoc DL(Node);
1811
1812 SDValue Dividend = Node->getOperand(0);
1813 SDValue Divisor = Node->getOperand(1);
1814 SDValue Mask = Node->getOperand(2);
1815 SDValue EVL = Node->getOperand(3);
1816
1817 // X % Y -> X-X/Y*Y
1818 SDValue Div = DAG.getNode(DivOpc, DL, VT, Dividend, Divisor, Mask, EVL);
1819 SDValue Mul = DAG.getNode(ISD::MUL, DL, VT, Divisor, Div);
1820 return DAG.getNode(ISD::SUB, DL, VT, Dividend, Mul);
1821}
1822
1823SDValue VectorLegalizer::ExpandLOOP_DEPENDENCE_MASK(SDNode *N) {
1824 return TLI.expandLoopDependenceMask(N, DAG);
1825}
1826
1827SDValue VectorLegalizer::ExpandMASK_BEFOREFIRST(SDNode *N) {
1828 // Expand to (get_active_lane_mask 0, (cttz_elts x))
1829 SDLoc DL(N);
1830 EVT VT = N->getValueType(0);
1831 EVT VecIdxVT = TLI.getVectorIdxTy(DAG.getDataLayout());
1832 SDValue CttzElts =
1833 DAG.getNode(ISD::CTTZ_ELTS, DL, VecIdxVT, N->getOperand(0));
1834 return DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, DL, VT,
1835 DAG.getConstant(0, DL, VecIdxVT), CttzElts);
1836}
1837
1838SDValue VectorLegalizer::ExpandMaskedBinOp(SDNode *N) {
1839 // Masked bin ops don't have undefined behaviour when dividing by zero
1840 // on disabled lanes and produce poison instead. Replace the divisor on the
1841 // disabled lanes with 1 to avoid division by zero or overflow.
1842 SDLoc dl(N);
1843 EVT VT = N->getValueType(0);
1844 SDValue SafeDivisor = DAG.getSelect(
1845 dl, VT, N->getOperand(2), N->getOperand(1), DAG.getConstant(1, dl, VT));
1846 return DAG.getNode(ISD::getUnmaskedBinOpOpcode(N->getOpcode()), dl, VT,
1847 N->getOperand(0), SafeDivisor);
1848}
1849
1850void VectorLegalizer::ExpandFP_TO_UINT(SDNode *Node,
1851 SmallVectorImpl<SDValue> &Results) {
1852 // Attempt to expand using TargetLowering.
1853 SDValue Result, Chain;
1854 if (TLI.expandFP_TO_UINT(Node, Result, Chain, DAG)) {
1855 Results.push_back(Result);
1856 if (Node->isStrictFPOpcode())
1857 Results.push_back(Chain);
1858 return;
1859 }
1860
1861 // Otherwise go ahead and unroll.
1862 if (Node->isStrictFPOpcode()) {
1863 UnrollStrictFPOp(Node, Results);
1864 return;
1865 }
1866
1867 Results.push_back(DAG.UnrollVectorOp(Node));
1868}
1869
1870void VectorLegalizer::ExpandUINT_TO_FLOAT(SDNode *Node,
1871 SmallVectorImpl<SDValue> &Results) {
1872 bool IsStrict = Node->isStrictFPOpcode();
1873 unsigned OpNo = IsStrict ? 1 : 0;
1874 SDValue Src = Node->getOperand(OpNo);
1875 EVT SrcVT = Src.getValueType();
1876 EVT DstVT = Node->getValueType(0);
1877 SDLoc DL(Node);
1878
1879 // Attempt to expand using TargetLowering.
1881 SDValue Chain;
1882 if (TLI.expandUINT_TO_FP(Node, Result, Chain, DAG)) {
1883 Results.push_back(Result);
1884 if (IsStrict)
1885 Results.push_back(Chain);
1886 return;
1887 }
1888
1889 // Make sure that the SINT_TO_FP and SRL instructions are available.
1890 if (((!IsStrict && TLI.getOperationAction(ISD::SINT_TO_FP, SrcVT) ==
1891 TargetLowering::Expand) ||
1892 (IsStrict && TLI.getOperationAction(ISD::STRICT_SINT_TO_FP, SrcVT) ==
1893 TargetLowering::Expand)) ||
1894 TLI.getOperationAction(ISD::SRL, SrcVT) == TargetLowering::Expand) {
1895 if (IsStrict) {
1896 UnrollStrictFPOp(Node, Results);
1897 return;
1898 }
1899
1900 Results.push_back(DAG.UnrollVectorOp(Node));
1901 return;
1902 }
1903
1904 unsigned BW = SrcVT.getScalarSizeInBits();
1905 assert((BW == 64 || BW == 32) &&
1906 "Elements in vector-UINT_TO_FP must be 32 or 64 bits wide");
1907
1908 // If STRICT_/FMUL is not supported by the target (in case of f16) replace the
1909 // UINT_TO_FP with a larger float and round to the smaller type
1910 if ((!IsStrict && !TLI.isOperationLegalOrCustom(ISD::FMUL, DstVT)) ||
1911 (IsStrict && !TLI.isOperationLegalOrCustom(ISD::STRICT_FMUL, DstVT))) {
1912 EVT FPVT = BW == 32 ? MVT::f32 : MVT::f64;
1913 SDValue UIToFP;
1915 SDValue TargetZero = DAG.getIntPtrConstant(0, DL, /*isTarget=*/true);
1916 EVT FloatVecVT = SrcVT.changeVectorElementType(*DAG.getContext(), FPVT);
1917 if (IsStrict) {
1918 UIToFP = DAG.getNode(ISD::STRICT_UINT_TO_FP, DL, {FloatVecVT, MVT::Other},
1919 {Node->getOperand(0), Src});
1920 Result = DAG.getNode(ISD::STRICT_FP_ROUND, DL, {DstVT, MVT::Other},
1921 {Node->getOperand(0), UIToFP, TargetZero});
1922 Results.push_back(Result);
1923 Results.push_back(Result.getValue(1));
1924 } else {
1925 UIToFP = DAG.getNode(ISD::UINT_TO_FP, DL, FloatVecVT, Src);
1926 Result = DAG.getNode(ISD::FP_ROUND, DL, DstVT, UIToFP, TargetZero);
1927 Results.push_back(Result);
1928 }
1929
1930 return;
1931 }
1932
1933 SDValue HalfWord = DAG.getConstant(BW / 2, DL, SrcVT);
1934
1935 // Constants to clear the upper part of the word.
1936 // Notice that we can also use SHL+SHR, but using a constant is slightly
1937 // faster on x86.
1938 uint64_t HWMask = (BW == 64) ? 0x00000000FFFFFFFF : 0x0000FFFF;
1939 SDValue HalfWordMask = DAG.getConstant(HWMask, DL, SrcVT);
1940
1941 // Two to the power of half-word-size.
1942 SDValue TWOHW = DAG.getConstantFP(1ULL << (BW / 2), DL, DstVT);
1943
1944 // Clear upper part of LO, lower HI
1945 SDValue HI = DAG.getNode(ISD::SRL, DL, SrcVT, Src, HalfWord);
1946 SDValue LO = DAG.getNode(ISD::AND, DL, SrcVT, Src, HalfWordMask);
1947
1948 if (IsStrict) {
1949 // Convert hi and lo to floats
1950 // Convert the hi part back to the upper values
1951 // TODO: Can any fast-math-flags be set on these nodes?
1952 SDValue fHI = DAG.getNode(ISD::STRICT_SINT_TO_FP, DL, {DstVT, MVT::Other},
1953 {Node->getOperand(0), HI});
1954 fHI = DAG.getNode(ISD::STRICT_FMUL, DL, {DstVT, MVT::Other},
1955 {fHI.getValue(1), fHI, TWOHW});
1956 SDValue fLO = DAG.getNode(ISD::STRICT_SINT_TO_FP, DL, {DstVT, MVT::Other},
1957 {Node->getOperand(0), LO});
1958
1959 SDValue TF = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, fHI.getValue(1),
1960 fLO.getValue(1));
1961
1962 // Add the two halves
1963 SDValue Result =
1964 DAG.getNode(ISD::STRICT_FADD, DL, {DstVT, MVT::Other}, {TF, fHI, fLO});
1965
1966 Results.push_back(Result);
1967 Results.push_back(Result.getValue(1));
1968 return;
1969 }
1970
1971 // Convert hi and lo to floats
1972 // Convert the hi part back to the upper values
1973 // TODO: Can any fast-math-flags be set on these nodes?
1974 SDValue fHI = DAG.getNode(ISD::SINT_TO_FP, DL, DstVT, HI);
1975 fHI = DAG.getNode(ISD::FMUL, DL, DstVT, fHI, TWOHW);
1976 SDValue fLO = DAG.getNode(ISD::SINT_TO_FP, DL, DstVT, LO);
1977
1978 // Add the two halves
1979 Results.push_back(DAG.getNode(ISD::FADD, DL, DstVT, fHI, fLO));
1980}
1981
1982SDValue VectorLegalizer::ExpandFNEG(SDNode *Node) {
1983 EVT VT = Node->getValueType(0);
1984 EVT IntVT = VT.changeVectorElementTypeToInteger();
1985
1987 return SDValue();
1988
1989 // Heuristic check to determine whether vector should be expanded to integer
1990 // operations or unrolled to scalar operations.
1991 // 1. Scalable vector is never unrolled.
1992 // 2. Fixed vector is unrolled if one of followings is true:
1993 // a. Vector only has 1 element and target knows how to handle scalar
1994 // FNEG (either legal or custom expand or promote).
1995 // b. Vector has more than 1 element and target supports scalar
1996 // FNEG natively and vector length <= 2(1 XOR + 1 CONST).
1997 // FIXME: Scalar construction instruction count varies in every architecture,
1998 // here we assume 1 instruction for now.
1999 if (VT.isFixedLengthVector()) {
2000 EVT EltVT = VT.getVectorElementType();
2001 unsigned NumElts = VT.getVectorNumElements();
2002 if ((NumElts == 1 &&
2004 (NumElts < 3 && TLI.isOperationLegal(ISD::FNEG, EltVT) &&
2005 TLI.isExtractVecEltCheap(VT, 0) &&
2006 (NumElts == 1 || TLI.isExtractVecEltCheap(VT, 1))))
2007 return SDValue();
2008 }
2009
2010 SDLoc DL(Node);
2011 SDValue Cast = DAG.getNode(ISD::BITCAST, DL, IntVT, Node->getOperand(0));
2012 SDValue SignMask = DAG.getConstant(
2013 APInt::getSignMask(IntVT.getScalarSizeInBits()), DL, IntVT);
2014 SDValue Xor = DAG.getNode(ISD::XOR, DL, IntVT, Cast, SignMask);
2015 return DAG.getNode(ISD::BITCAST, DL, VT, Xor);
2016}
2017
2018SDValue VectorLegalizer::ExpandFABS(SDNode *Node) {
2019 EVT VT = Node->getValueType(0);
2020 EVT IntVT = VT.changeVectorElementTypeToInteger();
2021
2023 return SDValue();
2024
2025 // Heuristic check to determine whether vector should be expanded to integer
2026 // operations or unrolled to scalar operations.
2027 // 1. Scalable vector is never unrolled.
2028 // 2. Fixed vector is unrolled if one of followings is true:
2029 // a. Vector only has 1 element and target knows how to handle scalar
2030 // FABS(either legal or custom expand or promote).
2031 // b. Vector has more than 1 element and target supports scalar
2032 // FABS natively and vector length <= 2(1 AND + 1 CONST).
2033 // FIXME: Scalar construction instruction count varies in every architecture,
2034 // here we assume 1 instruction for now.
2035 if (VT.isFixedLengthVector()) {
2036 EVT EltVT = VT.getVectorElementType();
2037 unsigned NumElts = VT.getVectorNumElements();
2038 if ((NumElts == 1 &&
2040 (NumElts < 3 && TLI.isOperationLegal(ISD::FABS, EltVT) &&
2041 TLI.isExtractVecEltCheap(VT, 0) &&
2042 (NumElts == 1 || TLI.isExtractVecEltCheap(VT, 1))))
2043 return SDValue();
2044 }
2045
2046 SDLoc DL(Node);
2047 SDValue Cast = DAG.getNode(ISD::BITCAST, DL, IntVT, Node->getOperand(0));
2048 SDValue ClearSignMask = DAG.getConstant(
2050 SDValue ClearedSign = DAG.getNode(ISD::AND, DL, IntVT, Cast, ClearSignMask);
2051 return DAG.getNode(ISD::BITCAST, DL, VT, ClearedSign);
2052}
2053
2054SDValue VectorLegalizer::ExpandFCOPYSIGN(SDNode *Node) {
2055 EVT VT = Node->getValueType(0);
2056 EVT IntVT = VT.changeVectorElementTypeToInteger();
2057
2058 if (VT != Node->getOperand(1).getValueType() ||
2061 return SDValue();
2062
2063 // Heuristic check to determine whether vector should be expanded to integer
2064 // operations or unrolled to scalar operations.
2065 // 1. Scalable vector is never unrolled.
2066 // 2. Fixed vector is unrolled if one of followings is true:
2067 // a. Vector only has 1 element and target knows how to handle scalar
2068 // FCOPYSIGN(either legal or custom expand or promote).
2069 // b. Vector has more than 1 element and target supports scalar
2070 // FCOPYSIGN natively and vector length <= 5(2 AND + 1 OR + 2 CONST).
2071 // FIXME: Scalar construction instruction count varies in every architecture,
2072 // here we assume 1 instruction for now.
2073 if (VT.isFixedLengthVector()) {
2074 EVT EltVT = VT.getVectorElementType();
2075 unsigned NumElts = VT.getVectorNumElements();
2076 if ((NumElts == 1 &&
2078 (NumElts < 6 && TLI.isOperationLegal(ISD::FCOPYSIGN, EltVT) &&
2079 TLI.isExtractVecEltCheap(VT, 0) &&
2080 (NumElts == 1 || TLI.isExtractVecEltCheap(VT, 1))))
2081 return SDValue();
2082 }
2083
2084 SDLoc DL(Node);
2085 SDValue Mag = DAG.getNode(ISD::BITCAST, DL, IntVT, Node->getOperand(0));
2086 SDValue Sign = DAG.getNode(ISD::BITCAST, DL, IntVT, Node->getOperand(1));
2087
2088 SDValue SignMask = DAG.getConstant(
2089 APInt::getSignMask(IntVT.getScalarSizeInBits()), DL, IntVT);
2090 SDValue SignBit = DAG.getNode(ISD::AND, DL, IntVT, Sign, SignMask);
2091
2092 SDValue ClearSignMask = DAG.getConstant(
2094 SDValue ClearedSign = DAG.getNode(ISD::AND, DL, IntVT, Mag, ClearSignMask);
2095
2096 SDValue CopiedSign = DAG.getNode(ISD::OR, DL, IntVT, ClearedSign, SignBit,
2098
2099 return DAG.getNode(ISD::BITCAST, DL, VT, CopiedSign);
2100}
2101
2102void VectorLegalizer::ExpandFSUB(SDNode *Node,
2103 SmallVectorImpl<SDValue> &Results) {
2104 // For floating-point values, (a-b) is the same as a+(-b). If FNEG is legal,
2105 // we can defer this to operation legalization where it will be lowered as
2106 // a+(-b).
2107 EVT VT = Node->getValueType(0);
2110 return; // Defer to LegalizeDAG
2111
2112 if (SDValue Expanded = TLI.expandVectorNaryOpBySplitting(Node, DAG)) {
2113 Results.push_back(Expanded);
2114 return;
2115 }
2116
2117 SDValue Tmp = DAG.UnrollVectorOp(Node);
2118 Results.push_back(Tmp);
2119}
2120
2121void VectorLegalizer::ExpandSETCC(SDNode *Node,
2122 SmallVectorImpl<SDValue> &Results) {
2123 bool NeedInvert = false;
2124 bool IsStrict = Node->getOpcode() == ISD::STRICT_FSETCC ||
2125 Node->getOpcode() == ISD::STRICT_FSETCCS;
2126 bool IsSignaling = Node->getOpcode() == ISD::STRICT_FSETCCS;
2127 unsigned Offset = IsStrict ? 1 : 0;
2128
2129 SDValue Chain = IsStrict ? Node->getOperand(0) : SDValue();
2130 SDValue LHS = Node->getOperand(0 + Offset);
2131 SDValue RHS = Node->getOperand(1 + Offset);
2132 SDValue CC = Node->getOperand(2 + Offset);
2133
2134 MVT OpVT = LHS.getSimpleValueType();
2135 ISD::CondCode CCCode = cast<CondCodeSDNode>(CC)->get();
2136
2137 if (TLI.getCondCodeAction(CCCode, OpVT) != TargetLowering::Expand) {
2138 if (IsStrict) {
2139 UnrollStrictFPOp(Node, Results);
2140 return;
2141 }
2142 Results.push_back(UnrollVSETCC(Node));
2143 return;
2144 }
2145
2146 SDLoc dl(Node);
2147 bool Legalized =
2148 TLI.LegalizeSetCCCondCode(DAG, Node->getValueType(0), LHS, RHS, CC,
2149 NeedInvert, dl, Chain, IsSignaling);
2150
2151 if (Legalized) {
2152 // If we expanded the SETCC by swapping LHS and RHS, or by inverting the
2153 // condition code, create a new SETCC node.
2154 if (CC.getNode()) {
2155 if (IsStrict) {
2156 LHS = DAG.getNode(Node->getOpcode(), dl, Node->getVTList(),
2157 {Chain, LHS, RHS, CC}, Node->getFlags());
2158 Chain = LHS.getValue(1);
2159 } else {
2160 LHS = DAG.getNode(ISD::SETCC, dl, Node->getValueType(0), LHS, RHS, CC,
2161 Node->getFlags());
2162 }
2163 }
2164
2165 // If we expanded the SETCC by inverting the condition code, then wrap
2166 // the existing SETCC in a NOT to restore the intended condition.
2167 if (NeedInvert)
2168 LHS = DAG.getLogicalNOT(dl, LHS, LHS->getValueType(0));
2169 } else {
2170 assert(!IsStrict && "Don't know how to expand for strict nodes.");
2171
2172 // Otherwise, SETCC for the given comparison type must be completely
2173 // illegal; expand it into a SELECT_CC.
2174 EVT VT = Node->getValueType(0);
2175 LHS = DAG.getNode(ISD::SELECT_CC, dl, VT, LHS, RHS,
2176 DAG.getBoolConstant(true, dl, VT, LHS.getValueType()),
2177 DAG.getBoolConstant(false, dl, VT, LHS.getValueType()),
2178 CC, Node->getFlags());
2179 }
2180
2181 Results.push_back(LHS);
2182 if (IsStrict)
2183 Results.push_back(Chain);
2184}
2185
2186void VectorLegalizer::ExpandUADDSUBO(SDNode *Node,
2187 SmallVectorImpl<SDValue> &Results) {
2188 SDValue Result, Overflow;
2189 TLI.expandUADDSUBO(Node, Result, Overflow, DAG);
2190 Results.push_back(Result);
2191 Results.push_back(Overflow);
2192}
2193
2194void VectorLegalizer::ExpandSADDSUBO(SDNode *Node,
2195 SmallVectorImpl<SDValue> &Results) {
2196 SDValue Result, Overflow;
2197 TLI.expandSADDSUBO(Node, Result, Overflow, DAG);
2198 Results.push_back(Result);
2199 Results.push_back(Overflow);
2200}
2201
2202void VectorLegalizer::ExpandMULO(SDNode *Node,
2203 SmallVectorImpl<SDValue> &Results) {
2204 SDValue Result, Overflow;
2205 if (!TLI.expandMULO(Node, Result, Overflow, DAG))
2206 std::tie(Result, Overflow) = DAG.UnrollVectorOverflowOp(Node);
2207
2208 Results.push_back(Result);
2209 Results.push_back(Overflow);
2210}
2211
2212void VectorLegalizer::ExpandFixedPointDiv(SDNode *Node,
2213 SmallVectorImpl<SDValue> &Results) {
2214 SDNode *N = Node;
2215 if (SDValue Expanded = TLI.expandFixedPointDiv(N->getOpcode(), SDLoc(N),
2216 N->getOperand(0), N->getOperand(1), N->getConstantOperandVal(2), DAG))
2217 Results.push_back(Expanded);
2218}
2219
2220void VectorLegalizer::ExpandStrictFPOp(SDNode *Node,
2221 SmallVectorImpl<SDValue> &Results) {
2222 switch (Node->getOpcode()) {
2223 default:
2224 break;
2226 ExpandUINT_TO_FLOAT(Node, Results);
2227 return;
2229 ExpandFP_TO_UINT(Node, Results);
2230 return;
2231 case ISD::STRICT_FSETCC:
2233 ExpandSETCC(Node, Results);
2234 return;
2235 case ISD::STRICT_FADD:
2236 case ISD::STRICT_FCEIL:
2237 case ISD::STRICT_FDIV:
2238 case ISD::STRICT_FFLOOR:
2239 case ISD::STRICT_FMA:
2240 case ISD::STRICT_FMUL:
2242 case ISD::STRICT_FRINT:
2243 case ISD::STRICT_FROUND:
2245 case ISD::STRICT_FTRUNC:
2246 case ISD::STRICT_FSQRT:
2247 case ISD::STRICT_FSUB: {
2248 if (SDValue Expanded = TLI.expandVectorNaryOpBySplitting(Node, DAG)) {
2249 Results.push_back(Expanded.getValue(0));
2250 Results.push_back(Expanded.getValue(1));
2251 return;
2252 }
2253 break;
2254 }
2255 }
2256
2257 UnrollStrictFPOp(Node, Results);
2258}
2259
2260void VectorLegalizer::ExpandREM(SDNode *Node,
2261 SmallVectorImpl<SDValue> &Results) {
2262 assert((Node->getOpcode() == ISD::SREM || Node->getOpcode() == ISD::UREM) &&
2263 "Expected REM node");
2264
2266 if (!TLI.expandREM(Node, Result, DAG))
2267 Result = DAG.UnrollVectorOp(Node);
2268 Results.push_back(Result);
2269}
2270
2271// Try to expand libm nodes into vector math routine calls. Callers provide the
2272// RTLIB::get<OP>(EVT) selector of the node's libcall family, which is used to
2273// look up mappings within RuntimeLibcallsInfo. The only mappings considered are
2274// those where the result and all operands are the same vector type. While
2275// predicated nodes are not supported, we will emit calls to masked routines by
2276// passing in a mask that is true for the lanes computed by the node.
2277bool VectorLegalizer::tryExpandVecMathCall(
2278 SDNode *Node, function_ref<RTLIB::Libcall(EVT)> GetLibcall,
2279 SmallVectorImpl<SDValue> &Results) {
2280 // Chain must be propagated but currently strict fp operations are down
2281 // converted to their none strict counterpart.
2282 assert(!Node->isStrictFPOpcode() && "Unexpected strict fp operation!");
2283
2284 EVT VT = Node->getValueType(0);
2285 LLVMContext &Ctx = *DAG.getContext();
2286 const LibcallLoweringInfo &Libcalls = DAG.getLibcalls();
2287
2288 // Try to widen the vector type when no libcall is available at that width.
2289 EVT CallVT = VT;
2290 RTLIB::LibcallImpl LCImpl =
2291 Libcalls.getVectorLibcallImplOrMasked(GetLibcall(CallVT));
2292 if (LCImpl == RTLIB::Unsupported && VT.getVectorElementCount().isScalar())
2293 return false;
2294 while (LCImpl == RTLIB::Unsupported) {
2295 CallVT = CallVT.getDoubleNumVectorElementsVT(Ctx);
2296 if (!CallVT.isSimple())
2297 return false;
2298 if (TLI.isTypeLegal(CallVT))
2299 LCImpl = Libcalls.getVectorLibcallImplOrMasked(GetLibcall(CallVT));
2300 }
2301
2302 const RTLIB::RuntimeLibcallsInfo &RTLCI = Libcalls.getRuntimeLibcallsInfo();
2303
2304 auto [FuncTy, FuncAttrs] = RTLCI.getFunctionTy(
2305 Ctx, DAG.getSubtarget().getTargetTriple(), DAG.getDataLayout(), LCImpl);
2306
2307 SDLoc DL(Node);
2308 TargetLowering::ArgListTy Args;
2309
2310 bool HasMaskArg = RTLCI.hasVectorMaskArgument(LCImpl);
2311
2312 // Sanity check just in case function has unexpected parameters.
2313 assert(FuncTy->getNumParams() == Node->getNumOperands() + HasMaskArg &&
2314 EVT::getEVT(FuncTy->getReturnType(), true) == CallVT &&
2315 "mismatch in value type and call signature type");
2316
2317 for (unsigned I = 0, E = FuncTy->getNumParams(); I != E; ++I) {
2318 Type *ParamTy = FuncTy->getParamType(I);
2319
2320 if (HasMaskArg && I == E - 1) {
2321 assert(cast<VectorType>(ParamTy)->getElementType()->isIntegerTy(1) &&
2322 cast<VectorType>(ParamTy)->getElementCount() ==
2323 CallVT.getVectorElementCount() &&
2324 "unexpected vector mask type");
2325 EVT MaskVT = EVT::getEVT(ParamTy, /*HandleUnknown=*/true);
2326 EVT SubMaskVT =
2328 SDValue Mask = DAG.getBoolConstant(true, DL, SubMaskVT, VT);
2329 // Only the lanes holding the node's elements need to be active.
2330 if (CallVT != VT)
2332 DL, DAG.getBoolConstant(false, DL, MaskVT, CallVT), Mask, 0);
2333 Args.emplace_back(Mask, ParamTy);
2334 } else {
2335 SDValue Op = Node->getOperand(I);
2336 assert(Op.getValueType() == VT && "mismatch in vector types");
2337 if (CallVT != VT) {
2338 unsigned NumConcat =
2340 SmallVector<SDValue, 4> Ops(NumConcat, Op);
2341 Op = DAG.getNode(ISD::CONCAT_VECTORS, DL, CallVT, Ops);
2342 }
2343 assert(Op.getValueType() == EVT::getEVT(ParamTy, true) &&
2344 "mismatch in value type and call argument type");
2345 Args.emplace_back(Op, ParamTy);
2346 }
2347 }
2348
2349 // Emit a call to the vector function.
2350 SDValue Callee =
2351 DAG.getExternalSymbol(LCImpl, TLI.getPointerTy(DAG.getDataLayout()));
2352 CallingConv::ID CC = RTLCI.getLibcallImplCallingConv(LCImpl);
2353
2354 TargetLowering::CallLoweringInfo CLI(DAG);
2355 CLI.setDebugLoc(DL)
2356 .setChain(DAG.getEntryNode())
2357 .setLibCallee(CC, FuncTy->getReturnType(), Callee, std::move(Args));
2358
2359 std::pair<SDValue, SDValue> CallResult = TLI.LowerCallTo(CLI);
2360 SDValue Result = CallResult.first;
2361 if (CallVT != VT)
2362 Result = DAG.getExtractSubvector(DL, VT, Result, 0);
2363 Results.push_back(Result);
2364 return true;
2365}
2366
2367void VectorLegalizer::UnrollStrictFPOp(SDNode *Node,
2368 SmallVectorImpl<SDValue> &Results) {
2369 EVT VT = Node->getValueType(0);
2370
2371 // Cannot unroll a scalable vector. Delay error reporting until the final
2372 // operation legalisation phase to maximise the chances of removing the node.
2373 if (VT.isScalableVector())
2374 return;
2375
2376 EVT EltVT = VT.getVectorElementType();
2377 unsigned NumElems = VT.getVectorNumElements();
2378 unsigned NumOpers = Node->getNumOperands();
2379 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
2380
2381 EVT TmpEltVT = EltVT;
2382 if (Node->getOpcode() == ISD::STRICT_FSETCC ||
2383 Node->getOpcode() == ISD::STRICT_FSETCCS)
2384 TmpEltVT = TLI.getSetCCResultType(DAG.getDataLayout(),
2385 *DAG.getContext(), TmpEltVT);
2386
2387 EVT ValueVTs[] = {TmpEltVT, MVT::Other};
2388 SDValue Chain = Node->getOperand(0);
2389 SDLoc dl(Node);
2390
2391 SmallVector<SDValue, 32> OpValues;
2392 SmallVector<SDValue, 32> OpChains;
2393 for (unsigned i = 0; i < NumElems; ++i) {
2395 SDValue Idx = DAG.getVectorIdxConstant(i, dl);
2396
2397 // The Chain is the first operand.
2398 Opers.push_back(Chain);
2399
2400 // Now process the remaining operands.
2401 for (unsigned j = 1; j < NumOpers; ++j) {
2402 SDValue Oper = Node->getOperand(j);
2403 EVT OperVT = Oper.getValueType();
2404
2405 if (OperVT.isVector())
2406 Oper = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl,
2407 OperVT.getVectorElementType(), Oper, Idx);
2408
2409 Opers.push_back(Oper);
2410 }
2411
2412 SDValue ScalarOp = DAG.getNode(Node->getOpcode(), dl, ValueVTs, Opers);
2413 SDValue ScalarResult = ScalarOp.getValue(0);
2414 SDValue ScalarChain = ScalarOp.getValue(1);
2415
2416 if (Node->getOpcode() == ISD::STRICT_FSETCC ||
2417 Node->getOpcode() == ISD::STRICT_FSETCCS)
2418 ScalarResult = DAG.getSelect(dl, EltVT, ScalarResult,
2419 DAG.getAllOnesConstant(dl, EltVT),
2420 DAG.getConstant(0, dl, EltVT));
2421
2422 OpValues.push_back(ScalarResult);
2423 OpChains.push_back(ScalarChain);
2424 }
2425
2426 SDValue Result = DAG.getBuildVector(VT, dl, OpValues);
2427 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OpChains);
2428
2429 Results.push_back(Result);
2430 Results.push_back(NewChain);
2431}
2432
2433SDValue VectorLegalizer::UnrollVSETCC(SDNode *Node) {
2434 EVT VT = Node->getValueType(0);
2435 unsigned NumElems = VT.getVectorNumElements();
2436 EVT EltVT = VT.getVectorElementType();
2437 SDValue LHS = Node->getOperand(0);
2438 SDValue RHS = Node->getOperand(1);
2439 SDValue CC = Node->getOperand(2);
2440 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
2441 SDLoc dl(Node);
2442 SmallVector<SDValue, 8> Ops(NumElems);
2443 for (unsigned i = 0; i < NumElems; ++i) {
2444 SDValue LHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, LHS,
2445 DAG.getVectorIdxConstant(i, dl));
2446 SDValue RHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, RHS,
2447 DAG.getVectorIdxConstant(i, dl));
2448 // FIXME: We should use i1 setcc + boolext here, but it causes regressions.
2449 Ops[i] = DAG.getNode(ISD::SETCC, dl,
2451 *DAG.getContext(), TmpEltVT),
2452 LHSElem, RHSElem, CC);
2453 Ops[i] = DAG.getSelect(dl, EltVT, Ops[i],
2454 DAG.getBoolConstant(true, dl, EltVT, VT),
2455 DAG.getConstant(0, dl, EltVT));
2456 }
2457 return DAG.getBuildVector(VT, dl, Ops);
2458}
2459
2461 return VectorLegalizer(*this).Run();
2462}
return SDValue()
const TargetLowering & TLI
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:852
const RTLIB::RuntimeLibcallsInfo & getRuntimeLibcallsInfo() const
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 getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
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)
LLVM_ABI SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either any-extending or truncat...
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...
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 expandVECTOR_SHUFFLE_VAR(SDNode *Node, SelectionDAG &DAG) const
Expand a VECTOR_SHUFFLE_VAR into variable-index element extracts.
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:851
@ 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:739
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:811
@ 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:885
@ 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:912
@ 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....
@ VECTOR_SHUFFLE_VAR
VECTOR_SHUFFLE_VAR(VEC, MASK) - Returns VEC permuted by MASK, an integer vector with the same number ...
Definition ISDOpcodes.h:665
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
Definition ISDOpcodes.h:771
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
Definition ISDOpcodes.h:942
@ 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:802
@ 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:820
@ PARTIAL_REDUCE_UMLA
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:876
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
Definition ISDOpcodes.h:731
@ 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:707
@ 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:828
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
Definition ISDOpcodes.h:688
@ 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:720
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:793
@ 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:882
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:843
@ 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:931
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition ISDOpcodes.h:920
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:751
@ 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:837
@ 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:807
@ 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:958
@ 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:763
@ SCMP
[US]CMP - 3-way comparison of signed or unsigned integers.
Definition ISDOpcodes.h:759
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
Definition ISDOpcodes.h:726
@ 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
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
Definition ISDOpcodes.h:570
@ 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:819
@ 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:991
@ VECTOR_COMPRESS
VECTOR_COMPRESS(Vec, Mask, Passthru) consecutively place vector elements based on mask e....
Definition ISDOpcodes.h:715
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
Definition ISDOpcodes.h:953
@ 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:977
@ VECREDUCE_FMINIMUM
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:888
@ 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:746
@ ABS_MIN_POISON
ABS with a poison result for INT_MIN.
Definition ISDOpcodes.h:775
@ 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...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
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:160
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:388
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
Definition ValueTypes.h:509
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:411
bool isByteSized() const
Return true if the bit size is a multiple of 8.
Definition ValueTypes.h:281
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
Definition ValueTypes.h:397
uint64_t getScalarSizeInBits() const
Definition ValueTypes.h:423
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:354
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:214
EVT getRoundIntegerType(LLVMContext &Context) const
Rounds the bit-width of the given integer EVT up to the nearest power of two (and at least to eight),...
Definition ValueTypes.h:457
bool isVector() const
Return true if this is a vector value type.
Definition ValueTypes.h:191
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
Definition ValueTypes.h:361
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
Definition ValueTypes.h:202
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition ValueTypes.h:366
EVT changeElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a type whose attributes match ourselves with the exception of the element type that i...
Definition ValueTypes.h:136
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Definition ValueTypes.h:374
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
Definition ValueTypes.h:346
bool isInteger() const
Return true if this is an integer or a vector integer type.
Definition ValueTypes.h:175
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