Index: include/llvm/Transforms/Utils/BasicBlockUtils.h =================================================================== --- include/llvm/Transforms/Utils/BasicBlockUtils.h +++ include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -110,6 +110,7 @@ bool MergeIdenticalEdges = false; bool KeepOneInputPHIs = false; bool PreserveLCSSA = false; + bool IgnoreUnreachableDests = false; CriticalEdgeSplittingOptions(DominatorTree *DT = nullptr, LoopInfo *LI = nullptr, @@ -131,6 +132,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: lib/Transforms/Instrumentation/SanitizerCoverage.cpp =================================================================== --- lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ 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: lib/Transforms/Utils/BreakCriticalEdges.cpp =================================================================== --- lib/Transforms/Utils/BreakCriticalEdges.cpp +++ 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: test/Instrumentation/SanitizerCoverage/unreachable-critedge.ll =================================================================== --- /dev/null +++ test/Instrumentation/SanitizerCoverage/unreachable-critedge.ll @@ -0,0 +1,67 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -S -sancov -sanitizer-coverage-level=3 | FileCheck %s + +define i32 @foo(i32 %c, i32 %d) { +; CHECK-LABEL: @foo( +; CHECK-NEXT: call void @__sanitizer_cov_trace_pc_guard(i32* getelementptr inbounds ([6 x i32], [6 x i32]* @__sancov_gen_, i32 0, i32 0)) +; CHECK-NEXT: call void asm sideeffect "", ""() +; CHECK-NEXT: switch i32 [[C:%.*]], label [[UNREACHABLE_BB:%.*]] [ +; CHECK-NEXT: i32 0, label [[EXIT0:%.*]] +; CHECK-NEXT: i32 1, label [[EXIT1:%.*]] +; CHECK-NEXT: i32 2, label [[DOTCONT_CRIT_EDGE:%.*]] +; CHECK-NEXT: ] +; CHECK: .cont_crit_edge: +; CHECK-NEXT: br label [[CONT:%.*]] +; CHECK: cont: +; CHECK-NEXT: switch i32 [[D:%.*]], label [[UNREACHABLE_BB]] [ +; CHECK-NEXT: i32 0, label [[EXIT2:%.*]] +; CHECK-NEXT: i32 1, label [[EXIT3:%.*]] +; CHECK-NEXT: i32 2, label [[CONT_CONT_CRIT_EDGE:%.*]] +; CHECK-NEXT: ] +; CHECK: cont.cont_crit_edge: +; CHECK-NEXT: call void @__sanitizer_cov_trace_pc_guard(i32* inttoptr (i64 add (i64 ptrtoint ([6 x i32]* @__sancov_gen_ to i64), i64 4) to i32*)) +; CHECK-NEXT: call void asm sideeffect "", ""() +; CHECK-NEXT: br label [[CONT]] +; CHECK: exit0: +; CHECK-NEXT: call void @__sanitizer_cov_trace_pc_guard(i32* inttoptr (i64 add (i64 ptrtoint ([6 x i32]* @__sancov_gen_ to i64), i64 8) to i32*)) +; CHECK-NEXT: call void asm sideeffect "", ""() +; CHECK-NEXT: ret i32 0 +; CHECK: exit1: +; CHECK-NEXT: call void @__sanitizer_cov_trace_pc_guard(i32* inttoptr (i64 add (i64 ptrtoint ([6 x i32]* @__sancov_gen_ to i64), i64 12) to i32*)) +; CHECK-NEXT: call void asm sideeffect "", ""() +; CHECK-NEXT: ret i32 1 +; CHECK: exit2: +; CHECK-NEXT: call void @__sanitizer_cov_trace_pc_guard(i32* inttoptr (i64 add (i64 ptrtoint ([6 x i32]* @__sancov_gen_ to i64), i64 16) to i32*)) +; CHECK-NEXT: call void asm sideeffect "", ""() +; CHECK-NEXT: ret i32 2 +; CHECK: exit3: +; CHECK-NEXT: call void @__sanitizer_cov_trace_pc_guard(i32* inttoptr (i64 add (i64 ptrtoint ([6 x i32]* @__sancov_gen_ to i64), i64 20) to i32*)) +; CHECK-NEXT: call void asm sideeffect "", ""() +; CHECK-NEXT: ret i32 3 +; 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 %cont] + +exit0: + ret i32 0; + +exit1: + ret i32 1; + +exit2: + ret i32 2; + +exit3: + ret i32 3; + +unreachable_bb: + unreachable +}