-
Notifications
You must be signed in to change notification settings - Fork 7
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
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1796 +/- ##
==========================================
- Coverage 86.63% 86.63% -0.01%
==========================================
Files 191 194 +3
Lines 34738 34885 +147
Branches 31571 31698 +127
==========================================
+ Hits 30097 30224 +127
- Misses 2940 2954 +14
- Partials 1701 1707 +6
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
can we deprecate remove_polyfuncs instead so we can include this in a non-breaking release? |
…and suppress warning on re-export
Yes, well, we can, and I have, but I admit I am not singing the praises of the tooling here - deprecate has a "since" tag for tools that might use it, but IIUC I have to guess what the next version number will be (i.e. the version in which it'll be deprecated); and the re-export causes problems (I have to suppress a warning there - I tried putting the |
31a7b44
to
08d9ebc
Compare
08d9ebc
to
e29ffa2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally looks good to me, just one comment mainly for my understanding.
hugr-passes/src/call_graph.rs
Outdated
fn traverse( | ||
h: &impl HugrView, | ||
node: Node, | ||
enclosing: NodeIndex<u32>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just for clarification - is enclosing
the node in the call graph corresponding to the node node
in the hugr or something else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's the (callgraph representation of) the nearest enclosing FuncDefn, so maybe the node's parent or an ancestor. I'll rename...
hugr-passes/src/call_graph.rs
Outdated
/// * If the Hugr is non-Module-rooted and `entry_points` is non-empty | ||
/// * If the Hugr is Module-rooted, but does not declare `main`, and `entry_points` is empty | ||
/// * If the Hugr is Module-rooted, and `entry_points` is non-empty but contains nodes that | ||
/// are not [FuncDefn](OpType::FuncDefn)s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As above, I don't think the second should panic.
I think the interface would be cleaner if entry_points
, maybe with a different name: must be FuncDefn
or FuncDecl
nodes that are immediate children of the root.
Now the first panic goes away, and the third would be an error with the offending nodes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to error, indeed. But FuncDefns inside a non-Module are invisible from outside (so unless you're gonna add new stuff inside the root - which you can do, but that's not linking, that's....arbitrary editing), so I've not allowed those as entry_points
. I could be persuaded, it'd be easier from a code perspective not to check, but it feels wrong :-!
hugr-passes/src/call_graph.rs
Outdated
let reachable = reachable_funcs(&CallGraph::new(h), h, entry_points).collect::<HashSet<_>>(); | ||
let unreachable = h | ||
.nodes() | ||
.filter(|n| h.get_optype(*n).is_func_defn() && !reachable.contains(n)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should remove dead FuncDecl
s too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done (no tests I admit)
Did you consider tracking in the Node weight whether it's a FuncDecl or a FuncDefn? |
No, good idea, done |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great, thank you.
Ok, so the big question here (@doug-q) is what happens to the "automatic"
Thoughts? |
I don't think breaking changes are a concern here. There are no users of this on non-module hugrs, so no users to break. I think this is my favoured option, I consider it not-onerous-at-all to ask callers to remove the dead polymorphic functions.
Agree that non-polymorphic functions being removed is bizarre. I think it would be better to do no removal.
I think it's fine to remove polymorphic FuncDefns where they were not previously children of the module. Having said that, I have a weak preference to not do so. To me it makes the pass strictly less useful:
For dead func removal: I would prefer a completely uniform treatment of Module and non-Module rooted HUGRs. In both cases:
I'm also ok with the pass as-is, if we need the additional flexibility afforded by the above we can change it then. For monomorphise: |
Ok - sounds reasonable - I would probably move to adding a callback/filter at the same time, but either way, this can be done later as a non-breaking change (it just allows more things), so no urgency, I'll leave it for now.
Ok, we agree that option 1 is the best target 👍 👍. I'm a bit hazy on the definition of breaking change (does that include runtime-breaking i.e. any behaviour change but not compile-breaking?), but erring on the side of caution I'll categorize dropping the automatic call to remove_polyfuncs as breaking, so not do that here - I've marked it with a TODO for the next release and kept the call to the now-deprecated remove_polyfuncs instead. |
Closes #1753.
remove_polyfuncs
preserved but deprecated, some uses in tests replaced to give coverage here.remove_polyfuncs
that currently follows monomorphization.