aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDuncan Sands <baldrick@free.fr>2010-05-27 19:09:06 +0000
committerDuncan Sands <baldrick@free.fr>2010-05-27 19:09:06 +0000
commit1d9b973fd7e60e4149678a03aac762551c846f13 (patch)
treee002a3d6cf5b6a3049d504b189c0052caa5049e6 /lib
parent084fb0ea3246300aa81dd2561ce4d84401b74792 (diff)
Teach instCombine to remove malloc+free if malloc's only uses are comparisons
to null. Patch by Matti Niemenmaa. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@104871 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Transforms/InstCombine/InstCombine.h1
-rw-r--r--lib/Transforms/InstCombine/InstCombineCalls.cpp2
-rw-r--r--lib/Transforms/InstCombine/InstCombineCompares.cpp29
-rw-r--r--lib/Transforms/InstCombine/InstructionCombining.cpp63
4 files changed, 49 insertions, 46 deletions
diff --git a/lib/Transforms/InstCombine/InstCombine.h b/lib/Transforms/InstCombine/InstCombine.h
index c7b04a4a83..5509b4f630 100644
--- a/lib/Transforms/InstCombine/InstCombine.h
+++ b/lib/Transforms/InstCombine/InstCombine.h
@@ -178,6 +178,7 @@ public:
Instruction *visitPHINode(PHINode &PN);
Instruction *visitGetElementPtrInst(GetElementPtrInst &GEP);
Instruction *visitAllocaInst(AllocaInst &AI);
+ Instruction *visitMalloc(Instruction &FI);
Instruction *visitFree(Instruction &FI);
Instruction *visitLoadInst(LoadInst &LI);
Instruction *visitStoreInst(StoreInst &SI);
diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 38e7b6ec2d..08a6ff41eb 100644
--- a/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -250,6 +250,8 @@ Instruction *InstCombiner::SimplifyMemSet(MemSetInst *MI) {
Instruction *InstCombiner::visitCallInst(CallInst &CI) {
if (isFreeCall(&CI))
return visitFree(CI);
+ if (isMalloc(&CI))
+ return visitMalloc(CI);
// If the caller function is nounwind, mark the call as nounwind, even if the
// callee isn't.
diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 861cf92d28..2b4998f3c3 100644
--- a/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -1924,35 +1924,6 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
}
break;
}
- case Instruction::Call:
- // If we have (malloc != null), and if the malloc has a single use, we
- // can assume it is successful and remove the malloc.
- if (isMalloc(LHSI) && LHSI->hasOneUse() &&
- isa<ConstantPointerNull>(RHSC)) {
- // Need to explicitly erase malloc call here, instead of adding it to
- // Worklist, because it won't get DCE'd from the Worklist since
- // isInstructionTriviallyDead() returns false for function calls.
- // It is OK to replace LHSI/MallocCall with Undef because the
- // instruction that uses it will be erased via Worklist.
- if (extractMallocCall(LHSI)) {
- LHSI->replaceAllUsesWith(UndefValue::get(LHSI->getType()));
- EraseInstFromFunction(*LHSI);
- return ReplaceInstUsesWith(I,
- ConstantInt::get(Type::getInt1Ty(I.getContext()),
- !I.isTrueWhenEqual()));
- }
- if (CallInst* MallocCall = extractMallocCallFromBitCast(LHSI))
- if (MallocCall->hasOneUse()) {
- MallocCall->replaceAllUsesWith(
- UndefValue::get(MallocCall->getType()));
- EraseInstFromFunction(*MallocCall);
- Worklist.Add(LHSI); // The malloc's bitcast use.
- return ReplaceInstUsesWith(I,
- ConstantInt::get(Type::getInt1Ty(I.getContext()),
- !I.isTrueWhenEqual()));
- }
- }
- break;
case Instruction::IntToPtr:
// icmp pred inttoptr(X), null -> icmp pred X, 0
if (RHSC->isNullValue() && TD &&
diff --git a/lib/Transforms/InstCombine/InstructionCombining.cpp b/lib/Transforms/InstCombine/InstructionCombining.cpp
index af9ec5cacf..ab43f7d881 100644
--- a/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -710,6 +710,52 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
return 0;
}
+
+
+static bool IsOnlyNullComparedAndFreed(const Value &V) {
+ for (Value::const_use_iterator UI = V.use_begin(), UE = V.use_end();
+ UI != UE; ++UI) {
+ if (isFreeCall(*UI))
+ continue;
+ if (const ICmpInst *ICI = dyn_cast<ICmpInst>(*UI))
+ if (ICI->isEquality() && isa<ConstantPointerNull>(ICI->getOperand(1)))
+ continue;
+ return false;
+ }
+ return true;
+}
+
+Instruction *InstCombiner::visitMalloc(Instruction &MI) {
+ // If we have a malloc call which is only used in any amount of comparisons
+ // to null and free calls, delete the calls and replace the comparisons with
+ // true or false as appropriate.
+ if (IsOnlyNullComparedAndFreed(MI)) {
+ for (Value::use_iterator UI = MI.use_begin(), UE = MI.use_end();
+ UI != UE;) {
+ // We can assume that every remaining use is a free call or an icmp eq/ne
+ // to null, so the cast is safe.
+ Instruction *I = cast<Instruction>(*UI);
+
+ // Early increment here, as we're about to get rid of the user.
+ ++UI;
+
+ if (isFreeCall(I)) {
+ EraseInstFromFunction(*cast<CallInst>(I));
+ continue;
+ }
+ // Again, the cast is safe.
+ ICmpInst *C = cast<ICmpInst>(I);
+ ReplaceInstUsesWith(*C, ConstantInt::get(Type::getInt1Ty(C->getContext()),
+ C->isFalseWhenEqual()));
+ EraseInstFromFunction(*C);
+ }
+ return EraseInstFromFunction(MI);
+ }
+ return 0;
+}
+
+
+
Instruction *InstCombiner::visitFree(Instruction &FI) {
Value *Op = FI.getOperand(1);
@@ -726,23 +772,6 @@ Instruction *InstCombiner::visitFree(Instruction &FI) {
if (isa<ConstantPointerNull>(Op))
return EraseInstFromFunction(FI);
- // If we have a malloc call whose only use is a free call, delete both.
- if (isMalloc(Op)) {
- if (CallInst* CI = extractMallocCallFromBitCast(Op)) {
- if (Op->hasOneUse() && CI->hasOneUse()) {
- EraseInstFromFunction(FI);
- EraseInstFromFunction(*CI);
- return EraseInstFromFunction(*cast<Instruction>(Op));
- }
- } else {
- // Op is a call to malloc
- if (Op->hasOneUse()) {
- EraseInstFromFunction(FI);
- return EraseInstFromFunction(*cast<Instruction>(Op));
- }
- }
- }
-
return 0;
}