For controlling what interfaces an optimization must preserve (typically functions, but also perhaps the entrypoint if a DFG)
We may want ability to tell passes not to waste compute time on optimizing other parts, but this is less of an issue - few classical compilers bother very much! Instead the preferred way is to split your Hugr into several, optimize them separately/differently, and then link them back together.
Hence, propose to combine these two concepts into a single enum:
#[non_exhaustive]
enum OptimizationScope<N> {
SpecificFuncs (Vec<N>), // heavily discouraged because serialization renumbers - maybe remove altogether and require setting visibility??
// maybe SpecificPublicFunctions(Vec<String>), etc. etc.
AllPublic (include_entrypoint: bool), // true has no effect if entrypoint==module-root
All (include_entrypoint: bool), // true has no effect if entrypoint==module-root
Aggressive, // if entrypoint is module root, then AllPublic(false); else just entrypoint
Local, // use entrypoint, do not recurse (possibly error on module-entrypoint?)
}
Default == All(true) as this is pretty conservative. Indeed, perhaps too conservative: All means DeadFunctionRemoval can't remove unused private functions! (It makes no sense to allow removal of functions but not alteration; a pass could create a new function, change all calls to use that, and remove the old one!)
Add ComposablePass::set_scope (breaking change as new pass method)
Note SpecificFuncs requires them all to be top-level/module children, so cannot express arbitrary entrypoint
There is some method to_nodes<H: HugrView>(&OptimizationScope, &H) -> Vec<H::Node> (all elements of which are not guaranteed to be module children), but this might be hidden. (Or, this might want to return 2*Vec: places to examine/transform, and funcs whose semantics to preserve - the former must be a superset of the latter but usually plus reachable funcs - e.g. if we are preserving interface of public funcs, we might still butcher up the private ones according to how they are used.)
For controlling what interfaces an optimization must preserve (typically functions, but also perhaps the entrypoint if a DFG)
We may want ability to tell passes not to waste compute time on optimizing other parts, but this is less of an issue - few classical compilers bother very much! Instead the preferred way is to split your Hugr into several, optimize them separately/differently, and then link them back together.
Hence, propose to combine these two concepts into a single enum:
Default==All(true)as this is pretty conservative. Indeed, perhaps too conservative:Allmeans DeadFunctionRemoval can't remove unused private functions! (It makes no sense to allow removal of functions but not alteration; a pass could create a new function, change all calls to use that, and remove the old one!)Add ComposablePass::set_scope (breaking change as new pass method)
Note SpecificFuncs requires them all to be top-level/module children, so cannot express arbitrary entrypoint
There is some method
to_nodes<H: HugrView>(&OptimizationScope, &H) -> Vec<H::Node>(all elements of which are not guaranteed to be module children), but this might be hidden. (Or, this might want to return 2*Vec: places to examine/transform, and funcs whose semantics to preserve - the former must be a superset of the latter but usually plus reachable funcs - e.g. if we are preserving interface of public funcs, we might still butcher up the private ones according to how they are used.)