Skip to content

Add Polly support #50044

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions config.toml.example
Original file line number Diff line number Diff line change
@@ -303,6 +303,10 @@
#optimize-tests = true
#debuginfo-tests = true

# Flag indicating whether tests are optimized with Polly. If optimize-tests is false,
# polly-tests will be false regardless of its value here.
#polly-tests = false

# Flag indicating whether codegen tests will be run or not. If you get an error
# saying that the FileCheck executable is missing, you may want to disable this.
#codegen-tests = true
@@ -346,6 +350,10 @@
# Whether to deny warnings in crates
#deny-warnings = true

# Use Polly on the rust compiler itself. If optimize is false, this will be
# false as well.
#polly-self = false

# =============================================================================
# Options for specific targets
#
11 changes: 10 additions & 1 deletion src/bootstrap/bin/rustc.rs
Original file line number Diff line number Diff line change
@@ -91,6 +91,7 @@ fn main() {
("RUSTC_REAL", "RUSTC_LIBDIR")
};
let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
let stage = usize::from_str(stage.as_str()).expect("RUSTC_STAGE not a usize");
let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
let on_fail = env::var_os("RUSTC_ON_FAIL").map(|of| Command::new(of));

@@ -152,7 +153,7 @@ fn main() {
// workaround undefined references to `rust_eh_unwind_resume` generated
// otherwise, see issue https://github.com/rust-lang/rust/issues/43095.
if crate_name == "panic_abort" ||
crate_name == "compiler_builtins" && stage != "0" {
crate_name == "compiler_builtins" && stage != 0 {
cmd.arg("-C").arg("panic=abort");
}

@@ -267,6 +268,14 @@ fn main() {
cmd.arg("--cfg").arg("parallel_queries");
}

let use_polly = match env::var("RUSTC_USE_POLLY") {
Ok(v) => v != "0",
Err(_) => false,
};
if use_polly && stage >= 1 {
cmd.arg("-Z").arg("polly");
}

let color = match env::var("RUSTC_COLOR") {
Ok(s) => usize::from_str(&s).expect("RUSTC_COLOR should be an integer"),
Err(_) => 0,
4 changes: 4 additions & 0 deletions src/bootstrap/bootstrap.py
Original file line number Diff line number Diff line change
@@ -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",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this not be a normal submodule placed in src/polly for example? I believe you can use LLVM_EXTERNAL_POLLY_SOURCE_DIR to tell llvm where to find it.

"src/llvm/tools/polly", "-b", "release_60"])
print("Submodules updated in %.2f seconds" % (time() - start_time))

def set_dev_environment(self):
14 changes: 13 additions & 1 deletion src/bootstrap/compile.rs
Original file line number Diff line number Diff line change
@@ -36,7 +36,7 @@ use native;
use tool;

use cache::{INTERNER, Interned};
use builder::{Step, RunConfig, ShouldRun, Builder};
use builder::{Step, RunConfig, ShouldRun, Builder, Kind};

#[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Std {
@@ -553,6 +553,18 @@ pub fn rustc_cargo_env(builder: &Builder, cargo: &mut Command) {
if builder.config.rustc_parallel_queries {
cargo.env("RUSTC_PARALLEL_QUERIES", "1");
}

let use_polly = match builder.kind {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

builder.kind only records how x.py is invoked, i.e. if you use

./x.py test src/test/compile-fail ...

then librustc etc will be built with builder.config.rust_polly_tests instead of builder.config.rust_polly_self, even if it is a build artifact.

Kind::Test | Kind::Check => {
builder.config.rust_polly_tests
},
_ => builder.config.rust_polly_self
};
if use_polly {
cargo.env("RUSTC_USE_POLLY", "1");
} else {
cargo.env("RUSTC_USE_POLLY", "0");
}
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
16 changes: 16 additions & 0 deletions src/bootstrap/config.rs
Original file line number Diff line number Diff line change
@@ -99,10 +99,12 @@ pub struct Config {
pub rustc_parallel_queries: bool,
pub rustc_default_linker: Option<String>,
pub rust_optimize_tests: bool,
pub rust_polly_tests: bool,
pub rust_debuginfo_tests: bool,
pub rust_dist_src: bool,
pub rust_codegen_backends: Vec<Interned<String>>,
pub rust_codegen_backends_dir: String,
pub rust_polly_self: bool,

pub build: Interned<String>,
pub hosts: Vec<Interned<String>>,
@@ -294,6 +296,7 @@ struct Rust {
rpath: Option<bool>,
optimize_tests: Option<bool>,
debuginfo_tests: Option<bool>,
polly_tests: Option<bool>,
codegen_tests: Option<bool>,
ignore_git: Option<bool>,
debug: Option<bool>,
@@ -306,6 +309,7 @@ struct Rust {
wasm_syscall: Option<bool>,
lld: Option<bool>,
deny_warnings: Option<bool>,
polly_self: Option<bool>,
}

/// TOML representation of how each build target is configured.
@@ -515,6 +519,10 @@ impl Config {
ignore_git = rust.ignore_git;
debug_jemalloc = rust.debug_jemalloc;
set(&mut config.rust_optimize_tests, rust.optimize_tests);
set(&mut config.rust_polly_tests, rust.polly_tests);
if !config.rust_optimize_tests {
config.rust_polly_tests = false;
}
set(&mut config.rust_debuginfo_tests, rust.debuginfo_tests);
set(&mut config.codegen_tests, rust.codegen_tests);
set(&mut config.rust_rpath, rust.rpath);
@@ -545,6 +553,10 @@ impl Config {
Some(n) => config.rust_codegen_units = Some(n),
None => {}
}

config.rust_polly_self = rust
.polly_self
.unwrap_or(false);
}

if let Some(ref t) = toml.target {
@@ -602,6 +614,10 @@ impl Config {
config.rust_debug_assertions = debug_assertions.unwrap_or(default);
config.rust_optimize = optimize.unwrap_or(!default);

if !config.rust_optimize {
config.rust_polly_self = false;
}

let default = config.channel == "dev";
config.ignore_git = ignore_git.unwrap_or(default);

3 changes: 3 additions & 0 deletions src/bootstrap/test.rs
Original file line number Diff line number Diff line change
@@ -960,6 +960,9 @@ impl Step for Compiletest {
}
flags.push("-Zunstable-options".to_string());
flags.push(builder.config.cmd.rustc_args().join(" "));
if builder.config.rust_polly_self {
flags.push("-Zpolly".into());
}

if let Some(linker) = builder.linker(target) {
cmd.arg("--linker").arg(linker);
2 changes: 2 additions & 0 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
@@ -1293,6 +1293,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"make the current crate share its generic instantiations"),
chalk: bool = (false, parse_bool, [TRACKED],
"enable the experimental Chalk-based trait solving engine"),
polly: bool = (false, parse_bool, [UNTRACKED], "Run the Polly polyhedral \
model optimization passes."),
}

pub fn default_lib_output() -> CrateType {
56 changes: 56 additions & 0 deletions src/librustc_llvm/build.rs
Original file line number Diff line number Diff line change
@@ -157,11 +157,53 @@ fn main() {
cfg.define("LLVM_RUSTLLVM", None);
}

let (enable_polly, polly_link_kind, polly_link_isl) = {
let mut cmd = Command::new(&llvm_config);
cmd.arg("--libdir");
let libdir = output(&mut cmd);
let libdir = libdir.lines().next().unwrap();
let libdir = Path::new(&libdir);
assert!(libdir.exists());

// We can't specify the full libname to rust, so the linker will always expect (on unix)
// LLVMPolly to be libLLVMPolly, which won't be present. I didn't realize this fact until
// after I wrote the following, but maybe this issue will be resolved in the future.
let allow_shared = false;
let mut found_static = false;
let mut found_shared = false;
for entry in libdir.read_dir().unwrap() {
if let Ok(entry) = entry {
if let Some(name) = entry.path().file_name() {
let name = name.to_str().unwrap();
if name.contains("Polly") {
if !found_static {
found_static = !name.contains("LLVM");
}
if !found_shared {
found_shared = name.contains("LLVM");
}
}
}
}
}

let found_static = found_static;
let found_shared = allow_shared && found_shared;
let enabled = found_static || found_shared;
let (kind, isl) = match (found_static, found_shared) {
(false, false) => ("", false),
(true, _) => ("static", true),
(false, true) => ("dylib", false),
};
(enabled, kind, isl)
};

build_helper::rerun_if_changed_anything_in_dir(Path::new("../rustllvm"));
cfg.file("../rustllvm/PassWrapper.cpp")
.file("../rustllvm/RustWrapper.cpp")
.file("../rustllvm/ArchiveWrapper.cpp")
.file("../rustllvm/Linker.cpp")
.define("ENABLE_POLLY", if enable_polly { "1" } else { "0" })
.cpp(true)
.cpp_link_stdlib(None) // we handle this below
.compile("rustllvm");
@@ -214,6 +256,20 @@ fn main() {
println!("cargo:rustc-link-lib={}={}", kind, name);
}

if enable_polly {
match polly_link_kind {
"dylib" => {
panic!("dynamically linking polly is not possible :(");
//println!("cargo:rustc-flags=-l:LLVMPolly")
},
_ => println!("cargo:rustc-link-lib={}=Polly", polly_link_kind),
}

if polly_link_isl {
println!("cargo:rustc-link-lib={}=PollyISL", polly_link_kind);
}
}

// LLVM ldflags
//
// If we're a cross-compile of LLVM then unfortunately we can't trust these
3 changes: 2 additions & 1 deletion src/librustc_llvm/ffi.rs
Original file line number Diff line number Diff line change
@@ -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);
2 changes: 1 addition & 1 deletion src/librustc_trans/back/lto.rs
Original file line number Diff line number Diff line change
@@ -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);
22 changes: 15 additions & 7 deletions src/librustc_trans/back/write.rs
Original file line number Diff line number Diff line change
@@ -250,6 +250,7 @@ pub struct ModuleConfig {
no_integrated_as: bool,
embed_bitcode: bool,
embed_bitcode_marker: bool,
pub polly: bool,
}

impl ModuleConfig {
@@ -281,7 +282,8 @@ impl ModuleConfig {
vectorize_loop: false,
vectorize_slp: false,
merge_functions: false,
inline_threshold: None
inline_threshold: None,
polly: false,
}
}

@@ -319,6 +321,8 @@ impl ModuleConfig {

self.merge_functions = sess.opts.optimize == config::OptLevel::Default ||
sess.opts.optimize == config::OptLevel::Aggressive;
self.polly = sess.opts.debugging_opts.polly && !self.no_prepopulate_passes &&
!sess.target.target.options.is_like_emscripten;
}
}

@@ -546,8 +550,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);
@@ -645,11 +649,12 @@ unsafe fn codegen(cgcx: &CodegenContext,
unsafe fn with_codegen<F, R>(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)
}
@@ -744,7 +749,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);
});
@@ -762,7 +768,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)
})?;
@@ -773,7 +780,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)
})?;
22 changes: 21 additions & 1 deletion src/rustllvm/PassWrapper.cpp
Original file line number Diff line number Diff line change
@@ -61,6 +61,13 @@ DEFINE_STDCXX_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassManagerBuilder,
LLVMPassManagerBuilderRef)

#if ENABLE_POLLY
namespace polly {
void initializePollyPasses(llvm::PassRegistry &Registry);
void registerPollyPasses(llvm::legacy::PassManagerBase &PM);
}
#endif

extern "C" void LLVMInitializePasses() {
PassRegistry &Registry = *PassRegistry::getPassRegistry();
initializeCore(Registry);
@@ -73,6 +80,10 @@ extern "C" void LLVMInitializePasses() {
initializeInstCombine(Registry);
initializeInstrumentation(Registry);
initializeTarget(Registry);

#if ENABLE_POLLY
polly::initializePollyPasses(Registry);
#endif
}

enum class LLVMRustPassKind {
@@ -420,10 +431,19 @@ extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) {
// 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 ENABLE_POLLY
if(Polly) {
polly::registerPollyPasses(*PM);
}
#else
(void)Polly;
#endif
}

extern "C" void LLVMRustConfigurePassManagerBuilder(
2 changes: 1 addition & 1 deletion src/rustllvm/llvm-rebuild-trigger
Original file line number Diff line number Diff line change
@@ -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