diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp index 4efebfd809cb77..a1c0f4f8c0add5 100644 --- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp @@ -26,6 +26,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/Analysis/CFG.h" #include "llvm/Analysis/CallGraph.h" #include "llvm/Analysis/CallGraphSCCPass.h" #include "llvm/Analysis/LazyCallGraph.h" @@ -37,6 +38,7 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/GlobalVariable.h" @@ -658,8 +660,11 @@ void CoroCloner::salvageDebugInfo() { // Remove all salvaged dbg.declare intrinsics that became // either unreachable or stale due to the CoroSplit transformation. + DominatorTree DomTree(*NewF); + SmallDenseMap UnreachableCache; auto IsUnreachableBlock = [&](BasicBlock *BB) { - return BB->hasNPredecessors(0) && BB != &NewF->getEntryBlock(); + return !isPotentiallyReachable(&NewF->getEntryBlock(), BB, nullptr, + &DomTree); }; for (DbgVariableIntrinsic *DVI : Worklist) { if (IsUnreachableBlock(DVI->getParent())) diff --git a/llvm/test/Transforms/Coroutines/coro-debug.ll b/llvm/test/Transforms/Coroutines/coro-debug.ll index c34428b3ed4045..d38c52835acd05 100644 --- a/llvm/test/Transforms/Coroutines/coro-debug.ll +++ b/llvm/test/Transforms/Coroutines/coro-debug.ll @@ -20,6 +20,7 @@ entry: store i8* %2, i8** %coro_hdl, align 8, !dbg !16 %3 = call i8 @llvm.coro.suspend(token none, i1 false), !dbg !17 %conv = sext i8 %3 to i32, !dbg !17 + %late_local = alloca i32, align 4 call void @coro.devirt.trigger(i8* null) switch i32 %conv, label %sw.default [ i32 0, label %sw.bb @@ -35,6 +36,10 @@ sw.bb: ; preds = %entry call void @llvm.dbg.declare(metadata i32* %x.addr, metadata !12, metadata !13), !dbg !14 call void @llvm.dbg.declare(metadata i8** %coro_hdl, metadata !15, metadata !13), !dbg !16 call void @llvm.dbg.declare(metadata i8* null, metadata !28, metadata !13), !dbg !16 + call void @llvm.dbg.declare(metadata i32* %late_local, metadata !29, metadata !13), !dbg !16 + br label %next, !dbg !18 + +next: br label %sw.epilog, !dbg !18 sw.bb1: ; preds = %entry @@ -58,6 +63,7 @@ coro_Cleanup: ; preds = %sw.epilog, %sw.bb1 coro_Suspend: ; preds = %coro_Cleanup, %sw.default %7 = call i1 @llvm.coro.end(i8* null, i1 false) #7, !dbg !24 %8 = load i8*, i8** %coro_hdl, align 8, !dbg !24 + store i32 0, i32* %late_local, !dbg !24 ret i8* %8, !dbg !24 } @@ -138,6 +144,7 @@ attributes #7 = { noduplicate } !26 = !DILocalVariable(name: "direct_const", scope: !6, file: !7, line: 55, type: !11) !27 = !DILocalVariable(name: "undefined", scope: !6, file: !7, line: 55, type: !11) !28 = !DILocalVariable(name: "null", scope: !6, file: !7, line: 55, type: !11) +!29 = !DILocalVariable(name: "partial_dead", scope: !6, file: !7, line: 55, type: !11) ; CHECK: define i8* @f(i32 %x) #0 !dbg ![[ORIG:[0-9]+]] ; CHECK: define internal fastcc void @f.resume(%f.Frame* noalias nonnull align 8 dereferenceable(32) %FramePtr) #0 !dbg ![[RESUME:[0-9]+]] @@ -149,6 +156,8 @@ attributes #7 = { noduplicate } ; CHECK: store %f.Frame* {{.*}}, %f.Frame** %[[DBG_PTR]] ; CHECK-NOT: alloca %struct.test* ; CHECK: call void @llvm.dbg.declare(metadata i32 0, metadata ![[RESUME_CONST:[0-9]+]], metadata !DIExpression()) +; Note that keeping the undef value here could be acceptable, too. +; CHECK-NOT: call void @llvm.dbg.declare(metadata i32* undef, metadata !{{[0-9]+}}, metadata !DIExpression()) ; CHECK: call void @coro.devirt.trigger(i8* null) ; CHECK: define internal fastcc void @f.destroy(%f.Frame* noalias nonnull align 8 dereferenceable(32) %FramePtr) #0 !dbg ![[DESTROY:[0-9]+]] ; CHECK: define internal fastcc void @f.cleanup(%f.Frame* noalias nonnull align 8 dereferenceable(32) %FramePtr) #0 !dbg ![[CLEANUP:[0-9]+]]