Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 40 additions & 24 deletions hugr-passes/src/composable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

mod scope;

use hugr_core::Hugr;
pub use scope::{InScope, PassScope, Preserve};

use std::{error::Error, marker::PhantomData};
Expand All @@ -23,7 +22,7 @@ use itertools::Either;
/// idempotent (i.e. such that after running a pass, rerunning it immediately has
/// no further effect). However this is *not* a requirement, e.g. a sequence of
/// idempotent passes created by [ComposablePass::then] may not be idempotent itself.
pub trait ComposablePass<H: HugrMut>: Sized {
pub trait ComposablePass<H: HugrMut>: WithScope + Sized {
/// Error thrown by this pass.
type Error: Error;
/// Result returned by this pass.
Expand All @@ -32,13 +31,6 @@ pub trait ComposablePass<H: HugrMut>: Sized {
/// Run the pass on the given HUGR.
fn run(&self, hugr: &mut H) -> Result<Self::Result, Self::Error>;

/// Set the scope configuration used to run the pass.
///
/// See [`PassScope`] for more details.
///
/// Since `hugr >=0.26.0`, passes must implement this to respect the scope configuration.
fn with_scope_internal(self, scope: impl Into<PassScope>) -> Self;

/// Apply a function to the error type of this pass, returning a new
/// [`ComposablePass`] that has the same result type.
fn map_err<E2: Error>(
Expand Down Expand Up @@ -79,12 +71,17 @@ pub trait ComposablePass<H: HugrMut>: Sized {
let res2 = self.1.run(hugr).map_err(E::from_second)?;
Ok((res1, res2))
}

fn with_scope_internal(self, scope: impl Into<PassScope>) -> Self {
}
impl<E, P1, P2> WithScope for Sequence<E, P1, P2>
where
P1: WithScope,
P2: WithScope,
{
fn with_scope(self, scope: impl Into<PassScope>) -> Self {
let scope = scope.into();
Self(
self.0.with_scope_internal(scope.clone()),
self.1.with_scope_internal(scope),
self.0.with_scope(scope.clone()),
self.1.with_scope(scope),
PhantomData,
)
}
Expand All @@ -100,12 +97,19 @@ pub trait WithScope {
/// Set the scope configuration used to run the pass.
///
/// See [`PassScope`] for more details.
///
/// Since `hugr >=0.26.0`, passes must implement this to respect the scope configuration.
fn with_scope(self, scope: impl Into<PassScope>) -> Self;
}

impl<P: ComposablePass<Hugr>> WithScope for P {
fn with_scope(self, scope: impl Into<PassScope>) -> Self {
self.with_scope_internal(scope)
/// Return a default instance of the pass with the given scope.
///
/// See [`PassScope`] for more details.
#[must_use]
fn default_with_scope(scope: PassScope) -> Self
where
Self: Default,
{
Self::default().with_scope(scope)
}
}

Expand Down Expand Up @@ -165,9 +169,13 @@ impl<P: ComposablePass<H>, H: HugrMut, E: Error, F: Fn(P::Error) -> E> Composabl
fn run(&self, hugr: &mut H) -> Result<P::Result, Self::Error> {
self.0.run(hugr).map_err(&self.1)
}
}

fn with_scope_internal(self, scope: impl Into<PassScope>) -> Self {
Self(self.0.with_scope_internal(scope), self.1, PhantomData)
impl<P: ComposablePass<H>, H: HugrMut, E: Error, F: Fn(P::Error) -> E> WithScope
for ErrMapper<P, H, E, F>
{
fn with_scope(self, scope: impl Into<PassScope>) -> Self {
Self(self.0.with_scope(scope), self.1, PhantomData)
}
}

Expand Down Expand Up @@ -247,9 +255,11 @@ where
})?;
Ok(res)
}
}

fn with_scope_internal(self, scope: impl Into<PassScope>) -> Self {
Self(self.0.with_scope_internal(scope), self.1)
impl<P: ComposablePass<H>, H: HugrMut> WithScope for ValidatingPass<P, H> {
fn with_scope(self, scope: impl Into<PassScope>) -> Self {
Self(self.0.with_scope(scope), self.1)
}
}

Expand Down Expand Up @@ -288,12 +298,18 @@ impl<
res.then(|| self.1.run(hugr).map_err(ErrorCombiner::from_second))
.transpose()
}
}

fn with_scope_internal(self, scope: impl Into<PassScope>) -> Self {
impl<E, H, A, B> WithScope for IfThen<E, H, A, B>
where
A: WithScope,
B: WithScope,
{
fn with_scope(self, scope: impl Into<PassScope>) -> Self {
let scope = scope.into();
Self(
self.0.with_scope_internal(scope.clone()),
self.1.with_scope_internal(scope),
self.0.with_scope(scope.clone()),
self.1.with_scope(scope),
PhantomData,
)
}
Expand Down
8 changes: 5 additions & 3 deletions hugr-passes/src/const_fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ use hugr_core::{
};
use value_handle::ValueHandle;

use crate::composable::{ComposablePass, PassScope, WithScope, validate_if_test};
use crate::dataflow::{
ConstLoader, ConstLocation, DFContext, Machine, PartialValue, TailLoopTermination,
partial_from_const,
};
use crate::dead_code::{DeadCodeElimError, DeadCodeElimPass, PreserveNode};
use crate::{ComposablePass, PassScope, composable::validate_if_test};

#[derive(Debug, Clone, Default)]
/// A configuration for the Constant Folding pass.
Expand Down Expand Up @@ -186,7 +186,7 @@ impl<H: HugrMut<Node = Node> + 'static> ComposablePass<H> for ConstantFoldPass {
.scope
.as_ref()
.map_or(DeadCodeElimPass::<H>::default(), |scope| {
DeadCodeElimPass::<H>::default().with_scope_internal(scope.clone())
DeadCodeElimPass::<H>::default_with_scope(scope.clone())
});
dce.with_entry_points(self.inputs.keys().copied())
.set_preserve_callback(if self.allow_increase_termination {
Expand All @@ -208,8 +208,10 @@ impl<H: HugrMut<Node = Node> + 'static> ComposablePass<H> for ConstantFoldPass {
})?;
Ok(())
}
}

fn with_scope_internal(mut self, scope: impl Into<PassScope>) -> Self {
impl WithScope for ConstantFoldPass {
fn with_scope(mut self, scope: impl Into<PassScope>) -> Self {
self.scope = Some(scope.into());
self
}
Expand Down
6 changes: 5 additions & 1 deletion hugr-passes/src/dead_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::collections::{HashMap, HashSet, VecDeque};
use std::fmt::{Debug, Display, Formatter};
use std::sync::Arc;

use crate::composable::WithScope;
use crate::{ComposablePass, PassScope};

/// Configuration for Dead Code Elimination pass
Expand Down Expand Up @@ -212,12 +213,15 @@ impl<H: HugrMut> ComposablePass<H> for DeadCodeElimPass<H> {
}
Ok(())
}
}

fn with_scope_internal(mut self, scope: impl Into<PassScope>) -> Self {
impl<H: HugrMut> WithScope for DeadCodeElimPass<H> {
fn with_scope(mut self, scope: impl Into<PassScope>) -> Self {
self.scope = Some(scope.into());
self
}
}

#[cfg(test)]
mod test {
use std::sync::Arc;
Expand Down
20 changes: 10 additions & 10 deletions hugr-passes/src/dead_funcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ use hugr_core::{
use itertools::Either;
use petgraph::visit::{Dfs, Walker};

use crate::{
ComposablePass, PassScope,
composable::{Preserve, ValidatePassError, validate_if_test},
use crate::composable::{
ComposablePass, PassScope, Preserve, ValidatePassError, WithScope, validate_if_test,
};

#[derive(Debug, thiserror::Error)]
Expand Down Expand Up @@ -68,7 +67,7 @@ impl RemoveDeadFuncsPass {
/// Adds new entry points - these must be [`FuncDefn`] nodes
/// that are children of the [`Module`] at the root of the Hugr.
///
/// Overrides any [PassScope] set by a call to [Self::with_scope_internal].
/// Overrides any [PassScope] set by a call to [Self::with_scope].
///
/// [`FuncDefn`]: hugr_core::ops::OpType::FuncDefn
/// [`Module`]: hugr_core::ops::OpType::Module
Expand All @@ -92,12 +91,6 @@ impl<H: HugrMut<Node = Node>> ComposablePass<H> for RemoveDeadFuncsPass {
type Error = RemoveDeadFuncsError;
type Result = ();

/// Overrides any entrypoints set by a call to [Self::with_module_entry_points].
fn with_scope_internal(mut self, scope: impl Into<PassScope>) -> Self {
self.entry_points = Either::Right(scope.into());
self
}

fn run(&self, hugr: &mut H) -> Result<(), RemoveDeadFuncsError> {
let mut entry_points = Vec::new();
match &self.entry_points {
Expand Down Expand Up @@ -161,6 +154,13 @@ impl<H: HugrMut<Node = Node>> ComposablePass<H> for RemoveDeadFuncsPass {
}
}

impl WithScope for RemoveDeadFuncsPass {
fn with_scope(mut self, scope: impl Into<PassScope>) -> Self {
self.entry_points = Either::Right(scope.into());
self
}
}

/// Deletes from the Hugr any functions that are not used by either `Call` or
/// `LoadFunction` nodes in reachable parts.
///
Expand Down
5 changes: 4 additions & 1 deletion hugr-passes/src/inline_dfgs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use hugr_core::hugr::{
};
use itertools::Itertools;

use crate::composable::WithScope;
use crate::{ComposablePass, PassScope};

/// Inlines all DFG nodes nested below the entrypoint.
Expand Down Expand Up @@ -44,8 +45,10 @@ impl<H: HugrMut> ComposablePass<H> for InlineDFGsPass {
}
Ok(())
}
}

fn with_scope_internal(mut self, scope: impl Into<PassScope>) -> Self {
impl WithScope for InlineDFGsPass {
fn with_scope(mut self, scope: impl Into<PassScope>) -> Self {
self.scope = scope.into();
self
}
Expand Down
6 changes: 4 additions & 2 deletions hugr-passes/src/monomorphize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use hugr_core::{
use hugr_core::hugr::{HugrView, OpType, hugrmut::HugrMut};
use itertools::Itertools as _;

use crate::composable::{ValidatePassError, validate_if_test};
use crate::composable::{ValidatePassError, WithScope, validate_if_test};
use crate::{ComposablePass, PassScope};

/// Replaces calls to polymorphic functions with calls to new monomorphic
Expand Down Expand Up @@ -223,8 +223,10 @@ impl<H: HugrMut<Node = Node>> ComposablePass<H> for MonomorphizePass {
};
Ok(())
}
}

fn with_scope_internal(mut self, scope: impl Into<PassScope>) -> Self {
impl WithScope for MonomorphizePass {
fn with_scope(mut self, scope: impl Into<PassScope>) -> Self {
self.scope = scope.into();
self
}
Expand Down
5 changes: 4 additions & 1 deletion hugr-passes/src/non_local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use hugr_core::{
types::{EdgeKind, Type},
};

use crate::composable::WithScope;
use crate::{ComposablePass, PassScope, composable::Preserve};

mod localize;
Expand Down Expand Up @@ -78,8 +79,10 @@ impl<H: HugrMut> ComposablePass<H> for LocalizeEdges {

Ok(())
}
}

fn with_scope_internal(mut self, scope: impl Into<PassScope>) -> Self {
impl WithScope for LocalizeEdges {
fn with_scope(mut self, scope: impl Into<PassScope>) -> Self {
self.scope = scope.into();
self
}
Expand Down
8 changes: 5 additions & 3 deletions hugr-passes/src/normalize_cfgs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use hugr_core::ops::{
};
use hugr_core::{Direction, Hugr, HugrView, Node, OutgoingPort, PortIndex};

use crate::composable::WithScope;
use crate::{ComposablePass, PassScope};

/// Merge any basic blocks that are direct children of the specified [`CFG`]-entrypoint
Expand Down Expand Up @@ -113,7 +114,7 @@ impl<N> NormalizeCFGPass<N> {
/// Allows mutating the set of CFG nodes that will be normalized.
///
/// Note that calling this method (even if the returned mut-ref is not written to) will
/// override any previous call to [Self::with_scope_internal].
/// override any previous call to [Self::with_scope].
///
/// If empty (the default), all (non-strict) descendants of the [HugrView::entrypoint]
/// will be normalized.
Expand Down Expand Up @@ -168,9 +169,10 @@ impl<H: HugrMut> ComposablePass<H> for NormalizeCFGPass<H::Node> {
}
Ok(results)
}
}

/// Overrides any previous call to [Self::cfgs]
fn with_scope_internal(mut self, scope: impl Into<PassScope>) -> Self {
impl<N> WithScope for NormalizeCFGPass<N> {
fn with_scope(mut self, scope: impl Into<PassScope>) -> Self {
self.scope = Either::Right(scope.into());
self
}
Expand Down
13 changes: 8 additions & 5 deletions hugr-passes/src/redundant_order_edges.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use hugr_core::{HugrView, IncomingPort, Node, OutgoingPort};
use itertools::Itertools;
use petgraph::visit::Walker;

use crate::composable::WithScope;
use crate::{ComposablePass, PassScope};

/// A pass for removing order edges in a Hugr region that are already implied by
Expand Down Expand Up @@ -156,11 +157,6 @@ impl<H: HugrMut<Node = Node>> ComposablePass<H> for RedundantOrderEdgesPass {
type Error = HugrError;
type Result = RedundantOrderEdgesResult;

fn with_scope_internal(mut self, scope: impl Into<PassScope>) -> Self {
self.scope = scope.into();
self
}

fn run(&self, hugr: &mut H) -> Result<Self::Result, Self::Error> {
// Nodes to explore in the hugr.
let mut region_candidates = VecDeque::from_iter(self.scope.root(hugr));
Expand All @@ -180,6 +176,13 @@ impl<H: HugrMut<Node = Node>> ComposablePass<H> for RedundantOrderEdgesPass {
}
}

impl WithScope for RedundantOrderEdgesPass {
fn with_scope(mut self, scope: impl Into<PassScope>) -> Self {
self.scope = scope.into();
self
}
}

#[cfg(test)]
mod tests {
use hugr_core::builder::{Dataflow, DataflowHugr, FunctionBuilder, SubContainer};
Expand Down
Loading
Loading