OSDN Git Service

Fix coverage check for full post-dominator basic blocks.
authorGeorge Karpenkov <ekarpenkov@apple.com>
Thu, 25 May 2017 01:41:46 +0000 (01:41 +0000)
committerGeorge Karpenkov <ekarpenkov@apple.com>
Thu, 25 May 2017 01:41:46 +0000 (01:41 +0000)
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

lib/Transforms/Instrumentation/SanitizerCoverage.cpp
test/Instrumentation/SanitizerCoverage/chains.ll [new file with mode: 0644]
test/Instrumentation/SanitizerCoverage/postdominator_check.ll [new file with mode: 0644]

index 4bc0a71..300085e 100644 (file)
@@ -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 (file)
index 0000000..86b1091
--- /dev/null
@@ -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 (file)
index 0000000..c50d663
--- /dev/null
@@ -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()
+
+}