[compiler-rt] Add support for generating profiles in a given directory

Diego Novillo dnovillo at google.com
Thu Jun 25 16:04:31 PDT 2015


When the file is initialized, this patch checks whether the path
specifies a directory. If so, it creates the directory tree before
truncating the file.

Diego.
-------------- next part --------------
commit 4f8f47f317c9d94d525f22a026e19e0fc93f1dcc
Author: Diego Novillo <dnovillo at google.com>
Date:   Thu Jun 25 18:50:33 2015 -0400

    Add support for generating profiles in a given directory.
    
    When the file is initialized, this patch checks whether the path
    specifies a directory. If so, it creates the directory tree before
    truncating the file.

diff --git a/lib/profile/GCDAProfiling.c b/lib/profile/GCDAProfiling.c
index e32e97f..e245cf0 100644
--- a/lib/profile/GCDAProfiling.c
+++ b/lib/profile/GCDAProfiling.c
@@ -20,6 +20,8 @@
 |*
 \*===----------------------------------------------------------------------===*/
 
+#include "InstrProfiling.h"
+
 #include <errno.h>
 #include <fcntl.h>
 #include <stdio.h>
@@ -209,7 +211,8 @@ static char *mangle_filename(const char *orig_filename) {
   return new_filename;
 }
 
-static void recursive_mkdir(char *path) {
+__attribute__((visibility("hidden")))
+void __llvm_profile_recursive_mkdir(char *path) {
   int i;
 
   for (i = 1; path[i] != '\0'; ++i) {
@@ -283,7 +286,7 @@ void llvm_gcda_start_file(const char *orig_filename, const char version[4],
     fd = open(filename, O_RDWR | O_CREAT, 0644);
     if (fd == -1) {
       /* Try creating the directories first then opening the file. */
-      recursive_mkdir(filename);
+      __llvm_profile_recursive_mkdir(filename);
       fd = open(filename, O_RDWR | O_CREAT, 0644);
       if (fd == -1) {
         /* Bah! It's hopeless. */
diff --git a/lib/profile/InstrProfiling.h b/lib/profile/InstrProfiling.h
index 84b673c..123e384 100644
--- a/lib/profile/InstrProfiling.h
+++ b/lib/profile/InstrProfiling.h
@@ -64,7 +64,7 @@ uint64_t *__llvm_profile_end_counters(void);
  * or if it hasn't been called, the \c LLVM_PROFILE_FILE environment variable,
  * or if that's not set, the last name given to
  * \a __llvm_profile_override_default_filename(), or if that's not set,
- * \c "default.profdata".
+ * \c "default.profraw".
  */
 int __llvm_profile_write_file(void);
 
@@ -104,4 +104,7 @@ uint64_t __llvm_profile_get_magic(void);
 /*! \brief Get the version of the file format. */
 uint64_t __llvm_profile_get_version(void);
 
+/*! \brief Create a directory tree. */
+void __llvm_profile_recursive_mkdir(char *Pathname);
+
 #endif /* PROFILE_INSTRPROFILING_H_ */
diff --git a/lib/profile/InstrProfilingFile.c b/lib/profile/InstrProfilingFile.c
index 0102a25..3006bf9 100644
--- a/lib/profile/InstrProfilingFile.c
+++ b/lib/profile/InstrProfilingFile.c
@@ -84,6 +84,13 @@ static void truncateCurrentFile(void) {
   if (!Filename || !Filename[0])
     return;
 
+  /* Create the directory holding the file, if needed. */
+  if (strchr(Filename, '/')) {
+    char *Copy = malloc(strlen(Filename) + 1);
+    strcpy(Copy, Filename);
+    __llvm_profile_recursive_mkdir(Copy);
+  }
+
   /* Truncate the file.  Later we'll reopen and append. */
   File = fopen(Filename, "w");
   if (!File)
diff --git a/test/profile/Inputs/gcc-flag-compatibility.c b/test/profile/Inputs/gcc-flag-compatibility.c
new file mode 100644
index 0000000..1c07bb1
--- /dev/null
+++ b/test/profile/Inputs/gcc-flag-compatibility.c
@@ -0,0 +1,8 @@
+int X = 0;
+
+int main() {
+  int i;
+  for (i = 0; i < 100; i++)
+    X += i;
+  return 0;
+}
diff --git a/test/profile/gcc-flag-compatibility.test b/test/profile/gcc-flag-compatibility.test
new file mode 100644
index 0000000..77a38b8
--- /dev/null
+++ b/test/profile/gcc-flag-compatibility.test
@@ -0,0 +1,17 @@
+RUN: mkdir -p %t.d
+RUN: %clang_profgen_gcc=%t.d/d1/d2 -o %t.d/code %S/Inputs/gcc-flag-compatibility.c
+
+# Test that the instrumented code writes to %t.d/d1/d2/default.profraw
+RUN: %run %t.d/code
+RUN: llvm-profdata merge -o %t.profdata %t.d/d1/d2/default.profraw
+
+# Test that we can override the directory and file name with LLVM_PROFILE_FILE.
+RUN: env LLVM_PROFILE_FILE=%t.d/x1/prof.raw %run %t.d/code
+RUN: llvm-profdata merge -o %t.profdata %t.d/x1/prof.raw
+
+# Test that we can specify a directory with -fprofile-use.
+RUN: llvm-profdata merge -o %t.d/pgo-data %t.d/x1/prof.raw
+RUN: %clang_profuse_gcc=%t.d -o %t.d/code %S/Inputs/gcc-flag-compatibility.c
+
+# Test that we can specify a file with -fprofile-use.
+RUN: %clang_profuse_gcc=%t.profdata -o %t.d/code %S/Inputs/gcc-flag-compatibility.c
diff --git a/test/profile/lit.cfg b/test/profile/lit.cfg
index e4910ab..b1b44a1 100644
--- a/test/profile/lit.cfg
+++ b/test/profile/lit.cfg
@@ -45,6 +45,8 @@ def build_invocation(compile_flags):
 config.substitutions.append( ("%clang ", build_invocation(clang_cflags)) )
 config.substitutions.append( ("%clang_profgen ", build_invocation(clang_cflags) + " -fprofile-instr-generate ") )
 config.substitutions.append( ("%clang_profuse=", build_invocation(clang_cflags) + " -fprofile-instr-use=") )
+config.substitutions.append( ("%clang_profgen_gcc=", build_invocation(clang_cflags) + " -fprofile-generate=") )
+config.substitutions.append( ("%clang_profuse_gcc=", build_invocation(clang_cflags) + " -fprofile-use=") )
 
 if config.host_os not in ['Darwin', 'FreeBSD', 'Linux']:
   config.unsupported = True


More information about the llvm-commits mailing list