teach instcombine to remove allocated buffers even if there are stores, memcpy/memmove/memset, and objectsize users.

This means we can do cheap DSE for heap memory.
Nothing is done if the pointer excapes or has a load.

The churn in the tests is mostly due to objectsize, since we want to make sure we
don't delete the malloc call before evaluating the objectsize (otherwise it becomes -1/0)

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@159876 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Nuno Lopes
2012-07-06 23:09:25 +00:00
parent eb54603ddd
commit 9969458b16
6 changed files with 128 additions and 17 deletions
@@ -1137,12 +1137,29 @@ static bool IsOnlyNullComparedAndFreed(Value *V, SmallVectorImpl<WeakVH> &Users,
}
}
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(U)) {
if (II->getIntrinsicID() == Intrinsic::lifetime_start ||
II->getIntrinsicID() == Intrinsic::lifetime_end) {
switch (II->getIntrinsicID()) {
default: return false;
case Intrinsic::memmove:
case Intrinsic::memcpy:
case Intrinsic::memset: {
MemIntrinsic *MI = cast<MemIntrinsic>(II);
if (MI->isVolatile() || MI->getRawDest() != V)
return false;
}
// fall through
case Intrinsic::objectsize:
case Intrinsic::lifetime_start:
case Intrinsic::lifetime_end:
Users.push_back(II);
continue;
}
}
if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
if (SI->isVolatile() || SI->getPointerOperand() != V)
return false;
Users.push_back(SI);
continue;
}
return false;
}
return true;
@@ -1164,6 +1181,12 @@ Instruction *InstCombiner::visitMalloc(Instruction &MI) {
C->isFalseWhenEqual()));
} else if (isa<BitCastInst>(I) || isa<GetElementPtrInst>(I)) {
ReplaceInstUsesWith(*I, UndefValue::get(I->getType()));
} else if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
if (II->getIntrinsicID() == Intrinsic::objectsize) {
ConstantInt *CI = cast<ConstantInt>(II->getArgOperand(1));
uint64_t DontKnow = CI->isZero() ? -1ULL : 0;
ReplaceInstUsesWith(*I, ConstantInt::get(I->getType(), DontKnow));
}
}
EraseInstFromFunction(*I);
}