[llvm] r213504 - [DAGCombiner] Improve the shuffle-vector folding logic.

Andrea Di Biagio Andrea_DiBiagio at sn.scee.net
Mon Jul 21 00:30:55 PDT 2014


Author: adibiagio
Date: Mon Jul 21 02:30:54 2014
New Revision: 213504

URL: http://llvm.org/viewvc/llvm-project?rev=213504&view=rev
Log:
[DAGCombiner] Improve the shuffle-vector folding logic.

Canonicalize shuffles according to rules:
 *  shuffle(A, shuffle(A, B)) -> shuffle(shuffle(A,B), A)
 *  shuffle(B, shuffle(A, B)) -> shuffle(shuffle(A,B), B)
 *  shuffle(B, shuffle(A, Undef)) -> shuffle(shuffle(A, Undef), B)

This patch helps identifying more shuffle pairs that could be combined reusing
the already existing rules in the DAGCombiner.

Added new test 'combine-vec-shuffle-5.ll' to verify that the canonicalized
shuffles are now folded into a single shuffle node by the DAGCombiner.
Added more test cases to 'combine-vec-shuffle-4.ll'.


Added:
    llvm/trunk/test/CodeGen/X86/combine-vec-shuffle-5.ll
Modified:
    llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
    llvm/trunk/test/CodeGen/X86/combine-vec-shuffle-4.ll

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=213504&r1=213503&r2=213504&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Mon Jul 21 02:30:54 2014
@@ -10743,6 +10743,28 @@ SDValue DAGCombiner::visitVECTOR_SHUFFLE
     }
   }
 
+  // Canonicalize shuffles according to rules:
+  //  shuffle(A, shuffle(A, B)) -> shuffle(shuffle(A,B), A)
+  //  shuffle(B, shuffle(A, B)) -> shuffle(shuffle(A,B), B)
+  //  shuffle(B, shuffle(A, Undef)) -> shuffle(shuffle(A, Undef), B)
+  if (N1.getOpcode() == ISD::VECTOR_SHUFFLE && N0.getOpcode() != ISD::UNDEF &&
+      N0.getOpcode() != ISD::VECTOR_SHUFFLE && Level < AfterLegalizeDAG &&
+      TLI.isTypeLegal(VT)) {
+    // The incoming shuffle must be of the same type as the result of the
+    // current shuffle.
+    assert(N1->getOperand(0).getValueType() == VT &&
+           "Shuffle types don't match");
+
+    SDValue SV0 = N1->getOperand(0);
+    SDValue SV1 = N1->getOperand(1);
+    bool HasSameOp0 = N0 == SV0;
+    bool IsSV1Undef = SV1.getOpcode() == ISD::UNDEF;
+    if (HasSameOp0 || IsSV1Undef || N0 == SV1)
+      // Commute the operands of this shuffle so that next rule
+      // will trigger.
+      return DAG.getCommutedVectorShuffle(*SVN);
+  }
+
   // Try to fold according to rules:
   //   shuffle(shuffle(A, B, M0), B, M1) -> shuffle(A, B, M2)
   //   shuffle(shuffle(A, B, M0), A, M1) -> shuffle(A, B, M2)

