-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Add a Global Value Numbering Pass #51120
base: master
Are you sure you want to change the base?
Conversation
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.
This is nice work, but doesn't work as is, because it doesn't consider the state of the heap.
For example, consider the following function:
function foo()
arr = Int[0]
a = arr[]
arr[] = 1
b = arr[]
(a, b)
end
As is, a
, and b
will be considered congruent and replaced with each other. However, this is incorrect.
That said, if we promote inaccessiblememonly to an IR flag, we could probably do this at least for things that don't touch memory, which might still be useful. Will have to wait until after #50805 though, since the flag space is currently full. |
I'm a bit confused, this seems to work fine for me. I see the same IR before the GVN pass, after the GVN pass and after "compact 2" on master (#95af5a08926).
Looking at the flags of |
Hmm, I may have been wrong, and IR_FLAG_CONSISTENT might be strong enough. I'll need to think about it again to make sure. |
Having thought about it some more, I think the semantics of IR_FLAG_CONSISTENT are probably sufficient to ensure that this bails on things that access non-consistent memory, so that part is probably fine.
e2951e1
to
9485da8
Compare
Does this fix #50887? |
Yes that was the inspiration for this. |
FTR, if you put a |
Also fixes bug when calling dominates, where firstedge is still set to 0 and thus out of bounds.
Also hopefully fix some indexing bugs.
It broke building Julia for some reason, ``` Segmentation fault in expression starting at compiler/compiler.jl:181 perform_lifting! at ./compiler/ssair/passes.jl:667 ```
Add fast path back in.
Prevent accidental use and make intent clearer
I think this should all be legal. Unfortunately iterating over `compact` makes this pass significantly slower, ~2x, as lots of time is spent in `renumber_ssa2!`.
This reverts commit 057d817. This broke building somehow and was quite slow anyways.
Address review. Fix bug in not wrapping result form `ssa_to_ssa` in a `SSAValue` before writing into `key` in `perform_symbolic_evaluation`
Fixes simplification of PhiNode to SSAValue by reverting indexing fix and setting `firstval` to equivalent SSAValue.
Indices are Int's I believe.
`sort!` is not defined for memory whilst bootstrapping.
This enables common subexpression elimination, fixes #50887. This is based on the NewGVN pass in LLVM.
A possible avenue for increasing the number of eliminations would be to implement code hoisting (eg. an expression that is also present in all predecessors to a block could be moved to the immediate dominator and then replaced; alternatively we could replace it with a phi node) or Partial Redundancy Elimination.
I'm not sure when it would be optimal for this pass to run, the effects of a function may allow a non inlined call to be eliminated completely whilst when inlined only parts may be deleted.
For small functions most of the time is spent on allocating two arrays (
ssa_to_ssa
and the array backingval_to_ssa
). For larger functions theget!
dominates, #51091 speeds upget!
2x. I don't think there any easy optimizations left, one possible avenue would be computing use lists (a list of every instruction in which aSSAValue
is used) and using that to not have to iterate over every instruction.