diff options
author | Nick Lewycky <nicholas@mxc.ca> | 2011-08-03 00:43:35 +0000 |
---|---|---|
committer | Nick Lewycky <nicholas@mxc.ca> | 2011-08-03 00:43:35 +0000 |
commit | d5061a9268d04c80af764291ef93fe3f7b51f0de (patch) | |
tree | d63baa440ac792dfe074875195844787e53420db /lib | |
parent | 19308a1ea1c34e3dbed7b801408b2a8fcaba73f5 (diff) | |
download | external_llvm-d5061a9268d04c80af764291ef93fe3f7b51f0de.zip external_llvm-d5061a9268d04c80af764291ef93fe3f7b51f0de.tar.gz external_llvm-d5061a9268d04c80af764291ef93fe3f7b51f0de.tar.bz2 |
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')
-rw-r--r-- | lib/Transforms/InstCombine/InstructionCombining.cpp | 67 |
1 files changed, 34 insertions, 33 deletions
diff --git a/lib/Transforms/InstCombine/InstructionCombining.cpp b/lib/Transforms/InstCombine/InstructionCombining.cpp index 5b763c0..9c93903 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); } |