summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h6
-rw-r--r--llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp2
-rw-r--r--llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp4
-rw-r--r--llvm/test/Instrumentation/SanitizerCoverage/unreachable-critedge.ll46
4 files changed, 57 insertions, 1 deletions
diff --git a/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h b/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
index 6ee649daa3f..4d861ffe9a3 100644
--- a/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
@@ -116,6 +116,7 @@ struct CriticalEdgeSplittingOptions {
bool MergeIdenticalEdges = false;
bool KeepOneInputPHIs = false;
bool PreserveLCSSA = false;
+ bool IgnoreUnreachableDests = false;
CriticalEdgeSplittingOptions(DominatorTree *DT = nullptr,
LoopInfo *LI = nullptr,
@@ -137,6 +138,11 @@ struct CriticalEdgeSplittingOptions {
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
diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
index 40151bc5d78..01e89d3c253 100644
--- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
+++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
@@ -535,7 +535,7 @@ bool SanitizerCoverageModule::runOnFunction(Function &F) {
isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
return false;
if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge)
- SplitAllCriticalEdges(F);
+ SplitAllCriticalEdges(F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests());
SmallVector<Instruction *, 8> IndirCalls;
SmallVector<BasicBlock *, 16> BlocksToInstrument;
SmallVector<Instruction *, 8> CmpTraceTargets;
diff --git a/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp b/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp
index 3b4b0b5de07..f5e4b53f6d9 100644
--- a/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp
+++ b/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp
@@ -153,6 +153,10 @@ llvm::SplitCriticalEdge(Instruction *TI, unsigned SuccNum,
if (isa<CallBrInst>(TI) && SuccNum > 0)
return nullptr;
+ if (Options.IgnoreUnreachableDests &&
+ isa<UnreachableInst>(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");
diff --git a/llvm/test/Instrumentation/SanitizerCoverage/unreachable-critedge.ll b/llvm/test/Instrumentation/SanitizerCoverage/unreachable-critedge.ll
new file mode 100644
index 00000000000..ad6cd574d7e
--- /dev/null
+++ b/llvm/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
+}
OpenPOWER on IntegriCloud