diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index dbb0be410a8..b94e8c76510 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -185,6 +185,21 @@ public: /// legalization. virtual bool shouldSplitVectorElementType(EVT /*VT*/) const { return false; } + // There are two general methods for expanding a BUILD_VECTOR node: + // 1. Use SCALAR_TO_VECTOR on the defined scalar values and then shuffle + // them together. + // 2. Build the vector on the stack and then load it. + // If this function returns true, then method (1) will be used, subject to + // the constraint that all of the necessary shuffles are legal (as determined + // by isShuffleMaskLegal). If this function returns false, then method (2) is + // always used. The vector type, and the number of defined values, are + // provided. + virtual bool + shouldExpandBuildVectorWithShuffles(EVT /* VT */, + unsigned DefinedValues) const { + return DefinedValues < 3; + } + /// Return true if integer divide is usually cheaper than a sequence of /// several shifts, adds, and multiplies for this target. bool isIntDivCheap() const { return IntDivIsCheap; } diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 608de82265a..853bae7b5bd 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -13,6 +13,7 @@ #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Triple.h" #include "llvm/CodeGen/Analysis.h" @@ -1889,7 +1890,15 @@ SDValue SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) { false, false, false, Alignment); } - if (!MoreThanTwoValues) { + SmallSet DefinedValues; + for (unsigned i = 0; i < NumElems; ++i) { + if (Node->getOperand(i).getOpcode() == ISD::UNDEF) + continue; + DefinedValues.insert(Node->getOperand(i)); + } + + if (!MoreThanTwoValues && + TLI.shouldExpandBuildVectorWithShuffles(VT, DefinedValues.size())) { SmallVector ShuffleVec(NumElems, -1); for (unsigned i = 0; i < NumElems; ++i) { SDValue V = Node->getOperand(i);