: (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.
*/
}
}
}
+ ProfileDumped = 0;
}
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.
*
* Sets the filename to be used for subsequent calls to
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);
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
* 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;
--- /dev/null
+/*
+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}
+*/