Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions doc/ION.md
Original file line number Diff line number Diff line change
Expand Up @@ -442,11 +442,14 @@ other):

```plain

Any(rc)
/ \
FixedReg(reg) FixedStack(reg)
\ /
Conflict
___Unknown_____
| | |
| | |
| ____Any(rc) |
|/ | |
Stack(rc) FixedReg(reg)
\ /
Conflict
```

Once we have the Requirement for a bundle, we can decide what to do.
Expand Down
11 changes: 11 additions & 0 deletions src/checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,17 @@ impl CheckerState {
}
return Err(CheckerError::AllocationIsNotReg { inst, op, alloc });
}
OperandConstraint::Stack => {
if alloc.kind() != AllocationKind::Stack {
// Accept pregs that represent a fixed stack slot.
if let Some(preg) = alloc.as_reg() {
if checker.machine_env.fixed_stack_slots.contains(&preg) {
return Ok(());
}
}
return Err(CheckerError::AllocationIsNotStack { inst, op, alloc });
}
}
OperandConstraint::FixedReg(preg) => {
if alloc != Allocation::reg(preg) {
return Err(CheckerError::AllocationIsNotFixedReg { inst, op, alloc });
Expand Down
8 changes: 8 additions & 0 deletions src/fastalloc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,10 @@ impl<'a, F: Function> Env<'a, F> {
OperandConstraint::Reuse(_) => {
unreachable!()
}

OperandConstraint::Stack => {
panic!("Stack constraints not supported in fastalloc");
}
}
}

Expand Down Expand Up @@ -576,6 +580,10 @@ impl<'a, F: Function> Env<'a, F> {
// This is handled elsewhere.
unreachable!();
}

OperandConstraint::Stack => {
panic!("Stack operand constraints not supported in fastalloc");
}
};
self.allocs[(inst.index(), op_idx)] = new_alloc;
Ok(new_alloc)
Expand Down
16 changes: 14 additions & 2 deletions src/ion/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ pub struct LiveBundle {
pub spill_weight_and_props: u32,
}

pub const BUNDLE_MAX_SPILL_WEIGHT: u32 = (1 << 29) - 1;
pub const BUNDLE_MAX_SPILL_WEIGHT: u32 = (1 << 28) - 1;
pub const MINIMAL_FIXED_BUNDLE_SPILL_WEIGHT: u32 = BUNDLE_MAX_SPILL_WEIGHT;
pub const MINIMAL_BUNDLE_SPILL_WEIGHT: u32 = BUNDLE_MAX_SPILL_WEIGHT - 1;
pub const BUNDLE_MAX_NORMAL_SPILL_WEIGHT: u32 = BUNDLE_MAX_SPILL_WEIGHT - 2;
Expand All @@ -218,12 +218,14 @@ impl LiveBundle {
minimal: bool,
fixed: bool,
fixed_def: bool,
stack: bool,
) {
debug_assert!(spill_weight <= BUNDLE_MAX_SPILL_WEIGHT);
self.spill_weight_and_props = spill_weight
| (if minimal { 1 << 31 } else { 0 })
| (if fixed { 1 << 30 } else { 0 })
| (if fixed_def { 1 << 29 } else { 0 });
| (if fixed_def { 1 << 29 } else { 0 })
| (if stack { 1 << 28 } else { 0 });
}

#[inline(always)]
Expand All @@ -241,6 +243,11 @@ impl LiveBundle {
self.spill_weight_and_props & (1 << 29) != 0
}

#[inline(always)]
pub fn cached_stack(&self) -> bool {
self.spill_weight_and_props & (1 << 28) != 0
}

