diff options
author | Justin Bogner <mail@justinbogner.com> | 2014-04-15 00:50:54 +0000 |
---|---|---|
committer | Justin Bogner <mail@justinbogner.com> | 2014-04-15 00:50:54 +0000 |
commit | 81ab90f7ed3c7420fca87c7339c823f136dcc4e5 (patch) | |
tree | fa6e1216d6a3f5f0efbbe8db3cb3ffa8f88589ad | |
parent | ddfadb46545686450598df07db5139fddeabba89 (diff) | |
download | bcm5719-llvm-81ab90f7ed3c7420fca87c7339c823f136dcc4e5.tar.gz bcm5719-llvm-81ab90f7ed3c7420fca87c7339c823f136dcc4e5.zip |
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.
llvm-svn: 206231
-rw-r--r-- | clang/lib/CodeGen/CGStmt.cpp | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenPGO.cpp | 14 | ||||
-rw-r--r-- | clang/test/Profile/Inputs/c-captured.profdata | 25 | ||||
-rw-r--r-- | clang/test/Profile/c-captured.c | 57 |
5 files changed, 101 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index d50d8b959a8..9ea53b3e1fb 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/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/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 7d5a59e99ed..ec9601e0644 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/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/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp index 4dbd01a6619..80c7e87de36 100644 --- a/clang/lib/CodeGen/CodeGenPGO.cpp +++ b/clang/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<ObjCMethodDecl *>(MD)); else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D)) Walker.TraverseDecl(const_cast<BlockDecl *>(BD)); + else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D)) + Walker.TraverseDecl(const_cast<CapturedDecl *>(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<BlockDecl>(D)) Walker.VisitBlockDecl(BD); + else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D)) + Walker.VisitCapturedDecl(const_cast<CapturedDecl *>(CD)); } void CodeGenPGO::applyFunctionAttributes(PGOProfileData *PGOData, diff --git a/clang/test/Profile/Inputs/c-captured.profdata b/clang/test/Profile/Inputs/c-captured.profdata new file mode 100644 index 00000000000..c2490d9b680 --- /dev/null +++ b/clang/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/clang/test/Profile/c-captured.c b/clang/test/Profile/c-captured.c new file mode 100644 index 00000000000..a2678ec6283 --- /dev/null +++ b/clang/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; +} |