Skip to content

Commit e684ee5

Browse files
authored
Fastalloc1 (#181)
This is the initial implementation of the fast register allocator in `src/fastalloc`.
1 parent 86303b0 commit e684ee5

File tree

10 files changed

+2309
-4
lines changed

10 files changed

+2309
-4
lines changed

fuzz/Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ path = "fuzz_targets/ion_checker.rs"
4949
test = false
5050
doc = false
5151

52+
[[bin]]
53+
name = "fastalloc_checker"
54+
path = "fuzz_targets/fastalloc_checker.rs"
55+
test = false
56+
doc = false
57+
5258
# Enable debug assertions and overflow checks when fuzzing
5359
[profile.release]
5460
debug = true
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Released under the terms of the Apache 2.0 license with LLVM
3+
* exception. See `LICENSE` for details.
4+
*/
5+
6+
#![no_main]
7+
use regalloc2::fuzzing::arbitrary::{Arbitrary, Result, Unstructured};
8+
use regalloc2::fuzzing::checker::Checker;
9+
use regalloc2::fuzzing::func::{Func, Options};
10+
use regalloc2::fuzzing::fuzz_target;
11+
12+
#[derive(Clone, Debug)]
13+
struct TestCase {
14+
func: Func,
15+
}
16+
17+
impl Arbitrary<'_> for TestCase {
18+
fn arbitrary(u: &mut Unstructured) -> Result<TestCase> {
19+
Ok(TestCase {
20+
func: Func::arbitrary_with_options(
21+
u,
22+
&Options {
23+
reused_inputs: true,
24+
fixed_regs: true,
25+
fixed_nonallocatable: true,
26+
clobbers: true,
27+
reftypes: false,
28+
},
29+
)?,
30+
})
31+
}
32+
}
33+
34+
fuzz_target!(|testcase: TestCase| {
35+
let func = testcase.func;
36+
let _ = env_logger::try_init();
37+
log::trace!("func:\n{:?}", func);
38+
let env = regalloc2::fuzzing::func::machine_env();
39+
let out =
40+
regalloc2::fuzzing::fastalloc::run(&func, &env, true, false).expect("regalloc did not succeed");
41+
42+
let mut checker = Checker::new(&func, &env);
43+
checker.prepare(&out);
44+
checker.run().expect("checker failed");
45+
});

regalloc2-tool/src/main.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use std::path::PathBuf;
22

33
use clap::Parser;
44
use regalloc2::{
5-
checker::Checker, serialize::SerializableFunction, Block, Edit, Function, InstOrEdit, Output,
6-
RegallocOptions,
5+
checker::Checker, serialize::SerializableFunction, Algorithm, Block, Edit, Function,
6+
InstOrEdit, Output, RegallocOptions,
77
};
88

99
#[derive(Parser)]
@@ -15,6 +15,24 @@ struct Args {
1515

1616
/// Input file containing a bincode-encoded SerializedFunction.
1717
input: PathBuf,
18+
19+
/// Which register allocation algorithm to use.
20+
algorithm: CliAlgorithm,
21+
}
22+
23+
#[derive(Clone, Copy, Debug, clap::ValueEnum)]
24+
enum CliAlgorithm {
25+
Ion,
26+
Fastalloc,
27+
}
28+
29+
impl From<CliAlgorithm> for Algorithm {
30+
fn from(cli_algo: CliAlgorithm) -> Algorithm {
31+
match cli_algo {
32+
CliAlgorithm::Ion => Algorithm::Ion,
33+
CliAlgorithm::Fastalloc => Algorithm::Fastalloc,
34+
}
35+
}
1836
}
1937

2038
fn main() {
@@ -32,6 +50,7 @@ fn main() {
3250
let options = RegallocOptions {
3351
verbose_log: true,
3452
validate_ssa: true,
53+
algorithm: args.algorithm.into(),
3554
};
3655
let output = match regalloc2::run(&function, function.machine_env(), &options) {
3756
Ok(output) => output,

src/fastalloc/iter.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
use crate::{Operand, OperandConstraint, OperandKind};
2+
3+
pub struct Operands<'a>(pub &'a [Operand]);
4+
5+
impl<'a> Operands<'a> {
6+
pub fn new(operands: &'a [Operand]) -> Self {
7+
Self(operands)
8+
}
9+
10+
pub fn matches<F: Fn(Operand) -> bool + 'a>(
11+
&self,
12+
predicate: F,
13+
) -> impl Iterator<Item = (usize, Operand)> + 'a {
14+
self.0
15+
.iter()
16+
.cloned()
17+
.enumerate()
18+
.filter(move |(_, op)| predicate(*op))
19+
}
20+
21+
pub fn def_ops(&self) -> impl Iterator<Item = (usize, Operand)> + 'a {
22+
self.matches(|op| op.kind() == OperandKind::Def)
23+
}
24+
25+
pub fn use_ops(&self) -> impl Iterator<Item = (usize, Operand)> + 'a {
26+
self.matches(|op| op.kind() == OperandKind::Use)
27+
}
28+
29+
pub fn reuse(&self) -> impl Iterator<Item = (usize, Operand)> + 'a {
30+
self.matches(|op| matches!(op.constraint(), OperandConstraint::Reuse(_)))
31+
}
32+
33+
pub fn fixed(&self) -> impl Iterator<Item = (usize, Operand)> + 'a {
34+
self.matches(|op| matches!(op.constraint(), OperandConstraint::FixedReg(_)))
35+
}
36+
}
37+
38+
impl<'a> core::ops::Index<usize> for Operands<'a> {
39+
type Output = Operand;
40+
41+
fn index(&self, index: usize) -> &Self::Output {
42+
&self.0[index]
43+
}
44+
}

0 commit comments

Comments
 (0)