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

Chris Lattner lattner at cs.uiuc.edu
Thu Jan 5 23:52:24 PST 2006



Changes in directory llvm/lib/Transforms/Scalar:

InstructionCombining.cpp updated: 1.408 -> 1.409
---
Log message:

Enhance the shift-shift folding code to allow a no-op cast to occur in between
the shifts.

This allows us to fold this (which is the 'integer add a constant' sequence
from cozmic's scheme compmiler):

int %x(uint %anf-temporary776) {
        %anf-temporary777 = shr uint %anf-temporary776, ubyte 1        
        %anf-temporary800 = cast uint %anf-temporary777 to int          
        %anf-temporary804 = shl int %anf-temporary800, ubyte 1        
        %anf-temporary805 = add int %anf-temporary804, -2            
        %anf-temporary806 = or int %anf-temporary805, 1         
        ret int %anf-temporary806
}

into this:

int %x(uint %anf-temporary776) {
        %anf-temporary776 = cast uint %anf-temporary776 to int          
        %anf-temporary776.mask1 = add int %anf-temporary776, -2        
        %anf-temporary805 = or int %anf-temporary776.mask1, 1         
        ret int %anf-temporary805
}

note that instcombine already knew how to eliminate the AND that the two 
shifts fold into.  This is tested by InstCombine/shift.ll:test26

-Chris



---
Diffs of the changes:  (+88 -55)

 InstructionCombining.cpp |  143 ++++++++++++++++++++++++++++-------------------
 1 files changed, 88 insertions(+), 55 deletions(-)


Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.408 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.409
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.408	Fri Jan  6 01:22:22 2006
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp	Fri Jan  6 01:52:12 2006
@@ -3648,68 +3648,101 @@
     }
   }
   
-  // If this is a shift of a shift, see if we can fold the two together.
+  // Find out if this is a shift of a shift by a constant.
+  ShiftInst *ShiftOp = 0;
   if (ShiftInst *Op0SI = dyn_cast<ShiftInst>(Op0))
