+// Attempt to lower a build vector of repeated elts as a build vector of unique
+// ops followed by a shuffle.
+static SDValue
+lowerBuildVectorWithRepeatedEltsUsingShuffle(SDValue V, SelectionDAG &DAG,
+ const X86Subtarget &Subtarget) {
+ MVT VT = V.getSimpleValueType();
+ unsigned NumElts = VT.getVectorNumElements();
+
+ // TODO - vXi8 insertions+shuffles often cause PSHUFBs which can lead to
+ // excessive/bulky shuffle mask creation.
+ if (VT.getScalarSizeInBits() < 16)
+ return SDValue();
+
+ // Create list of unique operands to be passed to a build vector and a shuffle
+ // mask describing the repetitions.
+ // TODO - we currently insert the first occurances in place - sometimes it
+ // might be better to insert them in other locations for shuffle efficiency.
+ bool HasRepeatedElts = false;
+ SmallVector<int, 16> Mask(NumElts, SM_SentinelUndef);
+ SmallVector<SDValue, 16> Uniques(V->op_begin(), V->op_end());
+ for (unsigned i = 0; i != NumElts; ++i) {
+ SDValue Op = Uniques[i];
+ if (Op.isUndef())
+ continue;
+ Mask[i] = i;
+
+ // Zeros can be efficiently repeated, so don't shuffle these.
+ if (X86::isZeroNode(Op))
+ continue;
+
+ // If any repeated operands are found then mark the build vector entry as
+ // undef and setup a copy in the shuffle mask.
+ for (unsigned j = i + 1; j != NumElts; ++j)
+ if (Op == Uniques[j]) {
+ HasRepeatedElts = true;
+ Mask[j] = i;
+ Uniques[j] = DAG.getUNDEF(VT.getScalarType());
+ }
+ }
+
+ if (!HasRepeatedElts)
+ return SDValue();
+
+ SDLoc DL(V);
+ return DAG.getVectorShuffle(VT, DL, DAG.getBuildVector(VT, DL, Uniques),
+ DAG.getUNDEF(VT), Mask);
+}
+