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