mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[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:
@@ -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 {
|
||||
|
||||
32
test/Profiler/coverage_nested.swift
Normal file
32
test/Profiler/coverage_nested.swift
Normal 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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
Reference in New Issue
Block a user