Files
swift-mirror/test/Profiler/coverage_if.swift
Hamish Knight c3b055a9a8 [Profiler] Improve if statement coverage
Fix counters for regions following `else if`s, fix
the counters for `else if` conditions, and fix
handling of `break` statements. Also while here,
clean up the handling of branch exit regions such
that we don't generate multiple overlapping
regions for each branch, but a single region at
the end of the entire `if` statement that accounts
for all exiting control flow.

rdar://104078910
rdar://104079242
2023-12-04 11:09:01 +00:00

232 lines
11 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -profile-generate -profile-coverage-mapping -emit-sorted-sil -emit-sil -module-name coverage_if %s | %FileCheck %s
// RUN: %target-swift-frontend -profile-generate -profile-coverage-mapping -emit-ir %s
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo
func foo(x : Bool) { // CHECK: [[@LINE]]:20 -> {{[0-9]+}}:2 : 0
// CHECK: [[@LINE+1]]:6 -> [[@LINE+1]]:9 : 0
if (x) { // CHECK: [[@LINE]]:10 -> [[@LINE+1]]:4 : 1
}
if (!x) { // CHECK: [[@LINE]]:11 -> [[@LINE+2]]:4 : 2
// ...
}
if (x) { } // CHECK: [[@LINE]]:10 -> [[@LINE]]:13 : 3
else { } // CHECK: [[@LINE]]:10 -> [[@LINE]]:13 : (0 - 3)
}
foo(x: true);
foo(x: false);
// rdar://29390569 Make sure we don't add a spurious unreachable empty region.
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo1
func foo1() -> Int { // CHECK-NEXT: [[@LINE]]:20 -> {{[0-9]+}}:2 : 0
if .random() { // CHECK-NEXT: [[@LINE]]:6 -> [[@LINE]]:15 : 0
return 0 // CHECK-NEXT: [[@LINE-1]]:16 -> [[@LINE+1]]:4 : 1
} else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : (0 - 1)
return 1 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 2
} else { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+2]]:4 : ((0 - 1) - 2)
return 2
} // CHECK-NEXT: }
}
// ...but we will add an unreachable region if you write code there.
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo2
func foo2() -> Int {
if .random() {
return 0
} else if .random() {
return 1
} else {
return 2
}
_ = foo1() // CHECK: [[@LINE]]:3 -> [[@LINE+1]]:2 : zero
}
// Make sure we don't add unreachable regions for a labeled jump either.
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo3
func foo3() -> Int { // CHECK-NEXT: [[@LINE]]:20 -> {{[0-9]+}}:2 : 0
x: do { // CHECK-NEXT: [[@LINE]]:9 -> [[@LINE+6]]:4 : 0
if .random() { // CHECK-NEXT: [[@LINE]]:8 -> [[@LINE]]:17 : 0
return 0 // CHECK-NEXT: [[@LINE-1]]:18 -> [[@LINE+1]]:6 : 1
} else { // CHECK-NEXT: [[@LINE]]:12 -> [[@LINE+2]]:6 : (0 - 1)
break x
}
} // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:11 : (0 - 1)
return 2
} // CHECK-NEXT: }
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo4
func foo4() -> Int {
x: do {
if .random() {
return 0
} else {
break x
}
let y = 0 // CHECK: [[@LINE]]:13 -> [[@LINE+1]]:4 : zero
}
return 2
}
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo5
func foo5() throws -> Int { // CHECK-NEXT: [[@LINE]]:27 -> {{[0-9]+}}:2 : 0
if .random() { // CHECK-NEXT: [[@LINE]]:6 -> [[@LINE]]:15 : 0
return 0 // CHECK-NEXT: [[@LINE-1]]:16 -> [[@LINE+1]]:4 : 1
} else { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+3]]:4 : (0 - 1)
struct S: Error {}
throw S()
}
} // CHECK-NEXT: }
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo6
func foo6(_ x: Int?) -> Int? { // CHECK-NEXT: [[@LINE]]:30 -> {{[0-9]+}}:2 : 0
if let x = x { // CHECK-NEXT: [[@LINE]]:16 -> [[@LINE+2]]:4 : 1
return x
} else { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+2]]:4 : (0 - 1)
return nil
}
} // CHECK-NEXT: }
// rdar://104078910, rdar://104079242 - Make sure the else if condition and the
// else gets a correct counter here.
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo7
func foo7() -> Int { // CHECK-NEXT: [[@LINE]]:20 -> [[@LINE+12]]:2 : 0
let x: Int
if .random() { // CHECK-NEXT: [[@LINE]]:6 -> [[@LINE]]:15 : 0
x = 0 // CHECK-NEXT: [[@LINE-1]]:16 -> [[@LINE+1]]:4 : 1
} else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : (0 - 1)
x = 1 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 2
} else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : ((0 - 1) - 2)
x = 2 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 3
} else { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+2]]:4 : (((0 - 1) - 2) - 3)
x = 3
}
return x
} // CHECK-NEXT: }
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo8
func foo8() -> Int { // CHECK-NEXT: [[@LINE]]:20 -> [[@LINE+12]]:2 : 0
let x: Int // CHECK-NEXT: [[@LINE+1]]:6 -> [[@LINE+1]]:15 : 0
if .random() { // CHECK-NEXT: [[@LINE]]:16 -> [[@LINE+2]]:4 : 1
return 0
} else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : (0 - 1)
x = 1 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 2
} else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : ((0 - 1) - 2)
x = 2 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 3
} else { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+2]]:4 : (((0 - 1) - 2) - 3)
x = 3
} // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:11 : (0 - 1)
return x
} // CHECK-NEXT: }
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo9
func foo9() -> Int { // CHECK-NEXT: [[@LINE]]:20 -> [[@LINE+12]]:2 : 0
let x: Int // CHECK-NEXT: [[@LINE+1]]:6 -> [[@LINE+1]]:15 : 0
if .random() { // CHECK-NEXT: [[@LINE]]:16 -> [[@LINE+2]]:4 : 1
return 0
} else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : (0 - 1)
return 1 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 2
} else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : ((0 - 1) - 2)
x = 2 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 3
} else { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+2]]:4 : (((0 - 1) - 2) - 3)
x = 3
} // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:11 : ((0 - 1) - 2)
return x
} // CHECK-NEXT: }
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo10
func foo10() -> Int { // CHECK-NEXT: [[@LINE]]:21 -> [[@LINE+12]]:2 : 0
let x: Int // CHECK-NEXT: [[@LINE+1]]:6 -> [[@LINE+1]]:15 : 0
if .random() { // CHECK-NEXT: [[@LINE]]:16 -> [[@LINE+2]]:4 : 1
return 0
} else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : (0 - 1)
return 1 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 2
} else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : ((0 - 1) - 2)
x = 2 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 3
} else { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+2]]:4 : (((0 - 1) - 2) - 3)
return 3
} // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:11 : 3
return x
} // CHECK-NEXT: }
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo11
func foo11() -> Int { // CHECK-NEXT: [[@LINE]]:21 -> [[@LINE+12]]:2 : 0
let x: Int // CHECK-NEXT: [[@LINE+1]]:6 -> [[@LINE+1]]:15 : 0
if .random() { // CHECK-NEXT: [[@LINE]]:16 -> [[@LINE+2]]:4 : 1
x = 0
} else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : (0 - 1)
x = 1 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 2
} else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : ((0 - 1) - 2)
x = 2 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 3
} else { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+2]]:4 : (((0 - 1) - 2) - 3)
return 3
} // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:11 : ((1 + 2) + 3)
return x
} // CHECK-NEXT: }
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo12
func foo12() -> Int { // CHECK-NEXT: [[@LINE]]:21 -> [[@LINE+9]]:2 : 0
let x: Int
y: if .random() { // CHECK-NEXT: [[@LINE]]:9 -> [[@LINE]]:18 : 0
x = 0 // CHECK-NEXT: [[@LINE-1]]:19 -> [[@LINE+2]]:4 : 1
break y
} else {
x = 1 // CHECK-NEXT: [[@LINE-1]]:10 -> [[@LINE+1]]:4 : (0 - 1)
}
return x
} // CHECK-NEXT: }
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo13
func foo13() -> Int { // CHECK-NEXT: [[@LINE]]:21 -> [[@LINE+10]]:2 : 0
let x: Int
y: if .random() { // CHECK-NEXT: [[@LINE]]:9 -> [[@LINE]]:18 : 0
x = 0 // CHECK-NEXT: [[@LINE-1]]:19 -> [[@LINE+2]]:4 : 1
break y
} else {
x = 1 // CHECK-NEXT: [[@LINE-1]]:10 -> [[@LINE+2]]:4 : (0 - 1)
break y
}
return x
} // CHECK-NEXT: }
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo14
func foo14() -> Int { // CHECK-NEXT: [[@LINE]]:21 -> [[@LINE+14]]:2 : 0
let x: Int // CHECK-NEXT: [[@LINE+1]]:9 -> [[@LINE+1]]:18 : 0
y: if .random() { // CHECK-NEXT: [[@LINE]]:19 -> [[@LINE+3]]:4 : 1
x = 0
break y
} else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : (0 - 1)
return 1 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 2
} else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : ((0 - 1) - 2)
x = 2 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+2]]:4 : 3
break y
} else { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+2]]:4 : (((0 - 1) - 2) - 3)
return 3
} // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:11 : (1 + 3)
return x
} // CHECK-NEXT: }
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo15
func foo15() -> Int { // CHECK-NEXT: [[@LINE]]:21 -> [[@LINE+19]]:2 : 0
let x: Int // CHECK-NEXT: [[@LINE+1]]:9 -> [[@LINE+1]]:18 : 0
y: if .random() { // CHECK-NEXT: [[@LINE]]:19 -> [[@LINE+5]]:4 : 1
x = 0
if .random() { // CHECK-NEXT: [[@LINE]]:8 -> [[@LINE]]:17 : 1
break y // CHECK-NEXT: [[@LINE-1]]:18 -> [[@LINE+1]]:6 : 2
} // CHECK-NEXT: [[@LINE]]:6 -> [[@LINE+1]]:4 : (1 - 2)
} else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : (0 - 1)
x = 1 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+4]]:4 : 3
if .random() { // CHECK-NEXT: [[@LINE]]:8 -> [[@LINE]]:17 : 3
return 1 // CHECK-NEXT: [[@LINE-1]]:18 -> [[@LINE+1]]:6 : 4
} // CHECK-NEXT: [[@LINE]]:6 -> [[@LINE+1]]:4 : (3 - 4)
} else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : ((0 - 1) - 3)
x = 2 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+2]]:4 : 5
break y
} else { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+2]]:4 : (((0 - 1) - 3) - 5)
return 3
} // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:11 : (((1 + 3) + 5) - 4)
return x
} // CHECK-NEXT: }