Browse Source

Simplify naming and add end block

control-flow-graph
Haled Odat 11 months ago
parent
commit
106accda9d
  1. 23
      core/engine/src/optimizer/control_flow_graph/basic_block.rs
  2. 50
      core/engine/src/optimizer/control_flow_graph/mod.rs

23
core/engine/src/optimizer/control_flow_graph/basic_block.rs

@ -16,7 +16,7 @@ bitflags! {
/// TODO: doc /// TODO: doc
#[derive(Default, Clone)] #[derive(Default, Clone)]
pub struct BasicBlock { pub struct BasicBlock {
pub(crate) predecessors: Vec<BasicBlockKey>, pub(crate) previous: Vec<BasicBlockKey>,
pub(crate) instructions: Vec<Instruction>, pub(crate) instructions: Vec<Instruction>,
pub(crate) terminator: Terminator, pub(crate) terminator: Terminator,
pub(crate) handler: Option<BasicBlockKey>, pub(crate) handler: Option<BasicBlockKey>,
@ -54,23 +54,15 @@ impl BasicBlock {
self.flags.contains(BasicBlockFlags::REACHABLE) self.flags.contains(BasicBlockFlags::REACHABLE)
} }
pub(crate) fn successors(&self) -> Vec<BasicBlockKey> { pub(crate) fn next(&self) -> Vec<BasicBlockKey> {
match self.terminator { let mut result = Vec::new();
Terminator::None => vec![], self.next_into(&mut result);
Terminator::JumpUnconditional { target, .. } => { result
vec![target]
}
Terminator::JumpConditional { no, yes, .. }
| Terminator::TemplateLookup { no, yes, .. } => {
vec![no, yes]
}
Terminator::Return => Vec::new(),
}
} }
pub(crate) fn next(&self, nexts: &mut Vec<BasicBlockKey>) { pub(crate) fn next_into(&self, nexts: &mut Vec<BasicBlockKey>) {
match self.terminator { match self.terminator {
Terminator::None | Terminator::Return => {} Terminator::None => {}
Terminator::JumpUnconditional { target, .. } => { Terminator::JumpUnconditional { target, .. } => {
nexts.push(target); nexts.push(target);
} }
@ -79,6 +71,7 @@ impl BasicBlock {
nexts.push(no); nexts.push(no);
nexts.push(yes); nexts.push(yes);
} }
Terminator::Return { end } => nexts.push(end),
} }
} }
} }

50
core/engine/src/optimizer/control_flow_graph/mod.rs

