From 8fd217cb290ae22546c57af245881094312dd9de Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 2 Aug 2002 20:00:25 +0000 Subject: [PATCH] Fix bug: test/Regression/Transforms/InstCombine/2002-08-02-CastTest.ll 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 --- .../Scalar/InstructionCombining.cpp | 44 ++++++++++++++++--- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 3d7e4f87afe..49466612988 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -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(CI.getOperand(0))) + if (CastInst *CSrc = dyn_cast(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; }