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
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
5 changes: 4 additions & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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.
@@ -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
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));

@@ -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");
}

@@ -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");
12 changes: 12 additions & 0 deletions src/bootstrap/builder.rs
Original file line number Diff line number Diff line change
@@ -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");
}
16 changes: 16 additions & 0 deletions src/bootstrap/config.rs
Original file line number Diff line number Diff line change
@@ -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>>,
@@ -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>,
@@ -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.
@@ -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);
@@ -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 {
@@ -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);

6 changes: 5 additions & 1 deletion src/bootstrap/native.rs
Original file line number Diff line number Diff line change
@@ -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");
3 changes: 3 additions & 0 deletions src/bootstrap/test.rs
Original file line number Diff line number Diff line change
@@ -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);
4 changes: 4 additions & 0 deletions src/ci/docker/dist-i686-linux/Dockerfile
Original file line number Diff line number Diff line change
@@ -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 \
4 changes: 4 additions & 0 deletions src/ci/docker/dist-x86_64-linux/Dockerfile
Original file line number Diff line number Diff line change
@@ -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 \
2 changes: 2 additions & 0 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
@@ -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],
2 changes: 1 addition & 1 deletion src/librustc_codegen_llvm/back/lto.rs
Original file line number Diff line number Diff line change
@@ -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 _);
25 changes: 17 additions & 8 deletions src/librustc_codegen_llvm/back/write.rs
Original file line number Diff line number Diff line change
@@ -265,6 +265,7 @@ pub struct ModuleConfig {
no_integrated_as: bool,
embed_bitcode: bool,
embed_bitcode_marker: bool,
pub polly: bool,
}

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

@@ -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;
}
}

@@ -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());
@@ -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)
}
@@ -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);
});
@@ -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)
})?;
@@ -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
6 changes: 4 additions & 2 deletions src/librustc_codegen_llvm/llvm/ffi.rs
Original file line number Diff line number Diff line change
@@ -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,
57 changes: 57 additions & 0 deletions src/librustc_llvm/build.rs
Original file line number Diff line number Diff line change
@@ -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");
@@ -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
1 change: 1 addition & 0 deletions src/polly
Submodule polly added at d3b94f
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 {
@@ -434,10 +445,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(
1 change: 1 addition & 0 deletions src/tools/tidy/src/lib.rs
Original file line number Diff line number Diff line change
@@ -78,6 +78,7 @@ fn filter_dirs(path: &Path) -> bool {
"src/tools/lldb",
"src/target",
"src/stdsimd",
"src/polly",
];
skip.iter().any(|p| path.ends_with(p))
}