Handle more cases of cast-of-cast in more general forms.
authorChris Lattner <sabre@nondot.org>
Thu, 15 Aug 2002 16:15:25 +0000 (16:15 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 15 Aug 2002 16:15:25 +0000 (16:15 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@3347 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/InstructionCombining.cpp

index cc00093c78a84bb93c4437888258ecc8b06b1046..f5acaf47e62d3032d278d9a0d869735b7f750804 100644 (file)
@@ -501,20 +501,47 @@ static inline bool isEliminableCastOfCast(const CastInst &CI,
 
   // Allow free casting and conversion of sizes as long as the sign doesn't
   // change...
-  if (isCIntegral(SrcTy) && isCIntegral(MidTy) && isCIntegral(DstTy) &&
-      SrcTy->isSigned() == MidTy->isSigned() &&
-      MidTy->isSigned() == DstTy->isSigned()) {
-    // Only accept cases where we are either monotonically increasing the type
-    // size, or monotonically decreasing it.
-    //
+  if (isCIntegral(SrcTy) && isCIntegral(MidTy) && isCIntegral(DstTy)) {
     unsigned SrcSize = SrcTy->getPrimitiveSize();
     unsigned MidSize = MidTy->getPrimitiveSize();
     unsigned DstSize = DstTy->getPrimitiveSize();
-    if (SrcSize <= MidSize && MidSize <= DstSize)
-      return true;
 
+    // Cases where we are monotonically decreasing the size of the type are
+    // always ok, regardless of what sign changes are going on.
+    //
     if (SrcSize >= MidSize && MidSize >= DstSize)
       return true;
+
+    // If we are monotonically growing, things are more complex.
+    //
+    if (SrcSize <= MidSize && MidSize <= DstSize) {
+      // We have eight combinations of signedness to worry about. Here's the
+      // table:
+      static const int SignTable[8] = {
+        // CODE, SrcSigned, MidSigned, DstSigned, Comment
+        1,     //   U          U          U       Always ok
+        1,     //   U          U          S       Always ok
+        3,     //   U          S          U       Ok iff SrcSize != MidSize
+        3,     //   U          S          S       Ok iff SrcSize != MidSize
+        0,     //   S          U          U       Never ok
+        2,     //   S          U          S       Ok iff MidSize == DstSize
+        1,     //   S          S          U       Always ok
+        1,     //   S          S          S       Always ok
+      };
+
+      // Choose an action based on the current entry of the signtable that this
+      // cast of cast refers to...
+      unsigned Row = SrcTy->isSigned()*4+MidTy->isSigned()*2+DstTy->isSigned();
+      switch (SignTable[Row]) {
+      case 0: return false;              // Never ok
+      case 1: return true;               // Always ok
+      case 2: return MidSize == DstSize; // Ok iff MidSize == DstSize
+      case 3:                            // Ok iff SrcSize != MidSize
+        return SrcSize != MidSize || SrcTy == Type::BoolTy;
+      default: assert(0 && "Bad entry in sign table!");
+      }
+      return false;  // NOT REACHED
+    }
   }
 
   // Otherwise, we cannot succeed.  Specifically we do not want to allow things