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