diff options
Diffstat (limited to 'lib/Transforms/Scalar/InstructionCombining.cpp')
-rw-r--r-- | lib/Transforms/Scalar/InstructionCombining.cpp | 96 |
1 files changed, 53 insertions, 43 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index d53cdbf87d..6b993750a3 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -1938,6 +1938,29 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) { return 0; } +enum CastType { + Noop = 0, + Truncate = 1, + Signext = 2, + Zeroext = 3 +}; + +/// getCastType - In the future, we will split the cast instruction into these +/// various types. Until then, we have to do the analysis here. +static CastType getCastType(const Type *Src, const Type *Dest) { + assert(Src->isIntegral() && Dest->isIntegral() && + "Only works on integral types!"); + unsigned SrcSize = Src->getPrimitiveSize()*8; + if (Src == Type::BoolTy) SrcSize = 1; + unsigned DestSize = Dest->getPrimitiveSize()*8; + if (Dest == Type::BoolTy) DestSize = 1; + + if (SrcSize == DestSize) return Noop; + if (SrcSize > DestSize) return Truncate; + if (Src->isSigned()) return Signext; + return Zeroext; +} + // isEliminableCastOfCast - Return true if it is valid to eliminate the CI // instruction. @@ -1954,50 +1977,37 @@ static inline bool isEliminableCastOfCast(const Type *SrcTy, const Type *MidTy, // Allow free casting and conversion of sizes as long as the sign doesn't // change... if (SrcTy->isIntegral() && MidTy->isIntegral() && DstTy->isIntegral()) { - unsigned SrcSize = SrcTy->getPrimitiveSize(); - unsigned MidSize = MidTy->getPrimitiveSize(); - unsigned DstSize = DstTy->getPrimitiveSize(); - - // 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) + CastType FirstCast = getCastType(SrcTy, MidTy); + CastType SecondCast = getCastType(MidTy, DstTy); + + // Capture the effect of these two casts. If the result is a legal cast, + // the CastType is stored here, otherwise a special code is used. + static const unsigned CastResult[] = { + // First cast is noop + 0, 1, 2, 3, + // First cast is a truncate + 1, 1, 4, 4, // trunc->extend is not safe to eliminate + // First cast is a sign ext + 2, 5, 2, 4, // signext->trunc always ok, signext->zeroext never ok + // First cast is a zero ext + 3, 5, 3, 3, // zeroext->trunc always ok + }; + + unsigned Result = CastResult[FirstCast*4+SecondCast]; + switch (Result) { + default: assert(0 && "Illegal table value!"); + case 0: + case 1: + case 2: + case 3: + // FIXME: in the future, when LLVM has explicit sign/zeroextends and + // truncates, we could eliminate more casts. + return (unsigned)getCastType(SrcTy, DstTy) == Result; + case 4: + return false; // Not possible to eliminate this here. + case 5: + // Sign or zero extend followed by truncate is always ok return true; - - // Cases where the source and destination type are the same, but the middle - // type is bigger are noops. - // - if (SrcSize == DstSize && MidSize > SrcSize) - 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!"); - } } } |