Function &F = *getAssociatedFunction();
if (AssumedLiveBlocks.empty()) {
- F.replaceAllUsesWith(UndefValue::get(F.getType()));
+ A.deleteAfterManifest(F);
return ChangeStatus::CHANGED;
}
}
}
}
+
+ if (SplitPos == &NormalDestBB->front())
+ AssumedLiveBlocks.insert(NormalDestBB);
}
BB = SplitPos->getParent();
HasChanged = ChangeStatus::CHANGED;
}
+ for (BasicBlock &BB : F)
+ if (!AssumedLiveBlocks.count(&BB))
+ A.deleteAfterManifest(BB);
+
return HasChanged;
}
<< " 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<BasicBlock *, 8> ToBeDeletedBBs;
+ ToBeDeletedBBs.reserve(NumDeadBlocks);
+ ToBeDeletedBBs.append(ToBeDeletedBlocks.begin(), ToBeDeletedBlocks.end());
+ DeleteDeadBlocks(ToBeDeletedBBs);
}
+
for (Function *Fn : ToBeDeletedFunctions) {
Fn->replaceAllUsesWith(UndefValue::get(Fn->getType()));
Fn->eraseFromParent();
; 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 #
; 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
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()
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
}
; 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
; 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
; 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()