Make instcombine a little more aggressive in combining vector shuffles.
authorBob Wilson <bob.wilson@apple.com>
Fri, 29 Oct 2010 22:02:50 +0000 (22:02 +0000)
committerBob Wilson <bob.wilson@apple.com>
Fri, 29 Oct 2010 22:02:50 +0000 (22:02 +0000)
Allow splats even if they don't match either of the original shuffles,
possibly due to undef entries in the shuffles masks.  Radar 8597790.
Also fix some 80-column violations.

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

lib/Transforms/InstCombine/InstCombineVectorOps.cpp
test/Transforms/InstCombine/vec_shuffle.ll

index a58124d7032e0c046a00e3f389146270ae641939..634add86a81cd785fd256fef1f7b4f463b81f5a8 100644 (file)
@@ -515,37 +515,44 @@ Instruction *InstCombiner::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
   // we are absolutely afraid of producing a shuffle mask not in the input
   // program, because the code gen may not be smart enough to turn a merged
   // shuffle into two specific shuffles: it may produce worse code.  As such,
-  // we only merge two shuffles if the result is one of the two input shuffle
-  // masks.  In this case, merging the shuffles just removes one instruction,
-  // which we know is safe.  This is good for things like turning:
-  // (splat(splat)) -> splat.
+  // we only merge two shuffles if the result is either a splat or one of the
+  // two input shuffle masks.  In this case, merging the shuffles just removes
+  // one instruction, which we know is safe.  This is good for things like
+  // turning: (splat(splat)) -> splat.
   if (ShuffleVectorInst *LHSSVI = dyn_cast<ShuffleVectorInst>(LHS)) {
     if (isa<UndefValue>(RHS)) {
       std::vector<unsigned> LHSMask = getShuffleMask(LHSSVI);
       
       if (LHSMask.size() == Mask.size()) {
         std::vector<unsigned> NewMask;
-        for (unsigned i = 0, e = Mask.size(); i != e; ++i)
-          if (Mask[i] >= e)
-            NewMask.push_back(2*e);
-          else
-            NewMask.push_back(LHSMask[Mask[i]]);
+        bool isSplat = true;
+        unsigned SplatElt = 2 * Mask.size(); // undef
+        for (unsigned i = 0, e = Mask.size(); i != e; ++i) {
+          unsigned MaskElt = 2 * e; // undef
+          if (Mask[i] < e)
+            MaskElt = LHSMask[Mask[i]];
+          // Check if this could still be a splat.
+          if (MaskElt < 2*e) {
+            if (SplatElt < 2*e && SplatElt != MaskElt)
+              isSplat = false;
+            SplatElt = MaskElt;
+          }
+          NewMask.push_back(MaskElt);
+        }
         
         // If the result mask is equal to the src shuffle or this
         // shuffle mask, do the replacement.
-        if (NewMask == LHSMask || NewMask == Mask) {
+        if (isSplat || NewMask == LHSMask || NewMask == Mask) {
           unsigned LHSInNElts =
           cast<VectorType>(LHSSVI->getOperand(0)->getType())->
           getNumElements();
           std::vector<Constant*> Elts;
+          const Type *Int32Ty = Type::getInt32Ty(SVI.getContext());
           for (unsigned i = 0, e = NewMask.size(); i != e; ++i) {
             if (NewMask[i] >= LHSInNElts*2) {
-              Elts.push_back(UndefValue::get(
-                                             Type::getInt32Ty(SVI.getContext())));
+              Elts.push_back(UndefValue::get(Int32Ty));
             } else {
-              Elts.push_back(ConstantInt::get(
-                                              Type::getInt32Ty(SVI.getContext()),
-                                              NewMask[i]));
+              Elts.push_back(ConstantInt::get(Int32Ty, NewMask[i]));
             }
           }
           return new ShuffleVectorInst(LHSSVI->getOperand(0),
index 5132a8ff9bd14548fe920bc35d9abdc08fcea1fa..d4977fb807edf4fd789776f269bcf656b27ed9d3 100644 (file)
@@ -87,3 +87,13 @@ define <4 x i8> @test9(<16 x i8> %tmp6) nounwind {
        %tmp9 = shufflevector <4 x i8> %tmp7, <4 x i8> undef, <4 x i32> < i32 3, i32 1, i32 2, i32 0 >          ; <<4 x i8>> [#uses=1]
        ret <4 x i8> %tmp9
 }
+
+; Redundant vector splats should be removed.  Radar 8597790.
+define <4 x i32> @test10(<4 x i32> %tmp5) nounwind {
+; CHECK: @test10
+; CHECK-NEXT: shufflevector
+; CHECK-NEXT: ret
+  %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
+  ret <4 x i32> %tmp7
+}