From f6cb5093853722a6d9f059f4e86435aa89e7491b Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Thu, 25 May 2017 01:41:46 +0000 Subject: [PATCH] Fix coverage check for full post-dominator basic blocks. Coverage instrumentation which does not instrument full post-dominators and full-dominators may skip valid paths, as the reasoning for skipping blocks may become circular. This patch fixes that, by only skipping full post-dominators with multiple predecessors, as such predecessors by definition can not be full-dominators. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@303827 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Instrumentation/SanitizerCoverage.cpp | 5 +- test/Instrumentation/SanitizerCoverage/chains.ll | 33 +++++++++ .../SanitizerCoverage/postdominator_check.ll | 85 ++++++++++++++++++++++ 3 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 test/Instrumentation/SanitizerCoverage/chains.ll create mode 100644 test/Instrumentation/SanitizerCoverage/postdominator_check.ll diff --git a/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/lib/Transforms/Instrumentation/SanitizerCoverage.cpp index 4bc0a713311..300085eccb0 100644 --- a/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ b/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -401,7 +401,10 @@ static bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB, if (Options.NoPrune || &F.getEntryBlock() == BB) return true; - return !(isFullDominator(BB, DT) || isFullPostDominator(BB, PDT)); + // Do not instrument full dominators, or full post-dominators with multiple + // predecessors. + return !isFullDominator(BB, DT) + && !(isFullPostDominator(BB, PDT) && !BB->getSinglePredecessor()); } bool SanitizerCoverageModule::runOnFunction(Function &F) { diff --git a/test/Instrumentation/SanitizerCoverage/chains.ll b/test/Instrumentation/SanitizerCoverage/chains.ll new file mode 100644 index 00000000000..86b109165ee --- /dev/null +++ b/test/Instrumentation/SanitizerCoverage/chains.ll @@ -0,0 +1,33 @@ +; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s + +define i32 @blah(i32) #0 { + %2 = icmp sgt i32 %0, 1 + br i1 %2, label %branch, label %exit +; CHECK: call void @__sanitizer_cov_trace_pc() + +branch: + br label %pos2 +; CHECK-LABEL: branch: +; CHECK-NOT: call void @__sanitizer_cov_trace_pc() + +pos2: + br label %pos3 +; CHECK-LABEL: pos2: +; CHECK-NOT: call void @__sanitizer_cov_trace_pc() + +pos3: + br label %pos4 +; CHECK-LABEL: pos3: +; CHECK-NOT: call void @__sanitizer_cov_trace_pc() + +pos4: + ret i32 0 +; CHECK-LABEL: pos4: +; CHECK: call void @__sanitizer_cov_trace_pc() + +exit: + ret i32 0 +; CHECK-LABEL: exit: +; CHECK: call void @__sanitizer_cov_trace_pc() + +} diff --git a/test/Instrumentation/SanitizerCoverage/postdominator_check.ll b/test/Instrumentation/SanitizerCoverage/postdominator_check.ll new file mode 100644 index 00000000000..c50d663eff8 --- /dev/null +++ b/test/Instrumentation/SanitizerCoverage/postdominator_check.ll @@ -0,0 +1,85 @@ +; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s +; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=0 -S | FileCheck %s --check-prefix=CHECK_NO_PRUNE + +define i32 @foo(i32) #0 { + %2 = icmp sgt i32 %0, 0 + br i1 %2, label %left, label %right +; CHECK: call void @__sanitizer_cov_trace_pc() + +; CHECK_NO_PRUNE: call void @__sanitizer_cov_trace_pc() + +left: + %3 = icmp sgt i32 %0, 10 + br i1 %3, label %left_left, label %left_right +; CHECK-LABEL: left: +; CHECK-NOT: call void @__sanitizer_cov_trace_pc() + +; CHECK_NO_PRUNE-LABEL: left: +; CHECK_NO_PRUNE: call void @__sanitizer_cov_trace_pc() + +left_left: + br label %left_join +; CHECK-LABEL: left_left: +; CHECK: call void @__sanitizer_cov_trace_pc() + +; CHECK_NO_PRUNE-LABEL: left_left: +; CHECK_NO_PRUNE: call void @__sanitizer_cov_trace_pc() + +left_right: + br label %left_join +; CHECK-LABEL: left_right: +; CHECK: call void @__sanitizer_cov_trace_pc() + +; CHECK_NO_PRUNE-LABEL: left_right: +; CHECK_NO_PRUNE: call void @__sanitizer_cov_trace_pc() + +left_join: + br label %finish +; CHECK-LABEL: left_join: +; CHECK-NOT: call void @__sanitizer_cov_trace_pc() + +; CHECK_NO_PRUNE-LABEL: left_join: +; CHECK_NO_PRUNE: call void @__sanitizer_cov_trace_pc() + +right: + %4 = icmp sgt i32 %0, 10 + br i1 %4, label %right_left, label %right_right +; CHECK-LABEL: right: +; CHECK-NOT: call void @__sanitizer_cov_trace_pc() + +; CHECK_NO_PRUNE-LABEL: right: +; CHECK_NO_PRUNE: call void @__sanitizer_cov_trace_pc() + +right_left: + br label %right_join +; CHECK-LABEL: right_left: +; CHECK: call void @__sanitizer_cov_trace_pc() + +; CHECK_NO_PRUNE-LABEL: right_left: +; CHECK_NO_PRUNE: call void @__sanitizer_cov_trace_pc() + +right_right: + br label %right_join +; CHECK-LABEL: right_right: +; CHECK: call void @__sanitizer_cov_trace_pc() + +; CHECK_NO_PRUNE-LABEL: right_right: +; CHECK_NO_PRUNE: call void @__sanitizer_cov_trace_pc() + +right_join: + br label %finish +; CHECK-LABEL: right_join: +; CHECK-NOT: call void @__sanitizer_cov_trace_pc() + +; CHECK_NO_PRUNE-LABEL: right_join: +; CHECK_NO_PRUNE: call void @__sanitizer_cov_trace_pc() + +finish: + ret i32 %0 +; CHECK-LABEL: finish: +; CHECK-NOT: call void @__sanitizer_cov_trace_pc() + +; CHECK_NO_PRUNE-LABEL: finish: +; CHECK_NO_PRUNE: call void @__sanitizer_cov_trace_pc() + +} -- 2.11.0