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