summaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-12-25 22:30:44 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-12-25 22:30:44 +0000
commit77fc4c146f0870ffb09c1afb823ccbe742c5e6ff (patch)
tree5c0eb39553003b9c75a901af6bc4ddabd6f2f28c /llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
parentf65dcba83ce5035ab88a85fe17628b447eb56e1b (diff)
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstructionCombining.cpp')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstructionCombining.cpp39
1 files changed, 33 insertions, 6 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 1f81624f79e7..eb5eadba194d 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -2546,7 +2546,7 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
return nullptr;
}
-static bool isNeverEqualToUnescapedAlloc(Value *V, const TargetLibraryInfo *TLI,
+static bool isNeverEqualToUnescapedAlloc(Value *V, const TargetLibraryInfo &TLI,
Instruction *AI) {
if (isa<ConstantPointerNull>(V))
return true;
@@ -2557,12 +2557,34 @@ static bool isNeverEqualToUnescapedAlloc(Value *V, const TargetLibraryInfo *TLI,
// through bitcasts of V can cause
// the result statement below to be true, even when AI and V (ex:
// i8* ->i32* ->i8* of AI) are the same allocations.
- return isAllocLikeFn(V, TLI) && V != AI;
+ return isAllocLikeFn(V, &TLI) && V != AI;
+}
+
+/// Given a call CB which uses an address UsedV, return true if we can prove the
+/// call's only possible effect is storing to V.
+static bool isRemovableWrite(CallBase &CB, Value *UsedV,
+ const TargetLibraryInfo &TLI) {
+ if (!CB.use_empty())
+ // TODO: add recursion if returned attribute is present
+ return false;
+
+ if (CB.isTerminator())
+ // TODO: remove implementation restriction
+ return false;
+
+ if (!CB.willReturn() || !CB.doesNotThrow())
+ return false;
+
+ // If the only possible side effect of the call is writing to the alloca,
+ // and the result isn't used, we can safely remove any reads implied by the
+ // call including those which might read the alloca itself.
+ Optional<MemoryLocation> Dest = MemoryLocation::getForDest(&CB, TLI);
+ return Dest && Dest->Ptr == UsedV;
}
static bool isAllocSiteRemovable(Instruction *AI,
SmallVectorImpl<WeakTrackingVH> &Users,
- const TargetLibraryInfo *TLI) {
+ const TargetLibraryInfo &TLI) {
SmallVector<Instruction*, 4> Worklist;
Worklist.push_back(AI);
@@ -2627,12 +2649,17 @@ static bool isAllocSiteRemovable(Instruction *AI,
}
}
- if (isFreeCall(I, TLI)) {
+ if (isRemovableWrite(*cast<CallBase>(I), PI, TLI)) {
+ Users.emplace_back(I);
+ continue;
+ }
+
+ if (isFreeCall(I, &TLI)) {
Users.emplace_back(I);
continue;
}
- if (isReallocLikeFn(I, TLI, true)) {
+ if (isReallocLikeFn(I, &TLI, true)) {
Users.emplace_back(I);
Worklist.push_back(I);
continue;
@@ -2676,7 +2703,7 @@ Instruction *InstCombinerImpl::visitAllocSite(Instruction &MI) {
DIB.reset(new DIBuilder(*MI.getModule(), /*AllowUnresolved=*/false));
}
- if (isAllocSiteRemovable(&MI, Users, &TLI)) {
+ if (isAllocSiteRemovable(&MI, Users, TLI)) {
for (unsigned i = 0, e = Users.size(); i != e; ++i) {
// Lowering all @llvm.objectsize calls first because they may
// use a bitcast/GEP of the alloca we are removing.