use std::collections::BTreeSet;
use crate::cfg::Cfg;
use super::common::{BranchRegionFact, IrreducibleRegion, LoopCandidate, RegionFact, RegionKind};
use super::helpers::collect_region_exits;
pub(super) fn analyze_regions(
cfg: &Cfg,
loop_candidates: &[LoopCandidate],
branch_regions: &[BranchRegionFact],
irreducible_regions: &[IrreducibleRegion],
) -> Vec<RegionFact> {
let mut regions = Vec::new();
let mut covered = BTreeSet::new();
for loop_candidate in loop_candidates {
covered.extend(loop_candidate.blocks.iter().copied());
regions.push(RegionFact {
blocks: loop_candidate.blocks.clone(),
entry: loop_candidate.header,
exits: loop_candidate.exits.clone(),
kind: RegionKind::LoopRegion,
reducible: loop_candidate.reducible,
structureable: loop_candidate.reducible,
});
}
for irreducible in irreducible_regions {
covered.extend(irreducible.blocks.iter().copied());
regions.push(RegionFact {
blocks: irreducible.blocks.clone(),
entry: irreducible.entry,
exits: collect_region_exits(cfg, &irreducible.blocks),
kind: RegionKind::Irreducible,
reducible: false,
structureable: false,
});
}
for branch_region in branch_regions {
if branch_region.structured_blocks.len() <= 1 {
continue;
}
covered.extend(branch_region.structured_blocks.iter().copied());
regions.push(RegionFact {
blocks: branch_region.structured_blocks.clone(),
entry: branch_region.header,
exits: BTreeSet::from([branch_region.merge]),
kind: RegionKind::BranchRegion,
reducible: true,
structureable: true,
});
}
for block in cfg.block_order.iter().copied() {
if !cfg.reachable_blocks.contains(&block) || covered.contains(&block) {
continue;
}
let exits = cfg.succs[block.index()]
.iter()
.map(|edge_ref| cfg.edges[edge_ref.index()].to)
.filter(|to| cfg.reachable_blocks.contains(to))
.collect();
regions.push(RegionFact {
blocks: BTreeSet::from([block]),
entry: block,
exits,
kind: RegionKind::Linear,
reducible: true,
structureable: true,
});
}
regions.sort_by_key(|region| (region.entry, region.kind));
regions
}