Teach the DAG combiner to fold a splat of a splat. Radar 8597790.
authorBob Wilson <bob.wilson@apple.com>
Thu, 28 Oct 2010 17:06:14 +0000 (17:06 +0000)
committerBob Wilson <bob.wilson@apple.com>
Thu, 28 Oct 2010 17:06:14 +0000 (17:06 +0000)
Also do some minor refactoring to reduce indentation.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@117558 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/SelectionDAG/DAGCombiner.cpp
test/CodeGen/ARM/vmla.ll

index 35e1f27df592787b063748b36dc020519aa98804..d09ae2d20efe3c42ff82b35578feca9a9a920282 100644 (file)
@@ -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<ShuffleVectorSDNode>(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<ShuffleVectorSDNode>(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<ShuffleVectorSDNode>(V);
+    if (SVV && SVV->isSplat())
+      return N0;
+
     if (V->getOpcode() == ISD::BUILD_VECTOR) {
-      unsigned NumElems = V->getNumOperands();
-      unsigned BaseIdx = cast<ShuffleVectorSDNode>(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 <u, u, u, u>, return <u, u, u, u>
-        if (!Base.getNode())
-          return N0;
-        for (unsigned i = 0; i != NumElems; ++i) {
-          if (V->getOperand(i) != Base) {
-            AllSame = false;
-            break;
-          }
+      }
+      // Splat of <u, u, u, u>, return <u, u, u, u>
+      if (!Base.getNode())
+        return N0;
+      for (unsigned i = 0; i != NumElts; ++i) {
+        if (V->getOperand(i) != Base) {
+          AllSame = false;
+          break;
         }
-        // Splat of <x, x, x, x>, return <x, x, x, x>
-        if (AllSame)
-          return N0;
       }
+      // Splat of <x, x, x, x>, return <x, x, x, x>
+      if (AllSame)
+        return N0;
     }
   }
   return SDValue();
index 9c6b210be797698c85550e9b26e33da682731df6..1f76d7377f559c43a9685ef8f6c177f84a5702ab 100644 (file)
@@ -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> <i32 1, i32 undef, i32 undef, i32 undef>
+  %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
+}