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-macro \
|
||||||
--package peepmatic-runtime \
|
--package peepmatic-runtime \
|
||||||
--package peepmatic-test
|
--package peepmatic-test
|
||||||
- name: Rebuild Cranelift's peepmatic-based peephole optimizers
|
- name: Rebuild Peepmatic-based peephole optimizers and test them
|
||||||
run: |
|
run: cargo test --features 'enable-peepmatic cranelift-codegen/rebuild-peephole-optimizers'
|
||||||
cd cranelift/
|
working-directory: ./cranelift
|
||||||
cargo build --features 'enable-peepmatic cranelift-codegen/rebuild-peephole-optimizers'
|
|
||||||
- name: Check that peephole optimizers are up to date
|
- name: Check that peephole optimizers are up to date
|
||||||
run: git diff --exit-code
|
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
|
# Perform all tests (debug mode) for `wasmtime`. This runs stable/beta/nightly
|
||||||
# channels of Rust as well as macOS/Linux/Windows.
|
# 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" }
|
smallvec = { version = "1.0.0" }
|
||||||
thiserror = "1.0.4"
|
thiserror = "1.0.4"
|
||||||
byteorder = { version = "1.3.2", default-features = false }
|
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" }
|
peepmatic-runtime = { path = "../peepmatic/crates/runtime", optional = true, version = "0.2.0" }
|
||||||
regalloc = { version = "0.0.28" }
|
regalloc = { version = "0.0.28" }
|
||||||
# It is a goal of the cranelift-codegen crate to have minimal external dependencies.
|
# 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]
|
[build-dependencies]
|
||||||
cranelift-codegen-meta = { path = "meta", version = "0.66.0" }
|
cranelift-codegen-meta = { path = "meta", version = "0.66.0" }
|
||||||
peepmatic = { path = "../peepmatic", optional = true, version = "0.66.0" }
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std", "unwind"]
|
default = ["std", "unwind"]
|
||||||
|
|||||||
@@ -90,20 +90,11 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "rebuild-peephole-optimizers")]
|
#[cfg(feature = "rebuild-peephole-optimizers")]
|
||||||
rebuild_peephole_optimizers();
|
{
|
||||||
}
|
std::fs::write(
|
||||||
|
std::path::Path::new(&out_dir).join("CRANELIFT_CODEGEN_PATH"),
|
||||||
#[cfg(feature = "rebuild-peephole-optimizers")]
|
cur_dir.to_str().unwrap(),
|
||||||
fn rebuild_peephole_optimizers() {
|
)
|
||||||
use std::path::Path;
|
.unwrap()
|
||||||
|
}
|
||||||
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`");
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ use peepmatic_runtime::{
|
|||||||
r#type::{BitWidth, Kind, Type},
|
r#type::{BitWidth, Kind, Type},
|
||||||
PeepholeOptimizations, PeepholeOptimizer,
|
PeepholeOptimizations, PeepholeOptimizer,
|
||||||
};
|
};
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::boxed::Box;
|
use std::boxed::Box;
|
||||||
use std::convert::{TryFrom, TryInto};
|
use std::convert::{TryFrom, TryInto};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
@@ -28,7 +29,34 @@ use std::sync::atomic::{AtomicPtr, Ordering};
|
|||||||
pub(crate) fn preopt<'a, 'b>(
|
pub(crate) fn preopt<'a, 'b>(
|
||||||
isa: &'b dyn TargetIsa,
|
isa: &'b dyn TargetIsa,
|
||||||
) -> PeepholeOptimizer<'static, 'a, &'b dyn TargetIsa> {
|
) -> PeepholeOptimizer<'static, 'a, &'b dyn TargetIsa> {
|
||||||
|
#[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");
|
static SERIALIZED: &[u8] = include_bytes!("preopt.serialized");
|
||||||
|
}
|
||||||
|
|
||||||
// Once initialized, this must never be re-assigned. The initialized value
|
// Once initialized, this must never be re-assigned. The initialized value
|
||||||
// is semantically "static data" and is intentionally leaked for the whole
|
// 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
|
// 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
|
// race to see who initializes `DESERIALIZED` first, and we need to be
|
||||||
// prepared to both win or lose that race.
|
// 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`");
|
.expect("should always be able to deserialize `preopt.serialized`");
|
||||||
let peep_opts = Box::into_raw(Box::new(peep_opts));
|
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()
|
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