LLVM 24.0.0git
LegalizeVectorOps.cpp
Go to the documentation of this file.
1//===- LegalizeVectorOps.cpp - Implement SelectionDAG::LegalizeVectors ----===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the SelectionDAG::LegalizeVectors method.
10//
11// The vector legalizer looks for vector operations which might need to be
12// scalarized and legalizes them. This is a separate step from Legalize because
13// scalarizing can introduce illegal types. For example, suppose we have an
14// ISD::SDIV of type v2i64 on x86-32. The type is legal (for example, addition
15// on a v2i64 is legal), but ISD::SDIV isn't legal, so we have to unroll the
16// operation, which introduces nodes with the illegal type i64 which must be
17// expanded. Similarly, suppose we have an ISD::SRA of type v16i8 on PowerPC;
18// the operation must be unrolled, which introduces nodes with the illegal
19// type i8 which must be promoted.
20//
21// This does not legalize vector manipulations like ISD::BUILD_VECTOR,
22// or operations that happen to take a vector which are custom-lowered;
23// the legalization for such operations never produces nodes
24// with illegal types, so it's okay to put off legalizing them until
25// SelectionDAG::Legalize runs.
26//
27//===----------------------------------------------------------------------===//
28
29#include "llvm/ADT/DenseMap.h"
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_MERGE(SDNode *Node);
136 SDValue ExpandVP_REM(SDNode *Node);
137 SDValue ExpandLOOP_DEPENDENCE_MASK(SDNode *N);
138 SDValue ExpandMaskedBinOp(SDNode *N);
139 SDValue ExpandSELECT(SDNode *Node);
140 std::pair<SDValue, SDValue> ExpandLoad(SDNode *N);
141 SDValue ExpandStore(SDNode *N);
142 SDValue ExpandFNEG(SDNode *Node);
143 SDValue ExpandFABS(SDNode *Node);
144 SDValue ExpandFCOPYSIGN(SDNode *Node);
145 void ExpandFSUB(SDNode *Node, SmallVectorImpl<SDValue> &Results);
146 void ExpandSETCC(SDNode *Node, SmallVectorImpl<SDValue> &Results);
147 SDValue ExpandBITREVERSE(SDNode *Node);
148 void ExpandUADDSUBO(SDNode *Node, SmallVectorImpl<SDValue> &Results);
149 void ExpandSADDSUBO(SDNode *Node, SmallVectorImpl<SDValue> &Results);
150 void ExpandMULO(SDNode *Node, SmallVectorImpl<SDValue> &Results);
151 void ExpandFixedPointDiv(SDNode *Node, SmallVectorImpl<SDValue> &Results);
152 void ExpandStrictFPOp(SDNode *Node, SmallVectorImpl<SDValue> &Results);
153 void ExpandREM(SDNode *Node, SmallVectorImpl<SDValue> &Results);
154
155 bool tryExpandVecMathCall(SDNode *Node, RTLIB::Libcall LC,
157
158 void UnrollStrictFPOp(SDNode *Node, SmallVectorImpl<SDValue> &Results);
159
160 /// Implements vector promotion.
161 ///
162 /// This is essentially just bitcasting the operands to a different type and
163 /// bitcasting the result back to the original type.
165
166 /// Implements [SU]INT_TO_FP vector promotion.
167 ///
168 /// This is a [zs]ext of the input operand to a larger integer type.
169 void PromoteINT_TO_FP(SDNode *Node, SmallVectorImpl<SDValue> &Results);
170
171 /// Implements FP_TO_[SU]INT vector promotion of the result type.
172 ///
173 /// It is promoted to a larger integer type. The result is then
174 /// truncated back to the original type.
175 void PromoteFP_TO_INT(SDNode *Node, SmallVectorImpl<SDValue> &Results);
176
177 /// Implements vector setcc operation promotion.
178 ///
179 /// All vector operands are promoted to a vector type with larger element
180 /// type.
181 void PromoteSETCC(SDNode *Node, SmallVectorImpl<SDValue> &Results);
182
183 void PromoteSTRICT(SDNode *Node, SmallVectorImpl<SDValue> &Results);
184
185 /// Calculate the reduction using a type of higher precision and round the
186 /// result to match the original type. Setting NonArithmetic signifies the
187 /// rounding of the result does not affect its value.
188 void PromoteFloatVECREDUCE(SDNode *Node, SmallVectorImpl<SDValue> &Results,
189 bool NonArithmetic);
190
191 void PromoteVECTOR_COMPRESS(SDNode *Node, SmallVectorImpl<SDValue> &Results);
192
193public:
194 VectorLegalizer(SelectionDAG& dag) :
195 DAG(dag), TLI(dag.getTargetLoweringInfo()) {}
196
197 /// Begin legalizer the vector operations in the DAG.
198 bool Run();
199};
200
201} // end anonymous namespace
202
203bool VectorLegalizer::Run() {
204 // Before we start legalizing vector nodes, check if there are any vectors.
205 bool HasVectors = false;
207 E = std::prev(DAG.allnodes_end()); I != std::next(E); ++I) {
208 // Check if the values of the nodes contain vectors. We don't need to check
209 // the operands because we are going to check their values at some point.
210 HasVectors = llvm::any_of(I->values(), [](EVT T) { return T.isVector(); });
211
212 // If we found a vector node we can start the legalization.
213 if (HasVectors)
214 break;
215 }
216
217 // If this basic block has no vectors then no need to legalize vectors.
218 if (!HasVectors)
219 return false;
220
221 // The legalize process is inherently a bottom-up recursive process (users
222 // legalize their uses before themselves). Given infinite stack space, we
223 // could just start legalizing on the root and traverse the whole graph. In
224 // practice however, this causes us to run out of stack space on large basic
225 // blocks. To avoid this problem, compute an ordering of the nodes where each
226 // node is only legalized after all of its operands are legalized.
229 E = std::prev(DAG.allnodes_end()); I != std::next(E); ++I)
230 LegalizeOp(SDValue(&*I, 0));
231
232 // Finally, it's possible the root changed. Get the new root.
233 SDValue OldRoot = DAG.getRoot();
234 assert(LegalizedNodes.count(OldRoot) && "Root didn't get legalized?");
235 DAG.setRoot(LegalizedNodes[OldRoot]);
236
237 LegalizedNodes.clear();
238
239 // Remove dead nodes now.
240 DAG.RemoveDeadNodes();
241
242 return Changed;
243}
244
245SDValue VectorLegalizer::TranslateLegalizeResults(SDValue Op, SDNode *Result) {
246 assert(Op->getNumValues() == Result->getNumValues() &&
247 "Unexpected number of results");
248 // Generic legalization: just pass the operand through.
249 for (unsigned i = 0, e = Op->getNumValues(); i != e; ++i)
250 AddLegalizedOperand(Op.getValue(i), SDValue(Result, i));
251 return SDValue(Result, Op.getResNo());
252}
253
255VectorLegalizer::RecursivelyLegalizeResults(SDValue Op,
257 assert(Results.size() == Op->getNumValues() &&
258 "Unexpected number of results");
259 // Make sure that the generated code is itself legal.
260 for (unsigned i = 0, e = Results.size(); i != e; ++i) {
261 Results[i] = LegalizeOp(Results[i]);
262 AddLegalizedOperand(Op.getValue(i), Results[i]);
263 }
264
265 return Results[Op.getResNo()];
266}
267
268SDValue VectorLegalizer::LegalizeOp(SDValue Op) {
269 // Note that LegalizeOp may be reentered even from single-use nodes, which
270 // means that we always must cache transformed nodes.
271 auto I = LegalizedNodes.find(Op);
272 if (I != LegalizedNodes.end()) return I->second;
273
274 // Legalize the operands
276 for (const SDValue &Oper : Op->op_values())
277 Ops.push_back(LegalizeOp(Oper));
278
279 SDNode *Node = DAG.UpdateNodeOperands(Op.getNode(), Ops);
280
281 bool HasVectorValueOrOp =
282 llvm::any_of(Node->values(), [](EVT T) { return T.isVector(); }) ||
283 llvm::any_of(Node->op_values(),
284 [](SDValue O) { return O.getValueType().isVector(); });
285 if (!HasVectorValueOrOp)
286 return TranslateLegalizeResults(Op, Node);
287
288 TargetLowering::LegalizeAction Action = TargetLowering::Legal;
289 EVT ValVT;
290 switch (Op.getOpcode()) {
291 default:
292 return TranslateLegalizeResults(Op, Node);
293 case ISD::LOAD: {
294 LoadSDNode *LD = cast<LoadSDNode>(Node);
295 ISD::LoadExtType ExtType = LD->getExtensionType();
296 EVT LoadedVT = LD->getMemoryVT();
297 if (LoadedVT.isVector() && ExtType != ISD::NON_EXTLOAD)
298 Action = TLI.getLoadAction(LD->getValueType(0), LoadedVT, LD->getAlign(),
299 LD->getAddressSpace(), ExtType, false);
300 break;
301 }
302 case ISD::STORE: {
303 StoreSDNode *ST = cast<StoreSDNode>(Node);
304 EVT StVT = ST->getMemoryVT();
305 MVT ValVT = ST->getValue().getSimpleValueType();
306 if (StVT.isVector() && ST->isTruncatingStore())
307 Action = TLI.getTruncStoreAction(ValVT, StVT, ST->getAlign(),
308 ST->getAddressSpace());
309 break;
310 }
312 Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
313 // This operation lies about being legal: when it claims to be legal,
314 // it should actually be expanded.
315 if (Action == TargetLowering::Legal)
316 Action = TargetLowering::Expand;
317 break;
318#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
319 case ISD::STRICT_##DAGN:
320#include "llvm/IR/ConstrainedOps.def"
321 ValVT = Node->getValueType(0);
322 if (Op.getOpcode() == ISD::STRICT_SINT_TO_FP ||
323 Op.getOpcode() == ISD::STRICT_UINT_TO_FP)
324 ValVT = Node->getOperand(1).getValueType();
325 if (Op.getOpcode() == ISD::STRICT_FSETCC ||
326 Op.getOpcode() == ISD::STRICT_FSETCCS) {
327 MVT OpVT = Node->getOperand(1).getSimpleValueType();
328 ISD::CondCode CCCode = cast<CondCodeSDNode>(Node->getOperand(3))->get();
329 Action = TLI.getCondCodeAction(CCCode, OpVT);
330 if (Action == TargetLowering::Legal)
331 Action = TLI.getOperationAction(Node->getOpcode(), OpVT);
332 } else {
333 Action = TLI.getOperationAction(Node->getOpcode(), ValVT);
334 }
335 // If we're asked to expand a strict vector floating-point operation,
336 // by default we're going to simply unroll it. That is usually the
337 // best approach, except in the case where the resulting strict (scalar)
338 // operations would themselves use the fallback mutation to non-strict.
339 // In that specific case, just do the fallback on the vector op.
340 if (Action == TargetLowering::Expand && !TLI.isStrictFPEnabled() &&
341 TLI.getStrictFPOperationAction(Node->getOpcode(), ValVT) ==
342 TargetLowering::Legal) {
343 EVT EltVT = ValVT.getVectorElementType();
344 if (TLI.getOperationAction(Node->getOpcode(), EltVT)
345 == TargetLowering::Expand &&
346 TLI.getStrictFPOperationAction(Node->getOpcode(), EltVT)
347 == TargetLowering::Legal)
348 Action = TargetLowering::Legal;
349 }
350 break;
351 case ISD::ADD:
352 case ISD::SUB:
353 case ISD::MUL:
354 case ISD::MULHS:
355 case ISD::MULHU:
356 case ISD::SDIV:
357 case ISD::UDIV:
358 case ISD::SREM:
359 case ISD::UREM:
360 case ISD::SDIVREM:
361 case ISD::UDIVREM:
362 case ISD::FADD:
363 case ISD::FSUB:
364 case ISD::FMUL:
365 case ISD::FDIV:
366 case ISD::FREM:
367 case ISD::AND:
368 case ISD::OR:
369 case ISD::XOR:
370 case ISD::SHL:
371 case ISD::SRA:
372 case ISD::SRL:
373 case ISD::FSHL:
374 case ISD::FSHR:
375 case ISD::ROTL:
376 case ISD::ROTR:
377 case ISD::ABS:
379 case ISD::ABDS:
380 case ISD::ABDU:
381 case ISD::AVGCEILS:
382 case ISD::AVGCEILU:
383 case ISD::AVGFLOORS:
384 case ISD::AVGFLOORU:
385 case ISD::BSWAP:
386 case ISD::BITREVERSE:
387 case ISD::CTLZ:
388 case ISD::CTTZ:
391 case ISD::CTPOP:
392 case ISD::CLMUL:
393 case ISD::CLMULH:
394 case ISD::CLMULR:
395 case ISD::SELECT:
396 case ISD::VSELECT:
397 case ISD::SELECT_CC:
398 case ISD::ZERO_EXTEND:
399 case ISD::ANY_EXTEND:
400 case ISD::TRUNCATE:
401 case ISD::SIGN_EXTEND:
402 case ISD::FP_TO_SINT:
403 case ISD::FP_TO_UINT:
404 case ISD::FNEG:
405 case ISD::FABS:
406 case ISD::FMINNUM:
407 case ISD::FMAXNUM:
410 case ISD::FMINIMUM:
411 case ISD::FMAXIMUM:
412 case ISD::FMINIMUMNUM:
413 case ISD::FMAXIMUMNUM:
414 case ISD::FCOPYSIGN:
415 case ISD::FSQRT:
416 case ISD::FSIN:
417 case ISD::FCOS:
418 case ISD::FTAN:
419 case ISD::FASIN:
420 case ISD::FACOS:
421 case ISD::FATAN:
422 case ISD::FATAN2:
423 case ISD::FSINH:
424 case ISD::FCOSH:
425 case ISD::FTANH:
426 case ISD::FLDEXP:
427 case ISD::FPOWI:
428 case ISD::FPOW:
429 case ISD::FCBRT:
430 case ISD::FLOG:
431 case ISD::FLOG2:
432 case ISD::FLOG10:
433 case ISD::FEXP:
434 case ISD::FEXP2:
435 case ISD::FEXP10:
436 case ISD::FCEIL:
437 case ISD::FTRUNC:
438 case ISD::FRINT:
439 case ISD::FNEARBYINT:
440 case ISD::FROUND:
441 case ISD::FROUNDEVEN:
442 case ISD::FFLOOR:
443 case ISD::FP_ROUND:
444 case ISD::FP_EXTEND:
446 case ISD::FMA:
451 case ISD::SMIN:
452 case ISD::SMAX:
453 case ISD::UMIN:
454 case ISD::UMAX:
455 case ISD::SMUL_LOHI:
456 case ISD::UMUL_LOHI:
457 case ISD::SADDO:
458 case ISD::UADDO:
459 case ISD::SSUBO:
460 case ISD::USUBO:
461 case ISD::SMULO:
462 case ISD::UMULO:
466 case ISD::FFREXP:
467 case ISD::FMODF:
468 case ISD::FSINCOS:
469 case ISD::FSINCOSPI:
470 case ISD::SADDSAT:
471 case ISD::UADDSAT:
472 case ISD::SSUBSAT:
473 case ISD::USUBSAT:
474 case ISD::SSHLSAT:
475 case ISD::USHLSAT:
478 case ISD::MGATHER:
480 case ISD::SCMP:
481 case ISD::UCMP:
484 case ISD::MASKED_UDIV:
485 case ISD::MASKED_SDIV:
486 case ISD::MASKED_UREM:
487 case ISD::MASKED_SREM:
489 Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
490 break;
491 case ISD::SMULFIX:
492 case ISD::SMULFIXSAT:
493 case ISD::UMULFIX:
494 case ISD::UMULFIXSAT:
495 case ISD::SDIVFIX:
496 case ISD::SDIVFIXSAT:
497 case ISD::UDIVFIX:
498 case ISD::UDIVFIXSAT: {
499 unsigned Scale = Node->getConstantOperandVal(2);
500 Action = TLI.getFixedPointOperationAction(Node->getOpcode(),
501 Node->getValueType(0), Scale);
502 break;
503 }
504 case ISD::LROUND:
505 case ISD::LLROUND:
506 case ISD::LRINT:
507 case ISD::LLRINT:
508 case ISD::SINT_TO_FP:
509 case ISD::UINT_TO_FP:
525 case ISD::CTTZ_ELTS:
528 Action = TLI.getOperationAction(Node->getOpcode(),
529 Node->getOperand(0).getValueType());
530 break;
533 Action = TLI.getOperationAction(Node->getOpcode(),
534 Node->getOperand(1).getValueType());
535 break;
536 case ISD::SETCC: {
537 MVT OpVT = Node->getOperand(0).getSimpleValueType();
538 ISD::CondCode CCCode = cast<CondCodeSDNode>(Node->getOperand(2))->get();
539 Action = TLI.getCondCodeAction(CCCode, OpVT);
540 if (Action == TargetLowering::Legal)
541 Action = TLI.getOperationAction(Node->getOpcode(), OpVT);
542 break;
543 }
548 Action =
549 TLI.getPartialReduceMLAAction(Op.getOpcode(), Node->getValueType(0),
550 Node->getOperand(1).getValueType());
551 break;
552
553#define BEGIN_REGISTER_VP_SDNODE(VPID, LEGALPOS, ...) \
554 case ISD::VPID: { \
555 EVT LegalizeVT = LEGALPOS < 0 ? Node->getValueType(-(1 + LEGALPOS)) \
556 : Node->getOperand(LEGALPOS).getValueType(); \
557 /* Defer non-vector results to LegalizeDAG. */ \
558 if (!Node->getValueType(0).isVector() && \
559 Node->getValueType(0) != MVT::Other) { \
560 Action = TargetLowering::Legal; \
561 break; \
562 } \
563 Action = TLI.getOperationAction(Node->getOpcode(), LegalizeVT); \
564 } break;
565#include "llvm/IR/VPIntrinsics.def"
566 }
567
568 LLVM_DEBUG(dbgs() << "\nLegalizing vector op: "; Node->dump(&DAG));
569
570 SmallVector<SDValue, 8> ResultVals;
571 switch (Action) {
572 default: llvm_unreachable("This action is not supported yet!");
573 case TargetLowering::Promote:
574 assert((Op.getOpcode() != ISD::LOAD && Op.getOpcode() != ISD::STORE) &&
575 "This action is not supported yet!");
576 LLVM_DEBUG(dbgs() << "Promoting\n");
577 Promote(Node, ResultVals);
578 assert(!ResultVals.empty() && "No results for promotion?");
579 break;
580 case TargetLowering::Legal:
581 LLVM_DEBUG(dbgs() << "Legal node: nothing to do\n");
582 break;
583 case TargetLowering::Custom:
584 LLVM_DEBUG(dbgs() << "Trying custom legalization\n");
585 if (LowerOperationWrapper(Node, ResultVals))
586 break;
587 LLVM_DEBUG(dbgs() << "Could not custom legalize node\n");
588 [[fallthrough]];
589 case TargetLowering::Expand:
590 LLVM_DEBUG(dbgs() << "Expanding\n");
591 Expand(Node, ResultVals);
592 break;
593 }
594
595 if (ResultVals.empty())
596 return TranslateLegalizeResults(Op, Node);
597
598 Changed = true;
599 return RecursivelyLegalizeResults(Op, ResultVals);
600}
601
602// FIXME: This is very similar to TargetLowering::LowerOperationWrapper. Can we
603// merge them somehow?
604bool VectorLegalizer::LowerOperationWrapper(SDNode *Node,
605 SmallVectorImpl<SDValue> &Results) {
606 SDValue Res = TLI.LowerOperation(SDValue(Node, 0), DAG);
607
608 if (!Res.getNode())
609 return false;
610
611 if (Res == SDValue(Node, 0))
612 return true;
613
614 // If the original node has one result, take the return value from
615 // LowerOperation as is. It might not be result number 0.
616 if (Node->getNumValues() == 1) {
617 Results.push_back(Res);
618 return true;
619 }
620
621 // If the original node has multiple results, then the return node should
622 // have the same number of results.
623 assert((Node->getNumValues() == Res->getNumValues()) &&
624 "Lowering returned the wrong number of results!");
625
626 // Places new result values base on N result number.
627 for (unsigned I = 0, E = Node->getNumValues(); I != E; ++I)
628 Results.push_back(Res.getValue(I));
629
630 return true;
631}
632
633void VectorLegalizer::PromoteSETCC(SDNode *Node,
634 SmallVectorImpl<SDValue> &Results) {
635 MVT VecVT = Node->getOperand(0).getSimpleValueType();
636 MVT NewVecVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VecVT);
637
638 unsigned ExtOp = VecVT.isFloatingPoint() ? ISD::FP_EXTEND : ISD::ANY_EXTEND;
639
640 SDLoc DL(Node);
641 SmallVector<SDValue, 5> Operands(Node->getNumOperands());
642
643 Operands[0] = DAG.getNode(ExtOp, DL, NewVecVT, Node->getOperand(0));
644 Operands[1] = DAG.getNode(ExtOp, DL, NewVecVT, Node->getOperand(1));
645 Operands[2] = Node->getOperand(2);
646
647 EVT ResVT =
648 TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), NewVecVT);
649 SDValue Res =
650 DAG.getNode(Node->getOpcode(), DL, ResVT, Operands, Node->getFlags());
651 if (ResVT != Node->getValueType(0))
652 Res = DAG.getBoolExtOrTrunc(Res, DL, Node->getValueType(0), NewVecVT);
653 Results.push_back(Res);
654}
655
656void VectorLegalizer::PromoteSTRICT(SDNode *Node,
657 SmallVectorImpl<SDValue> &Results) {
658 MVT VecVT = Node->getOperand(1).getSimpleValueType();
659 MVT NewVecVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VecVT);
660
661 assert(VecVT.isFloatingPoint());
662
663 SDLoc DL(Node);
664 SmallVector<SDValue, 5> Operands(Node->getNumOperands());
666
667 for (unsigned j = 1; j != Node->getNumOperands(); ++j)
668 if (Node->getOperand(j).getValueType().isVector() &&
669 !(ISD::isVPOpcode(Node->getOpcode()) &&
670 ISD::getVPMaskIdx(Node->getOpcode()) == j)) // Skip mask operand.
671 {
672 // promote the vector operand.
673 SDValue Ext =
674 DAG.getNode(ISD::STRICT_FP_EXTEND, DL, {NewVecVT, MVT::Other},
675 {Node->getOperand(0), Node->getOperand(j)});
676 Operands[j] = Ext.getValue(0);
677 Chains.push_back(Ext.getValue(1));
678 } else
679 Operands[j] = Node->getOperand(j); // Skip no vector operand.
680
681 SDVTList VTs = DAG.getVTList(NewVecVT, Node->getValueType(1));
682
683 Operands[0] = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
684
685 SDValue Res =
686 DAG.getNode(Node->getOpcode(), DL, VTs, Operands, Node->getFlags());
687
688 SDValue Round =
689 DAG.getNode(ISD::STRICT_FP_ROUND, DL, {VecVT, MVT::Other},
690 {Res.getValue(1), Res.getValue(0),
691 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true)});
692
693 Results.push_back(Round.getValue(0));
694 Results.push_back(Round.getValue(1));
695}
696
697void VectorLegalizer::PromoteFloatVECREDUCE(SDNode *Node,
698 SmallVectorImpl<SDValue> &Results,
699 bool NonArithmetic) {
700 MVT OpVT = Node->getOperand(0).getSimpleValueType();
701 assert(OpVT.isFloatingPoint() && "Expected floating point reduction!");
702 MVT NewOpVT = TLI.getTypeToPromoteTo(Node->getOpcode(), OpVT);
703
704 SDLoc DL(Node);
705 SDValue NewOp = DAG.getNode(ISD::FP_EXTEND, DL, NewOpVT, Node->getOperand(0));
706 SDValue Rdx =
707 DAG.getNode(Node->getOpcode(), DL, NewOpVT.getVectorElementType(), NewOp,
708 Node->getFlags());
709 SDValue Res =
710 DAG.getNode(ISD::FP_ROUND, DL, Node->getValueType(0), Rdx,
711 DAG.getIntPtrConstant(NonArithmetic, DL, /*isTarget=*/true));
712 Results.push_back(Res);
713}
714
715void VectorLegalizer::PromoteVECTOR_COMPRESS(
716 SDNode *Node, SmallVectorImpl<SDValue> &Results) {
717 SDLoc DL(Node);
718 EVT VT = Node->getValueType(0);
719 MVT PromotedVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VT.getSimpleVT());
720 assert((VT.isInteger() || VT.getSizeInBits() == PromotedVT.getSizeInBits()) &&
721 "Only integer promotion or bitcasts between types is supported");
722
723 SDValue Vec = Node->getOperand(0);
724 SDValue Mask = Node->getOperand(1);
725 SDValue Passthru = Node->getOperand(2);
726 if (VT.isInteger()) {
727 Vec = DAG.getNode(ISD::ANY_EXTEND, DL, PromotedVT, Vec);
728 Mask = TLI.promoteTargetBoolean(DAG, Mask, PromotedVT);
729 Passthru = DAG.getNode(ISD::ANY_EXTEND, DL, PromotedVT, Passthru);
730 } else {
731 Vec = DAG.getBitcast(PromotedVT, Vec);
732 Passthru = DAG.getBitcast(PromotedVT, Passthru);
733 }
734
736 DAG.getNode(ISD::VECTOR_COMPRESS, DL, PromotedVT, Vec, Mask, Passthru);
737 Result = VT.isInteger() ? DAG.getNode(ISD::TRUNCATE, DL, VT, Result)
738 : DAG.getBitcast(VT, Result);
739 Results.push_back(Result);
740}
741
742void VectorLegalizer::Promote(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
743 // For a few operations there is a specific concept for promotion based on
744 // the operand's type.
745 switch (Node->getOpcode()) {
746 case ISD::SINT_TO_FP:
747 case ISD::UINT_TO_FP:
750 // "Promote" the operation by extending the operand.
751 PromoteINT_TO_FP(Node, Results);
752 return;
753 case ISD::FP_TO_UINT:
754 case ISD::FP_TO_SINT:
757 // Promote the operation by extending the operand.
758 PromoteFP_TO_INT(Node, Results);
759 return;
760 case ISD::SETCC:
761 // Promote the operation by extending the operand.
762 PromoteSETCC(Node, Results);
763 return;
764 case ISD::STRICT_FADD:
765 case ISD::STRICT_FSUB:
766 case ISD::STRICT_FMUL:
767 case ISD::STRICT_FDIV:
769 case ISD::STRICT_FMA:
770 PromoteSTRICT(Node, Results);
771 return;
774 PromoteFloatVECREDUCE(Node, Results, /*NonArithmetic=*/false);
775 return;
780 PromoteFloatVECREDUCE(Node, Results, /*NonArithmetic=*/true);
781 return;
783 PromoteVECTOR_COMPRESS(Node, Results);
784 return;
785
786 case ISD::FP_ROUND:
787 case ISD::FP_EXTEND:
788 // These operations are used to do promotion so they can't be promoted
789 // themselves.
790 llvm_unreachable("Don't know how to promote this operation!");
791 }
792
793 // There are currently two cases of vector promotion:
794 // 1) Bitcasting a vector of integers to a different type to a vector of the
795 // same overall length. For example, x86 promotes ISD::AND v2i32 to v1i64.
796 // 2) Extending a vector of floats to a vector of the same number of larger
797 // floats. For example, AArch64 promotes ISD::FADD on v4f16 to v4f32.
798 assert(Node->getNumValues() == 1 &&
799 "Can't promote a vector with multiple results!");
800 MVT VT = Node->getSimpleValueType(0);
801 MVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VT);
802 SDLoc dl(Node);
803 SmallVector<SDValue, 4> Operands(Node->getNumOperands());
804
805 for (unsigned j = 0; j != Node->getNumOperands(); ++j) {
806 // Do not promote the mask operand of a VP OP.
807 bool SkipPromote = ISD::isVPOpcode(Node->getOpcode()) &&
808 ISD::getVPMaskIdx(Node->getOpcode()) == j;
809 if (Node->getOperand(j).getValueType().isVector() && !SkipPromote)
810 if (Node->getOperand(j)
811 .getValueType()
812 .getVectorElementType()
813 .isFloatingPoint() &&
815 Operands[j] = DAG.getNode(ISD::FP_EXTEND, dl, NVT, Node->getOperand(j));
816 else
817 Operands[j] = DAG.getNode(ISD::BITCAST, dl, NVT, Node->getOperand(j));
818 else
819 Operands[j] = Node->getOperand(j);
820 }
821
822 SDValue Res =
823 DAG.getNode(Node->getOpcode(), dl, NVT, Operands, Node->getFlags());
824
825 if ((VT.isFloatingPoint() && NVT.isFloatingPoint()) ||
828 Res = DAG.getNode(ISD::FP_ROUND, dl, VT, Res,
829 DAG.getIntPtrConstant(0, dl, /*isTarget=*/true));
830 else
831 Res = DAG.getNode(ISD::BITCAST, dl, VT, Res);
832
833 Results.push_back(Res);
834}
835
836void VectorLegalizer::PromoteINT_TO_FP(SDNode *Node,
837 SmallVectorImpl<SDValue> &Results) {
838 // INT_TO_FP operations may require the input operand be promoted even
839 // when the type is otherwise legal.
840 bool IsStrict = Node->isStrictFPOpcode();
841 MVT VT = Node->getOperand(IsStrict ? 1 : 0).getSimpleValueType();
842 MVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VT);
844 "Vectors have different number of elements!");
845
846 SDLoc dl(Node);
847 SmallVector<SDValue, 4> Operands(Node->getNumOperands());
848
849 unsigned Opc = (Node->getOpcode() == ISD::UINT_TO_FP ||
850 Node->getOpcode() == ISD::STRICT_UINT_TO_FP)
853 for (unsigned j = 0; j != Node->getNumOperands(); ++j) {
854 if (Node->getOperand(j).getValueType().isVector())
855 Operands[j] = DAG.getNode(Opc, dl, NVT, Node->getOperand(j));
856 else
857 Operands[j] = Node->getOperand(j);
858 }
859
860 if (IsStrict) {
861 SDValue Res = DAG.getNode(Node->getOpcode(), dl,
862 {Node->getValueType(0), MVT::Other}, Operands);
863 Results.push_back(Res);
864 Results.push_back(Res.getValue(1));
865 return;
866 }
867
868 SDValue Res =
869 DAG.getNode(Node->getOpcode(), dl, Node->getValueType(0), Operands);
870 Results.push_back(Res);
871}
872
873// For FP_TO_INT we promote the result type to a vector type with wider
874// elements and then truncate the result. This is different from the default
875// PromoteVector which uses bitcast to promote thus assumning that the
876// promoted vector type has the same overall size.
877void VectorLegalizer::PromoteFP_TO_INT(SDNode *Node,
878 SmallVectorImpl<SDValue> &Results) {
879 MVT VT = Node->getSimpleValueType(0);
880 MVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VT);
881 bool IsStrict = Node->isStrictFPOpcode();
883 "Vectors have different number of elements!");
884
885 unsigned NewOpc = Node->getOpcode();
886 // Change FP_TO_UINT to FP_TO_SINT if possible.
887 // TODO: Should we only do this if FP_TO_UINT itself isn't legal?
888 if (NewOpc == ISD::FP_TO_UINT &&
890 NewOpc = ISD::FP_TO_SINT;
891
892 if (NewOpc == ISD::STRICT_FP_TO_UINT &&
894 NewOpc = ISD::STRICT_FP_TO_SINT;
895
896 SDLoc dl(Node);
897 SDValue Promoted, Chain;
898 if (IsStrict) {
899 Promoted = DAG.getNode(NewOpc, dl, {NVT, MVT::Other},
900 {Node->getOperand(0), Node->getOperand(1)});
901 Chain = Promoted.getValue(1);
902 } else
903 Promoted = DAG.getNode(NewOpc, dl, NVT, Node->getOperand(0));
904
905 // Assert that the converted value fits in the original type. If it doesn't
906 // (eg: because the value being converted is too big), then the result of the
907 // original operation was undefined anyway, so the assert is still correct.
908 if (Node->getOpcode() == ISD::FP_TO_UINT ||
909 Node->getOpcode() == ISD::STRICT_FP_TO_UINT)
910 NewOpc = ISD::AssertZext;
911 else
912 NewOpc = ISD::AssertSext;
913
914 Promoted = DAG.getNode(NewOpc, dl, NVT, Promoted,
915 DAG.getValueType(VT.getScalarType()));
916 Promoted = DAG.getNode(ISD::TRUNCATE, dl, VT, Promoted);
917 Results.push_back(Promoted);
918 if (IsStrict)
919 Results.push_back(Chain);
920}
921
922std::pair<SDValue, SDValue> VectorLegalizer::ExpandLoad(SDNode *N) {
923 LoadSDNode *LD = cast<LoadSDNode>(N);
924 return TLI.scalarizeVectorLoad(LD, DAG);
925}
926
927SDValue VectorLegalizer::ExpandStore(SDNode *N) {
928 StoreSDNode *ST = cast<StoreSDNode>(N);
929 SDValue TF = TLI.scalarizeVectorStore(ST, DAG);
930 return TF;
931}
932
933void VectorLegalizer::Expand(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
934 switch (Node->getOpcode()) {
935 case ISD::LOAD: {
936 std::pair<SDValue, SDValue> Tmp = ExpandLoad(Node);
937 Results.push_back(Tmp.first);
938 Results.push_back(Tmp.second);
939 return;
940 }
941 case ISD::STORE:
942 Results.push_back(ExpandStore(Node));
943 return;
945 for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i)
946 Results.push_back(Node->getOperand(i));
947 return;
949 if (SDValue Expanded = ExpandSEXTINREG(Node)) {
950 Results.push_back(Expanded);
951 return;
952 }
953 break;
955 Results.push_back(ExpandANY_EXTEND_VECTOR_INREG(Node));
956 return;
958 Results.push_back(ExpandSIGN_EXTEND_VECTOR_INREG(Node));
959 return;
961 Results.push_back(ExpandZERO_EXTEND_VECTOR_INREG(Node));
962 return;
963 case ISD::BSWAP:
964 if (SDValue Expanded = ExpandBSWAP(Node)) {
965 Results.push_back(Expanded);
966 return;
967 }
968 break;
969 case ISD::VSELECT:
970 if (SDValue Expanded = ExpandVSELECT(Node)) {
971 Results.push_back(Expanded);
972 return;
973 }
974 break;
975 case ISD::VP_SREM:
976 case ISD::VP_UREM:
977 if (SDValue Expanded = ExpandVP_REM(Node)) {
978 Results.push_back(Expanded);
979 return;
980 }
981 break;
982 case ISD::SELECT:
983 if (SDValue Expanded = ExpandSELECT(Node)) {
984 Results.push_back(Expanded);
985 return;
986 }
987 break;
988 case ISD::SELECT_CC: {
989 if (Node->getValueType(0).isScalableVector()) {
990 EVT CondVT = TLI.getSetCCResultType(
991 DAG.getDataLayout(), *DAG.getContext(), Node->getValueType(0));
992 SDValue SetCC =
993 DAG.getNode(ISD::SETCC, SDLoc(Node), CondVT, Node->getOperand(0),
994 Node->getOperand(1), Node->getOperand(4));
995 Results.push_back(DAG.getSelect(SDLoc(Node), Node->getValueType(0), SetCC,
996 Node->getOperand(2),
997 Node->getOperand(3)));
998 return;
999 }
1000 break;
1001 }
1002 case ISD::FP_TO_UINT:
1003 ExpandFP_TO_UINT(Node, Results);
1004 return;
1005 case ISD::UINT_TO_FP:
1006 ExpandUINT_TO_FLOAT(Node, Results);
1007 return;
1008 case ISD::FNEG:
1009 if (SDValue Expanded = ExpandFNEG(Node)) {
1010 Results.push_back(Expanded);
1011 return;
1012 }
1013 break;
1014 case ISD::FABS:
1015 if (SDValue Expanded = ExpandFABS(Node)) {
1016 Results.push_back(Expanded);
1017 return;
1018 }
1019 break;
1020 case ISD::FCOPYSIGN:
1021 if (SDValue Expanded = ExpandFCOPYSIGN(Node)) {
1022 Results.push_back(Expanded);
1023 return;
1024 }
1025 break;
1026 case ISD::FCANONICALIZE: {
1027 // If the scalar element type has a
1028 // Legal/Custom FCANONICALIZE, don't
1029 // mess with the vector, fall back.
1030 EVT VT = Node->getValueType(0);
1031 EVT EltVT = VT.getVectorElementType();
1032 if (!VT.isScalableVector() &&
1034 TargetLowering::Expand)
1035 break;
1036 // Otherwise canonicalize the whole vector.
1037 SDValue Mul = TLI.expandFCANONICALIZE(Node, DAG);
1038 Results.push_back(Mul);
1039 return;
1040 }
1041 case ISD::FSUB:
1042 ExpandFSUB(Node, Results);
1043 return;
1044 case ISD::SETCC:
1045 ExpandSETCC(Node, Results);
1046 return;
1047 case ISD::ABS:
1049 if (SDValue Expanded = TLI.expandABS(Node, DAG)) {
1050 Results.push_back(Expanded);
1051 return;
1052 }
1053 break;
1054 case ISD::ABDS:
1055 case ISD::ABDU:
1056 if (SDValue Expanded = TLI.expandABD(Node, DAG)) {
1057 Results.push_back(Expanded);
1058 return;
1059 }
1060 break;
1061 case ISD::AVGCEILS:
1062 case ISD::AVGCEILU:
1063 case ISD::AVGFLOORS:
1064 case ISD::AVGFLOORU:
1065 if (SDValue Expanded = TLI.expandAVG(Node, DAG)) {
1066 Results.push_back(Expanded);
1067 return;
1068 }
1069 break;
1070 case ISD::BITREVERSE:
1071 if (SDValue Expanded = ExpandBITREVERSE(Node)) {
1072 Results.push_back(Expanded);
1073 return;
1074 }
1075 break;
1076 case ISD::CTPOP:
1077 if (SDValue Expanded = TLI.expandCTPOP(Node, DAG)) {
1078 Results.push_back(Expanded);
1079 return;
1080 }
1081 break;
1082 case ISD::CTLZ:
1084 if (SDValue Expanded = TLI.expandCTLZ(Node, DAG)) {
1085 Results.push_back(Expanded);
1086 return;
1087 }
1088 break;
1089 case ISD::CTTZ:
1091 if (SDValue Expanded = TLI.expandCTTZ(Node, DAG)) {
1092 Results.push_back(Expanded);
1093 return;
1094 }
1095 break;
1096 case ISD::FSHL:
1097 case ISD::FSHR:
1098 if (SDValue Expanded = TLI.expandFunnelShift(Node, DAG)) {
1099 Results.push_back(Expanded);
1100 return;
1101 }
1102 break;
1103 case ISD::CLMUL:
1104 case ISD::CLMULR:
1105 case ISD::CLMULH:
1106 if (SDValue Expanded = TLI.expandCLMUL(Node, DAG)) {
1107 Results.push_back(Expanded);
1108 return;
1109 }
1110 break;
1111 case ISD::PEXT:
1112 Results.push_back(TLI.expandPEXT(Node, DAG));
1113 return;
1114 case ISD::PDEP:
1115 Results.push_back(TLI.expandPDEP(Node, DAG));
1116 return;
1117 case ISD::ROTL:
1118 case ISD::ROTR:
1119 if (SDValue Expanded = TLI.expandROT(Node, false /*AllowVectorOps*/, DAG)) {
1120 Results.push_back(Expanded);
1121 return;
1122 }
1123 break;
1124 case ISD::FMINNUM:
1125 case ISD::FMAXNUM:
1126 if (SDValue Expanded = TLI.expandFMINNUM_FMAXNUM(Node, DAG)) {
1127 Results.push_back(Expanded);
1128 return;
1129 }
1130 break;
1131 case ISD::FMINIMUM:
1132 case ISD::FMAXIMUM:
1133 Results.push_back(TLI.expandFMINIMUM_FMAXIMUM(Node, DAG));
1134 return;
1135 case ISD::FMINIMUMNUM:
1136 case ISD::FMAXIMUMNUM:
1137 Results.push_back(TLI.expandFMINIMUMNUM_FMAXIMUMNUM(Node, DAG));
1138 return;
1139 case ISD::SMIN:
1140 case ISD::SMAX:
1141 case ISD::UMIN:
1142 case ISD::UMAX:
1143 if (SDValue Expanded = TLI.expandIntMINMAX(Node, DAG)) {
1144 Results.push_back(Expanded);
1145 return;
1146 }
1147 break;
1148 case ISD::UADDO:
1149 case ISD::USUBO:
1150 ExpandUADDSUBO(Node, Results);
1151 return;
1152 case ISD::SADDO:
1153 case ISD::SSUBO:
1154 ExpandSADDSUBO(Node, Results);
1155 return;
1156 case ISD::UMULO:
1157 case ISD::SMULO:
1158 ExpandMULO(Node, Results);
1159 return;
1160 case ISD::USUBSAT:
1161 case ISD::SSUBSAT:
1162 case ISD::UADDSAT:
1163 case ISD::SADDSAT:
1164 if (SDValue Expanded = TLI.expandAddSubSat(Node, DAG)) {
1165 Results.push_back(Expanded);
1166 return;
1167 }
1168 break;
1169 case ISD::USHLSAT:
1170 case ISD::SSHLSAT:
1171 if (SDValue Expanded = TLI.expandShlSat(Node, DAG)) {
1172 Results.push_back(Expanded);
1173 return;
1174 }
1175 break;
1178 // Expand the fpsosisat if it is scalable to prevent it from unrolling below.
1179 if (Node->getValueType(0).isScalableVector()) {
1180 if (SDValue Expanded = TLI.expandFP_TO_INT_SAT(Node, DAG)) {
1181 Results.push_back(Expanded);
1182 return;
1183 }
1184 }
1185 break;
1186 case ISD::SMULFIX:
1187 case ISD::UMULFIX:
1188 case ISD::SMULFIXSAT:
1189 case ISD::UMULFIXSAT:
1190 if (SDValue Expanded = TLI.expandFixedPointMul(Node, DAG)) {
1191 Results.push_back(Expanded);
1192 return;
1193 }
1194 break;
1195 case ISD::SDIVFIX:
1196 case ISD::UDIVFIX:
1197 ExpandFixedPointDiv(Node, Results);
1198 return;
1199 case ISD::SDIVFIXSAT:
1200 case ISD::UDIVFIXSAT:
1201 break;
1202#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
1203 case ISD::STRICT_##DAGN:
1204#include "llvm/IR/ConstrainedOps.def"
1205 ExpandStrictFPOp(Node, Results);
1206 return;
1207 case ISD::VECREDUCE_ADD:
1208 case ISD::VECREDUCE_MUL:
1209 case ISD::VECREDUCE_AND:
1210 case ISD::VECREDUCE_OR:
1211 case ISD::VECREDUCE_XOR:
1222 Results.push_back(TLI.expandVecReduce(Node, DAG));
1223 return;
1228 Results.push_back(TLI.expandPartialReduceMLA(Node, DAG));
1229 return;
1232 Results.push_back(TLI.expandVecReduceSeq(Node, DAG));
1233 return;
1234 case ISD::VECTOR_MATCH:
1235 Results.push_back(TLI.expandVectorMatch(Node, DAG));
1236 return;
1237 case ISD::SREM:
1238 case ISD::UREM:
1239 ExpandREM(Node, Results);
1240 return;
1241 case ISD::VP_MERGE:
1242 if (SDValue Expanded = ExpandVP_MERGE(Node)) {
1243 Results.push_back(Expanded);
1244 return;
1245 }
1246 break;
1247 case ISD::FREM: {
1248 RTLIB::Libcall LC = RTLIB::getREM(Node->getValueType(0));
1249 if (tryExpandVecMathCall(Node, LC, Results))
1250 return;
1251
1252 break;
1253 }
1254 case ISD::FSINCOS:
1255 case ISD::FSINCOSPI: {
1256 EVT VT = Node->getValueType(0);
1257 RTLIB::Libcall LC = Node->getOpcode() == ISD::FSINCOS
1258 ? RTLIB::getSINCOS(VT)
1259 : RTLIB::getSINCOSPI(VT);
1260 if (LC != RTLIB::UNKNOWN_LIBCALL &&
1261 TLI.expandMultipleResultFPLibCall(DAG, LC, Node, Results))
1262 return;
1263
1264 // TODO: Try to see if there's a narrower call available to use before
1265 // scalarizing.
1266 break;
1267 }
1268 case ISD::FPOW: {
1269 RTLIB::Libcall LC = RTLIB::getPOW(Node->getValueType(0));
1270 if (tryExpandVecMathCall(Node, LC, Results))
1271 return;
1272
1273 // TODO: Try to see if there's a narrower call available to use before
1274 // scalarizing.
1275 break;
1276 }
1277 case ISD::FCBRT: {
1278 RTLIB::Libcall LC = RTLIB::getCBRT(Node->getValueType(0));
1279 if (tryExpandVecMathCall(Node, LC, Results))
1280 return;
1281
1282 // TODO: Try to see if there's a narrower call available to use before
1283 // scalarizing.
1284 break;
1285 }
1286 case ISD::FMODF: {
1287 EVT VT = Node->getValueType(0);
1288 RTLIB::Libcall LC = RTLIB::getMODF(VT);
1289 if (LC != RTLIB::UNKNOWN_LIBCALL &&
1290 TLI.expandMultipleResultFPLibCall(DAG, LC, Node, Results,
1291 /*CallRetResNo=*/0))
1292 return;
1293 break;
1294 }
1296 Results.push_back(TLI.expandVECTOR_COMPRESS(Node, DAG));
1297 return;
1298 case ISD::CTTZ_ELTS:
1300 Results.push_back(TLI.expandCttzElts(Node, DAG));
1301 return;
1303 Results.push_back(TLI.expandVectorFindLastActive(Node, DAG));
1304 return;
1305 case ISD::SCMP:
1306 case ISD::UCMP:
1307 Results.push_back(TLI.expandCMP(Node, DAG));
1308 return;
1311 Results.push_back(ExpandLOOP_DEPENDENCE_MASK(Node));
1312 return;
1313
1314 case ISD::FADD:
1315 case ISD::FMUL:
1316 case ISD::FMA:
1317 case ISD::FDIV:
1318 case ISD::FCEIL:
1319 case ISD::FFLOOR:
1320 case ISD::FNEARBYINT:
1321 case ISD::FRINT:
1322 case ISD::FROUND:
1323 case ISD::FROUNDEVEN:
1324 case ISD::FTRUNC:
1325 case ISD::FSQRT:
1326 if (SDValue Expanded = TLI.expandVectorNaryOpBySplitting(Node, DAG)) {
1327 Results.push_back(Expanded);
1328 return;
1329 }
1330 break;
1332 if (SDValue Expanded = TLI.expandCONVERT_TO_ARBITRARY_FP(Node, DAG))
1333 Results.push_back(Expanded);
1334 else
1335 Results.push_back(DAG.getPOISON(Node->getValueType(0)));
1336 return;
1338 if (SDValue Expanded = TLI.expandCONVERT_FROM_ARBITRARY_FP(Node, DAG))
1339 Results.push_back(Expanded);
1340 else
1341 Results.push_back(DAG.getPOISON(Node->getValueType(0)));
1342 return;
1343 case ISD::MASKED_UDIV:
1344 case ISD::MASKED_SDIV:
1345 case ISD::MASKED_UREM:
1346 case ISD::MASKED_SREM:
1347 Results.push_back(ExpandMaskedBinOp(Node));
1348 return;
1349 }
1350
1351 SDValue Unrolled = DAG.UnrollVectorOp(Node);
1352 if (Node->getNumValues() == 1) {
1353 Results.push_back(Unrolled);
1354 } else {
1355 assert(Node->getNumValues() == Unrolled->getNumValues() &&
1356 "VectorLegalizer Expand returned wrong number of results!");
1357 for (unsigned I = 0, E = Unrolled->getNumValues(); I != E; ++I)
1358 Results.push_back(Unrolled.getValue(I));
1359 }
1360}
1361
1362SDValue VectorLegalizer::ExpandSELECT(SDNode *Node) {
1363 // Lower a select instruction where the condition is a scalar and the
1364 // operands are vectors. Lower this select to VSELECT and implement it
1365 // using XOR AND OR. The selector bit is broadcasted.
1366 EVT VT = Node->getValueType(0);
1367 SDLoc DL(Node);
1368
1369 SDValue Mask = Node->getOperand(0);
1370 SDValue Op1 = Node->getOperand(1);
1371 SDValue Op2 = Node->getOperand(2);
1372
1373 assert(VT.isVector() && !Mask.getValueType().isVector()
1374 && Op1.getValueType() == Op2.getValueType() && "Invalid type");
1375
1376 // If we can't even use the basic vector operations of
1377 // AND,OR,XOR, we will have to scalarize the op.
1378 // Notice that the operation may be 'promoted' which means that it is
1379 // 'bitcasted' to another type which is handled.
1380 // Also, we need to be able to construct a splat vector using either
1381 // BUILD_VECTOR or SPLAT_VECTOR.
1382 // FIXME: Should we also permit fixed-length SPLAT_VECTOR as a fallback to
1383 // BUILD_VECTOR?
1384 if (TLI.getOperationAction(ISD::AND, VT) == TargetLowering::Expand ||
1385 TLI.getOperationAction(ISD::XOR, VT) == TargetLowering::Expand ||
1386 TLI.getOperationAction(ISD::OR, VT) == TargetLowering::Expand ||
1389 VT) == TargetLowering::Expand)
1390 return SDValue();
1391
1392 // Generate a mask operand.
1393 EVT MaskTy = VT.changeVectorElementTypeToInteger();
1394
1395 // What is the size of each element in the vector mask.
1396 EVT BitTy = MaskTy.getScalarType();
1397
1398 Mask = DAG.getSelect(DL, BitTy, Mask, DAG.getAllOnesConstant(DL, BitTy),
1399 DAG.getConstant(0, DL, BitTy));
1400
1401 // Broadcast the mask so that the entire vector is all one or all zero.
1402 Mask = DAG.getSplat(MaskTy, DL, Mask);
1403
1404 // Bitcast the operands to be the same type as the mask.
1405 // This is needed when we select between FP types because
1406 // the mask is a vector of integers.
1407 Op1 = DAG.getNode(ISD::BITCAST, DL, MaskTy, Op1);
1408 Op2 = DAG.getNode(ISD::BITCAST, DL, MaskTy, Op2);
1409
1410 SDValue NotMask = DAG.getNOT(DL, Mask, MaskTy);
1411
1412 Op1 = DAG.getNode(ISD::AND, DL, MaskTy, Op1, Mask);
1413 Op2 = DAG.getNode(ISD::AND, DL, MaskTy, Op2, NotMask);
1414 SDValue Val = DAG.getNode(ISD::OR, DL, MaskTy, Op1, Op2);
1415 return DAG.getNode(ISD::BITCAST, DL, Node->getValueType(0), Val);
1416}
1417
1418SDValue VectorLegalizer::ExpandSEXTINREG(SDNode *Node) {
1419 EVT VT = Node->getValueType(0);
1420
1421 // Make sure that the SRA and SHL instructions are available.
1422 if (TLI.getOperationAction(ISD::SRA, VT) == TargetLowering::Expand ||
1423 TLI.getOperationAction(ISD::SHL, VT) == TargetLowering::Expand)
1424 return SDValue();
1425
1426 SDLoc DL(Node);
1427 EVT OrigTy = cast<VTSDNode>(Node->getOperand(1))->getVT();
1428
1429 unsigned BW = VT.getScalarSizeInBits();
1430 unsigned OrigBW = OrigTy.getScalarSizeInBits();
1431 SDValue ShiftSz = DAG.getConstant(BW - OrigBW, DL, VT);
1432
1433 SDValue Op = DAG.getNode(ISD::SHL, DL, VT, Node->getOperand(0), ShiftSz);
1434 return DAG.getNode(ISD::SRA, DL, VT, Op, ShiftSz);
1435}
1436
1437// Generically expand a vector anyext in register to a shuffle of the relevant
1438// lanes into the appropriate locations, with other lanes left undef.
1439SDValue VectorLegalizer::ExpandANY_EXTEND_VECTOR_INREG(SDNode *Node) {
1440 SDLoc DL(Node);
1441 EVT VT = Node->getValueType(0);
1442 int NumElements = VT.getVectorNumElements();
1443 SDValue Src = Node->getOperand(0);
1444 EVT SrcVT = Src.getValueType();
1445 int NumSrcElements = SrcVT.getVectorNumElements();
1446
1447 // *_EXTEND_VECTOR_INREG SrcVT can be smaller than VT - so insert the vector
1448 // into a larger vector type.
1449 if (SrcVT.bitsLE(VT)) {
1450 assert((VT.getSizeInBits() % SrcVT.getScalarSizeInBits()) == 0 &&
1451 "ANY_EXTEND_VECTOR_INREG vector size mismatch");
1452 NumSrcElements = VT.getSizeInBits() / SrcVT.getScalarSizeInBits();
1453 SrcVT = EVT::getVectorVT(*DAG.getContext(), SrcVT.getScalarType(),
1454 NumSrcElements);
1455 Src = DAG.getInsertSubvector(DL, DAG.getUNDEF(SrcVT), Src, 0);
1456 }
1457
1458 // Build a base mask of undef shuffles.
1459 SmallVector<int, 16> ShuffleMask;
1460 ShuffleMask.resize(NumSrcElements, -1);
1461
1462 // Place the extended lanes into the correct locations.
1463 int ExtLaneScale = NumSrcElements / NumElements;
1464 int EndianOffset = DAG.getDataLayout().isBigEndian() ? ExtLaneScale - 1 : 0;
1465 for (int i = 0; i < NumElements; ++i)
1466 ShuffleMask[i * ExtLaneScale + EndianOffset] = i;
1467
1468 return DAG.getNode(
1469 ISD::BITCAST, DL, VT,
1470 DAG.getVectorShuffle(SrcVT, DL, Src, DAG.getPOISON(SrcVT), ShuffleMask));
1471}
1472
1473SDValue VectorLegalizer::ExpandSIGN_EXTEND_VECTOR_INREG(SDNode *Node) {
1474 SDLoc DL(Node);
1475 EVT VT = Node->getValueType(0);
1476 SDValue Src = Node->getOperand(0);
1477 EVT SrcVT = Src.getValueType();
1478
1479 // First build an any-extend node which can be legalized above when we
1480 // recurse through it.
1482
1483 // Now we need sign extend. This will be exanded to shifts if it isn't
1484 // supported.
1485 EVT ExtVT = EVT::getVectorVT(*DAG.getContext(), SrcVT.getVectorElementType(),
1487 return DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, VT, Op,
1488 DAG.getValueType(ExtVT));
1489}
1490
1491// Generically expand a vector zext in register to a shuffle of the relevant
1492// lanes into the appropriate locations, a blend of zero into the high bits,
1493// and a bitcast to the wider element type.
1494SDValue VectorLegalizer::ExpandZERO_EXTEND_VECTOR_INREG(SDNode *Node) {
1495 SDLoc DL(Node);
1496 EVT VT = Node->getValueType(0);
1497 int NumElements = VT.getVectorNumElements();
1498 SDValue Src = Node->getOperand(0);
1499 EVT SrcVT = Src.getValueType();
1500 int NumSrcElements = SrcVT.getVectorNumElements();
1501
1502 // *_EXTEND_VECTOR_INREG SrcVT can be smaller than VT - so insert the vector
1503 // into a larger vector type.
1504 if (SrcVT.bitsLE(VT)) {
1505 assert((VT.getSizeInBits() % SrcVT.getScalarSizeInBits()) == 0 &&
1506 "ZERO_EXTEND_VECTOR_INREG vector size mismatch");
1507 NumSrcElements = VT.getSizeInBits() / SrcVT.getScalarSizeInBits();
1508 SrcVT = EVT::getVectorVT(*DAG.getContext(), SrcVT.getScalarType(),
1509 NumSrcElements);
1510 Src = DAG.getInsertSubvector(DL, DAG.getUNDEF(SrcVT), Src, 0);
1511 }
1512
1513 // Build up a zero vector to blend into this one.
1514 SDValue Zero = DAG.getConstant(0, DL, SrcVT);
1515
1516 // Shuffle the incoming lanes into the correct position, and pull all other
1517 // lanes from the zero vector.
1518 auto ShuffleMask = llvm::to_vector<16>(llvm::seq<int>(0, NumSrcElements));
1519
1520 int ExtLaneScale = NumSrcElements / NumElements;
1521 int EndianOffset = DAG.getDataLayout().isBigEndian() ? ExtLaneScale - 1 : 0;
1522 for (int i = 0; i < NumElements; ++i)
1523 ShuffleMask[i * ExtLaneScale + EndianOffset] = NumSrcElements + i;
1524
1525 return DAG.getNode(ISD::BITCAST, DL, VT,
1526 DAG.getVectorShuffle(SrcVT, DL, Zero, Src, ShuffleMask));
1527}
1528
1529static void createBSWAPShuffleMask(EVT VT, SmallVectorImpl<int> &ShuffleMask) {
1530 int ScalarSizeInBytes = VT.getScalarSizeInBits() / 8;
1531 for (int I = 0, E = VT.getVectorNumElements(); I != E; ++I)
1532 for (int J = ScalarSizeInBytes - 1; J >= 0; --J)
1533 ShuffleMask.push_back((I * ScalarSizeInBytes) + J);
1534}
1535
1536SDValue VectorLegalizer::ExpandBSWAP(SDNode *Node) {
1537 EVT VT = Node->getValueType(0);
1538
1539 // Scalable vectors can't use shuffle expansion.
1540 if (VT.isScalableVector())
1541 return TLI.expandBSWAP(Node, DAG);
1542
1543 // Generate a byte wise shuffle mask for the BSWAP.
1544 SmallVector<int, 16> ShuffleMask;
1545 createBSWAPShuffleMask(VT, ShuffleMask);
1546 EVT ByteVT = EVT::getVectorVT(*DAG.getContext(), MVT::i8, ShuffleMask.size());
1547
1548 // Only emit a shuffle if the mask is legal.
1549 if (TLI.isShuffleMaskLegal(ShuffleMask, ByteVT)) {
1550 SDLoc DL(Node);
1551 SDValue Op = DAG.getNode(ISD::BITCAST, DL, ByteVT, Node->getOperand(0));
1552 Op = DAG.getVectorShuffle(ByteVT, DL, Op, DAG.getPOISON(ByteVT),
1553 ShuffleMask);
1554 return DAG.getNode(ISD::BITCAST, DL, VT, Op);
1555 }
1556
1557 // If we have the appropriate vector bit operations, it is better to use them
1558 // than unrolling and expanding each component.
1559 if (TLI.isOperationLegalOrCustom(ISD::SHL, VT) &&
1563 return TLI.expandBSWAP(Node, DAG);
1564
1565 // Otherwise let the caller unroll.
1566 return SDValue();
1567}
1568
1569SDValue VectorLegalizer::ExpandBITREVERSE(SDNode *Node) {
1570 EVT VT = Node->getValueType(0);
1571
1572 // We can't unroll or use shuffles for scalable vectors.
1573 if (VT.isScalableVector())
1574 return TLI.expandBITREVERSE(Node, DAG);
1575
1576 // If we have the scalar operation, it's probably cheaper to unroll it.
1578 return SDValue();
1579
1580 // If the vector element width is a whole number of bytes, test if its legal
1581 // to BSWAP shuffle the bytes and then perform the BITREVERSE on the byte
1582 // vector. This greatly reduces the number of bit shifts necessary.
1583 unsigned ScalarSizeInBits = VT.getScalarSizeInBits();
1584 if (ScalarSizeInBits > 8 && (ScalarSizeInBits % 8) == 0) {
1585 SmallVector<int, 16> BSWAPMask;
1586 createBSWAPShuffleMask(VT, BSWAPMask);
1587
1588 EVT ByteVT = EVT::getVectorVT(*DAG.getContext(), MVT::i8, BSWAPMask.size());
1589 if (TLI.isShuffleMaskLegal(BSWAPMask, ByteVT) &&
1591 (TLI.isOperationLegalOrCustom(ISD::SHL, ByteVT) &&
1592 TLI.isOperationLegalOrCustom(ISD::SRL, ByteVT) &&
1595 SDLoc DL(Node);
1596 SDValue Op = DAG.getNode(ISD::BITCAST, DL, ByteVT, Node->getOperand(0));
1597 Op = DAG.getVectorShuffle(ByteVT, DL, Op, DAG.getPOISON(ByteVT),
1598 BSWAPMask);
1599 Op = DAG.getNode(ISD::BITREVERSE, DL, ByteVT, Op);
1600 Op = DAG.getNode(ISD::BITCAST, DL, VT, Op);
1601 return Op;
1602 }
1603 }
1604
1605 // If we have the appropriate vector bit operations, it is better to use them
1606 // than unrolling and expanding each component.
1607 if (TLI.isOperationLegalOrCustom(ISD::SHL, VT) &&
1611 return TLI.expandBITREVERSE(Node, DAG);
1612
1613 // Otherwise unroll.
1614 return SDValue();
1615}
1616
1617SDValue VectorLegalizer::ExpandVSELECT(SDNode *Node) {
1618 // Implement VSELECT in terms of XOR, AND, OR
1619 // on platforms which do not support blend natively.
1620 SDLoc DL(Node);
1621
1622 SDValue Mask = Node->getOperand(0);
1623 SDValue Op1 = Node->getOperand(1);
1624 SDValue Op2 = Node->getOperand(2);
1625
1626 EVT VT = Mask.getValueType();
1627
1628 // If we can't even use the basic vector operations of
1629 // AND,OR,XOR, we will have to scalarize the op.
1630 // Notice that the operation may be 'promoted' which means that it is
1631 // 'bitcasted' to another type which is handled.
1632 if (TLI.getOperationAction(ISD::AND, VT) == TargetLowering::Expand ||
1633 TLI.getOperationAction(ISD::XOR, VT) == TargetLowering::Expand ||
1634 TLI.getOperationAction(ISD::OR, VT) == TargetLowering::Expand)
1635 return SDValue();
1636
1637 // This operation also isn't safe with AND, OR, XOR when the boolean type is
1638 // 0/1 and the select operands aren't also booleans, as we need an all-ones
1639 // vector constant to mask with.
1640 // FIXME: Sign extend 1 to all ones if that's legal on the target.
1641 auto BoolContents = TLI.getBooleanContents(Op1.getValueType());
1642 if (BoolContents != TargetLowering::ZeroOrNegativeOneBooleanContent &&
1643 !(BoolContents == TargetLowering::ZeroOrOneBooleanContent &&
1644 Op1.getValueType().getVectorElementType() == MVT::i1))
1645 return SDValue();
1646
1647 // If the mask and the type are different sizes, unroll the vector op. This
1648 // can occur when getSetCCResultType returns something that is different in
1649 // size from the operand types. For example, v4i8 = select v4i32, v4i8, v4i8.
1650 if (VT.getSizeInBits() != Op1.getValueSizeInBits())
1651 return SDValue();
1652
1653 // Bitcast the operands to be the same type as the mask.
1654 // This is needed when we select between FP types because
1655 // the mask is a vector of integers.
1656 Op1 = DAG.getNode(ISD::BITCAST, DL, VT, Op1);
1657 Op2 = DAG.getNode(ISD::BITCAST, DL, VT, Op2);
1658
1659 SDValue NotMask = DAG.getNOT(DL, Mask, VT);
1660
1661 Op1 = DAG.getNode(ISD::AND, DL, VT, Op1, Mask);
1662 Op2 = DAG.getNode(ISD::AND, DL, VT, Op2, NotMask);
1663 SDValue Val = DAG.getNode(ISD::OR, DL, VT, Op1, Op2);
1664 return DAG.getNode(ISD::BITCAST, DL, Node->getValueType(0), Val);
1665}
1666
1667SDValue VectorLegalizer::ExpandVP_MERGE(SDNode *Node) {
1668 // Implement VP_MERGE in terms of VSELECT. Construct a mask where vector
1669 // indices less than the EVL/pivot are true. Combine that with the original
1670 // mask for a full-length mask. Use a full-length VSELECT to select between
1671 // the true and false values.
1672 SDLoc DL(Node);
1673
1674 SDValue Mask = Node->getOperand(0);
1675 SDValue Op1 = Node->getOperand(1);
1676 SDValue Op2 = Node->getOperand(2);
1677 SDValue EVL = Node->getOperand(3);
1678
1679 EVT MaskVT = Mask.getValueType();
1680 bool IsFixedLen = MaskVT.isFixedLengthVector();
1681
1682 EVT EVLVecVT = EVT::getVectorVT(*DAG.getContext(), EVL.getValueType(),
1683 MaskVT.getVectorElementCount());
1684
1685 // If we can't construct the EVL mask efficiently, it's better to unroll.
1686 if ((IsFixedLen &&
1688 (!IsFixedLen &&
1689 (!TLI.isOperationLegalOrCustom(ISD::STEP_VECTOR, EVLVecVT) ||
1691 return SDValue();
1692
1693 // If using a SETCC would result in a different type than the mask type,
1694 // unroll.
1695 if (TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(),
1696 EVLVecVT) != MaskVT)
1697 return SDValue();
1698
1699 SDValue StepVec = DAG.getStepVector(DL, EVLVecVT);
1700 SDValue SplatEVL = DAG.getSplat(EVLVecVT, DL, EVL);
1701 SDValue EVLMask =
1702 DAG.getSetCC(DL, MaskVT, StepVec, SplatEVL, ISD::CondCode::SETULT);
1703
1704 SDValue FullMask = DAG.getNode(ISD::AND, DL, MaskVT, Mask, EVLMask);
1705 return DAG.getSelect(DL, Node->getValueType(0), FullMask, Op1, Op2);
1706}
1707
1708SDValue VectorLegalizer::ExpandVP_REM(SDNode *Node) {
1709 // Implement VP_SREM/UREM in terms of VP_SDIV/VP_UDIV, MUL, SUB.
1710 EVT VT = Node->getValueType(0);
1711
1712 unsigned DivOpc = Node->getOpcode() == ISD::VP_SREM ? ISD::VP_SDIV : ISD::VP_UDIV;
1713
1714 if (!TLI.isOperationLegalOrCustom(DivOpc, VT) ||
1717 return SDValue();
1718
1719 SDLoc DL(Node);
1720
1721 SDValue Dividend = Node->getOperand(0);
1722 SDValue Divisor = Node->getOperand(1);
1723 SDValue Mask = Node->getOperand(2);
1724 SDValue EVL = Node->getOperand(3);
1725
1726 // X % Y -> X-X/Y*Y
1727 SDValue Div = DAG.getNode(DivOpc, DL, VT, Dividend, Divisor, Mask, EVL);
1728 SDValue Mul = DAG.getNode(ISD::MUL, DL, VT, Divisor, Div);
1729 return DAG.getNode(ISD::SUB, DL, VT, Dividend, Mul);
1730}
1731
1732SDValue VectorLegalizer::ExpandLOOP_DEPENDENCE_MASK(SDNode *N) {
1733 return TLI.expandLoopDependenceMask(N, DAG);
1734}
1735
1736SDValue VectorLegalizer::ExpandMaskedBinOp(SDNode *N) {
1737 // Masked bin ops don't have undefined behaviour when dividing by zero
1738 // on disabled lanes and produce poison instead. Replace the divisor on the
1739 // disabled lanes with 1 to avoid division by zero or overflow.
1740 SDLoc dl(N);
1741 EVT VT = N->getValueType(0);
1742 SDValue SafeDivisor = DAG.getSelect(
1743 dl, VT, N->getOperand(2), N->getOperand(1), DAG.getConstant(1, dl, VT));
1744 return DAG.getNode(ISD::getUnmaskedBinOpOpcode(N->getOpcode()), dl, VT,
1745 N->getOperand(0), SafeDivisor);
1746}
1747
1748void VectorLegalizer::ExpandFP_TO_UINT(SDNode *Node,
1749 SmallVectorImpl<SDValue> &Results) {
1750 // Attempt to expand using TargetLowering.
1751 SDValue Result, Chain;
1752 if (TLI.expandFP_TO_UINT(Node, Result, Chain, DAG)) {
1753 Results.push_back(Result);
1754 if (Node->isStrictFPOpcode())
1755 Results.push_back(Chain);
1756 return;
1757 }
1758
1759 // Otherwise go ahead and unroll.
1760 if (Node->isStrictFPOpcode()) {
1761 UnrollStrictFPOp(Node, Results);
1762 return;
1763 }
1764
1765 Results.push_back(DAG.UnrollVectorOp(Node));
1766}
1767
1768void VectorLegalizer::ExpandUINT_TO_FLOAT(SDNode *Node,
1769 SmallVectorImpl<SDValue> &Results) {
1770 bool IsStrict = Node->isStrictFPOpcode();
1771 unsigned OpNo = IsStrict ? 1 : 0;
1772 SDValue Src = Node->getOperand(OpNo);
1773 EVT SrcVT = Src.getValueType();
1774 EVT DstVT = Node->getValueType(0);
1775 SDLoc DL(Node);
1776
1777 // Attempt to expand using TargetLowering.
1779 SDValue Chain;
1780 if (TLI.expandUINT_TO_FP(Node, Result, Chain, DAG)) {
1781 Results.push_back(Result);
1782 if (IsStrict)
1783 Results.push_back(Chain);
1784 return;
1785 }
1786
1787 // Make sure that the SINT_TO_FP and SRL instructions are available.
1788 if (((!IsStrict && TLI.getOperationAction(ISD::SINT_TO_FP, SrcVT) ==
1789 TargetLowering::Expand) ||
1790 (IsStrict && TLI.getOperationAction(ISD::STRICT_SINT_TO_FP, SrcVT) ==
1791 TargetLowering::Expand)) ||
1792 TLI.getOperationAction(ISD::SRL, SrcVT) == TargetLowering::Expand) {
1793 if (IsStrict) {
1794 UnrollStrictFPOp(Node, Results);
1795 return;
1796 }
1797
1798 Results.push_back(DAG.UnrollVectorOp(Node));
1799 return;
1800 }
1801
1802 unsigned BW = SrcVT.getScalarSizeInBits();
1803 assert((BW == 64 || BW == 32) &&
1804 "Elements in vector-UINT_TO_FP must be 32 or 64 bits wide");
1805
1806 // If STRICT_/FMUL is not supported by the target (in case of f16) replace the
1807 // UINT_TO_FP with a larger float and round to the smaller type
1808 if ((!IsStrict && !TLI.isOperationLegalOrCustom(ISD::FMUL, DstVT)) ||
1809 (IsStrict && !TLI.isOperationLegalOrCustom(ISD::STRICT_FMUL, DstVT))) {
1810 EVT FPVT = BW == 32 ? MVT::f32 : MVT::f64;
1811 SDValue UIToFP;
1813 SDValue TargetZero = DAG.getIntPtrConstant(0, DL, /*isTarget=*/true);
1814 EVT FloatVecVT = SrcVT.changeVectorElementType(*DAG.getContext(), FPVT);
1815 if (IsStrict) {
1816 UIToFP = DAG.getNode(ISD::STRICT_UINT_TO_FP, DL, {FloatVecVT, MVT::Other},
1817 {Node->getOperand(0), Src});
1818 Result = DAG.getNode(ISD::STRICT_FP_ROUND, DL, {DstVT, MVT::Other},
1819 {Node->getOperand(0), UIToFP, TargetZero});
1820 Results.push_back(Result);
1821 Results.push_back(Result.getValue(1));
1822 } else {
1823 UIToFP = DAG.getNode(ISD::UINT_TO_FP, DL, FloatVecVT, Src);
1824 Result = DAG.getNode(ISD::FP_ROUND, DL, DstVT, UIToFP, TargetZero);
1825 Results.push_back(Result);
1826 }
1827
1828 return;
1829 }
1830
1831 SDValue HalfWord = DAG.getConstant(BW / 2, DL, SrcVT);
1832
1833 // Constants to clear the upper part of the word.
1834 // Notice that we can also use SHL+SHR, but using a constant is slightly
1835 // faster on x86.
1836 uint64_t HWMask = (BW == 64) ? 0x00000000FFFFFFFF : 0x0000FFFF;
1837 SDValue HalfWordMask = DAG.getConstant(HWMask, DL, SrcVT);
1838
1839 // Two to the power of half-word-size.
1840 SDValue TWOHW = DAG.getConstantFP(1ULL << (BW / 2), DL, DstVT);
1841
1842 // Clear upper part of LO, lower HI
1843 SDValue HI = DAG.getNode(ISD::SRL, DL, SrcVT, Src, HalfWord);
1844 SDValue LO = DAG.getNode(ISD::AND, DL, SrcVT, Src, HalfWordMask);
1845
1846 if (IsStrict) {
1847 // Convert hi and lo to floats
1848 // Convert the hi part back to the upper values
1849 // TODO: Can any fast-math-flags be set on these nodes?
1850 SDValue fHI = DAG.getNode(ISD::STRICT_SINT_TO_FP, DL, {DstVT, MVT::Other},
1851 {Node->getOperand(0), HI});
1852 fHI = DAG.getNode(ISD::STRICT_FMUL, DL, {DstVT, MVT::Other},
1853 {fHI.getValue(1), fHI, TWOHW});
1854 SDValue fLO = DAG.getNode(ISD::STRICT_SINT_TO_FP, DL, {DstVT, MVT::Other},
1855 {Node->getOperand(0), LO});
1856
1857 SDValue TF = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, fHI.getValue(1),
1858 fLO.getValue(1));
1859
1860 // Add the two halves
1861 SDValue Result =
1862 DAG.getNode(ISD::STRICT_FADD, DL, {DstVT, MVT::Other}, {TF, fHI, fLO});
1863
1864 Results.push_back(Result);
1865 Results.push_back(Result.getValue(1));
1866 return;
1867 }
1868
1869 // Convert hi and lo to floats
1870 // Convert the hi part back to the upper values
1871 // TODO: Can any fast-math-flags be set on these nodes?
1872 SDValue fHI = DAG.getNode(ISD::SINT_TO_FP, DL, DstVT, HI);
1873 fHI = DAG.getNode(ISD::FMUL, DL, DstVT, fHI, TWOHW);
1874 SDValue fLO = DAG.getNode(ISD::SINT_TO_FP, DL, DstVT, LO);
1875
1876 // Add the two halves
1877 Results.push_back(DAG.getNode(ISD::FADD, DL, DstVT, fHI, fLO));
1878}
1879
1880SDValue VectorLegalizer::ExpandFNEG(SDNode *Node) {
1881 EVT VT = Node->getValueType(0);
1882 EVT IntVT = VT.changeVectorElementTypeToInteger();
1883
1884 if (!TLI.isOperationLegalOrCustom(ISD::XOR, IntVT))
1885 return SDValue();
1886
1887 // Heuristic check to determine whether vector should be expanded to integer
1888 // operations or unrolled to scalar operations.
1889 // 1. Scalable vector is never unrolled.
1890 // 2. Fixed vector is unrolled if one of followings is true:
1891 // a. Vector only has 1 element and target knows how to handle scalar
1892 // FNEG (either legal or custom expand or promote).
1893 // b. Vector has more than 1 element and target supports scalar
1894 // FNEG natively and vector length <= 2(1 XOR + 1 CONST).
1895 // FIXME: Scalar construction instruction count varies in every architecture,
1896 // here we assume 1 instruction for now.
1897 if (VT.isFixedLengthVector()) {
1898 EVT EltVT = VT.getVectorElementType();
1899 unsigned NumElts = VT.getVectorNumElements();
1900 if ((NumElts == 1 &&
1902 (NumElts < 3 && TLI.isOperationLegal(ISD::FNEG, EltVT) &&
1903 TLI.isExtractVecEltCheap(VT, 0) &&
1904 (NumElts == 1 || TLI.isExtractVecEltCheap(VT, 1))))
1905 return SDValue();
1906 }
1907
1908 SDLoc DL(Node);
1909 SDValue Cast = DAG.getNode(ISD::BITCAST, DL, IntVT, Node->getOperand(0));
1910 SDValue SignMask = DAG.getConstant(
1911 APInt::getSignMask(IntVT.getScalarSizeInBits()), DL, IntVT);
1912 SDValue Xor = DAG.getNode(ISD::XOR, DL, IntVT, Cast, SignMask);
1913 return DAG.getNode(ISD::BITCAST, DL, VT, Xor);
1914}
1915
1916SDValue VectorLegalizer::ExpandFABS(SDNode *Node) {
1917 EVT VT = Node->getValueType(0);
1918 EVT IntVT = VT.changeVectorElementTypeToInteger();
1919
1920 if (!TLI.isOperationLegalOrCustom(ISD::AND, IntVT))
1921 return SDValue();
1922
1923 // Heuristic check to determine whether vector should be expanded to integer
1924 // operations or unrolled to scalar operations.
1925 // 1. Scalable vector is never unrolled.
1926 // 2. Fixed vector is unrolled if one of followings is true:
1927 // a. Vector only has 1 element and target knows how to handle scalar
1928 // FABS(either legal or custom expand or promote).
1929 // b. Vector has more than 1 element and target supports scalar
1930 // FABS natively and vector length <= 2(1 AND + 1 CONST).
1931 // FIXME: Scalar construction instruction count varies in every architecture,
1932 // here we assume 1 instruction for now.
1933 if (VT.isFixedLengthVector()) {
1934 EVT EltVT = VT.getVectorElementType();
1935 unsigned NumElts = VT.getVectorNumElements();
1936 if ((NumElts == 1 &&
1938 (NumElts < 3 && TLI.isOperationLegal(ISD::FABS, EltVT) &&
1939 TLI.isExtractVecEltCheap(VT, 0) &&
1940 (NumElts == 1 || TLI.isExtractVecEltCheap(VT, 1))))
1941 return SDValue();
1942 }
1943
1944 SDLoc DL(Node);
1945 SDValue Cast = DAG.getNode(ISD::BITCAST, DL, IntVT, Node->getOperand(0));
1946 SDValue ClearSignMask = DAG.getConstant(
1948 SDValue ClearedSign = DAG.getNode(ISD::AND, DL, IntVT, Cast, ClearSignMask);
1949 return DAG.getNode(ISD::BITCAST, DL, VT, ClearedSign);
1950}
1951
1952SDValue VectorLegalizer::ExpandFCOPYSIGN(SDNode *Node) {
1953 EVT VT = Node->getValueType(0);
1954 EVT IntVT = VT.changeVectorElementTypeToInteger();
1955
1956 if (VT != Node->getOperand(1).getValueType() ||
1957 !TLI.isOperationLegalOrCustom(ISD::AND, IntVT) ||
1958 !TLI.isOperationLegalOrCustom(ISD::OR, IntVT))
1959 return SDValue();
1960
1961 // Heuristic check to determine whether vector should be expanded to integer
1962 // operations or unrolled to scalar operations.
1963 // 1. Scalable vector is never unrolled.
1964 // 2. Fixed vector is unrolled if one of followings is true:
1965 // a. Vector only has 1 element and target knows how to handle scalar
1966 // FCOPYSIGN(either legal or custom expand or promote).
1967 // b. Vector has more than 1 element and target supports scalar
1968 // FCOPYSIGN natively and vector length <= 5(2 AND + 1 OR + 2 CONST).
1969 // FIXME: Scalar construction instruction count varies in every architecture,
1970 // here we assume 1 instruction for now.
1971 if (VT.isFixedLengthVector()) {
1972 EVT EltVT = VT.getVectorElementType();
1973 unsigned NumElts = VT.getVectorNumElements();
1974 if ((NumElts == 1 &&
1976 (NumElts < 6 && TLI.isOperationLegal(ISD::FCOPYSIGN, EltVT) &&
1977 TLI.isExtractVecEltCheap(VT, 0) &&
1978 (NumElts == 1 || TLI.isExtractVecEltCheap(VT, 1))))
1979 return SDValue();
1980 }
1981
1982 SDLoc DL(Node);
1983 SDValue Mag = DAG.getNode(ISD::BITCAST, DL, IntVT, Node->getOperand(0));
1984 SDValue Sign = DAG.getNode(ISD::BITCAST, DL, IntVT, Node->getOperand(1));
1985
1986 SDValue SignMask = DAG.getConstant(
1987 APInt::getSignMask(IntVT.getScalarSizeInBits()), DL, IntVT);
1988 SDValue SignBit = DAG.getNode(ISD::AND, DL, IntVT, Sign, SignMask);
1989
1990 SDValue ClearSignMask = DAG.getConstant(
1992 SDValue ClearedSign = DAG.getNode(ISD::AND, DL, IntVT, Mag, ClearSignMask);
1993
1994 SDValue CopiedSign = DAG.getNode(ISD::OR, DL, IntVT, ClearedSign, SignBit,
1996
1997 return DAG.getNode(ISD::BITCAST, DL, VT, CopiedSign);
1998}
1999
2000void VectorLegalizer::ExpandFSUB(SDNode *Node,
2001 SmallVectorImpl<SDValue> &Results) {
2002 // For floating-point values, (a-b) is the same as a+(-b). If FNEG is legal,
2003 // we can defer this to operation legalization where it will be lowered as
2004 // a+(-b).
2005 EVT VT = Node->getValueType(0);
2006 if (TLI.isOperationLegalOrCustom(ISD::FNEG, VT) &&
2008 return; // Defer to LegalizeDAG
2009
2010 if (SDValue Expanded = TLI.expandVectorNaryOpBySplitting(Node, DAG)) {
2011 Results.push_back(Expanded);
2012 return;
2013 }
2014
2015 SDValue Tmp = DAG.UnrollVectorOp(Node);
2016 Results.push_back(Tmp);
2017}
2018
2019void VectorLegalizer::ExpandSETCC(SDNode *Node,
2020 SmallVectorImpl<SDValue> &Results) {
2021 bool NeedInvert = false;
2022 bool IsStrict = Node->getOpcode() == ISD::STRICT_FSETCC ||
2023 Node->getOpcode() == ISD::STRICT_FSETCCS;
2024 bool IsSignaling = Node->getOpcode() == ISD::STRICT_FSETCCS;
2025 unsigned Offset = IsStrict ? 1 : 0;
2026
2027 SDValue Chain = IsStrict ? Node->getOperand(0) : SDValue();
2028 SDValue LHS = Node->getOperand(0 + Offset);
2029 SDValue RHS = Node->getOperand(1 + Offset);
2030 SDValue CC = Node->getOperand(2 + Offset);
2031
2032 MVT OpVT = LHS.getSimpleValueType();
2033 ISD::CondCode CCCode = cast<CondCodeSDNode>(CC)->get();
2034
2035 if (TLI.getCondCodeAction(CCCode, OpVT) != TargetLowering::Expand) {
2036 if (IsStrict) {
2037 UnrollStrictFPOp(Node, Results);
2038 return;
2039 }
2040 Results.push_back(UnrollVSETCC(Node));
2041 return;
2042 }
2043
2044 SDLoc dl(Node);
2045 bool Legalized =
2046 TLI.LegalizeSetCCCondCode(DAG, Node->getValueType(0), LHS, RHS, CC,
2047 NeedInvert, dl, Chain, IsSignaling);
2048
2049 if (Legalized) {
2050 // If we expanded the SETCC by swapping LHS and RHS, or by inverting the
2051 // condition code, create a new SETCC node.
2052 if (CC.getNode()) {
2053 if (IsStrict) {
2054 LHS = DAG.getNode(Node->getOpcode(), dl, Node->getVTList(),
2055 {Chain, LHS, RHS, CC}, Node->getFlags());
2056 Chain = LHS.getValue(1);
2057 } else {
2058 LHS = DAG.getNode(ISD::SETCC, dl, Node->getValueType(0), LHS, RHS, CC,
2059 Node->getFlags());
2060 }
2061 }
2062
2063 // If we expanded the SETCC by inverting the condition code, then wrap
2064 // the existing SETCC in a NOT to restore the intended condition.
2065 if (NeedInvert)
2066 LHS = DAG.getLogicalNOT(dl, LHS, LHS->getValueType(0));
2067 } else {
2068 assert(!IsStrict && "Don't know how to expand for strict nodes.");
2069
2070 // Otherwise, SETCC for the given comparison type must be completely
2071 // illegal; expand it into a SELECT_CC.
2072 EVT VT = Node->getValueType(0);
2073 LHS = DAG.getNode(ISD::SELECT_CC, dl, VT, LHS, RHS,
2074 DAG.getBoolConstant(true, dl, VT, LHS.getValueType()),
2075 DAG.getBoolConstant(false, dl, VT, LHS.getValueType()),
2076 CC, Node->getFlags());
2077 }
2078
2079 Results.push_back(LHS);
2080 if (IsStrict)
2081 Results.push_back(Chain);
2082}
2083
2084void VectorLegalizer::ExpandUADDSUBO(SDNode *Node,
2085 SmallVectorImpl<SDValue> &Results) {
2086 SDValue Result, Overflow;
2087 TLI.expandUADDSUBO(Node, Result, Overflow, DAG);
2088 Results.push_back(Result);
2089 Results.push_back(Overflow);
2090}
2091
2092void VectorLegalizer::ExpandSADDSUBO(SDNode *Node,
2093 SmallVectorImpl<SDValue> &Results) {
2094 SDValue Result, Overflow;
2095 TLI.expandSADDSUBO(Node, Result, Overflow, DAG);
2096 Results.push_back(Result);
2097 Results.push_back(Overflow);
2098}
2099
2100void VectorLegalizer::ExpandMULO(SDNode *Node,
2101 SmallVectorImpl<SDValue> &Results) {
2102 SDValue Result, Overflow;
2103 if (!TLI.expandMULO(Node, Result, Overflow, DAG))
2104 std::tie(Result, Overflow) = DAG.UnrollVectorOverflowOp(Node);
2105
2106 Results.push_back(Result);
2107 Results.push_back(Overflow);
2108}
2109
2110void VectorLegalizer::ExpandFixedPointDiv(SDNode *Node,
2111 SmallVectorImpl<SDValue> &Results) {
2112 SDNode *N = Node;
2113 if (SDValue Expanded = TLI.expandFixedPointDiv(N->getOpcode(), SDLoc(N),
2114 N->getOperand(0), N->getOperand(1), N->getConstantOperandVal(2), DAG))
2115 Results.push_back(Expanded);
2116}
2117
2118void VectorLegalizer::ExpandStrictFPOp(SDNode *Node,
2119 SmallVectorImpl<SDValue> &Results) {
2120 if (Node->getOpcode() == ISD::STRICT_UINT_TO_FP) {
2121 ExpandUINT_TO_FLOAT(Node, Results);
2122 return;
2123 }
2124 if (Node->getOpcode() == ISD::STRICT_FP_TO_UINT) {
2125 ExpandFP_TO_UINT(Node, Results);
2126 return;
2127 }
2128
2129 if (Node->getOpcode() == ISD::STRICT_FSETCC ||
2130 Node->getOpcode() == ISD::STRICT_FSETCCS) {
2131 ExpandSETCC(Node, Results);
2132 return;
2133 }
2134
2135 UnrollStrictFPOp(Node, Results);
2136}
2137
2138void VectorLegalizer::ExpandREM(SDNode *Node,
2139 SmallVectorImpl<SDValue> &Results) {
2140 assert((Node->getOpcode() == ISD::SREM || Node->getOpcode() == ISD::UREM) &&
2141 "Expected REM node");
2142
2144 if (!TLI.expandREM(Node, Result, DAG))
2145 Result = DAG.UnrollVectorOp(Node);
2146 Results.push_back(Result);
2147}
2148
2149// Try to expand libm nodes into vector math routine calls. Callers provide the
2150// LibFunc equivalent of the passed in Node, which is used to lookup mappings
2151// within TargetLibraryInfo. The only mappings considered are those where the
2152// result and all operands are the same vector type. While predicated nodes are
2153// not supported, we will emit calls to masked routines by passing in an all
2154// true mask.
2155bool VectorLegalizer::tryExpandVecMathCall(SDNode *Node, RTLIB::Libcall LC,
2156 SmallVectorImpl<SDValue> &Results) {
2157 // Chain must be propagated but currently strict fp operations are down
2158 // converted to their none strict counterpart.
2159 assert(!Node->isStrictFPOpcode() && "Unexpected strict fp operation!");
2160
2161 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
2162 if (LCImpl == RTLIB::Unsupported)
2163 return false;
2164
2165 EVT VT = Node->getValueType(0);
2166 const RTLIB::RuntimeLibcallsInfo &RTLCI = TLI.getRuntimeLibcallsInfo();
2167 LLVMContext &Ctx = *DAG.getContext();
2168
2169 auto [FuncTy, FuncAttrs] = RTLCI.getFunctionTy(
2170 Ctx, DAG.getSubtarget().getTargetTriple(), DAG.getDataLayout(), LCImpl);
2171
2172 SDLoc DL(Node);
2173 TargetLowering::ArgListTy Args;
2174
2175 bool HasMaskArg = RTLCI.hasVectorMaskArgument(LCImpl);
2176
2177 // Sanity check just in case function has unexpected parameters.
2178 assert(FuncTy->getNumParams() == Node->getNumOperands() + HasMaskArg &&
2179 EVT::getEVT(FuncTy->getReturnType(), true) == VT &&
2180 "mismatch in value type and call signature type");
2181
2182 for (unsigned I = 0, E = FuncTy->getNumParams(); I != E; ++I) {
2183 Type *ParamTy = FuncTy->getParamType(I);
2184
2185 if (HasMaskArg && I == E - 1) {
2186 assert(cast<VectorType>(ParamTy)->getElementType()->isIntegerTy(1) &&
2187 "unexpected vector mask type");
2188 EVT MaskVT = TLI.getSetCCResultType(DAG.getDataLayout(), Ctx, VT);
2189 Args.emplace_back(DAG.getBoolConstant(true, DL, MaskVT, VT),
2190 MaskVT.getTypeForEVT(Ctx));
2191
2192 } else {
2193 SDValue Op = Node->getOperand(I);
2194 assert(Op.getValueType() == EVT::getEVT(ParamTy, true) &&
2195 "mismatch in value type and call argument type");
2196 Args.emplace_back(Op, ParamTy);
2197 }
2198 }
2199
2200 // Emit a call to the vector function.
2201 SDValue Callee =
2202 DAG.getExternalSymbol(LCImpl, TLI.getPointerTy(DAG.getDataLayout()));
2203 CallingConv::ID CC = RTLCI.getLibcallImplCallingConv(LCImpl);
2204
2205 TargetLowering::CallLoweringInfo CLI(DAG);
2206 CLI.setDebugLoc(DL)
2207 .setChain(DAG.getEntryNode())
2208 .setLibCallee(CC, FuncTy->getReturnType(), Callee, std::move(Args));
2209
2210 std::pair<SDValue, SDValue> CallResult = TLI.LowerCallTo(CLI);
2211 Results.push_back(CallResult.first);
2212 return true;
2213}
2214
2215void VectorLegalizer::UnrollStrictFPOp(SDNode *Node,
2216 SmallVectorImpl<SDValue> &Results) {
2217 EVT VT = Node->getValueType(0);
2218 EVT EltVT = VT.getVectorElementType();
2219 unsigned NumElems = VT.getVectorNumElements();
2220 unsigned NumOpers = Node->getNumOperands();
2221 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
2222
2223 EVT TmpEltVT = EltVT;
2224 if (Node->getOpcode() == ISD::STRICT_FSETCC ||
2225 Node->getOpcode() == ISD::STRICT_FSETCCS)
2226 TmpEltVT = TLI.getSetCCResultType(DAG.getDataLayout(),
2227 *DAG.getContext(), TmpEltVT);
2228
2229 EVT ValueVTs[] = {TmpEltVT, MVT::Other};
2230 SDValue Chain = Node->getOperand(0);
2231 SDLoc dl(Node);
2232
2233 SmallVector<SDValue, 32> OpValues;
2234 SmallVector<SDValue, 32> OpChains;
2235 for (unsigned i = 0; i < NumElems; ++i) {
2237 SDValue Idx = DAG.getVectorIdxConstant(i, dl);
2238
2239 // The Chain is the first operand.
2240 Opers.push_back(Chain);
2241
2242 // Now process the remaining operands.
2243 for (unsigned j = 1; j < NumOpers; ++j) {
2244 SDValue Oper = Node->getOperand(j);
2245 EVT OperVT = Oper.getValueType();
2246
2247 if (OperVT.isVector())
2248 Oper = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl,
2249 OperVT.getVectorElementType(), Oper, Idx);
2250
2251 Opers.push_back(Oper);
2252 }
2253
2254 SDValue ScalarOp = DAG.getNode(Node->getOpcode(), dl, ValueVTs, Opers);
2255 SDValue ScalarResult = ScalarOp.getValue(0);
2256 SDValue ScalarChain = ScalarOp.getValue(1);
2257
2258 if (Node->getOpcode() == ISD::STRICT_FSETCC ||
2259 Node->getOpcode() == ISD::STRICT_FSETCCS)
2260 ScalarResult = DAG.getSelect(dl, EltVT, ScalarResult,
2261 DAG.getAllOnesConstant(dl, EltVT),
2262 DAG.getConstant(0, dl, EltVT));
2263
2264 OpValues.push_back(ScalarResult);
2265 OpChains.push_back(ScalarChain);
2266 }
2267
2268 SDValue Result = DAG.getBuildVector(VT, dl, OpValues);
2269 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OpChains);
2270
2271 Results.push_back(Result);
2272 Results.push_back(NewChain);
2273}
2274
2275SDValue VectorLegalizer::UnrollVSETCC(SDNode *Node) {
2276 EVT VT = Node->getValueType(0);
2277 unsigned NumElems = VT.getVectorNumElements();
2278 EVT EltVT = VT.getVectorElementType();
2279 SDValue LHS = Node->getOperand(0);
2280 SDValue RHS = Node->getOperand(1);
2281 SDValue CC = Node->getOperand(2);
2282 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
2283 SDLoc dl(Node);
2284 SmallVector<SDValue, 8> Ops(NumElems);
2285 for (unsigned i = 0; i < NumElems; ++i) {
2286 SDValue LHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, LHS,
2287 DAG.getVectorIdxConstant(i, dl));
2288 SDValue RHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, RHS,
2289 DAG.getVectorIdxConstant(i, dl));
2290 // FIXME: We should use i1 setcc + boolext here, but it causes regressions.
2291 Ops[i] = DAG.getNode(ISD::SETCC, dl,
2293 *DAG.getContext(), TmpEltVT),
2294 LHSElem, RHSElem, CC);
2295 Ops[i] = DAG.getSelect(dl, EltVT, Ops[i],
2296 DAG.getBoolConstant(true, dl, EltVT, VT),
2297 DAG.getConstant(0, dl, EltVT));
2298 }
2299 return DAG.getBuildVector(VT, dl, Ops);
2300}
2301
2303 return VectorLegalizer(*this).Run();
2304}
return SDValue()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static void createBSWAPShuffleMask(EVT VT, SmallVectorImpl< int > &ShuffleMask)
#define I(x, y, z)
Definition MD5.cpp:57
#define T
SI Fold Operands
This file defines the SmallVector class.
#define LLVM_DEBUG(...)
Definition Debug.h:119
This file describes how to lower LLVM code to machine code.
Value * RHS
Value * LHS
BinaryOperator * Mul
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
Definition APInt.h:226
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
Definition APInt.h:206
bool isBigEndian() const
Definition DataLayout.h:218
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:284
size_t size() const
Definition Function.h:842
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)
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.
bool expandMULO(SDNode *Node, SDValue &Result, SDValue &Overflow, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::[US]MULO.
bool LegalizeSetCCCondCode(SelectionDAG &DAG, EVT VT, SDValue &LHS, SDValue &RHS, SDValue &CC, bool &NeedInvert, const SDLoc &dl, SDValue &Chain, bool IsSignaling=false) const
Legalize a SETCC with given LHS and RHS and condition code CC on the current target.
SDValue scalarizeVectorStore(StoreSDNode *ST, SelectionDAG &DAG) const
SDValue expandVecReduceSeq(SDNode *Node, SelectionDAG &DAG) const
Expand a VECREDUCE_SEQ_* into an explicit ordered calculation.
SDValue expandFCANONICALIZE(SDNode *Node, SelectionDAG &DAG) const
Expand FCANONICALIZE to FMUL with 1.
SDValue expandCTLZ(SDNode *N, SelectionDAG &DAG) const
Expand CTLZ/CTLZ_ZERO_POISON nodes.
SDValue expandBITREVERSE(SDNode *N, SelectionDAG &DAG) const
Expand BITREVERSE nodes.
SDValue expandCTTZ(SDNode *N, SelectionDAG &DAG) const
Expand CTTZ/CTTZ_ZERO_POISON nodes.
SDValue expandABD(SDNode *N, SelectionDAG &DAG) const
Expand ABDS/ABDU nodes.
SDValue expandCLMUL(SDNode *N, SelectionDAG &DAG) const
Expand carryless multiply.
SDValue expandShlSat(SDNode *Node, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::[US]SHLSAT.
SDValue expandFP_TO_INT_SAT(SDNode *N, SelectionDAG &DAG) const
Expand FP_TO_[US]INT_SAT into FP_TO_[US]INT and selects or min/max.
SDValue expandCttzElts(SDNode *Node, SelectionDAG &DAG) const
Expand a CTTZ_ELTS or CTTZ_ELTS_ZERO_POISON by calculating (VL - i) for each active lane (i),...
void expandSADDSUBO(SDNode *Node, SDValue &Result, SDValue &Overflow, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::S(ADD|SUB)O.
SDValue expandABS(SDNode *N, SelectionDAG &DAG, bool IsNegative=false) const
Expand ABS nodes.
SDValue expandVecReduce(SDNode *Node, SelectionDAG &DAG) const
Expand a VECREDUCE_* into an explicit calculation.
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 expandVectorMatch(SDNode *N, SelectionDAG &DAG) const
Expand VECTOR_MATCH nodes.
SDValue expandCONVERT_TO_ARBITRARY_FP(SDNode *Node, SelectionDAG &DAG) const
Expand CONVERT_TO_ARBITRARY_FP using bit manipulation.
SDValue expandFunnelShift(SDNode *N, SelectionDAG &DAG) const
Expand funnel shift.
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const
This callback is invoked for operations that are unsupported by the target, which are registered to u...
SDValue expandFixedPointDiv(unsigned Opcode, const SDLoc &dl, SDValue LHS, SDValue RHS, unsigned Scale, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::[US]DIVFIX[SAT].
SDValue expandPEXT(SDNode *N, SelectionDAG &DAG) const
Expand parallel bit extract (compress).
SDValue expandVECTOR_COMPRESS(SDNode *Node, SelectionDAG &DAG) const
Expand a vector VECTOR_COMPRESS into a sequence of extract element, store temporarily,...
SDValue expandCONVERT_FROM_ARBITRARY_FP(SDNode *Node, SelectionDAG &DAG) const
Expand CONVERT_FROM_ARBITRARY_FP using bit manipulation.
SDValue expandROT(SDNode *N, bool AllowVectorOps, SelectionDAG &DAG) const
Expand rotations.
SDValue expandFMINNUM_FMAXNUM(SDNode *N, SelectionDAG &DAG) const
Expand fminnum/fmaxnum into fminnum_ieee/fmaxnum_ieee with quieted inputs.
SDValue expandCMP(SDNode *Node, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::[US]CMP.
SDValue expandFixedPointMul(SDNode *Node, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::[U|S]MULFIX[SAT].
SDValue expandIntMINMAX(SDNode *Node, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::[US][MIN|MAX].
SDValue expandVectorFindLastActive(SDNode *N, SelectionDAG &DAG) const
Expand VECTOR_FIND_LAST_ACTIVE nodes.
SDValue expandPartialReduceMLA(SDNode *Node, SelectionDAG &DAG) const
Expands PARTIAL_REDUCE_S/UMLA nodes to a series of simpler operations, consisting of zext/sext,...
void expandUADDSUBO(SDNode *Node, SDValue &Result, SDValue &Overflow, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::U(ADD|SUB)O.
SDValue expandPDEP(SDNode *N, SelectionDAG &DAG) const
Expand parallel bit deposit (expand).
bool expandUINT_TO_FP(SDNode *N, SDValue &Result, SDValue &Chain, SelectionDAG &DAG) const
Expand UINT(i64) to double(f64) conversion.
SDValue expandAVG(SDNode *N, SelectionDAG &DAG) const
Expand vector/scalar AVGCEILS/AVGCEILU/AVGFLOORS/AVGFLOORU nodes.
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:829
@ 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:513
@ 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:789
@ 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:863
@ 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:520
@ 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:890
@ 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:749
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
Definition ISDOpcodes.h:920
@ 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:517
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ CLMUL
Carry-less multiplication operations.
Definition ISDOpcodes.h:780
@ 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:798
@ PARTIAL_REDUCE_UMLA
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:854
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
Definition ISDOpcodes.h:717
@ STRICT_UINT_TO_FP
Definition ISDOpcodes.h:487
@ 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:693
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
Definition ISDOpcodes.h:543
@ 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:806
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
Definition ISDOpcodes.h:674
@ 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:706
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:771
@ 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:578
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:860
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:821
@ 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:909
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition ISDOpcodes.h:898
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:729
@ 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:988
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition ISDOpcodes.h:815
@ STRICT_SINT_TO_FP
STRICT_[US]INT_TO_FP - Convert a signed or unsigned integer to a floating point value.
Definition ISDOpcodes.h:486
@ MGATHER
Masked gather and scatter - load and store operations for a vector of random addresses with additiona...
@ STRICT_FP_TO_UINT
Definition ISDOpcodes.h:480
@ PEXT
Parallel bit extract (compress) and parallel bit deposit (expand).
Definition ISDOpcodes.h:785
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
Definition ISDOpcodes.h:502
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:479
@ 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:936
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:507
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:741
@ SCMP
[US]CMP - 3-way comparison of signed or unsigned integers.
Definition ISDOpcodes.h:737
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
Definition ISDOpcodes.h:712
@ VECTOR_MATCH
VECTOR_MATCH - this corresponds to the llvm.experimental.vector.match intrinsic.
@ STRICT_FADD
Constrained versions of the binary floating point operators.
Definition ISDOpcodes.h: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:797
@ 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:969
@ VECTOR_COMPRESS
VECTOR_COMPRESS(Vec, Mask, Passthru) consecutively place vector elements based on mask e....
Definition ISDOpcodes.h:701
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
Definition ISDOpcodes.h:931
@ 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:955
@ VECREDUCE_FMINIMUM
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:866
@ VECREDUCE_SEQ_FMUL
@ CONVERT_TO_ARBITRARY_FP
CONVERT_TO_ARBITRARY_FP - Converts a native FP value to an arbitrary floating-point format,...
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
Definition ISDOpcodes.h:62
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
Definition ISDOpcodes.h:536
@ 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:724
@ ABS_MIN_POISON
ABS with a poison result for INT_MIN.
Definition ISDOpcodes.h:753
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition ISDOpcodes.h:558
@ LOOP_DEPENDENCE_WAR_MASK
The llvm.loop.dependence.
LLVM_ABI NodeType getUnmaskedBinOpOpcode(unsigned MaskedOpc)
Given a MaskedOpc of ISD::MASKED_(U|S)(DIV|REM), returns the unmasked ISD::(U|S)(DIV|REM).
LLVM_ABI std::optional< unsigned > getVPMaskIdx(unsigned Opcode)
The operand position of the vector mask.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
LLVM_ABI bool isVPOpcode(unsigned Opcode)
Whether this is a vector-predicated Opcode.
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:381
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:578
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:1746
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
@ Xor
Bitwise or logical XOR of integers.
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition Sequence.h:341
#define N
Extended Value Type.
Definition ValueTypes.h:35
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
Definition ValueTypes.h:90
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.
LLVM_ABI std::pair< FunctionType *, AttributeList > getFunctionTy(LLVMContext &Ctx, const Triple &TT, const DataLayout &DL, RTLIB::LibcallImpl LibcallImpl) const
static LLVM_ABI bool hasVectorMaskArgument(RTLIB::LibcallImpl Impl)
Returns true if the function has a vector mask argument, which is assumed to be the last argument.