Skip to content

Commit d1eb6f9

Browse files
committed
[Profiler] Avoid introducing empty unreachable regions
When computing the counter for the region following a labeled statement such as `if`, avoid adding a new empty region if the counter for such a region is known to be zero, i.e unreachable. This avoids adding spurious unreachable regions after an if statements where each branch returns, throws, or otherwise jumps to a parent statement. We will however still add the region if any code follows such a statement, making it non-empty. rdar://29390569
1 parent c1ae4ed commit d1eb6f9

File tree

2 files changed

+82
-1
lines changed

2 files changed

+82
-1
lines changed

lib/SIL/IR/SILProfiler.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,17 @@ struct CoverageMapping : public ASTWalker {
814814
if (ControlFlowAdjust)
815815
Count = &createCounter(CounterExpr::Sub(*Count, *ControlFlowAdjust));
816816

817-
RegionStack.emplace_back(ASTNode(), *Count, getEndLoc(Scope), None);
817+
if (Count->isSemanticallyZero()) {
818+
// If the counter is semantically zero, form an 'incomplete' region with
819+
// no starting location. This prevents forming unreachable regions unless
820+
// there is a following statement or expression to extend the region.
821+
RegionStack.emplace_back(ASTNode(), *Count, None, None);
822+
} else {
823+
// Otherwise, we have a non-zero counter, so form a new region starting
824+
// at the end of the previous scope. This ensures the user covers both
825+
// branches of a condition.
826+
RegionStack.emplace_back(ASTNode(), *Count, getEndLoc(Scope), None);
827+
}
818828
}
819829

820830
/// Push a region covering \c Node onto the stack.

test/Profiler/coverage_if.swift

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,74 @@ func foo(x : Bool) { // CHECK: [[@LINE]]:20 -> {{[0-9]+}}:2 : 0
1717

1818
foo(x: true);
1919
foo(x: false);
20+
21+
// rdar://29390569 – Make sure we don't add a spurious unreachable empty region.
22+
23+
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo1
24+
func foo1() -> Int { // CHECK: [[@LINE]]:20 -> {{[0-9]+}}:2 : 0
25+
if .random() { // CHECK: [[@LINE]]:6 -> [[@LINE]]:15 : 0
26+
return 0 // CHECK: [[@LINE-1]]:16 -> [[@LINE+2]]:4 : 1
27+
// CHECK: [[@LINE+1]]:4 -> {{[0-9]+}}:2 : (0 - 1)
28+
} else if .random() { // CHECK: [[@LINE]]:13 -> [[@LINE]]:22 : (0 - 1)
29+
return 1 // CHECK: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 2
30+
} else { // CHECK: [[@LINE]]:4 -> {{[0-9]+}}:2 : ((0 - 1) - 2)
31+
return 2 // CHECK: [[@LINE-1]]:10 -> [[@LINE+1]]:4 : ((0 - 1) - 2)
32+
} // CHECK-NOT: zero
33+
}
34+
35+
// ...but we will add an unreachable region if you write code there.
36+
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo2
37+
func foo2() -> Int {
38+
if .random() {
39+
return 0
40+
} else if .random() {
41+
return 1
42+
} else {
43+
return 2
44+
}
45+
_ = foo1() // CHECK: [[@LINE]]:3 -> [[@LINE+1]]:2 : zero
46+
}
47+
48+
// Make sure we don't add unreachable regions for a labeled jump either.
49+
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo3
50+
func foo3() -> Int { // CHECK: [[@LINE]]:20 -> {{[0-9]+}}:2 : 0
51+
x: do { // CHECK: [[@LINE]]:9 -> [[@LINE+6]]:4 : 0
52+
if .random() { // CHECK: [[@LINE]]:8 -> [[@LINE]]:17 : 0
53+
return 0 // CHECK: [[@LINE-1]]:18 -> [[@LINE+1]]:6 : 1
54+
} else { // CHECK: [[@LINE]]:6 -> [[@LINE+3]]:4 : (0 - 1)
55+
break x // CHECK: [[@LINE-1]]:12 -> [[@LINE+1]]:6 : (0 - 1)
56+
} // CHECK-NOT: zero
57+
}
58+
return 2
59+
}
60+
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo4
61+
func foo4() -> Int {
62+
x: do {
63+
if .random() {
64+
return 0
65+
} else {
66+
break x
67+
}
68+
let y = 0 // CHECK: [[@LINE]]:13 -> [[@LINE+1]]:4 : zero
69+
}
70+
return 2
71+
}
72+
73+
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo5
74+
func foo5() throws -> Int { // CHECK: [[@LINE]]:27 -> {{[0-9]+}}:2 : 0
75+
if .random() { // CHECK: [[@LINE]]:6 -> [[@LINE]]:15 : 0
76+
return 0 // CHECK: [[@LINE-1]]:16 -> [[@LINE+1]]:4 : 1
77+
} else { // CHECK: [[@LINE]]:4 -> {{[0-9]+}}:2 : (0 - 1)
78+
struct S: Error {} // CHECK: [[@LINE-1]]:10 -> [[@LINE+2]]:4 : (0 - 1)
79+
throw S()
80+
} // CHECK-NOT: zero
81+
}
82+
83+
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo6
84+
func foo6(_ x: Int?) -> Int? { // CHECK: [[@LINE]]:30 -> {{[0-9]+}}:2 : 0
85+
if let x = x {
86+
return x // CHECK: [[@LINE-1]]:16 -> [[@LINE+1]]:4 : 1
87+
} else { // CHECK: [[@LINE]]:4 -> {{[0-9]+}}:2 : (0 - 1)
88+
return nil // CHECK: [[@LINE-1]]:10 -> [[@LINE+1]]:4 : (0 - 1)
89+
} // CHECK-NOT: zero
90+
}

0 commit comments

Comments
 (0)