use std::collections::HashMap;
use onnx_runtime_ir::{Graph, NodeId, ValueId};
use crate::error::PlanError;
use crate::options::PlanOptions;
use crate::view_map::ViewMap;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Interval {
pub def: usize,
pub use_end: usize,
}
impl Interval {
pub fn overlaps(&self, other: &Interval) -> bool {
self.def <= other.use_end && other.def <= self.use_end
}
}
#[derive(Clone, Debug)]
pub struct Liveness {
pub order_index: HashMap<NodeId, usize>,
pub order: Vec<NodeId>,
pub last_index: usize,
pub intervals: HashMap<ValueId, Interval>,
pub owners: Vec<ValueId>,
}
fn is_buffer_owner(graph: &Graph, view_map: &ViewMap, options: &PlanOptions, value: ValueId) -> bool {
if graph.initializers.contains_key(&value) {
return false; }
if view_map.is_view(value) {
return false; }
let Some(val) = graph.try_value(value) else {
return false;
};
if val.producer.is_some() {
return true; }
options.include_graph_inputs && graph.inputs.contains(&value)
}
pub fn compute_liveness(
graph: &Graph,
view_map: &ViewMap,
options: &PlanOptions,
) -> Result<Liveness, PlanError> {
let order = graph.topological_order().map_err(|_| PlanError::Cycle)?;
let order_index: HashMap<NodeId, usize> =
order.iter().enumerate().map(|(i, &n)| (n, i)).collect();
let last_index = order.len().saturating_sub(1);
let outputs: std::collections::HashSet<ValueId> = graph.outputs.iter().copied().collect();
let mut intervals: HashMap<ValueId, Interval> = HashMap::new();
for vid in graph.values.keys() {
if !is_buffer_owner(graph, view_map, options, vid) {
continue;
}
let def = graph
.value(vid)
.producer
.and_then(|p| order_index.get(&p).copied())
.unwrap_or(0); intervals.insert(vid, Interval { def, use_end: def });
}
for vid in graph.values.keys() {
let root = view_map.root(vid);
let Some(interval) = intervals.get_mut(&root) else {
continue;
};
for &consumer in &graph.value(vid).consumers {
if let Some(&idx) = order_index.get(&consumer) {
interval.use_end = interval.use_end.max(idx);
}
}
if outputs.contains(&vid) {
interval.use_end = interval.use_end.max(last_index);
}
}
let mut owners: Vec<ValueId> = intervals.keys().copied().collect();
owners.sort_by_key(|v| (intervals[v].def, v.0));
Ok(Liveness {
order_index,
order,
last_index,
intervals,
owners,
})
}