Skip to content

Commit

Permalink
simplified handling of reuse operands
Browse files Browse the repository at this point in the history
  • Loading branch information
d-sonuga committed Aug 9, 2024
1 parent 51b4b32 commit 376b45c
Show file tree
Hide file tree
Showing 2 changed files with 177 additions and 691 deletions.
258 changes: 53 additions & 205 deletions src/fastalloc/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ impl<'a> Operands<'a> {
)
}

pub fn fixed(&self) -> impl Iterator<Item = (usize, Operand)> + 'a {
self.matches(|op| matches!(op.constraint(), OperandConstraint::FixedReg(_)))
}

pub fn fixed_early(&self) -> impl Iterator<Item = (usize, Operand)> + 'a {
self.matches(|op|
matches!(op.constraint(), OperandConstraint::FixedReg(_))
Expand All @@ -70,6 +74,13 @@ impl<'a> Operands<'a> {
)
}

pub fn non_fixed_def(&self) -> impl Iterator<Item = (usize, Operand)> + 'a {
self.matches(|op|
!matches!(op.constraint(), OperandConstraint::FixedReg(_))
&& op.kind() == OperandKind::Def
)
}

pub fn non_fixed_non_reuse_late_use(&self) -> impl Iterator<Item = (usize, Operand)> + 'a {
self.matches(|op|
!matches!(op.constraint(),
Expand All @@ -91,231 +102,68 @@ impl<'a> Operands<'a> {
&& op.kind() == OperandKind::Def
)
}
}

