Skip to content
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

Add Polly support. #51061

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitmodules
Expand Up @@ -64,4 +64,7 @@
path = src/tools/clang
url = https://github.com/rust-lang-nursery/clang.git
branch = rust-release-80-v1

[submodule "src/polly"]
path = src/polly
url = 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.

Perhaps rust-lang should have its own fork of this repo?
I could imagine that if upstream polly gets synced with upstream llvm but rustc uses rust-lang-llvm with llvm upstream polly, there might be conflicts between let's say polly 8.0 and llvm 7.0 (the rustc-lang fork).

Copy link
Member

Choose a reason for hiding this comment

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

We could track the release_70 branch instead of master if version incompatibility is the only concern.

branch = master
8 changes: 8 additions & 0 deletions config.toml.example
Expand Up @@ -337,6 +337,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.
# Also see the target's llvm-filecheck option.
Expand Down Expand Up @@ -395,6 +399,10 @@
# Whether to verify generated LLVM IR
#verify-llvm-ir = false

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

# Map all debuginfo paths for libstd and crates to `/rust/$sha/$crate/...`,
# generally only set for releases
#remap-debuginfo = false
Expand Down
11 changes: 10 additions & 1 deletion src/bootstrap/bin/rustc.rs
Expand Up @@ -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));

Expand Down Expand Up @@ -159,7 +160,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");
}

Expand Down Expand Up @@ -287,6 +288,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");
}

if env::var_os("RUSTC_DENY_WARNINGS").is_some() && env::var_os("RUSTC_EXTERNAL_TOOL").is_none()
{
cmd.arg("-Dwarnings");
Expand Down
12 changes: 12 additions & 0 deletions src/bootstrap/builder.rs
Expand Up @@ -1116,6 +1116,18 @@ impl<'a> Builder<'a> {
cargo.env("WINAPI_NO_BUNDLED_LIBRARIES", "1");
}

let use_polly = match cmd {
"test" | "bench" => {
self.config.rust_polly_tests
},
_ => self.config.rust_polly_self
};
if use_polly && stage > 1 {
cargo.env("RUSTC_USE_POLLY", "1");
} else {
cargo.env("RUSTC_USE_POLLY", "0");
}

for _ in 1..self.verbosity {
cargo.arg("-v");
}
Expand Down
16 changes: 16 additions & 0 deletions src/bootstrap/config.rs
Expand Up @@ -104,12 +104,14 @@ 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_verify_llvm_ir: bool,
pub rust_remap_debuginfo: bool,
pub rust_polly_self: bool,

pub build: Interned<String>,
pub hosts: Vec<Interned<String>>,
Expand Down Expand Up @@ -309,6 +311,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>,
Expand All @@ -327,6 +330,7 @@ struct Rust {
backtrace_on_ice: Option<bool>,
verify_llvm_ir: Option<bool>,
remap_debuginfo: Option<bool>,
polly_self: Option<bool>,
}

/// TOML representation of how each build target is configured.
Expand Down Expand Up @@ -541,6 +545,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);
Expand Down Expand Up @@ -580,6 +588,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 {
Expand Down Expand Up @@ -644,6 +656,10 @@ impl Config {
config.rust_debuginfo = debuginfo.unwrap_or(default);
config.rust_debug_assertions = debug_assertions.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);

Expand Down
6 changes: 5 additions & 1 deletion src/bootstrap/native.rs
Expand Up @@ -148,13 +148,17 @@ impl Step for Llvm {
.define("LLVM_INCLUDE_DOCS", "OFF")
.define("LLVM_INCLUDE_BENCHMARKS", "OFF")
.define("LLVM_ENABLE_ZLIB", "OFF")
.define("WITH_POLLY", "OFF")
.define("LLVM_ENABLE_TERMINFO", "OFF")
.define("LLVM_ENABLE_LIBEDIT", "OFF")
.define("LLVM_PARALLEL_COMPILE_JOBS", builder.jobs().to_string())
.define("LLVM_TARGET_ARCH", target.split('-').next().unwrap())
.define("LLVM_DEFAULT_TARGET_TRIPLE", target);

if !self.emscripten {
let polly_src = builder.src.join("src/polly");
cfg.define("LLVM_EXTERNAL_POLLY_SOURCE_DIR", polly_src);
}

if builder.config.llvm_thin_lto && !emscripten {
cfg.define("LLVM_ENABLE_LTO", "Thin")
.define("LLVM_ENABLE_LLD", "ON");
Expand Down
3 changes: 3 additions & 0 deletions src/bootstrap/test.rs
Expand Up @@ -1045,6 +1045,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);
Expand Down
4 changes: 4 additions & 0 deletions src/ci/docker/dist-i686-linux/Dockerfile
Expand Up @@ -86,6 +86,10 @@ RUN ./build-headers.sh
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh

# Polly needs `PATH_MAX`
ENV CFLAGS="-DPATH_MAX=4096 ${CFLAGS}"
ENV CXXFLAGS="-DPATH_MAX=4096 ${CXXFLAGS}"

ENV HOSTS=i686-unknown-linux-gnu

ENV RUST_CONFIGURE_ARGS \
Expand Down
4 changes: 4 additions & 0 deletions src/ci/docker/dist-x86_64-linux/Dockerfile
Expand Up @@ -86,6 +86,10 @@ RUN ./build-headers.sh
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh

# Polly needs `PATH_MAX`
ENV CFLAGS="-DPATH_MAX=4096 ${CFLAGS}"
ENV CXXFLAGS="-DPATH_MAX=4096 ${CXXFLAGS}"

ENV HOSTS=x86_64-unknown-linux-gnu

ENV RUST_CONFIGURE_ARGS \
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/session/config.rs
Expand Up @@ -1382,6 +1382,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"run the self profiler"),
profile_json: bool = (false, parse_bool, [UNTRACKED],
"output a json file with profiler results"),
polly: bool = (false, parse_bool, [UNTRACKED], "Run the Polly polyhedral \
model optimization passes."),
emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED],
"emits a section containing stack size metadata"),
plt: Option<bool> = (None, parse_opt_bool, [TRACKED],
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_codegen_llvm/back/lto.rs
Expand Up @@ -569,7 +569,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);

