[llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp

Chris Lattner lattner at cs.uiuc.edu
Thu May 25 17:29:18 PDT 2006



Changes in directory llvm/lib/Transforms/Scalar:

InstructionCombining.cpp updated: 1.486 -> 1.487
---
Log message:

Transform things like (splat(splat)) -> splat


---
Diffs of the changes:  (+50 -4)

 InstructionCombining.cpp |   54 +++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 50 insertions(+), 4 deletions(-)


Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.486 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.487
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.486	Thu May 25 18:48:38 2006
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp	Thu May 25 19:29:06 2006
@@ -7398,18 +7398,26 @@
     // Remap any references to RHS to use LHS.
     std::vector<Constant*> Elts;
     for (unsigned i = 0, e = Mask.size(); i != e; ++i) {
-      if (Mask[i] > 2*e)
+      if (Mask[i] >= 2*e)
         Elts.push_back(UndefValue::get(Type::UIntTy));
-      else
-        Elts.push_back(ConstantUInt::get(Type::UIntTy, Mask[i] & (e-1)));
+      else {
+        if ((Mask[i] >= e && isa<UndefValue>(RHS)) ||
+            (Mask[i] <  e && isa<UndefValue>(LHS)))
+          Mask[i] = 2*e;     // Turn into undef.
+        else
+          Mask[i] &= (e-1);  // Force to LHS.
+        Elts.push_back(ConstantUInt::get(Type::UIntTy, Mask[i]));
+      }
     }
     SVI.setOperand(0, SVI.getOperand(1));
     SVI.setOperand(1, UndefValue::get(RHS->getType()));
     SVI.setOperand(2, ConstantPacked::get(Elts));
+    LHS = SVI.getOperand(0);
+    RHS = SVI.getOperand(1);
     MadeChange = true;
   }
   
-  // Analyze the shuffle, are the LHS or RHS and identity shuffle?
+  // Analyze the shuffle, are the LHS or RHS and identity shuffles?
   bool isLHSID = true, isRHSID = true;
     
   for (unsigned i = 0, e = Mask.size(); i != e; ++i) {
@@ -7425,6 +7433,44 @@
   if (isLHSID) return ReplaceInstUsesWith(SVI, LHS);
   if (isRHSID) return ReplaceInstUsesWith(SVI, RHS);
   
+  // If the LHS is a shufflevector itself, see if we can combine it with this
+  // one without producing an unusual shuffle.  Here we are really conservative:
+  // 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.
+  if (ShuffleVectorInst *LHSSVI = dyn_cast<ShuffleVectorInst>(LHS)) {
+    if (isa<UndefValue>(RHS)) {
+      std::vector<unsigned> LHSMask = getShuffleMask(LHSSVI);
+
+      std::vector<unsigned> NewMask;
+      for (unsigned i = 0, e = Mask.size(); i != e; ++i)
+        if (Mask[i] >= 2*e)
+          NewMask.push_back(2*e);
+        else
+          NewMask.push_back(LHSMask[Mask[i]]);
+      
+      // If the result mask is equal to the src shuffle or this shuffle mask, do
+      // the replacement.
+      if (NewMask == LHSMask || NewMask == Mask) {
+        std::vector<Constant*> Elts;
+        for (unsigned i = 0, e = NewMask.size(); i != e; ++i) {
+          if (NewMask[i] >= e*2) {
+            Elts.push_back(UndefValue::get(Type::UIntTy));
+          } else {
+            Elts.push_back(ConstantUInt::get(Type::UIntTy, NewMask[i]));
+          }
+        }
+        return new ShuffleVectorInst(LHSSVI->getOperand(0),
+                                     LHSSVI->getOperand(1),
+                                     ConstantPacked::get(Elts));
+      }
+    }
+  }
+  
   return MadeChange ? &SVI : 0;
 }
 






More information about the llvm-commits mailing list