#[inline(always)]
pub fn set_cached_fixed(&mut self) {
self.spill_weight_and_props |= 1 << 30;
Expand All @@ -251,6 +258,11 @@ impl LiveBundle {
self.spill_weight_and_props |= 1 << 29;
}

#[inline(always)]
pub fn set_cached_stack(&mut self) {
self.spill_weight_and_props |= 1 << 28;
}

#[inline(always)]
pub fn cached_spill_weight(&self) -> u32 {
self.spill_weight_and_props & BUNDLE_MAX_SPILL_WEIGHT
Expand Down
4 changes: 4 additions & 0 deletions src/ion/liveranges.rs
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,10 @@ impl<'a, F: Function> Env<'a, F> {
first_reg_slot.get_or_insert(u.slot);
}
}
// Maybe this could be supported in this future...
OperandConstraint::Stack => panic!(
"multiple uses of vreg with a Stack constraint are not supported"
),
}
}

Expand Down
21 changes: 19 additions & 2 deletions src/ion/merge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,11 @@ impl<'a, F: Function> Env<'a, F> {
}

// Check for a requirements conflict.
if self.bundles[from].cached_fixed() || self.bundles[to].cached_fixed() {
if self.bundles[from].cached_stack()
|| self.bundles[from].cached_fixed()
|| self.bundles[to].cached_stack()
|| self.bundles[to].cached_fixed()
{
if self.merge_bundle_requirements(from, to).is_err() {
trace!(" -> conflicting requirements; aborting merge");
return false;
Expand Down Expand Up @@ -154,6 +158,9 @@ impl<'a, F: Function> Env<'a, F> {
}
self.bundles[to].ranges = list;

if self.bundles[from].cached_stack() {
self.bundles[to].set_cached_stack();
}
if self.bundles[from].cached_fixed() {
self.bundles[to].set_cached_fixed();
}
Expand Down Expand Up @@ -236,6 +243,9 @@ impl<'a, F: Function> Env<'a, F> {
*to_range = to_range.join(from_range);
}

if self.bundles[from].cached_stack() {
self.bundles[to].set_cached_stack();
}
if self.bundles[from].cached_fixed() {
self.bundles[to].set_cached_fixed();
}
Expand Down Expand Up @@ -272,6 +282,7 @@ impl<'a, F: Function> Env<'a, F> {

let mut fixed = false;
let mut fixed_def = false;
let mut stack = false;
for entry in &self.bundles[bundle].ranges {
for u in &self.ranges[entry.index].uses {
if let OperandConstraint::FixedReg(_) = u.operand.constraint() {
Expand All @@ -280,7 +291,10 @@ impl<'a, F: Function> Env<'a, F> {
fixed_def = true;
}
}
if fixed && fixed_def {
if let OperandConstraint::Stack = u.operand.constraint() {
stack = true;
}
if fixed && stack && fixed_def {
break;
}
}
Expand All @@ -291,6 +305,9 @@ impl<'a, F: Function> Env<'a, F> {
if fixed_def {
self.bundles[bundle].set_cached_fixed_def();
}
if stack {
self.bundles[bundle].set_cached_stack();
}

// Create a spillslot for this bundle.
let reg = self.vreg(vreg);
Expand Down
16 changes: 15 additions & 1 deletion src/ion/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ impl<'a, F: Function> Env<'a, F> {
let minimal;
let mut fixed = false;
let mut fixed_def = false;
let mut stack = false;
let bundledata = &self.ctx.bundles[bundle];
let num_ranges = bundledata.ranges.len();
let first_range = bundledata.ranges[0].index;
Expand All @@ -288,7 +289,12 @@ impl<'a, F: Function> Env<'a, F> {
trace!(" -> is fixed def");
fixed_def = true;
}

}
if let OperandConstraint::Stack = u.operand.constraint() {
trace!(" -> stack operand at {:?}: {:?}", u.pos, u.operand);
stack = true;
}
if stack && fixed {
break;
}
}
Expand Down Expand Up @@ -351,6 +357,7 @@ impl<'a, F: Function> Env<'a, F> {
minimal,
fixed,
fixed_def,
stack,
);
}

Expand Down Expand Up @@ -1036,6 +1043,13 @@ impl<'a, F: Function> Env<'a, F> {
let fixed_preg = match req {
Requirement::FixedReg(preg) | Requirement::FixedStack(preg) => Some(preg),
Requirement::Register => None,
Requirement::Stack => {
// If we must be on the stack, mark our spillset
// as required immediately.
let spillset = self.bundles[bundle].spillset;
self.spillsets[spillset].required = true;
return Ok(());
}

Requirement::Any => {
self.ctx.spilled_bundles.push(bundle);
Expand Down
11 changes: 9 additions & 2 deletions src/ion/requirement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ pub enum Requirement {
FixedReg(PReg),
FixedStack(PReg),
Register,
Stack,
Any,
}
impl Requirement {
Expand All @@ -69,10 +70,15 @@ impl Requirement {
match (self, other) {
(other, Requirement::Any) | (Requirement::Any, other) => Ok(other),
(Requirement::Register, Requirement::Register) => Ok(self),
(Requirement::Stack, Requirement::Stack) => Ok(self),
(Requirement::Register, Requirement::FixedReg(preg))
| (Requirement::FixedReg(preg), Requirement::Register) => {
Ok(Requirement::FixedReg(preg))
}
(Requirement::Stack, Requirement::FixedStack(preg))
| (Requirement::FixedStack(preg), Requirement::Stack) => {
Ok(Requirement::FixedStack(preg))
}
(Requirement::FixedReg(a), Requirement::FixedReg(b)) if a == b => Ok(self),
(Requirement::FixedStack(a), Requirement::FixedStack(b)) if a == b => Ok(self),
_ => Err(RequirementConflict),
Expand All @@ -82,7 +88,7 @@ impl Requirement {
#[inline(always)]
pub fn is_stack(self) -> bool {
match self {
Requirement::FixedStack(..) => true,
Requirement::Stack | Requirement::FixedStack(..) => true,
Requirement::Register | Requirement::FixedReg(..) => false,
Requirement::Any => false,
}
Expand All @@ -92,7 +98,7 @@ impl Requirement {
pub fn is_reg(self) -> bool {
match self {
Requirement::Register | Requirement::FixedReg(..) => true,
Requirement::FixedStack(..) => false,
Requirement::Stack | Requirement::FixedStack(..) => false,
Requirement::Any => false,
}
}
Expand All @@ -110,6 +116,7 @@ impl<'a, F: Function> Env<'a, F> {
}
}
OperandConstraint::Reg | OperandConstraint::Reuse(_) => Requirement::Register,
OperandConstraint::Stack => Requirement::Stack,
OperandConstraint::Any => Requirement::Any,
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,8 @@ pub enum OperandConstraint {
Any,
/// Operand must be in a register. Register is read-only for Uses.
Reg,
/// Operand must be on the stack.
Stack,
/// Operand must be in a fixed register.
FixedReg(PReg),
/// On defs only: reuse a use's register.
Expand All @@ -539,6 +541,7 @@ impl core::fmt::Display for OperandConstraint {
match self {
Self::Any => write!(f, "any"),
Self::Reg => write!(f, "reg"),
Self::Stack => write!(f, "stack"),
Self::FixedReg(preg) => write!(f, "fixed({})", preg),
Self::Reuse(idx) => write!(f, "reuse({})", idx),
}
Expand Down Expand Up @@ -634,6 +637,7 @@ impl Operand {
let constraint_field = match constraint {
OperandConstraint::Any => 0,
OperandConstraint::Reg => 1,
OperandConstraint::Stack => 2,
OperandConstraint::FixedReg(preg) => {
debug_assert_eq!(preg.class(), vreg.class());
0b1000000 | preg.hw_enc() as u32
Expand Down Expand Up @@ -906,6 +910,7 @@ impl Operand {
match constraint_field {
0 => OperandConstraint::Any,
1 => OperandConstraint::Reg,
2 => OperandConstraint::Stack,
_ => unreachable!(),
}
}
Expand Down