mod adjacent;
mod binding;
mod boundary;
mod handoffs;
mod prune;
mod reads;
mod seeds;
use std::collections::BTreeSet;
use crate::hir::common::{HirBlock, HirProto, TempId};
use super::temp_touch::{TempRefScopeTracker, TempTouchIndex, collect_temp_refs_by_stmt};
use super::walk::for_each_nested_block_mut;
use self::adjacent::try_collapse_adjacent_local_seed_handoff;
use self::boundary::{LabelJumpIndex, collapse_boundary_alias_classes};
use self::handoffs::{HandoffAction, try_collapse_handoff_at};
pub(super) fn collapse_carried_local_handoffs_in_proto(proto: &mut HirProto) -> bool {
collapse_handoffs_recursive(&mut proto.body, &BTreeSet::new())
}
fn collapse_handoffs_recursive(block: &mut HirBlock, outer_temps: &BTreeSet<TempId>) -> bool {
let mut changed = false;
let stmt_temp_refs = collect_temp_refs_by_stmt(&block.stmts);
let mut temp_refs = TempRefScopeTracker::new(&stmt_temp_refs);
for index in 0..temp_refs.len() {
temp_refs.enter_stmt(index);
let child_outer = temp_refs.outer_with_prefix_and_suffix(outer_temps);
for_each_nested_block_mut(&mut block.stmts[index], &mut |nested_block| {
changed |= collapse_handoffs_recursive(nested_block, &child_outer);
});
temp_refs.leave_stmt(index);
}
changed |= collapse_block_handoffs(block, outer_temps);
changed
}
fn collapse_block_handoffs(block: &mut HirBlock, outer_temps: &BTreeSet<TempId>) -> bool {
let mut changed = collapse_boundary_alias_classes(block);
let mut index = 0;
let mut stmt_temp_refs = collect_temp_refs_by_stmt(&block.stmts);
loop {
let action = {
let temp_touches = TempTouchIndex::new(&stmt_temp_refs);
let label_jumps = LabelJumpIndex::new(&block.stmts);
let mut action = None;
while index < block.stmts.len() {
if try_collapse_adjacent_local_seed_handoff(block, index) {
action = Some(HandoffAction::RetrySameIndex);
break;
}
if let Some(handoff_action) =
try_collapse_handoff_at(block, index, outer_temps, &temp_touches, &label_jumps)
{
action = Some(handoff_action);
break;
}
index += 1;
}
action
};
let Some(action) = action else {
break;
};
changed = true;
if matches!(action, HandoffAction::AdvanceIndex) {
index += 1;
}
stmt_temp_refs = collect_temp_refs_by_stmt(&block.stmts);
}
changed
}