From 05a76eb9f235d96a174d99bbe695f476668fd00d Mon Sep 17 00:00:00 2001 From: Andrea Di Biagio Date: Wed, 13 Aug 2014 16:09:40 +0000 Subject: [PATCH] [DAGCombiner] Improved target independent vector shuffle combine rule. This patch improves the existing algorithm in DAGCombiner that attempts to fold shuffles according to rule: shuffle(shuffle(x, y, M1), undef, M2) -> shuffle(y, undef, M3) Before this change, there were cases where the DAGCombiner conservatively avoided folding shuffles even if the resulting mask would have been legal. That is because the algorithm wrongly assumed that commuting an illegal shuffle mask would always produce an illegal mask. With this change, we now correctly compute the commuted shuffle mask before calling method 'isShuffleMaskLegal' on it. On X86, this improves for example the codegen for the following function: define <4 x i32> @test(<4 x i32> %A, <4 x i32> %B) { %1 = shufflevector <4 x i32> %B, <4 x i32> %A, <4 x i32> %2 = shufflevector <4 x i32> %1, <4 x i32> undef, <4 x i32> ret <4 x i32> %2 } Before this change the X86 backend (-mcpu=corei7) generated the following assembly code for function @test: shufps $-23, %xmm0, %xmm1 # xmm1 = xmm1[1,2],xmm0[2,3] movhlps %xmm1, %xmm1 # xmm1 = xmm1[1,1] movaps %xmm1, %xmm0 Now we produce: movhlps %xmm0, %xmm0 # xmm0 = xmm0[1,1] Added extra test cases in combine-vec-shuffle-2.ll to verify that we correctly fold according to the above-mentioned rule. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@215555 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 34 +++++++---- test/CodeGen/X86/combine-vec-shuffle-2.ll | 72 +++++++++++++++++++++-- 2 files changed, 92 insertions(+), 14 deletions(-) diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index e8cbd8af7a8..603ccb090ed 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -10838,16 +10838,30 @@ SDValue DAGCombiner::visitVECTOR_SHUFFLE(SDNode *N) { // It may still be beneficial to combine the two shuffles if the // resulting shuffle is legal. - if (TLI.isTypeLegal(VT) && TLI.isShuffleMaskLegal(Mask, VT)) { - if (!CommuteOperands) - // shuffle(shuffle(x, undef, M1), undef, M2) -> shuffle(x, undef, M3). - // shuffle(shuffle(x, y, M1), undef, M2) -> shuffle(x, undef, M3) - return DAG.getVectorShuffle(VT, SDLoc(N), N0->getOperand(0), N1, - &Mask[0]); - - // shuffle(shuffle(x, y, M1), undef, M2) -> shuffle(undef, y, M3) - return DAG.getVectorShuffle(VT, SDLoc(N), N1, N0->getOperand(1), - &Mask[0]); + if (TLI.isTypeLegal(VT)) { + if (!CommuteOperands) { + if (TLI.isShuffleMaskLegal(Mask, VT)) + // shuffle(shuffle(x, undef, M1), undef, M2) -> shuffle(x, undef, M3). + // shuffle(shuffle(x, y, M1), undef, M2) -> shuffle(x, undef, M3) + return DAG.getVectorShuffle(VT, SDLoc(N), N0->getOperand(0), N1, + &Mask[0]); + } else { + // Compute the commuted shuffle mask. + for (unsigned i = 0; i != NumElts; ++i) { + int idx = Mask[i]; + if (idx < 0) + continue; + else if (idx < (int)NumElts) + Mask[i] = idx + NumElts; + else + Mask[i] = idx - NumElts; + } + + if (TLI.isShuffleMaskLegal(Mask, VT)) + // shuffle(shuffle(x, y, M1), undef, M2) -> shuffle(y, undef, M3) + return DAG.getVectorShuffle(VT, SDLoc(N), N0->getOperand(1), N1, + &Mask[0]); + } } } diff --git a/test/CodeGen/X86/combine-vec-shuffle-2.ll b/test/CodeGen/X86/combine-vec-shuffle-2.ll index 877d38260d6..872384ca0a1 100644 --- a/test/CodeGen/X86/combine-vec-shuffle-2.ll +++ b/test/CodeGen/X86/combine-vec-shuffle-2.ll @@ -204,8 +204,8 @@ define <4 x i32> @test18(<4 x i32> %A, <4 x i32> %B) { ret <4 x i32> %2 } ; CHECK-LABEL: test18 -; CHECK: blendps $11 -; CHECK-NEXT: pshufd $-59 +; CHECK-NOT: blendps +; CHECK: pshufd {{.*}} # xmm0 = xmm1[1,1,0,3] ; CHECK-NEXT: ret define <4 x i32> @test19(<4 x i32> %A, <4 x i32> %B) { @@ -240,6 +240,8 @@ define <4 x i32> @test21(<4 x i32> %A, <4 x i32> %B) { ; CHECK-NEXT: pshufd $-60 ; CHECK-NEXT: ret +; Test that we correctly combine shuffles according to rule +; shuffle(shuffle(x, y), undef) -> shuffle(y, undef) define <4 x i32> @test22(<4 x i32> %A, <4 x i32> %B) { %1 = shufflevector <4 x i32> %A, <4 x i32> %B, <4 x i32> @@ -247,7 +249,69 @@ define <4 x i32> @test22(<4 x i32> %A, <4 x i32> %B) { ret <4 x i32> %2 } ; CHECK-LABEL: test22 -; CHECK: blendps $11 -; CHECK-NEXT: pshufd $-43 +; CHECK-NOT: blendps +; CHECK: pshufd {{.*}} # xmm0 = xmm1[1,1,1,3] +; CHECK-NEXT: ret + +define <4 x i32> @test23(<4 x i32> %A, <4 x i32> %B) { + %1 = shufflevector <4 x i32> %A, <4 x i32> %B, <4 x i32> + %2 = shufflevector <4 x i32> %1, <4 x i32> undef, <4 x i32> + ret <4 x i32> %2 +} +; CHECK-LABEL: test23 +; CHECK-NOT: blendps +; CHECK: pshufd {{.*}} # xmm0 = xmm1[0,1,0,3] +; CHECK-NEXT: ret + +define <4 x i32> @test24(<4 x i32> %A, <4 x i32> %B) { + %1 = shufflevector <4 x i32> %A, <4 x i32> %B, <4 x i32> + %2 = shufflevector <4 x i32> %1, <4 x i32> undef, <4 x i32> + ret <4 x i32> %2 +} +; CHECK-LABEL: test24 +; CHECK-NOT: blendps +; CHECK: pshufd {{.*}} # xmm0 = xmm1[0,3,2,0] +; CHECK-NEXT: ret + +define <4 x i32> @test25(<4 x i32> %A, <4 x i32> %B) { + %1 = shufflevector <4 x i32> %B, <4 x i32> %A, <4 x i32> + %2 = shufflevector <4 x i32> %1, <4 x i32> undef, <4 x i32> + ret <4 x i32> %2 +} +; CHECK-LABEL: test25 +; CHECK-NOT: shufps +; CHECK: pshufd {{.*}} # xmm0 = xmm0[0,1,0,1] +; CHECK-NEXT: ret + +define <4 x i32> @test26(<4 x i32> %A, <4 x i32> %B) { + %1 = shufflevector <4 x i32> %B, <4 x i32> %A, <4 x i32> + %2 = shufflevector <4 x i32> %1, <4 x i32> undef, <4 x i32> + ret <4 x i32> %2 +} +; CHECK-LABEL: test26 +; CHECK-NOT: shufps +; CHECK: movhlps {{.*}} # xmm0 = xmm0[1,1] +; CHECK-NEXT: ret + +define <4 x i32> @test27(<4 x i32> %A, <4 x i32> %B) { + %1 = shufflevector <4 x i32> %B, <4 x i32> %A, <4 x i32> + %2 = shufflevector <4 x i32> %1, <4 x i32> undef, <4 x i32> + ret <4 x i32> %2 +} +; CHECK-LABEL: test27 +; CHECK-NOT: shufps +; CHECK-NOT: movhlps +; CHECK: pshufd {{.*}} # xmm0 = xmm0[0,1,0,1] +; CHECK-NEXT: ret + +define <4 x i32> @test28(<4 x i32> %A, <4 x i32> %B) { + %1 = shufflevector <4 x i32> %B, <4 x i32> %A, <4 x i32> + %2 = shufflevector <4 x i32> %1, <4 x i32> undef, <4 x i32> + ret <4 x i32> %2 +} +; CHECK-LABEL: test28 +; CHECK-NOT: shufps +; CHECK-NOT: movhlps +; CHECK: pshufd {{.*}} # xmm0 = xmm0[0,1,1,0] ; CHECK-NEXT: ret -- 2.34.1