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