Skip to content

Commit d5413a6

Browse files
wip
1 parent 5e48ea9 commit d5413a6

File tree

3 files changed

+100
-3
lines changed

3 files changed

+100
-3
lines changed

src/bootstrap/config.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ pub struct Config {
8989
pub llvm_assertions: bool,
9090
pub llvm_optimize: bool,
9191
pub llvm_thin_lto: bool,
92+
pub llvm_profile_generate: Option<String>,
93+
pub llvm_profile_use: Option<String>,
9294
pub llvm_release_debuginfo: bool,
9395
pub llvm_version_check: bool,
9496
pub llvm_static_stdcpp: bool,
@@ -405,6 +407,8 @@ struct Llvm {
405407
skip_rebuild: Option<bool>,
406408
optimize: Option<bool>,
407409
thin_lto: Option<bool>,
410+
profile_generate: Option<String>,
411+
profile_use: Option<String>,
408412
release_debuginfo: Option<bool>,
409413
assertions: Option<bool>,
410414
ccache: Option<StringOrBool>,
@@ -756,6 +760,8 @@ impl Config {
756760
llvm_skip_rebuild = llvm_skip_rebuild.or(llvm.skip_rebuild);
757761
set(&mut config.llvm_optimize, llvm.optimize);
758762
set(&mut config.llvm_thin_lto, llvm.thin_lto);
763+
config.llvm_profile_generate = llvm.profile_generate.clone();
764+
config.llvm_profile_use = llvm.profile_use.clone();
759765
set(&mut config.llvm_release_debuginfo, llvm.release_debuginfo);
760766
set(&mut config.llvm_version_check, llvm.version_check);
761767
set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp);
@@ -791,6 +797,7 @@ impl Config {
791797
// arbitrary) CI configuration locally seems bad/hard.
792798
check_ci_llvm!(llvm.optimize);
793799
check_ci_llvm!(llvm.thin_lto);
800+
check_ci_llvm!(llvm.profile_generate);
794801
check_ci_llvm!(llvm.release_debuginfo);
795802
check_ci_llvm!(llvm.link_shared);
796803
check_ci_llvm!(llvm.static_libstdcpp);

src/bootstrap/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,10 @@ impl Build {
631631
self.out.join(&*target.triple).join("lld")
632632
}
633633

634+
fn profdata_out(&self, target: TargetSelection) -> PathBuf {
635+
self.out.join(&*target.triple).join("profdata")
636+
}
637+
634638
/// Output directory for all documentation for a target
635639
fn doc_out(&self, target: TargetSelection) -> PathBuf {
636640
self.out.join(&*target.triple).join("doc")

src/bootstrap/native.rs

Lines changed: 89 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ impl Step for Llvm {
206206
}
207207
}
208208

209+
let pgo_compiler_flags = make_pgo_compiler_flags(&builder, target);
210+
209211
// This setting makes the LLVM tools link to the dynamic LLVM library,
210212
// which saves both memory during parallel links and overall disk space
211213
// for the tools. We don't do this on every platform as it doesn't work
@@ -316,7 +318,7 @@ impl Step for Llvm {
316318
cfg.define("LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN", "YES");
317319
}
318320

319-
configure_cmake(builder, target, &mut cfg, true);
321+
configure_cmake(builder, target, &mut cfg, pgo_compiler_flags, true);
320322

321323
// FIXME: we don't actually need to build all LLVM tools and all LLVM
322324
// libraries here, e.g., we just want a few components and a few
@@ -359,6 +361,7 @@ fn configure_cmake(
359361
builder: &Builder<'_>,
360362
target: TargetSelection,
361363
cfg: &mut cmake::Config,
364+
pgo_compiler_flags: Option<String>,
362365
use_compiler_launcher: bool,
363366
) {
364367
// Do not print installation messages for up-to-date files.
@@ -470,6 +473,10 @@ fn configure_cmake(
470473
if let Some(ref s) = builder.config.llvm_cflags {
471474
cflags.push_str(&format!(" {}", s));
472475
}
476+
if let &Some(ref pgo_compiler_flags) = &pgo_compiler_flags {
477+
cflags.push_str(&format!(" {}", pgo_compiler_flags));
478+
}
479+
473480
// Some compiler features used by LLVM (such as thread locals) will not work on a min version below iOS 10.
474481
if target.contains("apple-ios") {
475482
if target.contains("86-") {
@@ -489,6 +496,9 @@ fn configure_cmake(
489496
if let Some(ref s) = builder.config.llvm_cxxflags {
490497
cxxflags.push_str(&format!(" {}", s));
491498
}
499+
if let &Some(ref pgo_compiler_flags) = &pgo_compiler_flags {
500+
cxxflags.push_str(&format!(" {}", pgo_compiler_flags));
501+
}
492502
if builder.config.llvm_clang_cl.is_some() {
493503
cxxflags.push_str(&format!(" --target={}", target))
494504
}
@@ -557,7 +567,7 @@ impl Step for Lld {
557567
t!(fs::create_dir_all(&out_dir));
558568

559569
let mut cfg = cmake::Config::new(builder.src.join("src/llvm-project/lld"));
560-
configure_cmake(builder, target, &mut cfg, true);
570+
configure_cmake(builder, target, &mut cfg, None, true);
561571

562572
// This is an awful, awful hack. Discovered when we migrated to using
563573
// clang-cl to compile LLVM/LLD it turns out that LLD, when built out of
@@ -747,7 +757,7 @@ impl Step for Sanitizers {
747757
// Unfortunately sccache currently lacks support to build them successfully.
748758
// Disable compiler launcher on Darwin targets to avoid potential issues.
749759
let use_compiler_launcher = !self.target.contains("apple-darwin");
750-
configure_cmake(builder, self.target, &mut cfg, use_compiler_launcher);
760+
configure_cmake(builder, self.target, &mut cfg, None, use_compiler_launcher);
751761

752762
t!(fs::create_dir_all(&out_dir));
753763
cfg.out_dir(out_dir);
@@ -853,3 +863,79 @@ impl HashStamp {
853863
fs::write(&self.path, self.hash.as_deref().unwrap_or(b""))
854864
}
855865
}
866+
867+
868+
fn make_pgo_compiler_flags(builder: &Builder<'_>, target: TargetSelection) -> Option<String> {
869+
let profile_generate_path = profiling_path(builder, target, &builder.config.llvm_profile_generate, false);
870+
let profile_use_path = profiling_path(builder, target, &builder.config.llvm_profile_use, true);
871+
872+
let mut pgo_compiler_flags = String::new();
873+
874+
match (profile_generate_path, profile_use_path) {
875+
(Some(_), Some(_)) => {
876+
panic!("error: only one of llvm.profile-generate and \
877+
llvm.profile-use is allowed to be set at a time");
878+
}
879+
(None, None) => {
880+
return None;
881+
}
882+
(Some(profile_generate_path), None) => {
883+
if !builder.config.llvm_link_shared {
884+
panic!("error: llvm.link_shared is false but \
885+
llvm.profile-generate requires it to be true");
886+
}
887+
888+
pgo_compiler_flags += &format!("-fprofile-generate={}", profile_generate_path.display());
889+
}
890+
(None, Some(profile_use_path)) => {
891+
pgo_compiler_flags += &format!("-fprofile-use={}", profile_use_path.display());
892+
pgo_compiler_flags += " -mllvm -pgo-warn-missing-function";
893+
}
894+
}
895+
896+
assert_cc_is_clang_for_pgo(builder, target);
897+
898+
pgo_compiler_flags += &format!(" -mllvm -static-func-strip-dirname-prefix={}",
899+
builder.config.src.components().count());
900+
901+
Some(pgo_compiler_flags)
902+
}
903+
904+
fn profiling_path(
905+
builder: &Builder<'_>,
906+
target: TargetSelection,
907+
flag: &Option<String>,
908+
is_use_phase: bool
909+
) -> Option<PathBuf> {
910+
911+
let out_dir = builder.profdata_out(target);
912+
913+
flag.as_ref().and_then(|path| {
914+
if path == "default-path" {
915+
assert!(out_dir.is_absolute());
916+
917+
if is_use_phase {
918+
Some(out_dir.join("llvm").join("merged.profdata"))
919+
} else {
920+
Some(out_dir.join("llvm"))
921+
}
922+
} else {
923+
let path = PathBuf::from(&path);
924+
if !path.is_absolute() {
925+
eprintln!("warning: Ignoring llvm.profile-generate because \
926+
it is a relative path: `{}`", path.display());
927+
None
928+
} else {
929+
Some(path)
930+
}
931+
}
932+
})
933+
}
934+
935+
fn assert_cc_is_clang_for_pgo(builder: &Builder<'_>, target: TargetSelection) {
936+
// This is a stub impl. Make more intelligent.
937+
if !builder.cc(target).to_string_lossy().contains("clang") ||
938+
!builder.cxx(target).map(|cxx| cxx.to_string_lossy().contains("clang")).unwrap_or(false) {
939+
panic!("error: using PGO for LLVM is currently only supported with Clang");
940+
}
941+
}

0 commit comments

Comments
 (0)