first try handly cycles/chains (doesnt work)

This commit is contained in:
T0b1
2023-04-28 01:10:49 +02:00
parent a0404ec851
commit ef1e46d8ef

View File

@@ -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");