From ab5d98def1b0341b5ff2827a560ec2868b70366b Mon Sep 17 00:00:00 2001 From: Johannes Doerfert Date: Tue, 3 Sep 2019 20:42:16 +0000 Subject: [PATCH] [Attributor] Use the delete API for liveness Reviewers: uenoku, sstefan1 Subscribers: hiraditya, bollu, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D66833 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@370818 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/IPO/Attributor.cpp | 21 ++++++++++++++----- test/Transforms/FunctionAttrs/arg_returned.ll | 4 +--- test/Transforms/FunctionAttrs/liveness.ll | 15 +++++++------ 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/lib/Transforms/IPO/Attributor.cpp b/lib/Transforms/IPO/Attributor.cpp index 98ea3439d9ce..808aae2afd76 100644 --- a/lib/Transforms/IPO/Attributor.cpp +++ b/lib/Transforms/IPO/Attributor.cpp @@ -1868,7 +1868,7 @@ struct AAIsDeadImpl : public AAIsDead { Function &F = *getAssociatedFunction(); if (AssumedLiveBlocks.empty()) { - F.replaceAllUsesWith(UndefValue::get(F.getType())); + A.deleteAfterManifest(F); return ChangeStatus::CHANGED; } @@ -1918,6 +1918,9 @@ struct AAIsDeadImpl : public AAIsDead { } } } + + if (SplitPos == &NormalDestBB->front()) + AssumedLiveBlocks.insert(NormalDestBB); } BB = SplitPos->getParent(); @@ -1926,6 +1929,10 @@ struct AAIsDeadImpl : public AAIsDead { HasChanged = ChangeStatus::CHANGED; } + for (BasicBlock &BB : F) + if (!AssumedLiveBlocks.count(&BB)) + A.deleteAfterManifest(BB); + return HasChanged; } @@ -3309,14 +3316,18 @@ ChangeStatus Attributor::run() { << " blocks and " << ToBeDeletedInsts.size() << " instructions\n"); for (Instruction *I : ToBeDeletedInsts) { - if (I->hasNUsesOrMore(1)) + if (!I->use_empty()) I->replaceAllUsesWith(UndefValue::get(I->getType())); I->eraseFromParent(); } - for (BasicBlock *BB : ToBeDeletedBlocks) { - // TODO: Check if we need to replace users (PHIs, indirect branches?) - BB->eraseFromParent(); + + if (unsigned NumDeadBlocks = ToBeDeletedBlocks.size()) { + SmallVector ToBeDeletedBBs; + ToBeDeletedBBs.reserve(NumDeadBlocks); + ToBeDeletedBBs.append(ToBeDeletedBlocks.begin(), ToBeDeletedBlocks.end()); + DeleteDeadBlocks(ToBeDeletedBBs); } + for (Function *Fn : ToBeDeletedFunctions) { Fn->replaceAllUsesWith(UndefValue::get(Fn->getType())); Fn->eraseFromParent(); diff --git a/test/Transforms/FunctionAttrs/arg_returned.ll b/test/Transforms/FunctionAttrs/arg_returned.ll index 69b12fd5c0ba..fb7e5d9bc9ee 100644 --- a/test/Transforms/FunctionAttrs/arg_returned.ll +++ b/test/Transforms/FunctionAttrs/arg_returned.ll @@ -804,10 +804,8 @@ attributes #0 = { noinline nounwind uwtable } ; BOTH-DAG: attributes #{{[0-9]*}} = { nofree noinline nosync nounwind readnone uwtable } ; BOTH-DAG: attributes #{{[0-9]*}} = { nofree noinline noreturn nosync nounwind readonly uwtable } ; BOTH-DAG: attributes #{{[0-9]*}} = { noinline nounwind uwtable } -; BOTH-DAG: attributes #{{[0-9]*}} = { nofree noinline nosync nounwind readnone uwtable willreturn } -; BOTH-DAG: attributes #{{[0-9]*}} = { nofree noinline nosync nounwind uwtable willreturn } +; BOTH-DAG: attributes #{{[0-9]*}} = { noreturn } ; BOTH-DAG: attributes #{{[0-9]*}} = { nofree nosync willreturn } ; BOTH-DAG: attributes #{{[0-9]*}} = { nofree nosync } ; BOTH-DAG: attributes #{{[0-9]*}} = { nofree noreturn nosync } -; BOTH-DAG: attributes #{{[0-9]*}} = { noreturn } ; BOTH-NOT: attributes # diff --git a/test/Transforms/FunctionAttrs/liveness.ll b/test/Transforms/FunctionAttrs/liveness.ll index 046f7563894d..a8dd12cd1a5e 100644 --- a/test/Transforms/FunctionAttrs/liveness.ll +++ b/test/Transforms/FunctionAttrs/liveness.ll @@ -15,7 +15,7 @@ declare i32 @bar() nosync readnone ; This internal function has no live call sites, so all its BBs are considered dead, ; and nothing should be deduced for it. -; CHECK: define internal i32 @dead_internal_func(i32 %0) +; CHECK-NOT: define internal i32 @dead_internal_func(i32 %0) define internal i32 @dead_internal_func(i32 %0) { %2 = icmp slt i32 %0, 1 br i1 %2, label %3, label %5 @@ -56,14 +56,13 @@ entry: call void @no_return_call() ; CHECK: call void @no_return_call() ; CHECK-NEXT: unreachable + ; CHECK-NEXT: } call i32 @dead_internal_func(i32 10) - ; CHECK call i32 undef(i32 10) %cmp = icmp eq i32 %a, 0 br i1 %cmp, label %cond.true, label %cond.false cond.true: ; preds = %entry call i32 @internal_load(i32* %ptr2) - ; CHECK: call i32 @internal_load(i32* %ptr2) %load = call i32 @volatile_load(i32* %ptr1) call void @normal_call() %call = call i32 @foo() @@ -104,6 +103,8 @@ cond.false: ; preds = %entry br label %cond.end cond.end: ; preds = %cond.false, %cond.true +; CHECK: cond.end: +; CHECK-NEXT: ret i32 %call1 %cond = phi i32 [ %call, %cond.true ], [ %call1, %cond.false ] ret i32 %cond } @@ -120,7 +121,7 @@ cond.true: ; preds = %entry ; CHECK: call void @no_return_call() ; CHECK-NEXT: unreachable call i32 @dead_internal_func(i32 10) - ; CHECK call i32 undef(i32 10) + ; CHECK-NOT: call %call = call i32 @foo() br label %cond.end @@ -129,7 +130,7 @@ cond.false: ; preds = %entry ; CHECK: call void @no_return_call() ; CHECK-NEXT: unreachable call i32 @dead_internal_func(i32 10) - ; CHECK call i32 undef(i32 10) + ; CHECK-NEXT: } %call1 = call i32 @bar() br label %cond.end @@ -215,9 +216,7 @@ cond.true: ; preds = %entry ; CHECK-NEXT: call i32 @foo_noreturn_nounwind() ; CHECK-NEXT: unreachable - ; We keep the invoke around as other attributes might have references to it. - ; CHECK: cond.true.split: ; No predecessors! - ; CHECK-NEXT: invoke i32 @foo_noreturn_nounwind() + ; CHECK-NOT: @foo_noreturn_nounwind() cond.false: ; preds = %entry call void @normal_call()