@ -54,7 +54,7 @@ pub(crate) enum Terminator {
}, },
/// TODO: doc /// TODO: doc
Return, Return { end: BasicBlockKey },
} }
impl Terminator { impl Terminator {
@ -89,6 +89,7 @@ impl Terminator {
/// TODO: doc /// TODO: doc
pub struct ControlFlowGraph { pub struct ControlFlowGraph {
basic_block_start: BasicBlockKey, basic_block_start: BasicBlockKey,
basic_block_end: BasicBlockKey,
basic_blocks: SlotMap<BasicBlockKey, BasicBlock>, basic_blocks: SlotMap<BasicBlockKey, BasicBlock>,
} }
@ -122,19 +123,26 @@ impl Debug for ControlFlowGraph {
if basic_block.reachable() { "" } else { "not " } if basic_block.reachable() { "" } else { "not " }
)?; )?;
if !basic_block.predecessors.is_empty() { if key == self.basic_block_start {
write!(f, " -- predecessors ")?; write!(f, " -- start")?;
for predecessor in &basic_block.predecessors { }
if key == self.basic_block_end {
write!(f, " -- end")?;
}
if !basic_block.previous.is_empty() {
write!(f, " -- previous ")?;
for predecessor in &basic_block.previous {
let index = index_from_basic_block(*predecessor); let index = index_from_basic_block(*predecessor);
write!(f, "B{index}, ")?; write!(f, "B{index}, ")?;
} }
} }
let successors = basic_block.successors(); let next = basic_block.next();
if !successors.is_empty() { if !next.is_empty() {
write!(f, " -- successors ")?; write!(f, " -- next ")?;
for successor in &successors { for bb in &next {
let index = index_from_basic_block(*successor); let index = index_from_basic_block(*bb);
write!(f, "B{index}, ")?; write!(f, "B{index}, ")?;
} }
} }
@ -171,8 +179,9 @@ impl Debug for ControlFlowGraph {
let target = index_from_basic_block(*yes); let target = index_from_basic_block(*yes);
write!(f, "TemplateLookup B{target}")?; write!(f, "TemplateLookup B{target}")?;
} }
Terminator::Return => { Terminator::Return { end } => {
write!(f, "Return")?; let target = index_from_basic_block(*end);
write!(f, "Return B{target}")?;
} }
} }
writeln!(f)?; writeln!(f)?;
@ -271,6 +280,8 @@ impl ControlFlowGraph {
basic_block_keys[index] basic_block_keys[index]
}; };
let basic_block_end = basic_block_keys[leaders.len() - 1];
let mut iter = InstructionIterator::new(bytecode); let mut iter = InstructionIterator::new(bytecode);
for (i, leader) in leaders for (i, leader) in leaders
.iter() .iter()
@ -296,12 +307,14 @@ impl ControlFlowGraph {
while let Some((_, _, instruction)) = iter.next() { while let Some((_, _, instruction)) = iter.next() {
match instruction { match instruction {
Instruction::Return => { Instruction::Return => {
terminator = Terminator::Return; terminator = Terminator::Return {
end: basic_block_end,
};
} }
Instruction::Jump { address } | Instruction::Default { address } => { Instruction::Jump { address } | Instruction::Default { address } => {
let target = basic_block_from_bytecode_position(address); let target = basic_block_from_bytecode_position(address);
basic_blocks[target].predecessors.push(key); basic_blocks[target].previous.push(key);
terminator = Terminator::JumpUnconditional { terminator = Terminator::JumpUnconditional {
opcode: instruction.opcode(), opcode: instruction.opcode(),
@ -315,8 +328,8 @@ impl ControlFlowGraph {
let yes = basic_block_from_bytecode_position(address); let yes = basic_block_from_bytecode_position(address);
let no = basic_block_keys[i + 1]; let no = basic_block_keys[i + 1];
basic_blocks[yes].predecessors.push(key); basic_blocks[yes].previous.push(key);
basic_blocks[no].predecessors.push(key); basic_blocks[no].previous.push(key);
terminator = Terminator::TemplateLookup { no, yes, site }; terminator = Terminator::TemplateLookup { no, yes, site };
} }
@ -325,8 +338,8 @@ impl ControlFlowGraph {
let yes = basic_block_from_bytecode_position(address); let yes = basic_block_from_bytecode_position(address);
let no = basic_block_keys[i + 1]; let no = basic_block_keys[i + 1];
basic_blocks[yes].predecessors.push(key); basic_blocks[yes].previous.push(key);
basic_blocks[no].predecessors.push(key); basic_blocks[no].previous.push(key);
terminator = Terminator::JumpConditional { terminator = Terminator::JumpConditional {
opcode: instruction.opcode(), opcode: instruction.opcode(),
@ -351,6 +364,7 @@ impl ControlFlowGraph {
Self { Self {
basic_block_start: basic_block_keys[0], basic_block_start: basic_block_keys[0],
basic_block_end,
basic_blocks, basic_blocks,
} }
} }
@ -520,7 +534,7 @@ impl GraphEliminateUnreachableBasicBlocks {
// "reachable basic blocks should not be eliminated" // "reachable basic blocks should not be eliminated"
// ); // );
// basic_block.predecessors.clear(); // basic_block.previous.clear();
// basic_block.terminator = Terminator::None; // basic_block.terminator = Terminator::None;
// changed |= true; // changed |= true;

Loading…
Cancel
Save