Fix bug: test/Regression/Transforms/InstCombine/2002-08-02-CastTest.ll
authorChris Lattner <sabre@nondot.org>
Fri, 2 Aug 2002 20:00:25 +0000 (20:00 +0000)
committerChris Lattner <sabre@nondot.org>
Fri, 2 Aug 2002 20:00:25 +0000 (20:00 +0000)
Implement feature: Cast's can now be converted to bitwise AND expressions.

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

lib/Transforms/Scalar/InstructionCombining.cpp

index 3d7e4f87afe226730df67f84f982a50922c63cac..494666129887508d84f73a390e14fb5fa484d849 100644 (file)
@@ -404,14 +404,29 @@ static inline bool isEliminableCastOfCast(const CastInst &CI,
   const Type *MidTy = CSrc->getType();
   const Type *DstTy = CI.getType();
 
-  // It is legal to eliminate the instruction if casting A->B->A
-  if (SrcTy == DstTy) return true;
+  // It is legal to eliminate the instruction if casting A->B->A if the sizes
+  // are identical and the bits don't get reinterpreted (for example 
+  // int->float->int)
+  if (SrcTy == DstTy && SrcTy->isLosslesslyConvertableTo(MidTy))
+    return true;
 
   // Allow free casting and conversion of sizes as long as the sign doesn't
   // change...
-  if (SrcTy->isSigned() == MidTy->isSigned() &&
-      MidTy->isSigned() == DstTy->isSigned())
-    return true;
+  if (SrcTy->isIntegral() && MidTy->isIntegral() && DstTy->isIntegral() &&
+      SrcTy->isSigned() == MidTy->isSigned() &&
+      MidTy->isSigned() == DstTy->isSigned()) {
+    // Only accept cases where we are either monotonically increasing the type
+    // size, or monotonically decreasing it.
+    //
+    unsigned SrcSize = SrcTy->getPrimitiveSize();
+    unsigned MidSize = MidTy->getPrimitiveSize();
+    unsigned DstSize = DstTy->getPrimitiveSize();
+    if (SrcSize < MidSize && MidSize < DstSize)
+      return true;
+
+    if (SrcSize > MidSize && MidSize > DstSize)
+      return true;
+  }
 
   // Otherwise, we cannot succeed.  Specifically we do not want to allow things
   // like:  short -> ushort -> uint, because this can create wrong results if
@@ -432,11 +447,10 @@ Instruction *InstCombiner::visitCastInst(CastInst &CI) {
     return &CI;
   }
 
-
   // If casting the result of another cast instruction, try to eliminate this
   // one!
   //
-  if (CastInst *CSrc = dyn_cast<CastInst>(CI.getOperand(0)))
+  if (CastInst *CSrc = dyn_cast<CastInst>(CI.getOperand(0))) {
     if (isEliminableCastOfCast(CI, CSrc)) {
       // This instruction now refers directly to the cast's src operand.  This
       // has a good chance of making CSrc dead.
@@ -444,6 +458,22 @@ Instruction *InstCombiner::visitCastInst(CastInst &CI) {
       return &CI;
     }
 
+    // If this is an A->B->A cast, and we are dealing with integral types, try
+    // to convert this into a logical 'and' instruction.
+    //
+    if (CSrc->getOperand(0)->getType() == CI.getType() &&
+        CI.getType()->isIntegral() && CSrc->getType()->isIntegral() &&
+        CI.getType()->isUnsigned() && CSrc->getType()->isUnsigned() &&
+        CSrc->getType()->getPrimitiveSize() < CI.getType()->getPrimitiveSize()){
+      assert(CSrc->getType() != Type::ULongTy &&
+             "Cannot have type bigger than ulong!");
+      unsigned AndValue = (1U << CSrc->getType()->getPrimitiveSize()*8)-1;
+      Constant *AndOp = ConstantUInt::get(CI.getType(), AndValue);
+      return BinaryOperator::create(Instruction::And, CSrc->getOperand(0),
+                                    AndOp);
+    }
+  }
+
   return 0;
 }