summaryrefslogtreecommitdiff
path: root/lib/Transforms/InstCombine
diff options
context:
space:
mode:
authorNick Lewycky <nicholas@mxc.ca>2011-08-03 00:43:35 +0000
committerNick Lewycky <nicholas@mxc.ca>2011-08-03 00:43:35 +0000
commitd5061a9268d04c80af764291ef93fe3f7b51f0de (patch)
treed63baa440ac792dfe074875195844787e53420db /lib/Transforms/InstCombine
parent19308a1ea1c34e3dbed7b801408b2a8fcaba73f5 (diff)
downloadllvm-d5061a9268d04c80af764291ef93fe3f7b51f0de.tar.gz
llvm-d5061a9268d04c80af764291ef93fe3f7b51f0de.tar.bz2
llvm-d5061a9268d04c80af764291ef93fe3f7b51f0de.tar.xz
Fix logical error when detecting lifetime intrinsics.
Don't replace a gep/bitcast with 'undef' because that will form a "free(undef)" which in turn means "unreachable". What we wanted was a no-op. Instead, analyze the whole tree and look for all the instructions we need to delete first, then delete them second, not relying on the use_list to stay consistent. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@136752 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/InstCombine')
-rw-r--r--lib/Transforms/InstCombine/InstructionCombining.cpp67
1 files changed, 34 insertions, 33 deletions
diff --git a/lib/Transforms/InstCombine/InstructionCombining.cpp b/lib/Transforms/InstCombine/InstructionCombining.cpp
index 5b763c0b07..9c93903958 100644
--- a/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -46,6 +46,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/PatternMatch.h"
+#include "llvm/Support/ValueHandle.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm-c/Initialization.h"
@@ -1043,31 +1044,43 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
-static bool IsOnlyNullComparedAndFreed(const Value &V, int Depth = 0) {
+static bool IsOnlyNullComparedAndFreed(Value *V, SmallVector<WeakVH, 64> &Users,
+ int Depth = 0) {
if (Depth == 8)
return false;
- for (Value::const_use_iterator UI = V.use_begin(), UE = V.use_end();
+ for (Value::use_iterator UI = V->use_begin(), UE = V->use_end();
UI != UE; ++UI) {
- const User *U = *UI;
- if (isFreeCall(U))
+ User *U = *UI;
+ if (isFreeCall(U)) {
+ Users.push_back(U);
continue;
- if (const ICmpInst *ICI = dyn_cast<ICmpInst>(U))
- if (ICI->isEquality() && isa<ConstantPointerNull>(ICI->getOperand(1)))
+ }
+ if (ICmpInst *ICI = dyn_cast<ICmpInst>(U)) {
+ if (ICI->isEquality() && isa<ConstantPointerNull>(ICI->getOperand(1))) {
+ Users.push_back(ICI);
continue;
- if (const BitCastInst *BCI = dyn_cast<BitCastInst>(U)) {
- if (IsOnlyNullComparedAndFreed(*BCI, Depth+1))
+ }
+ }
+ if (BitCastInst *BCI = dyn_cast<BitCastInst>(U)) {
+ if (IsOnlyNullComparedAndFreed(BCI, Users, Depth+1)) {
+ Users.push_back(BCI);
continue;
+ }
}
- if (const GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(U)) {
+ if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(U)) {
if (GEPI->hasAllZeroIndices() &&
- IsOnlyNullComparedAndFreed(*GEPI, Depth+1))
+ IsOnlyNullComparedAndFreed(GEPI, Users, Depth+1)) {
+ Users.push_back(GEPI);
continue;
+ }
}
- if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(U)) {
+ if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(U)) {
if (II->getIntrinsicID() == Intrinsic::lifetime_start ||
- II->getIntrinsicID() == Intrinsic::lifetime_end)
+ II->getIntrinsicID() == Intrinsic::lifetime_end) {
+ Users.push_back(II);
continue;
+ }
}
return false;
}
@@ -1078,32 +1091,20 @@ 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;) {
- // All the users permitted by IsOnlyNullComparedAndFreed are Instructions.
- Instruction *I = cast<Instruction>(*UI);
-
- // Early increment here, as we're about to get rid of the user.
- ++UI;
-
- if (CallInst *CI = isFreeCall(I)) {
- if (CI != I)
- EraseInstFromFunction(*CI);
- EraseInstFromFunction(*I);
- } else if (ICmpInst *C = dyn_cast<ICmpInst>(I)) {
+ SmallVector<WeakVH, 64> Users;
+ if (IsOnlyNullComparedAndFreed(&MI, Users)) {
+ for (unsigned i = 0, e = Users.size(); i != e; ++i) {
+ Instruction *I = cast_or_null<Instruction>(&*Users[i]);
+ if (!I) continue;
+
+ if (ICmpInst *C = dyn_cast<ICmpInst>(I)) {
ReplaceInstUsesWith(*C,
ConstantInt::get(Type::getInt1Ty(C->getContext()),
C->isFalseWhenEqual()));
- EraseInstFromFunction(*C);
- } else if (I->getType()->isVoidTy()) {
- // An all-zero GEP or a bitcast.
+ } else if (isa<BitCastInst>(I) || isa<GetElementPtrInst>(I)) {
ReplaceInstUsesWith(*I, UndefValue::get(I->getType()));
- EraseInstFromFunction(*I);
- } else {
- // A lifetime intrinsic.
- EraseInstFromFunction(*I);
}
+ EraseInstFromFunction(*I);
}
return EraseInstFromFunction(MI);
}