Open justinchuby opened 1 year ago
A few more comments:
While the data-structure can provide minimal guarantees in the presence of modifications while iterating. However, designers of optimizations still need to think about the interaction between different optimizations if we want to combine them.
Taking a step back, one key question is how to combine multiple optimizations. We can run them one after another, which is straight-forward. However, we encounter situations where two optimizations can enable each other. Eg., replacing and if-node by its then (or else) branch when its condition is a constant can enable us to discover further constants downstream. Conversely, discovering new constants can enable if-node optimization.
This makes it necessary to "compose" optimizations: that is, as we iterate through nodes, we apply a sequence of optimizations to the visited node (one after another).
Where this gets complicated is when some optimizations are dependent on information computed via analyses that are impacted by the transformations performed by some other optimization.
Bottomline, sometimes optimizations need to combined or split into different passes based on a careful analysis of their mutual dependences. For example, the constant-folder does not try to eliminate dead-code ... dead-code elimination is done as a separate pass in the end, since it helps simplify the optimization design and implementation.
@justinchuby : some thoughts:
flatten ( replacement(x) for x in nodes )
(functional style, but incurs cost proportional to entire list)