Support for edge-splitting.

This commit is contained in:
Chris Fallin 2023-03-24 15:57:37 -07:00
parent 6623c8f9f3
commit b198c653aa

View file

@ -171,6 +171,49 @@ impl FunctionBody {
log::trace!("add_edge: from {} to {}", from, to); log::trace!("add_edge: from {} to {}", from, to);
} }
pub fn split_edge(&mut self, from: Block, to: Block, succ_idx: usize) -> Block {
assert_eq!(self.blocks[from].succs[succ_idx], to);
let pred_idx = self.blocks[from].pos_in_succ_pred[succ_idx];
assert_eq!(self.blocks[to].preds[pred_idx], from);
// Create the block itself.
let edge_block = self.add_block();
// Add blockparams.
let mut blockparams = vec![];
for i in 0..self.blocks[to].params.len() {
let ty = self.blocks[to].params[i].0;
blockparams.push(self.add_blockparam(edge_block, ty));
}
// Create an unconditional-branch terminator in the edge block.
self.blocks[edge_block].terminator = Terminator::Br {
target: BlockTarget {
block: to,
args: blockparams,
},
};
// Update target of from-block.
self.blocks[from]
.terminator
.update_target(succ_idx, |target| target.block = edge_block);
// Fill in succ/pred links on edge block.
self.blocks[edge_block].succs.push(to);
self.blocks[edge_block].pos_in_succ_pred.push(pred_idx);
self.blocks[edge_block].preds.push(from);
self.blocks[edge_block].pos_in_pred_succ.push(succ_idx);
// Update `succs` in `from`, `preds` in `to`.
self.blocks[from].succs[succ_idx] = edge_block;
self.blocks[from].pos_in_succ_pred[succ_idx] = 0;
self.blocks[to].preds[pred_idx] = edge_block;
self.blocks[to].pos_in_pred_succ[pred_idx] = 0;
edge_block
}
pub fn recompute_edges(&mut self) { pub fn recompute_edges(&mut self) {
for block in self.blocks.values_mut() { for block in self.blocks.values_mut() {
block.preds.clear(); block.preds.clear();