[Profiler] Limit decl walking behavior

Unify the mapped behavior with the unmapped
behavior and only ever walk into a pattern binding
decls, top-level code decls, and non-nested
functions. This avoids walking into e.g nested
types, leading to duplicate coverage.

We don't need to handle the unmapped behavior
separately, as top-level code decls are always
explicit, and non-nested functions are always
checked when we create the profiler.

rdar://99963912
This commit is contained in:
Hamish Knight
2022-09-15 17:01:43 +01:00
parent 30568a60a8
commit b7d3f502fe
3 changed files with 43 additions and 30 deletions

View File

@@ -211,8 +211,9 @@ shouldSkipExpr(Expr *E, ASTWalker::ParentTy Parent) {
return None;
}
/// Whether the children of an unmapped decl should still be walked.
static bool shouldWalkUnmappedDecl(const Decl *D) {
/// Whether the children of a decl that isn't explicitly handled should be
/// walked.
static bool shouldWalkIntoUnhandledDecl(const Decl *D) {
// We want to walk into the initializer for a pattern binding decl. This
// allows us to map LazyInitializerExprs.
return isa<PatternBindingDecl>(D);
@@ -252,15 +253,13 @@ struct MapRegionCounters : public ASTWalker {
}
PreWalkAction walkToDeclPre(Decl *D) override {
if (isUnmapped(D))
return Action::VisitChildrenIf(shouldWalkUnmappedDecl(D));
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D)) {
return visitFunctionDecl(*this, AFD, [&] { mapRegion(AFD->getBody()); });
} else if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(D)) {
mapRegion(TLCD->getBody());
return Action::Continue();
}
return Action::Continue();
return Action::VisitChildrenIf(shouldWalkIntoUnhandledDecl(D));
}
PreWalkResult<Stmt *> walkToStmtPre(Stmt *S) override {
@@ -601,17 +600,16 @@ struct PGOMapping : public ASTWalker {
}
PreWalkAction walkToDeclPre(Decl *D) override {
if (isUnmapped(D))
return Action::VisitChildrenIf(shouldWalkUnmappedDecl(D));
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D)) {
return visitFunctionDecl(*this, AFD, [&] {
setKnownExecutionCount(AFD->getBody());
});
}
if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(D))
if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(D)) {
setKnownExecutionCount(TLCD->getBody());
return Action::Continue();
return Action::Continue();
}
return Action::VisitChildrenIf(shouldWalkIntoUnhandledDecl(D));
}
LazyInitializerWalking getLazyInitializerWalkingBehavior() override {
@@ -974,9 +972,6 @@ public:
}
PreWalkAction walkToDeclPre(Decl *D) override {
if (isUnmapped(D))
return Action::VisitChildrenIf(shouldWalkUnmappedDecl(D));
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D)) {
return visitFunctionDecl(*this, AFD, [&] {
assignCounter(AFD->getBody());
@@ -984,8 +979,9 @@ public:
} else if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(D)) {
assignCounter(TLCD->getBody());
ImplicitTopLevelBody = TLCD->getBody();
return Action::Continue();
}
return Action::Continue();
return Action::VisitChildrenIf(shouldWalkIntoUnhandledDecl(D));
}
PostWalkAction walkToDeclPost(Decl *D) override {

View File

@@ -0,0 +1,32 @@
// RUN: %target-swift-frontend -emit-sil -profile-generate -profile-coverage-mapping -Xllvm -sil-full-demangle -emit-sorted-sil -module-name coverage_nested %s | %FileCheck %s
// RUN: %target-swift-frontend -profile-generate -profile-coverage-mapping -emit-ir %s
// https://github.com/apple/swift/issues/61129 Make sure we don't emit
// duplicate coverage for a nested type.
// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_nested13hasNestedTypeyyF" {{.*}} // coverage_nested.hasNestedType() -> ()
// CHECK-NEXT: [[@LINE+2]]:22 -> [[@LINE+11]]:2 : 0
// CHECK-NEXT: }
func hasNestedType() {
struct S {
// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_nested13hasNestedTypeyyF1SL_V1iSivpfi" {{.*}} // variable initialization expression of i : Swift.Int in S #1 in coverage_nested.hasNestedType() -> ()
// CHECK-NEXT: [[@LINE+4]]:13 -> [[@LINE+4]]:30 : 0
// CHECK-NEXT: [[@LINE+3]]:25 -> [[@LINE+3]]:26 : 1
// CHECK-NEXT: [[@LINE+2]]:29 -> [[@LINE+2]]:30 : (0 - 1)
// CHECK-NEXT: }
var i = .random() ? 0 : 1
}
}
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_nested.call_auto_closure()
// CHECK-NEXT: [[@LINE+3]]:26 -> [[@LINE+10]]:2 : 0
// CHECK-NEXT: }
func call_auto_closure() {
// CHECK-LABEL: sil_coverage_map {{.*}}// use_auto_closure #1 (@autoclosure () -> Swift.Bool) -> Swift.Bool in coverage_nested.call_auto_closure()
// CHECK-NEXT: [[@LINE+1]]:63 -> [[@LINE+3]]:4 : 0
func use_auto_closure(_ x: @autoclosure () -> Bool) -> Bool {
return x() // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}1
}
let _ = use_auto_closure(false || true)
}

View File

@@ -1,15 +0,0 @@
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -profile-generate -profile-coverage-mapping -emit-sil -module-name coverage_autoclosure %s | %FileCheck %s
// RUN: %target-swift-frontend -profile-generate -profile-coverage-mapping -emit-ir %s
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_autoclosure.call_auto_closure()
// CHECK-NEXT: [[@LINE+3]]:26 -> [[@LINE+10]]:2 : 0
// CHECK-NEXT: }
func call_auto_closure() {
// CHECK-LABEL: sil_coverage_map {{.*}}// use_auto_closure #1 (@autoclosure () -> Swift.Bool) -> Swift.Bool in coverage_autoclosure.call_auto_closure()
// CHECK-NEXT: [[@LINE+1]]:63 -> [[@LINE+3]]:4 : 0
func use_auto_closure(_ x: @autoclosure () -> Bool) -> Bool {
return x() // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}1
}
let _ = use_auto_closure(false || true)
}