Skip to content

Commit

Permalink
[Profile] Implement new API __llvm_profile_dump
Browse files Browse the repository at this point in the history
The API is intended to be used by user to do fine
grained (per-region) control of profile dumping.

Differential Revision: http://reviews.llvm.org/D23106

llvm-svn: 278092
  • Loading branch information
david-xl committed Aug 9, 2016
1 parent 84907c5 commit 3b2c002
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 0 deletions.
11 changes: 11 additions & 0 deletions compiler-rt/lib/profile/InstrProfiling.c
Expand Up @@ -27,6 +27,16 @@ COMPILER_RT_VISIBILITY uint64_t __llvm_profile_get_magic(void) {
: (INSTR_PROF_RAW_MAGIC_32);
}

static unsigned ProfileDumped = 0;

COMPILER_RT_VISIBILITY unsigned lprofProfileDumped() {
return ProfileDumped;
}

COMPILER_RT_VISIBILITY void lprofSetProfileDumped() {
ProfileDumped = 1;
}

/* Return the number of bytes needed to add to SizeInBytes to make it
* the result a multiple of 8.
*/
Expand Down Expand Up @@ -68,4 +78,5 @@ COMPILER_RT_VISIBILITY void __llvm_profile_reset_counters(void) {
}
}
}
ProfileDumped = 0;
}
22 changes: 22 additions & 0 deletions compiler-rt/lib/profile/InstrProfiling.h
Expand Up @@ -117,6 +117,28 @@ void INSTR_PROF_VALUE_PROF_FUNC(
*/
int __llvm_profile_write_file(void);

/*!
* \brief this is a wrapper interface to \c __llvm_profile_write_file.
* After this interface is invoked, a arleady dumped flag will be set
* so that profile won't be dumped again during program exit.
* Invocation of interface __llvm_profile_reset_counters will clear
* the flag. This interface is designed to be used to collect profile
* data from user selected hot regions. The use model is
* __llvm_profile_reset_counters();
* ... hot region 1
* __llvm_profile_dump();
* .. some other code
* __llvm_profile_reset_counters();
* ... hot region 2
* __llvm_profile_dump();
*
* It is expected that on-line profile merging is on with \c %m specifier
* used in profile filename . If merging is not turned on, user is expected
* to invoke __llvm_profile_set_filename to specify different profile names
* for different regions before dumping to avoid profile write clobbering.
*/
int __llvm_profile_dump(void);

/*!
* \brief Set the filename for writing instrumentation data.
*
Expand Down
18 changes: 18 additions & 0 deletions compiler-rt/lib/profile/InstrProfilingFile.c
Expand Up @@ -522,6 +522,12 @@ int __llvm_profile_write_file(void) {
const char *Filename;
char *FilenameBuf;

if (lprofProfileDumped()) {
PROF_NOTE("Profile data not written to file: %s.\n",
"already written");
return 0;
}

Length = getCurFilenameLength();
FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
Filename = getCurFilename(FilenameBuf);
Expand All @@ -548,6 +554,18 @@ int __llvm_profile_write_file(void) {
return rc;
}

COMPILER_RT_VISIBILITY
int __llvm_profile_dump(void) {
if (!doMerging())
PROF_WARN("Later invocation of __llvm_profile_dump can lead to clobbering "
" of previously dumped profile data : %s. Either use \%m "
"in profile name or change profile name before dumping.\n",
"online profile merging is not on");
int rc = __llvm_profile_write_file();
lprofSetProfileDumped();
return rc;
}

static void writeFileWithoutReturn(void) { __llvm_profile_write_file(); }

COMPILER_RT_VISIBILITY
Expand Down
7 changes: 7 additions & 0 deletions compiler-rt/lib/profile/InstrProfilingInternal.h
Expand Up @@ -163,6 +163,13 @@ void lprofSetupValueProfiler();
* to dump merged profile data into its own profile file. */
uint64_t lprofGetLoadModuleSignature();

/*
* Return non zero value if the profile data has already been
* dumped to the file.
*/
unsigned lprofProfileDumped();
void lprofSetProfileDumped();

COMPILER_RT_VISIBILITY extern char *(*GetEnvHook)(const char *);
COMPILER_RT_VISIBILITY extern void (*FreeHook)(void *);
COMPILER_RT_VISIBILITY extern uint8_t *DynamicBufferIOBuffer;
Expand Down
62 changes: 62 additions & 0 deletions compiler-rt/test/profile/instrprof-dump.c
@@ -0,0 +1,62 @@
/*
RUN: rm -fr %t.profdir
RUN: %clang_profgen=%t.profdir/default_%m.profraw -o %t -O2 %s
RUN: %run %t 2>&1 | FileCheck %s --check-prefix=NO_EXIT_WRITE
RUN: llvm-profdata merge -o %t.profdata %t.profdir
RUN: %clang_profuse=%t.profdata -o - -S -emit-llvm %s | FileCheck %s --check-prefix=PROF
NO_EXIT_WRITE: Profile data not written to file: already written
*/

int __llvm_profile_dump(void);
void __llvm_profile_reset_counters(void);
int foo(int);
int bar(int);
int skip(int);

int main(int argc, const char *argv[]) {
int Ret = foo(0); /* region 1 */
__llvm_profile_dump();

/* not profiled -- cleared later. */
skip(0); /* skipped region */

__llvm_profile_reset_counters();
Ret += bar(0); /* region 2 */
__llvm_profile_dump();

skip(1);

__llvm_profile_reset_counters();
/* foo's profile will be merged. */
foo(1); /* region 3 */
__llvm_profile_dump();

return Ret;
}

__attribute__((noinline)) int foo(int X) {
/* PROF: define {{.*}} @foo({{.*}}!prof ![[ENT:[0-9]+]]
PROF: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD1:[0-9]+]]
*/
return X <= 0 ? -X : X;
}

__attribute__((noinline)) int skip(int X) {
/* PROF: define {{.*}} @skip(
PROF: br i1 %{{.*}}, label %{{.*}}, label %{{[^,]+$}}
*/
return X <= 0 ? -X : X;
}

__attribute__((noinline)) int bar(int X) {
/* PROF-LABEL: define {{.*}} @bar(
PROF: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD2:[0-9]+]]
*/
return X <= 0 ? -X : X;
}

/*
PROF: ![[ENT]] = !{!"function_entry_count", i64 2}
PROF: ![[PD1]] = !{!"branch_weights", i32 2, i32 2}
*/

0 comments on commit 3b2c002

Please sign in to comment.