Remove old tests and reexport libfuzzer from fuzzing module (#69)
* Remove unused regalloc2-test crate This code doesn't build, and Chris says it's "a really old harness that existed prior to building the fuzzing and was used mainly to profile and get stats before integration with Cranelift". * Re-export libfuzzer/arbitrary from fuzzing module This avoids needing to keep dependencies on `arbitrary` in sync across the three different Cargo.toml files in this project. However, before version 0.4.2, libfuzzer-sys only supported using its macros if it was available at the top-level `libfuzzer_sys` path, which breaks when re-exporting it. So I'm upgrading to that version (or the newest patch release of it). Upgrading libfuzzer-sys in turn brings in the 1.0 release of the arbitrary crate, with a minor API change along the way.
This commit is contained in:
@@ -20,8 +20,7 @@ slice-group-by = "0.3.0"
|
|||||||
serde = { version = "1.0.136", features = ["derive"], optional = true }
|
serde = { version = "1.0.136", features = ["derive"], optional = true }
|
||||||
|
|
||||||
# The below are only needed for fuzzing.
|
# The below are only needed for fuzzing.
|
||||||
# Keep this in sync with libfuzzer_sys's crate version:
|
libfuzzer-sys = { version = "0.4.2", optional = true }
|
||||||
arbitrary = { version = "^0.4.6", optional = true }
|
|
||||||
|
|
||||||
# When testing regalloc2 by itself, enable debug assertions and overflow checks
|
# When testing regalloc2 by itself, enable debug assertions and overflow checks
|
||||||
[profile.release]
|
[profile.release]
|
||||||
@@ -39,7 +38,7 @@ checker = []
|
|||||||
trace-log = []
|
trace-log = []
|
||||||
|
|
||||||
# Exposes the internal API for fuzzing.
|
# Exposes the internal API for fuzzing.
|
||||||
fuzzing = ["arbitrary", "checker", "trace-log"]
|
fuzzing = ["libfuzzer-sys", "checker", "trace-log"]
|
||||||
|
|
||||||
# Enables serde for exposed types.
|
# Enables serde for exposed types.
|
||||||
enable-serde = ["serde"]
|
enable-serde = ["serde"]
|
||||||
|
|||||||
@@ -11,8 +11,6 @@ cargo-fuzz = true
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
regalloc2 = { path = "../", features = ["fuzzing"] }
|
regalloc2 = { path = "../", features = ["fuzzing"] }
|
||||||
libfuzzer-sys = "0.3"
|
|
||||||
arbitrary = { version = "^0.4.6", features = ["derive"] }
|
|
||||||
log = { version = "0.4.8", default-features = false }
|
log = { version = "0.4.8", default-features = false }
|
||||||
env_logger = "0.8.3"
|
env_logger = "0.8.3"
|
||||||
|
|
||||||
|
|||||||
@@ -4,15 +4,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#![no_main]
|
#![no_main]
|
||||||
use libfuzzer_sys::arbitrary::{Arbitrary, Result, Unstructured};
|
use regalloc2::fuzzing::arbitrary::{Arbitrary, Result, Unstructured};
|
||||||
use libfuzzer_sys::fuzz_target;
|
use regalloc2::fuzzing::{domtree, fuzz_target, postorder};
|
||||||
|
use regalloc2::Block;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use regalloc2::{
|
|
||||||
fuzzing::{domtree, postorder},
|
|
||||||
Block,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct CFG {
|
struct CFG {
|
||||||
num_blocks: usize,
|
num_blocks: usize,
|
||||||
@@ -20,7 +16,7 @@ struct CFG {
|
|||||||
succs: Vec<Vec<Block>>,
|
succs: Vec<Vec<Block>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Arbitrary for CFG {
|
impl Arbitrary<'_> for CFG {
|
||||||
fn arbitrary(u: &mut Unstructured) -> Result<CFG> {
|
fn arbitrary(u: &mut Unstructured) -> Result<CFG> {
|
||||||
let num_blocks = u.int_in_range(1..=1000)?;
|
let num_blocks = u.int_in_range(1..=1000)?;
|
||||||
let mut succs = vec![];
|
let mut succs = vec![];
|
||||||
@@ -111,7 +107,7 @@ struct TestCase {
|
|||||||
path: Path,
|
path: Path,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Arbitrary for TestCase {
|
impl Arbitrary<'_> for TestCase {
|
||||||
fn arbitrary(u: &mut Unstructured) -> Result<TestCase> {
|
fn arbitrary(u: &mut Unstructured) -> Result<TestCase> {
|
||||||
let cfg = CFG::arbitrary(u)?;
|
let cfg = CFG::arbitrary(u)?;
|
||||||
let path = Path::choose_from_cfg(&cfg, u)?;
|
let path = Path::choose_from_cfg(&cfg, u)?;
|
||||||
|
|||||||
@@ -4,9 +4,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#![no_main]
|
#![no_main]
|
||||||
use libfuzzer_sys::fuzz_target;
|
|
||||||
|
|
||||||
use regalloc2::fuzzing::func::Func;
|
use regalloc2::fuzzing::func::Func;
|
||||||
|
use regalloc2::fuzzing::fuzz_target;
|
||||||
|
|
||||||
fuzz_target!(|func: Func| {
|
fuzz_target!(|func: Func| {
|
||||||
let _ = env_logger::try_init();
|
let _ = env_logger::try_init();
|
||||||
|
|||||||
@@ -4,18 +4,17 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#![no_main]
|
#![no_main]
|
||||||
use libfuzzer_sys::arbitrary::{Arbitrary, Result, Unstructured};
|
use regalloc2::fuzzing::arbitrary::{Arbitrary, Result, Unstructured};
|
||||||
use libfuzzer_sys::fuzz_target;
|
|
||||||
|
|
||||||
use regalloc2::fuzzing::checker::Checker;
|
use regalloc2::fuzzing::checker::Checker;
|
||||||
use regalloc2::fuzzing::func::{Func, Options};
|
use regalloc2::fuzzing::func::{Func, Options};
|
||||||
|
use regalloc2::fuzzing::fuzz_target;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct TestCase {
|
struct TestCase {
|
||||||
func: Func,
|
func: Func,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Arbitrary for TestCase {
|
impl Arbitrary<'_> for TestCase {
|
||||||
fn arbitrary(u: &mut Unstructured) -> Result<TestCase> {
|
fn arbitrary(u: &mut Unstructured) -> Result<TestCase> {
|
||||||
Ok(TestCase {
|
Ok(TestCase {
|
||||||
func: Func::arbitrary_with_options(
|
func: Func::arbitrary_with_options(
|
||||||
|
|||||||
@@ -4,9 +4,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#![no_main]
|
#![no_main]
|
||||||
use libfuzzer_sys::arbitrary::{Arbitrary, Result, Unstructured};
|
use regalloc2::fuzzing::arbitrary::{Arbitrary, Result, Unstructured};
|
||||||
use libfuzzer_sys::fuzz_target;
|
use regalloc2::fuzzing::fuzz_target;
|
||||||
|
|
||||||
use regalloc2::fuzzing::moves::{MoveAndScratchResolver, ParallelMoves};
|
use regalloc2::fuzzing::moves::{MoveAndScratchResolver, ParallelMoves};
|
||||||
use regalloc2::{Allocation, PReg, RegClass, SpillSlot};
|
use regalloc2::{Allocation, PReg, RegClass, SpillSlot};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
@@ -17,7 +16,7 @@ struct TestCase {
|
|||||||
available_pregs: Vec<Allocation>,
|
available_pregs: Vec<Allocation>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Arbitrary for TestCase {
|
impl Arbitrary<'_> for TestCase {
|
||||||
fn arbitrary(u: &mut Unstructured) -> Result<Self> {
|
fn arbitrary(u: &mut Unstructured) -> Result<Self> {
|
||||||
let mut ret = TestCase {
|
let mut ret = TestCase {
|
||||||
moves: vec![],
|
moves: vec![],
|
||||||
|
|||||||
@@ -4,11 +4,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#![no_main]
|
#![no_main]
|
||||||
use libfuzzer_sys::arbitrary::{Arbitrary, Result, Unstructured};
|
use regalloc2::fuzzing::arbitrary::{Arbitrary, Result, Unstructured};
|
||||||
use libfuzzer_sys::fuzz_target;
|
|
||||||
|
|
||||||
use regalloc2::fuzzing::cfg::CFGInfo;
|
use regalloc2::fuzzing::cfg::CFGInfo;
|
||||||
use regalloc2::fuzzing::func::{Func, Options};
|
use regalloc2::fuzzing::func::{Func, Options};
|
||||||
|
use regalloc2::fuzzing::fuzz_target;
|
||||||
use regalloc2::fuzzing::ssa::validate_ssa;
|
use regalloc2::fuzzing::ssa::validate_ssa;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -16,7 +15,7 @@ struct TestCase {
|
|||||||
f: Func,
|
f: Func,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Arbitrary for TestCase {
|
impl Arbitrary<'_> for TestCase {
|
||||||
fn arbitrary(u: &mut Unstructured) -> Result<Self> {
|
fn arbitrary(u: &mut Unstructured) -> Result<Self> {
|
||||||
Ok(TestCase {
|
Ok(TestCase {
|
||||||
f: Func::arbitrary_with_options(
|
f: Func::arbitrary_with_options(
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ use crate::{
|
|||||||
OperandConstraint, OperandKind, OperandPos, PReg, PRegSet, RegClass, VReg,
|
OperandConstraint, OperandKind, OperandPos, PReg, PRegSet, RegClass, VReg,
|
||||||
};
|
};
|
||||||
|
|
||||||
use arbitrary::Result as ArbitraryResult;
|
use super::arbitrary::Result as ArbitraryResult;
|
||||||
use arbitrary::{Arbitrary, Unstructured};
|
use super::arbitrary::{Arbitrary, Unstructured};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub enum InstOpcode {
|
pub enum InstOpcode {
|
||||||
@@ -235,7 +235,7 @@ impl FuncBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Arbitrary for OperandConstraint {
|
impl Arbitrary<'_> for OperandConstraint {
|
||||||
fn arbitrary(u: &mut Unstructured) -> ArbitraryResult<Self> {
|
fn arbitrary(u: &mut Unstructured) -> ArbitraryResult<Self> {
|
||||||
Ok(*u.choose(&[OperandConstraint::Any, OperandConstraint::Reg])?)
|
Ok(*u.choose(&[OperandConstraint::Any, OperandConstraint::Reg])?)
|
||||||
}
|
}
|
||||||
@@ -293,7 +293,7 @@ impl std::default::Default for Options {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Arbitrary for Func {
|
impl Arbitrary<'_> for Func {
|
||||||
fn arbitrary(u: &mut Unstructured) -> ArbitraryResult<Func> {
|
fn arbitrary(u: &mut Unstructured) -> ArbitraryResult<Func> {
|
||||||
Func::arbitrary_with_options(u, &Options::default())
|
Func::arbitrary_with_options(u, &Options::default())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,3 +28,5 @@ pub mod ion {
|
|||||||
pub mod checker {
|
pub mod checker {
|
||||||
pub use crate::checker::*;
|
pub use crate::checker::*;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub use libfuzzer_sys::{arbitrary, fuzz_target};
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "regalloc2-test"
|
|
||||||
version = "0.0.1"
|
|
||||||
authors = ["Chris Fallin <chris@cfallin.org>", "Mozilla SpiderMonkey Developers"]
|
|
||||||
edition = "2018"
|
|
||||||
license = "Apache-2.0 WITH LLVM-exception AND MPL-2.0"
|
|
||||||
description = "small test driver for benchmarking regalloc2"
|
|
||||||
repository = "https://github.com/bytecodealliance/regalloc2"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
regalloc2 = { version = "*", path = "../", features = ["fuzzing"] }
|
|
||||||
|
|
||||||
# Keep this in sync with libfuzzer_sys's crate version:
|
|
||||||
arbitrary = { version = "^0.4.6" }
|
|
||||||
rand = { version = "0.8" }
|
|
||||||
rand_chacha = { version = "0.3" }
|
|
||||||
env_logger = { version = "*" }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
criterion = "0.3"
|
|
||||||
|
|
||||||
[profile.release]
|
|
||||||
debug = true
|
|
||||||
|
|
||||||
[[bench]]
|
|
||||||
name = "regalloc"
|
|
||||||
harness = false
|
|
||||||
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
//! Criterion-based benchmark target that computes insts/second for
|
|
||||||
//! arbitrary inputs.
|
|
||||||
|
|
||||||
use arbitrary::{Arbitrary, Unstructured};
|
|
||||||
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
|
|
||||||
use rand::{Rng, SeedableRng};
|
|
||||||
use rand_chacha::ChaCha8Rng;
|
|
||||||
use regalloc2::fuzzing::func::{machine_env, Func};
|
|
||||||
use regalloc2::ion;
|
|
||||||
use regalloc2::Function;
|
|
||||||
|
|
||||||
fn create_random_func(seed: u64, size: usize) -> Func {
|
|
||||||
let mut bytes: Vec<u8> = vec![];
|
|
||||||
bytes.resize(size, 0);
|
|
||||||
let mut rng = ChaCha8Rng::seed_from_u64(seed);
|
|
||||||
rng.fill(&mut bytes[..]);
|
|
||||||
loop {
|
|
||||||
let mut u = Unstructured::new(&bytes[..]);
|
|
||||||
match Func::arbitrary(&mut u) {
|
|
||||||
Ok(f) => {
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
Err(arbitrary::Error::NotEnoughData) => {
|
|
||||||
let len = bytes.len();
|
|
||||||
bytes.resize(len + 1024, 0);
|
|
||||||
rng.fill(&mut bytes[len..]);
|
|
||||||
}
|
|
||||||
Err(e) => panic!("unexpected error: {:?}", e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run_regalloc(c: &mut Criterion) {
|
|
||||||
const SIZE: usize = 1000 * 1000;
|
|
||||||
env_logger::init();
|
|
||||||
let env = machine_env();
|
|
||||||
let mut group = c.benchmark_group("benches");
|
|
||||||
for iter in 0..3 {
|
|
||||||
let func = create_random_func(iter, SIZE);
|
|
||||||
eprintln!("==== {} instructions", func.insts());
|
|
||||||
group.throughput(Throughput::Elements(func.insts() as u64));
|
|
||||||
group.bench_with_input(BenchmarkId::from_parameter(iter), &iter, |b, _| {
|
|
||||||
b.iter(|| {
|
|
||||||
// For fair comparison with regalloc.rs, which needs
|
|
||||||
// to clone its Func on every alloc, we clone
|
|
||||||
// too. Seems to make a few percent difference.
|
|
||||||
let func = func.clone();
|
|
||||||
ion::run(&func, &env).expect("regalloc did not succeed");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
group.finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
criterion_group!(benches, run_regalloc);
|
|
||||||
criterion_main!(benches);
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* Released under the terms of the Apache 2.0 license with LLVM
|
|
||||||
* exception. See `LICENSE` for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
use arbitrary::{Arbitrary, Unstructured};
|
|
||||||
use rand::{Rng, SeedableRng};
|
|
||||||
use rand_chacha::ChaCha8Rng;
|
|
||||||
use regalloc2::fuzzing::func::{machine_env, Func};
|
|
||||||
use regalloc2::ion;
|
|
||||||
use regalloc2::Function;
|
|
||||||
|
|
||||||
fn create_random_func(seed: u64, size: usize) -> Func {
|
|
||||||
let mut bytes: Vec<u8> = vec![];
|
|
||||||
bytes.resize(size, 0);
|
|
||||||
let mut rng = ChaCha8Rng::seed_from_u64(seed);
|
|
||||||
rng.fill(&mut bytes[..]);
|
|
||||||
loop {
|
|
||||||
let mut u = Unstructured::new(&bytes[..]);
|
|
||||||
match Func::arbitrary(&mut u) {
|
|
||||||
Ok(f) => {
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
Err(arbitrary::Error::NotEnoughData) => {
|
|
||||||
let len = bytes.len();
|
|
||||||
bytes.resize(len + 1024, 0);
|
|
||||||
rng.fill(&mut bytes[len..]);
|
|
||||||
}
|
|
||||||
Err(e) => panic!("unexpected error: {:?}", e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
const SIZE: usize = 1000 * 1000;
|
|
||||||
env_logger::init();
|
|
||||||
let env = machine_env();
|
|
||||||
for iter in 0..3 {
|
|
||||||
let func = create_random_func(iter, SIZE);
|
|
||||||
eprintln!("==== {} instructions", func.insts());
|
|
||||||
let mut stats: ion::Stats = ion::Stats::default();
|
|
||||||
for i in 0..1000 {
|
|
||||||
let out = ion::run(&func, &env).expect("regalloc did not succeed");
|
|
||||||
if i == 0 {
|
|
||||||
stats = out.stats;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
eprintln!("Stats: {:?}", stats);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user