LoopSafetyInfo, which is used in LICM was very conservative - whenever
there was an instruction that could have throw it assumed that
none of the instructions in the header is guaranteed to execute.
With this patch we are able to hoist instructions based on the stronger
execution guarantee, and preserve metadata.
Details
Diff Detail
- Repository
- rL LLVM
- Build Status
Buildable 16860 Build 16860: arc lint + arc unit
Event Timeline
Looks good, but you may want to wait for a green flag from someone more familiar with loops.
include/llvm/Analysis/MustExecute.h | ||
---|---|---|
45 ↗ | (On Diff #140594) | AssertingVH<Instruction>, to catch any invalidation bugs. |
include/llvm/Analysis/MustExecute.h | ||
---|---|---|
45 ↗ | (On Diff #140594) | That is excellent comment, I haven't thought about possibility of moving and deleting the instructions from header. |
llvm/include/llvm/Analysis/MustExecute.h | ||
---|---|---|
44 | This still tracks neither deletions nor RAUWs. | |
50 | nit: Guarantee -> Guaranteed | |
llvm/lib/Analysis/MustExecute.cpp | ||
278 | Wouldn't checking isGuaranteedToTransferExecutionToSuccessor(&HeaderInstr) be somewhat less error-prone wrt. deletions, RAUWs etc., especially since the header is already being scanned from the beginning? |
Philip, can you take a look at this since I saw you have made some improvements to this code recently?
Specifically NOT okay to land as is. The quadratic complexity concern is a real one and the window chosen here is very likely too large.
And if you're concern is purely LICM, this patch is no longer needed at all. I introduced a surgical fix for LICM which solves this without the need for O(n^2) work. Unfortunately, that approach only works for LICM (not, store promotion or other users of MustExecute). Unfortunately, as you've found there don't appear to be any good cheap ways to ask ordering questions around instructions within a basic block. If there were, we could just keep track of the first throwing instruction.
You could consider trying to wire in the caching needed for OrderedBasicBlock, but again, that's only needed if you're concern is different consumer than LICM
llvm/lib/Analysis/MustExecute.cpp | ||
---|---|---|
263 | Purely code style: this duplicates similar code in ValueTracking. Even if we were okay going this direction, we should merge not duplicate. |
We created an abstraction for the ordered basic block caching that works and is used in a few passes.
Transforms/Utils/OrderedInstructions.h
I suspect it's in a bad place for people to find it, and should be next to OrderedBasicBlock (or just make OrderedBasicBlock a hidden implementation detail, since all uses i can find really are doing it for multiple BB's anyway)
This approach was to satisfy this patch:
https://reviews.llvm.org/D45151
I will check in the meantime if your fix is enough to fix it, but I am concerned that it might be not enough.
OK, so it seems that at least the tests in the second patch passes without this patch, so I am fine with committing it without this one for one (also Philip if you could take a look at that patch I would be grateful)
I am worried about cases, where the first instruction does not throw, but it we can't hoist it (e.g. it depends on the loop phi) and after that, there is an instruction that can be hoisted.
Right now we bail out if we reach more than 66 instructions. Is there a lower number that is greater than 1 that you think would be small enough to slow down the compilation imperceptibly, like 10?
llvm/lib/Analysis/MustExecute.cpp | ||
---|---|---|
278 | Maybe introduce constant like "unsigned XZThreshoild = 66" with comment why 66 instead of a magic number? |
This still tracks neither deletions nor RAUWs.