xref: /src/contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1044eb2f6SDimitry Andric //===- LegalizeVectorOps.cpp - Implement SelectionDAG::LegalizeVectors ----===//
2009b1c42SEd Schouten //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6009b1c42SEd Schouten //
7009b1c42SEd Schouten //===----------------------------------------------------------------------===//
8009b1c42SEd Schouten //
9009b1c42SEd Schouten // This file implements the SelectionDAG::LegalizeVectors method.
10009b1c42SEd Schouten //
11009b1c42SEd Schouten // The vector legalizer looks for vector operations which might need to be
12009b1c42SEd Schouten // scalarized and legalizes them. This is a separate step from Legalize because
13009b1c42SEd Schouten // scalarizing can introduce illegal types.  For example, suppose we have an
14009b1c42SEd Schouten // ISD::SDIV of type v2i64 on x86-32.  The type is legal (for example, addition
15009b1c42SEd Schouten // on a v2i64 is legal), but ISD::SDIV isn't legal, so we have to unroll the
16009b1c42SEd Schouten // operation, which introduces nodes with the illegal type i64 which must be
17009b1c42SEd Schouten // expanded.  Similarly, suppose we have an ISD::SRA of type v16i8 on PowerPC;
18009b1c42SEd Schouten // the operation must be unrolled, which introduces nodes with the illegal
19009b1c42SEd Schouten // type i8 which must be promoted.
20009b1c42SEd Schouten //
21009b1c42SEd Schouten // This does not legalize vector manipulations like ISD::BUILD_VECTOR,
2259850d08SRoman Divacky // or operations that happen to take a vector which are custom-lowered;
2359850d08SRoman Divacky // the legalization for such operations never produces nodes
24009b1c42SEd Schouten // with illegal types, so it's okay to put off legalizing them until
25009b1c42SEd Schouten // SelectionDAG::Legalize runs.
26009b1c42SEd Schouten //
27009b1c42SEd Schouten //===----------------------------------------------------------------------===//
28009b1c42SEd Schouten 
29044eb2f6SDimitry Andric #include "llvm/ADT/DenseMap.h"
30044eb2f6SDimitry Andric #include "llvm/ADT/SmallVector.h"
31ac9a064cSDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h"
32ac9a064cSDimitry Andric #include "llvm/Analysis/VectorUtils.h"
33044eb2f6SDimitry Andric #include "llvm/CodeGen/ISDOpcodes.h"
34009b1c42SEd Schouten #include "llvm/CodeGen/SelectionDAG.h"
35044eb2f6SDimitry Andric #include "llvm/CodeGen/SelectionDAGNodes.h"
36044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetLowering.h"
37044eb2f6SDimitry Andric #include "llvm/CodeGen/ValueTypes.h"
38ac9a064cSDimitry Andric #include "llvm/CodeGenTypes/MachineValueType.h"
39044eb2f6SDimitry Andric #include "llvm/IR/DataLayout.h"
40044eb2f6SDimitry Andric #include "llvm/Support/Casting.h"
41044eb2f6SDimitry Andric #include "llvm/Support/Compiler.h"
421d5ae102SDimitry Andric #include "llvm/Support/Debug.h"
43044eb2f6SDimitry Andric #include "llvm/Support/ErrorHandling.h"
44044eb2f6SDimitry Andric #include <cassert>
45044eb2f6SDimitry Andric #include <cstdint>
46044eb2f6SDimitry Andric #include <iterator>
47044eb2f6SDimitry Andric #include <utility>
48044eb2f6SDimitry Andric 
49009b1c42SEd Schouten using namespace llvm;
50009b1c42SEd Schouten 
51b8a2042aSDimitry Andric #define DEBUG_TYPE "legalizevectorops"
52b8a2042aSDimitry Andric 
53009b1c42SEd Schouten namespace {
54044eb2f6SDimitry Andric 
55009b1c42SEd Schouten class VectorLegalizer {
56009b1c42SEd Schouten   SelectionDAG& DAG;
57d7f7719eSRoman Divacky   const TargetLowering &TLI;
58044eb2f6SDimitry Andric   bool Changed = false; // Keep track of whether anything changed
59009b1c42SEd Schouten 
605ca98fd9SDimitry Andric   /// For nodes that are of legal width, and that have more than one use, this
615ca98fd9SDimitry Andric   /// map indicates what regularized operand to use.  This allows us to avoid
625ca98fd9SDimitry Andric   /// legalizing the same thing more than once.
634a16efa3SDimitry Andric   SmallDenseMap<SDValue, SDValue, 64> LegalizedNodes;
64009b1c42SEd Schouten 
65eb11fae6SDimitry Andric   /// Adds a node to the translation cache.
AddLegalizedOperand(SDValue From,SDValue To)66009b1c42SEd Schouten   void AddLegalizedOperand(SDValue From, SDValue To) {
67009b1c42SEd Schouten     LegalizedNodes.insert(std::make_pair(From, To));
68009b1c42SEd Schouten     // If someone requests legalization of the new node, return itself.
69009b1c42SEd Schouten     if (From != To)
70009b1c42SEd Schouten       LegalizedNodes.insert(std::make_pair(To, To));
71009b1c42SEd Schouten   }
72009b1c42SEd Schouten 
73eb11fae6SDimitry Andric   /// Legalizes the given node.
74009b1c42SEd Schouten   SDValue LegalizeOp(SDValue Op);
755ca98fd9SDimitry Andric 
76eb11fae6SDimitry Andric   /// Assuming the node is legal, "legalize" the results.
77706b4fc4SDimitry Andric   SDValue TranslateLegalizeResults(SDValue Op, SDNode *Result);
78706b4fc4SDimitry Andric 
79706b4fc4SDimitry Andric   /// Make sure Results are legal and update the translation cache.
80706b4fc4SDimitry Andric   SDValue RecursivelyLegalizeResults(SDValue Op,
81706b4fc4SDimitry Andric                                      MutableArrayRef<SDValue> Results);
82706b4fc4SDimitry Andric 
83706b4fc4SDimitry Andric   /// Wrapper to interface LowerOperation with a vector of Results.
84706b4fc4SDimitry Andric   /// Returns false if the target wants to use default expansion. Otherwise
85706b4fc4SDimitry Andric   /// returns true. If return is true and the Results are empty, then the
86706b4fc4SDimitry Andric   /// target wants to keep the input node as is.
87706b4fc4SDimitry Andric   bool LowerOperationWrapper(SDNode *N, SmallVectorImpl<SDValue> &Results);
885ca98fd9SDimitry Andric 
89eb11fae6SDimitry Andric   /// Implements unrolling a VSETCC.
90706b4fc4SDimitry Andric   SDValue UnrollVSETCC(SDNode *Node);
915ca98fd9SDimitry Andric 
92eb11fae6SDimitry Andric   /// Implement expand-based legalization of vector operations.
935ca98fd9SDimitry Andric   ///
945ca98fd9SDimitry Andric   /// This is just a high-level routine to dispatch to specific code paths for
955ca98fd9SDimitry Andric   /// operations to legalize them.
96706b4fc4SDimitry Andric   void Expand(SDNode *Node, SmallVectorImpl<SDValue> &Results);
975ca98fd9SDimitry Andric 
98d8e91e46SDimitry Andric   /// Implements expansion for FP_TO_UINT; falls back to UnrollVectorOp if
99d8e91e46SDimitry Andric   /// FP_TO_SINT isn't legal.
100706b4fc4SDimitry Andric   void ExpandFP_TO_UINT(SDNode *Node, SmallVectorImpl<SDValue> &Results);
101d8e91e46SDimitry Andric 
1025ca98fd9SDimitry Andric   /// Implements expansion for UINT_TO_FLOAT; falls back to UnrollVectorOp if
1035ca98fd9SDimitry Andric   /// SINT_TO_FLOAT and SHR on vectors isn't legal.
104706b4fc4SDimitry Andric   void ExpandUINT_TO_FLOAT(SDNode *Node, SmallVectorImpl<SDValue> &Results);
1055ca98fd9SDimitry Andric 
106eb11fae6SDimitry Andric   /// Implement expansion for SIGN_EXTEND_INREG using SRL and SRA.
107706b4fc4SDimitry Andric   SDValue ExpandSEXTINREG(SDNode *Node);
1085ca98fd9SDimitry Andric 
109eb11fae6SDimitry Andric   /// Implement expansion for ANY_EXTEND_VECTOR_INREG.
1105ca98fd9SDimitry Andric   ///
1115ca98fd9SDimitry Andric   /// Shuffles the low lanes of the operand into place and bitcasts to the proper
1125ca98fd9SDimitry Andric   /// type. The contents of the bits in the extended part of each element are
1135ca98fd9SDimitry Andric   /// undef.
114706b4fc4SDimitry Andric   SDValue ExpandANY_EXTEND_VECTOR_INREG(SDNode *Node);
1155ca98fd9SDimitry Andric 
116eb11fae6SDimitry Andric   /// Implement expansion for SIGN_EXTEND_VECTOR_INREG.
1175ca98fd9SDimitry Andric   ///
1185ca98fd9SDimitry Andric   /// Shuffles the low lanes of the operand into place, bitcasts to the proper
1195ca98fd9SDimitry Andric   /// type, then shifts left and arithmetic shifts right to introduce a sign
1205ca98fd9SDimitry Andric   /// extension.
121706b4fc4SDimitry Andric   SDValue ExpandSIGN_EXTEND_VECTOR_INREG(SDNode *Node);
1225ca98fd9SDimitry Andric 
123eb11fae6SDimitry Andric   /// Implement expansion for ZERO_EXTEND_VECTOR_INREG.
1245ca98fd9SDimitry Andric   ///
1255ca98fd9SDimitry Andric   /// Shuffles the low lanes of the operand into place and blends zeros into
1265ca98fd9SDimitry Andric   /// the remaining lanes, finally bitcasting to the proper type.
127706b4fc4SDimitry Andric   SDValue ExpandZERO_EXTEND_VECTOR_INREG(SDNode *Node);
128d8e91e46SDimitry Andric 
129eb11fae6SDimitry Andric   /// Expand bswap of vectors into a shuffle if legal.
130706b4fc4SDimitry Andric   SDValue ExpandBSWAP(SDNode *Node);
1315ca98fd9SDimitry Andric 
132eb11fae6SDimitry Andric   /// Implement vselect in terms of XOR, AND, OR when blend is not
1335ca98fd9SDimitry Andric   /// supported by the target.
134706b4fc4SDimitry Andric   SDValue ExpandVSELECT(SDNode *Node);
1356f8fc217SDimitry Andric   SDValue ExpandVP_SELECT(SDNode *Node);
1366f8fc217SDimitry Andric   SDValue ExpandVP_MERGE(SDNode *Node);
137e3b55780SDimitry Andric   SDValue ExpandVP_REM(SDNode *Node);
138706b4fc4SDimitry Andric   SDValue ExpandSELECT(SDNode *Node);
139706b4fc4SDimitry Andric   std::pair<SDValue, SDValue> ExpandLoad(SDNode *N);
140706b4fc4SDimitry Andric   SDValue ExpandStore(SDNode *N);
141706b4fc4SDimitry Andric   SDValue ExpandFNEG(SDNode *Node);
142706b4fc4SDimitry Andric   void ExpandFSUB(SDNode *Node, SmallVectorImpl<SDValue> &Results);
143344a3780SDimitry Andric   void ExpandSETCC(SDNode *Node, SmallVectorImpl<SDValue> &Results);
144706b4fc4SDimitry Andric   void ExpandBITREVERSE(SDNode *Node, SmallVectorImpl<SDValue> &Results);
145706b4fc4SDimitry Andric   void ExpandUADDSUBO(SDNode *Node, SmallVectorImpl<SDValue> &Results);
146706b4fc4SDimitry Andric   void ExpandSADDSUBO(SDNode *Node, SmallVectorImpl<SDValue> &Results);
147706b4fc4SDimitry Andric   void ExpandMULO(SDNode *Node, SmallVectorImpl<SDValue> &Results);
148cfca06d7SDimitry Andric   void ExpandFixedPointDiv(SDNode *Node, SmallVectorImpl<SDValue> &Results);
149706b4fc4SDimitry Andric   void ExpandStrictFPOp(SDNode *Node, SmallVectorImpl<SDValue> &Results);
150cfca06d7SDimitry Andric   void ExpandREM(SDNode *Node, SmallVectorImpl<SDValue> &Results);
151706b4fc4SDimitry Andric 
152ac9a064cSDimitry Andric   bool tryExpandVecMathCall(SDNode *Node, RTLIB::Libcall LC,
153ac9a064cSDimitry Andric                             SmallVectorImpl<SDValue> &Results);
154ac9a064cSDimitry Andric   bool tryExpandVecMathCall(SDNode *Node, RTLIB::Libcall Call_F32,
155ac9a064cSDimitry Andric                             RTLIB::Libcall Call_F64, RTLIB::Libcall Call_F80,
156ac9a064cSDimitry Andric                             RTLIB::Libcall Call_F128,
157ac9a064cSDimitry Andric                             RTLIB::Libcall Call_PPCF128,
158ac9a064cSDimitry Andric                             SmallVectorImpl<SDValue> &Results);
159ac9a064cSDimitry Andric 
160706b4fc4SDimitry Andric   void UnrollStrictFPOp(SDNode *Node, SmallVectorImpl<SDValue> &Results);
1615ca98fd9SDimitry Andric 
162eb11fae6SDimitry Andric   /// Implements vector promotion.
1635ca98fd9SDimitry Andric   ///
1645ca98fd9SDimitry Andric   /// This is essentially just bitcasting the operands to a different type and
1655ca98fd9SDimitry Andric   /// bitcasting the result back to the original type.
166706b4fc4SDimitry Andric   void Promote(SDNode *Node, SmallVectorImpl<SDValue> &Results);
1675ca98fd9SDimitry Andric 
168eb11fae6SDimitry Andric   /// Implements [SU]INT_TO_FP vector promotion.
1695ca98fd9SDimitry Andric   ///
170eb11fae6SDimitry Andric   /// This is a [zs]ext of the input operand to a larger integer type.
171706b4fc4SDimitry Andric   void PromoteINT_TO_FP(SDNode *Node, SmallVectorImpl<SDValue> &Results);
1725ca98fd9SDimitry Andric 
173eb11fae6SDimitry Andric   /// Implements FP_TO_[SU]INT vector promotion of the result type.
1745ca98fd9SDimitry Andric   ///
175eb11fae6SDimitry Andric   /// It is promoted to a larger integer type.  The result is then
1765ca98fd9SDimitry Andric   /// truncated back to the original type.
177706b4fc4SDimitry Andric   void PromoteFP_TO_INT(SDNode *Node, SmallVectorImpl<SDValue> &Results);
178009b1c42SEd Schouten 
179b1c73532SDimitry Andric   /// Implements vector setcc operation promotion.
180b1c73532SDimitry Andric   ///
181b1c73532SDimitry Andric   /// All vector operands are promoted to a vector type with larger element
182b1c73532SDimitry Andric   /// type.
183b1c73532SDimitry Andric   void PromoteSETCC(SDNode *Node, SmallVectorImpl<SDValue> &Results);
184b1c73532SDimitry Andric 
185b1c73532SDimitry Andric   void PromoteSTRICT(SDNode *Node, SmallVectorImpl<SDValue> &Results);
186b1c73532SDimitry Andric 
187009b1c42SEd Schouten public:
VectorLegalizer(SelectionDAG & dag)188044eb2f6SDimitry Andric   VectorLegalizer(SelectionDAG& dag) :
189044eb2f6SDimitry Andric       DAG(dag), TLI(dag.getTargetLoweringInfo()) {}
190044eb2f6SDimitry Andric 
191eb11fae6SDimitry Andric   /// Begin legalizer the vector operations in the DAG.
192009b1c42SEd Schouten   bool Run();
193009b1c42SEd Schouten };
194009b1c42SEd Schouten 
195044eb2f6SDimitry Andric } // end anonymous namespace
196044eb2f6SDimitry Andric 
Run()197009b1c42SEd Schouten bool VectorLegalizer::Run() {
1984a16efa3SDimitry Andric   // Before we start legalizing vector nodes, check if there are any vectors.
1994a16efa3SDimitry Andric   bool HasVectors = false;
2004a16efa3SDimitry Andric   for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(),
2015ca98fd9SDimitry Andric        E = std::prev(DAG.allnodes_end()); I != std::next(E); ++I) {
2024a16efa3SDimitry Andric     // Check if the values of the nodes contain vectors. We don't need to check
2034a16efa3SDimitry Andric     // the operands because we are going to check their values at some point.
204cfca06d7SDimitry Andric     HasVectors = llvm::any_of(I->values(), [](EVT T) { return T.isVector(); });
2054a16efa3SDimitry Andric 
2064a16efa3SDimitry Andric     // If we found a vector node we can start the legalization.
2074a16efa3SDimitry Andric     if (HasVectors)
2084a16efa3SDimitry Andric       break;
2094a16efa3SDimitry Andric   }
2104a16efa3SDimitry Andric 
2114a16efa3SDimitry Andric   // If this basic block has no vectors then no need to legalize vectors.
2124a16efa3SDimitry Andric   if (!HasVectors)
2134a16efa3SDimitry Andric     return false;
2144a16efa3SDimitry Andric 
215009b1c42SEd Schouten   // The legalize process is inherently a bottom-up recursive process (users
216009b1c42SEd Schouten   // legalize their uses before themselves).  Given infinite stack space, we
217009b1c42SEd Schouten   // could just start legalizing on the root and traverse the whole graph.  In
218009b1c42SEd Schouten   // practice however, this causes us to run out of stack space on large basic
219009b1c42SEd Schouten   // blocks.  To avoid this problem, compute an ordering of the nodes where each
220009b1c42SEd Schouten   // node is only legalized after all of its operands are legalized.
221009b1c42SEd Schouten   DAG.AssignTopologicalOrder();
222009b1c42SEd Schouten   for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(),
2235ca98fd9SDimitry Andric        E = std::prev(DAG.allnodes_end()); I != std::next(E); ++I)
224dd58ef01SDimitry Andric     LegalizeOp(SDValue(&*I, 0));
225009b1c42SEd Schouten 
226009b1c42SEd Schouten   // Finally, it's possible the root changed.  Get the new root.
227009b1c42SEd Schouten   SDValue OldRoot = DAG.getRoot();
228009b1c42SEd Schouten   assert(LegalizedNodes.count(OldRoot) && "Root didn't get legalized?");
229009b1c42SEd Schouten   DAG.setRoot(LegalizedNodes[OldRoot]);
230009b1c42SEd Schouten 
231009b1c42SEd Schouten   LegalizedNodes.clear();
232009b1c42SEd Schouten 
233009b1c42SEd Schouten   // Remove dead nodes now.
234009b1c42SEd Schouten   DAG.RemoveDeadNodes();
235009b1c42SEd Schouten 
236009b1c42SEd Schouten   return Changed;
237009b1c42SEd Schouten }
238009b1c42SEd Schouten 
TranslateLegalizeResults(SDValue Op,SDNode * Result)239706b4fc4SDimitry Andric SDValue VectorLegalizer::TranslateLegalizeResults(SDValue Op, SDNode *Result) {
240706b4fc4SDimitry Andric   assert(Op->getNumValues() == Result->getNumValues() &&
241706b4fc4SDimitry Andric          "Unexpected number of results");
242009b1c42SEd Schouten   // Generic legalization: just pass the operand through.
243706b4fc4SDimitry Andric   for (unsigned i = 0, e = Op->getNumValues(); i != e; ++i)
244706b4fc4SDimitry Andric     AddLegalizedOperand(Op.getValue(i), SDValue(Result, i));
245706b4fc4SDimitry Andric   return SDValue(Result, Op.getResNo());
246706b4fc4SDimitry Andric }
247706b4fc4SDimitry Andric 
248706b4fc4SDimitry Andric SDValue
RecursivelyLegalizeResults(SDValue Op,MutableArrayRef<SDValue> Results)249706b4fc4SDimitry Andric VectorLegalizer::RecursivelyLegalizeResults(SDValue Op,
250706b4fc4SDimitry Andric                                             MutableArrayRef<SDValue> Results) {
251706b4fc4SDimitry Andric   assert(Results.size() == Op->getNumValues() &&
252706b4fc4SDimitry Andric          "Unexpected number of results");
253706b4fc4SDimitry Andric   // Make sure that the generated code is itself legal.
254706b4fc4SDimitry Andric   for (unsigned i = 0, e = Results.size(); i != e; ++i) {
255706b4fc4SDimitry Andric     Results[i] = LegalizeOp(Results[i]);
256706b4fc4SDimitry Andric     AddLegalizedOperand(Op.getValue(i), Results[i]);
257706b4fc4SDimitry Andric   }
258706b4fc4SDimitry Andric 
259706b4fc4SDimitry Andric   return Results[Op.getResNo()];
260009b1c42SEd Schouten }
261009b1c42SEd Schouten 
LegalizeOp(SDValue Op)262009b1c42SEd Schouten SDValue VectorLegalizer::LegalizeOp(SDValue Op) {
263009b1c42SEd Schouten   // Note that LegalizeOp may be reentered even from single-use nodes, which
264009b1c42SEd Schouten   // means that we always must cache transformed nodes.
265009b1c42SEd Schouten   DenseMap<SDValue, SDValue>::iterator I = LegalizedNodes.find(Op);
266009b1c42SEd Schouten   if (I != LegalizedNodes.end()) return I->second;
267009b1c42SEd Schouten 
268009b1c42SEd Schouten   // Legalize the operands
269009b1c42SEd Schouten   SmallVector<SDValue, 8> Ops;
270706b4fc4SDimitry Andric   for (const SDValue &Oper : Op->op_values())
271706b4fc4SDimitry Andric     Ops.push_back(LegalizeOp(Oper));
272009b1c42SEd Schouten 
273706b4fc4SDimitry Andric   SDNode *Node = DAG.UpdateNodeOperands(Op.getNode(), Ops);
274009b1c42SEd Schouten 
275cfca06d7SDimitry Andric   bool HasVectorValueOrOp =
276cfca06d7SDimitry Andric       llvm::any_of(Node->values(), [](EVT T) { return T.isVector(); }) ||
277cfca06d7SDimitry Andric       llvm::any_of(Node->op_values(),
278cfca06d7SDimitry Andric                    [](SDValue O) { return O.getValueType().isVector(); });
279e6d15924SDimitry Andric   if (!HasVectorValueOrOp)
280706b4fc4SDimitry Andric     return TranslateLegalizeResults(Op, Node);
281009b1c42SEd Schouten 
282eb11fae6SDimitry Andric   TargetLowering::LegalizeAction Action = TargetLowering::Legal;
283706b4fc4SDimitry Andric   EVT ValVT;
284009b1c42SEd Schouten   switch (Op.getOpcode()) {
285009b1c42SEd Schouten   default:
286706b4fc4SDimitry Andric     return TranslateLegalizeResults(Op, Node);
28777fc4c14SDimitry Andric   case ISD::LOAD: {
28877fc4c14SDimitry Andric     LoadSDNode *LD = cast<LoadSDNode>(Node);
28977fc4c14SDimitry Andric     ISD::LoadExtType ExtType = LD->getExtensionType();
29077fc4c14SDimitry Andric     EVT LoadedVT = LD->getMemoryVT();
29177fc4c14SDimitry Andric     if (LoadedVT.isVector() && ExtType != ISD::NON_EXTLOAD)
29277fc4c14SDimitry Andric       Action = TLI.getLoadExtAction(ExtType, LD->getValueType(0), LoadedVT);
29377fc4c14SDimitry Andric     break;
29477fc4c14SDimitry Andric   }
29577fc4c14SDimitry Andric   case ISD::STORE: {
29677fc4c14SDimitry Andric     StoreSDNode *ST = cast<StoreSDNode>(Node);
29777fc4c14SDimitry Andric     EVT StVT = ST->getMemoryVT();
29877fc4c14SDimitry Andric     MVT ValVT = ST->getValue().getSimpleValueType();
29977fc4c14SDimitry Andric     if (StVT.isVector() && ST->isTruncatingStore())
30077fc4c14SDimitry Andric       Action = TLI.getTruncStoreAction(ValVT, StVT);
30177fc4c14SDimitry Andric     break;
30277fc4c14SDimitry Andric   }
303706b4fc4SDimitry Andric   case ISD::MERGE_VALUES:
3041d5ae102SDimitry Andric     Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
305706b4fc4SDimitry Andric     // This operation lies about being legal: when it claims to be legal,
306706b4fc4SDimitry Andric     // it should actually be expanded.
307706b4fc4SDimitry Andric     if (Action == TargetLowering::Legal)
308706b4fc4SDimitry Andric       Action = TargetLowering::Expand;
309706b4fc4SDimitry Andric     break;
310cfca06d7SDimitry Andric #define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN)               \
311706b4fc4SDimitry Andric   case ISD::STRICT_##DAGN:
312706b4fc4SDimitry Andric #include "llvm/IR/ConstrainedOps.def"
313706b4fc4SDimitry Andric     ValVT = Node->getValueType(0);
314706b4fc4SDimitry Andric     if (Op.getOpcode() == ISD::STRICT_SINT_TO_FP ||
315706b4fc4SDimitry Andric         Op.getOpcode() == ISD::STRICT_UINT_TO_FP)
316706b4fc4SDimitry Andric       ValVT = Node->getOperand(1).getValueType();
3177fa27ce4SDimitry Andric     if (Op.getOpcode() == ISD::STRICT_FSETCC ||
3187fa27ce4SDimitry Andric         Op.getOpcode() == ISD::STRICT_FSETCCS) {
3197fa27ce4SDimitry Andric       MVT OpVT = Node->getOperand(1).getSimpleValueType();
3207fa27ce4SDimitry Andric       ISD::CondCode CCCode = cast<CondCodeSDNode>(Node->getOperand(3))->get();
3217fa27ce4SDimitry Andric       Action = TLI.getCondCodeAction(CCCode, OpVT);
3227fa27ce4SDimitry Andric       if (Action == TargetLowering::Legal)
3237fa27ce4SDimitry Andric         Action = TLI.getOperationAction(Node->getOpcode(), OpVT);
3247fa27ce4SDimitry Andric     } else {
325706b4fc4SDimitry Andric       Action = TLI.getOperationAction(Node->getOpcode(), ValVT);
3267fa27ce4SDimitry Andric     }
3271d5ae102SDimitry Andric     // If we're asked to expand a strict vector floating-point operation,
3281d5ae102SDimitry Andric     // by default we're going to simply unroll it.  That is usually the
3291d5ae102SDimitry Andric     // best approach, except in the case where the resulting strict (scalar)
3301d5ae102SDimitry Andric     // operations would themselves use the fallback mutation to non-strict.
3311d5ae102SDimitry Andric     // In that specific case, just do the fallback on the vector op.
332706b4fc4SDimitry Andric     if (Action == TargetLowering::Expand && !TLI.isStrictFPEnabled() &&
333706b4fc4SDimitry Andric         TLI.getStrictFPOperationAction(Node->getOpcode(), ValVT) ==
334706b4fc4SDimitry Andric             TargetLowering::Legal) {
335706b4fc4SDimitry Andric       EVT EltVT = ValVT.getVectorElementType();
3361d5ae102SDimitry Andric       if (TLI.getOperationAction(Node->getOpcode(), EltVT)
3371d5ae102SDimitry Andric           == TargetLowering::Expand &&
3381d5ae102SDimitry Andric           TLI.getStrictFPOperationAction(Node->getOpcode(), EltVT)
3391d5ae102SDimitry Andric           == TargetLowering::Legal)
3401d5ae102SDimitry Andric         Action = TargetLowering::Legal;
3411d5ae102SDimitry Andric     }
342eb11fae6SDimitry Andric     break;
343009b1c42SEd Schouten   case ISD::ADD:
344009b1c42SEd Schouten   case ISD::SUB:
345009b1c42SEd Schouten   case ISD::MUL:
346d8e91e46SDimitry Andric   case ISD::MULHS:
347d8e91e46SDimitry Andric   case ISD::MULHU:
348009b1c42SEd Schouten   case ISD::SDIV:
349009b1c42SEd Schouten   case ISD::UDIV:
350009b1c42SEd Schouten   case ISD::SREM:
351009b1c42SEd Schouten   case ISD::UREM:
352dd58ef01SDimitry Andric   case ISD::SDIVREM:
353dd58ef01SDimitry Andric   case ISD::UDIVREM:
354009b1c42SEd Schouten   case ISD::FADD:
355009b1c42SEd Schouten   case ISD::FSUB:
356009b1c42SEd Schouten   case ISD::FMUL:
357009b1c42SEd Schouten   case ISD::FDIV:
358009b1c42SEd Schouten   case ISD::FREM:
359009b1c42SEd Schouten   case ISD::AND:
360009b1c42SEd Schouten   case ISD::OR:
361009b1c42SEd Schouten   case ISD::XOR:
362009b1c42SEd Schouten   case ISD::SHL:
363009b1c42SEd Schouten   case ISD::SRA:
364009b1c42SEd Schouten   case ISD::SRL:
365d8e91e46SDimitry Andric   case ISD::FSHL:
366d8e91e46SDimitry Andric   case ISD::FSHR:
367009b1c42SEd Schouten   case ISD::ROTL:
368009b1c42SEd Schouten   case ISD::ROTR:
369d8e91e46SDimitry Andric   case ISD::ABS:
370ac9a064cSDimitry Andric   case ISD::ABDS:
371ac9a064cSDimitry Andric   case ISD::ABDU:
372ac9a064cSDimitry Andric   case ISD::AVGCEILS:
373ac9a064cSDimitry Andric   case ISD::AVGCEILU:
374ac9a064cSDimitry Andric   case ISD::AVGFLOORS:
375ac9a064cSDimitry Andric   case ISD::AVGFLOORU:
37668bcb7dbSDimitry Andric   case ISD::BSWAP:
377dd58ef01SDimitry Andric   case ISD::BITREVERSE:
378009b1c42SEd Schouten   case ISD::CTLZ:
37963faed5bSDimitry Andric   case ISD::CTTZ:
38063faed5bSDimitry Andric   case ISD::CTLZ_ZERO_UNDEF:
38163faed5bSDimitry Andric   case ISD::CTTZ_ZERO_UNDEF:
382009b1c42SEd Schouten   case ISD::CTPOP:
383009b1c42SEd Schouten   case ISD::SELECT:
38430815c53SDimitry Andric   case ISD::VSELECT:
385009b1c42SEd Schouten   case ISD::SELECT_CC:
386009b1c42SEd Schouten   case ISD::ZERO_EXTEND:
387009b1c42SEd Schouten   case ISD::ANY_EXTEND:
388009b1c42SEd Schouten   case ISD::TRUNCATE:
389009b1c42SEd Schouten   case ISD::SIGN_EXTEND:
390009b1c42SEd Schouten   case ISD::FP_TO_SINT:
391009b1c42SEd Schouten   case ISD::FP_TO_UINT:
392009b1c42SEd Schouten   case ISD::FNEG:
393009b1c42SEd Schouten   case ISD::FABS:
39467c32a98SDimitry Andric   case ISD::FMINNUM:
39567c32a98SDimitry Andric   case ISD::FMAXNUM:
396d8e91e46SDimitry Andric   case ISD::FMINNUM_IEEE:
397d8e91e46SDimitry Andric   case ISD::FMAXNUM_IEEE:
398d8e91e46SDimitry Andric   case ISD::FMINIMUM:
399d8e91e46SDimitry Andric   case ISD::FMAXIMUM:
400f8af5cf6SDimitry Andric   case ISD::FCOPYSIGN:
401009b1c42SEd Schouten   case ISD::FSQRT:
402009b1c42SEd Schouten   case ISD::FSIN:
403009b1c42SEd Schouten   case ISD::FCOS:
404ac9a064cSDimitry Andric   case ISD::FTAN:
405ac9a064cSDimitry Andric   case ISD::FASIN:
406ac9a064cSDimitry Andric   case ISD::FACOS:
407ac9a064cSDimitry Andric   case ISD::FATAN:
408ac9a064cSDimitry Andric   case ISD::FSINH:
409ac9a064cSDimitry Andric   case ISD::FCOSH:
410ac9a064cSDimitry Andric   case ISD::FTANH:
4117fa27ce4SDimitry Andric   case ISD::FLDEXP:
412009b1c42SEd Schouten   case ISD::FPOWI:
413009b1c42SEd Schouten   case ISD::FPOW:
414009b1c42SEd Schouten   case ISD::FLOG:
415009b1c42SEd Schouten   case ISD::FLOG2:
416009b1c42SEd Schouten   case ISD::FLOG10:
417009b1c42SEd Schouten   case ISD::FEXP:
418009b1c42SEd Schouten   case ISD::FEXP2:
419b1c73532SDimitry Andric   case ISD::FEXP10:
420009b1c42SEd Schouten   case ISD::FCEIL:
421009b1c42SEd Schouten   case ISD::FTRUNC:
422009b1c42SEd Schouten   case ISD::FRINT:
423009b1c42SEd Schouten   case ISD::FNEARBYINT:
424f8af5cf6SDimitry Andric   case ISD::FROUND:
425cfca06d7SDimitry Andric   case ISD::FROUNDEVEN:
426009b1c42SEd Schouten   case ISD::FFLOOR:
4274a16efa3SDimitry Andric   case ISD::FP_ROUND:
4284a16efa3SDimitry Andric   case ISD::FP_EXTEND:
429ac9a064cSDimitry Andric   case ISD::FPTRUNC_ROUND:
430522600a2SDimitry Andric   case ISD::FMA:
431411bd29eSDimitry Andric   case ISD::SIGN_EXTEND_INREG:
4325ca98fd9SDimitry Andric   case ISD::ANY_EXTEND_VECTOR_INREG:
4335ca98fd9SDimitry Andric   case ISD::SIGN_EXTEND_VECTOR_INREG:
4345ca98fd9SDimitry Andric   case ISD::ZERO_EXTEND_VECTOR_INREG:
4355a5ac124SDimitry Andric   case ISD::SMIN:
4365a5ac124SDimitry Andric   case ISD::SMAX:
4375a5ac124SDimitry Andric   case ISD::UMIN:
4385a5ac124SDimitry Andric   case ISD::UMAX:
439b915e9e0SDimitry Andric   case ISD::SMUL_LOHI:
440b915e9e0SDimitry Andric   case ISD::UMUL_LOHI:
441e6d15924SDimitry Andric   case ISD::SADDO:
442e6d15924SDimitry Andric   case ISD::UADDO:
443e6d15924SDimitry Andric   case ISD::SSUBO:
444e6d15924SDimitry Andric   case ISD::USUBO:
445e6d15924SDimitry Andric   case ISD::SMULO:
446e6d15924SDimitry Andric   case ISD::UMULO:
447eb11fae6SDimitry Andric   case ISD::FCANONICALIZE:
4487fa27ce4SDimitry Andric   case ISD::FFREXP:
449d8e91e46SDimitry Andric   case ISD::SADDSAT:
450d8e91e46SDimitry Andric   case ISD::UADDSAT:
451d8e91e46SDimitry Andric   case ISD::SSUBSAT:
452d8e91e46SDimitry Andric   case ISD::USUBSAT:
453b60736ecSDimitry Andric   case ISD::SSHLSAT:
454b60736ecSDimitry Andric   case ISD::USHLSAT:
455b60736ecSDimitry Andric   case ISD::FP_TO_SINT_SAT:
456b60736ecSDimitry Andric   case ISD::FP_TO_UINT_SAT:
457344a3780SDimitry Andric   case ISD::MGATHER:
458ac9a064cSDimitry Andric   case ISD::VECTOR_COMPRESS:
459ac9a064cSDimitry Andric   case ISD::SCMP:
460ac9a064cSDimitry Andric   case ISD::UCMP:
461eb11fae6SDimitry Andric     Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
462f4fe016fSEd Schouten     break;
463e6d15924SDimitry Andric   case ISD::SMULFIX:
464e6d15924SDimitry Andric   case ISD::SMULFIXSAT:
4651d5ae102SDimitry Andric   case ISD::UMULFIX:
466706b4fc4SDimitry Andric   case ISD::UMULFIXSAT:
467706b4fc4SDimitry Andric   case ISD::SDIVFIX:
468cfca06d7SDimitry Andric   case ISD::SDIVFIXSAT:
469cfca06d7SDimitry Andric   case ISD::UDIVFIX:
470cfca06d7SDimitry Andric   case ISD::UDIVFIXSAT: {
471d8e91e46SDimitry Andric     unsigned Scale = Node->getConstantOperandVal(2);
472d8e91e46SDimitry Andric     Action = TLI.getFixedPointOperationAction(Node->getOpcode(),
473d8e91e46SDimitry Andric                                               Node->getValueType(0), Scale);
474d8e91e46SDimitry Andric     break;
475d8e91e46SDimitry Andric   }
476ac9a064cSDimitry Andric   case ISD::LRINT:
477ac9a064cSDimitry Andric   case ISD::LLRINT:
478f4fe016fSEd Schouten   case ISD::SINT_TO_FP:
479f4fe016fSEd Schouten   case ISD::UINT_TO_FP:
480e6d15924SDimitry Andric   case ISD::VECREDUCE_ADD:
481e6d15924SDimitry Andric   case ISD::VECREDUCE_MUL:
482e6d15924SDimitry Andric   case ISD::VECREDUCE_AND:
483e6d15924SDimitry Andric   case ISD::VECREDUCE_OR:
484e6d15924SDimitry Andric   case ISD::VECREDUCE_XOR:
485e6d15924SDimitry Andric   case ISD::VECREDUCE_SMAX:
486e6d15924SDimitry Andric   case ISD::VECREDUCE_SMIN:
487e6d15924SDimitry Andric   case ISD::VECREDUCE_UMAX:
488e6d15924SDimitry Andric   case ISD::VECREDUCE_UMIN:
489e6d15924SDimitry Andric   case ISD::VECREDUCE_FADD:
490e6d15924SDimitry Andric   case ISD::VECREDUCE_FMUL:
491e6d15924SDimitry Andric   case ISD::VECREDUCE_FMAX:
492e6d15924SDimitry Andric   case ISD::VECREDUCE_FMIN:
4937fa27ce4SDimitry Andric   case ISD::VECREDUCE_FMAXIMUM:
4947fa27ce4SDimitry Andric   case ISD::VECREDUCE_FMINIMUM:
495eb11fae6SDimitry Andric     Action = TLI.getOperationAction(Node->getOpcode(),
496eb11fae6SDimitry Andric                                     Node->getOperand(0).getValueType());
497009b1c42SEd Schouten     break;
498b60736ecSDimitry Andric   case ISD::VECREDUCE_SEQ_FADD:
499b60736ecSDimitry Andric   case ISD::VECREDUCE_SEQ_FMUL:
500b60736ecSDimitry Andric     Action = TLI.getOperationAction(Node->getOpcode(),
501b60736ecSDimitry Andric                                     Node->getOperand(1).getValueType());
502b60736ecSDimitry Andric     break;
503344a3780SDimitry Andric   case ISD::SETCC: {
504344a3780SDimitry Andric     MVT OpVT = Node->getOperand(0).getSimpleValueType();
505344a3780SDimitry Andric     ISD::CondCode CCCode = cast<CondCodeSDNode>(Node->getOperand(2))->get();
506344a3780SDimitry Andric     Action = TLI.getCondCodeAction(CCCode, OpVT);
507344a3780SDimitry Andric     if (Action == TargetLowering::Legal)
5087fa27ce4SDimitry Andric       Action = TLI.getOperationAction(Node->getOpcode(), OpVT);
509344a3780SDimitry Andric     break;
510344a3780SDimitry Andric   }
5116f8fc217SDimitry Andric 
5126f8fc217SDimitry Andric #define BEGIN_REGISTER_VP_SDNODE(VPID, LEGALPOS, ...)                          \
5136f8fc217SDimitry Andric   case ISD::VPID: {                                                            \
5146f8fc217SDimitry Andric     EVT LegalizeVT = LEGALPOS < 0 ? Node->getValueType(-(1 + LEGALPOS))        \
5156f8fc217SDimitry Andric                                   : Node->getOperand(LEGALPOS).getValueType(); \
516145449b1SDimitry Andric     if (ISD::VPID == ISD::VP_SETCC) {                                          \
517145449b1SDimitry Andric       ISD::CondCode CCCode = cast<CondCodeSDNode>(Node->getOperand(2))->get(); \
518145449b1SDimitry Andric       Action = TLI.getCondCodeAction(CCCode, LegalizeVT.getSimpleVT());        \
519145449b1SDimitry Andric       if (Action != TargetLowering::Legal)                                     \
520145449b1SDimitry Andric         break;                                                                 \
521145449b1SDimitry Andric     }                                                                          \
522ac9a064cSDimitry Andric     /* Defer non-vector results to LegalizeDAG. */                             \
523ac9a064cSDimitry Andric     if (!Node->getValueType(0).isVector() &&                                   \
524ac9a064cSDimitry Andric         Node->getValueType(0) != MVT::Other) {                                 \
525ac9a064cSDimitry Andric       Action = TargetLowering::Legal;                                          \
526ac9a064cSDimitry Andric       break;                                                                   \
527ac9a064cSDimitry Andric     }                                                                          \
5286f8fc217SDimitry Andric     Action = TLI.getOperationAction(Node->getOpcode(), LegalizeVT);            \
5296f8fc217SDimitry Andric   } break;
5306f8fc217SDimitry Andric #include "llvm/IR/VPIntrinsics.def"
531009b1c42SEd Schouten   }
532009b1c42SEd Schouten 
533eb11fae6SDimitry Andric   LLVM_DEBUG(dbgs() << "\nLegalizing vector op: "; Node->dump(&DAG));
534b8a2042aSDimitry Andric 
535706b4fc4SDimitry Andric   SmallVector<SDValue, 8> ResultVals;
536eb11fae6SDimitry Andric   switch (Action) {
537dd58ef01SDimitry Andric   default: llvm_unreachable("This action is not supported yet!");
538009b1c42SEd Schouten   case TargetLowering::Promote:
53977fc4c14SDimitry Andric     assert((Op.getOpcode() != ISD::LOAD && Op.getOpcode() != ISD::STORE) &&
54077fc4c14SDimitry Andric            "This action is not supported yet!");
541706b4fc4SDimitry Andric     LLVM_DEBUG(dbgs() << "Promoting\n");
542706b4fc4SDimitry Andric     Promote(Node, ResultVals);
543706b4fc4SDimitry Andric     assert(!ResultVals.empty() && "No results for promotion?");
544009b1c42SEd Schouten     break;
5455ca98fd9SDimitry Andric   case TargetLowering::Legal:
546eb11fae6SDimitry Andric     LLVM_DEBUG(dbgs() << "Legal node: nothing to do\n");
54758b69754SDimitry Andric     break;
548706b4fc4SDimitry Andric   case TargetLowering::Custom:
549eb11fae6SDimitry Andric     LLVM_DEBUG(dbgs() << "Trying custom legalization\n");
550706b4fc4SDimitry Andric     if (LowerOperationWrapper(Node, ResultVals))
551009b1c42SEd Schouten       break;
552eb11fae6SDimitry Andric     LLVM_DEBUG(dbgs() << "Could not custom legalize node\n");
553e3b55780SDimitry Andric     [[fallthrough]];
554009b1c42SEd Schouten   case TargetLowering::Expand:
555706b4fc4SDimitry Andric     LLVM_DEBUG(dbgs() << "Expanding\n");
556706b4fc4SDimitry Andric     Expand(Node, ResultVals);
557706b4fc4SDimitry Andric     break;
558009b1c42SEd Schouten   }
559009b1c42SEd Schouten 
560706b4fc4SDimitry Andric   if (ResultVals.empty())
561706b4fc4SDimitry Andric     return TranslateLegalizeResults(Op, Node);
562706b4fc4SDimitry Andric 
563009b1c42SEd Schouten   Changed = true;
564706b4fc4SDimitry Andric   return RecursivelyLegalizeResults(Op, ResultVals);
565009b1c42SEd Schouten }
566009b1c42SEd Schouten 
567c0981da4SDimitry Andric // FIXME: This is very similar to TargetLowering::LowerOperationWrapper. Can we
568c0981da4SDimitry Andric // merge them somehow?
LowerOperationWrapper(SDNode * Node,SmallVectorImpl<SDValue> & Results)569706b4fc4SDimitry Andric bool VectorLegalizer::LowerOperationWrapper(SDNode *Node,
570706b4fc4SDimitry Andric                                             SmallVectorImpl<SDValue> &Results) {
571706b4fc4SDimitry Andric   SDValue Res = TLI.LowerOperation(SDValue(Node, 0), DAG);
572706b4fc4SDimitry Andric 
573706b4fc4SDimitry Andric   if (!Res.getNode())
574706b4fc4SDimitry Andric     return false;
575706b4fc4SDimitry Andric 
576706b4fc4SDimitry Andric   if (Res == SDValue(Node, 0))
577706b4fc4SDimitry Andric     return true;
578706b4fc4SDimitry Andric 
579706b4fc4SDimitry Andric   // If the original node has one result, take the return value from
580706b4fc4SDimitry Andric   // LowerOperation as is. It might not be result number 0.
581706b4fc4SDimitry Andric   if (Node->getNumValues() == 1) {
582706b4fc4SDimitry Andric     Results.push_back(Res);
583706b4fc4SDimitry Andric     return true;
584009b1c42SEd Schouten   }
585009b1c42SEd Schouten 
586706b4fc4SDimitry Andric   // If the original node has multiple results, then the return node should
587706b4fc4SDimitry Andric   // have the same number of results.
588706b4fc4SDimitry Andric   assert((Node->getNumValues() == Res->getNumValues()) &&
589706b4fc4SDimitry Andric          "Lowering returned the wrong number of results!");
590706b4fc4SDimitry Andric 
591706b4fc4SDimitry Andric   // Places new result values base on N result number.
592706b4fc4SDimitry Andric   for (unsigned I = 0, E = Node->getNumValues(); I != E; ++I)
593706b4fc4SDimitry Andric     Results.push_back(Res.getValue(I));
594706b4fc4SDimitry Andric 
595706b4fc4SDimitry Andric   return true;
596706b4fc4SDimitry Andric }
597706b4fc4SDimitry Andric 
PromoteSETCC(SDNode * Node,SmallVectorImpl<SDValue> & Results)598b1c73532SDimitry Andric void VectorLegalizer::PromoteSETCC(SDNode *Node,
599b1c73532SDimitry Andric                                    SmallVectorImpl<SDValue> &Results) {
600b1c73532SDimitry Andric   MVT VecVT = Node->getOperand(0).getSimpleValueType();
601b1c73532SDimitry Andric   MVT NewVecVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VecVT);
602b1c73532SDimitry Andric 
603b1c73532SDimitry Andric   unsigned ExtOp = VecVT.isFloatingPoint() ? ISD::FP_EXTEND : ISD::ANY_EXTEND;
604b1c73532SDimitry Andric 
605b1c73532SDimitry Andric   SDLoc DL(Node);
606b1c73532SDimitry Andric   SmallVector<SDValue, 5> Operands(Node->getNumOperands());
607b1c73532SDimitry Andric 
608b1c73532SDimitry Andric   Operands[0] = DAG.getNode(ExtOp, DL, NewVecVT, Node->getOperand(0));
609b1c73532SDimitry Andric   Operands[1] = DAG.getNode(ExtOp, DL, NewVecVT, Node->getOperand(1));
610b1c73532SDimitry Andric   Operands[2] = Node->getOperand(2);
611b1c73532SDimitry Andric 
612b1c73532SDimitry Andric   if (Node->getOpcode() == ISD::VP_SETCC) {
613b1c73532SDimitry Andric     Operands[3] = Node->getOperand(3); // mask
614b1c73532SDimitry Andric     Operands[4] = Node->getOperand(4); // evl
615b1c73532SDimitry Andric   }
616b1c73532SDimitry Andric 
617b1c73532SDimitry Andric   SDValue Res = DAG.getNode(Node->getOpcode(), DL, Node->getSimpleValueType(0),
618b1c73532SDimitry Andric                             Operands, Node->getFlags());
619b1c73532SDimitry Andric 
620b1c73532SDimitry Andric   Results.push_back(Res);
621b1c73532SDimitry Andric }
622b1c73532SDimitry Andric 
PromoteSTRICT(SDNode * Node,SmallVectorImpl<SDValue> & Results)623b1c73532SDimitry Andric void VectorLegalizer::PromoteSTRICT(SDNode *Node,
624b1c73532SDimitry Andric                                     SmallVectorImpl<SDValue> &Results) {
625b1c73532SDimitry Andric   MVT VecVT = Node->getOperand(1).getSimpleValueType();
626b1c73532SDimitry Andric   MVT NewVecVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VecVT);
627b1c73532SDimitry Andric 
628b1c73532SDimitry Andric   assert(VecVT.isFloatingPoint());
629b1c73532SDimitry Andric 
630b1c73532SDimitry Andric   SDLoc DL(Node);
631b1c73532SDimitry Andric   SmallVector<SDValue, 5> Operands(Node->getNumOperands());
632b1c73532SDimitry Andric   SmallVector<SDValue, 2> Chains;
633b1c73532SDimitry Andric 
634b1c73532SDimitry Andric   for (unsigned j = 1; j != Node->getNumOperands(); ++j)
635b1c73532SDimitry Andric     if (Node->getOperand(j).getValueType().isVector() &&
636b1c73532SDimitry Andric         !(ISD::isVPOpcode(Node->getOpcode()) &&
637b1c73532SDimitry Andric           ISD::getVPMaskIdx(Node->getOpcode()) == j)) // Skip mask operand.
638b1c73532SDimitry Andric     {
639b1c73532SDimitry Andric       // promote the vector operand.
640b1c73532SDimitry Andric       SDValue Ext =
641b1c73532SDimitry Andric           DAG.getNode(ISD::STRICT_FP_EXTEND, DL, {NewVecVT, MVT::Other},
642b1c73532SDimitry Andric                       {Node->getOperand(0), Node->getOperand(j)});
643b1c73532SDimitry Andric       Operands[j] = Ext.getValue(0);
644b1c73532SDimitry Andric       Chains.push_back(Ext.getValue(1));
645b1c73532SDimitry Andric     } else
646b1c73532SDimitry Andric       Operands[j] = Node->getOperand(j); // Skip no vector operand.
647b1c73532SDimitry Andric 
648b1c73532SDimitry Andric   SDVTList VTs = DAG.getVTList(NewVecVT, Node->getValueType(1));
649b1c73532SDimitry Andric 
650b1c73532SDimitry Andric   Operands[0] = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
651b1c73532SDimitry Andric 
652b1c73532SDimitry Andric   SDValue Res =
653b1c73532SDimitry Andric       DAG.getNode(Node->getOpcode(), DL, VTs, Operands, Node->getFlags());
654b1c73532SDimitry Andric 
655b1c73532SDimitry Andric   SDValue Round =
656b1c73532SDimitry Andric       DAG.getNode(ISD::STRICT_FP_ROUND, DL, {VecVT, MVT::Other},
657b1c73532SDimitry Andric                   {Res.getValue(1), Res.getValue(0),
658b1c73532SDimitry Andric                    DAG.getIntPtrConstant(0, DL, /*isTarget=*/true)});
659b1c73532SDimitry Andric 
660b1c73532SDimitry Andric   Results.push_back(Round.getValue(0));
661b1c73532SDimitry Andric   Results.push_back(Round.getValue(1));
662b1c73532SDimitry Andric }
663b1c73532SDimitry Andric 
Promote(SDNode * Node,SmallVectorImpl<SDValue> & Results)664706b4fc4SDimitry Andric void VectorLegalizer::Promote(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
6655ca98fd9SDimitry Andric   // For a few operations there is a specific concept for promotion based on
6665ca98fd9SDimitry Andric   // the operand's type.
667706b4fc4SDimitry Andric   switch (Node->getOpcode()) {
6685ca98fd9SDimitry Andric   case ISD::SINT_TO_FP:
6695ca98fd9SDimitry Andric   case ISD::UINT_TO_FP:
670706b4fc4SDimitry Andric   case ISD::STRICT_SINT_TO_FP:
671706b4fc4SDimitry Andric   case ISD::STRICT_UINT_TO_FP:
6725ca98fd9SDimitry Andric     // "Promote" the operation by extending the operand.
673706b4fc4SDimitry Andric     PromoteINT_TO_FP(Node, Results);
674706b4fc4SDimitry Andric     return;
6755ca98fd9SDimitry Andric   case ISD::FP_TO_UINT:
6765ca98fd9SDimitry Andric   case ISD::FP_TO_SINT:
677706b4fc4SDimitry Andric   case ISD::STRICT_FP_TO_UINT:
678706b4fc4SDimitry Andric   case ISD::STRICT_FP_TO_SINT:
6795ca98fd9SDimitry Andric     // Promote the operation by extending the operand.
680706b4fc4SDimitry Andric     PromoteFP_TO_INT(Node, Results);
681706b4fc4SDimitry Andric     return;
682b1c73532SDimitry Andric   case ISD::VP_SETCC:
683b1c73532SDimitry Andric   case ISD::SETCC:
684b1c73532SDimitry Andric     // Promote the operation by extending the operand.
685b1c73532SDimitry Andric     PromoteSETCC(Node, Results);
686b1c73532SDimitry Andric     return;
687b1c73532SDimitry Andric   case ISD::STRICT_FADD:
688b1c73532SDimitry Andric   case ISD::STRICT_FSUB:
689b1c73532SDimitry Andric   case ISD::STRICT_FMUL:
690b1c73532SDimitry Andric   case ISD::STRICT_FDIV:
691b1c73532SDimitry Andric   case ISD::STRICT_FSQRT:
692b1c73532SDimitry Andric   case ISD::STRICT_FMA:
693b1c73532SDimitry Andric     PromoteSTRICT(Node, Results);
694b1c73532SDimitry Andric     return;
695706b4fc4SDimitry Andric   case ISD::FP_ROUND:
696706b4fc4SDimitry Andric   case ISD::FP_EXTEND:
697706b4fc4SDimitry Andric     // These operations are used to do promotion so they can't be promoted
698706b4fc4SDimitry Andric     // themselves.
699706b4fc4SDimitry Andric     llvm_unreachable("Don't know how to promote this operation!");
7005ca98fd9SDimitry Andric   }
7015ca98fd9SDimitry Andric 
70267c32a98SDimitry Andric   // There are currently two cases of vector promotion:
70367c32a98SDimitry Andric   // 1) Bitcasting a vector of integers to a different type to a vector of the
7045a5ac124SDimitry Andric   //    same overall length. For example, x86 promotes ISD::AND v2i32 to v1i64.
70567c32a98SDimitry Andric   // 2) Extending a vector of floats to a vector of the same number of larger
70667c32a98SDimitry Andric   //    floats. For example, AArch64 promotes ISD::FADD on v4f16 to v4f32.
707706b4fc4SDimitry Andric   assert(Node->getNumValues() == 1 &&
708009b1c42SEd Schouten          "Can't promote a vector with multiple results!");
709706b4fc4SDimitry Andric   MVT VT = Node->getSimpleValueType(0);
710706b4fc4SDimitry Andric   MVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VT);
711706b4fc4SDimitry Andric   SDLoc dl(Node);
712706b4fc4SDimitry Andric   SmallVector<SDValue, 4> Operands(Node->getNumOperands());
713009b1c42SEd Schouten 
714706b4fc4SDimitry Andric   for (unsigned j = 0; j != Node->getNumOperands(); ++j) {
715b1c73532SDimitry Andric     // Do not promote the mask operand of a VP OP.
716b1c73532SDimitry Andric     bool SkipPromote = ISD::isVPOpcode(Node->getOpcode()) &&
717b1c73532SDimitry Andric                        ISD::getVPMaskIdx(Node->getOpcode()) == j;
718b1c73532SDimitry Andric     if (Node->getOperand(j).getValueType().isVector() && !SkipPromote)
719706b4fc4SDimitry Andric       if (Node->getOperand(j)
72067c32a98SDimitry Andric               .getValueType()
72167c32a98SDimitry Andric               .getVectorElementType()
722608e6659SDimitry Andric               .isFloatingPoint() &&
723608e6659SDimitry Andric           NVT.isVector() && NVT.getVectorElementType().isFloatingPoint())
724706b4fc4SDimitry Andric         Operands[j] = DAG.getNode(ISD::FP_EXTEND, dl, NVT, Node->getOperand(j));
72567c32a98SDimitry Andric       else
726706b4fc4SDimitry Andric         Operands[j] = DAG.getNode(ISD::BITCAST, dl, NVT, Node->getOperand(j));
727009b1c42SEd Schouten     else
728706b4fc4SDimitry Andric       Operands[j] = Node->getOperand(j);
729009b1c42SEd Schouten   }
730009b1c42SEd Schouten 
731706b4fc4SDimitry Andric   SDValue Res =
732706b4fc4SDimitry Andric       DAG.getNode(Node->getOpcode(), dl, NVT, Operands, Node->getFlags());
733706b4fc4SDimitry Andric 
734608e6659SDimitry Andric   if ((VT.isFloatingPoint() && NVT.isFloatingPoint()) ||
735608e6659SDimitry Andric       (VT.isVector() && VT.getVectorElementType().isFloatingPoint() &&
736608e6659SDimitry Andric        NVT.isVector() && NVT.getVectorElementType().isFloatingPoint()))
737e3b55780SDimitry Andric     Res = DAG.getNode(ISD::FP_ROUND, dl, VT, Res,
738e3b55780SDimitry Andric                       DAG.getIntPtrConstant(0, dl, /*isTarget=*/true));
73967c32a98SDimitry Andric   else
740706b4fc4SDimitry Andric     Res = DAG.getNode(ISD::BITCAST, dl, VT, Res);
741706b4fc4SDimitry Andric 
742706b4fc4SDimitry Andric   Results.push_back(Res);
743009b1c42SEd Schouten }
744009b1c42SEd Schouten 
PromoteINT_TO_FP(SDNode * Node,SmallVectorImpl<SDValue> & Results)745706b4fc4SDimitry Andric void VectorLegalizer::PromoteINT_TO_FP(SDNode *Node,
746706b4fc4SDimitry Andric                                        SmallVectorImpl<SDValue> &Results) {
74758b69754SDimitry Andric   // INT_TO_FP operations may require the input operand be promoted even
74858b69754SDimitry Andric   // when the type is otherwise legal.
749706b4fc4SDimitry Andric   bool IsStrict = Node->isStrictFPOpcode();
750706b4fc4SDimitry Andric   MVT VT = Node->getOperand(IsStrict ? 1 : 0).getSimpleValueType();
751706b4fc4SDimitry Andric   MVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VT);
752eb11fae6SDimitry Andric   assert(NVT.getVectorNumElements() == VT.getVectorNumElements() &&
753eb11fae6SDimitry Andric          "Vectors have different number of elements!");
75458b69754SDimitry Andric 
755706b4fc4SDimitry Andric   SDLoc dl(Node);
756706b4fc4SDimitry Andric   SmallVector<SDValue, 4> Operands(Node->getNumOperands());
75758b69754SDimitry Andric 
758706b4fc4SDimitry Andric   unsigned Opc = (Node->getOpcode() == ISD::UINT_TO_FP ||
759706b4fc4SDimitry Andric                   Node->getOpcode() == ISD::STRICT_UINT_TO_FP)
760706b4fc4SDimitry Andric                      ? ISD::ZERO_EXTEND
761706b4fc4SDimitry Andric                      : ISD::SIGN_EXTEND;
762706b4fc4SDimitry Andric   for (unsigned j = 0; j != Node->getNumOperands(); ++j) {
763706b4fc4SDimitry Andric     if (Node->getOperand(j).getValueType().isVector())
764706b4fc4SDimitry Andric       Operands[j] = DAG.getNode(Opc, dl, NVT, Node->getOperand(j));
76558b69754SDimitry Andric     else
766706b4fc4SDimitry Andric       Operands[j] = Node->getOperand(j);
76758b69754SDimitry Andric   }
76858b69754SDimitry Andric 
769706b4fc4SDimitry Andric   if (IsStrict) {
770706b4fc4SDimitry Andric     SDValue Res = DAG.getNode(Node->getOpcode(), dl,
771706b4fc4SDimitry Andric                               {Node->getValueType(0), MVT::Other}, Operands);
772706b4fc4SDimitry Andric     Results.push_back(Res);
773706b4fc4SDimitry Andric     Results.push_back(Res.getValue(1));
774706b4fc4SDimitry Andric     return;
775706b4fc4SDimitry Andric   }
776706b4fc4SDimitry Andric 
777706b4fc4SDimitry Andric   SDValue Res =
778706b4fc4SDimitry Andric       DAG.getNode(Node->getOpcode(), dl, Node->getValueType(0), Operands);
779706b4fc4SDimitry Andric   Results.push_back(Res);
7805ca98fd9SDimitry Andric }
7815ca98fd9SDimitry Andric 
7825ca98fd9SDimitry Andric // For FP_TO_INT we promote the result type to a vector type with wider
7835ca98fd9SDimitry Andric // elements and then truncate the result.  This is different from the default
7845ca98fd9SDimitry Andric // PromoteVector which uses bitcast to promote thus assumning that the
7855ca98fd9SDimitry Andric // promoted vector type has the same overall size.
PromoteFP_TO_INT(SDNode * Node,SmallVectorImpl<SDValue> & Results)786706b4fc4SDimitry Andric void VectorLegalizer::PromoteFP_TO_INT(SDNode *Node,
787706b4fc4SDimitry Andric                                        SmallVectorImpl<SDValue> &Results) {
788706b4fc4SDimitry Andric   MVT VT = Node->getSimpleValueType(0);
789706b4fc4SDimitry Andric   MVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VT);
790706b4fc4SDimitry Andric   bool IsStrict = Node->isStrictFPOpcode();
791eb11fae6SDimitry Andric   assert(NVT.getVectorNumElements() == VT.getVectorNumElements() &&
792eb11fae6SDimitry Andric          "Vectors have different number of elements!");
7935ca98fd9SDimitry Andric 
794706b4fc4SDimitry Andric   unsigned NewOpc = Node->getOpcode();
795eb11fae6SDimitry Andric   // Change FP_TO_UINT to FP_TO_SINT if possible.
796eb11fae6SDimitry Andric   // TODO: Should we only do this if FP_TO_UINT itself isn't legal?
797eb11fae6SDimitry Andric   if (NewOpc == ISD::FP_TO_UINT &&
798eb11fae6SDimitry Andric       TLI.isOperationLegalOrCustom(ISD::FP_TO_SINT, NVT))
7995ca98fd9SDimitry Andric     NewOpc = ISD::FP_TO_SINT;
8005ca98fd9SDimitry Andric 
801706b4fc4SDimitry Andric   if (NewOpc == ISD::STRICT_FP_TO_UINT &&
802706b4fc4SDimitry Andric       TLI.isOperationLegalOrCustom(ISD::STRICT_FP_TO_SINT, NVT))
803706b4fc4SDimitry Andric     NewOpc = ISD::STRICT_FP_TO_SINT;
804706b4fc4SDimitry Andric 
805706b4fc4SDimitry Andric   SDLoc dl(Node);
806706b4fc4SDimitry Andric   SDValue Promoted, Chain;
807706b4fc4SDimitry Andric   if (IsStrict) {
808706b4fc4SDimitry Andric     Promoted = DAG.getNode(NewOpc, dl, {NVT, MVT::Other},
809706b4fc4SDimitry Andric                            {Node->getOperand(0), Node->getOperand(1)});
810706b4fc4SDimitry Andric     Chain = Promoted.getValue(1);
811706b4fc4SDimitry Andric   } else
812706b4fc4SDimitry Andric     Promoted = DAG.getNode(NewOpc, dl, NVT, Node->getOperand(0));
81358b69754SDimitry Andric 
814044eb2f6SDimitry Andric   // Assert that the converted value fits in the original type.  If it doesn't
815044eb2f6SDimitry Andric   // (eg: because the value being converted is too big), then the result of the
816044eb2f6SDimitry Andric   // original operation was undefined anyway, so the assert is still correct.
817706b4fc4SDimitry Andric   if (Node->getOpcode() == ISD::FP_TO_UINT ||
818706b4fc4SDimitry Andric       Node->getOpcode() == ISD::STRICT_FP_TO_UINT)
819706b4fc4SDimitry Andric     NewOpc = ISD::AssertZext;
820706b4fc4SDimitry Andric   else
821706b4fc4SDimitry Andric     NewOpc = ISD::AssertSext;
822706b4fc4SDimitry Andric 
823706b4fc4SDimitry Andric   Promoted = DAG.getNode(NewOpc, dl, NVT, Promoted,
824044eb2f6SDimitry Andric                          DAG.getValueType(VT.getScalarType()));
825706b4fc4SDimitry Andric   Promoted = DAG.getNode(ISD::TRUNCATE, dl, VT, Promoted);
826706b4fc4SDimitry Andric   Results.push_back(Promoted);
827706b4fc4SDimitry Andric   if (IsStrict)
828706b4fc4SDimitry Andric     Results.push_back(Chain);
829044eb2f6SDimitry Andric }
83063faed5bSDimitry Andric 
ExpandLoad(SDNode * N)831706b4fc4SDimitry Andric std::pair<SDValue, SDValue> VectorLegalizer::ExpandLoad(SDNode *N) {
832706b4fc4SDimitry Andric   LoadSDNode *LD = cast<LoadSDNode>(N);
833cfca06d7SDimitry Andric   return TLI.scalarizeVectorLoad(LD, DAG);
83463faed5bSDimitry Andric }
83563faed5bSDimitry Andric 
ExpandStore(SDNode * N)836706b4fc4SDimitry Andric SDValue VectorLegalizer::ExpandStore(SDNode *N) {
837706b4fc4SDimitry Andric   StoreSDNode *ST = cast<StoreSDNode>(N);
83801095a5dSDimitry Andric   SDValue TF = TLI.scalarizeVectorStore(ST, DAG);
83963faed5bSDimitry Andric   return TF;
84063faed5bSDimitry Andric }
84163faed5bSDimitry Andric 
Expand(SDNode * Node,SmallVectorImpl<SDValue> & Results)842706b4fc4SDimitry Andric void VectorLegalizer::Expand(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
843706b4fc4SDimitry Andric   switch (Node->getOpcode()) {
84477fc4c14SDimitry Andric   case ISD::LOAD: {
84577fc4c14SDimitry Andric     std::pair<SDValue, SDValue> Tmp = ExpandLoad(Node);
84677fc4c14SDimitry Andric     Results.push_back(Tmp.first);
84777fc4c14SDimitry Andric     Results.push_back(Tmp.second);
84877fc4c14SDimitry Andric     return;
84977fc4c14SDimitry Andric   }
85077fc4c14SDimitry Andric   case ISD::STORE:
85177fc4c14SDimitry Andric     Results.push_back(ExpandStore(Node));
85277fc4c14SDimitry Andric     return;
853706b4fc4SDimitry Andric   case ISD::MERGE_VALUES:
854706b4fc4SDimitry Andric     for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i)
855706b4fc4SDimitry Andric       Results.push_back(Node->getOperand(i));
856706b4fc4SDimitry Andric     return;
8575ca98fd9SDimitry Andric   case ISD::SIGN_EXTEND_INREG:
858706b4fc4SDimitry Andric     Results.push_back(ExpandSEXTINREG(Node));
859706b4fc4SDimitry Andric     return;
8605ca98fd9SDimitry Andric   case ISD::ANY_EXTEND_VECTOR_INREG:
861706b4fc4SDimitry Andric     Results.push_back(ExpandANY_EXTEND_VECTOR_INREG(Node));
862706b4fc4SDimitry Andric     return;
8635ca98fd9SDimitry Andric   case ISD::SIGN_EXTEND_VECTOR_INREG:
864706b4fc4SDimitry Andric     Results.push_back(ExpandSIGN_EXTEND_VECTOR_INREG(Node));
865706b4fc4SDimitry Andric     return;
8665ca98fd9SDimitry Andric   case ISD::ZERO_EXTEND_VECTOR_INREG:
867706b4fc4SDimitry Andric     Results.push_back(ExpandZERO_EXTEND_VECTOR_INREG(Node));
868706b4fc4SDimitry Andric     return;
8695ca98fd9SDimitry Andric   case ISD::BSWAP:
870706b4fc4SDimitry Andric     Results.push_back(ExpandBSWAP(Node));
871706b4fc4SDimitry Andric     return;
872e3b55780SDimitry Andric   case ISD::VP_BSWAP:
873e3b55780SDimitry Andric     Results.push_back(TLI.expandVPBSWAP(Node, DAG));
874e3b55780SDimitry Andric     return;
8755ca98fd9SDimitry Andric   case ISD::VSELECT:
876706b4fc4SDimitry Andric     Results.push_back(ExpandVSELECT(Node));
877706b4fc4SDimitry Andric     return;
8786f8fc217SDimitry Andric   case ISD::VP_SELECT:
8796f8fc217SDimitry Andric     Results.push_back(ExpandVP_SELECT(Node));
8806f8fc217SDimitry Andric     return;
881e3b55780SDimitry Andric   case ISD::VP_SREM:
882e3b55780SDimitry Andric   case ISD::VP_UREM:
883e3b55780SDimitry Andric     if (SDValue Expanded = ExpandVP_REM(Node)) {
884e3b55780SDimitry Andric       Results.push_back(Expanded);
885e3b55780SDimitry Andric       return;
886e3b55780SDimitry Andric     }
887e3b55780SDimitry Andric     break;
8885ca98fd9SDimitry Andric   case ISD::SELECT:
889706b4fc4SDimitry Andric     Results.push_back(ExpandSELECT(Node));
890706b4fc4SDimitry Andric     return;
8914b4fe385SDimitry Andric   case ISD::SELECT_CC: {
8924b4fe385SDimitry Andric     if (Node->getValueType(0).isScalableVector()) {
8934b4fe385SDimitry Andric       EVT CondVT = TLI.getSetCCResultType(
8944b4fe385SDimitry Andric           DAG.getDataLayout(), *DAG.getContext(), Node->getValueType(0));
8954b4fe385SDimitry Andric       SDValue SetCC =
8964b4fe385SDimitry Andric           DAG.getNode(ISD::SETCC, SDLoc(Node), CondVT, Node->getOperand(0),
8974b4fe385SDimitry Andric                       Node->getOperand(1), Node->getOperand(4));
8984b4fe385SDimitry Andric       Results.push_back(DAG.getSelect(SDLoc(Node), Node->getValueType(0), SetCC,
8994b4fe385SDimitry Andric                                       Node->getOperand(2),
9004b4fe385SDimitry Andric                                       Node->getOperand(3)));
9014b4fe385SDimitry Andric       return;
9024b4fe385SDimitry Andric     }
9034b4fe385SDimitry Andric     break;
9044b4fe385SDimitry Andric   }
905d8e91e46SDimitry Andric   case ISD::FP_TO_UINT:
906706b4fc4SDimitry Andric     ExpandFP_TO_UINT(Node, Results);
907706b4fc4SDimitry Andric     return;
9085ca98fd9SDimitry Andric   case ISD::UINT_TO_FP:
909706b4fc4SDimitry Andric     ExpandUINT_TO_FLOAT(Node, Results);
910706b4fc4SDimitry Andric     return;
9115ca98fd9SDimitry Andric   case ISD::FNEG:
912706b4fc4SDimitry Andric     Results.push_back(ExpandFNEG(Node));
913706b4fc4SDimitry Andric     return;
91471d5a254SDimitry Andric   case ISD::FSUB:
915706b4fc4SDimitry Andric     ExpandFSUB(Node, Results);
916706b4fc4SDimitry Andric     return;
9175ca98fd9SDimitry Andric   case ISD::SETCC:
918145449b1SDimitry Andric   case ISD::VP_SETCC:
919344a3780SDimitry Andric     ExpandSETCC(Node, Results);
920706b4fc4SDimitry Andric     return;
921d8e91e46SDimitry Andric   case ISD::ABS:
922c0981da4SDimitry Andric     if (SDValue Expanded = TLI.expandABS(Node, DAG)) {
923c0981da4SDimitry Andric       Results.push_back(Expanded);
924706b4fc4SDimitry Andric       return;
925706b4fc4SDimitry Andric     }
926706b4fc4SDimitry Andric     break;
9277fa27ce4SDimitry Andric   case ISD::ABDS:
9287fa27ce4SDimitry Andric   case ISD::ABDU:
9297fa27ce4SDimitry Andric     if (SDValue Expanded = TLI.expandABD(Node, DAG)) {
9307fa27ce4SDimitry Andric       Results.push_back(Expanded);
9317fa27ce4SDimitry Andric       return;
9327fa27ce4SDimitry Andric     }
9337fa27ce4SDimitry Andric     break;
934ac9a064cSDimitry Andric   case ISD::AVGCEILS:
935ac9a064cSDimitry Andric   case ISD::AVGCEILU:
936ac9a064cSDimitry Andric   case ISD::AVGFLOORS:
937ac9a064cSDimitry Andric   case ISD::AVGFLOORU:
938ac9a064cSDimitry Andric     if (SDValue Expanded = TLI.expandAVG(Node, DAG)) {
939ac9a064cSDimitry Andric       Results.push_back(Expanded);
940ac9a064cSDimitry Andric       return;
941ac9a064cSDimitry Andric     }
942ac9a064cSDimitry Andric     break;
943dd58ef01SDimitry Andric   case ISD::BITREVERSE:
944706b4fc4SDimitry Andric     ExpandBITREVERSE(Node, Results);
945706b4fc4SDimitry Andric     return;
946e3b55780SDimitry Andric   case ISD::VP_BITREVERSE:
947e3b55780SDimitry Andric     if (SDValue Expanded = TLI.expandVPBITREVERSE(Node, DAG)) {
948e3b55780SDimitry Andric       Results.push_back(Expanded);
949e3b55780SDimitry Andric       return;
950e3b55780SDimitry Andric     }
951e3b55780SDimitry Andric     break;
952d8e91e46SDimitry Andric   case ISD::CTPOP:
953c0981da4SDimitry Andric     if (SDValue Expanded = TLI.expandCTPOP(Node, DAG)) {
954c0981da4SDimitry Andric       Results.push_back(Expanded);
955706b4fc4SDimitry Andric       return;
956706b4fc4SDimitry Andric     }
957706b4fc4SDimitry Andric     break;
958e3b55780SDimitry Andric   case ISD::VP_CTPOP:
959e3b55780SDimitry Andric     if (SDValue Expanded = TLI.expandVPCTPOP(Node, DAG)) {
960e3b55780SDimitry Andric       Results.push_back(Expanded);
961e3b55780SDimitry Andric       return;
962e3b55780SDimitry Andric     }
963e3b55780SDimitry Andric     break;
964b915e9e0SDimitry Andric   case ISD::CTLZ:
965dd58ef01SDimitry Andric   case ISD::CTLZ_ZERO_UNDEF:
966c0981da4SDimitry Andric     if (SDValue Expanded = TLI.expandCTLZ(Node, DAG)) {
967c0981da4SDimitry Andric       Results.push_back(Expanded);
968706b4fc4SDimitry Andric       return;
969706b4fc4SDimitry Andric     }
970706b4fc4SDimitry Andric     break;
971e3b55780SDimitry Andric   case ISD::VP_CTLZ:
972e3b55780SDimitry Andric   case ISD::VP_CTLZ_ZERO_UNDEF:
973e3b55780SDimitry Andric     if (SDValue Expanded = TLI.expandVPCTLZ(Node, DAG)) {
974e3b55780SDimitry Andric       Results.push_back(Expanded);
975e3b55780SDimitry Andric       return;
976e3b55780SDimitry Andric     }
977e3b55780SDimitry Andric     break;
978d8e91e46SDimitry Andric   case ISD::CTTZ:
979dd58ef01SDimitry Andric   case ISD::CTTZ_ZERO_UNDEF:
980c0981da4SDimitry Andric     if (SDValue Expanded = TLI.expandCTTZ(Node, DAG)) {
981c0981da4SDimitry Andric       Results.push_back(Expanded);
982706b4fc4SDimitry Andric       return;
983706b4fc4SDimitry Andric     }
984706b4fc4SDimitry Andric     break;
985e3b55780SDimitry Andric   case ISD::VP_CTTZ:
986e3b55780SDimitry Andric   case ISD::VP_CTTZ_ZERO_UNDEF:
987e3b55780SDimitry Andric     if (SDValue Expanded = TLI.expandVPCTTZ(Node, DAG)) {
988e3b55780SDimitry Andric       Results.push_back(Expanded);
989e3b55780SDimitry Andric       return;
990e3b55780SDimitry Andric     }
991e3b55780SDimitry Andric     break;
992d8e91e46SDimitry Andric   case ISD::FSHL:
993e3b55780SDimitry Andric   case ISD::VP_FSHL:
994d8e91e46SDimitry Andric   case ISD::FSHR:
995e3b55780SDimitry Andric   case ISD::VP_FSHR:
99677fc4c14SDimitry Andric     if (SDValue Expanded = TLI.expandFunnelShift(Node, DAG)) {
99777fc4c14SDimitry Andric       Results.push_back(Expanded);
998706b4fc4SDimitry Andric       return;
999706b4fc4SDimitry Andric     }
1000706b4fc4SDimitry Andric     break;
1001d8e91e46SDimitry Andric   case ISD::ROTL:
1002d8e91e46SDimitry Andric   case ISD::ROTR:
100377fc4c14SDimitry Andric     if (SDValue Expanded = TLI.expandROT(Node, false /*AllowVectorOps*/, DAG)) {
100477fc4c14SDimitry Andric       Results.push_back(Expanded);
1005706b4fc4SDimitry Andric       return;
1006706b4fc4SDimitry Andric     }
1007706b4fc4SDimitry Andric     break;
1008d8e91e46SDimitry Andric   case ISD::FMINNUM:
1009d8e91e46SDimitry Andric   case ISD::FMAXNUM:
1010706b4fc4SDimitry Andric     if (SDValue Expanded = TLI.expandFMINNUM_FMAXNUM(Node, DAG)) {
1011706b4fc4SDimitry Andric       Results.push_back(Expanded);
1012706b4fc4SDimitry Andric       return;
1013706b4fc4SDimitry Andric     }
1014706b4fc4SDimitry Andric     break;
1015ac9a064cSDimitry Andric   case ISD::FMINIMUM:
1016ac9a064cSDimitry Andric   case ISD::FMAXIMUM:
1017ac9a064cSDimitry Andric     Results.push_back(TLI.expandFMINIMUM_FMAXIMUM(Node, DAG));
1018ac9a064cSDimitry Andric     return;
1019b60736ecSDimitry Andric   case ISD::SMIN:
1020b60736ecSDimitry Andric   case ISD::SMAX:
1021b60736ecSDimitry Andric   case ISD::UMIN:
1022b60736ecSDimitry Andric   case ISD::UMAX:
1023b60736ecSDimitry Andric     if (SDValue Expanded = TLI.expandIntMINMAX(Node, DAG)) {
1024b60736ecSDimitry Andric       Results.push_back(Expanded);
1025b60736ecSDimitry Andric       return;
1026b60736ecSDimitry Andric     }
1027b60736ecSDimitry Andric     break;
1028e6d15924SDimitry Andric   case ISD::UADDO:
1029e6d15924SDimitry Andric   case ISD::USUBO:
1030706b4fc4SDimitry Andric     ExpandUADDSUBO(Node, Results);
1031706b4fc4SDimitry Andric     return;
1032e6d15924SDimitry Andric   case ISD::SADDO:
1033e6d15924SDimitry Andric   case ISD::SSUBO:
1034706b4fc4SDimitry Andric     ExpandSADDSUBO(Node, Results);
1035706b4fc4SDimitry Andric     return;
1036e6d15924SDimitry Andric   case ISD::UMULO:
1037e6d15924SDimitry Andric   case ISD::SMULO:
1038706b4fc4SDimitry Andric     ExpandMULO(Node, Results);
1039706b4fc4SDimitry Andric     return;
1040d8e91e46SDimitry Andric   case ISD::USUBSAT:
1041d8e91e46SDimitry Andric   case ISD::SSUBSAT:
1042d8e91e46SDimitry Andric   case ISD::UADDSAT:
1043d8e91e46SDimitry Andric   case ISD::SADDSAT:
1044706b4fc4SDimitry Andric     if (SDValue Expanded = TLI.expandAddSubSat(Node, DAG)) {
1045706b4fc4SDimitry Andric       Results.push_back(Expanded);
1046706b4fc4SDimitry Andric       return;
1047706b4fc4SDimitry Andric     }
1048706b4fc4SDimitry Andric     break;
1049e3b55780SDimitry Andric   case ISD::USHLSAT:
1050e3b55780SDimitry Andric   case ISD::SSHLSAT:
1051e3b55780SDimitry Andric     if (SDValue Expanded = TLI.expandShlSat(Node, DAG)) {
1052e3b55780SDimitry Andric       Results.push_back(Expanded);
1053e3b55780SDimitry Andric       return;
1054e3b55780SDimitry Andric     }
1055e3b55780SDimitry Andric     break;
10564b4fe385SDimitry Andric   case ISD::FP_TO_SINT_SAT:
10574b4fe385SDimitry Andric   case ISD::FP_TO_UINT_SAT:
10584b4fe385SDimitry Andric     // Expand the fpsosisat if it is scalable to prevent it from unrolling below.
10594b4fe385SDimitry Andric     if (Node->getValueType(0).isScalableVector()) {
10604b4fe385SDimitry Andric       if (SDValue Expanded = TLI.expandFP_TO_INT_SAT(Node, DAG)) {
10614b4fe385SDimitry Andric         Results.push_back(Expanded);
10624b4fe385SDimitry Andric         return;
10634b4fe385SDimitry Andric       }
10644b4fe385SDimitry Andric     }
10654b4fe385SDimitry Andric     break;
1066e6d15924SDimitry Andric   case ISD::SMULFIX:
1067e6d15924SDimitry Andric   case ISD::UMULFIX:
1068706b4fc4SDimitry Andric     if (SDValue Expanded = TLI.expandFixedPointMul(Node, DAG)) {
1069706b4fc4SDimitry Andric       Results.push_back(Expanded);
1070706b4fc4SDimitry Andric       return;
1071706b4fc4SDimitry Andric     }
1072706b4fc4SDimitry Andric     break;
10731d5ae102SDimitry Andric   case ISD::SMULFIXSAT:
10741d5ae102SDimitry Andric   case ISD::UMULFIXSAT:
10751d5ae102SDimitry Andric     // FIXME: We do not expand SMULFIXSAT/UMULFIXSAT here yet, not sure exactly
10761d5ae102SDimitry Andric     // why. Maybe it results in worse codegen compared to the unroll for some
10771d5ae102SDimitry Andric     // targets? This should probably be investigated. And if we still prefer to
10781d5ae102SDimitry Andric     // unroll an explanation could be helpful.
1079706b4fc4SDimitry Andric     break;
1080706b4fc4SDimitry Andric   case ISD::SDIVFIX:
1081706b4fc4SDimitry Andric   case ISD::UDIVFIX:
1082cfca06d7SDimitry Andric     ExpandFixedPointDiv(Node, Results);
1083706b4fc4SDimitry Andric     return;
1084cfca06d7SDimitry Andric   case ISD::SDIVFIXSAT:
1085cfca06d7SDimitry Andric   case ISD::UDIVFIXSAT:
1086cfca06d7SDimitry Andric     break;
1087cfca06d7SDimitry Andric #define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN)               \
1088706b4fc4SDimitry Andric   case ISD::STRICT_##DAGN:
1089706b4fc4SDimitry Andric #include "llvm/IR/ConstrainedOps.def"
1090706b4fc4SDimitry Andric     ExpandStrictFPOp(Node, Results);
1091706b4fc4SDimitry Andric     return;
1092e6d15924SDimitry Andric   case ISD::VECREDUCE_ADD:
1093e6d15924SDimitry Andric   case ISD::VECREDUCE_MUL:
1094e6d15924SDimitry Andric   case ISD::VECREDUCE_AND:
1095e6d15924SDimitry Andric   case ISD::VECREDUCE_OR:
1096e6d15924SDimitry Andric   case ISD::VECREDUCE_XOR:
1097e6d15924SDimitry Andric   case ISD::VECREDUCE_SMAX:
1098e6d15924SDimitry Andric   case ISD::VECREDUCE_SMIN:
1099e6d15924SDimitry Andric   case ISD::VECREDUCE_UMAX:
1100e6d15924SDimitry Andric   case ISD::VECREDUCE_UMIN:
1101e6d15924SDimitry Andric   case ISD::VECREDUCE_FADD:
1102e6d15924SDimitry Andric   case ISD::VECREDUCE_FMUL:
1103e6d15924SDimitry Andric   case ISD::VECREDUCE_FMAX:
1104e6d15924SDimitry Andric   case ISD::VECREDUCE_FMIN:
11057fa27ce4SDimitry Andric   case ISD::VECREDUCE_FMAXIMUM:
11067fa27ce4SDimitry Andric   case ISD::VECREDUCE_FMINIMUM:
1107706b4fc4SDimitry Andric     Results.push_back(TLI.expandVecReduce(Node, DAG));
1108706b4fc4SDimitry Andric     return;
1109b60736ecSDimitry Andric   case ISD::VECREDUCE_SEQ_FADD:
1110b60736ecSDimitry Andric   case ISD::VECREDUCE_SEQ_FMUL:
1111b60736ecSDimitry Andric     Results.push_back(TLI.expandVecReduceSeq(Node, DAG));
1112b60736ecSDimitry Andric     return;
1113cfca06d7SDimitry Andric   case ISD::SREM:
1114cfca06d7SDimitry Andric   case ISD::UREM:
1115cfca06d7SDimitry Andric     ExpandREM(Node, Results);
1116cfca06d7SDimitry Andric     return;
11176f8fc217SDimitry Andric   case ISD::VP_MERGE:
11186f8fc217SDimitry Andric     Results.push_back(ExpandVP_MERGE(Node));
11196f8fc217SDimitry Andric     return;
1120ac9a064cSDimitry Andric   case ISD::FREM:
1121ac9a064cSDimitry Andric     if (tryExpandVecMathCall(Node, RTLIB::REM_F32, RTLIB::REM_F64,
1122ac9a064cSDimitry Andric                              RTLIB::REM_F80, RTLIB::REM_F128,
1123ac9a064cSDimitry Andric                              RTLIB::REM_PPCF128, Results))
1124ac9a064cSDimitry Andric       return;
1125ac9a064cSDimitry Andric 
1126ac9a064cSDimitry Andric     break;
1127ac9a064cSDimitry Andric   case ISD::VECTOR_COMPRESS:
1128ac9a064cSDimitry Andric     Results.push_back(TLI.expandVECTOR_COMPRESS(Node, DAG));
1129ac9a064cSDimitry Andric     return;
11305ca98fd9SDimitry Andric   }
11315ca98fd9SDimitry Andric 
11327fa27ce4SDimitry Andric   SDValue Unrolled = DAG.UnrollVectorOp(Node);
1133ac9a064cSDimitry Andric   if (Node->getNumValues() == 1) {
1134ac9a064cSDimitry Andric     Results.push_back(Unrolled);
1135ac9a064cSDimitry Andric   } else {
1136ac9a064cSDimitry Andric     assert(Node->getNumValues() == Unrolled->getNumValues() &&
1137ac9a064cSDimitry Andric       "VectorLegalizer Expand returned wrong number of results!");
11387fa27ce4SDimitry Andric     for (unsigned I = 0, E = Unrolled->getNumValues(); I != E; ++I)
11397fa27ce4SDimitry Andric       Results.push_back(Unrolled.getValue(I));
1140706b4fc4SDimitry Andric   }
1141ac9a064cSDimitry Andric }
1142706b4fc4SDimitry Andric 
ExpandSELECT(SDNode * Node)1143706b4fc4SDimitry Andric SDValue VectorLegalizer::ExpandSELECT(SDNode *Node) {
1144522600a2SDimitry Andric   // Lower a select instruction where the condition is a scalar and the
1145522600a2SDimitry Andric   // operands are vectors. Lower this select to VSELECT and implement it
1146522600a2SDimitry Andric   // using XOR AND OR. The selector bit is broadcasted.
1147706b4fc4SDimitry Andric   EVT VT = Node->getValueType(0);
1148706b4fc4SDimitry Andric   SDLoc DL(Node);
1149522600a2SDimitry Andric 
1150706b4fc4SDimitry Andric   SDValue Mask = Node->getOperand(0);
1151706b4fc4SDimitry Andric   SDValue Op1 = Node->getOperand(1);
1152706b4fc4SDimitry Andric   SDValue Op2 = Node->getOperand(2);
1153522600a2SDimitry Andric 
1154522600a2SDimitry Andric   assert(VT.isVector() && !Mask.getValueType().isVector()
1155522600a2SDimitry Andric          && Op1.getValueType() == Op2.getValueType() && "Invalid type");
1156522600a2SDimitry Andric 
1157522600a2SDimitry Andric   // If we can't even use the basic vector operations of
1158522600a2SDimitry Andric   // AND,OR,XOR, we will have to scalarize the op.
1159522600a2SDimitry Andric   // Notice that the operation may be 'promoted' which means that it is
1160522600a2SDimitry Andric   // 'bitcasted' to another type which is handled.
1161344a3780SDimitry Andric   // Also, we need to be able to construct a splat vector using either
1162344a3780SDimitry Andric   // BUILD_VECTOR or SPLAT_VECTOR.
1163344a3780SDimitry Andric   // FIXME: Should we also permit fixed-length SPLAT_VECTOR as a fallback to
1164344a3780SDimitry Andric   // BUILD_VECTOR?
1165522600a2SDimitry Andric   if (TLI.getOperationAction(ISD::AND, VT) == TargetLowering::Expand ||
1166522600a2SDimitry Andric       TLI.getOperationAction(ISD::XOR, VT) == TargetLowering::Expand ||
1167522600a2SDimitry Andric       TLI.getOperationAction(ISD::OR, VT) == TargetLowering::Expand ||
1168344a3780SDimitry Andric       TLI.getOperationAction(VT.isFixedLengthVector() ? ISD::BUILD_VECTOR
1169344a3780SDimitry Andric                                                       : ISD::SPLAT_VECTOR,
1170344a3780SDimitry Andric                              VT) == TargetLowering::Expand)
1171706b4fc4SDimitry Andric     return DAG.UnrollVectorOp(Node);
1172522600a2SDimitry Andric 
1173522600a2SDimitry Andric   // Generate a mask operand.
1174f8af5cf6SDimitry Andric   EVT MaskTy = VT.changeVectorElementTypeToInteger();
1175522600a2SDimitry Andric 
1176522600a2SDimitry Andric   // What is the size of each element in the vector mask.
1177522600a2SDimitry Andric   EVT BitTy = MaskTy.getScalarType();
1178522600a2SDimitry Andric 
1179c0981da4SDimitry Andric   Mask = DAG.getSelect(DL, BitTy, Mask, DAG.getAllOnesConstant(DL, BitTy),
11805a5ac124SDimitry Andric                        DAG.getConstant(0, DL, BitTy));
1181522600a2SDimitry Andric 
1182344a3780SDimitry Andric   // Broadcast the mask so that the entire vector is all one or all zero.
1183e3b55780SDimitry Andric   Mask = DAG.getSplat(MaskTy, DL, Mask);
1184522600a2SDimitry Andric 
1185522600a2SDimitry Andric   // Bitcast the operands to be the same type as the mask.
1186522600a2SDimitry Andric   // This is needed when we select between FP types because
1187522600a2SDimitry Andric   // the mask is a vector of integers.
1188522600a2SDimitry Andric   Op1 = DAG.getNode(ISD::BITCAST, DL, MaskTy, Op1);
1189522600a2SDimitry Andric   Op2 = DAG.getNode(ISD::BITCAST, DL, MaskTy, Op2);
1190522600a2SDimitry Andric 
1191c0981da4SDimitry Andric   SDValue NotMask = DAG.getNOT(DL, Mask, MaskTy);
1192522600a2SDimitry Andric 
1193522600a2SDimitry Andric   Op1 = DAG.getNode(ISD::AND, DL, MaskTy, Op1, Mask);
1194522600a2SDimitry Andric   Op2 = DAG.getNode(ISD::AND, DL, MaskTy, Op2, NotMask);
1195522600a2SDimitry Andric   SDValue Val = DAG.getNode(ISD::OR, DL, MaskTy, Op1, Op2);
1196706b4fc4SDimitry Andric   return DAG.getNode(ISD::BITCAST, DL, Node->getValueType(0), Val);
1197522600a2SDimitry Andric }
1198522600a2SDimitry Andric 
ExpandSEXTINREG(SDNode * Node)1199706b4fc4SDimitry Andric SDValue VectorLegalizer::ExpandSEXTINREG(SDNode *Node) {
1200706b4fc4SDimitry Andric   EVT VT = Node->getValueType(0);
12014a16efa3SDimitry Andric 
12024a16efa3SDimitry Andric   // Make sure that the SRA and SHL instructions are available.
12034a16efa3SDimitry Andric   if (TLI.getOperationAction(ISD::SRA, VT) == TargetLowering::Expand ||
12044a16efa3SDimitry Andric       TLI.getOperationAction(ISD::SHL, VT) == TargetLowering::Expand)
1205706b4fc4SDimitry Andric     return DAG.UnrollVectorOp(Node);
12064a16efa3SDimitry Andric 
1207706b4fc4SDimitry Andric   SDLoc DL(Node);
1208706b4fc4SDimitry Andric   EVT OrigTy = cast<VTSDNode>(Node->getOperand(1))->getVT();
12094a16efa3SDimitry Andric 
1210b915e9e0SDimitry Andric   unsigned BW = VT.getScalarSizeInBits();
1211b915e9e0SDimitry Andric   unsigned OrigBW = OrigTy.getScalarSizeInBits();
12125a5ac124SDimitry Andric   SDValue ShiftSz = DAG.getConstant(BW - OrigBW, DL, VT);
12134a16efa3SDimitry Andric 
1214706b4fc4SDimitry Andric   SDValue Op = DAG.getNode(ISD::SHL, DL, VT, Node->getOperand(0), ShiftSz);
12154a16efa3SDimitry Andric   return DAG.getNode(ISD::SRA, DL, VT, Op, ShiftSz);
12164a16efa3SDimitry Andric }
12174a16efa3SDimitry Andric 
12185ca98fd9SDimitry Andric // Generically expand a vector anyext in register to a shuffle of the relevant
12195ca98fd9SDimitry Andric // lanes into the appropriate locations, with other lanes left undef.
ExpandANY_EXTEND_VECTOR_INREG(SDNode * Node)1220706b4fc4SDimitry Andric SDValue VectorLegalizer::ExpandANY_EXTEND_VECTOR_INREG(SDNode *Node) {
1221706b4fc4SDimitry Andric   SDLoc DL(Node);
1222706b4fc4SDimitry Andric   EVT VT = Node->getValueType(0);
12235ca98fd9SDimitry Andric   int NumElements = VT.getVectorNumElements();
1224706b4fc4SDimitry Andric   SDValue Src = Node->getOperand(0);
12255ca98fd9SDimitry Andric   EVT SrcVT = Src.getValueType();
12265ca98fd9SDimitry Andric   int NumSrcElements = SrcVT.getVectorNumElements();
12275ca98fd9SDimitry Andric 
1228e6d15924SDimitry Andric   // *_EXTEND_VECTOR_INREG SrcVT can be smaller than VT - so insert the vector
1229e6d15924SDimitry Andric   // into a larger vector type.
1230e6d15924SDimitry Andric   if (SrcVT.bitsLE(VT)) {
1231e6d15924SDimitry Andric     assert((VT.getSizeInBits() % SrcVT.getScalarSizeInBits()) == 0 &&
1232e6d15924SDimitry Andric            "ANY_EXTEND_VECTOR_INREG vector size mismatch");
1233e6d15924SDimitry Andric     NumSrcElements = VT.getSizeInBits() / SrcVT.getScalarSizeInBits();
1234e6d15924SDimitry Andric     SrcVT = EVT::getVectorVT(*DAG.getContext(), SrcVT.getScalarType(),
1235e6d15924SDimitry Andric                              NumSrcElements);
1236cfca06d7SDimitry Andric     Src = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, SrcVT, DAG.getUNDEF(SrcVT),
1237cfca06d7SDimitry Andric                       Src, DAG.getVectorIdxConstant(0, DL));
1238e6d15924SDimitry Andric   }
1239e6d15924SDimitry Andric 
12405ca98fd9SDimitry Andric   // Build a base mask of undef shuffles.
12415ca98fd9SDimitry Andric   SmallVector<int, 16> ShuffleMask;
12425ca98fd9SDimitry Andric   ShuffleMask.resize(NumSrcElements, -1);
12435ca98fd9SDimitry Andric 
12445ca98fd9SDimitry Andric   // Place the extended lanes into the correct locations.
12455ca98fd9SDimitry Andric   int ExtLaneScale = NumSrcElements / NumElements;
1246ee8648bdSDimitry Andric   int EndianOffset = DAG.getDataLayout().isBigEndian() ? ExtLaneScale - 1 : 0;
12475ca98fd9SDimitry Andric   for (int i = 0; i < NumElements; ++i)
12485ca98fd9SDimitry Andric     ShuffleMask[i * ExtLaneScale + EndianOffset] = i;
12495ca98fd9SDimitry Andric 
12505ca98fd9SDimitry Andric   return DAG.getNode(
12515ca98fd9SDimitry Andric       ISD::BITCAST, DL, VT,
12525ca98fd9SDimitry Andric       DAG.getVectorShuffle(SrcVT, DL, Src, DAG.getUNDEF(SrcVT), ShuffleMask));
12535ca98fd9SDimitry Andric }
12545ca98fd9SDimitry Andric 
ExpandSIGN_EXTEND_VECTOR_INREG(SDNode * Node)1255706b4fc4SDimitry Andric SDValue VectorLegalizer::ExpandSIGN_EXTEND_VECTOR_INREG(SDNode *Node) {
1256706b4fc4SDimitry Andric   SDLoc DL(Node);
1257706b4fc4SDimitry Andric   EVT VT = Node->getValueType(0);
1258706b4fc4SDimitry Andric   SDValue Src = Node->getOperand(0);
12595ca98fd9SDimitry Andric   EVT SrcVT = Src.getValueType();
12605ca98fd9SDimitry Andric 
12615ca98fd9SDimitry Andric   // First build an any-extend node which can be legalized above when we
12625ca98fd9SDimitry Andric   // recurse through it.
1263706b4fc4SDimitry Andric   SDValue Op = DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, VT, Src);
12645ca98fd9SDimitry Andric 
12655ca98fd9SDimitry Andric   // Now we need sign extend. Do this by shifting the elements. Even if these
12665ca98fd9SDimitry Andric   // aren't legal operations, they have a better chance of being legalized
12675ca98fd9SDimitry Andric   // without full scalarization than the sign extension does.
1268b915e9e0SDimitry Andric   unsigned EltWidth = VT.getScalarSizeInBits();
1269b915e9e0SDimitry Andric   unsigned SrcEltWidth = SrcVT.getScalarSizeInBits();
12705a5ac124SDimitry Andric   SDValue ShiftAmount = DAG.getConstant(EltWidth - SrcEltWidth, DL, VT);
12715ca98fd9SDimitry Andric   return DAG.getNode(ISD::SRA, DL, VT,
12725ca98fd9SDimitry Andric                      DAG.getNode(ISD::SHL, DL, VT, Op, ShiftAmount),
12735ca98fd9SDimitry Andric                      ShiftAmount);
12745ca98fd9SDimitry Andric }
12755ca98fd9SDimitry Andric 
12765ca98fd9SDimitry Andric // Generically expand a vector zext in register to a shuffle of the relevant
12775ca98fd9SDimitry Andric // lanes into the appropriate locations, a blend of zero into the high bits,
12785ca98fd9SDimitry Andric // and a bitcast to the wider element type.
ExpandZERO_EXTEND_VECTOR_INREG(SDNode * Node)1279706b4fc4SDimitry Andric SDValue VectorLegalizer::ExpandZERO_EXTEND_VECTOR_INREG(SDNode *Node) {
1280706b4fc4SDimitry Andric   SDLoc DL(Node);
1281706b4fc4SDimitry Andric   EVT VT = Node->getValueType(0);
12825ca98fd9SDimitry Andric   int NumElements = VT.getVectorNumElements();
1283706b4fc4SDimitry Andric   SDValue Src = Node->getOperand(0);
12845ca98fd9SDimitry Andric   EVT SrcVT = Src.getValueType();
12855ca98fd9SDimitry Andric   int NumSrcElements = SrcVT.getVectorNumElements();
12865ca98fd9SDimitry Andric 
1287e6d15924SDimitry Andric   // *_EXTEND_VECTOR_INREG SrcVT can be smaller than VT - so insert the vector
1288e6d15924SDimitry Andric   // into a larger vector type.
1289e6d15924SDimitry Andric   if (SrcVT.bitsLE(VT)) {
1290e6d15924SDimitry Andric     assert((VT.getSizeInBits() % SrcVT.getScalarSizeInBits()) == 0 &&
1291e6d15924SDimitry Andric            "ZERO_EXTEND_VECTOR_INREG vector size mismatch");
1292e6d15924SDimitry Andric     NumSrcElements = VT.getSizeInBits() / SrcVT.getScalarSizeInBits();
1293e6d15924SDimitry Andric     SrcVT = EVT::getVectorVT(*DAG.getContext(), SrcVT.getScalarType(),
1294e6d15924SDimitry Andric                              NumSrcElements);
1295cfca06d7SDimitry Andric     Src = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, SrcVT, DAG.getUNDEF(SrcVT),
1296cfca06d7SDimitry Andric                       Src, DAG.getVectorIdxConstant(0, DL));
1297e6d15924SDimitry Andric   }
1298e6d15924SDimitry Andric 
12995ca98fd9SDimitry Andric   // Build up a zero vector to blend into this one.
130001095a5dSDimitry Andric   SDValue Zero = DAG.getConstant(0, DL, SrcVT);
13015ca98fd9SDimitry Andric 
13025ca98fd9SDimitry Andric   // Shuffle the incoming lanes into the correct position, and pull all other
13035ca98fd9SDimitry Andric   // lanes from the zero vector.
1304145449b1SDimitry Andric   auto ShuffleMask = llvm::to_vector<16>(llvm::seq<int>(0, NumSrcElements));
13055ca98fd9SDimitry Andric 
13065ca98fd9SDimitry Andric   int ExtLaneScale = NumSrcElements / NumElements;
1307ee8648bdSDimitry Andric   int EndianOffset = DAG.getDataLayout().isBigEndian() ? ExtLaneScale - 1 : 0;
13085ca98fd9SDimitry Andric   for (int i = 0; i < NumElements; ++i)
13095ca98fd9SDimitry Andric     ShuffleMask[i * ExtLaneScale + EndianOffset] = NumSrcElements + i;
13105ca98fd9SDimitry Andric 
13115ca98fd9SDimitry Andric   return DAG.getNode(ISD::BITCAST, DL, VT,
13125ca98fd9SDimitry Andric                      DAG.getVectorShuffle(SrcVT, DL, Zero, Src, ShuffleMask));
13135ca98fd9SDimitry Andric }
13145ca98fd9SDimitry Andric 
createBSWAPShuffleMask(EVT VT,SmallVectorImpl<int> & ShuffleMask)131501095a5dSDimitry Andric static void createBSWAPShuffleMask(EVT VT, SmallVectorImpl<int> &ShuffleMask) {
131601095a5dSDimitry Andric   int ScalarSizeInBytes = VT.getScalarSizeInBits() / 8;
131701095a5dSDimitry Andric   for (int I = 0, E = VT.getVectorNumElements(); I != E; ++I)
131801095a5dSDimitry Andric     for (int J = ScalarSizeInBytes - 1; J >= 0; --J)
131901095a5dSDimitry Andric       ShuffleMask.push_back((I * ScalarSizeInBytes) + J);
132001095a5dSDimitry Andric }
132101095a5dSDimitry Andric 
ExpandBSWAP(SDNode * Node)1322706b4fc4SDimitry Andric SDValue VectorLegalizer::ExpandBSWAP(SDNode *Node) {
1323706b4fc4SDimitry Andric   EVT VT = Node->getValueType(0);
13245ca98fd9SDimitry Andric 
1325c0981da4SDimitry Andric   // Scalable vectors can't use shuffle expansion.
1326c0981da4SDimitry Andric   if (VT.isScalableVector())
1327c0981da4SDimitry Andric     return TLI.expandBSWAP(Node, DAG);
1328c0981da4SDimitry Andric 
13295ca98fd9SDimitry Andric   // Generate a byte wise shuffle mask for the BSWAP.
13305ca98fd9SDimitry Andric   SmallVector<int, 16> ShuffleMask;
133101095a5dSDimitry Andric   createBSWAPShuffleMask(VT, ShuffleMask);
13325ca98fd9SDimitry Andric   EVT ByteVT = EVT::getVectorVT(*DAG.getContext(), MVT::i8, ShuffleMask.size());
13335ca98fd9SDimitry Andric 
13345ca98fd9SDimitry Andric   // Only emit a shuffle if the mask is legal.
1335c0981da4SDimitry Andric   if (TLI.isShuffleMaskLegal(ShuffleMask, ByteVT)) {
1336706b4fc4SDimitry Andric     SDLoc DL(Node);
1337706b4fc4SDimitry Andric     SDValue Op = DAG.getNode(ISD::BITCAST, DL, ByteVT, Node->getOperand(0));
133801095a5dSDimitry Andric     Op = DAG.getVectorShuffle(ByteVT, DL, Op, DAG.getUNDEF(ByteVT), ShuffleMask);
13395ca98fd9SDimitry Andric     return DAG.getNode(ISD::BITCAST, DL, VT, Op);
13405ca98fd9SDimitry Andric   }
13415ca98fd9SDimitry Andric 
1342c0981da4SDimitry Andric   // If we have the appropriate vector bit operations, it is better to use them
1343c0981da4SDimitry Andric   // than unrolling and expanding each component.
1344c0981da4SDimitry Andric   if (TLI.isOperationLegalOrCustom(ISD::SHL, VT) &&
1345c0981da4SDimitry Andric       TLI.isOperationLegalOrCustom(ISD::SRL, VT) &&
1346c0981da4SDimitry Andric       TLI.isOperationLegalOrCustomOrPromote(ISD::AND, VT) &&
1347c0981da4SDimitry Andric       TLI.isOperationLegalOrCustomOrPromote(ISD::OR, VT))
1348c0981da4SDimitry Andric     return TLI.expandBSWAP(Node, DAG);
1349c0981da4SDimitry Andric 
1350c0981da4SDimitry Andric   // Otherwise unroll.
1351c0981da4SDimitry Andric   return DAG.UnrollVectorOp(Node);
1352c0981da4SDimitry Andric }
1353c0981da4SDimitry Andric 
ExpandBITREVERSE(SDNode * Node,SmallVectorImpl<SDValue> & Results)1354706b4fc4SDimitry Andric void VectorLegalizer::ExpandBITREVERSE(SDNode *Node,
1355706b4fc4SDimitry Andric                                        SmallVectorImpl<SDValue> &Results) {
1356706b4fc4SDimitry Andric   EVT VT = Node->getValueType(0);
1357dd58ef01SDimitry Andric 
1358c0981da4SDimitry Andric   // We can't unroll or use shuffles for scalable vectors.
1359c0981da4SDimitry Andric   if (VT.isScalableVector()) {
1360c0981da4SDimitry Andric     Results.push_back(TLI.expandBITREVERSE(Node, DAG));
1361c0981da4SDimitry Andric     return;
1362c0981da4SDimitry Andric   }
1363c0981da4SDimitry Andric 
1364dd58ef01SDimitry Andric   // If we have the scalar operation, it's probably cheaper to unroll it.
1365706b4fc4SDimitry Andric   if (TLI.isOperationLegalOrCustom(ISD::BITREVERSE, VT.getScalarType())) {
1366706b4fc4SDimitry Andric     SDValue Tmp = DAG.UnrollVectorOp(Node);
1367706b4fc4SDimitry Andric     Results.push_back(Tmp);
1368706b4fc4SDimitry Andric     return;
1369706b4fc4SDimitry Andric   }
1370dd58ef01SDimitry Andric 
137101095a5dSDimitry Andric   // If the vector element width is a whole number of bytes, test if its legal
137201095a5dSDimitry Andric   // to BSWAP shuffle the bytes and then perform the BITREVERSE on the byte
137301095a5dSDimitry Andric   // vector. This greatly reduces the number of bit shifts necessary.
137401095a5dSDimitry Andric   unsigned ScalarSizeInBits = VT.getScalarSizeInBits();
137501095a5dSDimitry Andric   if (ScalarSizeInBits > 8 && (ScalarSizeInBits % 8) == 0) {
137601095a5dSDimitry Andric     SmallVector<int, 16> BSWAPMask;
137701095a5dSDimitry Andric     createBSWAPShuffleMask(VT, BSWAPMask);
137801095a5dSDimitry Andric 
137901095a5dSDimitry Andric     EVT ByteVT = EVT::getVectorVT(*DAG.getContext(), MVT::i8, BSWAPMask.size());
138001095a5dSDimitry Andric     if (TLI.isShuffleMaskLegal(BSWAPMask, ByteVT) &&
138101095a5dSDimitry Andric         (TLI.isOperationLegalOrCustom(ISD::BITREVERSE, ByteVT) ||
138201095a5dSDimitry Andric          (TLI.isOperationLegalOrCustom(ISD::SHL, ByteVT) &&
138301095a5dSDimitry Andric           TLI.isOperationLegalOrCustom(ISD::SRL, ByteVT) &&
138401095a5dSDimitry Andric           TLI.isOperationLegalOrCustomOrPromote(ISD::AND, ByteVT) &&
138501095a5dSDimitry Andric           TLI.isOperationLegalOrCustomOrPromote(ISD::OR, ByteVT)))) {
1386706b4fc4SDimitry Andric       SDLoc DL(Node);
1387706b4fc4SDimitry Andric       SDValue Op = DAG.getNode(ISD::BITCAST, DL, ByteVT, Node->getOperand(0));
138801095a5dSDimitry Andric       Op = DAG.getVectorShuffle(ByteVT, DL, Op, DAG.getUNDEF(ByteVT),
138901095a5dSDimitry Andric                                 BSWAPMask);
139001095a5dSDimitry Andric       Op = DAG.getNode(ISD::BITREVERSE, DL, ByteVT, Op);
1391706b4fc4SDimitry Andric       Op = DAG.getNode(ISD::BITCAST, DL, VT, Op);
1392706b4fc4SDimitry Andric       Results.push_back(Op);
1393706b4fc4SDimitry Andric       return;
139401095a5dSDimitry Andric     }
139501095a5dSDimitry Andric   }
139601095a5dSDimitry Andric 
1397dd58ef01SDimitry Andric   // If we have the appropriate vector bit operations, it is better to use them
1398dd58ef01SDimitry Andric   // than unrolling and expanding each component.
1399706b4fc4SDimitry Andric   if (TLI.isOperationLegalOrCustom(ISD::SHL, VT) &&
1400706b4fc4SDimitry Andric       TLI.isOperationLegalOrCustom(ISD::SRL, VT) &&
1401706b4fc4SDimitry Andric       TLI.isOperationLegalOrCustomOrPromote(ISD::AND, VT) &&
1402c0981da4SDimitry Andric       TLI.isOperationLegalOrCustomOrPromote(ISD::OR, VT)) {
1403c0981da4SDimitry Andric     Results.push_back(TLI.expandBITREVERSE(Node, DAG));
1404706b4fc4SDimitry Andric     return;
1405c0981da4SDimitry Andric   }
1406706b4fc4SDimitry Andric 
1407706b4fc4SDimitry Andric   // Otherwise unroll.
1408706b4fc4SDimitry Andric   SDValue Tmp = DAG.UnrollVectorOp(Node);
1409706b4fc4SDimitry Andric   Results.push_back(Tmp);
1410dd58ef01SDimitry Andric }
1411dd58ef01SDimitry Andric 
ExpandVSELECT(SDNode * Node)1412706b4fc4SDimitry Andric SDValue VectorLegalizer::ExpandVSELECT(SDNode *Node) {
141330815c53SDimitry Andric   // Implement VSELECT in terms of XOR, AND, OR
141430815c53SDimitry Andric   // on platforms which do not support blend natively.
1415706b4fc4SDimitry Andric   SDLoc DL(Node);
141630815c53SDimitry Andric 
1417706b4fc4SDimitry Andric   SDValue Mask = Node->getOperand(0);
1418706b4fc4SDimitry Andric   SDValue Op1 = Node->getOperand(1);
1419706b4fc4SDimitry Andric   SDValue Op2 = Node->getOperand(2);
142030815c53SDimitry Andric 
1421f8af5cf6SDimitry Andric   EVT VT = Mask.getValueType();
1422f8af5cf6SDimitry Andric 
142330815c53SDimitry Andric   // If we can't even use the basic vector operations of
142430815c53SDimitry Andric   // AND,OR,XOR, we will have to scalarize the op.
142563faed5bSDimitry Andric   // Notice that the operation may be 'promoted' which means that it is
142663faed5bSDimitry Andric   // 'bitcasted' to another type which is handled.
142763faed5bSDimitry Andric   if (TLI.getOperationAction(ISD::AND, VT) == TargetLowering::Expand ||
142863faed5bSDimitry Andric       TLI.getOperationAction(ISD::XOR, VT) == TargetLowering::Expand ||
1429344a3780SDimitry Andric       TLI.getOperationAction(ISD::OR, VT) == TargetLowering::Expand)
1430344a3780SDimitry Andric     return DAG.UnrollVectorOp(Node);
1431344a3780SDimitry Andric 
1432344a3780SDimitry Andric   // This operation also isn't safe with AND, OR, XOR when the boolean type is
1433344a3780SDimitry Andric   // 0/1 and the select operands aren't also booleans, as we need an all-ones
1434344a3780SDimitry Andric   // vector constant to mask with.
1435344a3780SDimitry Andric   // FIXME: Sign extend 1 to all ones if that's legal on the target.
1436344a3780SDimitry Andric   auto BoolContents = TLI.getBooleanContents(Op1.getValueType());
1437344a3780SDimitry Andric   if (BoolContents != TargetLowering::ZeroOrNegativeOneBooleanContent &&
1438344a3780SDimitry Andric       !(BoolContents == TargetLowering::ZeroOrOneBooleanContent &&
1439344a3780SDimitry Andric         Op1.getValueType().getVectorElementType() == MVT::i1))
1440706b4fc4SDimitry Andric     return DAG.UnrollVectorOp(Node);
144130815c53SDimitry Andric 
1442f8af5cf6SDimitry Andric   // If the mask and the type are different sizes, unroll the vector op. This
1443f8af5cf6SDimitry Andric   // can occur when getSetCCResultType returns something that is different in
1444f8af5cf6SDimitry Andric   // size from the operand types. For example, v4i8 = select v4i32, v4i8, v4i8.
1445b915e9e0SDimitry Andric   if (VT.getSizeInBits() != Op1.getValueSizeInBits())
1446706b4fc4SDimitry Andric     return DAG.UnrollVectorOp(Node);
1447f8af5cf6SDimitry Andric 
144830815c53SDimitry Andric   // Bitcast the operands to be the same type as the mask.
144930815c53SDimitry Andric   // This is needed when we select between FP types because
145030815c53SDimitry Andric   // the mask is a vector of integers.
145130815c53SDimitry Andric   Op1 = DAG.getNode(ISD::BITCAST, DL, VT, Op1);
145230815c53SDimitry Andric   Op2 = DAG.getNode(ISD::BITCAST, DL, VT, Op2);
145330815c53SDimitry Andric 
1454c0981da4SDimitry Andric   SDValue NotMask = DAG.getNOT(DL, Mask, VT);
145530815c53SDimitry Andric 
145630815c53SDimitry Andric   Op1 = DAG.getNode(ISD::AND, DL, VT, Op1, Mask);
145730815c53SDimitry Andric   Op2 = DAG.getNode(ISD::AND, DL, VT, Op2, NotMask);
1458b61ab53cSDimitry Andric   SDValue Val = DAG.getNode(ISD::OR, DL, VT, Op1, Op2);
1459706b4fc4SDimitry Andric   return DAG.getNode(ISD::BITCAST, DL, Node->getValueType(0), Val);
146030815c53SDimitry Andric }
146130815c53SDimitry Andric 
ExpandVP_SELECT(SDNode * Node)14626f8fc217SDimitry Andric SDValue VectorLegalizer::ExpandVP_SELECT(SDNode *Node) {
14636f8fc217SDimitry Andric   // Implement VP_SELECT in terms of VP_XOR, VP_AND and VP_OR on platforms which
14646f8fc217SDimitry Andric   // do not support it natively.
14656f8fc217SDimitry Andric   SDLoc DL(Node);
14666f8fc217SDimitry Andric 
14676f8fc217SDimitry Andric   SDValue Mask = Node->getOperand(0);
14686f8fc217SDimitry Andric   SDValue Op1 = Node->getOperand(1);
14696f8fc217SDimitry Andric   SDValue Op2 = Node->getOperand(2);
14706f8fc217SDimitry Andric   SDValue EVL = Node->getOperand(3);
14716f8fc217SDimitry Andric 
14726f8fc217SDimitry Andric   EVT VT = Mask.getValueType();
14736f8fc217SDimitry Andric 
14746f8fc217SDimitry Andric   // If we can't even use the basic vector operations of
14756f8fc217SDimitry Andric   // VP_AND,VP_OR,VP_XOR, we will have to scalarize the op.
14766f8fc217SDimitry Andric   if (TLI.getOperationAction(ISD::VP_AND, VT) == TargetLowering::Expand ||
14776f8fc217SDimitry Andric       TLI.getOperationAction(ISD::VP_XOR, VT) == TargetLowering::Expand ||
14786f8fc217SDimitry Andric       TLI.getOperationAction(ISD::VP_OR, VT) == TargetLowering::Expand)
14796f8fc217SDimitry Andric     return DAG.UnrollVectorOp(Node);
14806f8fc217SDimitry Andric 
14816f8fc217SDimitry Andric   // This operation also isn't safe when the operands aren't also booleans.
14826f8fc217SDimitry Andric   if (Op1.getValueType().getVectorElementType() != MVT::i1)
14836f8fc217SDimitry Andric     return DAG.UnrollVectorOp(Node);
14846f8fc217SDimitry Andric 
14856f8fc217SDimitry Andric   SDValue Ones = DAG.getAllOnesConstant(DL, VT);
14867fa27ce4SDimitry Andric   SDValue NotMask = DAG.getNode(ISD::VP_XOR, DL, VT, Mask, Ones, Ones, EVL);
14876f8fc217SDimitry Andric 
14887fa27ce4SDimitry Andric   Op1 = DAG.getNode(ISD::VP_AND, DL, VT, Op1, Mask, Ones, EVL);
14897fa27ce4SDimitry Andric   Op2 = DAG.getNode(ISD::VP_AND, DL, VT, Op2, NotMask, Ones, EVL);
14907fa27ce4SDimitry Andric   return DAG.getNode(ISD::VP_OR, DL, VT, Op1, Op2, Ones, EVL);
14916f8fc217SDimitry Andric }
14926f8fc217SDimitry Andric 
ExpandVP_MERGE(SDNode * Node)14936f8fc217SDimitry Andric SDValue VectorLegalizer::ExpandVP_MERGE(SDNode *Node) {
14946f8fc217SDimitry Andric   // Implement VP_MERGE in terms of VSELECT. Construct a mask where vector
14956f8fc217SDimitry Andric   // indices less than the EVL/pivot are true. Combine that with the original
14966f8fc217SDimitry Andric   // mask for a full-length mask. Use a full-length VSELECT to select between
14976f8fc217SDimitry Andric   // the true and false values.
14986f8fc217SDimitry Andric   SDLoc DL(Node);
14996f8fc217SDimitry Andric 
15006f8fc217SDimitry Andric   SDValue Mask = Node->getOperand(0);
15016f8fc217SDimitry Andric   SDValue Op1 = Node->getOperand(1);
15026f8fc217SDimitry Andric   SDValue Op2 = Node->getOperand(2);
15036f8fc217SDimitry Andric   SDValue EVL = Node->getOperand(3);
15046f8fc217SDimitry Andric 
15056f8fc217SDimitry Andric   EVT MaskVT = Mask.getValueType();
15066f8fc217SDimitry Andric   bool IsFixedLen = MaskVT.isFixedLengthVector();
15076f8fc217SDimitry Andric 
15086f8fc217SDimitry Andric   EVT EVLVecVT = EVT::getVectorVT(*DAG.getContext(), EVL.getValueType(),
15096f8fc217SDimitry Andric                                   MaskVT.getVectorElementCount());
15106f8fc217SDimitry Andric 
15116f8fc217SDimitry Andric   // If we can't construct the EVL mask efficiently, it's better to unroll.
15126f8fc217SDimitry Andric   if ((IsFixedLen &&
15136f8fc217SDimitry Andric        !TLI.isOperationLegalOrCustom(ISD::BUILD_VECTOR, EVLVecVT)) ||
15146f8fc217SDimitry Andric       (!IsFixedLen &&
15156f8fc217SDimitry Andric        (!TLI.isOperationLegalOrCustom(ISD::STEP_VECTOR, EVLVecVT) ||
15166f8fc217SDimitry Andric         !TLI.isOperationLegalOrCustom(ISD::SPLAT_VECTOR, EVLVecVT))))
15176f8fc217SDimitry Andric     return DAG.UnrollVectorOp(Node);
15186f8fc217SDimitry Andric 
15196f8fc217SDimitry Andric   // If using a SETCC would result in a different type than the mask type,
15206f8fc217SDimitry Andric   // unroll.
15216f8fc217SDimitry Andric   if (TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(),
15226f8fc217SDimitry Andric                              EVLVecVT) != MaskVT)
15236f8fc217SDimitry Andric     return DAG.UnrollVectorOp(Node);
15246f8fc217SDimitry Andric 
15256f8fc217SDimitry Andric   SDValue StepVec = DAG.getStepVector(DL, EVLVecVT);
1526e3b55780SDimitry Andric   SDValue SplatEVL = DAG.getSplat(EVLVecVT, DL, EVL);
15276f8fc217SDimitry Andric   SDValue EVLMask =
15286f8fc217SDimitry Andric       DAG.getSetCC(DL, MaskVT, StepVec, SplatEVL, ISD::CondCode::SETULT);
15296f8fc217SDimitry Andric 
15306f8fc217SDimitry Andric   SDValue FullMask = DAG.getNode(ISD::AND, DL, MaskVT, Mask, EVLMask);
15316f8fc217SDimitry Andric   return DAG.getSelect(DL, Node->getValueType(0), FullMask, Op1, Op2);
15326f8fc217SDimitry Andric }
15336f8fc217SDimitry Andric 
ExpandVP_REM(SDNode * Node)1534e3b55780SDimitry Andric SDValue VectorLegalizer::ExpandVP_REM(SDNode *Node) {
1535e3b55780SDimitry Andric   // Implement VP_SREM/UREM in terms of VP_SDIV/VP_UDIV, VP_MUL, VP_SUB.
1536e3b55780SDimitry Andric   EVT VT = Node->getValueType(0);
1537e3b55780SDimitry Andric 
1538e3b55780SDimitry Andric   unsigned DivOpc = Node->getOpcode() == ISD::VP_SREM ? ISD::VP_SDIV : ISD::VP_UDIV;
1539e3b55780SDimitry Andric 
1540e3b55780SDimitry Andric   if (!TLI.isOperationLegalOrCustom(DivOpc, VT) ||
1541e3b55780SDimitry Andric       !TLI.isOperationLegalOrCustom(ISD::VP_MUL, VT) ||
1542e3b55780SDimitry Andric       !TLI.isOperationLegalOrCustom(ISD::VP_SUB, VT))
1543e3b55780SDimitry Andric     return SDValue();
1544e3b55780SDimitry Andric 
1545e3b55780SDimitry Andric   SDLoc DL(Node);
1546e3b55780SDimitry Andric 
1547e3b55780SDimitry Andric   SDValue Dividend = Node->getOperand(0);
1548e3b55780SDimitry Andric   SDValue Divisor = Node->getOperand(1);
1549e3b55780SDimitry Andric   SDValue Mask = Node->getOperand(2);
1550e3b55780SDimitry Andric   SDValue EVL = Node->getOperand(3);
1551e3b55780SDimitry Andric 
1552e3b55780SDimitry Andric   // X % Y -> X-X/Y*Y
1553e3b55780SDimitry Andric   SDValue Div = DAG.getNode(DivOpc, DL, VT, Dividend, Divisor, Mask, EVL);
1554e3b55780SDimitry Andric   SDValue Mul = DAG.getNode(ISD::VP_MUL, DL, VT, Divisor, Div, Mask, EVL);
1555e3b55780SDimitry Andric   return DAG.getNode(ISD::VP_SUB, DL, VT, Dividend, Mul, Mask, EVL);
1556e3b55780SDimitry Andric }
1557e3b55780SDimitry Andric 
ExpandFP_TO_UINT(SDNode * Node,SmallVectorImpl<SDValue> & Results)1558706b4fc4SDimitry Andric void VectorLegalizer::ExpandFP_TO_UINT(SDNode *Node,
1559706b4fc4SDimitry Andric                                        SmallVectorImpl<SDValue> &Results) {
1560d8e91e46SDimitry Andric   // Attempt to expand using TargetLowering.
15611d5ae102SDimitry Andric   SDValue Result, Chain;
1562706b4fc4SDimitry Andric   if (TLI.expandFP_TO_UINT(Node, Result, Chain, DAG)) {
1563706b4fc4SDimitry Andric     Results.push_back(Result);
1564706b4fc4SDimitry Andric     if (Node->isStrictFPOpcode())
1565706b4fc4SDimitry Andric       Results.push_back(Chain);
1566706b4fc4SDimitry Andric     return;
15671d5ae102SDimitry Andric   }
1568d8e91e46SDimitry Andric 
1569d8e91e46SDimitry Andric   // Otherwise go ahead and unroll.
1570706b4fc4SDimitry Andric   if (Node->isStrictFPOpcode()) {
1571706b4fc4SDimitry Andric     UnrollStrictFPOp(Node, Results);
1572706b4fc4SDimitry Andric     return;
1573d8e91e46SDimitry Andric   }
1574d8e91e46SDimitry Andric 
1575706b4fc4SDimitry Andric   Results.push_back(DAG.UnrollVectorOp(Node));
1576706b4fc4SDimitry Andric }
1577706b4fc4SDimitry Andric 
ExpandUINT_TO_FLOAT(SDNode * Node,SmallVectorImpl<SDValue> & Results)1578706b4fc4SDimitry Andric void VectorLegalizer::ExpandUINT_TO_FLOAT(SDNode *Node,
1579706b4fc4SDimitry Andric                                           SmallVectorImpl<SDValue> &Results) {
1580706b4fc4SDimitry Andric   bool IsStrict = Node->isStrictFPOpcode();
1581706b4fc4SDimitry Andric   unsigned OpNo = IsStrict ? 1 : 0;
1582706b4fc4SDimitry Andric   SDValue Src = Node->getOperand(OpNo);
1583706b4fc4SDimitry Andric   EVT VT = Src.getValueType();
1584706b4fc4SDimitry Andric   SDLoc DL(Node);
15856b943ff3SDimitry Andric 
1586d8e91e46SDimitry Andric   // Attempt to expand using TargetLowering.
1587d8e91e46SDimitry Andric   SDValue Result;
1588706b4fc4SDimitry Andric   SDValue Chain;
1589706b4fc4SDimitry Andric   if (TLI.expandUINT_TO_FP(Node, Result, Chain, DAG)) {
1590706b4fc4SDimitry Andric     Results.push_back(Result);
1591706b4fc4SDimitry Andric     if (IsStrict)
1592706b4fc4SDimitry Andric       Results.push_back(Chain);
1593706b4fc4SDimitry Andric     return;
1594706b4fc4SDimitry Andric   }
1595d8e91e46SDimitry Andric 
15966b943ff3SDimitry Andric   // Make sure that the SINT_TO_FP and SRL instructions are available.
1597706b4fc4SDimitry Andric   if (((!IsStrict && TLI.getOperationAction(ISD::SINT_TO_FP, VT) ==
1598706b4fc4SDimitry Andric                          TargetLowering::Expand) ||
1599706b4fc4SDimitry Andric        (IsStrict && TLI.getOperationAction(ISD::STRICT_SINT_TO_FP, VT) ==
1600706b4fc4SDimitry Andric                         TargetLowering::Expand)) ||
1601706b4fc4SDimitry Andric       TLI.getOperationAction(ISD::SRL, VT) == TargetLowering::Expand) {
1602706b4fc4SDimitry Andric     if (IsStrict) {
1603706b4fc4SDimitry Andric       UnrollStrictFPOp(Node, Results);
1604706b4fc4SDimitry Andric       return;
1605706b4fc4SDimitry Andric     }
1606706b4fc4SDimitry Andric 
1607706b4fc4SDimitry Andric     Results.push_back(DAG.UnrollVectorOp(Node));
1608706b4fc4SDimitry Andric     return;
1609706b4fc4SDimitry Andric   }
16106b943ff3SDimitry Andric 
1611b915e9e0SDimitry Andric   unsigned BW = VT.getScalarSizeInBits();
1612b915e9e0SDimitry Andric   assert((BW == 64 || BW == 32) &&
16136b943ff3SDimitry Andric          "Elements in vector-UINT_TO_FP must be 32 or 64 bits wide");
16146b943ff3SDimitry Andric 
16155a5ac124SDimitry Andric   SDValue HalfWord = DAG.getConstant(BW / 2, DL, VT);
16166b943ff3SDimitry Andric 
16176b943ff3SDimitry Andric   // Constants to clear the upper part of the word.
16186b943ff3SDimitry Andric   // Notice that we can also use SHL+SHR, but using a constant is slightly
16196b943ff3SDimitry Andric   // faster on x86.
1620b915e9e0SDimitry Andric   uint64_t HWMask = (BW == 64) ? 0x00000000FFFFFFFF : 0x0000FFFF;
16215a5ac124SDimitry Andric   SDValue HalfWordMask = DAG.getConstant(HWMask, DL, VT);
16226b943ff3SDimitry Andric 
16236b943ff3SDimitry Andric   // Two to the power of half-word-size.
1624706b4fc4SDimitry Andric   SDValue TWOHW =
1625706b4fc4SDimitry Andric       DAG.getConstantFP(1ULL << (BW / 2), DL, Node->getValueType(0));
16266b943ff3SDimitry Andric 
16276b943ff3SDimitry Andric   // Clear upper part of LO, lower HI
1628706b4fc4SDimitry Andric   SDValue HI = DAG.getNode(ISD::SRL, DL, VT, Src, HalfWord);
1629706b4fc4SDimitry Andric   SDValue LO = DAG.getNode(ISD::AND, DL, VT, Src, HalfWordMask);
1630706b4fc4SDimitry Andric 
1631706b4fc4SDimitry Andric   if (IsStrict) {
1632706b4fc4SDimitry Andric     // Convert hi and lo to floats
1633706b4fc4SDimitry Andric     // Convert the hi part back to the upper values
1634706b4fc4SDimitry Andric     // TODO: Can any fast-math-flags be set on these nodes?
1635706b4fc4SDimitry Andric     SDValue fHI = DAG.getNode(ISD::STRICT_SINT_TO_FP, DL,
1636706b4fc4SDimitry Andric                               {Node->getValueType(0), MVT::Other},
1637706b4fc4SDimitry Andric                               {Node->getOperand(0), HI});
1638706b4fc4SDimitry Andric     fHI = DAG.getNode(ISD::STRICT_FMUL, DL, {Node->getValueType(0), MVT::Other},
1639706b4fc4SDimitry Andric                       {fHI.getValue(1), fHI, TWOHW});
1640706b4fc4SDimitry Andric     SDValue fLO = DAG.getNode(ISD::STRICT_SINT_TO_FP, DL,
1641706b4fc4SDimitry Andric                               {Node->getValueType(0), MVT::Other},
1642706b4fc4SDimitry Andric                               {Node->getOperand(0), LO});
1643706b4fc4SDimitry Andric 
1644706b4fc4SDimitry Andric     SDValue TF = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, fHI.getValue(1),
1645706b4fc4SDimitry Andric                              fLO.getValue(1));
1646706b4fc4SDimitry Andric 
1647706b4fc4SDimitry Andric     // Add the two halves
1648706b4fc4SDimitry Andric     SDValue Result =
1649706b4fc4SDimitry Andric         DAG.getNode(ISD::STRICT_FADD, DL, {Node->getValueType(0), MVT::Other},
1650706b4fc4SDimitry Andric                     {TF, fHI, fLO});
1651706b4fc4SDimitry Andric 
1652706b4fc4SDimitry Andric     Results.push_back(Result);
1653706b4fc4SDimitry Andric     Results.push_back(Result.getValue(1));
1654706b4fc4SDimitry Andric     return;
1655706b4fc4SDimitry Andric   }
16566b943ff3SDimitry Andric 
16576b943ff3SDimitry Andric   // Convert hi and lo to floats
16586b943ff3SDimitry Andric   // Convert the hi part back to the upper values
1659dd58ef01SDimitry Andric   // TODO: Can any fast-math-flags be set on these nodes?
1660706b4fc4SDimitry Andric   SDValue fHI = DAG.getNode(ISD::SINT_TO_FP, DL, Node->getValueType(0), HI);
1661706b4fc4SDimitry Andric   fHI = DAG.getNode(ISD::FMUL, DL, Node->getValueType(0), fHI, TWOHW);
1662706b4fc4SDimitry Andric   SDValue fLO = DAG.getNode(ISD::SINT_TO_FP, DL, Node->getValueType(0), LO);
16636b943ff3SDimitry Andric 
16646b943ff3SDimitry Andric   // Add the two halves
1665706b4fc4SDimitry Andric   Results.push_back(
1666706b4fc4SDimitry Andric       DAG.getNode(ISD::FADD, DL, Node->getValueType(0), fHI, fLO));
16676b943ff3SDimitry Andric }
16686b943ff3SDimitry Andric 
ExpandFNEG(SDNode * Node)1669706b4fc4SDimitry Andric SDValue VectorLegalizer::ExpandFNEG(SDNode *Node) {
1670706b4fc4SDimitry Andric   if (TLI.isOperationLegalOrCustom(ISD::FSUB, Node->getValueType(0))) {
1671706b4fc4SDimitry Andric     SDLoc DL(Node);
1672706b4fc4SDimitry Andric     SDValue Zero = DAG.getConstantFP(-0.0, DL, Node->getValueType(0));
1673dd58ef01SDimitry Andric     // TODO: If FNEG had fast-math-flags, they'd get propagated to this FSUB.
1674706b4fc4SDimitry Andric     return DAG.getNode(ISD::FSUB, DL, Node->getValueType(0), Zero,
1675706b4fc4SDimitry Andric                        Node->getOperand(0));
1676009b1c42SEd Schouten   }
1677706b4fc4SDimitry Andric   return DAG.UnrollVectorOp(Node);
1678009b1c42SEd Schouten }
1679009b1c42SEd Schouten 
ExpandFSUB(SDNode * Node,SmallVectorImpl<SDValue> & Results)1680706b4fc4SDimitry Andric void VectorLegalizer::ExpandFSUB(SDNode *Node,
1681706b4fc4SDimitry Andric                                  SmallVectorImpl<SDValue> &Results) {
168271d5a254SDimitry Andric   // For floating-point values, (a-b) is the same as a+(-b). If FNEG is legal,
168371d5a254SDimitry Andric   // we can defer this to operation legalization where it will be lowered as
168471d5a254SDimitry Andric   // a+(-b).
1685706b4fc4SDimitry Andric   EVT VT = Node->getValueType(0);
168671d5a254SDimitry Andric   if (TLI.isOperationLegalOrCustom(ISD::FNEG, VT) &&
168771d5a254SDimitry Andric       TLI.isOperationLegalOrCustom(ISD::FADD, VT))
1688706b4fc4SDimitry Andric     return; // Defer to LegalizeDAG
168971d5a254SDimitry Andric 
1690706b4fc4SDimitry Andric   SDValue Tmp = DAG.UnrollVectorOp(Node);
1691706b4fc4SDimitry Andric   Results.push_back(Tmp);
169271d5a254SDimitry Andric }
169371d5a254SDimitry Andric 
ExpandSETCC(SDNode * Node,SmallVectorImpl<SDValue> & Results)1694344a3780SDimitry Andric void VectorLegalizer::ExpandSETCC(SDNode *Node,
1695344a3780SDimitry Andric                                   SmallVectorImpl<SDValue> &Results) {
1696344a3780SDimitry Andric   bool NeedInvert = false;
1697145449b1SDimitry Andric   bool IsVP = Node->getOpcode() == ISD::VP_SETCC;
16987fa27ce4SDimitry Andric   bool IsStrict = Node->getOpcode() == ISD::STRICT_FSETCC ||
16997fa27ce4SDimitry Andric                   Node->getOpcode() == ISD::STRICT_FSETCCS;
17007fa27ce4SDimitry Andric   bool IsSignaling = Node->getOpcode() == ISD::STRICT_FSETCCS;
17017fa27ce4SDimitry Andric   unsigned Offset = IsStrict ? 1 : 0;
17027fa27ce4SDimitry Andric 
17037fa27ce4SDimitry Andric   SDValue Chain = IsStrict ? Node->getOperand(0) : SDValue();
17047fa27ce4SDimitry Andric   SDValue LHS = Node->getOperand(0 + Offset);
17057fa27ce4SDimitry Andric   SDValue RHS = Node->getOperand(1 + Offset);
17067fa27ce4SDimitry Andric   SDValue CC = Node->getOperand(2 + Offset);
17077fa27ce4SDimitry Andric 
17087fa27ce4SDimitry Andric   MVT OpVT = LHS.getSimpleValueType();
17097fa27ce4SDimitry Andric   ISD::CondCode CCCode = cast<CondCodeSDNode>(CC)->get();
1710344a3780SDimitry Andric 
1711344a3780SDimitry Andric   if (TLI.getCondCodeAction(CCCode, OpVT) != TargetLowering::Expand) {
17127fa27ce4SDimitry Andric     if (IsStrict) {
17137fa27ce4SDimitry Andric       UnrollStrictFPOp(Node, Results);
17147fa27ce4SDimitry Andric       return;
17157fa27ce4SDimitry Andric     }
1716344a3780SDimitry Andric     Results.push_back(UnrollVSETCC(Node));
1717344a3780SDimitry Andric     return;
1718344a3780SDimitry Andric   }
1719344a3780SDimitry Andric 
1720145449b1SDimitry Andric   SDValue Mask, EVL;
1721145449b1SDimitry Andric   if (IsVP) {
17227fa27ce4SDimitry Andric     Mask = Node->getOperand(3 + Offset);
17237fa27ce4SDimitry Andric     EVL = Node->getOperand(4 + Offset);
1724145449b1SDimitry Andric   }
1725145449b1SDimitry Andric 
17267fa27ce4SDimitry Andric   SDLoc dl(Node);
1727145449b1SDimitry Andric   bool Legalized =
1728145449b1SDimitry Andric       TLI.LegalizeSetCCCondCode(DAG, Node->getValueType(0), LHS, RHS, CC, Mask,
17297fa27ce4SDimitry Andric                                 EVL, NeedInvert, dl, Chain, IsSignaling);
1730344a3780SDimitry Andric 
1731344a3780SDimitry Andric   if (Legalized) {
1732344a3780SDimitry Andric     // If we expanded the SETCC by swapping LHS and RHS, or by inverting the
1733344a3780SDimitry Andric     // condition code, create a new SETCC node.
1734145449b1SDimitry Andric     if (CC.getNode()) {
17357fa27ce4SDimitry Andric       if (IsStrict) {
17367fa27ce4SDimitry Andric         LHS = DAG.getNode(Node->getOpcode(), dl, Node->getVTList(),
17377fa27ce4SDimitry Andric                           {Chain, LHS, RHS, CC}, Node->getFlags());
17387fa27ce4SDimitry Andric         Chain = LHS.getValue(1);
17397fa27ce4SDimitry Andric       } else if (IsVP) {
1740145449b1SDimitry Andric         LHS = DAG.getNode(ISD::VP_SETCC, dl, Node->getValueType(0),
1741145449b1SDimitry Andric                           {LHS, RHS, CC, Mask, EVL}, Node->getFlags());
17427fa27ce4SDimitry Andric       } else {
17437fa27ce4SDimitry Andric         LHS = DAG.getNode(ISD::SETCC, dl, Node->getValueType(0), LHS, RHS, CC,
17447fa27ce4SDimitry Andric                           Node->getFlags());
17457fa27ce4SDimitry Andric       }
1746145449b1SDimitry Andric     }
1747344a3780SDimitry Andric 
1748344a3780SDimitry Andric     // If we expanded the SETCC by inverting the condition code, then wrap
1749344a3780SDimitry Andric     // the existing SETCC in a NOT to restore the intended condition.
1750145449b1SDimitry Andric     if (NeedInvert) {
1751145449b1SDimitry Andric       if (!IsVP)
1752344a3780SDimitry Andric         LHS = DAG.getLogicalNOT(dl, LHS, LHS->getValueType(0));
1753145449b1SDimitry Andric       else
1754145449b1SDimitry Andric         LHS = DAG.getVPLogicalNOT(dl, LHS, Mask, EVL, LHS->getValueType(0));
1755145449b1SDimitry Andric     }
1756344a3780SDimitry Andric   } else {
17577fa27ce4SDimitry Andric     assert(!IsStrict && "Don't know how to expand for strict nodes.");
17587fa27ce4SDimitry Andric 
1759344a3780SDimitry Andric     // Otherwise, SETCC for the given comparison type must be completely
1760344a3780SDimitry Andric     // illegal; expand it into a SELECT_CC.
1761344a3780SDimitry Andric     EVT VT = Node->getValueType(0);
1762344a3780SDimitry Andric     LHS =
1763344a3780SDimitry Andric         DAG.getNode(ISD::SELECT_CC, dl, VT, LHS, RHS,
1764344a3780SDimitry Andric                     DAG.getBoolConstant(true, dl, VT, LHS.getValueType()),
1765344a3780SDimitry Andric                     DAG.getBoolConstant(false, dl, VT, LHS.getValueType()), CC);
1766344a3780SDimitry Andric     LHS->setFlags(Node->getFlags());
1767344a3780SDimitry Andric   }
1768344a3780SDimitry Andric 
1769344a3780SDimitry Andric   Results.push_back(LHS);
17707fa27ce4SDimitry Andric   if (IsStrict)
17717fa27ce4SDimitry Andric     Results.push_back(Chain);
1772344a3780SDimitry Andric }
1773344a3780SDimitry Andric 
ExpandUADDSUBO(SDNode * Node,SmallVectorImpl<SDValue> & Results)1774706b4fc4SDimitry Andric void VectorLegalizer::ExpandUADDSUBO(SDNode *Node,
1775706b4fc4SDimitry Andric                                      SmallVectorImpl<SDValue> &Results) {
1776e6d15924SDimitry Andric   SDValue Result, Overflow;
1777706b4fc4SDimitry Andric   TLI.expandUADDSUBO(Node, Result, Overflow, DAG);
1778706b4fc4SDimitry Andric   Results.push_back(Result);
1779706b4fc4SDimitry Andric   Results.push_back(Overflow);
1780e6d15924SDimitry Andric }
1781e6d15924SDimitry Andric 
ExpandSADDSUBO(SDNode * Node,SmallVectorImpl<SDValue> & Results)1782706b4fc4SDimitry Andric void VectorLegalizer::ExpandSADDSUBO(SDNode *Node,
1783706b4fc4SDimitry Andric                                      SmallVectorImpl<SDValue> &Results) {
1784e6d15924SDimitry Andric   SDValue Result, Overflow;
1785706b4fc4SDimitry Andric   TLI.expandSADDSUBO(Node, Result, Overflow, DAG);
1786706b4fc4SDimitry Andric   Results.push_back(Result);
1787706b4fc4SDimitry Andric   Results.push_back(Overflow);
1788e6d15924SDimitry Andric }
1789e6d15924SDimitry Andric 
ExpandMULO(SDNode * Node,SmallVectorImpl<SDValue> & Results)1790706b4fc4SDimitry Andric void VectorLegalizer::ExpandMULO(SDNode *Node,
1791706b4fc4SDimitry Andric                                  SmallVectorImpl<SDValue> &Results) {
1792e6d15924SDimitry Andric   SDValue Result, Overflow;
1793706b4fc4SDimitry Andric   if (!TLI.expandMULO(Node, Result, Overflow, DAG))
1794706b4fc4SDimitry Andric     std::tie(Result, Overflow) = DAG.UnrollVectorOverflowOp(Node);
1795e6d15924SDimitry Andric 
1796706b4fc4SDimitry Andric   Results.push_back(Result);
1797706b4fc4SDimitry Andric   Results.push_back(Overflow);
1798e6d15924SDimitry Andric }
1799e6d15924SDimitry Andric 
ExpandFixedPointDiv(SDNode * Node,SmallVectorImpl<SDValue> & Results)1800cfca06d7SDimitry Andric void VectorLegalizer::ExpandFixedPointDiv(SDNode *Node,
1801cfca06d7SDimitry Andric                                           SmallVectorImpl<SDValue> &Results) {
1802706b4fc4SDimitry Andric   SDNode *N = Node;
1803706b4fc4SDimitry Andric   if (SDValue Expanded = TLI.expandFixedPointDiv(N->getOpcode(), SDLoc(N),
1804706b4fc4SDimitry Andric           N->getOperand(0), N->getOperand(1), N->getConstantOperandVal(2), DAG))
1805cfca06d7SDimitry Andric     Results.push_back(Expanded);
1806dd58ef01SDimitry Andric }
1807dd58ef01SDimitry Andric 
ExpandStrictFPOp(SDNode * Node,SmallVectorImpl<SDValue> & Results)1808706b4fc4SDimitry Andric void VectorLegalizer::ExpandStrictFPOp(SDNode *Node,
1809706b4fc4SDimitry Andric                                        SmallVectorImpl<SDValue> &Results) {
1810706b4fc4SDimitry Andric   if (Node->getOpcode() == ISD::STRICT_UINT_TO_FP) {
1811706b4fc4SDimitry Andric     ExpandUINT_TO_FLOAT(Node, Results);
1812706b4fc4SDimitry Andric     return;
1813706b4fc4SDimitry Andric   }
1814706b4fc4SDimitry Andric   if (Node->getOpcode() == ISD::STRICT_FP_TO_UINT) {
1815706b4fc4SDimitry Andric     ExpandFP_TO_UINT(Node, Results);
1816706b4fc4SDimitry Andric     return;
1817e6d15924SDimitry Andric   }
1818e6d15924SDimitry Andric 
18197fa27ce4SDimitry Andric   if (Node->getOpcode() == ISD::STRICT_FSETCC ||
18207fa27ce4SDimitry Andric       Node->getOpcode() == ISD::STRICT_FSETCCS) {
18217fa27ce4SDimitry Andric     ExpandSETCC(Node, Results);
18227fa27ce4SDimitry Andric     return;
18237fa27ce4SDimitry Andric   }
18247fa27ce4SDimitry Andric 
1825706b4fc4SDimitry Andric   UnrollStrictFPOp(Node, Results);
1826706b4fc4SDimitry Andric }
1827706b4fc4SDimitry Andric 
ExpandREM(SDNode * Node,SmallVectorImpl<SDValue> & Results)1828cfca06d7SDimitry Andric void VectorLegalizer::ExpandREM(SDNode *Node,
1829cfca06d7SDimitry Andric                                 SmallVectorImpl<SDValue> &Results) {
1830cfca06d7SDimitry Andric   assert((Node->getOpcode() == ISD::SREM || Node->getOpcode() == ISD::UREM) &&
1831cfca06d7SDimitry Andric          "Expected REM node");
1832cfca06d7SDimitry Andric 
1833cfca06d7SDimitry Andric   SDValue Result;
1834cfca06d7SDimitry Andric   if (!TLI.expandREM(Node, Result, DAG))
1835cfca06d7SDimitry Andric     Result = DAG.UnrollVectorOp(Node);
1836cfca06d7SDimitry Andric   Results.push_back(Result);
1837cfca06d7SDimitry Andric }
1838cfca06d7SDimitry Andric 
1839ac9a064cSDimitry Andric // Try to expand libm nodes into vector math routine calls. Callers provide the
1840ac9a064cSDimitry Andric // LibFunc equivalent of the passed in Node, which is used to lookup mappings
1841ac9a064cSDimitry Andric // within TargetLibraryInfo. The only mappings considered are those where the
1842ac9a064cSDimitry Andric // result and all operands are the same vector type. While predicated nodes are
1843ac9a064cSDimitry Andric // not supported, we will emit calls to masked routines by passing in an all
1844ac9a064cSDimitry Andric // true mask.
tryExpandVecMathCall(SDNode * Node,RTLIB::Libcall LC,SmallVectorImpl<SDValue> & Results)1845ac9a064cSDimitry Andric bool VectorLegalizer::tryExpandVecMathCall(SDNode *Node, RTLIB::Libcall LC,
1846ac9a064cSDimitry Andric                                            SmallVectorImpl<SDValue> &Results) {
1847ac9a064cSDimitry Andric   // Chain must be propagated but currently strict fp operations are down
1848ac9a064cSDimitry Andric   // converted to their none strict counterpart.
1849ac9a064cSDimitry Andric   assert(!Node->isStrictFPOpcode() && "Unexpected strict fp operation!");
1850ac9a064cSDimitry Andric 
1851ac9a064cSDimitry Andric   const char *LCName = TLI.getLibcallName(LC);
1852ac9a064cSDimitry Andric   if (!LCName)
1853ac9a064cSDimitry Andric     return false;
1854ac9a064cSDimitry Andric   LLVM_DEBUG(dbgs() << "Looking for vector variant of " << LCName << "\n");
1855ac9a064cSDimitry Andric 
1856ac9a064cSDimitry Andric   EVT VT = Node->getValueType(0);
1857ac9a064cSDimitry Andric   ElementCount VL = VT.getVectorElementCount();
1858ac9a064cSDimitry Andric 
1859ac9a064cSDimitry Andric   // Lookup a vector function equivalent to the specified libcall. Prefer
1860ac9a064cSDimitry Andric   // unmasked variants but we will generate a mask if need be.
1861ac9a064cSDimitry Andric   const TargetLibraryInfo &TLibInfo = DAG.getLibInfo();
1862ac9a064cSDimitry Andric   const VecDesc *VD = TLibInfo.getVectorMappingInfo(LCName, VL, false);
1863ac9a064cSDimitry Andric   if (!VD)
1864ac9a064cSDimitry Andric     VD = TLibInfo.getVectorMappingInfo(LCName, VL, /*Masked=*/true);
1865ac9a064cSDimitry Andric   if (!VD)
1866ac9a064cSDimitry Andric     return false;
1867ac9a064cSDimitry Andric 
1868ac9a064cSDimitry Andric   LLVMContext *Ctx = DAG.getContext();
1869ac9a064cSDimitry Andric   Type *Ty = VT.getTypeForEVT(*Ctx);
1870ac9a064cSDimitry Andric   Type *ScalarTy = Ty->getScalarType();
1871ac9a064cSDimitry Andric 
1872ac9a064cSDimitry Andric   // Construct a scalar function type based on Node's operands.
1873ac9a064cSDimitry Andric   SmallVector<Type *, 8> ArgTys;
1874ac9a064cSDimitry Andric   for (unsigned i = 0; i < Node->getNumOperands(); ++i) {
1875ac9a064cSDimitry Andric     assert(Node->getOperand(i).getValueType() == VT &&
1876ac9a064cSDimitry Andric            "Expected matching vector types!");
1877ac9a064cSDimitry Andric     ArgTys.push_back(ScalarTy);
1878ac9a064cSDimitry Andric   }
1879ac9a064cSDimitry Andric   FunctionType *ScalarFTy = FunctionType::get(ScalarTy, ArgTys, false);
1880ac9a064cSDimitry Andric 
1881ac9a064cSDimitry Andric   // Generate call information for the vector function.
1882ac9a064cSDimitry Andric   const std::string MangledName = VD->getVectorFunctionABIVariantString();
1883ac9a064cSDimitry Andric   auto OptVFInfo = VFABI::tryDemangleForVFABI(MangledName, ScalarFTy);
1884ac9a064cSDimitry Andric   if (!OptVFInfo)
1885ac9a064cSDimitry Andric     return false;
1886ac9a064cSDimitry Andric 
1887ac9a064cSDimitry Andric   LLVM_DEBUG(dbgs() << "Found vector variant " << VD->getVectorFnName()
1888ac9a064cSDimitry Andric                     << "\n");
1889ac9a064cSDimitry Andric 
1890ac9a064cSDimitry Andric   // Sanity check just in case OptVFInfo has unexpected parameters.
1891ac9a064cSDimitry Andric   if (OptVFInfo->Shape.Parameters.size() !=
1892ac9a064cSDimitry Andric       Node->getNumOperands() + VD->isMasked())
1893ac9a064cSDimitry Andric     return false;
1894ac9a064cSDimitry Andric 
1895ac9a064cSDimitry Andric   // Collect vector call operands.
1896ac9a064cSDimitry Andric 
1897ac9a064cSDimitry Andric   SDLoc DL(Node);
1898ac9a064cSDimitry Andric   TargetLowering::ArgListTy Args;
1899ac9a064cSDimitry Andric   TargetLowering::ArgListEntry Entry;
1900ac9a064cSDimitry Andric   Entry.IsSExt = false;
1901ac9a064cSDimitry Andric   Entry.IsZExt = false;
1902ac9a064cSDimitry Andric 
1903ac9a064cSDimitry Andric   unsigned OpNum = 0;
1904ac9a064cSDimitry Andric   for (auto &VFParam : OptVFInfo->Shape.Parameters) {
1905ac9a064cSDimitry Andric     if (VFParam.ParamKind == VFParamKind::GlobalPredicate) {
1906ac9a064cSDimitry Andric       EVT MaskVT = TLI.getSetCCResultType(DAG.getDataLayout(), *Ctx, VT);
1907ac9a064cSDimitry Andric       Entry.Node = DAG.getBoolConstant(true, DL, MaskVT, VT);
1908ac9a064cSDimitry Andric       Entry.Ty = MaskVT.getTypeForEVT(*Ctx);
1909ac9a064cSDimitry Andric       Args.push_back(Entry);
1910ac9a064cSDimitry Andric       continue;
1911ac9a064cSDimitry Andric     }
1912ac9a064cSDimitry Andric 
1913ac9a064cSDimitry Andric     // Only vector operands are supported.
1914ac9a064cSDimitry Andric     if (VFParam.ParamKind != VFParamKind::Vector)
1915ac9a064cSDimitry Andric       return false;
1916ac9a064cSDimitry Andric 
1917ac9a064cSDimitry Andric     Entry.Node = Node->getOperand(OpNum++);
1918ac9a064cSDimitry Andric     Entry.Ty = Ty;
1919ac9a064cSDimitry Andric     Args.push_back(Entry);
1920ac9a064cSDimitry Andric   }
1921ac9a064cSDimitry Andric 
1922ac9a064cSDimitry Andric   // Emit a call to the vector function.
1923ac9a064cSDimitry Andric   SDValue Callee = DAG.getExternalSymbol(VD->getVectorFnName().data(),
1924ac9a064cSDimitry Andric                                          TLI.getPointerTy(DAG.getDataLayout()));
1925ac9a064cSDimitry Andric   TargetLowering::CallLoweringInfo CLI(DAG);
1926ac9a064cSDimitry Andric   CLI.setDebugLoc(DL)
1927ac9a064cSDimitry Andric       .setChain(DAG.getEntryNode())
1928ac9a064cSDimitry Andric       .setLibCallee(CallingConv::C, Ty, Callee, std::move(Args));
1929ac9a064cSDimitry Andric 
1930ac9a064cSDimitry Andric   std::pair<SDValue, SDValue> CallResult = TLI.LowerCallTo(CLI);
1931ac9a064cSDimitry Andric   Results.push_back(CallResult.first);
1932ac9a064cSDimitry Andric   return true;
1933ac9a064cSDimitry Andric }
1934ac9a064cSDimitry Andric 
1935ac9a064cSDimitry Andric /// Try to expand the node to a vector libcall based on the result type.
tryExpandVecMathCall(SDNode * Node,RTLIB::Libcall Call_F32,RTLIB::Libcall Call_F64,RTLIB::Libcall Call_F80,RTLIB::Libcall Call_F128,RTLIB::Libcall Call_PPCF128,SmallVectorImpl<SDValue> & Results)1936ac9a064cSDimitry Andric bool VectorLegalizer::tryExpandVecMathCall(
1937ac9a064cSDimitry Andric     SDNode *Node, RTLIB::Libcall Call_F32, RTLIB::Libcall Call_F64,
1938ac9a064cSDimitry Andric     RTLIB::Libcall Call_F80, RTLIB::Libcall Call_F128,
1939ac9a064cSDimitry Andric     RTLIB::Libcall Call_PPCF128, SmallVectorImpl<SDValue> &Results) {
1940ac9a064cSDimitry Andric   RTLIB::Libcall LC = RTLIB::getFPLibCall(
1941ac9a064cSDimitry Andric       Node->getValueType(0).getVectorElementType(), Call_F32, Call_F64,
1942ac9a064cSDimitry Andric       Call_F80, Call_F128, Call_PPCF128);
1943ac9a064cSDimitry Andric 
1944ac9a064cSDimitry Andric   if (LC == RTLIB::UNKNOWN_LIBCALL)
1945ac9a064cSDimitry Andric     return false;
1946ac9a064cSDimitry Andric 
1947ac9a064cSDimitry Andric   return tryExpandVecMathCall(Node, LC, Results);
1948ac9a064cSDimitry Andric }
1949ac9a064cSDimitry Andric 
UnrollStrictFPOp(SDNode * Node,SmallVectorImpl<SDValue> & Results)1950706b4fc4SDimitry Andric void VectorLegalizer::UnrollStrictFPOp(SDNode *Node,
1951706b4fc4SDimitry Andric                                        SmallVectorImpl<SDValue> &Results) {
1952706b4fc4SDimitry Andric   EVT VT = Node->getValueType(0);
1953eb11fae6SDimitry Andric   EVT EltVT = VT.getVectorElementType();
1954eb11fae6SDimitry Andric   unsigned NumElems = VT.getVectorNumElements();
1955706b4fc4SDimitry Andric   unsigned NumOpers = Node->getNumOperands();
1956eb11fae6SDimitry Andric   const TargetLowering &TLI = DAG.getTargetLoweringInfo();
1957706b4fc4SDimitry Andric 
1958706b4fc4SDimitry Andric   EVT TmpEltVT = EltVT;
1959706b4fc4SDimitry Andric   if (Node->getOpcode() == ISD::STRICT_FSETCC ||
1960706b4fc4SDimitry Andric       Node->getOpcode() == ISD::STRICT_FSETCCS)
1961706b4fc4SDimitry Andric     TmpEltVT = TLI.getSetCCResultType(DAG.getDataLayout(),
1962706b4fc4SDimitry Andric                                       *DAG.getContext(), TmpEltVT);
1963706b4fc4SDimitry Andric 
1964706b4fc4SDimitry Andric   EVT ValueVTs[] = {TmpEltVT, MVT::Other};
1965706b4fc4SDimitry Andric   SDValue Chain = Node->getOperand(0);
1966706b4fc4SDimitry Andric   SDLoc dl(Node);
1967eb11fae6SDimitry Andric 
1968eb11fae6SDimitry Andric   SmallVector<SDValue, 32> OpValues;
1969eb11fae6SDimitry Andric   SmallVector<SDValue, 32> OpChains;
1970eb11fae6SDimitry Andric   for (unsigned i = 0; i < NumElems; ++i) {
1971eb11fae6SDimitry Andric     SmallVector<SDValue, 4> Opers;
1972cfca06d7SDimitry Andric     SDValue Idx = DAG.getVectorIdxConstant(i, dl);
1973eb11fae6SDimitry Andric 
1974eb11fae6SDimitry Andric     // The Chain is the first operand.
1975eb11fae6SDimitry Andric     Opers.push_back(Chain);
1976eb11fae6SDimitry Andric 
1977eb11fae6SDimitry Andric     // Now process the remaining operands.
1978eb11fae6SDimitry Andric     for (unsigned j = 1; j < NumOpers; ++j) {
1979706b4fc4SDimitry Andric       SDValue Oper = Node->getOperand(j);
1980eb11fae6SDimitry Andric       EVT OperVT = Oper.getValueType();
1981eb11fae6SDimitry Andric 
1982eb11fae6SDimitry Andric       if (OperVT.isVector())
1983eb11fae6SDimitry Andric         Oper = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl,
1984e6d15924SDimitry Andric                            OperVT.getVectorElementType(), Oper, Idx);
1985eb11fae6SDimitry Andric 
1986eb11fae6SDimitry Andric       Opers.push_back(Oper);
1987eb11fae6SDimitry Andric     }
1988eb11fae6SDimitry Andric 
1989706b4fc4SDimitry Andric     SDValue ScalarOp = DAG.getNode(Node->getOpcode(), dl, ValueVTs, Opers);
1990706b4fc4SDimitry Andric     SDValue ScalarResult = ScalarOp.getValue(0);
1991706b4fc4SDimitry Andric     SDValue ScalarChain = ScalarOp.getValue(1);
1992eb11fae6SDimitry Andric 
1993706b4fc4SDimitry Andric     if (Node->getOpcode() == ISD::STRICT_FSETCC ||
1994706b4fc4SDimitry Andric         Node->getOpcode() == ISD::STRICT_FSETCCS)
1995706b4fc4SDimitry Andric       ScalarResult = DAG.getSelect(dl, EltVT, ScalarResult,
1996c0981da4SDimitry Andric                                    DAG.getAllOnesConstant(dl, EltVT),
1997706b4fc4SDimitry Andric                                    DAG.getConstant(0, dl, EltVT));
1998706b4fc4SDimitry Andric 
1999706b4fc4SDimitry Andric     OpValues.push_back(ScalarResult);
2000706b4fc4SDimitry Andric     OpChains.push_back(ScalarChain);
2001eb11fae6SDimitry Andric   }
2002eb11fae6SDimitry Andric 
2003eb11fae6SDimitry Andric   SDValue Result = DAG.getBuildVector(VT, dl, OpValues);
2004eb11fae6SDimitry Andric   SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OpChains);
2005eb11fae6SDimitry Andric 
2006706b4fc4SDimitry Andric   Results.push_back(Result);
2007706b4fc4SDimitry Andric   Results.push_back(NewChain);
2008eb11fae6SDimitry Andric }
2009eb11fae6SDimitry Andric 
UnrollVSETCC(SDNode * Node)2010706b4fc4SDimitry Andric SDValue VectorLegalizer::UnrollVSETCC(SDNode *Node) {
2011706b4fc4SDimitry Andric   EVT VT = Node->getValueType(0);
2012009b1c42SEd Schouten   unsigned NumElems = VT.getVectorNumElements();
201359850d08SRoman Divacky   EVT EltVT = VT.getVectorElementType();
2014706b4fc4SDimitry Andric   SDValue LHS = Node->getOperand(0);
2015706b4fc4SDimitry Andric   SDValue RHS = Node->getOperand(1);
2016706b4fc4SDimitry Andric   SDValue CC = Node->getOperand(2);
201759850d08SRoman Divacky   EVT TmpEltVT = LHS.getValueType().getVectorElementType();
2018706b4fc4SDimitry Andric   SDLoc dl(Node);
2019009b1c42SEd Schouten   SmallVector<SDValue, 8> Ops(NumElems);
2020009b1c42SEd Schouten   for (unsigned i = 0; i < NumElems; ++i) {
2021cfca06d7SDimitry Andric     SDValue LHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, LHS,
2022cfca06d7SDimitry Andric                                   DAG.getVectorIdxConstant(i, dl));
2023cfca06d7SDimitry Andric     SDValue RHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, RHS,
2024cfca06d7SDimitry Andric                                   DAG.getVectorIdxConstant(i, dl));
2025f8af5cf6SDimitry Andric     Ops[i] = DAG.getNode(ISD::SETCC, dl,
2026ee8648bdSDimitry Andric                          TLI.getSetCCResultType(DAG.getDataLayout(),
2027ee8648bdSDimitry Andric                                                 *DAG.getContext(), TmpEltVT),
2028009b1c42SEd Schouten                          LHSElem, RHSElem, CC);
2029c0981da4SDimitry Andric     Ops[i] = DAG.getSelect(dl, EltVT, Ops[i], DAG.getAllOnesConstant(dl, EltVT),
20305a5ac124SDimitry Andric                            DAG.getConstant(0, dl, EltVT));
2031009b1c42SEd Schouten   }
203271d5a254SDimitry Andric   return DAG.getBuildVector(VT, dl, Ops);
2033009b1c42SEd Schouten }
2034009b1c42SEd Schouten 
LegalizeVectors()2035009b1c42SEd Schouten bool SelectionDAG::LegalizeVectors() {
2036009b1c42SEd Schouten   return VectorLegalizer(*this).Run();
2037009b1c42SEd Schouten }
2038