fix stackmaps
This commit is contained in:
@@ -9,14 +9,16 @@ use crate::{
|
|||||||
OperandKind, OperandPos, Output, PReg, PRegSet, ProgPoint, RegAllocError, RegClass, SpillSlot,
|
OperandKind, OperandPos, Output, PReg, PRegSet, ProgPoint, RegAllocError, RegClass, SpillSlot,
|
||||||
VReg,
|
VReg,
|
||||||
};
|
};
|
||||||
use crate::{postorder, InstPosition};
|
use crate::{domtree, postorder, InstPosition};
|
||||||
|
|
||||||
|
use super::data_structures::u64_key;
|
||||||
use super::Stats;
|
use super::Stats;
|
||||||
|
|
||||||
#[derive(Default, Clone, Copy)]
|
#[derive(Default, Clone, Copy)]
|
||||||
struct VRegData {
|
struct VRegData {
|
||||||
pub preg: Option<PReg>,
|
pub preg: Option<PReg>,
|
||||||
pub slot_idx: Option<u32>,
|
pub slot_idx: Option<u32>,
|
||||||
|
pub def_block: Option<Block>,
|
||||||
pub reftype: bool,
|
pub reftype: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,6 +36,7 @@ struct BlockData {
|
|||||||
|
|
||||||
struct ReadOnlyData {
|
struct ReadOnlyData {
|
||||||
pub postorder: Vec<Block>,
|
pub postorder: Vec<Block>,
|
||||||
|
pub idom: Vec<Block>,
|
||||||
pub reg_order_int: Vec<PReg>,
|
pub reg_order_int: Vec<PReg>,
|
||||||
pub reg_order_float: Vec<PReg>,
|
pub reg_order_float: Vec<PReg>,
|
||||||
}
|
}
|
||||||
@@ -60,12 +63,22 @@ impl ReadOnlyData {
|
|||||||
reg_order
|
reg_order
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let postorder = postorder::calculate(func.num_blocks(), func.entry_block(), |b| {
|
||||||
|
func.block_succs(b)
|
||||||
|
});
|
||||||
|
|
||||||
|
let idom = domtree::calculate(
|
||||||
|
func.num_blocks(),
|
||||||
|
|b| func.block_preds(b),
|
||||||
|
&postorder,
|
||||||
|
func.entry_block(),
|
||||||
|
);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
reg_order_int,
|
reg_order_int,
|
||||||
reg_order_float,
|
reg_order_float,
|
||||||
postorder: postorder::calculate(func.num_blocks(), func.entry_block(), |b| {
|
postorder,
|
||||||
func.block_succs(b)
|
idom,
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,14 +415,26 @@ pub fn run<F: Function>(func: &F, mach_env: &MachineEnv) -> Result<Output, RegAl
|
|||||||
// we do not iterate the blocks in their index order so the order of edits might not be sorted by progpoint
|
// we do not iterate the blocks in their index order so the order of edits might not be sorted by progpoint
|
||||||
// however it should be nearly sorted
|
// however it should be nearly sorted
|
||||||
state.edits.sort_by_key(|entry| entry.0);
|
state.edits.sort_by_key(|entry| entry.0);
|
||||||
|
// these might also not be sorted
|
||||||
|
//state.safepoint_slots.sort_by_key(|entry| entry.0);
|
||||||
|
state
|
||||||
|
.safepoint_slots
|
||||||
|
.sort_unstable_by_key(|(progpoint, slot)| u64_key(progpoint.to_index(), slot.bits()));
|
||||||
|
|
||||||
trace!("Edits:");
|
if trace_enabled!() {
|
||||||
for edit in &state.edits {
|
trace!("Edits:");
|
||||||
match edit.1 {
|
for edit in &state.edits {
|
||||||
Edit::Move { from, to } => {
|
match edit.1 {
|
||||||
trace!("At {:?} from {} to {}", edit.0, from, to);
|
Edit::Move { from, to } => {
|
||||||
|
trace!("At {:?} from {} to {}", edit.0, from, to);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trace!("StackMaps:");
|
||||||
|
for entry in &state.safepoint_slots {
|
||||||
|
trace!("At {:?} at {}", entry.0, entry.1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Output {
|
Ok(Output {
|
||||||
@@ -469,14 +494,19 @@ fn allocate_block_insts<'a, F: Function>(
|
|||||||
if req_refs_on_stack {
|
if req_refs_on_stack {
|
||||||
state.clear_reftype_vregs();
|
state.clear_reftype_vregs();
|
||||||
let pos = ProgPoint::before(inst);
|
let pos = ProgPoint::before(inst);
|
||||||
|
trace!("Calculating Stackmap for {:?}", pos);
|
||||||
|
|
||||||
for vreg in state.reftype_vregs {
|
for vreg in state.reftype_vregs {
|
||||||
let data = &state.vregs[vreg.vreg()];
|
let data = &state.vregs[vreg.vreg()];
|
||||||
if let Some(slot) = data.slot_idx {
|
if let Some(slot) = data.slot_idx {
|
||||||
trace!("Marking vreg {} as saved on stack at {}", vreg, slot);
|
if domtree::dominates(&const_state.idom, data.def_block.unwrap(), block) {
|
||||||
state
|
trace!("Marking vreg {} as saved on stack at {}", vreg, slot);
|
||||||
.safepoint_slots
|
state
|
||||||
.push((pos, Allocation::stack(SpillSlot::new(slot as usize))));
|
.safepoint_slots
|
||||||
|
.push((pos, Allocation::stack(SpillSlot::new(slot as usize))));
|
||||||
|
} else {
|
||||||
|
trace!("Skipping {} as it does not dominate", vreg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -560,6 +590,7 @@ fn allocate_block_insts<'a, F: Function>(
|
|||||||
late_write_disallow_regs.add(reg);
|
late_write_disallow_regs.add(reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state.vregs[vreg.vreg()].def_block = Some(block);
|
||||||
state.allocs[alloc_idx + i] = Allocation::reg(reg);
|
state.allocs[alloc_idx + i] = Allocation::reg(reg);
|
||||||
state.assign_preg(reg, vreg);
|
state.assign_preg(reg, vreg);
|
||||||
|
|
||||||
@@ -634,6 +665,7 @@ fn allocate_block_insts<'a, F: Function>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
OperandKind::Def => {
|
OperandKind::Def => {
|
||||||
|
state.vregs[vreg.vreg()].def_block = Some(block);
|
||||||
let slot = state.alloc_stack_slot(vreg);
|
let slot = state.alloc_stack_slot(vreg);
|
||||||
state.allocs[alloc_idx + i] =
|
state.allocs[alloc_idx + i] =
|
||||||
Allocation::stack(SpillSlot::new(slot as usize));
|
Allocation::stack(SpillSlot::new(slot as usize));
|
||||||
@@ -684,6 +716,7 @@ fn allocate_block_insts<'a, F: Function>(
|
|||||||
state.move_to_preg(vreg, reg, ProgPoint::before(inst));
|
state.move_to_preg(vreg, reg, ProgPoint::before(inst));
|
||||||
} else {
|
} else {
|
||||||
// early def
|
// early def
|
||||||
|
state.vregs[vreg.vreg()].def_block = Some(block);
|
||||||
state.assign_preg(reg, vreg);
|
state.assign_preg(reg, vreg);
|
||||||
state.alloc_stack_slot(vreg);
|
state.alloc_stack_slot(vreg);
|
||||||
state.move_to_stack(reg, vreg, ProgPoint::after(inst));
|
state.move_to_stack(reg, vreg, ProgPoint::after(inst));
|
||||||
@@ -724,6 +757,8 @@ fn allocate_block_insts<'a, F: Function>(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state.vregs[vreg.vreg()].def_block = Some(block);
|
||||||
|
|
||||||
match op.constraint() {
|
match op.constraint() {
|
||||||
OperandConstraint::Reg => {
|
OperandConstraint::Reg => {
|
||||||
// find first non-allocated register
|
// find first non-allocated register
|
||||||
@@ -874,6 +909,13 @@ fn handle_out_block_params<'a, F: Function>(
|
|||||||
let out_slot = state.vregs[out_vreg.vreg()].slot_idx.unwrap();
|
let out_slot = state.vregs[out_vreg.vreg()].slot_idx.unwrap();
|
||||||
let in_slot = state.vregs[in_vreg.vreg()].slot_idx.unwrap();
|
let in_slot = state.vregs[in_vreg.vreg()].slot_idx.unwrap();
|
||||||
|
|
||||||
|
trace!(
|
||||||
|
"Move {} from slot {} to slot {} for {}",
|
||||||
|
out_vreg,
|
||||||
|
out_slot,
|
||||||
|
in_slot,
|
||||||
|
in_vreg
|
||||||
|
);
|
||||||
state.edits.push((
|
state.edits.push((
|
||||||
ProgPoint::before(last_inst),
|
ProgPoint::before(last_inst),
|
||||||
Edit::Move {
|
Edit::Move {
|
||||||
@@ -915,6 +957,8 @@ fn handle_out_block_params<'a, F: Function>(
|
|||||||
debug_assert!(state.vregs[out_vreg.vreg()].slot_idx.is_some());
|
debug_assert!(state.vregs[out_vreg.vreg()].slot_idx.is_some());
|
||||||
let out_slot_idx = state.vregs[out_vreg.vreg()].slot_idx.unwrap();
|
let out_slot_idx = state.vregs[out_vreg.vreg()].slot_idx.unwrap();
|
||||||
|
|
||||||
|
state.vregs[in_vreg.vreg()].def_block = Some(succ);
|
||||||
|
|
||||||
// TODO: if out_vreg dies at this edge, we could reuse its stack slot
|
// TODO: if out_vreg dies at this edge, we could reuse its stack slot
|
||||||
// TODO: we should also be able to reuse the slot if the successor only has one predecessor (us); check with AE
|
// TODO: we should also be able to reuse the slot if the successor only has one predecessor (us); check with AE
|
||||||
let mut no_alias = false;
|
let mut no_alias = false;
|
||||||
@@ -947,6 +991,13 @@ fn handle_out_block_params<'a, F: Function>(
|
|||||||
tmp_reg_float
|
tmp_reg_float
|
||||||
};
|
};
|
||||||
let slot = state.create_stack_slot(out_vreg.class());
|
let slot = state.create_stack_slot(out_vreg.class());
|
||||||
|
trace!(
|
||||||
|
"Moving {} from slot {} to slot {} for {}",
|
||||||
|
out_vreg,
|
||||||
|
out_slot_idx,
|
||||||
|
slot,
|
||||||
|
in_vreg
|
||||||
|
);
|
||||||
state.edits.push((
|
state.edits.push((
|
||||||
ProgPoint::before(last_inst),
|
ProgPoint::before(last_inst),
|
||||||
Edit::Move {
|
Edit::Move {
|
||||||
|
|||||||
Reference in New Issue
Block a user