Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -14920,6 +14920,16 @@ return DAG.getVectorShuffle(VT, SDLoc(N), SV0, SV1, Mask); } + // shuffle(shuffle_splat(A), u) -> shuffle_splat(A) + // The case where the shuffle-splat has a single use should have been handled + // previously, so here the shuffle being visited is not the only use of the + // splat-shuffle. + if (auto Shuf = dyn_cast(N0)) + if (N1->isUndef() && Shuf->isSplat()) { + assert(!N->isOnlyUserOf(Shuf) && + "Single use of splat-shuffle should have already been visited"); + return N0; + } return SDValue(); } Index: test/CodeGen/X86/shuffle-of-splat-multiuses.ll =================================================================== --- test/CodeGen/X86/shuffle-of-splat-multiuses.ll +++ test/CodeGen/X86/shuffle-of-splat-multiuses.ll @@ -5,9 +5,8 @@ define <2 x double> @foo2(<2 x double> %v, <2 x double> *%p) nounwind { ; AVX2-LABEL: foo2: ; AVX2: # BB#0: -; AVX2-NEXT: vpermilpd {{.*#+}} xmm1 = xmm0[1,1] -; AVX2-NEXT: vpermilpd {{.*#+}} xmm0 = xmm1[1,0] -; AVX2-NEXT: vmovapd %xmm1, (%rdi) +; AVX2-NEXT: vpermilpd {{.*#+}} xmm0 = xmm0[1,1] +; AVX2-NEXT: vmovapd %xmm0, (%rdi) ; AVX2-NEXT: retq %res = shufflevector <2 x double> %v, <2 x double> undef, <2 x i32> %res1 = shufflevector<2 x double> %res, <2 x double> undef, <2 x i32> @@ -18,9 +17,8 @@ define <4 x double> @foo4(<4 x double> %v, <4 x double> *%p) nounwind { ; AVX2-LABEL: foo4: ; AVX2: # BB#0: -; AVX2-NEXT: vpermpd {{.*#+}} ymm1 = ymm0[2,2,2,2] -; AVX2-NEXT: vpermpd {{.*#+}} ymm0 = ymm1[2,0,2,3] -; AVX2-NEXT: vmovapd %ymm1, (%rdi) +; AVX2-NEXT: vpermpd {{.*#+}} ymm0 = ymm0[2,2,2,2] +; AVX2-NEXT: vmovapd %ymm0, (%rdi) ; AVX2-NEXT: retq %res = shufflevector <4 x double> %v, <4 x double> undef, <4 x i32> %res1 = shufflevector<4 x double> %res, <4 x double> undef, <4 x i32> @@ -32,10 +30,8 @@ ; AVX2-LABEL: foo8: ; AVX2: # BB#0: ; AVX2-NEXT: vmovshdup {{.*#+}} ymm0 = ymm0[1,1,3,3,5,5,7,7] -; AVX2-NEXT: vpermpd {{.*#+}} ymm1 = ymm0[2,2,2,2] -; AVX2-NEXT: vmovaps {{.*#+}} ymm0 = <2,0,u,u,5,1,3,7> -; AVX2-NEXT: vpermps %ymm1, %ymm0, %ymm0 -; AVX2-NEXT: vmovapd %ymm1, (%rdi) +; AVX2-NEXT: vpermpd {{.*#+}} ymm0 = ymm0[2,2,2,2] +; AVX2-NEXT: vmovapd %ymm0, (%rdi) ; AVX2-NEXT: retq %res = shufflevector <8 x float> %v, <8 x float> undef, <8 x i32> %res1 = shufflevector<8 x float> %res, <8 x float> undef, <8 x i32>