summaryrefslogtreecommitdiffstats
path: root/lib/Transforms/Scalar
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2002-05-02 17:06:02 +0000
committerChris Lattner <sabre@nondot.org>2002-05-02 17:06:02 +0000
commita1be566213aa495c782b9871b03233f9d1d1659c (patch)
treef6b982a9c28cc130d28a8c2f23c7cb57ff71d8de /lib/Transforms/Scalar
parentfa49f810c2df4ded6755edbe0625029758c81657 (diff)
downloadexternal_llvm-a1be566213aa495c782b9871b03233f9d1d1659c.zip
external_llvm-a1be566213aa495c782b9871b03233f9d1d1659c.tar.gz
external_llvm-a1be566213aa495c782b9871b03233f9d1d1659c.tar.bz2
* Add ability to eliminate a bunch of different cascading cast variations
* Allow elimination of getelementptr X, uint 0 (which is a noop) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2428 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Scalar')
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp62
1 files changed, 60 insertions, 2 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 2ad2356..59172b5 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -61,6 +61,7 @@ namespace {
Instruction *visitSub(BinaryOperator *I);
Instruction *visitMul(BinaryOperator *I);
Instruction *visitCastInst(CastInst *CI);
+ Instruction *visitGetElementPtrInst(GetElementPtrInst *GEP);
Instruction *visitMemAccessInst(MemAccessInst *MAI);
// visitInstruction - Specify what to return for unhandled instructions...
@@ -163,18 +164,75 @@ Instruction *InstCombiner::visitMul(BinaryOperator *I) {
}
-// CastInst simplification - If the user is casting a value to the same type,
-// eliminate this cast instruction...
+// isEliminableCastOfCast - Return true if it is valid to eliminate the CI
+// instruction.
+//
+static inline bool isEliminableCastOfCast(const CastInst *CI,
+ const CastInst *CSrc) {
+ assert(CI->getOperand(0) == CSrc);
+ const Type *SrcTy = CSrc->getOperand(0)->getType();
+ 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;
+
+ // 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;
+
+ // Otherwise, we cannot succeed. Specifically we do not want to allow things
+ // like: short -> ushort -> uint, because this can create wrong results if
+ // the input short is negative!
+ //
+ return false;
+}
+
+
+// CastInst simplification
//
Instruction *InstCombiner::visitCastInst(CastInst *CI) {
+ // If the user is casting a value to the same type, eliminate this cast
+ // instruction...
if (CI->getType() == CI->getOperand(0)->getType() && !CI->use_empty()) {
AddUsesToWorkList(CI); // Add all modified instrs to worklist
CI->replaceAllUsesWith(CI->getOperand(0));
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 (isEliminableCastOfCast(CI, CSrc)) {
+ // This instruction now refers directly to the cast's src operand. This
+ // has a good chance of making CSrc dead.
+ CI->setOperand(0, CSrc->getOperand(0));
+ return CI;
+ }
+
return 0;
}
+
+
+Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst *GEP) {
+ // Is it getelementptr %P, uint 0
+ // If so, elminate the noop.
+ if (GEP->getNumOperands() == 2 && !GEP->use_empty() &&
+ GEP->getOperand(1) == Constant::getNullValue(Type::UIntTy)) {
+ AddUsesToWorkList(GEP); // Add all modified instrs to worklist
+ GEP->replaceAllUsesWith(GEP->getOperand(0));
+ return GEP;
+ }
+
+ return visitMemAccessInst(GEP);
+}
+
+
// Combine Indices - If the source pointer to this mem access instruction is a
// getelementptr instruction, combine the indices of the GEP into this
// instruction