12cab237bSDimitry Andric //===- LegalizeVectorOps.cpp - Implement SelectionDAG::LegalizeVectors ----===//
2f22ef01cSRoman Divacky //
3f22ef01cSRoman Divacky // The LLVM Compiler Infrastructure
4f22ef01cSRoman Divacky //
5f22ef01cSRoman Divacky // This file is distributed under the University of Illinois Open Source
6f22ef01cSRoman Divacky // License. See LICENSE.TXT for details.
7f22ef01cSRoman Divacky //
8f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
9f22ef01cSRoman Divacky //
10f22ef01cSRoman Divacky // This file implements the SelectionDAG::LegalizeVectors method.
11f22ef01cSRoman Divacky //
12f22ef01cSRoman Divacky // The vector legalizer looks for vector operations which might need to be
13f22ef01cSRoman Divacky // scalarized and legalizes them. This is a separate step from Legalize because
14f22ef01cSRoman Divacky // scalarizing can introduce illegal types. For example, suppose we have an
15f22ef01cSRoman Divacky // ISD::SDIV of type v2i64 on x86-32. The type is legal (for example, addition
16f22ef01cSRoman Divacky // on a v2i64 is legal), but ISD::SDIV isn't legal, so we have to unroll the
17f22ef01cSRoman Divacky // operation, which introduces nodes with the illegal type i64 which must be
18f22ef01cSRoman Divacky // expanded. Similarly, suppose we have an ISD::SRA of type v16i8 on PowerPC;
19f22ef01cSRoman Divacky // the operation must be unrolled, which introduces nodes with the illegal
20f22ef01cSRoman Divacky // type i8 which must be promoted.
21f22ef01cSRoman Divacky //
22f22ef01cSRoman Divacky // This does not legalize vector manipulations like ISD::BUILD_VECTOR,
23f22ef01cSRoman Divacky // or operations that happen to take a vector which are custom-lowered;
24f22ef01cSRoman Divacky // the legalization for such operations never produces nodes
25f22ef01cSRoman Divacky // with illegal types, so it's okay to put off legalizing them until
26f22ef01cSRoman Divacky // SelectionDAG::Legalize runs.
27f22ef01cSRoman Divacky //
28f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
29f22ef01cSRoman Divacky
302cab237bSDimitry Andric #include "llvm/ADT/APInt.h"
312cab237bSDimitry Andric #include "llvm/ADT/DenseMap.h"
322cab237bSDimitry Andric #include "llvm/ADT/SmallVector.h"
332cab237bSDimitry Andric #include "llvm/CodeGen/ISDOpcodes.h"
342cab237bSDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h"
35f22ef01cSRoman Divacky #include "llvm/CodeGen/SelectionDAG.h"
362cab237bSDimitry Andric #include "llvm/CodeGen/SelectionDAGNodes.h"
372cab237bSDimitry Andric #include "llvm/CodeGen/TargetLowering.h"
382cab237bSDimitry Andric #include "llvm/CodeGen/ValueTypes.h"
392cab237bSDimitry Andric #include "llvm/IR/DataLayout.h"
402cab237bSDimitry Andric #include "llvm/Support/Casting.h"
412cab237bSDimitry Andric #include "llvm/Support/Compiler.h"
422cab237bSDimitry Andric #include "llvm/Support/ErrorHandling.h"
434ba319b5SDimitry Andric #include "llvm/Support/MachineValueType.h"
442cab237bSDimitry Andric #include "llvm/Support/MathExtras.h"
452cab237bSDimitry Andric #include <cassert>
462cab237bSDimitry Andric #include <cstdint>
472cab237bSDimitry Andric #include <iterator>
482cab237bSDimitry Andric #include <utility>
492cab237bSDimitry Andric
50f22ef01cSRoman Divacky using namespace llvm;
51f22ef01cSRoman Divacky
52fe4fed2eSDimitry Andric #define DEBUG_TYPE "legalizevectorops"
53fe4fed2eSDimitry Andric
54f22ef01cSRoman Divacky namespace {
552cab237bSDimitry Andric
56f22ef01cSRoman Divacky class VectorLegalizer {
57f22ef01cSRoman Divacky SelectionDAG& DAG;
58f22ef01cSRoman Divacky const TargetLowering &TLI;
592cab237bSDimitry Andric bool Changed = false; // Keep track of whether anything changed
60f22ef01cSRoman Divacky
6191bc56edSDimitry Andric /// For nodes that are of legal width, and that have more than one use, this
6291bc56edSDimitry Andric /// map indicates what regularized operand to use. This allows us to avoid
6391bc56edSDimitry Andric /// legalizing the same thing more than once.
64139f7f9bSDimitry Andric SmallDenseMap<SDValue, SDValue, 64> LegalizedNodes;
65f22ef01cSRoman Divacky
664ba319b5SDimitry Andric /// Adds a node to the translation cache.
AddLegalizedOperand(SDValue From,SDValue To)67f22ef01cSRoman Divacky void AddLegalizedOperand(SDValue From, SDValue To) {
68f22ef01cSRoman Divacky LegalizedNodes.insert(std::make_pair(From, To));
69f22ef01cSRoman Divacky // If someone requests legalization of the new node, return itself.
70f22ef01cSRoman Divacky if (From != To)
71f22ef01cSRoman Divacky LegalizedNodes.insert(std::make_pair(To, To));
72f22ef01cSRoman Divacky }
73f22ef01cSRoman Divacky
744ba319b5SDimitry Andric /// Legalizes the given node.
75f22ef01cSRoman Divacky SDValue LegalizeOp(SDValue Op);
7691bc56edSDimitry Andric
774ba319b5SDimitry Andric /// Assuming the node is legal, "legalize" the results.
78f22ef01cSRoman Divacky SDValue TranslateLegalizeResults(SDValue Op, SDValue Result);
7991bc56edSDimitry Andric
804ba319b5SDimitry Andric /// Implements unrolling a VSETCC.
81f22ef01cSRoman Divacky SDValue UnrollVSETCC(SDValue Op);
8291bc56edSDimitry Andric
834ba319b5SDimitry Andric /// Implement expand-based legalization of vector operations.
8491bc56edSDimitry Andric ///
8591bc56edSDimitry Andric /// This is just a high-level routine to dispatch to specific code paths for
8691bc56edSDimitry Andric /// operations to legalize them.
8791bc56edSDimitry Andric SDValue Expand(SDValue Op);
8891bc56edSDimitry Andric
89*b5893f02SDimitry Andric /// Implements expansion for FP_TO_UINT; falls back to UnrollVectorOp if
90*b5893f02SDimitry Andric /// FP_TO_SINT isn't legal.
91*b5893f02SDimitry Andric SDValue ExpandFP_TO_UINT(SDValue Op);
92*b5893f02SDimitry Andric
9391bc56edSDimitry Andric /// Implements expansion for UINT_TO_FLOAT; falls back to UnrollVectorOp if
9491bc56edSDimitry Andric /// SINT_TO_FLOAT and SHR on vectors isn't legal.
953b0f4066SDimitry Andric SDValue ExpandUINT_TO_FLOAT(SDValue Op);
9691bc56edSDimitry Andric
974ba319b5SDimitry Andric /// Implement expansion for SIGN_EXTEND_INREG using SRL and SRA.
98139f7f9bSDimitry Andric SDValue ExpandSEXTINREG(SDValue Op);
9991bc56edSDimitry Andric
1004ba319b5SDimitry Andric /// Implement expansion for ANY_EXTEND_VECTOR_INREG.
10191bc56edSDimitry Andric ///
10291bc56edSDimitry Andric /// Shuffles the low lanes of the operand into place and bitcasts to the proper
10391bc56edSDimitry Andric /// type. The contents of the bits in the extended part of each element are
10491bc56edSDimitry Andric /// undef.
10591bc56edSDimitry Andric SDValue ExpandANY_EXTEND_VECTOR_INREG(SDValue Op);
10691bc56edSDimitry Andric
1074ba319b5SDimitry Andric /// Implement expansion for SIGN_EXTEND_VECTOR_INREG.
10891bc56edSDimitry Andric ///
10991bc56edSDimitry Andric /// Shuffles the low lanes of the operand into place, bitcasts to the proper
11091bc56edSDimitry Andric /// type, then shifts left and arithmetic shifts right to introduce a sign
11191bc56edSDimitry Andric /// extension.
11291bc56edSDimitry Andric SDValue ExpandSIGN_EXTEND_VECTOR_INREG(SDValue Op);
11391bc56edSDimitry Andric
1144ba319b5SDimitry Andric /// Implement expansion for ZERO_EXTEND_VECTOR_INREG.
11591bc56edSDimitry Andric ///
11691bc56edSDimitry Andric /// Shuffles the low lanes of the operand into place and blends zeros into
11791bc56edSDimitry Andric /// the remaining lanes, finally bitcasting to the proper type.
11891bc56edSDimitry Andric SDValue ExpandZERO_EXTEND_VECTOR_INREG(SDValue Op);
11991bc56edSDimitry Andric
120*b5893f02SDimitry Andric /// Implement expand-based legalization of ABS vector operations.
121*b5893f02SDimitry Andric /// If following expanding is legal/custom then do it:
122*b5893f02SDimitry Andric /// (ABS x) --> (XOR (ADD x, (SRA x, sizeof(x)-1)), (SRA x, sizeof(x)-1))
123*b5893f02SDimitry Andric /// else unroll the operation.
124*b5893f02SDimitry Andric SDValue ExpandABS(SDValue Op);
125*b5893f02SDimitry Andric
1264ba319b5SDimitry Andric /// Expand bswap of vectors into a shuffle if legal.
12791bc56edSDimitry Andric SDValue ExpandBSWAP(SDValue Op);
12891bc56edSDimitry Andric
1294ba319b5SDimitry Andric /// Implement vselect in terms of XOR, AND, OR when blend is not
13091bc56edSDimitry Andric /// supported by the target.
1316122f3e6SDimitry Andric SDValue ExpandVSELECT(SDValue Op);
1323861d79fSDimitry Andric SDValue ExpandSELECT(SDValue Op);
133dff0c46cSDimitry Andric SDValue ExpandLoad(SDValue Op);
134dff0c46cSDimitry Andric SDValue ExpandStore(SDValue Op);
135f22ef01cSRoman Divacky SDValue ExpandFNEG(SDValue Op);
1367a7e6055SDimitry Andric SDValue ExpandFSUB(SDValue Op);
1377d523365SDimitry Andric SDValue ExpandBITREVERSE(SDValue Op);
138*b5893f02SDimitry Andric SDValue ExpandCTPOP(SDValue Op);
139d88c1a5aSDimitry Andric SDValue ExpandCTLZ(SDValue Op);
140*b5893f02SDimitry Andric SDValue ExpandCTTZ(SDValue Op);
141*b5893f02SDimitry Andric SDValue ExpandFunnelShift(SDValue Op);
142*b5893f02SDimitry Andric SDValue ExpandROT(SDValue Op);
143*b5893f02SDimitry Andric SDValue ExpandFMINNUM_FMAXNUM(SDValue Op);
144*b5893f02SDimitry Andric SDValue ExpandAddSubSat(SDValue Op);
1454ba319b5SDimitry Andric SDValue ExpandStrictFPOp(SDValue Op);
14691bc56edSDimitry Andric
1474ba319b5SDimitry Andric /// Implements vector promotion.
14891bc56edSDimitry Andric ///
14991bc56edSDimitry Andric /// This is essentially just bitcasting the operands to a different type and
15091bc56edSDimitry Andric /// bitcasting the result back to the original type.
15191bc56edSDimitry Andric SDValue Promote(SDValue Op);
15291bc56edSDimitry Andric
1534ba319b5SDimitry Andric /// Implements [SU]INT_TO_FP vector promotion.
15491bc56edSDimitry Andric ///
15530785c0eSDimitry Andric /// This is a [zs]ext of the input operand to a larger integer type.
15691bc56edSDimitry Andric SDValue PromoteINT_TO_FP(SDValue Op);
15791bc56edSDimitry Andric
1584ba319b5SDimitry Andric /// Implements FP_TO_[SU]INT vector promotion of the result type.
15991bc56edSDimitry Andric ///
16030785c0eSDimitry Andric /// It is promoted to a larger integer type. The result is then
16191bc56edSDimitry Andric /// truncated back to the original type.
16230785c0eSDimitry Andric SDValue PromoteFP_TO_INT(SDValue Op);
163f22ef01cSRoman Divacky
164f22ef01cSRoman Divacky public:
VectorLegalizer(SelectionDAG & dag)1652cab237bSDimitry Andric VectorLegalizer(SelectionDAG& dag) :
1662cab237bSDimitry Andric DAG(dag), TLI(dag.getTargetLoweringInfo()) {}
1672cab237bSDimitry Andric
1684ba319b5SDimitry Andric /// Begin legalizer the vector operations in the DAG.
169f22ef01cSRoman Divacky bool Run();
170f22ef01cSRoman Divacky };
171f22ef01cSRoman Divacky
1722cab237bSDimitry Andric } // end anonymous namespace
1732cab237bSDimitry Andric
Run()174f22ef01cSRoman Divacky bool VectorLegalizer::Run() {
175139f7f9bSDimitry Andric // Before we start legalizing vector nodes, check if there are any vectors.
176139f7f9bSDimitry Andric bool HasVectors = false;
177139f7f9bSDimitry Andric for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(),
17891bc56edSDimitry Andric E = std::prev(DAG.allnodes_end()); I != std::next(E); ++I) {
179139f7f9bSDimitry Andric // Check if the values of the nodes contain vectors. We don't need to check
180139f7f9bSDimitry Andric // the operands because we are going to check their values at some point.
181139f7f9bSDimitry Andric for (SDNode::value_iterator J = I->value_begin(), E = I->value_end();
182139f7f9bSDimitry Andric J != E; ++J)
183139f7f9bSDimitry Andric HasVectors |= J->isVector();
184139f7f9bSDimitry Andric
185139f7f9bSDimitry Andric // If we found a vector node we can start the legalization.
186139f7f9bSDimitry Andric if (HasVectors)
187139f7f9bSDimitry Andric break;
188139f7f9bSDimitry Andric }
189139f7f9bSDimitry Andric
190139f7f9bSDimitry Andric // If this basic block has no vectors then no need to legalize vectors.
191139f7f9bSDimitry Andric if (!HasVectors)
192139f7f9bSDimitry Andric return false;
193139f7f9bSDimitry Andric
194f22ef01cSRoman Divacky // The legalize process is inherently a bottom-up recursive process (users
195f22ef01cSRoman Divacky // legalize their uses before themselves). Given infinite stack space, we
196f22ef01cSRoman Divacky // could just start legalizing on the root and traverse the whole graph. In
197f22ef01cSRoman Divacky // practice however, this causes us to run out of stack space on large basic
198f22ef01cSRoman Divacky // blocks. To avoid this problem, compute an ordering of the nodes where each
199f22ef01cSRoman Divacky // node is only legalized after all of its operands are legalized.
200f22ef01cSRoman Divacky DAG.AssignTopologicalOrder();
201f22ef01cSRoman Divacky for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(),
20291bc56edSDimitry Andric E = std::prev(DAG.allnodes_end()); I != std::next(E); ++I)
2037d523365SDimitry Andric LegalizeOp(SDValue(&*I, 0));
204f22ef01cSRoman Divacky
205f22ef01cSRoman Divacky // Finally, it's possible the root changed. Get the new root.
206f22ef01cSRoman Divacky SDValue OldRoot = DAG.getRoot();
207f22ef01cSRoman Divacky assert(LegalizedNodes.count(OldRoot) && "Root didn't get legalized?");
208f22ef01cSRoman Divacky DAG.setRoot(LegalizedNodes[OldRoot]);
209f22ef01cSRoman Divacky
210f22ef01cSRoman Divacky LegalizedNodes.clear();
211f22ef01cSRoman Divacky
212f22ef01cSRoman Divacky // Remove dead nodes now.
213f22ef01cSRoman Divacky DAG.RemoveDeadNodes();
214f22ef01cSRoman Divacky
215f22ef01cSRoman Divacky return Changed;
216f22ef01cSRoman Divacky }
217f22ef01cSRoman Divacky
TranslateLegalizeResults(SDValue Op,SDValue Result)218f22ef01cSRoman Divacky SDValue VectorLegalizer::TranslateLegalizeResults(SDValue Op, SDValue Result) {
219f22ef01cSRoman Divacky // Generic legalization: just pass the operand through.
220f22ef01cSRoman Divacky for (unsigned i = 0, e = Op.getNode()->getNumValues(); i != e; ++i)
221f22ef01cSRoman Divacky AddLegalizedOperand(Op.getValue(i), Result.getValue(i));
222f22ef01cSRoman Divacky return Result.getValue(Op.getResNo());
223f22ef01cSRoman Divacky }
224f22ef01cSRoman Divacky
LegalizeOp(SDValue Op)225f22ef01cSRoman Divacky SDValue VectorLegalizer::LegalizeOp(SDValue Op) {
226f22ef01cSRoman Divacky // Note that LegalizeOp may be reentered even from single-use nodes, which
227f22ef01cSRoman Divacky // means that we always must cache transformed nodes.
228f22ef01cSRoman Divacky DenseMap<SDValue, SDValue>::iterator I = LegalizedNodes.find(Op);
229f22ef01cSRoman Divacky if (I != LegalizedNodes.end()) return I->second;
230f22ef01cSRoman Divacky
231f22ef01cSRoman Divacky SDNode* Node = Op.getNode();
232f22ef01cSRoman Divacky
233f22ef01cSRoman Divacky // Legalize the operands
234f22ef01cSRoman Divacky SmallVector<SDValue, 8> Ops;
2353dac3a9bSDimitry Andric for (const SDValue &Op : Node->op_values())
2363dac3a9bSDimitry Andric Ops.push_back(LegalizeOp(Op));
237f22ef01cSRoman Divacky
2384ba319b5SDimitry Andric SDValue Result = SDValue(DAG.UpdateNodeOperands(Op.getNode(), Ops),
2394ba319b5SDimitry Andric Op.getResNo());
240f22ef01cSRoman Divacky
241dff0c46cSDimitry Andric if (Op.getOpcode() == ISD::LOAD) {
242dff0c46cSDimitry Andric LoadSDNode *LD = cast<LoadSDNode>(Op.getNode());
243dff0c46cSDimitry Andric ISD::LoadExtType ExtType = LD->getExtensionType();
244fe4fed2eSDimitry Andric if (LD->getMemoryVT().isVector() && ExtType != ISD::NON_EXTLOAD) {
2454ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "\nLegalizing extending vector load: ";
2464ba319b5SDimitry Andric Node->dump(&DAG));
24739d628a0SDimitry Andric switch (TLI.getLoadExtAction(LD->getExtensionType(), LD->getValueType(0),
24839d628a0SDimitry Andric LD->getMemoryVT())) {
24939d628a0SDimitry Andric default: llvm_unreachable("This action is not supported yet!");
25039d628a0SDimitry Andric case TargetLowering::Legal:
251dff0c46cSDimitry Andric return TranslateLegalizeResults(Op, Result);
25239d628a0SDimitry Andric case TargetLowering::Custom:
25339d628a0SDimitry Andric if (SDValue Lowered = TLI.LowerOperation(Result, DAG)) {
254*b5893f02SDimitry Andric assert(Lowered->getNumValues() == Op->getNumValues() &&
255*b5893f02SDimitry Andric "Unexpected number of results");
256*b5893f02SDimitry Andric if (Lowered != Result) {
257*b5893f02SDimitry Andric // Make sure the new code is also legal.
258*b5893f02SDimitry Andric Lowered = LegalizeOp(Lowered);
25939d628a0SDimitry Andric Changed = true;
26039d628a0SDimitry Andric }
2617d523365SDimitry Andric return TranslateLegalizeResults(Op, Lowered);
26239d628a0SDimitry Andric }
2636d97bb29SDimitry Andric LLVM_FALLTHROUGH;
26439d628a0SDimitry Andric case TargetLowering::Expand:
265dff0c46cSDimitry Andric Changed = true;
266dff0c46cSDimitry Andric return LegalizeOp(ExpandLoad(Op));
267dff0c46cSDimitry Andric }
268fe4fed2eSDimitry Andric }
269dff0c46cSDimitry Andric } else if (Op.getOpcode() == ISD::STORE) {
270dff0c46cSDimitry Andric StoreSDNode *ST = cast<StoreSDNode>(Op.getNode());
271dff0c46cSDimitry Andric EVT StVT = ST->getMemoryVT();
272139f7f9bSDimitry Andric MVT ValVT = ST->getValue().getSimpleValueType();
273fe4fed2eSDimitry Andric if (StVT.isVector() && ST->isTruncatingStore()) {
2744ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "\nLegalizing truncating vector store: ";
275fe4fed2eSDimitry Andric Node->dump(&DAG));
2767d523365SDimitry Andric switch (TLI.getTruncStoreAction(ValVT, StVT)) {
277dff0c46cSDimitry Andric default: llvm_unreachable("This action is not supported yet!");
278dff0c46cSDimitry Andric case TargetLowering::Legal:
279dff0c46cSDimitry Andric return TranslateLegalizeResults(Op, Result);
280ff0cc061SDimitry Andric case TargetLowering::Custom: {
281ff0cc061SDimitry Andric SDValue Lowered = TLI.LowerOperation(Result, DAG);
282*b5893f02SDimitry Andric if (Lowered != Result) {
283*b5893f02SDimitry Andric // Make sure the new code is also legal.
284*b5893f02SDimitry Andric Lowered = LegalizeOp(Lowered);
285*b5893f02SDimitry Andric Changed = true;
286*b5893f02SDimitry Andric }
287ff0cc061SDimitry Andric return TranslateLegalizeResults(Op, Lowered);
288ff0cc061SDimitry Andric }
289dff0c46cSDimitry Andric case TargetLowering::Expand:
290dff0c46cSDimitry Andric Changed = true;
291dff0c46cSDimitry Andric return LegalizeOp(ExpandStore(Op));
292dff0c46cSDimitry Andric }
293fe4fed2eSDimitry Andric }
294*b5893f02SDimitry Andric }
295dff0c46cSDimitry Andric
296*b5893f02SDimitry Andric bool HasVectorValue = false;
297f22ef01cSRoman Divacky for (SDNode::value_iterator J = Node->value_begin(), E = Node->value_end();
298f22ef01cSRoman Divacky J != E;
299f22ef01cSRoman Divacky ++J)
300f22ef01cSRoman Divacky HasVectorValue |= J->isVector();
301f22ef01cSRoman Divacky if (!HasVectorValue)
302f22ef01cSRoman Divacky return TranslateLegalizeResults(Op, Result);
303f22ef01cSRoman Divacky
3044ba319b5SDimitry Andric TargetLowering::LegalizeAction Action = TargetLowering::Legal;
305f22ef01cSRoman Divacky switch (Op.getOpcode()) {
306f22ef01cSRoman Divacky default:
307f22ef01cSRoman Divacky return TranslateLegalizeResults(Op, Result);
3084ba319b5SDimitry Andric case ISD::STRICT_FADD:
3094ba319b5SDimitry Andric case ISD::STRICT_FSUB:
3104ba319b5SDimitry Andric case ISD::STRICT_FMUL:
3114ba319b5SDimitry Andric case ISD::STRICT_FDIV:
312*b5893f02SDimitry Andric case ISD::STRICT_FREM:
3134ba319b5SDimitry Andric case ISD::STRICT_FSQRT:
3144ba319b5SDimitry Andric case ISD::STRICT_FMA:
3154ba319b5SDimitry Andric case ISD::STRICT_FPOW:
3164ba319b5SDimitry Andric case ISD::STRICT_FPOWI:
3174ba319b5SDimitry Andric case ISD::STRICT_FSIN:
3184ba319b5SDimitry Andric case ISD::STRICT_FCOS:
3194ba319b5SDimitry Andric case ISD::STRICT_FEXP:
3204ba319b5SDimitry Andric case ISD::STRICT_FEXP2:
3214ba319b5SDimitry Andric case ISD::STRICT_FLOG:
3224ba319b5SDimitry Andric case ISD::STRICT_FLOG10:
3234ba319b5SDimitry Andric case ISD::STRICT_FLOG2:
3244ba319b5SDimitry Andric case ISD::STRICT_FRINT:
3254ba319b5SDimitry Andric case ISD::STRICT_FNEARBYINT:
326*b5893f02SDimitry Andric case ISD::STRICT_FMAXNUM:
327*b5893f02SDimitry Andric case ISD::STRICT_FMINNUM:
328*b5893f02SDimitry Andric case ISD::STRICT_FCEIL:
329*b5893f02SDimitry Andric case ISD::STRICT_FFLOOR:
330*b5893f02SDimitry Andric case ISD::STRICT_FROUND:
331*b5893f02SDimitry Andric case ISD::STRICT_FTRUNC:
3324ba319b5SDimitry Andric // These pseudo-ops get legalized as if they were their non-strict
3334ba319b5SDimitry Andric // equivalent. For instance, if ISD::FSQRT is legal then ISD::STRICT_FSQRT
3344ba319b5SDimitry Andric // is also legal, but if ISD::FSQRT requires expansion then so does
3354ba319b5SDimitry Andric // ISD::STRICT_FSQRT.
3364ba319b5SDimitry Andric Action = TLI.getStrictFPOperationAction(Node->getOpcode(),
3374ba319b5SDimitry Andric Node->getValueType(0));
3384ba319b5SDimitry Andric break;
339f22ef01cSRoman Divacky case ISD::ADD:
340f22ef01cSRoman Divacky case ISD::SUB:
341f22ef01cSRoman Divacky case ISD::MUL:
342*b5893f02SDimitry Andric case ISD::MULHS:
343*b5893f02SDimitry Andric case ISD::MULHU:
344f22ef01cSRoman Divacky case ISD::SDIV:
345f22ef01cSRoman Divacky case ISD::UDIV:
346f22ef01cSRoman Divacky case ISD::SREM:
347f22ef01cSRoman Divacky case ISD::UREM:
3487d523365SDimitry Andric case ISD::SDIVREM:
3497d523365SDimitry Andric case ISD::UDIVREM:
350f22ef01cSRoman Divacky case ISD::FADD:
351f22ef01cSRoman Divacky case ISD::FSUB:
352f22ef01cSRoman Divacky case ISD::FMUL:
353f22ef01cSRoman Divacky case ISD::FDIV:
354f22ef01cSRoman Divacky case ISD::FREM:
355f22ef01cSRoman Divacky case ISD::AND:
356f22ef01cSRoman Divacky case ISD::OR:
357f22ef01cSRoman Divacky case ISD::XOR:
358f22ef01cSRoman Divacky case ISD::SHL:
359f22ef01cSRoman Divacky case ISD::SRA:
360f22ef01cSRoman Divacky case ISD::SRL:
361*b5893f02SDimitry Andric case ISD::FSHL:
362*b5893f02SDimitry Andric case ISD::FSHR:
363f22ef01cSRoman Divacky case ISD::ROTL:
364f22ef01cSRoman Divacky case ISD::ROTR:
365*b5893f02SDimitry Andric case ISD::ABS:
36685d60e68SDimitry Andric case ISD::BSWAP:
3677d523365SDimitry Andric case ISD::BITREVERSE:
368f22ef01cSRoman Divacky case ISD::CTLZ:
369dff0c46cSDimitry Andric case ISD::CTTZ:
370dff0c46cSDimitry Andric case ISD::CTLZ_ZERO_UNDEF:
371dff0c46cSDimitry Andric case ISD::CTTZ_ZERO_UNDEF:
372f22ef01cSRoman Divacky case ISD::CTPOP:
373f22ef01cSRoman Divacky case ISD::SELECT:
3746122f3e6SDimitry Andric case ISD::VSELECT:
375f22ef01cSRoman Divacky case ISD::SELECT_CC:
3766122f3e6SDimitry Andric case ISD::SETCC:
377f22ef01cSRoman Divacky case ISD::ZERO_EXTEND:
378f22ef01cSRoman Divacky case ISD::ANY_EXTEND:
379f22ef01cSRoman Divacky case ISD::TRUNCATE:
380f22ef01cSRoman Divacky case ISD::SIGN_EXTEND:
381f22ef01cSRoman Divacky case ISD::FP_TO_SINT:
382f22ef01cSRoman Divacky case ISD::FP_TO_UINT:
383f22ef01cSRoman Divacky case ISD::FNEG:
384f22ef01cSRoman Divacky case ISD::FABS:
38539d628a0SDimitry Andric case ISD::FMINNUM:
38639d628a0SDimitry Andric case ISD::FMAXNUM:
387*b5893f02SDimitry Andric case ISD::FMINNUM_IEEE:
388*b5893f02SDimitry Andric case ISD::FMAXNUM_IEEE:
389*b5893f02SDimitry Andric case ISD::FMINIMUM:
390*b5893f02SDimitry Andric case ISD::FMAXIMUM:
391f785676fSDimitry Andric case ISD::FCOPYSIGN:
392f22ef01cSRoman Divacky case ISD::FSQRT:
393f22ef01cSRoman Divacky case ISD::FSIN:
394f22ef01cSRoman Divacky case ISD::FCOS:
395f22ef01cSRoman Divacky case ISD::FPOWI:
396f22ef01cSRoman Divacky case ISD::FPOW:
397f22ef01cSRoman Divacky case ISD::FLOG:
398f22ef01cSRoman Divacky case ISD::FLOG2:
399f22ef01cSRoman Divacky case ISD::FLOG10:
400f22ef01cSRoman Divacky case ISD::FEXP:
401f22ef01cSRoman Divacky case ISD::FEXP2:
402f22ef01cSRoman Divacky case ISD::FCEIL:
403f22ef01cSRoman Divacky case ISD::FTRUNC:
404f22ef01cSRoman Divacky case ISD::FRINT:
405f22ef01cSRoman Divacky case ISD::FNEARBYINT:
406f785676fSDimitry Andric case ISD::FROUND:
407f22ef01cSRoman Divacky case ISD::FFLOOR:
408139f7f9bSDimitry Andric case ISD::FP_ROUND:
409139f7f9bSDimitry Andric case ISD::FP_EXTEND:
4103861d79fSDimitry Andric case ISD::FMA:
41117a519f9SDimitry Andric case ISD::SIGN_EXTEND_INREG:
41291bc56edSDimitry Andric case ISD::ANY_EXTEND_VECTOR_INREG:
41391bc56edSDimitry Andric case ISD::SIGN_EXTEND_VECTOR_INREG:
41491bc56edSDimitry Andric case ISD::ZERO_EXTEND_VECTOR_INREG:
415ff0cc061SDimitry Andric case ISD::SMIN:
416ff0cc061SDimitry Andric case ISD::SMAX:
417ff0cc061SDimitry Andric case ISD::UMIN:
418ff0cc061SDimitry Andric case ISD::UMAX:
419d88c1a5aSDimitry Andric case ISD::SMUL_LOHI:
420d88c1a5aSDimitry Andric case ISD::UMUL_LOHI:
4214ba319b5SDimitry Andric case ISD::FCANONICALIZE:
422*b5893f02SDimitry Andric case ISD::SADDSAT:
423*b5893f02SDimitry Andric case ISD::UADDSAT:
424*b5893f02SDimitry Andric case ISD::SSUBSAT:
425*b5893f02SDimitry Andric case ISD::USUBSAT:
4264ba319b5SDimitry Andric Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
427f22ef01cSRoman Divacky break;
428*b5893f02SDimitry Andric case ISD::SMULFIX: {
429*b5893f02SDimitry Andric unsigned Scale = Node->getConstantOperandVal(2);
430*b5893f02SDimitry Andric Action = TLI.getFixedPointOperationAction(Node->getOpcode(),
431*b5893f02SDimitry Andric Node->getValueType(0), Scale);
432*b5893f02SDimitry Andric break;
433*b5893f02SDimitry Andric }
434f22ef01cSRoman Divacky case ISD::FP_ROUND_INREG:
4354ba319b5SDimitry Andric Action = TLI.getOperationAction(Node->getOpcode(),
4364ba319b5SDimitry Andric cast<VTSDNode>(Node->getOperand(1))->getVT());
437f22ef01cSRoman Divacky break;
438f22ef01cSRoman Divacky case ISD::SINT_TO_FP:
439f22ef01cSRoman Divacky case ISD::UINT_TO_FP:
4404ba319b5SDimitry Andric Action = TLI.getOperationAction(Node->getOpcode(),
4414ba319b5SDimitry Andric Node->getOperand(0).getValueType());
442f22ef01cSRoman Divacky break;
443f22ef01cSRoman Divacky }
444f22ef01cSRoman Divacky
4454ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "\nLegalizing vector op: "; Node->dump(&DAG));
446fe4fed2eSDimitry Andric
4474ba319b5SDimitry Andric switch (Action) {
4487d523365SDimitry Andric default: llvm_unreachable("This action is not supported yet!");
449f22ef01cSRoman Divacky case TargetLowering::Promote:
45091bc56edSDimitry Andric Result = Promote(Op);
451f22ef01cSRoman Divacky Changed = true;
452f22ef01cSRoman Divacky break;
45391bc56edSDimitry Andric case TargetLowering::Legal:
4544ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "Legal node: nothing to do\n");
4557ae0e2c9SDimitry Andric break;
456f22ef01cSRoman Divacky case TargetLowering::Custom: {
4574ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "Trying custom legalization\n");
4583ca95b02SDimitry Andric if (SDValue Tmp1 = TLI.LowerOperation(Op, DAG)) {
4594ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "Successfully custom legalized node\n");
460f22ef01cSRoman Divacky Result = Tmp1;
461f22ef01cSRoman Divacky break;
462f22ef01cSRoman Divacky }
4634ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "Could not custom legalize node\n");
464d88c1a5aSDimitry Andric LLVM_FALLTHROUGH;
465f22ef01cSRoman Divacky }
466f22ef01cSRoman Divacky case TargetLowering::Expand:
46791bc56edSDimitry Andric Result = Expand(Op);
468f22ef01cSRoman Divacky }
469f22ef01cSRoman Divacky
470f22ef01cSRoman Divacky // Make sure that the generated code is itself legal.
471f22ef01cSRoman Divacky if (Result != Op) {
472f22ef01cSRoman Divacky Result = LegalizeOp(Result);
473f22ef01cSRoman Divacky Changed = true;
474f22ef01cSRoman Divacky }
475f22ef01cSRoman Divacky
476f22ef01cSRoman Divacky // Note that LegalizeOp may be reentered even from single-use nodes, which
477f22ef01cSRoman Divacky // means that we always must cache transformed nodes.
478f22ef01cSRoman Divacky AddLegalizedOperand(Op, Result);
479f22ef01cSRoman Divacky return Result;
480f22ef01cSRoman Divacky }
481f22ef01cSRoman Divacky
Promote(SDValue Op)48291bc56edSDimitry Andric SDValue VectorLegalizer::Promote(SDValue Op) {
48391bc56edSDimitry Andric // For a few operations there is a specific concept for promotion based on
48491bc56edSDimitry Andric // the operand's type.
48591bc56edSDimitry Andric switch (Op.getOpcode()) {
48691bc56edSDimitry Andric case ISD::SINT_TO_FP:
48791bc56edSDimitry Andric case ISD::UINT_TO_FP:
48891bc56edSDimitry Andric // "Promote" the operation by extending the operand.
48991bc56edSDimitry Andric return PromoteINT_TO_FP(Op);
49091bc56edSDimitry Andric case ISD::FP_TO_UINT:
49191bc56edSDimitry Andric case ISD::FP_TO_SINT:
49291bc56edSDimitry Andric // Promote the operation by extending the operand.
49330785c0eSDimitry Andric return PromoteFP_TO_INT(Op);
49491bc56edSDimitry Andric }
49591bc56edSDimitry Andric
49639d628a0SDimitry Andric // There are currently two cases of vector promotion:
49739d628a0SDimitry Andric // 1) Bitcasting a vector of integers to a different type to a vector of the
498ff0cc061SDimitry Andric // same overall length. For example, x86 promotes ISD::AND v2i32 to v1i64.
49939d628a0SDimitry Andric // 2) Extending a vector of floats to a vector of the same number of larger
50039d628a0SDimitry Andric // floats. For example, AArch64 promotes ISD::FADD on v4f16 to v4f32.
501139f7f9bSDimitry Andric MVT VT = Op.getSimpleValueType();
502f22ef01cSRoman Divacky assert(Op.getNode()->getNumValues() == 1 &&
503f22ef01cSRoman Divacky "Can't promote a vector with multiple results!");
504139f7f9bSDimitry Andric MVT NVT = TLI.getTypeToPromoteTo(Op.getOpcode(), VT);
505f785676fSDimitry Andric SDLoc dl(Op);
506f22ef01cSRoman Divacky SmallVector<SDValue, 4> Operands(Op.getNumOperands());
507f22ef01cSRoman Divacky
508f22ef01cSRoman Divacky for (unsigned j = 0; j != Op.getNumOperands(); ++j) {
509f22ef01cSRoman Divacky if (Op.getOperand(j).getValueType().isVector())
51039d628a0SDimitry Andric if (Op.getOperand(j)
51139d628a0SDimitry Andric .getValueType()
51239d628a0SDimitry Andric .getVectorElementType()
51344f7b0dcSDimitry Andric .isFloatingPoint() &&
51444f7b0dcSDimitry Andric NVT.isVector() && NVT.getVectorElementType().isFloatingPoint())
51539d628a0SDimitry Andric Operands[j] = DAG.getNode(ISD::FP_EXTEND, dl, NVT, Op.getOperand(j));
51639d628a0SDimitry Andric else
5172754fe60SDimitry Andric Operands[j] = DAG.getNode(ISD::BITCAST, dl, NVT, Op.getOperand(j));
518f22ef01cSRoman Divacky else
519f22ef01cSRoman Divacky Operands[j] = Op.getOperand(j);
520f22ef01cSRoman Divacky }
521f22ef01cSRoman Divacky
5227d523365SDimitry Andric Op = DAG.getNode(Op.getOpcode(), dl, NVT, Operands, Op.getNode()->getFlags());
52344f7b0dcSDimitry Andric if ((VT.isFloatingPoint() && NVT.isFloatingPoint()) ||
52444f7b0dcSDimitry Andric (VT.isVector() && VT.getVectorElementType().isFloatingPoint() &&
52544f7b0dcSDimitry Andric NVT.isVector() && NVT.getVectorElementType().isFloatingPoint()))
526ff0cc061SDimitry Andric return DAG.getNode(ISD::FP_ROUND, dl, VT, Op, DAG.getIntPtrConstant(0, dl));
52739d628a0SDimitry Andric else
5282754fe60SDimitry Andric return DAG.getNode(ISD::BITCAST, dl, VT, Op);
529f22ef01cSRoman Divacky }
530f22ef01cSRoman Divacky
PromoteINT_TO_FP(SDValue Op)53191bc56edSDimitry Andric SDValue VectorLegalizer::PromoteINT_TO_FP(SDValue Op) {
5327ae0e2c9SDimitry Andric // INT_TO_FP operations may require the input operand be promoted even
5337ae0e2c9SDimitry Andric // when the type is otherwise legal.
53430785c0eSDimitry Andric MVT VT = Op.getOperand(0).getSimpleValueType();
53530785c0eSDimitry Andric MVT NVT = TLI.getTypeToPromoteTo(Op.getOpcode(), VT);
53630785c0eSDimitry Andric assert(NVT.getVectorNumElements() == VT.getVectorNumElements() &&
53730785c0eSDimitry Andric "Vectors have different number of elements!");
5387ae0e2c9SDimitry Andric
539f785676fSDimitry Andric SDLoc dl(Op);
5407ae0e2c9SDimitry Andric SmallVector<SDValue, 4> Operands(Op.getNumOperands());
5417ae0e2c9SDimitry Andric
5427ae0e2c9SDimitry Andric unsigned Opc = Op.getOpcode() == ISD::UINT_TO_FP ? ISD::ZERO_EXTEND :
5437ae0e2c9SDimitry Andric ISD::SIGN_EXTEND;
5447ae0e2c9SDimitry Andric for (unsigned j = 0; j != Op.getNumOperands(); ++j) {
5457ae0e2c9SDimitry Andric if (Op.getOperand(j).getValueType().isVector())
5467ae0e2c9SDimitry Andric Operands[j] = DAG.getNode(Opc, dl, NVT, Op.getOperand(j));
5477ae0e2c9SDimitry Andric else
5487ae0e2c9SDimitry Andric Operands[j] = Op.getOperand(j);
5497ae0e2c9SDimitry Andric }
5507ae0e2c9SDimitry Andric
55191bc56edSDimitry Andric return DAG.getNode(Op.getOpcode(), dl, Op.getValueType(), Operands);
55291bc56edSDimitry Andric }
55391bc56edSDimitry Andric
55491bc56edSDimitry Andric // For FP_TO_INT we promote the result type to a vector type with wider
55591bc56edSDimitry Andric // elements and then truncate the result. This is different from the default
55691bc56edSDimitry Andric // PromoteVector which uses bitcast to promote thus assumning that the
55791bc56edSDimitry Andric // promoted vector type has the same overall size.
PromoteFP_TO_INT(SDValue Op)55830785c0eSDimitry Andric SDValue VectorLegalizer::PromoteFP_TO_INT(SDValue Op) {
55930785c0eSDimitry Andric MVT VT = Op.getSimpleValueType();
56030785c0eSDimitry Andric MVT NVT = TLI.getTypeToPromoteTo(Op.getOpcode(), VT);
56130785c0eSDimitry Andric assert(NVT.getVectorNumElements() == VT.getVectorNumElements() &&
56230785c0eSDimitry Andric "Vectors have different number of elements!");
56391bc56edSDimitry Andric
56430785c0eSDimitry Andric unsigned NewOpc = Op->getOpcode();
56530785c0eSDimitry Andric // Change FP_TO_UINT to FP_TO_SINT if possible.
56630785c0eSDimitry Andric // TODO: Should we only do this if FP_TO_UINT itself isn't legal?
56730785c0eSDimitry Andric if (NewOpc == ISD::FP_TO_UINT &&
56830785c0eSDimitry Andric TLI.isOperationLegalOrCustom(ISD::FP_TO_SINT, NVT))
56991bc56edSDimitry Andric NewOpc = ISD::FP_TO_SINT;
57091bc56edSDimitry Andric
5712cab237bSDimitry Andric SDLoc dl(Op);
57230785c0eSDimitry Andric SDValue Promoted = DAG.getNode(NewOpc, dl, NVT, Op.getOperand(0));
5737ae0e2c9SDimitry Andric
5742cab237bSDimitry Andric // Assert that the converted value fits in the original type. If it doesn't
5752cab237bSDimitry Andric // (eg: because the value being converted is too big), then the result of the
5762cab237bSDimitry Andric // original operation was undefined anyway, so the assert is still correct.
5772cab237bSDimitry Andric Promoted = DAG.getNode(Op->getOpcode() == ISD::FP_TO_UINT ? ISD::AssertZext
5782cab237bSDimitry Andric : ISD::AssertSext,
57930785c0eSDimitry Andric dl, NVT, Promoted,
5802cab237bSDimitry Andric DAG.getValueType(VT.getScalarType()));
5812cab237bSDimitry Andric return DAG.getNode(ISD::TRUNCATE, dl, VT, Promoted);
5822cab237bSDimitry Andric }
583dff0c46cSDimitry Andric
ExpandLoad(SDValue Op)584dff0c46cSDimitry Andric SDValue VectorLegalizer::ExpandLoad(SDValue Op) {
585dff0c46cSDimitry Andric LoadSDNode *LD = cast<LoadSDNode>(Op.getNode());
5863ca95b02SDimitry Andric
587dff0c46cSDimitry Andric EVT SrcVT = LD->getMemoryVT();
5883ca95b02SDimitry Andric EVT SrcEltVT = SrcVT.getScalarType();
5893ca95b02SDimitry Andric unsigned NumElem = SrcVT.getVectorNumElements();
5903ca95b02SDimitry Andric
5913ca95b02SDimitry Andric SDValue NewChain;
5923ca95b02SDimitry Andric SDValue Value;
5933ca95b02SDimitry Andric if (SrcVT.getVectorNumElements() > 1 && !SrcEltVT.isByteSized()) {
5943ca95b02SDimitry Andric SDLoc dl(Op);
595dff0c46cSDimitry Andric
596139f7f9bSDimitry Andric SmallVector<SDValue, 8> Vals;
597dff0c46cSDimitry Andric SmallVector<SDValue, 8> LoadChains;
598139f7f9bSDimitry Andric
5993ca95b02SDimitry Andric EVT DstEltVT = LD->getValueType(0).getScalarType();
6003ca95b02SDimitry Andric SDValue Chain = LD->getChain();
6013ca95b02SDimitry Andric SDValue BasePTR = LD->getBasePtr();
6023ca95b02SDimitry Andric ISD::LoadExtType ExtType = LD->getExtensionType();
603139f7f9bSDimitry Andric
604139f7f9bSDimitry Andric // When elements in a vector is not byte-addressable, we cannot directly
605139f7f9bSDimitry Andric // load each element by advancing pointer, which could only address bytes.
606139f7f9bSDimitry Andric // Instead, we load all significant words, mask bits off, and concatenate
607139f7f9bSDimitry Andric // them to form each element. Finally, they are extended to destination
608139f7f9bSDimitry Andric // scalar type to build the destination vector.
609875ed548SDimitry Andric EVT WideVT = TLI.getPointerTy(DAG.getDataLayout());
610139f7f9bSDimitry Andric
611139f7f9bSDimitry Andric assert(WideVT.isRound() &&
612139f7f9bSDimitry Andric "Could not handle the sophisticated case when the widest integer is"
613139f7f9bSDimitry Andric " not power of 2.");
614139f7f9bSDimitry Andric assert(WideVT.bitsGE(SrcEltVT) &&
615139f7f9bSDimitry Andric "Type is not legalized?");
616139f7f9bSDimitry Andric
617139f7f9bSDimitry Andric unsigned WideBytes = WideVT.getStoreSize();
618139f7f9bSDimitry Andric unsigned Offset = 0;
619139f7f9bSDimitry Andric unsigned RemainingBytes = SrcVT.getStoreSize();
620139f7f9bSDimitry Andric SmallVector<SDValue, 8> LoadVals;
621139f7f9bSDimitry Andric while (RemainingBytes > 0) {
622139f7f9bSDimitry Andric SDValue ScalarLoad;
623139f7f9bSDimitry Andric unsigned LoadBytes = WideBytes;
624139f7f9bSDimitry Andric
625139f7f9bSDimitry Andric if (RemainingBytes >= LoadBytes) {
6263ca95b02SDimitry Andric ScalarLoad =
6273ca95b02SDimitry Andric DAG.getLoad(WideVT, dl, Chain, BasePTR,
628139f7f9bSDimitry Andric LD->getPointerInfo().getWithOffset(Offset),
629ff0cc061SDimitry Andric MinAlign(LD->getAlignment(), Offset),
6303ca95b02SDimitry Andric LD->getMemOperand()->getFlags(), LD->getAAInfo());
631139f7f9bSDimitry Andric } else {
632139f7f9bSDimitry Andric EVT LoadVT = WideVT;
633139f7f9bSDimitry Andric while (RemainingBytes < LoadBytes) {
634139f7f9bSDimitry Andric LoadBytes >>= 1; // Reduce the load size by half.
635139f7f9bSDimitry Andric LoadVT = EVT::getIntegerVT(*DAG.getContext(), LoadBytes << 3);
636139f7f9bSDimitry Andric }
6373ca95b02SDimitry Andric ScalarLoad =
6383ca95b02SDimitry Andric DAG.getExtLoad(ISD::EXTLOAD, dl, WideVT, Chain, BasePTR,
6393ca95b02SDimitry Andric LD->getPointerInfo().getWithOffset(Offset), LoadVT,
640ff0cc061SDimitry Andric MinAlign(LD->getAlignment(), Offset),
6413ca95b02SDimitry Andric LD->getMemOperand()->getFlags(), LD->getAAInfo());
642139f7f9bSDimitry Andric }
643139f7f9bSDimitry Andric
644139f7f9bSDimitry Andric RemainingBytes -= LoadBytes;
645139f7f9bSDimitry Andric Offset += LoadBytes;
6462cab237bSDimitry Andric
6472cab237bSDimitry Andric BasePTR = DAG.getObjectPtrOffset(dl, BasePTR, LoadBytes);
648139f7f9bSDimitry Andric
649139f7f9bSDimitry Andric LoadVals.push_back(ScalarLoad.getValue(0));
650139f7f9bSDimitry Andric LoadChains.push_back(ScalarLoad.getValue(1));
651139f7f9bSDimitry Andric }
652139f7f9bSDimitry Andric
653139f7f9bSDimitry Andric // Extract bits, pack and extend/trunc them into destination type.
654139f7f9bSDimitry Andric unsigned SrcEltBits = SrcEltVT.getSizeInBits();
655ff0cc061SDimitry Andric SDValue SrcEltBitMask = DAG.getConstant((1U << SrcEltBits) - 1, dl, WideVT);
656139f7f9bSDimitry Andric
657139f7f9bSDimitry Andric unsigned BitOffset = 0;
658139f7f9bSDimitry Andric unsigned WideIdx = 0;
659139f7f9bSDimitry Andric unsigned WideBits = WideVT.getSizeInBits();
660139f7f9bSDimitry Andric
661139f7f9bSDimitry Andric for (unsigned Idx = 0; Idx != NumElem; ++Idx) {
662139f7f9bSDimitry Andric SDValue Lo, Hi, ShAmt;
663139f7f9bSDimitry Andric
664139f7f9bSDimitry Andric if (BitOffset < WideBits) {
665875ed548SDimitry Andric ShAmt = DAG.getConstant(
666875ed548SDimitry Andric BitOffset, dl, TLI.getShiftAmountTy(WideVT, DAG.getDataLayout()));
667139f7f9bSDimitry Andric Lo = DAG.getNode(ISD::SRL, dl, WideVT, LoadVals[WideIdx], ShAmt);
668139f7f9bSDimitry Andric Lo = DAG.getNode(ISD::AND, dl, WideVT, Lo, SrcEltBitMask);
669139f7f9bSDimitry Andric }
670139f7f9bSDimitry Andric
671139f7f9bSDimitry Andric BitOffset += SrcEltBits;
672139f7f9bSDimitry Andric if (BitOffset >= WideBits) {
673139f7f9bSDimitry Andric WideIdx++;
67444f7b0dcSDimitry Andric BitOffset -= WideBits;
67544f7b0dcSDimitry Andric if (BitOffset > 0) {
676875ed548SDimitry Andric ShAmt = DAG.getConstant(
677875ed548SDimitry Andric SrcEltBits - BitOffset, dl,
678875ed548SDimitry Andric TLI.getShiftAmountTy(WideVT, DAG.getDataLayout()));
679139f7f9bSDimitry Andric Hi = DAG.getNode(ISD::SHL, dl, WideVT, LoadVals[WideIdx], ShAmt);
680139f7f9bSDimitry Andric Hi = DAG.getNode(ISD::AND, dl, WideVT, Hi, SrcEltBitMask);
681139f7f9bSDimitry Andric }
682139f7f9bSDimitry Andric }
683139f7f9bSDimitry Andric
684139f7f9bSDimitry Andric if (Hi.getNode())
685139f7f9bSDimitry Andric Lo = DAG.getNode(ISD::OR, dl, WideVT, Lo, Hi);
686139f7f9bSDimitry Andric
687139f7f9bSDimitry Andric switch (ExtType) {
688139f7f9bSDimitry Andric default: llvm_unreachable("Unknown extended-load op!");
689139f7f9bSDimitry Andric case ISD::EXTLOAD:
690139f7f9bSDimitry Andric Lo = DAG.getAnyExtOrTrunc(Lo, dl, DstEltVT);
691139f7f9bSDimitry Andric break;
692139f7f9bSDimitry Andric case ISD::ZEXTLOAD:
693139f7f9bSDimitry Andric Lo = DAG.getZExtOrTrunc(Lo, dl, DstEltVT);
694139f7f9bSDimitry Andric break;
695139f7f9bSDimitry Andric case ISD::SEXTLOAD:
696875ed548SDimitry Andric ShAmt =
697875ed548SDimitry Andric DAG.getConstant(WideBits - SrcEltBits, dl,
698875ed548SDimitry Andric TLI.getShiftAmountTy(WideVT, DAG.getDataLayout()));
699139f7f9bSDimitry Andric Lo = DAG.getNode(ISD::SHL, dl, WideVT, Lo, ShAmt);
700139f7f9bSDimitry Andric Lo = DAG.getNode(ISD::SRA, dl, WideVT, Lo, ShAmt);
701139f7f9bSDimitry Andric Lo = DAG.getSExtOrTrunc(Lo, dl, DstEltVT);
702139f7f9bSDimitry Andric break;
703139f7f9bSDimitry Andric }
704139f7f9bSDimitry Andric Vals.push_back(Lo);
705139f7f9bSDimitry Andric }
706dff0c46cSDimitry Andric
7073ca95b02SDimitry Andric NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, LoadChains);
7087a7e6055SDimitry Andric Value = DAG.getBuildVector(Op.getNode()->getValueType(0), dl, Vals);
7093ca95b02SDimitry Andric } else {
7103ca95b02SDimitry Andric SDValue Scalarized = TLI.scalarizeVectorLoad(LD, DAG);
7114ba319b5SDimitry Andric // Skip past MERGE_VALUE node if known.
7124ba319b5SDimitry Andric if (Scalarized->getOpcode() == ISD::MERGE_VALUES) {
7134ba319b5SDimitry Andric NewChain = Scalarized.getOperand(1);
7144ba319b5SDimitry Andric Value = Scalarized.getOperand(0);
7154ba319b5SDimitry Andric } else {
7163ca95b02SDimitry Andric NewChain = Scalarized.getValue(1);
7173ca95b02SDimitry Andric Value = Scalarized.getValue(0);
7183ca95b02SDimitry Andric }
7194ba319b5SDimitry Andric }
720dff0c46cSDimitry Andric
721dff0c46cSDimitry Andric AddLegalizedOperand(Op.getValue(0), Value);
722dff0c46cSDimitry Andric AddLegalizedOperand(Op.getValue(1), NewChain);
723dff0c46cSDimitry Andric
724dff0c46cSDimitry Andric return (Op.getResNo() ? NewChain : Value);
725dff0c46cSDimitry Andric }
726dff0c46cSDimitry Andric
ExpandStore(SDValue Op)727dff0c46cSDimitry Andric SDValue VectorLegalizer::ExpandStore(SDValue Op) {
728dff0c46cSDimitry Andric StoreSDNode *ST = cast<StoreSDNode>(Op.getNode());
7293ca95b02SDimitry Andric SDValue TF = TLI.scalarizeVectorStore(ST, DAG);
730dff0c46cSDimitry Andric AddLegalizedOperand(Op, TF);
731dff0c46cSDimitry Andric return TF;
732dff0c46cSDimitry Andric }
733dff0c46cSDimitry Andric
Expand(SDValue Op)73491bc56edSDimitry Andric SDValue VectorLegalizer::Expand(SDValue Op) {
73591bc56edSDimitry Andric switch (Op->getOpcode()) {
73691bc56edSDimitry Andric case ISD::SIGN_EXTEND_INREG:
73791bc56edSDimitry Andric return ExpandSEXTINREG(Op);
73891bc56edSDimitry Andric case ISD::ANY_EXTEND_VECTOR_INREG:
73991bc56edSDimitry Andric return ExpandANY_EXTEND_VECTOR_INREG(Op);
74091bc56edSDimitry Andric case ISD::SIGN_EXTEND_VECTOR_INREG:
74191bc56edSDimitry Andric return ExpandSIGN_EXTEND_VECTOR_INREG(Op);
74291bc56edSDimitry Andric case ISD::ZERO_EXTEND_VECTOR_INREG:
74391bc56edSDimitry Andric return ExpandZERO_EXTEND_VECTOR_INREG(Op);
74491bc56edSDimitry Andric case ISD::BSWAP:
74591bc56edSDimitry Andric return ExpandBSWAP(Op);
74691bc56edSDimitry Andric case ISD::VSELECT:
74791bc56edSDimitry Andric return ExpandVSELECT(Op);
74891bc56edSDimitry Andric case ISD::SELECT:
74991bc56edSDimitry Andric return ExpandSELECT(Op);
750*b5893f02SDimitry Andric case ISD::FP_TO_UINT:
751*b5893f02SDimitry Andric return ExpandFP_TO_UINT(Op);
75291bc56edSDimitry Andric case ISD::UINT_TO_FP:
75391bc56edSDimitry Andric return ExpandUINT_TO_FLOAT(Op);
75491bc56edSDimitry Andric case ISD::FNEG:
75591bc56edSDimitry Andric return ExpandFNEG(Op);
7567a7e6055SDimitry Andric case ISD::FSUB:
7577a7e6055SDimitry Andric return ExpandFSUB(Op);
75891bc56edSDimitry Andric case ISD::SETCC:
75991bc56edSDimitry Andric return UnrollVSETCC(Op);
760*b5893f02SDimitry Andric case ISD::ABS:
761*b5893f02SDimitry Andric return ExpandABS(Op);
7627d523365SDimitry Andric case ISD::BITREVERSE:
7637d523365SDimitry Andric return ExpandBITREVERSE(Op);
764*b5893f02SDimitry Andric case ISD::CTPOP:
765*b5893f02SDimitry Andric return ExpandCTPOP(Op);
766d88c1a5aSDimitry Andric case ISD::CTLZ:
7677d523365SDimitry Andric case ISD::CTLZ_ZERO_UNDEF:
768d88c1a5aSDimitry Andric return ExpandCTLZ(Op);
769*b5893f02SDimitry Andric case ISD::CTTZ:
7707d523365SDimitry Andric case ISD::CTTZ_ZERO_UNDEF:
771*b5893f02SDimitry Andric return ExpandCTTZ(Op);
772*b5893f02SDimitry Andric case ISD::FSHL:
773*b5893f02SDimitry Andric case ISD::FSHR:
774*b5893f02SDimitry Andric return ExpandFunnelShift(Op);
775*b5893f02SDimitry Andric case ISD::ROTL:
776*b5893f02SDimitry Andric case ISD::ROTR:
777*b5893f02SDimitry Andric return ExpandROT(Op);
778*b5893f02SDimitry Andric case ISD::FMINNUM:
779*b5893f02SDimitry Andric case ISD::FMAXNUM:
780*b5893f02SDimitry Andric return ExpandFMINNUM_FMAXNUM(Op);
781*b5893f02SDimitry Andric case ISD::USUBSAT:
782*b5893f02SDimitry Andric case ISD::SSUBSAT:
783*b5893f02SDimitry Andric case ISD::UADDSAT:
784*b5893f02SDimitry Andric case ISD::SADDSAT:
785*b5893f02SDimitry Andric return ExpandAddSubSat(Op);
7864ba319b5SDimitry Andric case ISD::STRICT_FADD:
7874ba319b5SDimitry Andric case ISD::STRICT_FSUB:
7884ba319b5SDimitry Andric case ISD::STRICT_FMUL:
7894ba319b5SDimitry Andric case ISD::STRICT_FDIV:
790*b5893f02SDimitry Andric case ISD::STRICT_FREM:
7914ba319b5SDimitry Andric case ISD::STRICT_FSQRT:
7924ba319b5SDimitry Andric case ISD::STRICT_FMA:
7934ba319b5SDimitry Andric case ISD::STRICT_FPOW:
7944ba319b5SDimitry Andric case ISD::STRICT_FPOWI:
7954ba319b5SDimitry Andric case ISD::STRICT_FSIN:
7964ba319b5SDimitry Andric case ISD::STRICT_FCOS:
7974ba319b5SDimitry Andric case ISD::STRICT_FEXP:
7984ba319b5SDimitry Andric case ISD::STRICT_FEXP2:
7994ba319b5SDimitry Andric case ISD::STRICT_FLOG:
8004ba319b5SDimitry Andric case ISD::STRICT_FLOG10:
8014ba319b5SDimitry Andric case ISD::STRICT_FLOG2:
8024ba319b5SDimitry Andric case ISD::STRICT_FRINT:
8034ba319b5SDimitry Andric case ISD::STRICT_FNEARBYINT:
804*b5893f02SDimitry Andric case ISD::STRICT_FMAXNUM:
805*b5893f02SDimitry Andric case ISD::STRICT_FMINNUM:
806*b5893f02SDimitry Andric case ISD::STRICT_FCEIL:
807*b5893f02SDimitry Andric case ISD::STRICT_FFLOOR:
808*b5893f02SDimitry Andric case ISD::STRICT_FROUND:
809*b5893f02SDimitry Andric case ISD::STRICT_FTRUNC:
8104ba319b5SDimitry Andric return ExpandStrictFPOp(Op);
81191bc56edSDimitry Andric default:
81291bc56edSDimitry Andric return DAG.UnrollVectorOp(Op.getNode());
81391bc56edSDimitry Andric }
81491bc56edSDimitry Andric }
81591bc56edSDimitry Andric
ExpandSELECT(SDValue Op)8163861d79fSDimitry Andric SDValue VectorLegalizer::ExpandSELECT(SDValue Op) {
8173861d79fSDimitry Andric // Lower a select instruction where the condition is a scalar and the
8183861d79fSDimitry Andric // operands are vectors. Lower this select to VSELECT and implement it
8193861d79fSDimitry Andric // using XOR AND OR. The selector bit is broadcasted.
8203861d79fSDimitry Andric EVT VT = Op.getValueType();
821f785676fSDimitry Andric SDLoc DL(Op);
8223861d79fSDimitry Andric
8233861d79fSDimitry Andric SDValue Mask = Op.getOperand(0);
8243861d79fSDimitry Andric SDValue Op1 = Op.getOperand(1);
8253861d79fSDimitry Andric SDValue Op2 = Op.getOperand(2);
8263861d79fSDimitry Andric
8273861d79fSDimitry Andric assert(VT.isVector() && !Mask.getValueType().isVector()
8283861d79fSDimitry Andric && Op1.getValueType() == Op2.getValueType() && "Invalid type");
8293861d79fSDimitry Andric
8303861d79fSDimitry Andric // If we can't even use the basic vector operations of
8313861d79fSDimitry Andric // AND,OR,XOR, we will have to scalarize the op.
8323861d79fSDimitry Andric // Notice that the operation may be 'promoted' which means that it is
8333861d79fSDimitry Andric // 'bitcasted' to another type which is handled.
8343861d79fSDimitry Andric // Also, we need to be able to construct a splat vector using BUILD_VECTOR.
8353861d79fSDimitry Andric if (TLI.getOperationAction(ISD::AND, VT) == TargetLowering::Expand ||
8363861d79fSDimitry Andric TLI.getOperationAction(ISD::XOR, VT) == TargetLowering::Expand ||
8373861d79fSDimitry Andric TLI.getOperationAction(ISD::OR, VT) == TargetLowering::Expand ||
8383861d79fSDimitry Andric TLI.getOperationAction(ISD::BUILD_VECTOR, VT) == TargetLowering::Expand)
8393861d79fSDimitry Andric return DAG.UnrollVectorOp(Op.getNode());
8403861d79fSDimitry Andric
8413861d79fSDimitry Andric // Generate a mask operand.
842f785676fSDimitry Andric EVT MaskTy = VT.changeVectorElementTypeToInteger();
8433861d79fSDimitry Andric
8443861d79fSDimitry Andric // What is the size of each element in the vector mask.
8453861d79fSDimitry Andric EVT BitTy = MaskTy.getScalarType();
8463861d79fSDimitry Andric
847f785676fSDimitry Andric Mask = DAG.getSelect(DL, BitTy, Mask,
848ff0cc061SDimitry Andric DAG.getConstant(APInt::getAllOnesValue(BitTy.getSizeInBits()), DL,
849ff0cc061SDimitry Andric BitTy),
850ff0cc061SDimitry Andric DAG.getConstant(0, DL, BitTy));
8513861d79fSDimitry Andric
8523861d79fSDimitry Andric // Broadcast the mask so that the entire vector is all-one or all zero.
8537a7e6055SDimitry Andric Mask = DAG.getSplatBuildVector(MaskTy, DL, Mask);
8543861d79fSDimitry Andric
8553861d79fSDimitry Andric // Bitcast the operands to be the same type as the mask.
8563861d79fSDimitry Andric // This is needed when we select between FP types because
8573861d79fSDimitry Andric // the mask is a vector of integers.
8583861d79fSDimitry Andric Op1 = DAG.getNode(ISD::BITCAST, DL, MaskTy, Op1);
8593861d79fSDimitry Andric Op2 = DAG.getNode(ISD::BITCAST, DL, MaskTy, Op2);
8603861d79fSDimitry Andric
8613861d79fSDimitry Andric SDValue AllOnes = DAG.getConstant(
862ff0cc061SDimitry Andric APInt::getAllOnesValue(BitTy.getSizeInBits()), DL, MaskTy);
8633861d79fSDimitry Andric SDValue NotMask = DAG.getNode(ISD::XOR, DL, MaskTy, Mask, AllOnes);
8643861d79fSDimitry Andric
8653861d79fSDimitry Andric Op1 = DAG.getNode(ISD::AND, DL, MaskTy, Op1, Mask);
8663861d79fSDimitry Andric Op2 = DAG.getNode(ISD::AND, DL, MaskTy, Op2, NotMask);
8673861d79fSDimitry Andric SDValue Val = DAG.getNode(ISD::OR, DL, MaskTy, Op1, Op2);
8683861d79fSDimitry Andric return DAG.getNode(ISD::BITCAST, DL, Op.getValueType(), Val);
8693861d79fSDimitry Andric }
8703861d79fSDimitry Andric
ExpandSEXTINREG(SDValue Op)871139f7f9bSDimitry Andric SDValue VectorLegalizer::ExpandSEXTINREG(SDValue Op) {
872139f7f9bSDimitry Andric EVT VT = Op.getValueType();
873139f7f9bSDimitry Andric
874139f7f9bSDimitry Andric // Make sure that the SRA and SHL instructions are available.
875139f7f9bSDimitry Andric if (TLI.getOperationAction(ISD::SRA, VT) == TargetLowering::Expand ||
876139f7f9bSDimitry Andric TLI.getOperationAction(ISD::SHL, VT) == TargetLowering::Expand)
877139f7f9bSDimitry Andric return DAG.UnrollVectorOp(Op.getNode());
878139f7f9bSDimitry Andric
879f785676fSDimitry Andric SDLoc DL(Op);
880139f7f9bSDimitry Andric EVT OrigTy = cast<VTSDNode>(Op->getOperand(1))->getVT();
881139f7f9bSDimitry Andric
882d88c1a5aSDimitry Andric unsigned BW = VT.getScalarSizeInBits();
883d88c1a5aSDimitry Andric unsigned OrigBW = OrigTy.getScalarSizeInBits();
884ff0cc061SDimitry Andric SDValue ShiftSz = DAG.getConstant(BW - OrigBW, DL, VT);
885139f7f9bSDimitry Andric
886139f7f9bSDimitry Andric Op = Op.getOperand(0);
887139f7f9bSDimitry Andric Op = DAG.getNode(ISD::SHL, DL, VT, Op, ShiftSz);
888139f7f9bSDimitry Andric return DAG.getNode(ISD::SRA, DL, VT, Op, ShiftSz);
889139f7f9bSDimitry Andric }
890139f7f9bSDimitry Andric
89191bc56edSDimitry Andric // Generically expand a vector anyext in register to a shuffle of the relevant
89291bc56edSDimitry Andric // lanes into the appropriate locations, with other lanes left undef.
ExpandANY_EXTEND_VECTOR_INREG(SDValue Op)89391bc56edSDimitry Andric SDValue VectorLegalizer::ExpandANY_EXTEND_VECTOR_INREG(SDValue Op) {
89491bc56edSDimitry Andric SDLoc DL(Op);
89591bc56edSDimitry Andric EVT VT = Op.getValueType();
89691bc56edSDimitry Andric int NumElements = VT.getVectorNumElements();
89791bc56edSDimitry Andric SDValue Src = Op.getOperand(0);
89891bc56edSDimitry Andric EVT SrcVT = Src.getValueType();
89991bc56edSDimitry Andric int NumSrcElements = SrcVT.getVectorNumElements();
90091bc56edSDimitry Andric
90191bc56edSDimitry Andric // Build a base mask of undef shuffles.
90291bc56edSDimitry Andric SmallVector<int, 16> ShuffleMask;
90391bc56edSDimitry Andric ShuffleMask.resize(NumSrcElements, -1);
90491bc56edSDimitry Andric
90591bc56edSDimitry Andric // Place the extended lanes into the correct locations.
90691bc56edSDimitry Andric int ExtLaneScale = NumSrcElements / NumElements;
907875ed548SDimitry Andric int EndianOffset = DAG.getDataLayout().isBigEndian() ? ExtLaneScale - 1 : 0;
90891bc56edSDimitry Andric for (int i = 0; i < NumElements; ++i)
90991bc56edSDimitry Andric ShuffleMask[i * ExtLaneScale + EndianOffset] = i;
91091bc56edSDimitry Andric
91191bc56edSDimitry Andric return DAG.getNode(
91291bc56edSDimitry Andric ISD::BITCAST, DL, VT,
91391bc56edSDimitry Andric DAG.getVectorShuffle(SrcVT, DL, Src, DAG.getUNDEF(SrcVT), ShuffleMask));
91491bc56edSDimitry Andric }
91591bc56edSDimitry Andric
ExpandSIGN_EXTEND_VECTOR_INREG(SDValue Op)91691bc56edSDimitry Andric SDValue VectorLegalizer::ExpandSIGN_EXTEND_VECTOR_INREG(SDValue Op) {
91791bc56edSDimitry Andric SDLoc DL(Op);
91891bc56edSDimitry Andric EVT VT = Op.getValueType();
91991bc56edSDimitry Andric SDValue Src = Op.getOperand(0);
92091bc56edSDimitry Andric EVT SrcVT = Src.getValueType();
92191bc56edSDimitry Andric
92291bc56edSDimitry Andric // First build an any-extend node which can be legalized above when we
92391bc56edSDimitry Andric // recurse through it.
924*b5893f02SDimitry Andric Op = DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, VT, Src);
92591bc56edSDimitry Andric
92691bc56edSDimitry Andric // Now we need sign extend. Do this by shifting the elements. Even if these
92791bc56edSDimitry Andric // aren't legal operations, they have a better chance of being legalized
92891bc56edSDimitry Andric // without full scalarization than the sign extension does.
929d88c1a5aSDimitry Andric unsigned EltWidth = VT.getScalarSizeInBits();
930d88c1a5aSDimitry Andric unsigned SrcEltWidth = SrcVT.getScalarSizeInBits();
931ff0cc061SDimitry Andric SDValue ShiftAmount = DAG.getConstant(EltWidth - SrcEltWidth, DL, VT);
93291bc56edSDimitry Andric return DAG.getNode(ISD::SRA, DL, VT,
93391bc56edSDimitry Andric DAG.getNode(ISD::SHL, DL, VT, Op, ShiftAmount),
93491bc56edSDimitry Andric ShiftAmount);
93591bc56edSDimitry Andric }
93691bc56edSDimitry Andric
93791bc56edSDimitry Andric // Generically expand a vector zext in register to a shuffle of the relevant
93891bc56edSDimitry Andric // lanes into the appropriate locations, a blend of zero into the high bits,
93991bc56edSDimitry Andric // and a bitcast to the wider element type.
ExpandZERO_EXTEND_VECTOR_INREG(SDValue Op)94091bc56edSDimitry Andric SDValue VectorLegalizer::ExpandZERO_EXTEND_VECTOR_INREG(SDValue Op) {
94191bc56edSDimitry Andric SDLoc DL(Op);
94291bc56edSDimitry Andric EVT VT = Op.getValueType();
94391bc56edSDimitry Andric int NumElements = VT.getVectorNumElements();
94491bc56edSDimitry Andric SDValue Src = Op.getOperand(0);
94591bc56edSDimitry Andric EVT SrcVT = Src.getValueType();
94691bc56edSDimitry Andric int NumSrcElements = SrcVT.getVectorNumElements();
94791bc56edSDimitry Andric
94891bc56edSDimitry Andric // Build up a zero vector to blend into this one.
9493ca95b02SDimitry Andric SDValue Zero = DAG.getConstant(0, DL, SrcVT);
95091bc56edSDimitry Andric
95191bc56edSDimitry Andric // Shuffle the incoming lanes into the correct position, and pull all other
95291bc56edSDimitry Andric // lanes from the zero vector.
95391bc56edSDimitry Andric SmallVector<int, 16> ShuffleMask;
95491bc56edSDimitry Andric ShuffleMask.reserve(NumSrcElements);
95591bc56edSDimitry Andric for (int i = 0; i < NumSrcElements; ++i)
95691bc56edSDimitry Andric ShuffleMask.push_back(i);
95791bc56edSDimitry Andric
95891bc56edSDimitry Andric int ExtLaneScale = NumSrcElements / NumElements;
959875ed548SDimitry Andric int EndianOffset = DAG.getDataLayout().isBigEndian() ? ExtLaneScale - 1 : 0;
96091bc56edSDimitry Andric for (int i = 0; i < NumElements; ++i)
96191bc56edSDimitry Andric ShuffleMask[i * ExtLaneScale + EndianOffset] = NumSrcElements + i;
96291bc56edSDimitry Andric
96391bc56edSDimitry Andric return DAG.getNode(ISD::BITCAST, DL, VT,
96491bc56edSDimitry Andric DAG.getVectorShuffle(SrcVT, DL, Zero, Src, ShuffleMask));
96591bc56edSDimitry Andric }
96691bc56edSDimitry Andric
createBSWAPShuffleMask(EVT VT,SmallVectorImpl<int> & ShuffleMask)9673ca95b02SDimitry Andric static void createBSWAPShuffleMask(EVT VT, SmallVectorImpl<int> &ShuffleMask) {
9683ca95b02SDimitry Andric int ScalarSizeInBytes = VT.getScalarSizeInBits() / 8;
9693ca95b02SDimitry Andric for (int I = 0, E = VT.getVectorNumElements(); I != E; ++I)
9703ca95b02SDimitry Andric for (int J = ScalarSizeInBytes - 1; J >= 0; --J)
9713ca95b02SDimitry Andric ShuffleMask.push_back((I * ScalarSizeInBytes) + J);
9723ca95b02SDimitry Andric }
9733ca95b02SDimitry Andric
ExpandBSWAP(SDValue Op)97491bc56edSDimitry Andric SDValue VectorLegalizer::ExpandBSWAP(SDValue Op) {
97591bc56edSDimitry Andric EVT VT = Op.getValueType();
97691bc56edSDimitry Andric
97791bc56edSDimitry Andric // Generate a byte wise shuffle mask for the BSWAP.
97891bc56edSDimitry Andric SmallVector<int, 16> ShuffleMask;
9793ca95b02SDimitry Andric createBSWAPShuffleMask(VT, ShuffleMask);
98091bc56edSDimitry Andric EVT ByteVT = EVT::getVectorVT(*DAG.getContext(), MVT::i8, ShuffleMask.size());
98191bc56edSDimitry Andric
98291bc56edSDimitry Andric // Only emit a shuffle if the mask is legal.
98391bc56edSDimitry Andric if (!TLI.isShuffleMaskLegal(ShuffleMask, ByteVT))
98491bc56edSDimitry Andric return DAG.UnrollVectorOp(Op.getNode());
98591bc56edSDimitry Andric
98691bc56edSDimitry Andric SDLoc DL(Op);
98791bc56edSDimitry Andric Op = DAG.getNode(ISD::BITCAST, DL, ByteVT, Op.getOperand(0));
9883ca95b02SDimitry Andric Op = DAG.getVectorShuffle(ByteVT, DL, Op, DAG.getUNDEF(ByteVT), ShuffleMask);
98991bc56edSDimitry Andric return DAG.getNode(ISD::BITCAST, DL, VT, Op);
99091bc56edSDimitry Andric }
99191bc56edSDimitry Andric
ExpandBITREVERSE(SDValue Op)9927d523365SDimitry Andric SDValue VectorLegalizer::ExpandBITREVERSE(SDValue Op) {
9937d523365SDimitry Andric EVT VT = Op.getValueType();
9947d523365SDimitry Andric
9957d523365SDimitry Andric // If we have the scalar operation, it's probably cheaper to unroll it.
9967d523365SDimitry Andric if (TLI.isOperationLegalOrCustom(ISD::BITREVERSE, VT.getScalarType()))
9977d523365SDimitry Andric return DAG.UnrollVectorOp(Op.getNode());
9987d523365SDimitry Andric
9993ca95b02SDimitry Andric // If the vector element width is a whole number of bytes, test if its legal
10003ca95b02SDimitry Andric // to BSWAP shuffle the bytes and then perform the BITREVERSE on the byte
10013ca95b02SDimitry Andric // vector. This greatly reduces the number of bit shifts necessary.
10023ca95b02SDimitry Andric unsigned ScalarSizeInBits = VT.getScalarSizeInBits();
10033ca95b02SDimitry Andric if (ScalarSizeInBits > 8 && (ScalarSizeInBits % 8) == 0) {
10043ca95b02SDimitry Andric SmallVector<int, 16> BSWAPMask;
10053ca95b02SDimitry Andric createBSWAPShuffleMask(VT, BSWAPMask);
10063ca95b02SDimitry Andric
10073ca95b02SDimitry Andric EVT ByteVT = EVT::getVectorVT(*DAG.getContext(), MVT::i8, BSWAPMask.size());
10083ca95b02SDimitry Andric if (TLI.isShuffleMaskLegal(BSWAPMask, ByteVT) &&
10093ca95b02SDimitry Andric (TLI.isOperationLegalOrCustom(ISD::BITREVERSE, ByteVT) ||
10103ca95b02SDimitry Andric (TLI.isOperationLegalOrCustom(ISD::SHL, ByteVT) &&
10113ca95b02SDimitry Andric TLI.isOperationLegalOrCustom(ISD::SRL, ByteVT) &&
10123ca95b02SDimitry Andric TLI.isOperationLegalOrCustomOrPromote(ISD::AND, ByteVT) &&
10133ca95b02SDimitry Andric TLI.isOperationLegalOrCustomOrPromote(ISD::OR, ByteVT)))) {
10143ca95b02SDimitry Andric SDLoc DL(Op);
10153ca95b02SDimitry Andric Op = DAG.getNode(ISD::BITCAST, DL, ByteVT, Op.getOperand(0));
10163ca95b02SDimitry Andric Op = DAG.getVectorShuffle(ByteVT, DL, Op, DAG.getUNDEF(ByteVT),
10173ca95b02SDimitry Andric BSWAPMask);
10183ca95b02SDimitry Andric Op = DAG.getNode(ISD::BITREVERSE, DL, ByteVT, Op);
10193ca95b02SDimitry Andric return DAG.getNode(ISD::BITCAST, DL, VT, Op);
10203ca95b02SDimitry Andric }
10213ca95b02SDimitry Andric }
10223ca95b02SDimitry Andric
10237d523365SDimitry Andric // If we have the appropriate vector bit operations, it is better to use them
10247d523365SDimitry Andric // than unrolling and expanding each component.
10257d523365SDimitry Andric if (!TLI.isOperationLegalOrCustom(ISD::SHL, VT) ||
10267d523365SDimitry Andric !TLI.isOperationLegalOrCustom(ISD::SRL, VT) ||
10273ca95b02SDimitry Andric !TLI.isOperationLegalOrCustomOrPromote(ISD::AND, VT) ||
10283ca95b02SDimitry Andric !TLI.isOperationLegalOrCustomOrPromote(ISD::OR, VT))
10297d523365SDimitry Andric return DAG.UnrollVectorOp(Op.getNode());
10307d523365SDimitry Andric
10317d523365SDimitry Andric // Let LegalizeDAG handle this later.
10327d523365SDimitry Andric return Op;
10337d523365SDimitry Andric }
10347d523365SDimitry Andric
ExpandVSELECT(SDValue Op)10356122f3e6SDimitry Andric SDValue VectorLegalizer::ExpandVSELECT(SDValue Op) {
10366122f3e6SDimitry Andric // Implement VSELECT in terms of XOR, AND, OR
10376122f3e6SDimitry Andric // on platforms which do not support blend natively.
1038f785676fSDimitry Andric SDLoc DL(Op);
10396122f3e6SDimitry Andric
10406122f3e6SDimitry Andric SDValue Mask = Op.getOperand(0);
10416122f3e6SDimitry Andric SDValue Op1 = Op.getOperand(1);
10426122f3e6SDimitry Andric SDValue Op2 = Op.getOperand(2);
10436122f3e6SDimitry Andric
1044f785676fSDimitry Andric EVT VT = Mask.getValueType();
1045f785676fSDimitry Andric
10466122f3e6SDimitry Andric // If we can't even use the basic vector operations of
10476122f3e6SDimitry Andric // AND,OR,XOR, we will have to scalarize the op.
1048dff0c46cSDimitry Andric // Notice that the operation may be 'promoted' which means that it is
1049dff0c46cSDimitry Andric // 'bitcasted' to another type which is handled.
10503861d79fSDimitry Andric // This operation also isn't safe with AND, OR, XOR when the boolean
10513861d79fSDimitry Andric // type is 0/1 as we need an all ones vector constant to mask with.
10523861d79fSDimitry Andric // FIXME: Sign extend 1 to all ones if thats legal on the target.
1053dff0c46cSDimitry Andric if (TLI.getOperationAction(ISD::AND, VT) == TargetLowering::Expand ||
1054dff0c46cSDimitry Andric TLI.getOperationAction(ISD::XOR, VT) == TargetLowering::Expand ||
10553861d79fSDimitry Andric TLI.getOperationAction(ISD::OR, VT) == TargetLowering::Expand ||
105691bc56edSDimitry Andric TLI.getBooleanContents(Op1.getValueType()) !=
10573861d79fSDimitry Andric TargetLowering::ZeroOrNegativeOneBooleanContent)
10586122f3e6SDimitry Andric return DAG.UnrollVectorOp(Op.getNode());
10596122f3e6SDimitry Andric
1060f785676fSDimitry Andric // If the mask and the type are different sizes, unroll the vector op. This
1061f785676fSDimitry Andric // can occur when getSetCCResultType returns something that is different in
1062f785676fSDimitry Andric // size from the operand types. For example, v4i8 = select v4i32, v4i8, v4i8.
1063d88c1a5aSDimitry Andric if (VT.getSizeInBits() != Op1.getValueSizeInBits())
1064f785676fSDimitry Andric return DAG.UnrollVectorOp(Op.getNode());
1065f785676fSDimitry Andric
10666122f3e6SDimitry Andric // Bitcast the operands to be the same type as the mask.
10676122f3e6SDimitry Andric // This is needed when we select between FP types because
10686122f3e6SDimitry Andric // the mask is a vector of integers.
10696122f3e6SDimitry Andric Op1 = DAG.getNode(ISD::BITCAST, DL, VT, Op1);
10706122f3e6SDimitry Andric Op2 = DAG.getNode(ISD::BITCAST, DL, VT, Op2);
10716122f3e6SDimitry Andric
10726122f3e6SDimitry Andric SDValue AllOnes = DAG.getConstant(
1073d88c1a5aSDimitry Andric APInt::getAllOnesValue(VT.getScalarSizeInBits()), DL, VT);
10746122f3e6SDimitry Andric SDValue NotMask = DAG.getNode(ISD::XOR, DL, VT, Mask, AllOnes);
10756122f3e6SDimitry Andric
10766122f3e6SDimitry Andric Op1 = DAG.getNode(ISD::AND, DL, VT, Op1, Mask);
10776122f3e6SDimitry Andric Op2 = DAG.getNode(ISD::AND, DL, VT, Op2, NotMask);
1078cb4dff85SDimitry Andric SDValue Val = DAG.getNode(ISD::OR, DL, VT, Op1, Op2);
1079cb4dff85SDimitry Andric return DAG.getNode(ISD::BITCAST, DL, Op.getValueType(), Val);
10806122f3e6SDimitry Andric }
10816122f3e6SDimitry Andric
ExpandABS(SDValue Op)1082*b5893f02SDimitry Andric SDValue VectorLegalizer::ExpandABS(SDValue Op) {
1083*b5893f02SDimitry Andric // Attempt to expand using TargetLowering.
1084*b5893f02SDimitry Andric SDValue Result;
1085*b5893f02SDimitry Andric if (TLI.expandABS(Op.getNode(), Result, DAG))
1086*b5893f02SDimitry Andric return Result;
1087*b5893f02SDimitry Andric
1088*b5893f02SDimitry Andric // Otherwise go ahead and unroll.
1089*b5893f02SDimitry Andric return DAG.UnrollVectorOp(Op.getNode());
1090*b5893f02SDimitry Andric }
1091*b5893f02SDimitry Andric
ExpandFP_TO_UINT(SDValue Op)1092*b5893f02SDimitry Andric SDValue VectorLegalizer::ExpandFP_TO_UINT(SDValue Op) {
1093*b5893f02SDimitry Andric // Attempt to expand using TargetLowering.
1094*b5893f02SDimitry Andric SDValue Result;
1095*b5893f02SDimitry Andric if (TLI.expandFP_TO_UINT(Op.getNode(), Result, DAG))
1096*b5893f02SDimitry Andric return Result;
1097*b5893f02SDimitry Andric
1098*b5893f02SDimitry Andric // Otherwise go ahead and unroll.
1099*b5893f02SDimitry Andric return DAG.UnrollVectorOp(Op.getNode());
1100*b5893f02SDimitry Andric }
1101*b5893f02SDimitry Andric
ExpandUINT_TO_FLOAT(SDValue Op)11023b0f4066SDimitry Andric SDValue VectorLegalizer::ExpandUINT_TO_FLOAT(SDValue Op) {
11033b0f4066SDimitry Andric EVT VT = Op.getOperand(0).getValueType();
1104f785676fSDimitry Andric SDLoc DL(Op);
11053b0f4066SDimitry Andric
1106*b5893f02SDimitry Andric // Attempt to expand using TargetLowering.
1107*b5893f02SDimitry Andric SDValue Result;
1108*b5893f02SDimitry Andric if (TLI.expandUINT_TO_FP(Op.getNode(), Result, DAG))
1109*b5893f02SDimitry Andric return Result;
1110*b5893f02SDimitry Andric
11113b0f4066SDimitry Andric // Make sure that the SINT_TO_FP and SRL instructions are available.
1112dff0c46cSDimitry Andric if (TLI.getOperationAction(ISD::SINT_TO_FP, VT) == TargetLowering::Expand ||
1113dff0c46cSDimitry Andric TLI.getOperationAction(ISD::SRL, VT) == TargetLowering::Expand)
11143b0f4066SDimitry Andric return DAG.UnrollVectorOp(Op.getNode());
11153b0f4066SDimitry Andric
1116d88c1a5aSDimitry Andric unsigned BW = VT.getScalarSizeInBits();
1117d88c1a5aSDimitry Andric assert((BW == 64 || BW == 32) &&
11183b0f4066SDimitry Andric "Elements in vector-UINT_TO_FP must be 32 or 64 bits wide");
11193b0f4066SDimitry Andric
1120ff0cc061SDimitry Andric SDValue HalfWord = DAG.getConstant(BW / 2, DL, VT);
11213b0f4066SDimitry Andric
11223b0f4066SDimitry Andric // Constants to clear the upper part of the word.
11233b0f4066SDimitry Andric // Notice that we can also use SHL+SHR, but using a constant is slightly
11243b0f4066SDimitry Andric // faster on x86.
1125d88c1a5aSDimitry Andric uint64_t HWMask = (BW == 64) ? 0x00000000FFFFFFFF : 0x0000FFFF;
1126ff0cc061SDimitry Andric SDValue HalfWordMask = DAG.getConstant(HWMask, DL, VT);
11273b0f4066SDimitry Andric
11283b0f4066SDimitry Andric // Two to the power of half-word-size.
11294ba319b5SDimitry Andric SDValue TWOHW = DAG.getConstantFP(1ULL << (BW / 2), DL, Op.getValueType());
11303b0f4066SDimitry Andric
11313b0f4066SDimitry Andric // Clear upper part of LO, lower HI
11323b0f4066SDimitry Andric SDValue HI = DAG.getNode(ISD::SRL, DL, VT, Op.getOperand(0), HalfWord);
11333b0f4066SDimitry Andric SDValue LO = DAG.getNode(ISD::AND, DL, VT, Op.getOperand(0), HalfWordMask);
11343b0f4066SDimitry Andric
11353b0f4066SDimitry Andric // Convert hi and lo to floats
11363b0f4066SDimitry Andric // Convert the hi part back to the upper values
11377d523365SDimitry Andric // TODO: Can any fast-math-flags be set on these nodes?
11383b0f4066SDimitry Andric SDValue fHI = DAG.getNode(ISD::SINT_TO_FP, DL, Op.getValueType(), HI);
11393b0f4066SDimitry Andric fHI = DAG.getNode(ISD::FMUL, DL, Op.getValueType(), fHI, TWOHW);
11403b0f4066SDimitry Andric SDValue fLO = DAG.getNode(ISD::SINT_TO_FP, DL, Op.getValueType(), LO);
11413b0f4066SDimitry Andric
11423b0f4066SDimitry Andric // Add the two halves
11433b0f4066SDimitry Andric return DAG.getNode(ISD::FADD, DL, Op.getValueType(), fHI, fLO);
11443b0f4066SDimitry Andric }
11453b0f4066SDimitry Andric
ExpandFNEG(SDValue Op)1146f22ef01cSRoman Divacky SDValue VectorLegalizer::ExpandFNEG(SDValue Op) {
1147f22ef01cSRoman Divacky if (TLI.isOperationLegalOrCustom(ISD::FSUB, Op.getValueType())) {
1148ff0cc061SDimitry Andric SDLoc DL(Op);
1149ff0cc061SDimitry Andric SDValue Zero = DAG.getConstantFP(-0.0, DL, Op.getValueType());
11507d523365SDimitry Andric // TODO: If FNEG had fast-math-flags, they'd get propagated to this FSUB.
1151ff0cc061SDimitry Andric return DAG.getNode(ISD::FSUB, DL, Op.getValueType(),
1152f22ef01cSRoman Divacky Zero, Op.getOperand(0));
1153f22ef01cSRoman Divacky }
1154f22ef01cSRoman Divacky return DAG.UnrollVectorOp(Op.getNode());
1155f22ef01cSRoman Divacky }
1156f22ef01cSRoman Divacky
ExpandFSUB(SDValue Op)11577a7e6055SDimitry Andric SDValue VectorLegalizer::ExpandFSUB(SDValue Op) {
11587a7e6055SDimitry Andric // For floating-point values, (a-b) is the same as a+(-b). If FNEG is legal,
11597a7e6055SDimitry Andric // we can defer this to operation legalization where it will be lowered as
11607a7e6055SDimitry Andric // a+(-b).
11617a7e6055SDimitry Andric EVT VT = Op.getValueType();
11627a7e6055SDimitry Andric if (TLI.isOperationLegalOrCustom(ISD::FNEG, VT) &&
11637a7e6055SDimitry Andric TLI.isOperationLegalOrCustom(ISD::FADD, VT))
11647a7e6055SDimitry Andric return Op; // Defer to LegalizeDAG
11657a7e6055SDimitry Andric
11667a7e6055SDimitry Andric return DAG.UnrollVectorOp(Op.getNode());
11677a7e6055SDimitry Andric }
11687a7e6055SDimitry Andric
ExpandCTPOP(SDValue Op)1169*b5893f02SDimitry Andric SDValue VectorLegalizer::ExpandCTPOP(SDValue Op) {
1170*b5893f02SDimitry Andric SDValue Result;
1171*b5893f02SDimitry Andric if (TLI.expandCTPOP(Op.getNode(), Result, DAG))
1172*b5893f02SDimitry Andric return Result;
1173d88c1a5aSDimitry Andric
1174d88c1a5aSDimitry Andric return DAG.UnrollVectorOp(Op.getNode());
1175d88c1a5aSDimitry Andric }
1176d88c1a5aSDimitry Andric
ExpandCTLZ(SDValue Op)1177*b5893f02SDimitry Andric SDValue VectorLegalizer::ExpandCTLZ(SDValue Op) {
1178*b5893f02SDimitry Andric SDValue Result;
1179*b5893f02SDimitry Andric if (TLI.expandCTLZ(Op.getNode(), Result, DAG))
1180*b5893f02SDimitry Andric return Result;
1181*b5893f02SDimitry Andric
1182*b5893f02SDimitry Andric return DAG.UnrollVectorOp(Op.getNode());
11833ca95b02SDimitry Andric }
11847d523365SDimitry Andric
ExpandCTTZ(SDValue Op)1185*b5893f02SDimitry Andric SDValue VectorLegalizer::ExpandCTTZ(SDValue Op) {
1186*b5893f02SDimitry Andric SDValue Result;
1187*b5893f02SDimitry Andric if (TLI.expandCTTZ(Op.getNode(), Result, DAG))
1188*b5893f02SDimitry Andric return Result;
1189*b5893f02SDimitry Andric
1190*b5893f02SDimitry Andric return DAG.UnrollVectorOp(Op.getNode());
1191*b5893f02SDimitry Andric }
1192*b5893f02SDimitry Andric
ExpandFunnelShift(SDValue Op)1193*b5893f02SDimitry Andric SDValue VectorLegalizer::ExpandFunnelShift(SDValue Op) {
1194*b5893f02SDimitry Andric SDValue Result;
1195*b5893f02SDimitry Andric if (TLI.expandFunnelShift(Op.getNode(), Result, DAG))
1196*b5893f02SDimitry Andric return Result;
1197*b5893f02SDimitry Andric
1198*b5893f02SDimitry Andric return DAG.UnrollVectorOp(Op.getNode());
1199*b5893f02SDimitry Andric }
1200*b5893f02SDimitry Andric
ExpandROT(SDValue Op)1201*b5893f02SDimitry Andric SDValue VectorLegalizer::ExpandROT(SDValue Op) {
1202*b5893f02SDimitry Andric SDValue Result;
1203*b5893f02SDimitry Andric if (TLI.expandROT(Op.getNode(), Result, DAG))
1204*b5893f02SDimitry Andric return Result;
1205*b5893f02SDimitry Andric
1206*b5893f02SDimitry Andric return DAG.UnrollVectorOp(Op.getNode());
1207*b5893f02SDimitry Andric }
1208*b5893f02SDimitry Andric
ExpandFMINNUM_FMAXNUM(SDValue Op)1209*b5893f02SDimitry Andric SDValue VectorLegalizer::ExpandFMINNUM_FMAXNUM(SDValue Op) {
1210*b5893f02SDimitry Andric if (SDValue Expanded = TLI.expandFMINNUM_FMAXNUM(Op.getNode(), DAG))
1211*b5893f02SDimitry Andric return Expanded;
1212*b5893f02SDimitry Andric return DAG.UnrollVectorOp(Op.getNode());
1213*b5893f02SDimitry Andric }
1214*b5893f02SDimitry Andric
ExpandAddSubSat(SDValue Op)1215*b5893f02SDimitry Andric SDValue VectorLegalizer::ExpandAddSubSat(SDValue Op) {
1216*b5893f02SDimitry Andric if (SDValue Expanded = TLI.expandAddSubSat(Op.getNode(), DAG))
1217*b5893f02SDimitry Andric return Expanded;
12187d523365SDimitry Andric return DAG.UnrollVectorOp(Op.getNode());
12197d523365SDimitry Andric }
12207d523365SDimitry Andric
ExpandStrictFPOp(SDValue Op)12214ba319b5SDimitry Andric SDValue VectorLegalizer::ExpandStrictFPOp(SDValue Op) {
12224ba319b5SDimitry Andric EVT VT = Op.getValueType();
12234ba319b5SDimitry Andric EVT EltVT = VT.getVectorElementType();
12244ba319b5SDimitry Andric unsigned NumElems = VT.getVectorNumElements();
12254ba319b5SDimitry Andric unsigned NumOpers = Op.getNumOperands();
12264ba319b5SDimitry Andric const TargetLowering &TLI = DAG.getTargetLoweringInfo();
12274ba319b5SDimitry Andric EVT ValueVTs[] = {EltVT, MVT::Other};
12284ba319b5SDimitry Andric SDValue Chain = Op.getOperand(0);
12294ba319b5SDimitry Andric SDLoc dl(Op);
12304ba319b5SDimitry Andric
12314ba319b5SDimitry Andric SmallVector<SDValue, 32> OpValues;
12324ba319b5SDimitry Andric SmallVector<SDValue, 32> OpChains;
12334ba319b5SDimitry Andric for (unsigned i = 0; i < NumElems; ++i) {
12344ba319b5SDimitry Andric SmallVector<SDValue, 4> Opers;
12354ba319b5SDimitry Andric SDValue Idx = DAG.getConstant(i, dl,
12364ba319b5SDimitry Andric TLI.getVectorIdxTy(DAG.getDataLayout()));
12374ba319b5SDimitry Andric
12384ba319b5SDimitry Andric // The Chain is the first operand.
12394ba319b5SDimitry Andric Opers.push_back(Chain);
12404ba319b5SDimitry Andric
12414ba319b5SDimitry Andric // Now process the remaining operands.
12424ba319b5SDimitry Andric for (unsigned j = 1; j < NumOpers; ++j) {
12434ba319b5SDimitry Andric SDValue Oper = Op.getOperand(j);
12444ba319b5SDimitry Andric EVT OperVT = Oper.getValueType();
12454ba319b5SDimitry Andric
12464ba319b5SDimitry Andric if (OperVT.isVector())
12474ba319b5SDimitry Andric Oper = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl,
12484ba319b5SDimitry Andric EltVT, Oper, Idx);
12494ba319b5SDimitry Andric
12504ba319b5SDimitry Andric Opers.push_back(Oper);
12514ba319b5SDimitry Andric }
12524ba319b5SDimitry Andric
12534ba319b5SDimitry Andric SDValue ScalarOp = DAG.getNode(Op->getOpcode(), dl, ValueVTs, Opers);
12544ba319b5SDimitry Andric
12554ba319b5SDimitry Andric OpValues.push_back(ScalarOp.getValue(0));
12564ba319b5SDimitry Andric OpChains.push_back(ScalarOp.getValue(1));
12574ba319b5SDimitry Andric }
12584ba319b5SDimitry Andric
12594ba319b5SDimitry Andric SDValue Result = DAG.getBuildVector(VT, dl, OpValues);
12604ba319b5SDimitry Andric SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OpChains);
12614ba319b5SDimitry Andric
12624ba319b5SDimitry Andric AddLegalizedOperand(Op.getValue(0), Result);
12634ba319b5SDimitry Andric AddLegalizedOperand(Op.getValue(1), NewChain);
12644ba319b5SDimitry Andric
1265*b5893f02SDimitry Andric return Op.getResNo() ? NewChain : Result;
12664ba319b5SDimitry Andric }
12674ba319b5SDimitry Andric
UnrollVSETCC(SDValue Op)1268f22ef01cSRoman Divacky SDValue VectorLegalizer::UnrollVSETCC(SDValue Op) {
1269f22ef01cSRoman Divacky EVT VT = Op.getValueType();
1270f22ef01cSRoman Divacky unsigned NumElems = VT.getVectorNumElements();
1271f22ef01cSRoman Divacky EVT EltVT = VT.getVectorElementType();
1272f22ef01cSRoman Divacky SDValue LHS = Op.getOperand(0), RHS = Op.getOperand(1), CC = Op.getOperand(2);
1273f22ef01cSRoman Divacky EVT TmpEltVT = LHS.getValueType().getVectorElementType();
1274f785676fSDimitry Andric SDLoc dl(Op);
1275f22ef01cSRoman Divacky SmallVector<SDValue, 8> Ops(NumElems);
1276f22ef01cSRoman Divacky for (unsigned i = 0; i < NumElems; ++i) {
1277875ed548SDimitry Andric SDValue LHSElem = DAG.getNode(
1278875ed548SDimitry Andric ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, LHS,
1279875ed548SDimitry Andric DAG.getConstant(i, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
1280875ed548SDimitry Andric SDValue RHSElem = DAG.getNode(
1281875ed548SDimitry Andric ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, RHS,
1282875ed548SDimitry Andric DAG.getConstant(i, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
1283f785676fSDimitry Andric Ops[i] = DAG.getNode(ISD::SETCC, dl,
1284875ed548SDimitry Andric TLI.getSetCCResultType(DAG.getDataLayout(),
1285875ed548SDimitry Andric *DAG.getContext(), TmpEltVT),
1286f22ef01cSRoman Divacky LHSElem, RHSElem, CC);
1287f785676fSDimitry Andric Ops[i] = DAG.getSelect(dl, EltVT, Ops[i],
1288f22ef01cSRoman Divacky DAG.getConstant(APInt::getAllOnesValue
1289ff0cc061SDimitry Andric (EltVT.getSizeInBits()), dl, EltVT),
1290ff0cc061SDimitry Andric DAG.getConstant(0, dl, EltVT));
1291f22ef01cSRoman Divacky }
12927a7e6055SDimitry Andric return DAG.getBuildVector(VT, dl, Ops);
1293f22ef01cSRoman Divacky }
1294f22ef01cSRoman Divacky
LegalizeVectors()1295f22ef01cSRoman Divacky bool SelectionDAG::LegalizeVectors() {
1296f22ef01cSRoman Divacky return VectorLegalizer(*this).Run();
1297f22ef01cSRoman Divacky }
1298