summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2002-08-02 20:00:25 +0000
committerChris Lattner <sabre@nondot.org>2002-08-02 20:00:25 +0000
commit8fd217cb290ae22546c57af245881094312dd9de (patch)
treec50228b9711f051ebfc0010f3d2e1bbbdef9041c /lib
parent7b572eff4826e9889f032cfe9591ef449c6c52e1 (diff)
downloadexternal_llvm-8fd217cb290ae22546c57af245881094312dd9de.zip
external_llvm-8fd217cb290ae22546c57af245881094312dd9de.tar.gz
external_llvm-8fd217cb290ae22546c57af245881094312dd9de.tar.bz2
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
Diffstat (limited to 'lib')
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp44
1 files changed, 37 insertions, 7 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 3d7e4f8..4946661 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<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;
}