first try handly cycles/chains (doesnt work)
This commit is contained in:
@@ -908,6 +908,155 @@ fn handle_out_block_params<'a, F: Function>(
|
||||
let in_params = state.func.block_params(succ);
|
||||
let out_params = state.func.branch_blockparams(block, last_inst, 0);
|
||||
debug_assert_eq!(in_params.len(), out_params.len());
|
||||
assert!(in_params.len() < 254);
|
||||
|
||||
if in_params.is_empty() {
|
||||
trace!("No params. Skipping");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// TODO: this is a really dumb way to handle cycles/chains
|
||||
// need a better algo
|
||||
let mut depend_count: SmallVec<[u8; 8]> = SmallVec::new();
|
||||
let mut params_left: SmallVec<[u8; 8]> = SmallVec::new();
|
||||
//let mut remap: SmallVec<[Option<u32>; 8]> = SmallVec::new();
|
||||
|
||||
depend_count.resize(out_params.len(), 0);
|
||||
//remap.resize(out_params.len(), None);
|
||||
for i in 0..in_params.len() {
|
||||
params_left.push(i as u8);
|
||||
}
|
||||
|
||||
for i in 0..out_params.len() {
|
||||
let out_slot = state.vregs[out_params[i].vreg()].slot_idx.unwrap();
|
||||
for j in 0..in_params.len() {
|
||||
let in_slot = state.vregs[in_params[j].vreg()].slot_idx.unwrap();
|
||||
if i == j {
|
||||
continue;
|
||||
}
|
||||
|
||||
if out_slot == in_slot {
|
||||
depend_count[j] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while !params_left.is_empty() {
|
||||
let count = params_left.len();
|
||||
|
||||
let mut i = 0;
|
||||
while i < params_left.len() {
|
||||
let idx = params_left[i] as usize;
|
||||
if depend_count[idx] != 0 {
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
params_left.swap_remove(i);
|
||||
let out_slot = state.vregs[out_params[idx].vreg()].slot_idx.unwrap();
|
||||
// check if any other value depends on this
|
||||
for j in 0..params_left.len() {
|
||||
let idx = params_left[j] as usize;
|
||||
let in_slot = state.vregs[in_params[idx].vreg()].slot_idx.unwrap();
|
||||
if in_slot == out_slot {
|
||||
depend_count[idx] -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
let in_vreg = in_params[idx];
|
||||
let out_vreg = out_params[idx];
|
||||
|
||||
debug_assert!(state.vregs[in_vreg.vreg()].slot_idx.is_some());
|
||||
debug_assert!(state.vregs[out_vreg.vreg()].slot_idx.is_some());
|
||||
|
||||
let tmp_reg = if out_vreg.class() == RegClass::Int {
|
||||
tmp_reg_int
|
||||
} else {
|
||||
tmp_reg_float
|
||||
};
|
||||
/*let out_slot = match remap[idx] {
|
||||
Some(idx) => idx,
|
||||
None => 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();
|
||||
|
||||
trace!(
|
||||
"Move {} from slot {} to slot {} for {}",
|
||||
out_vreg,
|
||||
out_slot,
|
||||
in_slot,
|
||||
in_vreg
|
||||
);
|
||||
if out_slot == in_slot {
|
||||
continue;
|
||||
}
|
||||
state.edits.push((
|
||||
ProgPoint::before(last_inst),
|
||||
Edit::Move {
|
||||
from: Allocation::stack(SpillSlot::new(out_slot as usize)),
|
||||
to: Allocation::reg(tmp_reg),
|
||||
},
|
||||
));
|
||||
state.edits.push((
|
||||
ProgPoint::before(last_inst),
|
||||
Edit::Move {
|
||||
from: Allocation::reg(tmp_reg),
|
||||
to: Allocation::stack(SpillSlot::new(in_slot as usize)),
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
if params_left.len() == count {
|
||||
// everything left belongs to a cycle
|
||||
if cfg!(debug_assertions) {
|
||||
for i in 0..params_left.len() {
|
||||
assert_eq!(depend_count[params_left[i] as usize], 1);
|
||||
}
|
||||
}
|
||||
|
||||
// just move the first element to a tmp pos and search which reg depends on it
|
||||
// TODO: we should sanity check that all regs in the cycle die after the block
|
||||
|
||||
let idx = params_left[0] as usize;
|
||||
let tmp_reg = if out_params[idx].class() == RegClass::Int {
|
||||
tmp_reg_int
|
||||
} else {
|
||||
tmp_reg_float
|
||||
};
|
||||
let out_slot = state.vregs[out_params[idx].vreg()].slot_idx.take().unwrap();
|
||||
state.edits.push((
|
||||
ProgPoint::before(last_inst),
|
||||
Edit::Move {
|
||||
from: Allocation::stack(SpillSlot::new(out_slot as usize)),
|
||||
to: Allocation::reg(tmp_reg),
|
||||
},
|
||||
));
|
||||
// TODO: mark out_slot as free
|
||||
let new_slot = state.alloc_stack_slot(out_params[idx]);
|
||||
trace!(
|
||||
"Cycle detected. Breaking by allocating new slot {} for {}",
|
||||
new_slot,
|
||||
out_params[idx]
|
||||
);
|
||||
state.edits.push((
|
||||
ProgPoint::before(last_inst),
|
||||
Edit::Move {
|
||||
from: Allocation::reg(tmp_reg),
|
||||
to: Allocation::stack(SpillSlot::new(new_slot as usize)),
|
||||
},
|
||||
));
|
||||
|
||||
for j in 0..params_left.len() {
|
||||
let in_slot = state.vregs[in_params[params_left[j] as usize].vreg()]
|
||||
.slot_idx
|
||||
.unwrap();
|
||||
if in_slot == out_slot {
|
||||
depend_count[params_left[j] as usize] -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: need to break cycles
|
||||
// e.g.
|
||||
@@ -915,13 +1064,18 @@ fn handle_out_block_params<'a, F: Function>(
|
||||
// Move v145 from slot 6 to slot 3 for v136
|
||||
// Move v146 from slot 3 to slot 4 for v137
|
||||
// or
|
||||
// 6->3
|
||||
// 3->5
|
||||
// 5->6
|
||||
// 0: 6->4
|
||||
// 1: 6->3
|
||||
// 2: 3->5
|
||||
// 3: 5->6
|
||||
// depends: [3, 3, 1, 2]
|
||||
// or
|
||||
// 3->6
|
||||
// 6->3
|
||||
for i in 0..in_params.len() {
|
||||
// 2->1
|
||||
// 1->4
|
||||
// depends: [1, 0, 0xFF, 2]
|
||||
/*for i in 0..in_params.len() {
|
||||
let in_vreg = in_params[i];
|
||||
let out_vreg = out_params[i];
|
||||
|
||||
@@ -960,7 +1114,7 @@ fn handle_out_block_params<'a, F: Function>(
|
||||
to: Allocation::stack(SpillSlot::new(in_slot as usize)),
|
||||
},
|
||||
));
|
||||
}
|
||||
}*/
|
||||
} else {
|
||||
trace!("Successors not allocated. Creating allocation");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user