diff options
author | Chris Lattner <sabre@nondot.org> | 2002-08-15 16:15:25 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2002-08-15 16:15:25 +0000 |
commit | 3ecce66e253be217aa3c2bda60b8e8908602b001 (patch) | |
tree | 5d2a376a82b73745afcd824316c14f640bcd9d80 | |
parent | c5b74477c0f2d108e91dd803d29142ed0113ea04 (diff) |
Handle more cases of cast-of-cast in more general forms.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@3347 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Transforms/Scalar/InstructionCombining.cpp | 43 |
1 files changed, 35 insertions, 8 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index cc00093c78..f5acaf47e6 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -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 |