OnceReduction: Optimize idempotent functions#8369
Conversation
tlively
left a comment
There was a problem hiding this comment.
I wonder how complicated it would be to do a proper interprocedural control flow analysis that would let us find all idempotent operations (e.g. idempotent function calls, sets of globals that are only ever set to a single value, etc.) dominated by previous copies of the same operation. That would let us uniformly optimize all the idempotent operations we could want without special-casing "once" functions or being limited to single basic blocks.
| // When we see an idempotent-marked function, which as mentioned above is | ||
| // effectively "once" but does not have an explicit global controlling it, we | ||
| // create a fake global name for it to use here. That gives each function we | ||
| // can optimize a unique global name for our optimizer to track. That is, the | ||
| // global name is a real global for ones we found a global for, and for | ||
| // idempotent functions, it is a unique name that is not an actual global. |
There was a problem hiding this comment.
As a drive-by, it might be nice to rename this to onceFuncGlobals, since the values are globals.
| ;; We can remove both of these second calls. | ||
| (call $idempotent) | ||
| (call $idempotent2) |
There was a problem hiding this comment.
It's not clear to me that we should allow removing calls to idempotent functions when there are arbitrary side effects between the calls and their preceding calls. For example, gcc's pure annotation does not allow optimization when there are intervening side effects.
There was a problem hiding this comment.
I commented on the discussion to get feedback:
There was a problem hiding this comment.
If we can't optimize like this, then the OnceReduction pass may not be the right place to do this, as "once" functions can be optimized in this way.
There was a problem hiding this comment.
I added a comment to clarify that in the linked discussion we are leaning towards allowing this optimization.
(We can reconsider later if this is a problem, and perhaps add a parameter to this intrinsic, as both use cases might matter.)
OnceReduction already does that: it uses a DomTree to find all dominated second calls, and removes them. Maybe you're thinking of LocalCSE which is limited to a single basic block? It is worth improving that one. |
OnceReduction finds functions that execute once, then removes later
calls to them,
This PR makes it do the same for idempotent-marked calls.
So far this only handles the simple case of no params or results.