cranelift: Don't build peepmatic-based optimizations in build.rs
Instead, when the `rebuild-peephole-optimizers` feature is enabled, rebuild them the first time they are used. This allows peepmatic to run when Cranelift's `Opcode` is defined and available, which paves the way forward for: * merging `peepmatic_runtime::operator::Operator` and Cranelift's `Opcode` (we are wasting a bunch of cycles converting between the two of them), and * supporting vcode optimizations in `peepmatic`.
This commit is contained in:
11
.github/workflows/main.yml
vendored
11
.github/workflows/main.yml
vendored
@@ -162,16 +162,11 @@ jobs:
|
||||
--package peepmatic-macro \
|
||||
--package peepmatic-runtime \
|
||||
--package peepmatic-test
|
||||
- name: Rebuild Cranelift's peepmatic-based peephole optimizers
|
||||
run: |
|
||||
cd cranelift/
|
||||
cargo build --features 'enable-peepmatic cranelift-codegen/rebuild-peephole-optimizers'
|
||||
- name: Rebuild Peepmatic-based peephole optimizers and test them
|
||||
run: cargo test --features 'enable-peepmatic cranelift-codegen/rebuild-peephole-optimizers'
|
||||
working-directory: ./cranelift
|
||||
- name: Check that peephole optimizers are up to date
|
||||
run: git diff --exit-code
|
||||
- name: Test `cranelift-codegen` with `peepmatic` enabled
|
||||
run: |
|
||||
cd cranelift/
|
||||
cargo test --features 'enable-peepmatic'
|
||||
|
||||
# Perform all tests (debug mode) for `wasmtime`. This runs stable/beta/nightly
|
||||
# channels of Rust as well as macOS/Linux/Windows.
|
||||
|
||||
@@ -25,6 +25,7 @@ gimli = { version = "0.21.0", default-features = false, features = ["write"], op
|
||||
smallvec = { version = "1.0.0" }
|
||||
thiserror = "1.0.4"
|
||||
byteorder = { version = "1.3.2", default-features = false }
|
||||
peepmatic = { path = "../peepmatic", optional = true, version = "0.66.0" }
|
||||
peepmatic-runtime = { path = "../peepmatic/crates/runtime", optional = true, version = "0.2.0" }
|
||||
regalloc = { version = "0.0.28" }
|
||||
# It is a goal of the cranelift-codegen crate to have minimal external dependencies.
|
||||
@@ -34,7 +35,6 @@ regalloc = { version = "0.0.28" }
|
||||
|
||||
[build-dependencies]
|
||||
cranelift-codegen-meta = { path = "meta", version = "0.66.0" }
|
||||
peepmatic = { path = "../peepmatic", optional = true, version = "0.66.0" }
|
||||
|
||||
[features]
|
||||
default = ["std", "unwind"]
|
||||
|
||||
@@ -90,20 +90,11 @@ fn main() {
|
||||
}
|
||||
|
||||
#[cfg(feature = "rebuild-peephole-optimizers")]
|
||||
rebuild_peephole_optimizers();
|
||||
}
|
||||
|
||||
#[cfg(feature = "rebuild-peephole-optimizers")]
|
||||
fn rebuild_peephole_optimizers() {
|
||||
use std::path::Path;
|
||||
|
||||
let source_path = Path::new("src").join("preopt.peepmatic");
|
||||
println!("cargo:rerun-if-changed={}", source_path.display());
|
||||
|
||||
let preopt =
|
||||
peepmatic::compile_file(&source_path).expect("failed to compile `src/preopt.peepmatic`");
|
||||
|
||||
preopt
|
||||
.serialize_to_file(&Path::new("src").join("preopt.serialized"))
|
||||
.expect("failed to serialize peephole optimizer to `src/preopt.serialized`");
|
||||
{
|
||||
std::fs::write(
|
||||
std::path::Path::new(&out_dir).join("CRANELIFT_CODEGEN_PATH"),
|
||||
cur_dir.to_str().unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ use peepmatic_runtime::{
|
||||
r#type::{BitWidth, Kind, Type},
|
||||
PeepholeOptimizations, PeepholeOptimizer,
|
||||
};
|
||||
use std::borrow::Cow;
|
||||
use std::boxed::Box;
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::ptr;
|
||||
@@ -28,7 +29,34 @@ use std::sync::atomic::{AtomicPtr, Ordering};
|
||||
pub(crate) fn preopt<'a, 'b>(
|
||||
isa: &'b dyn TargetIsa,
|
||||
) -> PeepholeOptimizer<'static, 'a, &'b dyn TargetIsa> {
|
||||
static SERIALIZED: &[u8] = include_bytes!("preopt.serialized");
|
||||
#[cfg(feature = "rebuild-peephole-optimizers")]
|
||||
fn get_serialized() -> Cow<'static, [u8]> {
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
let codegen_path = Path::new(include_str!(concat!(
|
||||
env!("OUT_DIR"),
|
||||
"/CRANELIFT_CODEGEN_PATH"
|
||||
)));
|
||||
let source_path = codegen_path.join("src").join("preopt.peepmatic");
|
||||
println!("cargo:rerun-if-changed={}", source_path.display());
|
||||
|
||||
let preopt = peepmatic::compile_file(&source_path)
|
||||
.expect("failed to compile `src/preopt.peepmatic`");
|
||||
|
||||
let serialized_path = codegen_path.join("src").join("preopt.serialized");
|
||||
preopt
|
||||
.serialize_to_file(&serialized_path)
|
||||
.expect("failed to serialize peephole optimizer to `src/preopt.serialized`");
|
||||
fs::read(&serialized_path)
|
||||
.expect("failed to read `src/preopt.serialized`")
|
||||
.into()
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "rebuild-peephole-optimizers"))]
|
||||
fn get_serialized() -> Cow<'static, [u8]> {
|
||||
static SERIALIZED: &[u8] = include_bytes!("preopt.serialized");
|
||||
}
|
||||
|
||||
// Once initialized, this must never be re-assigned. The initialized value
|
||||
// is semantically "static data" and is intentionally leaked for the whole
|
||||
@@ -46,7 +74,7 @@ pub(crate) fn preopt<'a, 'b>(
|
||||
// another thread could be doing the same thing concurrently, so there is a
|
||||
// race to see who initializes `DESERIALIZED` first, and we need to be
|
||||
// prepared to both win or lose that race.
|
||||
let peep_opts = PeepholeOptimizations::deserialize(SERIALIZED)
|
||||
let peep_opts = PeepholeOptimizations::deserialize(&get_serialized())
|
||||
.expect("should always be able to deserialize `preopt.serialized`");
|
||||
let peep_opts = Box::into_raw(Box::new(peep_opts));
|
||||
|
||||
@@ -891,3 +919,21 @@ unsafe impl<'a, 'b> InstructionSet<'b> for &'a dyn TargetIsa {
|
||||
self.pointer_bits()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(feature = "x86")]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::isa::lookup;
|
||||
use crate::settings::{builder, Flags};
|
||||
use std::str::FromStr;
|
||||
use target_lexicon::triple;
|
||||
|
||||
#[test]
|
||||
fn get_peepmatic_preopt() {
|
||||
let isa = lookup(triple!("x86_64"))
|
||||
.expect("expect x86 ISA")
|
||||
.finish(Flags::new(builder()));
|
||||
let _ = preopt(&*isa);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user