diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 35e1f27df59..d09ae2d20ef 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -6346,9 +6346,10 @@ SDValue DAGCombiner::visitVECTOR_SHUFFLE(SDNode *N) { // FIXME: implement canonicalizations from DAG.getVectorShuffle() - // If it is a splat, check if the argument vector is a build_vector with - // all scalar elements the same. - if (cast(N)->isSplat()) { + // If it is a splat, check if the argument vector is another splat or a + // build_vector with all scalar elements the same. + ShuffleVectorSDNode *SVN = cast(N); + if (SVN->isSplat() && SVN->getSplatIndex() < (int)NumElts) { SDNode *V = N0.getNode(); // If this is a bit convert that changes the element type of the vector but @@ -6361,31 +6362,34 @@ SDValue DAGCombiner::visitVECTOR_SHUFFLE(SDNode *N) { V = ConvInput.getNode(); } + // Fold a splat of a splat. + ShuffleVectorSDNode *SVV = dyn_cast(V); + if (SVV && SVV->isSplat()) + return N0; + if (V->getOpcode() == ISD::BUILD_VECTOR) { - unsigned NumElems = V->getNumOperands(); - unsigned BaseIdx = cast(N)->getSplatIndex(); - if (NumElems > BaseIdx) { - SDValue Base; - bool AllSame = true; - for (unsigned i = 0; i != NumElems; ++i) { - if (V->getOperand(i).getOpcode() != ISD::UNDEF) { - Base = V->getOperand(i); - break; - } + assert(V->getNumOperands() == NumElts && + "BUILD_VECTOR has wrong number of operands"); + SDValue Base; + bool AllSame = true; + for (unsigned i = 0; i != NumElts; ++i) { + if (V->getOperand(i).getOpcode() != ISD::UNDEF) { + Base = V->getOperand(i); + break; } - // Splat of , return - if (!Base.getNode()) - return N0; - for (unsigned i = 0; i != NumElems; ++i) { - if (V->getOperand(i) != Base) { - AllSame = false; - break; - } - } - // Splat of , return - if (AllSame) - return N0; } + // Splat of , return + if (!Base.getNode()) + return N0; + for (unsigned i = 0; i != NumElts; ++i) { + if (V->getOperand(i) != Base) { + AllSame = false; + break; + } + } + // Splat of , return + if (AllSame) + return N0; } } return SDValue(); diff --git a/test/CodeGen/ARM/vmla.ll b/test/CodeGen/ARM/vmla.ll index 9c6b210be79..1f76d7377f5 100644 --- a/test/CodeGen/ARM/vmla.ll +++ b/test/CodeGen/ARM/vmla.ll @@ -213,3 +213,19 @@ entry: %4 = add <2 x i64> %arg0_uint64x2_t, %3 ret <2 x i64> %4 } + +; Redundant vector splats should be removed. Radar 8597790. +define void @fold_splat(<4 x i32>* %a, <4 x i32>* %b, <4 x i32>* %c) nounwind { +; CHECK: fold_splat +; CHECK-NOT: vdup +; CHECK: vmla.i32 + %tmp1 = load <4 x i32>* %a, align 16 + %tmp3 = load <4 x i32>* %b, align 16 + %tmp5 = load <4 x i32>* %c, align 16 + %tmp6 = shufflevector <4 x i32> %tmp5, <4 x i32> undef, <4 x i32> + %tmp7 = shufflevector <4 x i32> %tmp6, <4 x i32> undef, <4 x i32> zeroinitializer + %tmp8 = mul <4 x i32> %tmp3, %tmp7 + %tmp9 = add <4 x i32> %tmp1, %tmp8 + store <4 x i32> %tmp9, <4 x i32>* %a, align 16 + ret void +}