more stuff in regs
This commit is contained in:
@@ -159,11 +159,11 @@ impl PRNG {
|
||||
}
|
||||
|
||||
fn val(&mut self) -> u64 {
|
||||
let e = self.a - PRNG::rot(self.b, 27);
|
||||
let e = self.a.wrapping_sub(PRNG::rot(self.b, 27));
|
||||
self.a = self.b ^ PRNG::rot(self.c, 17);
|
||||
self.b = self.c + self.d;
|
||||
self.c = self.d + e;
|
||||
self.d = e + self.a;
|
||||
self.b = self.c.wrapping_add(self.d);
|
||||
self.c = self.d.wrapping_add(e);
|
||||
self.d = e.wrapping_add(self.a);
|
||||
self.d
|
||||
}
|
||||
|
||||
@@ -463,15 +463,26 @@ impl<'a, F: Function> FastAllocState<'a, F> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear_reftype_vregs(&mut self) {
|
||||
pub fn clear_reftype_vregs(&mut self, cur_inst: Inst) {
|
||||
if self.reftype_vregs_in_pregs_count == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
for i in 0..self.pregs.len() {
|
||||
if let Some(vreg) = self.pregs[i].vreg.clone() {
|
||||
let vreg = vreg.vreg();
|
||||
if self.vregs[vreg].reftype {
|
||||
let vreg_idx = vreg.vreg();
|
||||
if self.vregs[vreg_idx].reftype {
|
||||
debug_assert_eq!(self.vregs[vreg_idx].preg.unwrap().index(), i);
|
||||
if self.vregs[vreg_idx].slot_idx.is_none() {
|
||||
// TODO: we unconditionally save a vreg even if it is killed, move that logic down later
|
||||
self.alloc_stack_slot(vreg);
|
||||
self.move_to_stack(
|
||||
self.vregs[vreg_idx].preg.unwrap(),
|
||||
vreg,
|
||||
ProgPoint::before(cur_inst),
|
||||
);
|
||||
}
|
||||
|
||||
self.clear_preg_idx(i);
|
||||
}
|
||||
}
|
||||
@@ -680,7 +691,7 @@ fn allocate_block_insts<'a, F: Function>(
|
||||
let mut late_write_regs = PRegSet::empty();
|
||||
|
||||
if req_refs_on_stack {
|
||||
state.clear_reftype_vregs();
|
||||
state.clear_reftype_vregs(inst);
|
||||
let pos = ProgPoint::before(inst);
|
||||
trace!("Calculating Stackmap for {:?}", pos);
|
||||
|
||||
@@ -994,8 +1005,8 @@ fn allocate_block_insts<'a, F: Function>(
|
||||
state.move_to_stack(tmp_reg, vreg, ProgPoint::after(inst));
|
||||
regs_allocated.add(tmp_reg);
|
||||
} else {
|
||||
state.alloc_stack_slot(vreg);
|
||||
state.move_to_stack(reg, vreg, ProgPoint::after(inst));
|
||||
//state.alloc_stack_slot(vreg);
|
||||
//state.move_to_stack(reg, vreg, ProgPoint::after(inst));
|
||||
regs_allocated.add(reg);
|
||||
}
|
||||
trace!("Chose {} for operand {}", reg, i);
|
||||
@@ -1011,7 +1022,19 @@ fn allocate_block_insts<'a, F: Function>(
|
||||
Allocation::stack(SpillSlot::new(*slot as usize));
|
||||
trace!("Chose slot {} for operand {}", slot, i);
|
||||
} else {
|
||||
return Err(RegAllocError::SSA(vreg, inst));
|
||||
let cur_preg = state.vregs[vreg.vreg()].preg.unwrap();
|
||||
if op.constraint() == OperandConstraint::Any {
|
||||
// TODO: have reg be a higher priority than stack?
|
||||
state.allocs[alloc_idx + i] = Allocation::reg(cur_preg);
|
||||
trace!("Chose {} for operand {}", cur_preg, i);
|
||||
} else {
|
||||
// move to stack
|
||||
let slot: u32 = state.alloc_stack_slot(vreg);
|
||||
state.move_to_stack(cur_preg, vreg, ProgPoint::before(inst));
|
||||
state.allocs[alloc_idx + i] =
|
||||
Allocation::stack(SpillSlot::new(slot as usize));
|
||||
trace!("Chose slot {} for operand {}", slot, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
OperandKind::Def => {
|
||||
@@ -1097,14 +1120,29 @@ fn allocate_block_insts<'a, F: Function>(
|
||||
return Err(RegAllocError::TooManyLiveRegs);
|
||||
}
|
||||
|
||||
// need to move from stack to reg
|
||||
state.move_to_preg(vreg, reg, ProgPoint::before(inst));
|
||||
if let Some(cur_preg) = state.vregs[vreg.vreg()].preg {
|
||||
// TODO: make sure this is not used in another use?
|
||||
state.clear_preg(cur_preg);
|
||||
state.edits.push((
|
||||
ProgPoint::before(inst),
|
||||
Edit::Move {
|
||||
from: Allocation::reg(cur_preg),
|
||||
to: Allocation::reg(reg),
|
||||
},
|
||||
));
|
||||
debug_assert!(state.pregs[reg.index()].vreg.is_none());
|
||||
state.pregs[reg.index()].vreg = Some(vreg);
|
||||
state.vregs[vreg.vreg()].preg = Some(reg);
|
||||
} else {
|
||||
// need to move from stack to reg
|
||||
state.move_to_preg(vreg, reg, ProgPoint::before(inst));
|
||||
}
|
||||
} else {
|
||||
// early def
|
||||
state.vregs[vreg.vreg()].def_block = Some(block);
|
||||
state.assign_preg(reg, vreg);
|
||||
state.alloc_stack_slot(vreg);
|
||||
state.move_to_stack(reg, vreg, ProgPoint::after(inst));
|
||||
//state.alloc_stack_slot(vreg);
|
||||
//state.move_to_stack(reg, vreg, ProgPoint::after(inst));
|
||||
}
|
||||
|
||||
allocated = true;
|
||||
@@ -1255,8 +1293,8 @@ fn allocate_block_insts<'a, F: Function>(
|
||||
// early def
|
||||
state.vregs[vreg.vreg()].def_block = Some(block);
|
||||
state.assign_preg(preg, vreg);
|
||||
state.alloc_stack_slot(vreg);
|
||||
state.move_to_stack(preg, vreg, ProgPoint::after(inst));
|
||||
//state.alloc_stack_slot(vreg);
|
||||
//state.move_to_stack(preg, vreg, ProgPoint::after(inst));
|
||||
}
|
||||
|
||||
trace!("Chose {} for operand {}", preg, i);
|
||||
@@ -1370,8 +1408,8 @@ fn allocate_block_insts<'a, F: Function>(
|
||||
|
||||
state.clear_preg(reg);
|
||||
state.assign_preg(reg, vreg);
|
||||
state.alloc_stack_slot(vreg);
|
||||
state.move_to_stack(reg, vreg, ProgPoint::after(inst));
|
||||
//state.alloc_stack_slot(vreg);
|
||||
//state.move_to_stack(reg, vreg, ProgPoint::after(inst));
|
||||
trace!("Chose {} for operand {}", reg, i);
|
||||
allocated = true;
|
||||
break;
|
||||
@@ -1446,8 +1484,8 @@ fn allocate_block_insts<'a, F: Function>(
|
||||
state.allocs[alloc_idx + i] = Allocation::reg(reg);
|
||||
|
||||
state.assign_preg(reg, vreg);
|
||||
state.alloc_stack_slot(vreg);
|
||||
state.move_to_stack(reg, vreg, ProgPoint::after(inst));
|
||||
//state.alloc_stack_slot(vreg);
|
||||
//state.move_to_stack(reg, vreg, ProgPoint::after(inst));
|
||||
trace!("Chose {} for operand {}", reg, i);
|
||||
} else {
|
||||
if ffa_reg_pool == PRegSet::empty() {
|
||||
@@ -1500,8 +1538,8 @@ fn allocate_block_insts<'a, F: Function>(
|
||||
// early def
|
||||
state.vregs[vreg.vreg()].def_block = Some(block);
|
||||
state.assign_preg(preg, vreg);
|
||||
state.alloc_stack_slot(vreg);
|
||||
state.move_to_stack(preg, vreg, ProgPoint::after(inst));
|
||||
//state.alloc_stack_slot(vreg);
|
||||
//state.move_to_stack(preg, vreg, ProgPoint::after(inst));
|
||||
}
|
||||
|
||||
trace!("Chose {} for operand {}", preg, i);
|
||||
@@ -1574,55 +1612,10 @@ fn allocate_block_insts<'a, F: Function>(
|
||||
state.cur_inst_pos += 1;
|
||||
}
|
||||
|
||||
// Move all liveout/block param vregs to a stack slot if they dont have one and clear pregs
|
||||
for i in 0..state.pregs.len() {
|
||||
match state.pregs[i].vreg {
|
||||
None => {}
|
||||
Some(vreg) => {
|
||||
trace!("Clearing {} from p{}", vreg, i);
|
||||
let idx = vreg.vreg();
|
||||
// TODO: obv dont need that if the block param handle funcs can handle reg locations
|
||||
let is_out_param = 'block: {
|
||||
let last_inst = state.func.block_insns(block).last();
|
||||
if !state.func.is_branch(last_inst) {
|
||||
break 'block false;
|
||||
}
|
||||
|
||||
for succ_idx in 0..state.func.block_succs(block).len() {
|
||||
for out_vreg in state.func.branch_blockparams(block, last_inst, succ_idx) {
|
||||
if *out_vreg == vreg {
|
||||
break 'block true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
};
|
||||
if (is_out_param || state.liveouts[block.index()].get(idx))
|
||||
&& state.vregs[idx].slot_idx.is_none()
|
||||
{
|
||||
let preg = state.vregs[idx].preg.unwrap();
|
||||
let slot = state.create_stack_slot(preg.class());
|
||||
state.edits.push((
|
||||
ProgPoint::before(Inst::new(block_last_inst_idx)),
|
||||
Edit::Move {
|
||||
from: Allocation::reg(preg),
|
||||
to: Allocation::stack(SpillSlot::new(slot as usize)),
|
||||
},
|
||||
));
|
||||
state.vregs[idx].slot_idx = Some(slot);
|
||||
}
|
||||
|
||||
state.vregs[idx].preg = None;
|
||||
state.pregs[i].vreg = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_out_block_params<'a, F: Function>(
|
||||
fn handle_out_block_params2<'a, F: Function>(
|
||||
state: &mut FastAllocState<'a, F>,
|
||||
const_state: &ReadOnlyData,
|
||||
block: Block,
|
||||
@@ -1638,6 +1631,42 @@ fn handle_out_block_params<'a, F: Function>(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let succs = state.func.block_succs(block);
|
||||
if succs.len() == 1 {
|
||||
let succ = succs[0];
|
||||
|
||||
if state.blocks[succ.index()].params_allocated {
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
todo!("")
|
||||
}
|
||||
|
||||
fn handle_out_block_params<'a, F: Function>(
|
||||
state: &mut FastAllocState<'a, F>,
|
||||
const_state: &ReadOnlyData,
|
||||
block: Block,
|
||||
) -> Result<(), RegAllocError> {
|
||||
let mut last_inst = state.func.block_insns(block).last();
|
||||
trace!(
|
||||
"Allocating outgoing blockparams for {}, last_inst: {}",
|
||||
block.index(),
|
||||
last_inst.index()
|
||||
);
|
||||
if !state.func.is_branch(last_inst) {
|
||||
trace!("Last inst {} is not a branch", last_inst.index());
|
||||
|
||||
// TODO: we need preg maps for each bblock but rn we need to clear the pregs so that the allocation of the next block is not mistaken
|
||||
for i in 0..state.pregs.len() {
|
||||
if state.pregs[i].vreg.is_some() {
|
||||
state.clear_preg_idx(i);
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut pregs_used_by_br = PRegSet::empty();
|
||||
{
|
||||
let alloc_start = state.inst_alloc_offsets[last_inst.index()] as usize;
|
||||
@@ -1677,7 +1706,56 @@ fn handle_out_block_params<'a, F: Function>(
|
||||
|
||||
let succs = state.func.block_succs(block);
|
||||
if succs.len() == 1 && state.blocks[succs[0].index()].params_allocated {
|
||||
trace!("Only one allocated successor, moving allocations");
|
||||
trace!("Only one allocated successor, moving allocations. Moving all liveouts to stack");
|
||||
// done here as there are cases where there are multiple branches at the end of a bblock so we cannot insert any moves
|
||||
// in the case of multiple successors
|
||||
// Move all liveout/block param vregs to a stack slot if they dont have one and clear pregs
|
||||
for i in 0..state.pregs.len() {
|
||||
match state.pregs[i].vreg {
|
||||
None => {}
|
||||
Some(vreg) => {
|
||||
trace!("Clearing {} from p{}", vreg, i);
|
||||
let idx = vreg.vreg();
|
||||
// TODO: obv dont need that if the block param handle funcs can handle reg locations
|
||||
let is_out_param = 'block: {
|
||||
let last_inst = state.func.block_insns(block).last();
|
||||
if !state.func.is_branch(last_inst) {
|
||||
break 'block false;
|
||||
}
|
||||
|
||||
for succ_idx in 0..state.func.block_succs(block).len() {
|
||||
for out_vreg in
|
||||
state.func.branch_blockparams(block, last_inst, succ_idx)
|
||||
{
|
||||
if *out_vreg == vreg {
|
||||
break 'block true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
};
|
||||
if (is_out_param || state.liveouts[block.index()].get(idx))
|
||||
&& state.vregs[idx].slot_idx.is_none()
|
||||
{
|
||||
let preg = state.vregs[idx].preg.unwrap();
|
||||
let slot = state.create_stack_slot(preg.class());
|
||||
state.edits.push((
|
||||
ProgPoint::before(Inst::new(last_inst.index())),
|
||||
Edit::Move {
|
||||
from: Allocation::reg(preg),
|
||||
to: Allocation::stack(SpillSlot::new(slot as usize)),
|
||||
},
|
||||
));
|
||||
state.vregs[idx].slot_idx = Some(slot);
|
||||
}
|
||||
|
||||
state.vregs[idx].preg = None;
|
||||
state.pregs[i].vreg = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let succ = succs[0];
|
||||
// move values to the already allocated places
|
||||
let in_params = state.func.block_params(succ);
|
||||
@@ -2110,14 +2188,75 @@ fn handle_out_block_params<'a, F: Function>(
|
||||
} else {
|
||||
trace!("Successors not allocated. Creating allocation");
|
||||
|
||||
let mut allocs = SmallVec::<[(VReg, u32); 4]>::new();
|
||||
// Move all liveout/block param vregs to a stack slot if they dont have one and clear pregs
|
||||
for i in 0..state.pregs.len() {
|
||||
match state.pregs[i].vreg {
|
||||
None => {}
|
||||
Some(vreg) => {
|
||||
trace!("Clearing {} from p{}", vreg, i);
|
||||
let idx = vreg.vreg();
|
||||
// TODO: obv dont need that if the block param handle funcs can handle reg locations
|
||||
let is_out_param = 'block: {
|
||||
let last_inst = state.func.block_insns(block).last();
|
||||
if !state.func.is_branch(last_inst) {
|
||||
break 'block false;
|
||||
}
|
||||
|
||||
for succ_idx in 0..state.func.block_succs(block).len() {
|
||||
for out_vreg in
|
||||
state.func.branch_blockparams(block, last_inst, succ_idx)
|
||||
{
|
||||
if *out_vreg == vreg {
|
||||
break 'block true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
};
|
||||
if (is_out_param || state.liveouts[block.index()].get(idx))
|
||||
&& state.vregs[idx].slot_idx.is_none()
|
||||
{
|
||||
let preg = state.vregs[idx].preg.unwrap();
|
||||
let slot = state.create_stack_slot(preg.class());
|
||||
for succ in state.func.block_succs(block) {
|
||||
let insert_pos = if succs.len() == 1 {
|
||||
ProgPoint::before(last_inst)
|
||||
} else {
|
||||
ProgPoint::before(state.func.block_insns(*succ).first())
|
||||
};
|
||||
|
||||
state.edits.push((
|
||||
insert_pos,
|
||||
Edit::Move {
|
||||
from: Allocation::reg(preg),
|
||||
to: Allocation::stack(SpillSlot::new(slot as usize)),
|
||||
},
|
||||
));
|
||||
}
|
||||
state.vregs[idx].slot_idx = Some(slot);
|
||||
}
|
||||
|
||||
state.vregs[idx].preg = None;
|
||||
state.pregs[i].vreg = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set incoming block params of successor to the current stack slot
|
||||
for (i, &succ) in state.func.block_succs(block).iter().enumerate() {
|
||||
let mut allocs = SmallVec::<[(VReg, u32); 4]>::new();
|
||||
trace!("Creating block {}", succ.index());
|
||||
if state.blocks[succ.index()].params_allocated {
|
||||
return Err(RegAllocError::CritEdge(block, succ));
|
||||
}
|
||||
|
||||
let insert_pos = if succs.len() == 1 {
|
||||
ProgPoint::before(last_inst)
|
||||
} else {
|
||||
ProgPoint::before(state.func.block_insns(succ).first())
|
||||
};
|
||||
|
||||
// we allocate the params here
|
||||
// TODO: can there be a problem if the same successor occurs multiple times?
|
||||
state.blocks[succ.index()].params_allocated = true;
|
||||
@@ -2132,6 +2271,7 @@ fn handle_out_block_params<'a, F: Function>(
|
||||
let in_vreg = in_params[i];
|
||||
debug_assert!(state.vregs[out_vreg.vreg()].slot_idx.is_some());
|
||||
debug_assert!(state.vregs[in_vreg.vreg()].slot_idx.is_none());
|
||||
debug_assert!(state.vregs[out_vreg.vreg()].preg.is_none());
|
||||
let out_slot_idx = state.vregs[out_vreg.vreg()].slot_idx.unwrap();
|
||||
|
||||
if out_vreg == VReg::invalid() {
|
||||
@@ -2197,14 +2337,14 @@ fn handle_out_block_params<'a, F: Function>(
|
||||
in_vreg
|
||||
);
|
||||
state.edits.push((
|
||||
ProgPoint::before(last_inst),
|
||||
insert_pos,
|
||||
Edit::Move {
|
||||
from: Allocation::stack(SpillSlot::new(out_slot_idx as usize)),
|
||||
to: Allocation::reg(tmp_reg),
|
||||
},
|
||||
));
|
||||
state.edits.push((
|
||||
ProgPoint::before(last_inst),
|
||||
insert_pos,
|
||||
Edit::Move {
|
||||
from: Allocation::reg(tmp_reg),
|
||||
to: Allocation::stack(SpillSlot::new(slot as usize)),
|
||||
|
||||
Reference in New Issue
Block a user