forked from OSchip/llvm-project
[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> <i32 1, i32 2, i32 6, i32 7> %2 = shufflevector <4 x i32> %1, <4 x i32> undef, <4 x i32> <i32 2, i32 3, i32 2, i32 3> 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. llvm-svn: 215555
This commit is contained in:
parent
f67672e41c
commit
ace8e1e3d4
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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> <i32 4, i32 5, i32 2, i32 7>
|
||||
|
@ -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> <i32 4, i32 5, i32 2, i32 7>
|
||||
%2 = shufflevector <4 x i32> %1, <4 x i32> undef, <4 x i32> <i32 0, i32 1, i32 0, i32 3>
|
||||
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> <i32 4, i32 1, i32 6, i32 7>
|
||||
%2 = shufflevector <4 x i32> %1, <4 x i32> undef, <4 x i32> <i32 0, i32 3, i32 2, i32 4>
|
||||
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> <i32 1, i32 5, i32 2, i32 4>
|
||||
%2 = shufflevector <4 x i32> %1, <4 x i32> undef, <4 x i32> <i32 3, i32 1, i32 3, i32 1>
|
||||
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> <i32 1, i32 2, i32 6, i32 7>
|
||||
%2 = shufflevector <4 x i32> %1, <4 x i32> undef, <4 x i32> <i32 2, i32 3, i32 2, i32 3>
|
||||
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> <i32 2, i32 1, i32 5, i32 4>
|
||||
%2 = shufflevector <4 x i32> %1, <4 x i32> undef, <4 x i32> <i32 3, i32 2, i32 3, i32 2>
|
||||
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> <i32 1, i32 2, i32 4, i32 5>
|
||||
%2 = shufflevector <4 x i32> %1, <4 x i32> undef, <4 x i32> <i32 2, i32 3, i32 3, i32 2>
|
||||
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
|
||||
|
||||
|
|
Loading…
Reference in New Issue