Skip to content

Commit

Permalink
Support caching Clang invocations with -fprofile-use and -fprofile-in…
Browse files Browse the repository at this point in the history
…str-use.
  • Loading branch information
michaelwoerister committed Feb 18, 2022
1 parent 573c9ba commit dc28e0e
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 3 deletions.
129 changes: 127 additions & 2 deletions src/compiler/clang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,14 @@ counted_array!(pub static ARGS: [ArgInfo<gcc::ArgData>; _] = [
take_arg!("-fdebug-compilation-dir", OsString, Separated, PassThrough),
flag!("-fmodules", TooHardFlag),
flag!("-fno-color-diagnostics", NoDiagnosticsColorFlag),
flag!("-fno-profile-instr-generate", TooHardFlag),
flag!("-fno-profile-instr-use", TooHardFlag),
take_arg!("-fplugin", PathBuf, CanBeConcatenated('='), ExtraHashFile),
flag!("-fprofile-instr-generate", ProfileGenerate),
// Can be either -fprofile-instr-use or -fprofile-instr-use=path
take_arg!("-fprofile-instr-use", OsString, Concatenated, TooHard),
// Note: the PathBuf argument is optional
take_arg!("-fprofile-instr-use", PathBuf, Concatenated('='), ClangProfileUse),
// Note: this overrides the -fprofile-use option in gcc.rs.
take_arg!("-fprofile-use", PathBuf, Concatenated('='), ClangProfileUse),
take_arg!("-fsanitize-blacklist", PathBuf, Concatenated('='), ExtraHashFile),
take_arg!("-gcc-toolchain", OsString, Separated, PassThrough),
take_arg!("-include-pch", PathBuf, CanBeSeparated, PreprocessorArgumentPath),
Expand All @@ -132,6 +136,27 @@ counted_array!(pub static ARGS: [ArgInfo<gcc::ArgData>; _] = [
flag!("-verify", PreprocessorArgumentFlag),
]);

// Maps the `-fprofile-use` argument to the actual path of the
// .profdata file Clang will try to use.
pub(crate) fn resolve_profile_use_path(arg: &Path, cwd: &Path) -> PathBuf {
// Note that `arg` might be empty (if no argument was given to
// -fprofile-use), in which case `path` will be `cwd` after
// the next statement and "./default.profdata" at the end of the
// block. This matches Clang's behavior for when no argument is
// given.
let mut path = cwd.join(arg);

assert!(!arg.as_os_str().is_empty() || path == cwd);

// Clang allows specifying a directory here, in which case it
// will look for the file `default.profdata` in that directory.
if path.is_dir() {
path.push("default.profdata");
}

path
}

#[cfg(test)]
mod test {
use super::*;
Expand Down Expand Up @@ -406,4 +431,104 @@ mod test {
let a = parses!("-c", "foo.c", "-o", "foo.o");
assert_eq!(a.color_mode, ColorMode::Auto);
}

#[test]
fn test_parse_arguments_profile_instr_use() {
let a = parses!(
"-c",
"foo.c",
"-o",
"foo.o",
"-fprofile-instr-use=foo.profdata"
);
assert_eq!(ovec!["-fprofile-instr-use=foo.profdata"], a.common_args);
assert_eq!(
ovec![std::env::current_dir().unwrap().join("foo.profdata")],
a.extra_hash_files
);
}

#[test]
fn test_parse_arguments_profile_use() {
let a = parses!("-c", "foo.c", "-o", "foo.o", "-fprofile-use=xyz.profdata");

assert_eq!(ovec!["-fprofile-use=xyz.profdata"], a.common_args);
assert_eq!(
ovec![std::env::current_dir().unwrap().join("xyz.profdata")],
a.extra_hash_files
);
}

#[test]
fn test_parse_arguments_profile_use_with_directory() {
let a = parses!("-c", "foo.c", "-o", "foo.o", "-fprofile-use=.");

assert_eq!(ovec!["-fprofile-use=."], a.common_args);
assert_eq!(
ovec![std::env::current_dir().unwrap().join("default.profdata")],
a.extra_hash_files
);
}

#[test]
fn test_parse_arguments_profile_use_with_no_argument() {
let a = parses!("-c", "foo.c", "-o", "foo.o", "-fprofile-use");

assert_eq!(ovec!["-fprofile-use"], a.common_args);
assert_eq!(
ovec![std::env::current_dir().unwrap().join("default.profdata")],
a.extra_hash_files
);
}

#[test]
fn test_parse_arguments_pgo_cancellation() {
assert_eq!(
CompilerArguments::CannotCache("-fno-profile-use", None),
parse_arguments_(stringvec![
"-c",
"foo.c",
"-o",
"foo.o",
"-fprofile-use",
"-fno-profile-use"
])
);

assert_eq!(
CompilerArguments::CannotCache("-fno-profile-instr-use", None),
parse_arguments_(stringvec![
"-c",
"foo.c",
"-o",
"foo.o",
"-fprofile-instr-use",
"-fno-profile-instr-use"
])
);

assert_eq!(
CompilerArguments::CannotCache("-fno-profile-generate", None),
parse_arguments_(stringvec![
"-c",
"foo.c",
"-o",
"foo.o",
"-fprofile-generate",
"-fno-profile-generate"
])
);

assert_eq!(
CompilerArguments::CannotCache("-fno-profile-instr-generate", None),
parse_arguments_(stringvec![
"-c",
"foo.c",
"-o",
"foo.o",
"-fprofile-instr-generate",
"-fno-profile-instr-generate"
])
);
}
}
8 changes: 8 additions & 0 deletions src/compiler/gcc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ ArgData! { pub
Language(OsString),
SplitDwarf,
ProfileGenerate,
ClangProfileUse(PathBuf),
TestCoverage,
Coverage,
ExtraHashFile(PathBuf),
Expand Down Expand Up @@ -168,6 +169,8 @@ counted_array!(pub static ARGS: [ArgInfo<ArgData>; _] = [
flag!("-c", DoCompilation),
take_arg!("-fdiagnostics-color", OsString, Concatenated('='), DiagnosticsColor),
flag!("-fno-diagnostics-color", NoDiagnosticsColorFlag),
flag!("-fno-profile-generate", TooHardFlag),
flag!("-fno-profile-use", TooHardFlag),
flag!("-fno-working-directory", PreprocessorArgumentFlag),
flag!("-fplugin=libcc1plugin", TooHardFlag),
flag!("-fprofile-arcs", ProfileGenerate),
Expand Down Expand Up @@ -278,6 +281,9 @@ where
OsString::from(arg.flag_str().expect("Compilation flag expected"));
}
Some(ProfileGenerate) => profile_generate = true,
Some(ClangProfileUse(path)) => {
extra_hash_files.push(clang::resolve_profile_use_path(path, cwd));
}
Some(TestCoverage) => outputs_gcno = true,
Some(Coverage) => {
outputs_gcno = true;
Expand Down Expand Up @@ -337,6 +343,7 @@ where
let args = match arg.get_data() {
Some(SplitDwarf)
| Some(ProfileGenerate)
| Some(ClangProfileUse(_))
| Some(TestCoverage)
| Some(Coverage)
| Some(DiagnosticsColor(_))
Expand Down Expand Up @@ -380,6 +387,7 @@ where
let args = match arg.get_data() {
Some(SplitDwarf)
| Some(ProfileGenerate)
| Some(ClangProfileUse(_))
| Some(TestCoverage)
| Some(Coverage)
| Some(DoCompilation)
Expand Down
20 changes: 19 additions & 1 deletion src/compiler/msvc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,12 @@ pub fn parse_arguments(
profile_generate = true;
&mut common_args
}

Some(ClangProfileUse(path)) => {
extra_hash_files.push(clang::resolve_profile_use_path(path, cwd));
&mut common_args
}

Some(ExtraHashFile(path)) => {
extra_hash_files.push(cwd.join(path));
&mut common_args
Expand Down Expand Up @@ -1061,13 +1067,15 @@ mod test {
"-Xclang",
"host_dictionary.obj",
"-clang:-fprofile-generate",
"-clang:-fprofile-use=xyz.profdata",
"dictionary.c"
];
let ParsedArguments {
dependency_args,
preprocessor_args,
common_args,
profile_generate,
extra_hash_files,
..
} = match parse_arguments(args) {
CompilerArguments::Ok(args) => args,
Expand All @@ -1090,7 +1098,17 @@ mod test {
"host_dictionary.obj"
)
);
assert_eq!(common_args, ovec!("-clang:-fprofile-generate"));
assert_eq!(
common_args,
ovec!(
"-clang:-fprofile-generate",
"-clang:-fprofile-use=xyz.profdata"
)
);
assert_eq!(
extra_hash_files,
ovec!(std::env::current_dir().unwrap().join("xyz.profdata"))
);
}

#[test]
Expand Down

0 comments on commit dc28e0e

Please sign in to comment.