Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various fixes & minor improvements #16

Merged
merged 4 commits into from
Nov 16, 2021
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
37 changes: 17 additions & 20 deletions src/checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@

use crate::{
Allocation, AllocationKind, Block, Edit, Function, Inst, InstPosition, Operand,
OperandConstraint, OperandKind, OperandPos, Output, PReg, ProgPoint, SpillSlot, VReg,
OperandConstraint, OperandKind, OperandPos, Output, PReg, ProgPoint, RegClass, VReg,
};

use std::collections::{HashMap, HashSet, VecDeque};
Expand Down Expand Up @@ -143,11 +143,11 @@ pub enum CheckerError {
},
ConflictedValueInStackmap {
inst: Inst,
slot: SpillSlot,
alloc: Allocation,
},
NonRefValueInStackmap {
inst: Inst,
slot: SpillSlot,
alloc: Allocation,
vreg: VReg,
},
}
Expand Down Expand Up @@ -332,9 +332,8 @@ impl CheckerState {
self.check_val(inst, *op, *alloc, val, allocs)?;
}
}
&CheckerInst::Safepoint { inst, ref slots } => {
for &slot in slots {
let alloc = Allocation::stack(slot);
&CheckerInst::Safepoint { inst, ref allocs } => {
for &alloc in allocs {
let val = self
.allocations
.get(&alloc)
Expand All @@ -343,17 +342,17 @@ impl CheckerState {
log::trace!(
"checker: checkinst {:?}: safepoint slot {}, checker value {:?}",
checkinst,
slot,
alloc,
val
);

match val {
CheckerValue::Unknown => {}
CheckerValue::Conflicted => {
return Err(CheckerError::ConflictedValueInStackmap { inst, slot });
return Err(CheckerError::ConflictedValueInStackmap { inst, alloc });
}
CheckerValue::Reg(vreg, false) => {
return Err(CheckerError::NonRefValueInStackmap { inst, slot, vreg });
return Err(CheckerError::NonRefValueInStackmap { inst, alloc, vreg });
}
CheckerValue::Reg(_, true) => {}
}
Expand Down Expand Up @@ -405,12 +404,10 @@ impl CheckerState {
self.allocations
.insert(alloc, CheckerValue::Reg(vreg, reftyped));
}
&CheckerInst::Safepoint { ref slots, .. } => {
&CheckerInst::Safepoint { ref allocs, .. } => {
for (alloc, value) in &mut self.allocations {
if let CheckerValue::Reg(_, true) = *value {
if alloc.is_reg() {
*value = CheckerValue::Conflicted;
} else if alloc.is_stack() && !slots.contains(&alloc.as_stack().unwrap()) {
if !allocs.contains(&alloc) {
*value = CheckerValue::Conflicted;
}
}
Expand Down Expand Up @@ -483,9 +480,9 @@ pub(crate) enum CheckerInst {
/// of a value is logically transferred to a new vreg.
DefAlloc { alloc: Allocation, vreg: VReg },

/// A safepoint, with the given SpillSlots specified as containing
/// A safepoint, with the given Allocations specified as containing
/// reftyped values. All other reftyped values become invalid.
Safepoint { inst: Inst, slots: Vec<SpillSlot> },
Safepoint { inst: Inst, allocs: Vec<Allocation> },
}

#[derive(Debug)]
Expand Down Expand Up @@ -529,7 +526,7 @@ impl<'a, F: Function> Checker<'a, F> {
pub fn prepare(&mut self, out: &Output) {
log::trace!("checker: out = {:?}", out);
// Preprocess safepoint stack-maps into per-inst vecs.
let mut safepoint_slots: HashMap<Inst, Vec<SpillSlot>> = HashMap::new();
let mut safepoint_slots: HashMap<Inst, Vec<Allocation>> = HashMap::new();
for &(progpoint, slot) in &out.safepoint_slots {
safepoint_slots
.entry(progpoint.inst())
Expand All @@ -551,9 +548,9 @@ impl<'a, F: Function> Checker<'a, F> {

// If this is a safepoint, then check the spillslots at this point.
if self.f.requires_refs_on_stack(inst) {
let slots = safepoint_slots.remove(&inst).unwrap_or_else(|| vec![]);
let allocs = safepoint_slots.remove(&inst).unwrap_or_else(|| vec![]);

let checkinst = CheckerInst::Safepoint { inst, slots };
let checkinst = CheckerInst::Safepoint { inst, allocs };
self.bb_insts.get_mut(&block).unwrap().push(checkinst);
}

Expand Down Expand Up @@ -727,9 +724,9 @@ impl<'a, F: Function> Checker<'a, F> {
&CheckerInst::DefAlloc { alloc, vreg } => {
log::trace!(" defalloc: {}:{}", vreg, alloc);
}
&CheckerInst::Safepoint { ref slots, .. } => {
&CheckerInst::Safepoint { ref allocs, .. } => {
let mut slotargs = vec![];
for &slot in slots {
for &slot in allocs {
slotargs.push(format!("{}", slot));
}
log::trace!(" safepoint: {}", slotargs.join(", "));
Expand Down
1 change: 0 additions & 1 deletion src/fuzzing/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,6 @@ pub fn machine_env() -> MachineEnv {
[regs.iter().cloned().skip(24).collect(), vec![]];
let scratch_by_class: [PReg; 2] = [PReg::new(31, RegClass::Int), PReg::new(0, RegClass::Float)];
MachineEnv {
regs,
preferred_regs_by_class,
non_preferred_regs_by_class,
scratch_by_class,
Expand Down
5 changes: 2 additions & 3 deletions src/ion/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::index::ContainerComparator;
use crate::indexset::IndexSet;
use crate::{
define_index, Allocation, Block, Edit, Function, Inst, MachineEnv, Operand, PReg, ProgPoint,
RegClass, SpillSlot, VReg,
RegClass, VReg,
};
use smallvec::SmallVec;
use std::cmp::Ordering;
Expand Down Expand Up @@ -293,7 +293,6 @@ pub struct Env<'a, F: Function> {
pub vreg_regs: Vec<VReg>,
pub pregs: Vec<PRegData>,
pub allocation_queue: PrioQueue,
pub clobbers: Vec<Inst>, // Sorted list of insts with clobbers.
pub safepoints: Vec<Inst>, // Sorted list of safepoint insts.
pub safepoints_per_vreg: HashMap<usize, HashSet<Inst>>,

Expand Down Expand Up @@ -337,7 +336,7 @@ pub struct Env<'a, F: Function> {
pub allocs: Vec<Allocation>,
pub inst_alloc_offsets: Vec<u32>,
pub num_spillslots: u32,
pub safepoint_slots: Vec<(ProgPoint, SpillSlot)>,
pub safepoint_slots: Vec<(ProgPoint, Allocation)>,

pub allocated_bundle_count: usize,

Expand Down
12 changes: 5 additions & 7 deletions src/ion/liveranges.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,11 @@ impl<'a, F: Function> Env<'a, F> {
allocations: LiveRangeSet::new(),
},
);
for &preg in &self.env.regs {
self.pregs[preg.index()].reg = preg;
for i in 0..=PReg::MAX {
let preg_int = PReg::new(i, RegClass::Int);
self.pregs[preg_int.index()].reg = preg_int;
let preg_float = PReg::new(i, RegClass::Float);
self.pregs[preg_float.index()].reg = preg_float;
}
// Create VRegs from the vreg count.
for idx in 0..self.func.num_vregs() {
Expand Down Expand Up @@ -445,10 +448,6 @@ impl<'a, F: Function> Env<'a, F> {
// For each instruction, in reverse order, process
// operands and clobbers.
for inst in insns.rev().iter() {
if self.func.inst_clobbers(inst).len() > 0 {
self.clobbers.push(inst);
}

// Mark clobbers with CodeRanges on PRegs.
for i in 0..self.func.inst_clobbers(inst).len() {
// don't borrow `self`
Expand Down Expand Up @@ -1231,7 +1230,6 @@ impl<'a, F: Function> Env<'a, F> {
}
}

self.clobbers.sort_unstable();
self.blockparam_ins.sort_unstable();
self.blockparam_outs.sort_unstable();
self.prog_move_srcs.sort_unstable_by_key(|(pos, _)| *pos);
Expand Down
1 change: 0 additions & 1 deletion src/ion/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ impl<'a, F: Function> Env<'a, F> {
vreg_regs: Vec::with_capacity(n),
pregs: vec![],
allocation_queue: PrioQueue::new(),
clobbers: vec![],
safepoints: vec![],
safepoints_per_vreg: HashMap::new(),
spilled_bundles: vec![],
Expand Down
6 changes: 2 additions & 4 deletions src/ion/stackmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,8 @@ impl<'a, F: Function> Env<'a, F> {
}
log::trace!(" -> covers safepoint {:?}", safepoints[safepoint_idx]);

let slot = alloc
.as_stack()
.expect("Reference-typed value not in spillslot at safepoint");
self.safepoint_slots.push((safepoints[safepoint_idx], slot));
self.safepoint_slots
.push((safepoints[safepoint_idx], alloc));
safepoint_idx += 1;
}
}
Expand Down
17 changes: 7 additions & 10 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,13 @@ impl PReg {
/// all PRegs and index it efficiently.
#[inline(always)]
pub fn index(self) -> usize {
((self.class as u8 as usize) << 5) | (self.hw_enc as usize)
((self.class as u8 as usize) << Self::MAX_BITS) | (self.hw_enc as usize)
}

/// Construct a PReg from the value returned from `.index()`.
#[inline(always)]
pub fn from_index(index: usize) -> Self {
let class = (index >> 5) & 1;
let class = (index >> Self::MAX_BITS) & 1;
let class = match class {
0 => RegClass::Int,
1 => RegClass::Float,
Expand Down Expand Up @@ -1139,12 +1139,6 @@ pub enum Edit {
/// as well.
#[derive(Clone, Debug)]
pub struct MachineEnv {
/// Physical registers. Every register that might be mentioned in
/// any constraint must be listed here, even if it is not
/// allocatable (present in one of
/// `{preferred,non_preferred}_regs_by_class`).
pub regs: Vec<PReg>,

/// Preferred physical registers for each class. These are the
/// registers that will be allocated first, if free.
pub preferred_regs_by_class: [Vec<PReg>; 2],
Expand Down Expand Up @@ -1186,8 +1180,11 @@ pub struct Output {
/// Allocation offset in `allocs` for each instruction.
pub inst_alloc_offsets: Vec<u32>,

/// Safepoint records: at a given program point, a reference-typed value lives in the given SpillSlot.
pub safepoint_slots: Vec<(ProgPoint, SpillSlot)>,
/// Safepoint records: at a given program point, a reference-typed value
/// lives in the given Allocation. Currently these are guaranteed to be
/// stack slots, but in the future an option may be added to allow
/// reftype value to be kept in registers at safepoints.
pub safepoint_slots: Vec<(ProgPoint, Allocation)>,

/// Debug info: a labeled value (as applied to vregs by
/// `Function::debug_value_labels()` on the input side) is located
Expand Down