Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add CallGraph struct, and dead-function-removal pass #1796

Merged
merged 24 commits into from
Dec 24, 2024
Merged
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
3a0ee56
Add call_graph.rs, start writing docs
acl-cqc Dec 17, 2024
fcd5321
roots == Some(empty) meaningless => make non-Opt; pub CallGraphEdge; …
acl-cqc Dec 17, 2024
c497e4d
Remove remove_polyfuncs
acl-cqc Dec 17, 2024
c3dd939
Warn on missing docs
acl-cqc Dec 17, 2024
3bc33bc
Reinstate remove_polyfuncs but deprecate: guess next version number, …
acl-cqc Dec 17, 2024
1e95bc6
Test module entry_points
acl-cqc Dec 17, 2024
9061dc9
Move reachable_funcs outside of CallGraph
acl-cqc Dec 17, 2024
e29ffa2
Rename entry_points<->roots, use extend + assert
acl-cqc Dec 17, 2024
5f89cac
Merge branch 'main' into acl/remove_dead_funcs
acl-cqc Dec 17, 2024
4ee87aa
Merge 'origin/main' into acl/remove_dead_funcs, deprecation msgs
acl-cqc Dec 18, 2024
220bf67
Add RemoveDeadFuncsPass. TODO make remove_dead_funcs use ValidationLe…
acl-cqc Dec 18, 2024
466123d
enclosing{=>_func}, switch order, comment
acl-cqc Dec 18, 2024
f8008d9
Use Pass in tests
acl-cqc Dec 18, 2024
7ba818d
Add CallGraphNode enum and accessors
acl-cqc Dec 20, 2024
03cac78
Move remove_dead_funcs stuff into separate file
acl-cqc Dec 20, 2024
e39c279
Add (rather useless atm) error type
acl-cqc Dec 20, 2024
3f1caa8
switch from Bfs to Dfs
acl-cqc Dec 20, 2024
c47a99e
Don't auto-insert 'main'; error not panic on bad entry-point
acl-cqc Dec 20, 2024
4f36e56
Sneakily-without-tests remove FuncDecls too
acl-cqc Dec 20, 2024
eaca2e7
Use petgraph::visit::Walker rather than std::iter::from_fn
acl-cqc Dec 20, 2024
393a476
dead_func_removal -> dead_funcs
acl-cqc Dec 23, 2024
53389c7
Reinstate monomorphize calling remove_polyfuncs with note re. planned…
acl-cqc Dec 23, 2024
6b496f1
fmt
acl-cqc Dec 23, 2024
4a07dee
Also deprecate remove_polyfuncs_ref; fix docs
acl-cqc Dec 23, 2024
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
Prev Previous commit
Next Next commit
Add (rather useless atm) error type
acl-cqc committed Dec 20, 2024
commit e39c2794578d1865c1bbdfa91e3a0008bb6c37e4
20 changes: 16 additions & 4 deletions hugr-passes/src/dead_func_removal.rs
Original file line number Diff line number Diff line change
@@ -11,6 +11,15 @@ use crate::validation::{ValidatePassError, ValidationLevel};

use super::call_graph::{CallGraph, CallGraphNode};

#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
/// Errors produced by [ConstantFoldPass].
pub enum RemoveDeadFuncsError {
#[error(transparent)]
#[allow(missing_docs)]
ValidationError(#[from] ValidatePassError),
}

fn reachable_funcs<'a>(
cg: &'a CallGraph,
h: &'a impl HugrView,
@@ -68,10 +77,9 @@ impl RemoveDeadFuncsPass {
}

/// Runs the pass (see [remove_dead_funcs]) with this configuration
pub fn run<H: HugrMut>(&self, hugr: &mut H) -> Result<(), ValidatePassError> {
pub fn run<H: HugrMut>(&self, hugr: &mut H) -> Result<(), RemoveDeadFuncsError> {
self.validation.run_validated_pass(hugr, |hugr: &mut H, _| {
remove_dead_funcs(hugr, self.entry_points.iter().cloned());
Ok(())
remove_dead_funcs(hugr, self.entry_points.iter().cloned())
})
}
}
@@ -96,7 +104,10 @@ impl RemoveDeadFuncsPass {
/// [FuncDefn]: hugr_core::ops::OpType::FuncDefn
/// [LoadFunction]: hugr_core::ops::OpType::LoadFunction
/// [Module]: hugr_core::ops::OpType::Module
pub fn remove_dead_funcs(h: &mut impl HugrMut, entry_points: impl IntoIterator<Item = Node>) {
pub fn remove_dead_funcs(
h: &mut impl HugrMut,
entry_points: impl IntoIterator<Item = Node>,
) -> Result<(), RemoveDeadFuncsError> {
let reachable = reachable_funcs(&CallGraph::new(h), h, entry_points).collect::<HashSet<_>>();
let unreachable = h
.nodes()
@@ -105,6 +116,7 @@ pub fn remove_dead_funcs(h: &mut impl HugrMut, entry_points: impl IntoIterator<I
for n in unreachable {
h.remove_subtree(n);
}
Ok(())
}

#[cfg(test)]
6 changes: 3 additions & 3 deletions hugr-passes/src/monomorphize.rs
Original file line number Diff line number Diff line change
@@ -47,7 +47,7 @@ fn monomorphize_ref(h: &mut impl HugrMut) {
if !is_polymorphic_funcdefn(h.get_optype(root)) {
mono_scan(h, root, None, &mut HashMap::new());
if !h.get_optype(root).is_module() {
remove_dead_funcs(h, []);
remove_dead_funcs(h, []).unwrap(); // no-entry-points always succeeds
}
}
}
@@ -493,7 +493,7 @@ mod test {
assert_eq!(mono2, mono); // Idempotent

let mut nopoly = mono;
remove_dead_funcs(&mut nopoly, []);
remove_dead_funcs(&mut nopoly, [])?;
let mut funcs = list_funcs(&nopoly);

assert!(funcs.values().all(|(_, fd)| !is_polymorphic(fd)));
@@ -715,7 +715,7 @@ mod test {
};

MonomorphizePass::default().run(&mut hugr).unwrap();
remove_dead_funcs(&mut hugr, []);
remove_dead_funcs(&mut hugr, []).unwrap();

let funcs = list_funcs(&hugr);
assert!(funcs.values().all(|(_, fd)| !is_polymorphic(fd)));