if config.verify_llvm_ir {
let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _);
Expand Down
25 changes: 17 additions & 8 deletions src/librustc_codegen_llvm/back/write.rs
Expand Up @@ -265,6 +265,7 @@ pub struct ModuleConfig {
no_integrated_as: bool,
embed_bitcode: bool,
embed_bitcode_marker: bool,
pub polly: bool,
}

impl ModuleConfig {
Expand Down Expand Up @@ -297,7 +298,8 @@ impl ModuleConfig {
vectorize_loop: false,
vectorize_slp: false,
merge_functions: false,
inline_threshold: None
inline_threshold: None,
polly: false,
}
}

Expand Down Expand Up @@ -336,6 +338,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;
}
}

Expand Down Expand Up @@ -568,8 +572,8 @@ unsafe fn optimize(cgcx: &CodegenContext,
|| config.obj_is_bitcode || config.emit_bc_compressed || config.embed_bitcode);
let mut have_name_anon_globals_pass = false;
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);
let prepare_for_thin_lto = cgcx.lto == Lto::Thin || cgcx.lto == Lto::ThinLocal ||
(cgcx.lto != Lto::Fat && cgcx.opts.debugging_opts.cross_lang_lto.enabled());
Expand Down Expand Up @@ -702,11 +706,12 @@ unsafe fn codegen(cgcx: &CodegenContext,
unsafe fn with_codegen<'ll, F, R>(tm: &'ll llvm::TargetMachine,
llmod: &'ll llvm::Module,
no_builtins: bool,
polly: bool,
f: F) -> R
where F: FnOnce(&'ll mut PassManager<'ll>) -> R,
{
let cpm = llvm::LLVMCreatePassManager();
llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod, polly);
llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
f(cpm)
}
Expand Down Expand Up @@ -801,7 +806,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);
});
Expand All @@ -819,15 +825,17 @@ 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)
})?;
timeline.record("asm");
}

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)
})?;
Expand Down Expand Up @@ -2221,7 +2229,8 @@ pub unsafe fn with_llvm_pmb(llmod: &llvm::Module,
llvm::LLVMPassManagerBuilderSetDisableUnrollLoops(builder, 1);
}

llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, config.no_builtins);
llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, config.no_builtins,
config.polly);

// Here we match what clang does (kinda). For O0 we only inline
// always-inline functions (but don't add lifetime intrinsics), at O1 we
Expand Down
6 changes: 4 additions & 2 deletions src/librustc_codegen_llvm/llvm/ffi.rs
Expand Up @@ -1470,10 +1470,12 @@ extern "C" {
EmitStackSizeSection: bool)
-> Option<&'static mut TargetMachine>;
pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine);
pub fn LLVMRustAddAnalysisPasses(T: &'a TargetMachine, PM: &PassManager<'a>, M: &'a Module);
pub fn LLVMRustAddAnalysisPasses(T: &'a TargetMachine, PM: &PassManager<'a>, M: &'a Module,
Polly: bool);
pub fn LLVMRustAddBuilderLibraryInfo(PMB: &'a PassManagerBuilder,
M: &'a Module,
DisableSimplifyLibCalls: bool);
DisableSimplifyLibCalls: bool,
Polly: bool);
pub fn LLVMRustConfigurePassManagerBuilder(PMB: &PassManagerBuilder,
OptLevel: CodeGenOptLevel,
MergeFunctions: bool,
Expand Down
57 changes: 57 additions & 0 deletions src/librustc_llvm/build.rs
Expand Up @@ -161,11 +161,54 @@ 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 = !cfg!(feature = "emscripten") &&
(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");
Expand Down Expand Up @@ -218,6 +261,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
Expand Down