#[cfg(test)]
mod tests {
use alloc::vec::Vec;
use alloc::vec;
use crate::{PReg, RegClass};
use super::*;

// Using a new function because Operand::new isn't a const function
const fn operand(vreg_no: u32, constraint: OperandConstraint, kind: OperandKind, pos: OperandPos) -> Operand {
let constraint_field = match constraint {
OperandConstraint::Any => 0,
OperandConstraint::Reg => 1,
OperandConstraint::Stack => 2,
OperandConstraint::FixedReg(preg) => {
0b1000000 | preg.hw_enc() as u32
}
OperandConstraint::Reuse(which) => {
0b0100000 | which as u32
}
};
let class_field = RegClass::Int as u8 as u32;
let pos_field = pos as u8 as u32;
let kind_field = kind as u8 as u32;
Operand {
bits: vreg_no
| (class_field << 21)
| (pos_field << 23)
| (kind_field << 24)
| (constraint_field << 25),
}
}

const fn late_reuse_def_operand(vreg_no: u32) -> Operand {
operand(vreg_no, OperandConstraint::Reuse(0), OperandKind::Def, OperandPos::Late)
}

const fn early_reuse_def_operand(vreg_no: u32) -> Operand {
operand(vreg_no, OperandConstraint::Reuse(0), OperandKind::Def, OperandPos::Early)
}

const fn early_reuse_use_operand(vreg_no: u32) -> Operand {
operand(vreg_no, OperandConstraint::Reuse(0), OperandKind::Use, OperandPos::Early)
}

const fn late_reuse_use_operand(vreg_no: u32) -> Operand {
operand(vreg_no, OperandConstraint::Reuse(0), OperandKind::Use, OperandPos::Late)
}

const fn late_def_operand(vreg_no: u32) -> Operand {
operand(vreg_no, OperandConstraint::Any, OperandKind::Def, OperandPos::Late)
}

const fn late_use_operand(vreg_no: u32) -> Operand {
operand(vreg_no, OperandConstraint::Any, OperandKind::Use, OperandPos::Late)
}

const fn early_use_operand(vreg_no: u32) -> Operand {
operand(vreg_no, OperandConstraint::Any, OperandKind::Use, OperandPos::Early)
}

const fn early_def_operand(vreg_no: u32) -> Operand {
operand(vreg_no, OperandConstraint::Any, OperandKind::Def, OperandPos::Early)
}

const fn fixed_late_def_operand(vreg_no: u32) -> Operand {
operand(
vreg_no,
OperandConstraint::FixedReg(PReg::new(1, RegClass::Int)),
OperandKind::Def,
OperandPos::Late,
pub fn non_fixed_late_use(&self) -> impl Iterator<Item = (usize, Operand)> + 'a {
self.matches(|op| !matches!(op.constraint(), OperandConstraint::FixedReg(_))
&& op.pos() == OperandPos::Late
&& op.kind() == OperandKind::Use
)
}

const fn fixed_early_def_operand(vreg_no: u32) -> Operand {
operand(
vreg_no,
OperandConstraint::FixedReg(PReg::new(1, RegClass::Int)),
OperandKind::Def,
OperandPos::Early,
pub fn non_fixed_late_def(&self) -> impl Iterator<Item = (usize, Operand)> + 'a {
self.matches(|op| !matches!(op.constraint(), OperandConstraint::FixedReg(_))
&& op.pos() == OperandPos::Late
&& op.kind() == OperandKind::Def
)
}


const fn fixed_late_use_operand(vreg_no: u32) -> Operand {
operand(
vreg_no,
OperandConstraint::FixedReg(PReg::new(1, RegClass::Int)),
OperandKind::Use,
OperandPos::Late,
pub fn non_fixed_early_use(&self) -> impl Iterator<Item = (usize, Operand)> + 'a {
self.matches(|op| !matches!(op.constraint(), OperandConstraint::FixedReg(_))
&& op.pos() == OperandPos::Early
&& op.kind() == OperandKind::Use
)
}

const fn fixed_early_use_operand(vreg_no: u32) -> Operand {
operand(
vreg_no,
OperandConstraint::FixedReg(PReg::new(1, RegClass::Int)),
OperandKind::Use,
OperandPos::Early,
pub fn non_fixed_early_def(&self) -> impl Iterator<Item = (usize, Operand)> + 'a {
self.matches(|op| !matches!(op.constraint(), OperandConstraint::FixedReg(_))
&& op.pos() == OperandPos::Early
&& op.kind() == OperandKind::Def
)
}

static OPERANDS: [Operand; 14] = [
late_reuse_def_operand(0),
late_def_operand(1),
early_reuse_def_operand(2),
early_use_operand(3),
early_def_operand(4),
late_reuse_def_operand(5),
late_use_operand(6),
late_reuse_use_operand(7),
early_def_operand(8),
early_use_operand(9),

fixed_late_def_operand(10),
fixed_early_def_operand(11),
fixed_late_use_operand(12),
fixed_early_use_operand(13),
];

#[test]
fn late() {
let late_operands: Vec<(usize, Operand)> = Operands::new(&OPERANDS).non_fixed_non_reuse_late()
.collect();
assert_eq!(late_operands, vec![
(1, late_def_operand(1)),
(6, late_use_operand(6)),
]);
}

#[test]
fn late_def() {
let late_def_operands: Vec<(usize, Operand)> = Operands::new(&OPERANDS).non_reuse_late_def()
.collect();
assert_eq!(late_def_operands, vec![
(1, late_def_operand(1)),
(10, fixed_late_def_operand(10)),
]);
}

#[test]
fn early() {
let early_operands: Vec<(usize, Operand)> = Operands::new(&OPERANDS).non_fixed_non_reuse_early()
.collect();
assert_eq!(early_operands, vec![
(3, early_use_operand(3)),
(4, early_def_operand(4)),
(8, early_def_operand(8)),
(9, early_use_operand(9)),
]);
}

#[test]
fn early_def() {
let early_def_operands: Vec<(usize, Operand)> = Operands::new(&OPERANDS).non_reuse_early_def()
.collect();
assert_eq!(early_def_operands, vec![
(4, early_def_operand(4)),
(8, early_def_operand(8)),
(11, fixed_early_def_operand(11)),
]);
}

#[test]
fn reuse() {
let reuse_operands: Vec<(usize, Operand)> = Operands::new(&OPERANDS).reuse()
.collect();
assert_eq!(reuse_operands, vec![
(0, late_reuse_def_operand(0)),
(2, early_reuse_def_operand(2)),
(5, late_reuse_def_operand(5)),
(7, late_reuse_use_operand(7)),
]);
pub fn late_def(&self) -> impl Iterator<Item = (usize, Operand)> + 'a {
self.matches(|op|
op.pos() == OperandPos::Late
&& op.kind() == OperandKind::Def
)
}

#[test]
fn fixed_late() {
let fixed_late_operands: Vec<(usize, Operand)> = Operands::new(&OPERANDS).fixed_late()
.collect();
assert_eq!(fixed_late_operands, vec![
(10, fixed_late_def_operand(10)),
(12, fixed_late_use_operand(12)),
]);
pub fn early_def(&self) -> impl Iterator<Item = (usize, Operand)> + 'a {
self.matches(|op|
op.pos() == OperandPos::Early
&& op.kind() == OperandKind::Def
)
}

#[test]
fn fixed_early() {
let fixed_early_operands: Vec<(usize, Operand)> = Operands::new(&OPERANDS).fixed_early()
.collect();
assert_eq!(fixed_early_operands, vec![
(11, fixed_early_def_operand(11)),
(13, fixed_early_use_operand(13)),
]);

pub fn fixed_early_use(&self) -> impl Iterator<Item = (usize, Operand)> + 'a {
self.matches(|op| matches!(op.constraint(), OperandConstraint::FixedReg(_))
&& op.pos() == OperandPos::Early
&& op.kind() == OperandKind::Use
)
}

#[test]
fn def() {
let def_operands: Vec<(usize, Operand)> = Operands::new(&OPERANDS).non_reuse_def()
.collect();
assert_eq!(def_operands, vec![
(1, late_def_operand(1)),
(4, early_def_operand(4)),
(8, early_def_operand(8)),
(10, fixed_late_def_operand(10)),
(11, fixed_early_def_operand(11)),
]);
pub fn fixed_late_def(&self) -> impl Iterator<Item = (usize, Operand)> + 'a {
self.matches(|op| matches!(op.constraint(), OperandConstraint::FixedReg(_))
&& op.pos() == OperandPos::Late
&& op.kind() == OperandKind::Def
)
}
}

impl<'a> core::ops::Index<usize> for Operands<'a> {
type Output = Operand;

#[test]
fn non_fixed_non_reuse_late_def() {
let def_operands: Vec<(usize, Operand)> = Operands::new(&OPERANDS).non_fixed_non_reuse_late_def()
.collect();
assert_eq!(def_operands, vec![
(1, late_def_operand(1)),
]);
}

#[test]
fn non_fixed_non_reuse_late_use() {
let late_operands: Vec<(usize, Operand)> = Operands::new(&OPERANDS).non_fixed_non_reuse_late_use()
.collect();
assert_eq!(late_operands, vec![
(6, late_use_operand(6)),
]);
fn index(&self, index: usize) -> &Self::Output {
&self.0[index]
}
}
Loading

0 comments on commit 376b45c

Please sign in to comment.