Modified: llvm/trunk/test/CodeGen/X86/combine-vec-shuffle-4.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/combine-vec-shuffle-4.ll?rev=213504&r1=213503&r2=213504&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/combine-vec-shuffle-4.ll (original)
+++ llvm/trunk/test/CodeGen/X86/combine-vec-shuffle-4.ll Mon Jul 21 02:30:54 2014
@@ -116,3 +116,122 @@ define <4 x float> @test10(<4 x float> %
 ; CHECK-NOT: movlhps
 ; CHECK: ret
 
+define <4 x float> @test11(<4 x float> %a, <4 x float> %b) {
+  %1 = shufflevector <4 x float> %a, <4 x float> undef, <4 x i32> <i32 4, i32 2, i32 3, i32 1>
+  %2 = shufflevector <4 x float> %b, <4 x float> %1, <4 x i32> <i32 0, i32 1, i32 5, i32 6>
+  ret <4 x float> %2
+}
+; CHECK-LABEL: test11
+; Mask: [4,5,2,3]
+; CHECK: movsd
+; CHECK: ret
+
+define <4 x float> @test12(<4 x float> %a, <4 x float> %b) {
+  %1 = shufflevector <4 x float> %a, <4 x float> undef, <4 x i32> <i32 6, i32 0, i32 1, i32 7>
+  %2 = shufflevector <4 x float> %b, <4 x float> %1, <4 x i32> <i32 5, i32 6, i32 0, i32 1>
+  ret <4 x float> %2
+}
+; CHECK-LABEL: test12
+; Mask: [0,1,4,5]
+; CHECK: movlhps 
+; CHECK: ret
+
+define <4 x float> @test13(<4 x float> %a, <4 x float> %b) {
+  %1 = shufflevector <4 x float> %a, <4 x float> undef, <4 x i32> <i32 0, i32 5, i32 1, i32 7>
+  %2 = shufflevector <4 x float> %b, <4 x float> %1, <4 x i32> <i32 4, i32 5, i32 0, i32 5>
+  ret <4 x float> %2
+}
+; CHECK-LABEL: test13
+; Mask: [0,1,4,u]
+; CHECK: movlhps
+; CHECK: ret
+
+define <4 x float> @test14(<4 x float> %a, <4 x float> %b) {
+  %1 = shufflevector <4 x float> %a, <4 x float> undef, <4 x i32> <i32 2, i32 3, i32 5, i32 5>
+  %2 = shufflevector <4 x float> %b, <4 x float> %1, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
+  ret <4 x float> %2
+}
+; CHECK-LABEL: test14
+; Mask: [6,7,2,3]
+; CHECK: movhlps
+; CHECK-NEXT: ret
+
+define <4 x float> @test15(<4 x float> %a, <4 x float> %b) {
+  %1 = shufflevector <4 x float> %a, <4 x float> undef, <4 x i32> <i32 0, i32 4, i32 1, i32 3>
+  %2 = shufflevector <4 x float> %b, <4 x float> %1, <4 x i32> <i32 4, i32 6, i32 2, i32 3>
+  ret <4 x float> %2
+}
+; CHECK-LABEL: test15
+; Mask: [0,1,6,7]
+; CHECK: blendps $12
+; CHECK: ret
+
+; Verify that shuffles are canonicalized according to rules:
+;  shuffle(B, shuffle(A, Undef)) -> shuffle(shuffle(A, Undef), B)
+;
+; This allows to trigger the following combine rule:
+;  (shuffle(shuffle A, Undef, M0), A, M1) -> (shuffle A, Undef, M2)
+;
+; As a result, all the shuffle pairs in each function below should be
+; combined into a single legal shuffle operation.
+
+define <4 x float> @test16(<4 x float> %a) {
+  %1 = shufflevector <4 x float> %a, <4 x float> undef, <4 x i32> <i32 4, i32 2, i32 3, i32 1>
+  %2 = shufflevector <4 x float> %a, <4 x float> %1, <4 x i32> <i32 0, i32 1, i32 5, i32 3>
+  ret <4 x float> %2
+}
+; CHECK-LABEL: test16
+; Mask: [0,1,2,3]
+; CHECK-NOT: pshufd
+; CHECK-NOT: shufps
+; CHECK-NOT: movlhps
+; CHECK: ret
+
+define <4 x float> @test17(<4 x float> %a) {
+  %1 = shufflevector <4 x float> %a, <4 x float> undef, <4 x i32> <i32 6, i32 0, i32 1, i32 7>
+  %2 = shufflevector <4 x float> %a, <4 x float> %1, <4 x i32> <i32 5, i32 6, i32 0, i32 1>
+  ret <4 x float> %2
+}
+; CHECK-LABEL: test17
+; Mask: [0,1,0,1]
+; CHECK-NOT: pshufd
+; CHECK-NOT: shufps
+; CHECK: movlhps 
+; CHECK-NEXT: ret
+
+define <4 x float> @test18(<4 x float> %a) {
+  %1 = shufflevector <4 x float> %a, <4 x float> undef, <4 x i32> <i32 0, i32 5, i32 1, i32 7>
+  %2 = shufflevector <4 x float> %a, <4 x float> %1, <4 x i32> <i32 4, i32 6, i32 0, i32 5>
+  ret <4 x float> %2
+}
+; CHECK-LABEL: test18
+; Mask: [0,1,0,u]
+; CHECK-NOT: pshufd
+; CHECK-NOT: shufps
+; CHECK: movlhps
+; CHECK-NEXT: ret
+
+define <4 x float> @test19(<4 x float> %a) {
+  %1 = shufflevector <4 x float> %a, <4 x float> undef, <4 x i32> <i32 2, i32 3, i32 5, i32 5>
+  %2 = shufflevector <4 x float> %a, <4 x float> %1, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
+  ret <4 x float> %2
+}
+; CHECK-LABEL: test19
+; Mask: [2,3,2,3]
+; CHECK-NOT: movlhps
+; CHECK-NOT: palignr
+; CHECK: movhlps
+; CHECK-NEXT: ret
+
+define <4 x float> @test20(<4 x float> %a) {
+  %1 = shufflevector <4 x float> %a, <4 x float> undef, <4 x i32> <i32 0, i32 4, i32 1, i32 3>
+  %2 = shufflevector <4 x float> %a, <4 x float> %1, <4 x i32> <i32 4, i32 6, i32 2, i32 3>
+  ret <4 x float> %2
+}
+; CHECK-LABEL: test20
+; Mask: [0,1,2,3]
+; CHECK-NOT: pshufd
+; CHECK-NOT: shufps
+; CHECK-NOT: movlhps
+; CHECK: ret
+

Added: llvm/trunk/test/CodeGen/X86/combine-vec-shuffle-5.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/combine-vec-shuffle-5.ll?rev=213504&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/combine-vec-shuffle-5.ll (added)
+++ llvm/trunk/test/CodeGen/X86/combine-vec-shuffle-5.ll Mon Jul 21 02:30:54 2014
@@ -0,0 +1,257 @@
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7 | FileCheck %s
+
+; Verify that the DAGCombiner correctly folds all the shufflevector pairs
+; into a single shuffle operation.
+
+define <4 x float> @test1(<4 x float> %a, <4 x float> %b) {
+  %1 = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 4, i32 1, i32 6, i32 3>
+  %2 = shufflevector <4 x float> %b, <4 x float> %1, <4 x i32> <i32 4, i32 1, i32 6, i32 3>
+  ret <4 x float> %2
+}
+; CHECK-LABEL: test1
+; Mask: [0,1,2,3]
+; CHECK: movaps
+; CHECK: ret
+
+define <4 x float> @test2(<4 x float> %a, <4 x float> %b) {
+  %1 = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 0, i32 5, i32 2, i32 7>
+  %2 = shufflevector <4 x float> %b, <4 x float> %1, <4 x i32> <i32 4, i32 5, i32 2, i32 7>
+  ret <4 x float> %2
+}
+; CHECK-LABEL: test2
+; Mask: [0,5,6,7]
+; CHECK: movss
+; CHECK: ret
+
+define <4 x float> @test3(<4 x float> %a, <4 x float> %b) {
+  %1 = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 0, i32 5, i32 1, i32 7>
+  %2 = shufflevector <4 x float> %b, <4 x float> %1, <4 x i32> <i32 4, i32 6, i32 0, i32 5>
+  ret <4 x float> %2
+}
+; CHECK-LABEL: test3
+; Mask: [0,1,4,5]
+; CHECK: movlhps
+; CHECK: ret
+
+define <4 x float> @test4(<4 x float> %a, <4 x float> %b) {
+  %1 = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 2, i32 3, i32 5, i32 5>
+  %2 = shufflevector <4 x float> %b, <4 x float> %1, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
+  ret <4 x float> %2
+}
+; CHECK-LABEL: test4
+; Mask: [6,7,2,3]
+; CHECK: movhlps
+; CHECK-NEXT: ret
+
+define <4 x float> @test5(<4 x float> %a, <4 x float> %b) {
+  %1 = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 4, i32 1, i32 6, i32 3>
+  %2 = shufflevector <4 x float> %b, <4 x float> %1, <4 x i32> <i32 4, i32 5, i32 6, i32 3>
+  ret <4 x float> %2
+}
+; CHECK-LABEL: test5
+; Mask: [4,1,6,7]
+; CHECK: blendps $13
+; CHECK: ret
+
+
+define <4 x i32> @test6(<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 3>
+  %2 = shufflevector <4 x i32> %b, <4 x i32> %1, <4 x i32> <i32 4, i32 1, i32 6, i32 3>
+  ret <4 x i32> %2
+}
+; CHECK-LABEL: test6
+; Mask: [4,5,6,7]
+; CHECK: movaps
+; CHECK: ret
+
+define <4 x i32> @test7(<4 x i32> %a, <4 x i32> %b) {
+  %1 = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 5, i32 2, i32 7>
+  %2 = shufflevector <4 x i32> %b, <4 x i32> %1, <4 x i32> <i32 4, i32 5, i32 2, i32 7>
+  ret <4 x i32> %2
+}
+; CHECK-LABEL: test7
+; Mask: [0,5,6,7]
+; CHECK: movss
+; CHECK: ret
+
+define <4 x i32> @test8(<4 x i32> %a, <4 x i32> %b) {
+  %1 = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 5, i32 1, i32 7>
+  %2 = shufflevector <4 x i32> %b, <4 x i32> %1, <4 x i32> <i32 4, i32 6, i32 0, i32 5>
+  ret <4 x i32> %2
+}
+; CHECK-LABEL: test8
+; Mask: [0,1,4,5]
+; CHECK: movlhps
+; CHECK: ret
+
+define <4 x i32> @test9(<4 x i32> %a, <4 x i32> %b) {
+  %1 = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 2, i32 3, i32 5, i32 5>
+  %2 = shufflevector <4 x i32> %b, <4 x i32> %1, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
+  ret <4 x i32> %2
+}
+; CHECK-LABEL: test9
+; Mask: [6,7,2,3]
+; CHECK: movhlps
+; CHECK-NEXT: ret
+
+define <4 x i32> @test10(<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 3>
+  %2 = shufflevector <4 x i32> %b, <4 x i32> %1, <4 x i32> <i32 4, i32 5, i32 6, i32 3>
+  ret <4 x i32> %2
+}
+; CHECK-LABEL: test10
+; Mask: [4,1,6,7]
+; CHECK: blendps
+; CHECK: ret
+
+define <4 x float> @test11(<4 x float> %a, <4 x float> %b) {
+  %1 = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 4, i32 1, i32 6, i32 3>
+  %2 = shufflevector <4 x float> %a, <4 x float> %1, <4 x i32> <i32 0, i32 5, i32 2, i32 7>
+  ret <4 x float> %2
+}
+; CHECK-LABEL: test11
+; Mask: [0,1,2,3]
+; CHECK-NOT: movaps
+; CHECK-NOT: blendps
+; CHECK: ret
+
+define <4 x float> @test12(<4 x float> %a, <4 x float> %b) {
+  %1 = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 0, i32 5, i32 6, i32 7>
+  %2 = shufflevector <4 x float> %a, <4 x float> %1, <4 x i32> <i32 0, i32 5, i32 6, i32 7>
+  ret <4 x float> %2
+}
+; CHECK-LABEL: test12
+; Mask: [0,5,6,7]
+; CHECK: movss
+; CHECK: ret
+
+define <4 x float> @test13(<4 x float> %a, <4 x float> %b) {
+  %1 = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+  %2 = shufflevector <4 x float> %a, <4 x float> %1, <4 x i32> <i32 0, i32 1, i32 6, i32 7>
+  ret <4 x float> %2
+}
+; CHECK-LABEL: test13
+; Mask: [0,1,4,5]
+; CHECK: movlhps
+; CHECK: ret
+
+define <4 x float> @test14(<4 x float> %a, <4 x float> %b) {
+  %1 = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 6, i32 7, i32 5, i32 5>
+  %2 = shufflevector <4 x float> %a, <4 x float> %1, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
+  ret <4 x float> %2
+}
+; CHECK-LABEL: test14
+; Mask: [6,7,2,3]
+; CHECK: movhlps
+; CHECK: ret
+
+define <4 x float> @test15(<4 x float> %a, <4 x float> %b) {
+  %1 = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 4, i32 1, i32 6, i32 7>
+  %2 = shufflevector <4 x float> %a, <4 x float> %1, <4 x i32> <i32 4, i32 1, i32 6, i32 7>
+  ret <4 x float> %2
+}
+; CHECK-LABEL: test15
+; Mask: [4,1,6,7]
+; CHECK: blendps $13
+; CHECK: ret
+
+define <4 x i32> @test16(<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 3>
+  %2 = shufflevector <4 x i32> %a, <4 x i32> %1, <4 x i32> <i32 0, i32 5, i32 2, i32 7>
+  ret <4 x i32> %2
+}
+; CHECK-LABEL: test16
+; Mask: [0,1,2,3]
+; CHECK-NOT: movaps
+; CHECK-NOT: blendps
+; CHECK: ret
+
+define <4 x i32> @test17(<4 x i32> %a, <4 x i32> %b) {
+  %1 = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 5, i32 6, i32 7>
+  %2 = shufflevector <4 x i32> %a, <4 x i32> %1, <4 x i32> <i32 0, i32 5, i32 6, i32 7>
+  ret <4 x i32> %2
+}
+; CHECK-LABEL: test17
+; Mask: [0,5,6,7]
+; CHECK: movss
+; CHECK: ret
+
+define <4 x i32> @test18(<4 x i32> %a, <4 x i32> %b) {
+  %1 = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+  %2 = shufflevector <4 x i32> %a, <4 x i32> %1, <4 x i32> <i32 0, i32 1, i32 6, i32 7>
+  ret <4 x i32> %2
+}
+; CHECK-LABEL: test18
+; Mask: [0,1,4,5]
+; CHECK: movlhps
+; CHECK: ret
+
+define <4 x i32> @test19(<4 x i32> %a, <4 x i32> %b) {
+  %1 = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 6, i32 7, i32 5, i32 5>
+  %2 = shufflevector <4 x i32> %a, <4 x i32> %1, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
+  ret <4 x i32> %2
+}
+; CHECK-LABEL: test19
+; Mask: [6,7,2,3]
+; CHECK: movhlps
+; CHECK: ret
+
+define <4 x i32> @test20(<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> %a, <4 x i32> %1, <4 x i32> <i32 4, i32 1, i32 6, i32 7>
+  ret <4 x i32> %2
+}
+; CHECK-LABEL: test20
+; Mask: [4,1,6,7]
+; CHECK: blendps $13
+; CHECK: ret
+
+; Verify that we correctly fold shuffles even when we use illegal vector types.
+define <4 x i8> @test1c(<4 x i8>* %a, <4 x i8>* %b) {
+  %A = load <4 x i8>* %a
+  %B = load <4 x i8>* %b
+  %1 = shufflevector <4 x i8> %A, <4 x i8> %B, <4 x i32> <i32 0, i32 5, i32 2, i32 7>
+  %2 = shufflevector <4 x i8> %B, <4 x i8> %1, <4 x i32> <i32 4, i32 5, i32 2, i32 7>
+  ret <4 x i8> %2
+}
+; CHECK-LABEL: test1c
+; Mask: [0,5,6,7]
+; CHECK: movss
+; CHECK-NEXT: ret
+
+define <4 x i8> @test2c(<4 x i8>* %a, <4 x i8>* %b) {
+  %A = load <4 x i8>* %a
+  %B = load <4 x i8>* %b
+  %1 = shufflevector <4 x i8> %A, <4 x i8> %B, <4 x i32> <i32 0, i32 5, i32 1, i32 5>
+  %2 = shufflevector <4 x i8> %B, <4 x i8> %1, <4 x i32> <i32 4, i32 6, i32 0, i32 5>
+  ret <4 x i8> %2
+}
+; CHECK-LABEL: test2c
+; Mask: [0,1,4,5]
+; CHECK: movlhps
+; CHECK-NEXT: ret
+
+define <4 x i8> @test3c(<4 x i8>* %a, <4 x i8>* %b) {
+  %A = load <4 x i8>* %a
+  %B = load <4 x i8>* %b
+  %1 = shufflevector <4 x i8> %A, <4 x i8> %B, <4 x i32> <i32 2, i32 3, i32 5, i32 5>
+  %2 = shufflevector <4 x i8> %B, <4 x i8> %1, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
+  ret <4 x i8> %2
+}
+; CHECK-LABEL: test3c
+; Mask: [6,7,2,3]
+; CHECK: movhlps
+; CHECK: ret
+
+define <4 x i8> @test4c(<4 x i8>* %a, <4 x i8>* %b) {
+  %A = load <4 x i8>* %a
+  %B = load <4 x i8>* %b
+  %1 = shufflevector <4 x i8> %A, <4 x i8> %B, <4 x i32> <i32 4, i32 1, i32 6, i32 3>
+  %2 = shufflevector <4 x i8> %B, <4 x i8> %1, <4 x i32> <i32 4, i32 5, i32 6, i32 3>
+  ret <4 x i8> %2
+}
+; CHECK-LABEL: test4c
+; Mask: [4,1,6,7]
+; CHECK: blendps $13
+; CHECK: ret
+





More information about the llvm-commits mailing list