Index: llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h =================================================================== --- llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h +++ llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -116,6 +116,7 @@ bool MergeIdenticalEdges = false; bool KeepOneInputPHIs = false; bool PreserveLCSSA = false; + bool IgnoreUnreachableDests = false; CriticalEdgeSplittingOptions(DominatorTree *DT = nullptr, LoopInfo *LI = nullptr, @@ -137,6 +138,11 @@ PreserveLCSSA = true; return *this; } + + CriticalEdgeSplittingOptions &setIgnoreUnreachableDests() { + IgnoreUnreachableDests = true; + return *this; + } }; /// If this edge is a critical edge, insert a new node to split the critical Index: llvm/trunk/lib/Transforms/Instrumentation/SanitizerCoverage.cpp =================================================================== --- llvm/trunk/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ llvm/trunk/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -535,7 +535,7 @@ isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) return false; if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge) - SplitAllCriticalEdges(F); + SplitAllCriticalEdges(F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests()); SmallVector IndirCalls; SmallVector BlocksToInstrument; SmallVector CmpTraceTargets; Index: llvm/trunk/lib/Transforms/Utils/BreakCriticalEdges.cpp =================================================================== --- llvm/trunk/lib/Transforms/Utils/BreakCriticalEdges.cpp +++ llvm/trunk/lib/Transforms/Utils/BreakCriticalEdges.cpp @@ -153,6 +153,10 @@ if (isa(TI) && SuccNum > 0) return nullptr; + if (Options.IgnoreUnreachableDests && + isa(DestBB->getFirstNonPHIOrDbgOrLifetime())) + return nullptr; + // Create a new basic block, linking it into the CFG. BasicBlock *NewBB = BasicBlock::Create(TI->getContext(), TIBB->getName() + "." + DestBB->getName() + "_crit_edge"); Index: llvm/trunk/test/Instrumentation/SanitizerCoverage/unreachable-critedge.ll =================================================================== --- llvm/trunk/test/Instrumentation/SanitizerCoverage/unreachable-critedge.ll +++ llvm/trunk/test/Instrumentation/SanitizerCoverage/unreachable-critedge.ll @@ -0,0 +1,46 @@ +; RUN: opt < %s -S -sancov -sanitizer-coverage-level=3 | FileCheck %s + +; The critical edges to unreachable_bb should not be split. +define i32 @foo(i32 %c, i32 %d) { +; CHECK-LABEL: @foo( +; CHECK: switch i32 [[C:%.*]], label [[UNREACHABLE_BB:%.*]] [ +; CHECK-NEXT: i32 0, label %exit0 +; CHECK-NEXT: i32 1, label %exit1 +; CHECK-NEXT: i32 2, label %cont +; CHECK-NEXT: ] +; CHECK: cont: +; CHECK: switch i32 [[D:%.*]], label [[UNREACHABLE_BB]] [ +; CHECK-NEXT: i32 0, label %exit2 +; CHECK-NEXT: i32 1, label %exit3 +; CHECK-NEXT: i32 2, label %exit4 +; CHECK-NEXT: ] +; CHECK: unreachable_bb: +; CHECK-NEXT: unreachable +; + switch i32 %c, label %unreachable_bb [i32 0, label %exit0 + i32 1, label %exit1 + i32 2, label %cont] + +cont: + switch i32 %d, label %unreachable_bb [i32 0, label %exit2 + i32 1, label %exit3 + i32 2, label %exit4] + +exit0: + ret i32 0 + +exit1: + ret i32 1 + +exit2: + ret i32 2 + +exit3: + ret i32 3 + +exit4: + ret i32 4 + +unreachable_bb: + unreachable +}