From 7762503291c2f8caf3f2a5b3de9a5193ca998060 Mon Sep 17 00:00:00 2001 From: Richard Diamond Date: Sat, 24 Feb 2018 13:14:57 -0600 Subject: [PATCH] Add Polly support. It is always compiled and linked, but not used by default. Use can be triggered via `-C polly=true` or at compiler build-time (see `config.toml.example`). Force LLVM rebuild on buildbots. --- config.toml.example | 3 +++ src/bootstrap/bootstrap.py | 4 ++++ src/bootstrap/compile.rs | 3 +++ src/bootstrap/config.rs | 6 ++++++ src/librustc/session/config.rs | 3 +++ src/librustc_llvm/build.rs | 3 +++ src/librustc_llvm/ffi.rs | 3 ++- src/librustc_trans/back/lto.rs | 2 +- src/librustc_trans/back/write.rs | 22 +++++++++++++++------- src/rustllvm/PassWrapper.cpp | 18 +++++++++++++++++- src/rustllvm/llvm-rebuild-trigger | 2 +- 11 files changed, 58 insertions(+), 11 deletions(-) diff --git a/config.toml.example b/config.toml.example index effe00843810d..a574bd1c02f56 100644 --- a/config.toml.example +++ b/config.toml.example @@ -346,6 +346,9 @@ # Whether to deny warnings in crates #deny-warnings = true +# Use polyhedral optimizations by default. +#use-polly-by-default = false + # ============================================================================= # Options for specific targets # diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 487440becf630..f5ba263cd1258 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -690,6 +690,10 @@ def update_submodules(self): recorded_submodules[data[3]] = data[2] for module in filtered_submodules: self.update_submodule(module[0], module[1], recorded_submodules) + polly_path = "src/llvm/tools/polly" + if not os.path.exists(os.path.join(self.rust_root, polly_path)): + run(["git", "clone", "https://github.com/llvm-mirror/polly.git", + "src/llvm/tools/polly", "-b", "release_60"]) print("Submodules updated in %.2f seconds" % (time() - start_time)) def set_dev_environment(self): diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 07bce77af8d24..f1d94ebbee7ee 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -553,6 +553,9 @@ fn rustc_cargo_env(builder: &Builder, cargo: &mut Command) { if builder.config.rustc_parallel_queries { cargo.env("RUSTC_PARALLEL_QUERIES", "1"); } + if builder.config.rust_codegen_polly_by_default { + cargo.env("RUSTC_FORCE_USE_POLLY", "1"); + } } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 1b4b2c5fb2a54..35c08c5865932 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -103,6 +103,7 @@ pub struct Config { pub rust_dist_src: bool, pub rust_codegen_backends: Vec>, pub rust_codegen_backends_dir: String, + pub rust_codegen_polly_by_default: bool, pub build: Interned, pub hosts: Vec>, @@ -306,6 +307,7 @@ struct Rust { wasm_syscall: Option, lld: Option, deny_warnings: Option, + use_polly_by_default: Option, } /// TOML representation of how each build target is configured. @@ -537,6 +539,10 @@ impl Config { Some(n) => config.rust_codegen_units = Some(n), None => {} } + + config.rust_codegen_polly_by_default = rust + .use_polly_by_default + .unwrap_or(false); } if let Some(ref t) = toml.target { diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 59823390a0a58..1b46d0fe227e8 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1074,6 +1074,9 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, [TRACKED], "panic strategy to compile crate with"), incremental: Option = (None, parse_opt_string, [UNTRACKED], "enable incremental compilation"), + polly: bool = (option_env!("RUSTC_FORCE_USE_POLLY").map(|_| true ).unwrap_or(false), + parse_bool, [UNTRACKED], "Run the Polly polyhedral \ + model optimization passes."), } options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 54e3f544acb68..97a42893f9716 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -208,6 +208,9 @@ fn main() { println!("cargo:rustc-link-lib={}={}", kind, name); } + println!("cargo:rustc-link-lib=static=Polly"); + println!("cargo:rustc-link-lib=static=PollyISL"); + // LLVM ldflags // // If we're a cross-compile of LLVM then unfortunately we can't trust these diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs index dba2e918f6f3a..dcbfe52eee1aa 100644 --- a/src/librustc_llvm/ffi.rs +++ b/src/librustc_llvm/ffi.rs @@ -1642,7 +1642,8 @@ extern "C" { Singlethread: bool) -> TargetMachineRef; pub fn LLVMRustDisposeTargetMachine(T: TargetMachineRef); - pub fn LLVMRustAddAnalysisPasses(T: TargetMachineRef, PM: PassManagerRef, M: ModuleRef); + pub fn LLVMRustAddAnalysisPasses(T: TargetMachineRef, PM: PassManagerRef, M: ModuleRef, + Polly: bool); pub fn LLVMRustAddBuilderLibraryInfo(PMB: PassManagerBuilderRef, M: ModuleRef, DisableSimplifyLibCalls: bool); diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index 2a473f1ecbcc5..bbf2fc74a0ac0 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -460,7 +460,7 @@ fn run_pass_manager(cgcx: &CodegenContext, debug!("running the pass manager"); unsafe { let pm = llvm::LLVMCreatePassManager(); - llvm::LLVMRustAddAnalysisPasses(tm, pm, llmod); + llvm::LLVMRustAddAnalysisPasses(tm, pm, llmod, config.polly); let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _); assert!(!pass.is_null()); llvm::LLVMRustAddPass(pm, pass); diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index f501b1739eb9c..d619f328b6b65 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -271,6 +271,7 @@ pub struct ModuleConfig { no_integrated_as: bool, embed_bitcode: bool, embed_bitcode_marker: bool, + pub polly: bool, } impl ModuleConfig { @@ -302,7 +303,8 @@ impl ModuleConfig { vectorize_loop: false, vectorize_slp: false, merge_functions: false, - inline_threshold: None + inline_threshold: None, + polly: false, } } @@ -340,6 +342,8 @@ impl ModuleConfig { self.merge_functions = sess.opts.optimize == config::OptLevel::Default || sess.opts.optimize == config::OptLevel::Aggressive; + self.polly = sess.opts.cg.polly && !self.no_prepopulate_passes && + !sess.target.target.options.is_like_emscripten; } } @@ -567,8 +571,8 @@ unsafe fn optimize(cgcx: &CodegenContext, if !config.no_verify { assert!(addpass("verify")); } if !config.no_prepopulate_passes { - llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod); - llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod); + llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod, config.polly); + llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod, config.polly); let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None); with_llvm_pmb(llmod, &config, opt_level, &mut |b| { llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm); @@ -666,11 +670,12 @@ unsafe fn codegen(cgcx: &CodegenContext, unsafe fn with_codegen(tm: TargetMachineRef, llmod: ModuleRef, no_builtins: bool, + polly: bool, f: F) -> R where F: FnOnce(PassManagerRef) -> R, { let cpm = llvm::LLVMCreatePassManager(); - llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod); + llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod, polly); llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins); f(cpm) } @@ -765,7 +770,8 @@ unsafe fn codegen(cgcx: &CodegenContext, cursor.position() as size_t } - with_codegen(tm, llmod, config.no_builtins, |cpm| { + with_codegen(tm, llmod, config.no_builtins, config.polly, + |cpm| { llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr(), demangle_callback); llvm::LLVMDisposePassManager(cpm); }); @@ -783,7 +789,8 @@ unsafe fn codegen(cgcx: &CodegenContext, } else { llmod }; - with_codegen(tm, llmod, config.no_builtins, |cpm| { + with_codegen(tm, llmod, config.no_builtins, config.polly, + |cpm| { write_output_file(diag_handler, tm, cpm, llmod, &path, llvm::FileType::AssemblyFile) })?; @@ -794,7 +801,8 @@ unsafe fn codegen(cgcx: &CodegenContext, } if write_obj { - with_codegen(tm, llmod, config.no_builtins, |cpm| { + with_codegen(tm, llmod, config.no_builtins, config.polly, + |cpm| { write_output_file(diag_handler, tm, cpm, llmod, &obj_out, llvm::FileType::ObjectFile) })?; diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 382ef2cc407dd..eca4be5d3e209 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -61,6 +61,11 @@ DEFINE_STDCXX_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef) DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassManagerBuilder, LLVMPassManagerBuilderRef) + +namespace polly { +void initializePollyPasses(llvm::PassRegistry &Registry); +} + extern "C" void LLVMInitializePasses() { PassRegistry &Registry = *PassRegistry::getPassRegistry(); initializeCore(Registry); @@ -73,6 +78,8 @@ extern "C" void LLVMInitializePasses() { initializeInstCombine(Registry); initializeInstrumentation(Registry); initializeTarget(Registry); + + polly::initializePollyPasses(Registry); } enum class LLVMRustPassKind { @@ -415,15 +422,24 @@ extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) { delete unwrap(TM); } +namespace polly { +void registerPollyPasses(llvm::legacy::PassManagerBase &PM); +} + // Unfortunately, LLVM doesn't expose a C API to add the corresponding analysis // passes for a target to a pass manager. We export that functionality through // this function. extern "C" void LLVMRustAddAnalysisPasses(LLVMTargetMachineRef TM, LLVMPassManagerRef PMR, - LLVMModuleRef M) { + LLVMModuleRef M, + bool Polly) { PassManagerBase *PM = unwrap(PMR); PM->add( createTargetTransformInfoWrapperPass(unwrap(TM)->getTargetIRAnalysis())); + + if(Polly) { + polly::registerPollyPasses(*PM); + } } extern "C" void LLVMRustConfigurePassManagerBuilder( diff --git a/src/rustllvm/llvm-rebuild-trigger b/src/rustllvm/llvm-rebuild-trigger index c3fc3e5452c4f..15ba34c3da429 100644 --- a/src/rustllvm/llvm-rebuild-trigger +++ b/src/rustllvm/llvm-rebuild-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2018-04-05 +2018-04-18