Skip to content

Commit

Permalink
Move Machine into datalog.rs, pub(super) fields in AnalysisResults, r…
Browse files Browse the repository at this point in the history
…m DatalogResults
  • Loading branch information
acl-cqc committed Oct 22, 2024
1 parent 8bab4d5 commit 3eccadf
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 77 deletions.
3 changes: 2 additions & 1 deletion hugr-passes/src/dataflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
//! Dataflow analysis of Hugrs.

mod datalog;
pub use datalog::Machine;
mod value_row;

mod machine;
pub use machine::{AnalysisResults, Machine, TailLoopTermination};
pub use machine::{AnalysisResults, TailLoopTermination};

mod partial_value;
pub use partial_value::{AbstractValue, PartialSum, PartialValue, Sum};
Expand Down
67 changes: 54 additions & 13 deletions hugr-passes/src/dataflow/datalog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ use std::hash::Hash;

use hugr_core::extension::prelude::{MakeTuple, UnpackTuple};
use hugr_core::ops::{OpTrait, OpType};
use hugr_core::{HugrView, IncomingPort, Node, OutgoingPort, PortIndex as _};
use hugr_core::{HugrView, IncomingPort, Node, OutgoingPort, PortIndex as _, Wire};

use super::value_row::ValueRow;
use super::{AbstractValue, DFContext, PartialValue};
use super::{AbstractValue, AnalysisResults, DFContext, PartialValue};

type PV<V> = PartialValue<V>;

Expand All @@ -19,18 +19,53 @@ pub enum IO {
Output,
}

