Merge pull request #16 from Amanieu/misc
Various fixes & minor improvements
This commit is contained in:
@@ -78,7 +78,7 @@
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Allocation, AllocationKind, Block, Edit, Function, Inst, InstPosition, Operand,
|
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};
|
use std::collections::{HashMap, HashSet, VecDeque};
|
||||||
@@ -143,11 +143,11 @@ pub enum CheckerError {
|
|||||||
},
|
},
|
||||||
ConflictedValueInStackmap {
|
ConflictedValueInStackmap {
|
||||||
inst: Inst,
|
inst: Inst,
|
||||||
slot: SpillSlot,
|
alloc: Allocation,
|
||||||
},
|
},
|
||||||
NonRefValueInStackmap {
|
NonRefValueInStackmap {
|
||||||
inst: Inst,
|
inst: Inst,
|
||||||
slot: SpillSlot,
|
alloc: Allocation,
|
||||||
vreg: VReg,
|
vreg: VReg,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -332,9 +332,8 @@ impl CheckerState {
|
|||||||
self.check_val(inst, *op, *alloc, val, allocs)?;
|
self.check_val(inst, *op, *alloc, val, allocs)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&CheckerInst::Safepoint { inst, ref slots } => {
|
&CheckerInst::Safepoint { inst, ref allocs } => {
|
||||||
for &slot in slots {
|
for &alloc in allocs {
|
||||||
let alloc = Allocation::stack(slot);
|
|
||||||
let val = self
|
let val = self
|
||||||
.allocations
|
.allocations
|
||||||
.get(&alloc)
|
.get(&alloc)
|
||||||
@@ -343,17 +342,17 @@ impl CheckerState {
|
|||||||
log::trace!(
|
log::trace!(
|
||||||
"checker: checkinst {:?}: safepoint slot {}, checker value {:?}",
|
"checker: checkinst {:?}: safepoint slot {}, checker value {:?}",
|
||||||
checkinst,
|
checkinst,
|
||||||
slot,
|
alloc,
|
||||||
val
|
val
|
||||||
);
|
);
|
||||||
|
|
||||||
match val {
|
match val {
|
||||||
CheckerValue::Unknown => {}
|
CheckerValue::Unknown => {}
|
||||||
CheckerValue::Conflicted => {
|
CheckerValue::Conflicted => {
|
||||||
return Err(CheckerError::ConflictedValueInStackmap { inst, slot });
|
return Err(CheckerError::ConflictedValueInStackmap { inst, alloc });
|
||||||
}
|
}
|
||||||
CheckerValue::Reg(vreg, false) => {
|
CheckerValue::Reg(vreg, false) => {
|
||||||
return Err(CheckerError::NonRefValueInStackmap { inst, slot, vreg });
|
return Err(CheckerError::NonRefValueInStackmap { inst, alloc, vreg });
|
||||||
}
|
}
|
||||||
CheckerValue::Reg(_, true) => {}
|
CheckerValue::Reg(_, true) => {}
|
||||||
}
|
}
|
||||||
@@ -405,12 +404,10 @@ impl CheckerState {
|
|||||||
self.allocations
|
self.allocations
|
||||||
.insert(alloc, CheckerValue::Reg(vreg, reftyped));
|
.insert(alloc, CheckerValue::Reg(vreg, reftyped));
|
||||||
}
|
}
|
||||||
&CheckerInst::Safepoint { ref slots, .. } => {
|
&CheckerInst::Safepoint { ref allocs, .. } => {
|
||||||
for (alloc, value) in &mut self.allocations {
|
for (alloc, value) in &mut self.allocations {
|
||||||
if let CheckerValue::Reg(_, true) = *value {
|
if let CheckerValue::Reg(_, true) = *value {
|
||||||
if alloc.is_reg() {
|
if !allocs.contains(&alloc) {
|
||||||
*value = CheckerValue::Conflicted;
|
|
||||||
} else if alloc.is_stack() && !slots.contains(&alloc.as_stack().unwrap()) {
|
|
||||||
*value = CheckerValue::Conflicted;
|
*value = CheckerValue::Conflicted;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -483,9 +480,9 @@ pub(crate) enum CheckerInst {
|
|||||||
/// of a value is logically transferred to a new vreg.
|
/// of a value is logically transferred to a new vreg.
|
||||||
DefAlloc { alloc: Allocation, vreg: 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.
|
/// reftyped values. All other reftyped values become invalid.
|
||||||
Safepoint { inst: Inst, slots: Vec<SpillSlot> },
|
Safepoint { inst: Inst, allocs: Vec<Allocation> },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -529,7 +526,7 @@ impl<'a, F: Function> Checker<'a, F> {
|
|||||||
pub fn prepare(&mut self, out: &Output) {
|
pub fn prepare(&mut self, out: &Output) {
|
||||||
log::trace!("checker: out = {:?}", out);
|
log::trace!("checker: out = {:?}", out);
|
||||||
// Preprocess safepoint stack-maps into per-inst vecs.
|
// 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 {
|
for &(progpoint, slot) in &out.safepoint_slots {
|
||||||
safepoint_slots
|
safepoint_slots
|
||||||
.entry(progpoint.inst())
|
.entry(progpoint.inst())
|
||||||
@@ -551,9 +548,9 @@ impl<'a, F: Function> Checker<'a, F> {
|
|||||||
|
|
||||||
// If this is a safepoint, then check the spillslots at this point.
|
// If this is a safepoint, then check the spillslots at this point.
|
||||||
if self.f.requires_refs_on_stack(inst) {
|
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);
|
self.bb_insts.get_mut(&block).unwrap().push(checkinst);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -727,9 +724,9 @@ impl<'a, F: Function> Checker<'a, F> {
|
|||||||
&CheckerInst::DefAlloc { alloc, vreg } => {
|
&CheckerInst::DefAlloc { alloc, vreg } => {
|
||||||
log::trace!(" defalloc: {}:{}", vreg, alloc);
|
log::trace!(" defalloc: {}:{}", vreg, alloc);
|
||||||
}
|
}
|
||||||
&CheckerInst::Safepoint { ref slots, .. } => {
|
&CheckerInst::Safepoint { ref allocs, .. } => {
|
||||||
let mut slotargs = vec![];
|
let mut slotargs = vec![];
|
||||||
for &slot in slots {
|
for &slot in allocs {
|
||||||
slotargs.push(format!("{}", slot));
|
slotargs.push(format!("{}", slot));
|
||||||
}
|
}
|
||||||
log::trace!(" safepoint: {}", slotargs.join(", "));
|
log::trace!(" safepoint: {}", slotargs.join(", "));
|
||||||
|
|||||||
@@ -589,7 +589,6 @@ pub fn machine_env() -> MachineEnv {
|
|||||||
[regs.iter().cloned().skip(24).collect(), vec![]];
|
[regs.iter().cloned().skip(24).collect(), vec![]];
|
||||||
let scratch_by_class: [PReg; 2] = [PReg::new(31, RegClass::Int), PReg::new(0, RegClass::Float)];
|
let scratch_by_class: [PReg; 2] = [PReg::new(31, RegClass::Int), PReg::new(0, RegClass::Float)];
|
||||||
MachineEnv {
|
MachineEnv {
|
||||||
regs,
|
|
||||||
preferred_regs_by_class,
|
preferred_regs_by_class,
|
||||||
non_preferred_regs_by_class,
|
non_preferred_regs_by_class,
|
||||||
scratch_by_class,
|
scratch_by_class,
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ use crate::index::ContainerComparator;
|
|||||||
use crate::indexset::IndexSet;
|
use crate::indexset::IndexSet;
|
||||||
use crate::{
|
use crate::{
|
||||||
define_index, Allocation, Block, Edit, Function, Inst, MachineEnv, Operand, PReg, ProgPoint,
|
define_index, Allocation, Block, Edit, Function, Inst, MachineEnv, Operand, PReg, ProgPoint,
|
||||||
RegClass, SpillSlot, VReg,
|
RegClass, VReg,
|
||||||
};
|
};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
@@ -293,7 +293,6 @@ pub struct Env<'a, F: Function> {
|
|||||||
pub vreg_regs: Vec<VReg>,
|
pub vreg_regs: Vec<VReg>,
|
||||||
pub pregs: Vec<PRegData>,
|
pub pregs: Vec<PRegData>,
|
||||||
pub allocation_queue: PrioQueue,
|
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: Vec<Inst>, // Sorted list of safepoint insts.
|
||||||
pub safepoints_per_vreg: HashMap<usize, HashSet<Inst>>,
|
pub safepoints_per_vreg: HashMap<usize, HashSet<Inst>>,
|
||||||
|
|
||||||
@@ -337,7 +336,7 @@ pub struct Env<'a, F: Function> {
|
|||||||
pub allocs: Vec<Allocation>,
|
pub allocs: Vec<Allocation>,
|
||||||
pub inst_alloc_offsets: Vec<u32>,
|
pub inst_alloc_offsets: Vec<u32>,
|
||||||
pub num_spillslots: u32,
|
pub num_spillslots: u32,
|
||||||
pub safepoint_slots: Vec<(ProgPoint, SpillSlot)>,
|
pub safepoint_slots: Vec<(ProgPoint, Allocation)>,
|
||||||
|
|
||||||
pub allocated_bundle_count: usize,
|
pub allocated_bundle_count: usize,
|
||||||
|
|
||||||
|
|||||||
@@ -105,8 +105,11 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
allocations: LiveRangeSet::new(),
|
allocations: LiveRangeSet::new(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
for &preg in &self.env.regs {
|
for i in 0..=PReg::MAX {
|
||||||
self.pregs[preg.index()].reg = preg;
|
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.
|
// Create VRegs from the vreg count.
|
||||||
for idx in 0..self.func.num_vregs() {
|
for idx in 0..self.func.num_vregs() {
|
||||||
@@ -445,10 +448,6 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
// For each instruction, in reverse order, process
|
// For each instruction, in reverse order, process
|
||||||
// operands and clobbers.
|
// operands and clobbers.
|
||||||
for inst in insns.rev().iter() {
|
for inst in insns.rev().iter() {
|
||||||
if self.func.inst_clobbers(inst).len() > 0 {
|
|
||||||
self.clobbers.push(inst);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark clobbers with CodeRanges on PRegs.
|
// Mark clobbers with CodeRanges on PRegs.
|
||||||
for i in 0..self.func.inst_clobbers(inst).len() {
|
for i in 0..self.func.inst_clobbers(inst).len() {
|
||||||
// don't borrow `self`
|
// don't borrow `self`
|
||||||
@@ -1231,7 +1230,6 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.clobbers.sort_unstable();
|
|
||||||
self.blockparam_ins.sort_unstable();
|
self.blockparam_ins.sort_unstable();
|
||||||
self.blockparam_outs.sort_unstable();
|
self.blockparam_outs.sort_unstable();
|
||||||
self.prog_move_srcs.sort_unstable_by_key(|(pos, _)| *pos);
|
self.prog_move_srcs.sort_unstable_by_key(|(pos, _)| *pos);
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
vreg_regs: Vec::with_capacity(n),
|
vreg_regs: Vec::with_capacity(n),
|
||||||
pregs: vec![],
|
pregs: vec![],
|
||||||
allocation_queue: PrioQueue::new(),
|
allocation_queue: PrioQueue::new(),
|
||||||
clobbers: vec![],
|
|
||||||
safepoints: vec![],
|
safepoints: vec![],
|
||||||
safepoints_per_vreg: HashMap::new(),
|
safepoints_per_vreg: HashMap::new(),
|
||||||
spilled_bundles: vec![],
|
spilled_bundles: vec![],
|
||||||
|
|||||||
@@ -58,10 +58,8 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
}
|
}
|
||||||
log::trace!(" -> covers safepoint {:?}", safepoints[safepoint_idx]);
|
log::trace!(" -> covers safepoint {:?}", safepoints[safepoint_idx]);
|
||||||
|
|
||||||
let slot = alloc
|
self.safepoint_slots
|
||||||
.as_stack()
|
.push((safepoints[safepoint_idx], alloc));
|
||||||
.expect("Reference-typed value not in spillslot at safepoint");
|
|
||||||
self.safepoint_slots.push((safepoints[safepoint_idx], slot));
|
|
||||||
safepoint_idx += 1;
|
safepoint_idx += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
17
src/lib.rs
17
src/lib.rs
@@ -108,13 +108,13 @@ impl PReg {
|
|||||||
/// all PRegs and index it efficiently.
|
/// all PRegs and index it efficiently.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn index(self) -> usize {
|
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()`.
|
/// Construct a PReg from the value returned from `.index()`.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn from_index(index: usize) -> Self {
|
pub fn from_index(index: usize) -> Self {
|
||||||
let class = (index >> 5) & 1;
|
let class = (index >> Self::MAX_BITS) & 1;
|
||||||
let class = match class {
|
let class = match class {
|
||||||
0 => RegClass::Int,
|
0 => RegClass::Int,
|
||||||
1 => RegClass::Float,
|
1 => RegClass::Float,
|
||||||
@@ -1139,12 +1139,6 @@ pub enum Edit {
|
|||||||
/// as well.
|
/// as well.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct MachineEnv {
|
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
|
/// Preferred physical registers for each class. These are the
|
||||||
/// registers that will be allocated first, if free.
|
/// registers that will be allocated first, if free.
|
||||||
pub preferred_regs_by_class: [Vec<PReg>; 2],
|
pub preferred_regs_by_class: [Vec<PReg>; 2],
|
||||||
@@ -1186,8 +1180,11 @@ pub struct Output {
|
|||||||
/// Allocation offset in `allocs` for each instruction.
|
/// Allocation offset in `allocs` for each instruction.
|
||||||
pub inst_alloc_offsets: Vec<u32>,
|
pub inst_alloc_offsets: Vec<u32>,
|
||||||
|
|
||||||
/// Safepoint records: at a given program point, a reference-typed value lives in the given SpillSlot.
|
/// Safepoint records: at a given program point, a reference-typed value
|
||||||
pub safepoint_slots: Vec<(ProgPoint, SpillSlot)>,
|
/// 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
|
/// Debug info: a labeled value (as applied to vregs by
|
||||||
/// `Function::debug_value_labels()` on the input side) is located
|
/// `Function::debug_value_labels()` on the input side) is located
|
||||||
|
|||||||
Reference in New Issue
Block a user