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

Chris Lattner sabre at nondot.org
Fri Mar 2 21:27:51 PST 2007



Changes in directory llvm/lib/Transforms/Scalar:

InstructionCombining.cpp updated: 1.641 -> 1.642
---
Log message:

my recent change caused a failure in a bswap testcase, because it changed
the order that instcombine processed instructions in the testcase.  The end
result is that instcombine finished with:

define i16 @test1(i16 %a) {
        %tmp = zext i16 %a to i32               ; <i32> [#uses=2]
        %tmp21 = lshr i32 %tmp, 8               ; <i32> [#uses=1]
        %tmp5 = shl i32 %tmp, 8         ; <i32> [#uses=1]
        %tmp.upgrd.32 = or i32 %tmp21, %tmp5            ; <i32> [#uses=1]
        %tmp.upgrd.3 = trunc i32 %tmp.upgrd.32 to i16           ; <i16> [#uses=1]
        ret i16 %tmp.upgrd.3
}

which can't get matched as a bswap.

This patch makes instcombine more sophisticated about removing truncating
casts, allowing it to turn this into:

define i16 @test2(i16 %a) {
        %tmp211 = lshr i16 %a, 8
        %tmp52 = shl i16 %a, 8
        %tmp.upgrd.323 = or i16 %tmp211, %tmp52
        ret i16 %tmp.upgrd.323
}

which then matches as bswap.  This fixes bswap.ll and implements 
InstCombine/cast2.ll:test[12].  This also implements cast elimination of
add/sub.



---
Diffs of the changes:  (+71 -48)

 InstructionCombining.cpp |  119 ++++++++++++++++++++++++++++-------------------
 1 files changed, 71 insertions(+), 48 deletions(-)


Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.641 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.642
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.641	Fri Mar  2 20:04:50 2007
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp	Fri Mar  2 23:27:34 2007
@@ -5908,35 +5908,62 @@
 }
 
 /// CanEvaluateInDifferentType - Return true if we can take the specified value
-/// and return it without inserting any new casts.  This is used by code that
-/// tries to decide whether promoting or shrinking integer operations to wider
-/// or smaller types will allow us to eliminate a truncate or extend.
-static bool CanEvaluateInDifferentType(Value *V, const Type *Ty,
+/// and return it as type Ty without inserting any new casts and without
+/// changing the computed value.  This is used by code that tries to decide
+/// whether promoting or shrinking integer operations to wider or smaller types
+/// will allow us to eliminate a truncate or extend.
+///
+/// This is a truncation operation if Ty is smaller than V->getType(), or an
+/// extension operation if Ty is larger.
+static bool CanEvaluateInDifferentType(Value *V, const IntegerType *Ty,
                                        int &NumCastsRemoved) {
-  if (isa<Constant>(V)) return true;
+  // We can always evaluate constants in another type.
+  if (isa<ConstantInt>(V))
+    return true;
   
   Instruction *I = dyn_cast<Instruction>(V);
-  if (!I || !I->hasOneUse()) return false;
+  if (!I) return false;
+  
+  const IntegerType *OrigTy = cast<IntegerType>(V->getType());
   
   switch (I->getOpcode()) {
+  case Instruction::Add:
+  case Instruction::Sub:
   case Instruction::And:
   case Instruction::Or:
   case Instruction::Xor:
+    if (!I->hasOneUse()) return false;
     // These operators can all arbitrarily be extended or truncated.
     return CanEvaluateInDifferentType(I->getOperand(0), Ty, NumCastsRemoved) &&
            CanEvaluateInDifferentType(I->getOperand(1), Ty, NumCastsRemoved);
-  case Instruction::AShr:
-  case Instruction::LShr:
+
   case Instruction::Shl:
-    // If this is just a bitcast changing the sign of the operation, we can
-    // convert if the operand can be converted.
-    if (V->getType()->getPrimitiveSizeInBits() == Ty->getPrimitiveSizeInBits())
-      return CanEvaluateInDifferentType(I->getOperand(0), Ty, NumCastsRemoved);
+    if (!I->hasOneUse()) return false;
+    // If we are truncating the result of this SHL, and if it's a shift of a
+    // constant amount, we can always perform a SHL in a smaller type.
+    if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1))) {
+      if (Ty->getBitWidth() < OrigTy->getBitWidth() &&
+          CI->getZExtValue() < Ty->getBitWidth())
+        return CanEvaluateInDifferentType(I->getOperand(0), Ty,NumCastsRemoved);
+    }
+    break;
+  case Instruction::LShr:
+    if (!I->hasOneUse()) return false;
+    // If this is a truncate of a logical shr, we can truncate it to a smaller
+    // lshr iff we know that the bits we would otherwise be shifting in are
+    // already zeros.
+    if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1))) {
+      if (Ty->getBitWidth() < OrigTy->getBitWidth() &&
+          MaskedValueIsZero(I->getOperand(0),
+                            OrigTy->getBitMask() & ~Ty->getBitMask()) &&
+          CI->getZExtValue() < Ty->getBitWidth()) {
+        return CanEvaluateInDifferentType(I->getOperand(0), Ty, NumCastsRemoved);
+      }
+    }
     break;
   case Instruction::Trunc:
   case Instruction::ZExt:
   case Instruction::SExt:
-  case Instruction::BitCast:
     // If this is a cast from the destination type, we can trivially eliminate
     // it, and this will remove a cast overall.
     if (I->getOperand(0)->getType() == Ty) {
@@ -5962,7 +5989,7 @@
 /// CanEvaluateInDifferentType returns true for, actually insert the code to
 /// evaluate the expression.
 Value *InstCombiner::EvaluateInDifferentType(Value *V, const Type *Ty, 
-                                             bool isSigned ) {
+                                             bool isSigned) {
   if (Constant *C = dyn_cast<Constant>(V))
     return ConstantExpr::getIntegerCast(C, Ty, isSigned /*Sext or ZExt*/);
 
@@ -5970,21 +5997,18 @@
   Instruction *I = cast<Instruction>(V);
   Instruction *Res = 0;
   switch (I->getOpcode()) {
+  case Instruction::Add:
+  case Instruction::Sub:
   case Instruction::And:
   case Instruction::Or:
-  case Instruction::Xor: {
-    Value *LHS = EvaluateInDifferentType(I->getOperand(0), Ty, isSigned);
-    Value *RHS = EvaluateInDifferentType(I->getOperand(1), Ty, isSigned);
-    Res = BinaryOperator::create((Instruction::BinaryOps)I->getOpcode(),
-                                 LHS, RHS, I->getName());
-    break;
-  }
+  case Instruction::Xor:
   case Instruction::AShr:
   case Instruction::LShr:
   case Instruction::Shl: {
     Value *LHS = EvaluateInDifferentType(I->getOperand(0), Ty, isSigned);
-    Res = BinaryOperator::create(Instruction::BinaryOps(I->getOpcode()), LHS, 
-                                 I->getOperand(1), I->getName());
+    Value *RHS = EvaluateInDifferentType(I->getOperand(1), Ty, isSigned);
+    Res = BinaryOperator::create((Instruction::BinaryOps)I->getOpcode(),
+                                 LHS, RHS, I->getName());
     break;
   }    
   case Instruction::Trunc:
@@ -6066,8 +6090,8 @@
   return 0;
 }
 
-/// Only the TRUNC, ZEXT, SEXT, and BITCONVERT can have both operands as
-/// integers. This function implements the common transforms for all those
+/// Only the TRUNC, ZEXT, SEXT, and BITCAST can both operand and result as
+/// integer types. This function implements the common transforms for all those
 /// cases.
 /// @brief Implement the transforms common to CastInst with integer operands
 Instruction *InstCombiner::commonIntCastTransforms(CastInst &CI) {
@@ -6093,9 +6117,11 @@
   if (!SrcI || !Src->hasOneUse())
     return 0;
 
-  // Attempt to propagate the cast into the instruction.
+  // Attempt to propagate the cast into the instruction for int->int casts.
   int NumCastsRemoved = 0;
-  if (CanEvaluateInDifferentType(SrcI, DestTy, NumCastsRemoved)) {
+  if (!isa<BitCastInst>(CI) &&
+      CanEvaluateInDifferentType(SrcI, cast<IntegerType>(DestTy),
+                                 NumCastsRemoved)) {
     // If this cast is a truncate, evaluting in a different type always
     // eliminates the cast, so it is always a win.  If this is a noop-cast
     // this just removes a noop cast which isn't pointful, but simplifies
@@ -6104,27 +6130,24 @@
     // the input have eliminated at least one cast.  If this is a sign
     // extension, we insert two new casts (to do the extension) so we
     // require that two casts have been eliminated.
-    bool DoXForm = CI.isNoopCast(TD->getIntPtrType());
-    if (!DoXForm) {
-      switch (CI.getOpcode()) {
-        case Instruction::Trunc:
-          DoXForm = true;
-          break;
-        case Instruction::ZExt:
-          DoXForm = NumCastsRemoved >= 1;
-          break;
-        case Instruction::SExt:
-          DoXForm = NumCastsRemoved >= 2;
-          break;
-        case Instruction::BitCast:
-          DoXForm = false;
-          break;
-        default:
-          // All the others use floating point so we shouldn't actually 
-          // get here because of the check above.
-          assert(!"Unknown cast type .. unreachable");
-          break;
-      }
+    bool DoXForm;
+    switch (CI.getOpcode()) {
+    default:
+      // All the others use floating point so we shouldn't actually 
+      // get here because of the check above.
+      assert(0 && "Unknown cast type");
+    case Instruction::Trunc:
+      DoXForm = true;
+      break;
+    case Instruction::ZExt:
+      DoXForm = NumCastsRemoved >= 1;
+      break;
+    case Instruction::SExt:
+      DoXForm = NumCastsRemoved >= 2;
+      break;
+    case Instruction::BitCast:
+      DoXForm = false;
+      break;
     }
     
     if (DoXForm) {






More information about the llvm-commits mailing list