pub(super) struct DatalogResults<V> {
pub in_wire_value: Vec<(Node, IncomingPort, PV<V>)>,
pub out_wire_value: Vec<(Node, OutgoingPort, PV<V>)>,
pub case_reachable: Vec<(Node, Node)>,
pub bb_reachable: Vec<(Node, Node)>,
/// Basic structure for performing an analysis. Usage:
/// 1. Get a new instance via [Self::default()]
/// 2. (Optionally / for tests) zero or more [Self::prepopulate_wire] with initial values
/// 3. Call [Self::run] to produce [AnalysisResults] which can be inspected via
/// [read_out_wire](AnalysisResults::read_out_wire)
pub struct Machine<V: AbstractValue>(Vec<(Node, IncomingPort, PartialValue<V>)>);

/// derived-Default requires the context to be Defaultable, which is unnecessary
impl<V: AbstractValue> Default for Machine<V> {
fn default() -> Self {
Self(Default::default())
}
}

pub(super) fn run_datalog<V: AbstractValue>(
impl<V: AbstractValue> Machine<V> {
/// Provide initial values for some wires.
// Likely for test purposes only - should we make non-pub or #[cfg(test)] ?
pub fn prepopulate_wire(&mut self, h: &impl HugrView, wire: Wire, value: PartialValue<V>) {
self.0.extend(
h.linked_inputs(wire.node(), wire.source())
.map(|(n, inp)| (n, inp, value.clone())),
);
}

/// Run the analysis (iterate until a lattice fixpoint is reached),
/// given initial values for some of the root node inputs.
/// (Note that `in_values` will not be useful for `Case` or `DFB`-rooted Hugrs,
/// but should handle other containers.)
/// The context passed in allows interpretation of leaf operations.
pub fn run<H: HugrView>(
mut self,
context: &impl DFContext<V>,
hugr: H,
in_values: impl IntoIterator<Item = (IncomingPort, PartialValue<V>)>,
) -> AnalysisResults<V, H> {
let root = hugr.root();
self.0
.extend(in_values.into_iter().map(|(p, v)| (root, p, v)));
run_datalog(self.0, context, hugr)
}
}

pub(super) fn run_datalog<V: AbstractValue, H: HugrView>(
in_wire_value_proto: Vec<(Node, IncomingPort, PV<V>)>,
c: &impl DFContext<V>,
hugr: &impl HugrView,
) -> DatalogResults<V> {
hugr: H,
) -> AnalysisResults<V, H> {
// ascent-(macro-)generated code generates a bunch of warnings,
// keep code in here to a minimum.
#![allow(
Expand Down Expand Up @@ -84,7 +119,7 @@ pub(super) fn run_datalog<V: AbstractValue>(
if !op_t.is_container(),
if let Some(sig) = op_t.dataflow_signature(),
node_in_value_row(n, vs),
if let Some(outs) = propagate_leaf_op(c, hugr, *n, &vs[..], sig.output_count()),
if let Some(outs) = propagate_leaf_op(c, &hugr, *n, &vs[..], sig.output_count()),
for (p, v) in (0..).map(OutgoingPort::from).zip(outs);

// DFG
Expand Down Expand Up @@ -211,9 +246,15 @@ pub(super) fn run_datalog<V: AbstractValue>(
io_node(func, outp, IO::Output),
in_wire_value(outp, p, v);
};
DatalogResults {
let out_wire_values = all_results
.out_wire_value
.iter()
.map(|(n, p, v)| (Wire::new(*n, *p), v.clone()))
.collect();
AnalysisResults {
hugr,
out_wire_values,
in_wire_value: all_results.in_wire_value,
out_wire_value: all_results.out_wire_value,
case_reachable: all_results.case_reachable,
bb_reachable: all_results.bb_reachable,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,66 +2,15 @@ use std::collections::HashMap;

use hugr_core::{ops::Value, types::ConstTypeError, HugrView, IncomingPort, Node, PortIndex, Wire};

use super::datalog::{run_datalog, DatalogResults};
use super::{AbstractValue, DFContext, PartialValue};

/// Basic structure for performing an analysis. Usage:
/// 1. Get a new instance via [Self::default()]
/// 2. (Optionally / for tests) zero or more [Self::prepopulate_wire] with initial values
/// 3. Call [Self::run] to produce [AnalysisResults] which can be inspected via
/// [read_out_wire](AnalysisResults::read_out_wire)
pub struct Machine<V: AbstractValue>(Vec<(Node, IncomingPort, PartialValue<V>)>);
use super::{AbstractValue, PartialValue};

/// Results of a dataflow analysis, packaged with context for easy inspection
pub struct AnalysisResults<V: AbstractValue, H: HugrView> {
hugr: H,
results: DatalogResults<V>,
out_wire_values: HashMap<Wire, PartialValue<V>>,
}

/// derived-Default requires the context to be Defaultable, which is unnecessary
impl<V: AbstractValue> Default for Machine<V> {
fn default() -> Self {
Self(Default::default())
}
}

impl<V: AbstractValue> Machine<V> {
/// Provide initial values for some wires.
// Likely for test purposes only - should we make non-pub or #[cfg(test)] ?
pub fn prepopulate_wire(&mut self, h: &impl HugrView, wire: Wire, value: PartialValue<V>) {
self.0.extend(
h.linked_inputs(wire.node(), wire.source())
.map(|(n, inp)| (n, inp, value.clone())),
);
}

/// Run the analysis (iterate until a lattice fixpoint is reached),
/// given initial values for some of the root node inputs.
/// (Note that `in_values` will not be useful for `Case` or `DFB`-rooted Hugrs,
/// but should handle other containers.)
/// The context passed in allows interpretation of leaf operations.
pub fn run<H: HugrView>(
mut self,
context: &impl DFContext<V>,
hugr: H,
in_values: impl IntoIterator<Item = (IncomingPort, PartialValue<V>)>,
) -> AnalysisResults<V, H> {
let root = hugr.root();
self.0
.extend(in_values.into_iter().map(|(p, v)| (root, p, v)));
let results = run_datalog(self.0, context, &hugr);
let out_wire_values = results
.out_wire_value
.iter()
.map(|(n, p, v)| (Wire::new(*n, *p), v.clone()))
.collect();
AnalysisResults {
hugr,
results,
out_wire_values,
}
}
pub(super) hugr: H,
pub(super) in_wire_value: Vec<(Node, IncomingPort, PartialValue<V>)>,
pub(super) case_reachable: Vec<(Node, Node)>,
pub(super) bb_reachable: Vec<(Node, Node)>,
pub(super) out_wire_values: HashMap<Wire, PartialValue<V>>,
}

impl<V: AbstractValue, H: HugrView> AnalysisResults<V, H> {
Expand All @@ -79,8 +28,7 @@ impl<V: AbstractValue, H: HugrView> AnalysisResults<V, H> {
self.hugr.get_optype(node).as_tail_loop()?;
let [_, out] = self.hugr.get_io(node).unwrap();
Some(TailLoopTermination::from_control_value(
self.results
.in_wire_value
self.in_wire_value
.iter()
.find_map(|(n, p, v)| (*n == out && p.index() == 0).then_some(v))
.unwrap(),
Expand All @@ -99,8 +47,7 @@ impl<V: AbstractValue, H: HugrView> AnalysisResults<V, H> {
let cond = self.hugr.get_parent(case)?;
self.hugr.get_optype(cond).as_conditional()?;
Some(
self.results
.case_reachable
self.case_reachable
.iter()
.any(|(cond2, case2)| &cond == cond2 && &case == case2),
)
Expand All @@ -120,8 +67,7 @@ impl<V: AbstractValue, H: HugrView> AnalysisResults<V, H> {
return None;
};
Some(
self.results
.bb_reachable
self.bb_reachable
.iter()
.any(|(cfg2, bb2)| *cfg2 == cfg && *bb2 == bb),
)
Expand Down

0 comments on commit 3eccadf

Please sign in to comment.