]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Improve handling of profiling options
authorJoel Rosdahl <joel@rosdahl.net>
Thu, 30 Apr 2020 06:29:31 +0000 (08:29 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Fri, 1 May 2020 12:45:02 +0000 (14:45 +0200)
Handling of -fprofile-{generate,use}[=path] was implemented in PR #2
(2011). ccache has since then gained support for Clang, which is not
GCC-compatible for -fprofile-{generate,use}[=path]. Furthermore, GCC 9
changed the semantics of -fprofile-{generate,use}=path, making it
incompatible with ccache’s original implementation.

One crucial problem with the implementation is that there is no error
handling when the expected profiling data file cannot be found. This
means that there will be false positives cache hits for Clang and GCC
9+.

Fix this by:

* Checking for different profiling data file locations to handle
  different compilers and versions.
* Bailing out if no profiling data file can be found.

Also:

* Implemented support for Clang’s -fprofile-instr-{generate,use}[=path]
  options.
* Implemented support for -fauto-profile[=path].
* Removed the conversion of absolute path to the profile directory.
  91a2954e says that the directory is rewritten to increase the hit
  rate, but I don’t understand how that could be the case.
* Added tests for the profiling options. Exception:
  -fauto-profile[=path], since that would require running the perf tool.

Fixes #582.

(cherry picked from commit c9fdcef576dd13a2ea2355bcd866b5c561cb1562)

src/ArgsInfo.hpp
src/ccache.cpp
test/run
test/suites/profiling.bash [new file with mode: 0644]
test/suites/profiling_clang.bash [new file with mode: 0644]
test/suites/profiling_gcc.bash [new file with mode: 0644]
unittest/test_argument_processing.cpp

index 76a9a708ab78df3775658335820adc6ba3f37484..9b85fbe469e37dd4595903618879e1dc1bfc6b0b 100644 (file)
@@ -79,8 +79,8 @@ struct ArgsInfo
   // Is the compiler being asked to output coverage data (.gcda) at runtime?
   bool profile_arcs = false;
 
-  // Name of the custom profile directory (default: object dirname).
-  std::string profile_dir;
+  // Name of the custom profile directory or file.
+  std::string profile_path;
 
   // Profile generation / usage information.
   bool profile_use = false;
index a53f7a11fca2c9e4ceb9342082851b03ef54b148..30f93e0039ef73c1289b273636caaf0b26bfd127 100644 (file)
@@ -1559,8 +1559,8 @@ hash_common_info(const Context& ctx,
   // Possibly hash the coverage data file path.
   if (ctx.args_info.generating_coverage && ctx.args_info.profile_arcs) {
     std::string dir;
-    if (!ctx.args_info.profile_dir.empty()) {
-      dir = ctx.args_info.profile_dir;
+    if (!ctx.args_info.profile_path.empty()) {
+      dir = ctx.args_info.profile_path;
     } else {
       dir =
         Util::real_path(std::string(Util::dir_name(ctx.args_info.output_obj)));
@@ -1604,6 +1604,43 @@ hash_common_info(const Context& ctx,
   }
 }
 
+static bool
+hash_profile_data_file(const Context& ctx, struct hash* hash)
+{
+  const std::string& profile_path = ctx.args_info.profile_path;
+  string_view base_name = Util::remove_extension(ctx.args_info.output_obj);
+  std::string hashified_cwd = ctx.apparent_cwd;
+  std::replace(hashified_cwd.begin(), hashified_cwd.end(), '/', '#');
+
+  std::vector<std::string> paths_to_try{
+    // -fprofile-use[=dir]/-fbranch-probabilities (GCC <9)
+    fmt::format("{}/{}.gcda", profile_path, base_name),
+    // -fprofile-use[=dir]/-fbranch-probabilities (GCC >=9)
+    fmt::format("{}/{}#{}.gcda", profile_path, hashified_cwd, base_name),
+    // -fprofile(-instr)-use=file (Clang), -fauto-profile=file (GCC >=5)
+    profile_path,
+    // -fprofile(-instr)-use=dir (Clang)
+    fmt::format("{}/default.profdata", profile_path),
+    // -fauto-profile (GCC >=5)
+    "fbdata.afdo", // -fprofile-dir is not used
+  };
+
+  bool found = false;
+  for (const std::string& p : paths_to_try) {
+    cc_log("Checking for profile data file %s", p.c_str());
+    auto st = Stat::stat(p);
+    if (st && !st.is_directory()) {
+      cc_log("Adding profile data %s to the hash", p.c_str());
+      hash_delimiter(hash, "-fprofile-use");
+      if (hash_file(hash, p.c_str())) {
+        found = true;
+      }
+    }
+  }
+
+  return found;
+}
+
 // Update a hash sum with information specific to the direct and preprocessor
 // modes and calculate the result name. Returns the result name on success,
 // otherwise NULL. Caller frees.
@@ -1784,33 +1821,29 @@ calculate_result_name(Context& ctx,
     hash_nvcc_host_compiler(ctx, hash, nullptr, nullptr);
   }
 
-  // For profile generation (-fprofile-arcs, -fprofile-generate):
-  // - hash profile directory
+  // For profile generation (-fprofile(-instr)-generate[=path])
+  // - hash profile path
   //
-  // For profile usage (-fprofile-use):
+  // For profile usage (-fprofile(-instr)-use, -fbranch-probabilities):
   // - hash profile data
   //
   // -fbranch-probabilities and -fvpt usage is covered by
   // -fprofile-generate/-fprofile-use.
   //
   // The profile directory can be specified as an argument to
-  // -fprofile-generate=, -fprofile-use= or -fprofile-dir=.
+  // -fprofile(-instr)-generate=, -fprofile(-instr)-use= or -fprofile-dir=.
+
   if (ctx.args_info.profile_generate) {
+    assert(!ctx.args_info.profile_path.empty());
     cc_log("Adding profile directory %s to our hash",
-           ctx.args_info.profile_dir.c_str());
+           ctx.args_info.profile_path.c_str());
     hash_delimiter(hash, "-fprofile-dir");
-    hash_string(hash, ctx.args_info.profile_dir);
+    hash_string(hash, ctx.args_info.profile_path);
   }
 
-  if (ctx.args_info.profile_use) {
-    // Calculate gcda name.
-    string_view base_name = Util::remove_extension(ctx.args_info.output_obj);
-    std::string gcda_name =
-      fmt::format("{}/{}.gcda", ctx.args_info.profile_dir, base_name);
-    cc_log("Adding profile data %s to our hash", gcda_name.c_str());
-    // Add the gcda to our hash.
-    hash_delimiter(hash, "-fprofile-use");
-    hash_file(hash, gcda_name.c_str());
+  if (ctx.args_info.profile_use && !hash_profile_data_file(ctx, hash)) {
+    cc_log("No profile data file found");
+    failed(STATS_NOINPUT);
   }
 
   // Adding -arch to hash since cpp output is affected.
@@ -2077,6 +2110,64 @@ detect_pch(Context& ctx, const char* option, const char* arg, bool* found_pch)
   return true;
 }
 
+static bool
+process_profiling_option(Context& ctx, const std::string& arg)
+{
+  std::string new_profile_path;
+  bool new_profile_use = false;
+
+  if (Util::starts_with(arg, "-fprofile-dir=")) {
+    new_profile_path = arg.substr(arg.find('=') + 1);
+  } else if (arg == "-fprofile-generate" || arg == "-fprofile-instr-generate") {
+    ctx.args_info.profile_generate = true;
+    if (ctx.guessed_compiler == GuessedCompiler::clang) {
+      new_profile_path = ".";
+    } else {
+      // GCC uses $PWD/$(basename $obj).
+      new_profile_path = ctx.apparent_cwd;
+    }
+  } else if (Util::starts_with(arg, "-fprofile-generate=")
+             || Util::starts_with(arg, "-fprofile-instr-generate=")) {
+    ctx.args_info.profile_generate = true;
+    new_profile_path = arg.substr(arg.find('=') + 1);
+  } else if (arg == "-fprofile-use" || arg == "-fprofile-instr-use"
+             || arg == "-fbranch-probabilities" || arg == "-fauto-profile") {
+    new_profile_use = true;
+    if (ctx.args_info.profile_path.empty()) {
+      new_profile_path = ".";
+    }
+  } else if (Util::starts_with(arg, "-fprofile-use=")
+             || Util::starts_with(arg, "-fprofile-instr-use=")
+             || Util::starts_with(arg, "-fauto-profile=")) {
+    new_profile_use = true;
+    new_profile_path = arg.substr(arg.find('=') + 1);
+  } else {
+    cc_log("Unknown profiling option: %s", arg.c_str());
+    return false;
+  }
+
+  if (new_profile_use) {
+    if (ctx.args_info.profile_use) {
+      cc_log("Multiple profiling options not supported");
+      return false;
+    }
+    ctx.args_info.profile_use = true;
+  }
+
+  if (!new_profile_path.empty()) {
+    ctx.args_info.profile_path = new_profile_path;
+    cc_log("Set profile directory to %s", ctx.args_info.profile_path.c_str());
+  }
+
+  if (ctx.args_info.profile_generate && ctx.args_info.profile_use) {
+    // Too hard to figure out what the compiler will do.
+    cc_log("Both generating and using profile info, giving up");
+    return false;
+  }
+
+  return true;
+}
+
 // Process the compiler options into options suitable for passing to the
 // preprocessor and the real compiler. preprocessor_args doesn't include -E;
 // this is added later. extra_args_to_hash are the arguments that are not
@@ -2158,6 +2249,7 @@ process_args(Context& ctx,
 
   for (size_t i = 1; i < expanded_args.size(); i++) {
     size_t argc = expanded_args.size();
+    const std::string& arg = expanded_args[i];
 
     // The user knows best: just swallow the next arg.
     if (str_eq(argv[i], "--ccache-skip")) {
@@ -2244,7 +2336,7 @@ process_args(Context& ctx,
 
     // -Xarch_* options are too hard.
     if (str_startswith(argv[i], "-Xarch_")) {
-      cc_log("Unsupported compiler option :%s", argv[i]);
+      cc_log("Unsupported compiler option%s", argv[i]);
       return STATS_UNSUPPORTED_OPTION;
     }
 
@@ -2497,8 +2589,13 @@ process_args(Context& ctx,
       args_add(common_args, argv[i]);
       continue;
     }
-    if (str_startswith(argv[i], "-fprofile-dir=")) {
-      args_info.profile_dir.assign(argv[i] + 14);
+    if (Util::starts_with(arg, "-fprofile-")
+        || Util::starts_with(arg, "-fauto-profile")
+        || arg == "-fbranch-probabilities") {
+      if (!process_profiling_option(ctx, argv[i])) {
+        // The failure is logged by process_profiling_option.
+        return STATS_UNSUPPORTED_OPTION;
+      }
       args_add(common_args, argv[i]);
       continue;
     }
@@ -2609,53 +2706,6 @@ process_args(Context& ctx,
       continue;
     }
 
-    if (str_startswith(argv[i], "-fprofile-")) {
-      char* arg = x_strdup(argv[i]);
-      const char* arg_profile_dir = strchr(argv[i], '=');
-      if (arg_profile_dir) {
-        // Convert to absolute path.
-        std::string dir = Util::real_path(arg_profile_dir + 1);
-
-        // We can get a better hit rate by using the real path here.
-        free(arg);
-        char* option = x_strndup(argv[i], arg_profile_dir - argv[i]);
-        arg = format("%s=%s", option, dir.c_str());
-        cc_log("Rewriting %s to %s", argv[i], arg);
-        free(option);
-      }
-
-      bool supported_profile_option = false;
-      if (str_startswith(argv[i], "-fprofile-generate")
-          || str_eq(argv[i], "-fprofile-arcs")) {
-        args_info.profile_generate = true;
-        supported_profile_option = true;
-      } else if (str_startswith(argv[i], "-fprofile-use")
-                 || str_eq(argv[i], "-fbranch-probabilities")) {
-        args_info.profile_use = true;
-        supported_profile_option = true;
-      } else if (str_eq(argv[i], "-fprofile-dir")) {
-        supported_profile_option = true;
-      }
-
-      if (supported_profile_option) {
-        args_add(common_args, arg);
-        free(arg);
-
-        // If the profile directory has already been set, give up... Hard to
-        // know what the user means, and what the compiler will do.
-        if (arg_profile_dir && !args_info.profile_dir.empty()) {
-          cc_log("Profile directory already set; giving up");
-          return STATS_UNSUPPORTED_OPTION;
-        } else if (arg_profile_dir) {
-          cc_log("Setting profile directory to %s", arg_profile_dir);
-          args_info.profile_dir = from_cstr(arg_profile_dir);
-        }
-        continue;
-      }
-      cc_log("Unknown profile option: %s", argv[i]);
-      free(arg);
-    }
-
     if (str_eq(argv[i], "-fcolor-diagnostics")
         || str_eq(argv[i], "-fno-color-diagnostics")
         || str_eq(argv[i], "-fdiagnostics-color")
@@ -2897,8 +2947,8 @@ process_args(Context& ctx,
     }
   }
 
-  if (args_info.profile_dir.empty()) {
-    args_info.profile_dir = ctx.apparent_cwd;
+  if (args_info.profile_path.empty()) {
+    args_info.profile_path = ctx.apparent_cwd;
   }
 
   if (explicit_language && str_eq(explicit_language, "none")) {
index c7fcbed0df8ccc2114df75696c188954e6f90ac5..7b356d7b2dab32d1e7a0eb00a2826e2bfebfd25d 100755 (executable)
--- a/test/run
+++ b/test/run
@@ -363,6 +363,7 @@ case $compiler_version in
         ;;
     *clang*)
         COMPILER_TYPE_CLANG=true
+        CLANG_VERSION_SUFFIX=$(echo $COMPILER | sed -r 's/.*clang//')
         ;;
     *)
         echo "WARNING: Compiler $COMPILER not supported (version: $compiler_version) -- not running tests" >&2
@@ -425,6 +426,9 @@ multi_arch
 serialize_diagnostics
 sanitize_blacklist
 debug_prefix_map
+profiling
+profiling_gcc
+profiling_clang
 split_dwarf
 masquerading
 hardlink
diff --git a/test/suites/profiling.bash b/test/suites/profiling.bash
new file mode 100644 (file)
index 0000000..553f908
--- /dev/null
@@ -0,0 +1,103 @@
+SUITE_profiling_PROBE() {
+    touch test.c
+    if ! $COMPILER -fprofile-generate -c test.c 2>/dev/null; then
+        echo "compiler does not support profiling"
+    fi
+    if $COMPILER_TYPE_CLANG && ! which llvm-profdata$CLANG_VERSION_SUFFIX >/dev/null 2>/dev/null; then
+        echo "llvm-profdata$CLANG_VERSION_SUFFIX tool not found"
+    fi
+}
+
+SUITE_profiling_SETUP() {
+    echo 'int main(void) { return 0; }' >test.c
+    unset CCACHE_NODIRECT
+}
+
+SUITE_profiling() {
+    # -------------------------------------------------------------------------
+    TEST "-fprofile-use, missing file"
+
+    $CCACHE_COMPILE -fprofile-use -c test.c 2>/dev/null
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 0
+    expect_stat 'no input file' 1
+
+    # -------------------------------------------------------------------------
+    TEST "-fbranch-probabilities, missing file"
+
+    $CCACHE_COMPILE -fbranch-probabilities -c test.c 2>/dev/null
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 0
+    expect_stat 'no input file' 1
+
+    # -------------------------------------------------------------------------
+    TEST "-fprofile-use=file, missing file"
+
+    $CCACHE_COMPILE -fprofile-use=data.gcda -c test.c 2>/dev/null
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 0
+    expect_stat 'no input file' 1
+
+    # -------------------------------------------------------------------------
+    TEST "-fprofile-use"
+
+    $CCACHE_COMPILE -fprofile-generate -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 1
+
+    $COMPILER -fprofile-generate test.o -o test
+
+    ./test
+    merge_profiling_data .
+
+    $CCACHE_COMPILE -fprofile-use -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 2
+
+    $CCACHE_COMPILE -fprofile-use -c test.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache miss' 2
+
+    ./test
+    merge_profiling_data .
+
+    $CCACHE_COMPILE -fprofile-use -c test.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache miss' 3
+
+    # -------------------------------------------------------------------------
+    TEST "-fprofile-use=dir"
+
+    mkdir data
+
+    $CCACHE_COMPILE -fprofile-generate=data -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 1
+
+    $COMPILER -fprofile-generate=data test.o -o test
+
+    ./test
+    merge_profiling_data data
+
+    $CCACHE_COMPILE -fprofile-use=data -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 2
+
+    $CCACHE_COMPILE -fprofile-use=data -c test.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache miss' 2
+
+    ./test
+    merge_profiling_data data
+
+    $CCACHE_COMPILE -fprofile-use=data -c test.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache miss' 3
+}
+
+merge_profiling_data() {
+    local dir=$1
+    if $COMPILER_TYPE_CLANG; then
+        llvm-profdata$CLANG_VERSION_SUFFIX merge -output $dir/default.profdata $dir/*.profraw
+    fi
+}
diff --git a/test/suites/profiling_clang.bash b/test/suites/profiling_clang.bash
new file mode 100644 (file)
index 0000000..4344f7d
--- /dev/null
@@ -0,0 +1,98 @@
+SUITE_profiling_clang_PROBE() {
+    if ! $COMPILER_TYPE_CLANG; then
+        echo "compiler is not Clang"
+    fi
+    if ! which llvm-profdata$CLANG_VERSION_SUFFIX >/dev/null 2>/dev/null; then
+        echo "llvm-profdata$CLANG_VERSION_SUFFIX tool not found"
+    fi
+}
+
+SUITE_profiling_clang_SETUP() {
+    echo 'int main(void) { return 0; }' >test.c
+    unset CCACHE_NODIRECT
+}
+
+SUITE_profiling_clang() {
+    # -------------------------------------------------------------------------
+    TEST "-fprofile-use=file"
+
+    mkdir data
+
+    $CCACHE_COMPILE -fprofile-generate=data -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 1
+
+    $COMPILER -fprofile-generate=data test.o -o test
+
+    ./test
+    llvm-profdata$CLANG_VERSION_SUFFIX merge -output foo.profdata data/default_*.profraw
+
+    $CCACHE_COMPILE -fprofile-use=foo.profdata -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 2
+
+    $CCACHE_COMPILE -fprofile-use=foo.profdata -c test.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache miss' 2
+
+    ./test
+    llvm-profdata$CLANG_VERSION_SUFFIX merge -output foo.profdata data/default_*.profraw
+
+    $CCACHE_COMPILE -fprofile-use=foo.profdata -c test.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache miss' 3
+
+    # -------------------------------------------------------------------------
+    TEST "-fprofile-instr-use"
+
+    mkdir data
+
+    $CCACHE_COMPILE -fprofile-instr-generate -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 1
+
+    $COMPILER -fprofile-instr-generate test.o -o test
+
+    ./test
+    llvm-profdata$CLANG_VERSION_SUFFIX merge -output default.profdata default.profraw
+
+    $CCACHE_COMPILE -fprofile-instr-use -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 2
+
+    $CCACHE_COMPILE -fprofile-instr-use -c test.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache miss' 2
+
+    echo >>default.profdata  # Dummy change to trigger modification
+
+    $CCACHE_COMPILE -fprofile-instr-use -c test.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache miss' 3
+
+    # -------------------------------------------------------------------------
+    TEST "-fprofile-instr-use=file"
+
+    $CCACHE_COMPILE -fprofile-instr-generate=foo.profraw -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 1
+
+    $COMPILER -fprofile-instr-generate=data=foo.profraw test.o -o test
+
+    ./test
+    llvm-profdata$CLANG_VERSION_SUFFIX merge -output foo.profdata foo.profraw
+
+    $CCACHE_COMPILE -fprofile-instr-use=foo.profdata -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 2
+
+    $CCACHE_COMPILE -fprofile-instr-use=foo.profdata -c test.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache miss' 2
+
+    echo >>foo.profdata  # Dummy change to trigger modification
+
+    $CCACHE_COMPILE -fprofile-instr-use=foo.profdata -c test.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache miss' 3
+}
diff --git a/test/suites/profiling_gcc.bash b/test/suites/profiling_gcc.bash
new file mode 100644 (file)
index 0000000..fe61109
--- /dev/null
@@ -0,0 +1,118 @@
+SUITE_profiling_gcc_PROBE() {
+    if ! $COMPILER_TYPE_GCC; then
+        echo "compiler is not GCC"
+    fi
+}
+
+SUITE_profiling_gcc_SETUP() {
+    echo 'int main(void) { return 0; }' >test.c
+    unset CCACHE_NODIRECT
+}
+
+SUITE_profiling_gcc() {
+    # -------------------------------------------------------------------------
+    TEST "-fbranch-probabilities"
+
+    $CCACHE_COMPILE -fprofile-generate -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 1
+
+    $COMPILER -fprofile-generate test.o -o test
+
+    ./test
+
+    $CCACHE_COMPILE -fbranch-probabilities -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 2
+
+    $CCACHE_COMPILE -fbranch-probabilities -c test.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache miss' 2
+
+    ./test
+
+    $CCACHE_COMPILE -fbranch-probabilities -c test.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache miss' 3
+
+    # -------------------------------------------------------------------------
+    TEST "-fprofile-dir=dir + -fprofile-use"
+
+    mkdir data
+
+    $CCACHE_COMPILE -fprofile-dir=data -fprofile-generate -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 1
+
+    $COMPILER -fprofile-dir=data -fprofile-generate test.o -o test
+
+    ./test
+
+    $CCACHE_COMPILE -fprofile-dir=data -fprofile-use -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 2
+
+    $CCACHE_COMPILE -fprofile-dir=data -fprofile-use -c test.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache miss' 2
+
+    ./test
+
+    $CCACHE_COMPILE -fprofile-dir=data -fprofile-use -c test.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache miss' 3
+
+    # -------------------------------------------------------------------------
+    TEST "-fprofile-use + -fprofile-dir=dir"
+
+    mkdir data
+
+    $CCACHE_COMPILE -fprofile-generate -fprofile-dir=data -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 1
+
+    $COMPILER -fprofile-generate -fprofile-dir=data test.o -o test
+
+    ./test
+
+    $CCACHE_COMPILE -fprofile-use -fprofile-dir=data -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 2
+
+    $CCACHE_COMPILE -fprofile-use -fprofile-dir=data -c test.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache miss' 2
+
+    ./test
+
+    $CCACHE_COMPILE -fprofile-use -fprofile-dir=data -c test.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache miss' 3
+
+    # -------------------------------------------------------------------------
+    TEST "-fprofile-dir=path1 + -fprofile-use=path2"
+
+    mkdir data
+
+    $CCACHE_COMPILE -fprofile-dir=data2 -fprofile-generate=data -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 1
+
+    $COMPILER -fprofile-dir=data2 -fprofile-generate=data test.o -o test
+
+    ./test
+
+    $CCACHE_COMPILE -fprofile-dir=data2 -fprofile-use=data -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 2
+
+    $CCACHE_COMPILE -fprofile-dir=data2 -fprofile-use=data -c test.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache miss' 2
+
+    ./test
+
+    $CCACHE_COMPILE -fprofile-dir=data2 -fprofile-use=data -c test.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache miss' 3
+}
index 9a53c749461b81886a608e26f7c89f7f29a1d813..4fc681920b569444baf42942c09ff358767a19ac 100644 (file)
@@ -509,56 +509,6 @@ TEST(MT_flag_with_immediate_argument_should_not_add_MQobj)
   CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
 }
 
-TEST(fprofile_flag_with_existing_dir_should_be_rewritten_to_real_path)
-{
-  Context ctx;
-
-  Args orig = args_init_from_string("gcc -c -fprofile-generate=some/dir foo.c");
-  Args exp_cpp = args_init_from_string("gcc");
-  Args exp_extra = args_init(0, NULL);
-  Args exp_cc = args_init_from_string("gcc");
-  Args act_cpp;
-  Args act_extra;
-  Args act_cc;
-
-  char* s;
-
-  create_file("foo.c", "");
-  mkdir("some", 0777);
-  mkdir("some/dir", 0777);
-  std::string path = Util::real_path("some/dir");
-  s = format("-fprofile-generate=%s", path.c_str());
-  args_add(exp_cpp, s);
-  args_add(exp_cc, s);
-  args_add(exp_cc, "-c");
-  free(s);
-
-  CHECK(!process_args(ctx, orig, act_cpp, act_extra, act_cc));
-  CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
-  CHECK_ARGS_EQ_FREE12(exp_extra, act_extra);
-  CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
-}
-
-TEST(fprofile_flag_with_nonexistent_dir_should_not_be_rewritten)
-{
-  Context ctx;
-
-  Args orig = args_init_from_string("gcc -c -fprofile-generate=some/dir foo.c");
-  Args exp_cpp = args_init_from_string("gcc -fprofile-generate=some/dir");
-  Args exp_extra = args_init(0, NULL);
-  Args exp_cc = args_init_from_string("gcc -fprofile-generate=some/dir -c");
-  Args act_cpp;
-  Args act_extra;
-  Args act_cc;
-
-  create_file("foo.c", "");
-
-  CHECK(!process_args(ctx, orig, act_cpp, act_extra, act_cc));
-  CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
-  CHECK_ARGS_EQ_FREE12(exp_extra, act_extra);
-  CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
-}
-
 TEST(isystem_flag_with_separate_arg_should_be_rewritten_if_basedir_is_used)
 {
   Context ctx;