-    if (ConstantUInt *ShiftAmt1C =
-        dyn_cast<ConstantUInt>(Op0SI->getOperand(1))) {
-      unsigned ShiftAmt1 = (unsigned)ShiftAmt1C->getValue();
-      unsigned ShiftAmt2 = (unsigned)Op1->getValue();
+    ShiftOp = Op0SI;
+  else if (CastInst *CI = dyn_cast<CastInst>(Op0)) {
+    // If this is a noop-integer case of a shift instruction, use the shift.
+    if (CI->getOperand(0)->getType()->isInteger() &&
+        CI->getOperand(0)->getType()->getPrimitiveSizeInBits() ==
+        CI->getType()->getPrimitiveSizeInBits() &&
+        isa<ShiftInst>(CI->getOperand(0))) {
+      ShiftOp = cast<ShiftInst>(CI->getOperand(0));
+    }
+  }
+  
+  if (ShiftOp && isa<ConstantUInt>(ShiftOp->getOperand(1))) {
+    // Find the operands and properties of the input shift.  Note that the
+    // signedness of the input shift may differ from the current shift if there
+    // is a noop cast between the two.
+    bool isShiftOfLeftShift = ShiftOp->getOpcode() == Instruction::Shl;
+    bool isShiftOfSignedShift = ShiftOp->getType()->isSigned();
+    bool isShiftOfUnsignedShift = !isSignedShift;
+    
+    ConstantUInt *ShiftAmt1C = cast<ConstantUInt>(ShiftOp->getOperand(1));
+
+    unsigned ShiftAmt1 = (unsigned)ShiftAmt1C->getValue();
+    unsigned ShiftAmt2 = (unsigned)Op1->getValue();
+    
+    // Check for (A << c1) << c2   and   (A >> c1) >> c2.
+    if (isLeftShift == isShiftOfLeftShift) {
+      // Do not fold these shifts if the first one is signed and the second one
+      // is unsigned and this is a right shift.  Further, don't do any folding
+      // on them.
+      if (isShiftOfSignedShift && isUnsignedShift && !isLeftShift)
+        return 0;
       
-      // Check for (A << c1) << c2   and   (A >> c1) >> c2
-      if (I.getOpcode() == Op0SI->getOpcode()) {
-        unsigned Amt = ShiftAmt1+ShiftAmt2;   // Fold into one big shift.
-        if (Op0->getType()->getPrimitiveSizeInBits() < Amt)
-          Amt = Op0->getType()->getPrimitiveSizeInBits();
-        return new ShiftInst(I.getOpcode(), Op0SI->getOperand(0),
-                             ConstantUInt::get(Type::UByteTy, Amt));
-      }
+      unsigned Amt = ShiftAmt1+ShiftAmt2;   // Fold into one big shift.
+      if (Amt > Op0->getType()->getPrimitiveSizeInBits())
+        Amt = Op0->getType()->getPrimitiveSizeInBits();
       
-      // Check for (A << c1) >> c2 or visaversa.  If we are dealing with
-      // signed types, we can only support the (A >> c1) << c2 configuration,
-      // because it can not turn an arbitrary bit of A into a sign bit.
-      if (isUnsignedShift || isLeftShift) {
-        // Calculate bitmask for what gets shifted off the edge...
-        Constant *C = ConstantIntegral::getAllOnesValue(I.getType());
-        if (isLeftShift)
-          C = ConstantExpr::getShl(C, ShiftAmt1C);
-        else
-          C = ConstantExpr::getShr(C, ShiftAmt1C);
-        
-        Instruction *Mask =
-          BinaryOperator::createAnd(Op0SI->getOperand(0), C,
-                                    Op0SI->getOperand(0)->getName()+".mask");
-        InsertNewInstBefore(Mask, I);
-        
-        // Figure out what flavor of shift we should use...
-        if (ShiftAmt1 == ShiftAmt2)
-          return ReplaceInstUsesWith(I, Mask);  // (A << c) >> c  === A & c2
-        else if (ShiftAmt1 < ShiftAmt2) {
-          return new ShiftInst(I.getOpcode(), Mask,
-                               ConstantUInt::get(Type::UByteTy, ShiftAmt2-ShiftAmt1));
-        } else {
-          return new ShiftInst(Op0SI->getOpcode(), Mask,
-                               ConstantUInt::get(Type::UByteTy, ShiftAmt1-ShiftAmt2));
-        }
+      Value *Op = ShiftOp->getOperand(0);
+      if (isShiftOfSignedShift != isSignedShift)
+        Op = InsertNewInstBefore(new CastInst(Op, I.getType(), "tmp"), I);
+      return new ShiftInst(I.getOpcode(), Op,
+                           ConstantUInt::get(Type::UByteTy, Amt));
+    }
+    
+    // Check for (A << c1) >> c2 or (A >> c1) << c2.  If we are dealing with
+    // signed types, we can only support the (A >> c1) << c2 configuration,
+    // because it can not turn an arbitrary bit of A into a sign bit.
+    if (isUnsignedShift || isLeftShift) {
+      // Calculate bitmask for what gets shifted off the edge.
+      Constant *C = ConstantIntegral::getAllOnesValue(I.getType());
+      if (isLeftShift)
+        C = ConstantExpr::getShl(C, ShiftAmt1C);
+      else
+        C = ConstantExpr::getShr(C, ShiftAmt1C); // must be an unsigned shr.
+      
+      Value *Op = ShiftOp->getOperand(0);
+      if (isShiftOfSignedShift != isSignedShift)
+        Op = InsertNewInstBefore(new CastInst(Op, I.getType(),Op->getName()),I);
+      
+      Instruction *Mask =
+        BinaryOperator::createAnd(Op, C, Op->getName()+".mask");
+      InsertNewInstBefore(Mask, I);
+      
+      // Figure out what flavor of shift we should use...
+      if (ShiftAmt1 == ShiftAmt2)
+        return ReplaceInstUsesWith(I, Mask);  // (A << c) >> c  === A & c2
+      else if (ShiftAmt1 < ShiftAmt2) {
+        return new ShiftInst(I.getOpcode(), Mask,
+                         ConstantUInt::get(Type::UByteTy, ShiftAmt2-ShiftAmt1));
       } else {
-        // We can handle signed (X << C1) >> C2 if it's a sign extend.  In
-        // this case, C1 == C2 and C1 is 8, 16, or 32.
-        if (ShiftAmt1 == ShiftAmt2) {
-          const Type *SExtType = 0;
-          switch (ShiftAmt1) {
-          case 8 : SExtType = Type::SByteTy; break;
-          case 16: SExtType = Type::ShortTy; break;
-          case 32: SExtType = Type::IntTy; break;
-          }
-          
-          if (SExtType) {
-            Instruction *NewTrunc = new CastInst(Op0SI->getOperand(0),
-                                                 SExtType, "sext");
-            InsertNewInstBefore(NewTrunc, I);
-            return new CastInst(NewTrunc, I.getType());
-          }
+        return new ShiftInst(ShiftOp->getOpcode(), Mask,
+                         ConstantUInt::get(Type::UByteTy, ShiftAmt1-ShiftAmt2));
+      }
+    } else {
+      // We can handle signed (X << C1) >> C2 if it's a sign extend.  In
+      // this case, C1 == C2 and C1 is 8, 16, or 32.
+      if (ShiftAmt1 == ShiftAmt2) {
+        const Type *SExtType = 0;
+        switch (ShiftAmt1) {
+        case 8 : SExtType = Type::SByteTy; break;
+        case 16: SExtType = Type::ShortTy; break;
+        case 32: SExtType = Type::IntTy; break;
+        }
+        
+        if (SExtType) {
+          Instruction *NewTrunc = new CastInst(ShiftOp->getOperand(0),
+                                               SExtType, "sext");
+          InsertNewInstBefore(NewTrunc, I);
+          return new CastInst(NewTrunc, I.getType());
         }
       }
     }
+  }
   return 0;
 }
 






More information about the llvm-commits mailing list