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