From c087dce5222a15b327b895ffc194e3c9e0a33e4e Mon Sep 17 00:00:00 2001 From: Justin Bogner Date: Tue, 15 Apr 2014 00:50:54 +0000 Subject: [PATCH] CodeGen: Handle CapturedStmt in instrumentation based profiling CapturedStmt was being ignored by instrumentation based profiling, and its counters attributed to the containing function. Instead, we need to treat this as a top level entity, like we do with blocks. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@206231 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGStmt.cpp | 3 ++ lib/CodeGen/CodeGenFunction.h | 2 + lib/CodeGen/CodeGenPGO.cpp | 14 ++++++ test/Profile/Inputs/c-captured.profdata | 25 +++++++++++ test/Profile/c-captured.c | 57 +++++++++++++++++++++++++ 5 files changed, 101 insertions(+) create mode 100644 test/Profile/Inputs/c-captured.profdata create mode 100644 test/Profile/c-captured.c diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index d50d8b959a..9ea53b3e1f 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -1962,8 +1962,11 @@ CodeGenFunction::GenerateCapturedStmtFunction(const CapturedDecl *CD, CXXThisValue = EmitLoadOfLValue(ThisLValue, Loc).getScalarVal(); } + PGO.assignRegionCounters(CD, F); CapturedStmtInfo->EmitBody(*this, CD->getBody()); FinishFunction(CD->getBodyRBrace()); + PGO.emitInstrumentationData(); + PGO.destroyRegionCounters(); return F; } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 7d5a59e99e..ec9601e064 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -195,6 +195,8 @@ public: /// \brief Emit the captured statement body. virtual void EmitBody(CodeGenFunction &CGF, Stmt *S) { + RegionCounter Cnt = CGF.getPGORegionCounter(S); + Cnt.beginRegion(CGF.Builder); CGF.EmitStmt(S); } diff --git a/lib/CodeGen/CodeGenPGO.cpp b/lib/CodeGen/CodeGenPGO.cpp index 4dbd01a661..80c7e87de3 100644 --- a/lib/CodeGen/CodeGenPGO.cpp +++ b/lib/CodeGen/CodeGenPGO.cpp @@ -335,6 +335,7 @@ namespace { // traverse them in the parent context. bool TraverseBlockExpr(BlockExpr *BE) { return true; } bool TraverseLambdaBody(LambdaExpr *LE) { return true; } + bool TraverseCapturedStmt(CapturedStmt *CS) { return true; } bool VisitDecl(const Decl *D) { switch (D->getKind()) { @@ -347,6 +348,7 @@ namespace { case Decl::CXXConversion: case Decl::ObjCMethod: case Decl::Block: + case Decl::Captured: CounterMap[D->getBody()] = NextCounter++; break; } @@ -437,6 +439,14 @@ namespace { // parent context. void VisitLambdaExpr(const LambdaExpr *LE) {} + void VisitCapturedDecl(const CapturedDecl *D) { + // Counter tracks entry to the capture body. + RegionCounter Cnt(PGO, D->getBody()); + Cnt.beginRegion(); + CountMap[D->getBody()] = PGO.getCurrentRegionCount(); + Visit(D->getBody()); + } + void VisitObjCMethodDecl(const ObjCMethodDecl *D) { // Counter tracks entry to the method body. RegionCounter Cnt(PGO, D->getBody()); @@ -838,6 +848,8 @@ void CodeGenPGO::mapRegionCounters(const Decl *D) { Walker.TraverseDecl(const_cast(MD)); else if (const BlockDecl *BD = dyn_cast_or_null(D)) Walker.TraverseDecl(const_cast(BD)); + else if (const CapturedDecl *CD = dyn_cast_or_null(D)) + Walker.TraverseDecl(const_cast(CD)); NumRegionCounters = Walker.NextCounter; // FIXME: The number of counters isn't sufficient for the hash FunctionHash = NumRegionCounters; @@ -852,6 +864,8 @@ void CodeGenPGO::computeRegionCounts(const Decl *D) { Walker.VisitObjCMethodDecl(MD); else if (const BlockDecl *BD = dyn_cast_or_null(D)) Walker.VisitBlockDecl(BD); + else if (const CapturedDecl *CD = dyn_cast_or_null(D)) + Walker.VisitCapturedDecl(const_cast(CD)); } void CodeGenPGO::applyFunctionAttributes(PGOProfileData *PGOData, diff --git a/test/Profile/Inputs/c-captured.profdata b/test/Profile/Inputs/c-captured.profdata new file mode 100644 index 0000000000..c2490d9b68 --- /dev/null +++ b/test/Profile/Inputs/c-captured.profdata @@ -0,0 +1,25 @@ +c-captured.c:__captured_stmt +2 +2 +1 +1 + +c-captured.c:__captured_stmt1 +3 +3 +1 +10 +1 + +main +1 +1 +1 + +debug_captured +3 +3 +1 +1 +1 + diff --git a/test/Profile/c-captured.c b/test/Profile/c-captured.c new file mode 100644 index 0000000000..a2678ec628 --- /dev/null +++ b/test/Profile/c-captured.c @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-captured.c %s -o - -emit-llvm -fprofile-instr-generate | FileCheck -check-prefix=PGOGEN -check-prefix=PGOALL %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-captured.c %s -o - -emit-llvm -fprofile-instr-use=%S/Inputs/c-captured.profdata | FileCheck -check-prefix=PGOUSE -check-prefix=PGOALL %s + +// PGOGEN: @[[DCC:__llvm_profile_counters_debug_captured]] = global [3 x i64] zeroinitializer +// PGOGEN: @[[CSC:__llvm_profile_counters___captured_stmt]] = internal global [2 x i64] zeroinitializer +// PGOGEN: @[[C1C:__llvm_profile_counters___captured_stmt1]] = internal global [3 x i64] zeroinitializer + +// PGOALL-LABEL: define void @debug_captured() +// PGOGEN: store {{.*}} @[[DCC]], i64 0, i64 0 +void debug_captured() { + int x = 10; + + // Check both debug_captured counters, so we can do this all in one pass + // PGOGEN: store {{.*}} @[[DCC]], i64 0, i64 1 + // PGOUSE: br {{.*}} !prof ![[DC1:[0-9]+]] + // PGOGEN: store {{.*}} @[[DCC]], i64 0, i64 2 + // PGOUSE: br {{.*}} !prof ![[DC2:[0-9]+]] + // PGOALL: ret + + // PGOALL-LABEL: define internal void @__captured_stmt( + // PGOGEN: store {{.*}} @[[CSC]], i64 0, i64 0 + #pragma clang __debug captured + { + // PGOGEN: store {{.*}} @[[CSC]], i64 0, i64 1 + // PGOUSE: br {{.*}} !prof ![[CS1:[0-9]+]] + if (x) {} + // PGOALL: ret + } + + if (x) {} // This is DC1. Checked above. + + // PGOALL-LABEL: define internal void @__captured_stmt1( + // PGOGEN: store {{.*}} @[[C1C]], i64 0, i64 0 + #pragma clang __debug captured + { + // PGOGEN: store {{.*}} @[[C1C]], i64 0, i64 1 + // PGOUSE: br {{.*}} !prof ![[C11:[0-9]+]] + for (int i = 0; i < x; ++i) {} + // PGOGEN: store {{.*}} @[[C1C]], i64 0, i64 2 + // PGOUSE: br {{.*}} !prof ![[C12:[0-9]+]] + if (x) {} + // PGOALL: ret + } + + if (x) {} // This is DC2. Checked above. +} + +// PGOUSE-DAG: ![[DC1]] = metadata !{metadata !"branch_weights", i32 2, i32 1} +// PGOUSE-DAG: ![[DC2]] = metadata !{metadata !"branch_weights", i32 2, i32 1} +// PGOUSE-DAG: ![[CS1]] = metadata !{metadata !"branch_weights", i32 2, i32 1} +// PGOUSE-DAG: ![[C11]] = metadata !{metadata !"branch_weights", i32 11, i32 2} +// PGOUSE-DAG: ![[C12]] = metadata !{metadata !"branch_weights", i32 2, i32 1} + +int main(int argc, const char *argv[]) { + debug_captured(); + return 0; +} -- 2.40.0