#
4f567207 |
| 27-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
Prevent rotating the blocks of a loop (and thus getting a backedge to be fallthrough) in cases where we might fail to rotate an exit to an outer loop onto the end of the loop chain.
Having *some* ro
Prevent rotating the blocks of a loop (and thus getting a backedge to be fallthrough) in cases where we might fail to rotate an exit to an outer loop onto the end of the loop chain.
Having *some* rotation, but not performing this rotation, is the primary fix of thep performance regression with -enable-block-placement for Olden/em3d (a whopping 30% regression). Still working on reducing the test case that actually exercises this and the new rotation strategy out of this code, but I want to check if this regresses other test cases first as that may indicate it isn't the correct fix.
llvm-svn: 145195
show more ...
|
#
03adbd46 |
| 27-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
Take two on rotating the block ordering of loops. My previous attempt was centered around the premise of laying out a loop in a chain, and then rotating that chain. This is good for preserving contig
Take two on rotating the block ordering of loops. My previous attempt was centered around the premise of laying out a loop in a chain, and then rotating that chain. This is good for preserving contiguous layout, but bad for actually making sane rotations. In order to keep it safe, I had to essentially make it impossible to rotate deeply nested loops. The information needed to correctly reason about a deeply nested loop is actually available -- *before* we layout the loop. We know the inner loops are already fused into chains, etc. We lose information the moment we actually lay out the loop.
The solution was the other alternative for this algorithm I discussed with Benjamin and some others: rather than rotating the loop after-the-fact, try to pick a profitable starting block for the loop's layout, and then use our existing layout logic. I was worried about the complexity of this "pick" step, but it turns out such complexity is needed to handle all the important cases I keep teasing out of benchmarks.
This is, I'm afraid, a bit of a work-in-progress. It is still misbehaving on some likely important cases I'm investigating in Olden. It also isn't really tested. I'm going to try to craft some interesting nested-loop test cases, but it's likely to be extremely time consuming and I don't want to go there until I'm sure I'm testing the correct behavior. Sadly I can't come up with a way of getting simple, fine grained test cases for this logic. We need complex loop structures to even trigger much of it.
llvm-svn: 145183
show more ...
|
#
9e466841 |
| 27-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
Fix an impressive type-o / spell-o Duncan noticed.
llvm-svn: 145181
|
#
a0545809 |
| 27-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
Rework a bit of the implementation of loop block rotation to not rely so heavily on AnalyzeBranch. That routine doesn't behave as we want given that rotation occurs mid-way through re-ordering the fu
Rework a bit of the implementation of loop block rotation to not rely so heavily on AnalyzeBranch. That routine doesn't behave as we want given that rotation occurs mid-way through re-ordering the function. Instead merely check that there are not unanalyzable branching constructs present, and then reason about the CFG via successor lists. This actually simplifies my mental model for all of this as well.
The concrete result is that we now will rotate more loop chains. I've added a test case from Olden highlighting the effect. There is still a bit more to do here though in order to regain all of the performance in Olden.
llvm-svn: 145179
show more ...
|
#
9ffb97e6 |
| 27-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
Introduce a loop block rotation optimization to the new block placement pass. This is designed to achieve one of the important optimizations that the old code placement pass did, but more simply.
Th
Introduce a loop block rotation optimization to the new block placement pass. This is designed to achieve one of the important optimizations that the old code placement pass did, but more simply.
This is a somewhat rough and *very* conservative version of the transform. We could get a lot fancier here if there are profitable cases to do so. In particular, this only looks for a single pattern, it insists that the loop backedge being rotated away is the last backedge in the chain, and it doesn't provide any means of doing better in-loop placement due to the rotation. However, it appears that it will handle the important loops I am finding in the LLVM test suite.
llvm-svn: 145158
show more ...
|
#
7adee1a0 |
| 24-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
Fix a silly use-after-free issue. A much earlier version of this code need lots of fanciness around retaining a reference to a Chain's slot in the BlockToChain map, but that's all gone now. We can ju
Fix a silly use-after-free issue. A much earlier version of this code need lots of fanciness around retaining a reference to a Chain's slot in the BlockToChain map, but that's all gone now. We can just go directly to allocating the new chain (which will update the mapping for us) and using it.
Somewhat gross mechanically generated test case replicates the issue Duncan spotted when actually testing this out.
llvm-svn: 145120
show more ...
|
#
d394bafd |
| 24-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
When adding blocks to the list of those which no longer have any CFG conflicts, we should only be adding the first block of the chain to the list, lest we try to merge into the middle of that chain.
When adding blocks to the list of those which no longer have any CFG conflicts, we should only be adding the first block of the chain to the list, lest we try to merge into the middle of that chain. Most of the places we were doing this we already happened to be looking at the first block, but there is no reason to assume that, and in some cases it was clearly wrong.
I've added a couple of tests here. One already worked, but I like having an explicit test for it. The other is reduced from a test case Duncan reduced for me and used to crash. Now it is handled correctly.
llvm-svn: 145119
show more ...
|
#
99fe42fb |
| 23-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
Relax an invariant that block placement was trying to assert a bit further. This invariant just wasn't going to work in the face of unanalyzable branches; we need to be resillient to the phenomenon o
Relax an invariant that block placement was trying to assert a bit further. This invariant just wasn't going to work in the face of unanalyzable branches; we need to be resillient to the phenomenon of chains poking into a loop and poking out of a loop. In fact, we already were, we just needed to not assert on it.
This was found during a bootstrap with block placement turned on.
llvm-svn: 145100
show more ...
|
#
4a87aa0c |
| 23-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
Fix a crash in block placement due to an inner loop that happened to be reversed in the function's original ordering, and we happened to encounter it while handling an outer unnatural CFG structure.
Fix a crash in block placement due to an inner loop that happened to be reversed in the function's original ordering, and we happened to encounter it while handling an outer unnatural CFG structure.
Thanks to the test case reduced from GCC's source by Benjamin Kramer. This may also fix a crasher in gzip that Duncan reduced for me, but I haven't yet gotten to testing that one.
llvm-svn: 145094
show more ...
|
#
18dfac38 |
| 20-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
The logic for breaking the CFG in the presence of hot successors didn't properly account for the *global* probability of the edge being taken. This manifested as a very large number of unconditional
The logic for breaking the CFG in the presence of hot successors didn't properly account for the *global* probability of the edge being taken. This manifested as a very large number of unconditional branches to blocks being merged against the CFG even though they weren't particularly hot within the CFG.
The fix is to check whether the edge being merged is both locally hot relative to other successors for the source block, and globally hot compared to other (unmerged) predecessors of the destination block.
This introduces a new crasher on GCC single-source, but it's currently behind a flag, and Ben has offered to work on the reduction. =]
llvm-svn: 145010
show more ...
|
#
f3dc9eff |
| 19-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
Move the handling of unanalyzable branches out of the loop-driven chain formation phase and into the initial walk of the basic blocks. We essentially pre-merge all blocks where unanalyzable fallthrou
Move the handling of unanalyzable branches out of the loop-driven chain formation phase and into the initial walk of the basic blocks. We essentially pre-merge all blocks where unanalyzable fallthrough exists, as we won't be able to update the terminators effectively after any reorderings. This is quite a bit more principled as there may be CFGs where the second half of the unanalyzable pair has some analyzable predecessor that gets placed first. Then it may get placed next, implicitly breaking the unanalyzable branch even though we never even looked at the part that isn't analyzable. I've included a test case that triggers this (thanks Benjamin yet again!), and I'm hoping to synthesize some more general ones as I dig into related issues.
Also, to make this new scheme work we have to be able to handle branches into the middle of a chain, so add this check. We always fallback on the incoming ordering.
Finally, this starts to really underscore a known limitation of the current implementation -- we don't consider broken predecessors when merging successors. This can caused major missed opportunities, and is something I'm planning on looking at next (modulo more bug reports).
llvm-svn: 144994
show more ...
|
Revision tags: llvmorg-3.0.0, llvmorg-3.0.0-rc4 |
|
#
9b548a7f |
| 15-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
Rather than trying to use the loop block sequence *or* the function block sequence when recovering from unanalyzable control flow constructs, *always* use the function sequence. I'm not sure why I ev
Rather than trying to use the loop block sequence *or* the function block sequence when recovering from unanalyzable control flow constructs, *always* use the function sequence. I'm not sure why I ever went down the path of trying to use the loop sequence, it is fundamentally not the correct sequence to use. We're trying to preserve the incoming layout in the cases of unreasonable control flow, and that is only encoded at the function level. We already have a filter to select *exactly* the sub-set of blocks within the function that we're trying to form into a chain.
The resulting code layout is also significantly better because of this. In several places we were ending up with completely unreasonable control flow constructs due to the ordering chosen by the loop structure for its internal storage. This change removes a completely wasteful vector of basic blocks, saving memory allocation in the common case even though it costs us CPU in the fairly rare case of unnatural loops. Finally, it fixes the latest crasher reduced out of GCC's single source. Thanks again to Benjamin Kramer for the reduction, my bugpoint skills failed at it.
llvm-svn: 144627
show more ...
|
#
fd9b4d98 |
| 14-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
It helps to deallocate memory as well as allocate it. =] This actually cleans up all the chains allocated during the processing of each function so that for very large inputs we don't just grow memor
It helps to deallocate memory as well as allocate it. =] This actually cleans up all the chains allocated during the processing of each function so that for very large inputs we don't just grow memory usage without bound.
llvm-svn: 144533
show more ...
|
#
0a31d149 |
| 14-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
Remove an over-eager assert that was firing on one of the ARM regression tests when I forcibly enabled block placement.
It is apparantly possible for an unanalyzable block to fallthrough to a non-lo
Remove an over-eager assert that was firing on one of the ARM regression tests when I forcibly enabled block placement.
It is apparantly possible for an unanalyzable block to fallthrough to a non-loop block. I don't actually beleive this is correct, I believe that 'canFallThrough' is returning true needlessly for the code construct, and I've left a bit of a FIXME on the verification code to try to track down why this is coming up.
Anyways, removing the assert doesn't degrade the correctness of the algorithm.
llvm-svn: 144532
show more ...
|
#
0af6a0bb |
| 14-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
Begin chipping away at one of the biggest quadratic-ish behaviors in this pass. We're leaving already merged blocks on the worklist, and scanning them again and again only to determine each time thro
Begin chipping away at one of the biggest quadratic-ish behaviors in this pass. We're leaving already merged blocks on the worklist, and scanning them again and again only to determine each time through that indeed they aren't viable. We can instead remove them once we're going to have to scan the worklist. This is the easy way to implement removing them. If this remains on the profile (as I somewhat suspect it will), we can get a lot more clever here, as the worklist's order is essentially irrelevant. We can use swapping and fold the two loops to reduce overhead even when there are many blocks on the worklist but only a few of them are removed.
llvm-svn: 144531
show more ...
|
#
84cd44c7 |
| 14-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
Under the hood, MBPI is doing a linear scan of every successor every time it is queried to compute the probability of a single successor. This makes computing the probability of every successor of a
Under the hood, MBPI is doing a linear scan of every successor every time it is queried to compute the probability of a single successor. This makes computing the probability of every successor of a block in sequence... really really slow. ;] This switches to a linear walk of the successors rather than a quadratic one. One of several quadratic behaviors slowing this pass down.
I'm not really thrilled with moving the sum code into the public interface of MBPI, but I don't (at the moment) have ideas for a better interface. My direction I'm thinking in for a better interface is to have MBPI actually retain much more state and make *all* of these queries cheap. That's a lot of work, and would require invasive changes. Until then, this seems like the least bad (ie, least quadratic) solution. Suggestions welcome.
llvm-svn: 144530
show more ...
|
#
1071cfa4 |
| 14-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
Teach machine block placement to cope with unnatural loops. These don't get loop info structures associated with them, and so we need some way to make forward progress selecting and placing basic blo
Teach machine block placement to cope with unnatural loops. These don't get loop info structures associated with them, and so we need some way to make forward progress selecting and placing basic blocks. The technique used here is pretty brutal -- it just scans the list of blocks looking for the first unplaced candidate. It keeps placing blocks like this until the CFG becomes tractable.
The cost is somewhat unfortunate, it requires allocating a vector of all basic block pointers eagerly. I have some ideas about how to simplify and optimize this, but I'm trying to get the logic correct first.
Thanks to Benjamin Kramer for the reduced test case out of GCC. Sadly there are other bugs that GCC is tickling that I'm reducing and working on now.
llvm-svn: 144516
show more ...
|
#
c4a2cb34 |
| 13-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
Cleanup some 80-columns violations and poor formatting. These snuck by when I was reading through the code for style.
llvm-svn: 144513
|
#
8e1d9067 |
| 13-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
Enhance the assertion mechanisms in place to make it easier to catch when we fail to place all the blocks of a loop. Currently this is happening for unnatural loops, and this logic helps more immedia
Enhance the assertion mechanisms in place to make it easier to catch when we fail to place all the blocks of a loop. Currently this is happening for unnatural loops, and this logic helps more immediately point to the problem.
llvm-svn: 144504
show more ...
|
#
0bb42c0f |
| 13-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
Teach MBP to force-merge layout successors for blocks with unanalyzable branches that also may involve fallthrough. In the case of blocks with no fallthrough, we can still re-order the blocks profita
Teach MBP to force-merge layout successors for blocks with unanalyzable branches that also may involve fallthrough. In the case of blocks with no fallthrough, we can still re-order the blocks profitably. For example instruction decoding will in some cases continue past an indirect jump, making laying out its most likely successor there profitable.
Note, no test case. I don't know how to write a test case that exercises this logic, but it matches the described desired semantics in discussions with Jakob and others. If anyone has a nice example of IR that will trigger this, that would be lovely.
Also note, there are still assertion failures in real world code with this. I'm digging into those next, now that I know this isn't the cause.
llvm-svn: 144499
show more ...
|
#
f9213fe7 |
| 13-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
Hoist another gross nested loop into a helper method.
llvm-svn: 144498
|
#
eb4ec3ae |
| 13-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
Add a missing doxygen comment for a helper method.
llvm-svn: 144497
|
#
b336172f |
| 13-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
Hoist a nested loop into its own method.
llvm-svn: 144496
|
#
8d150789 |
| 13-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
Rewrite #3 of machine block placement. This is based somewhat on the second algorithm, but only loosely. It is more heavily based on the last discussion I had with Andy. It continues to walk from the
Rewrite #3 of machine block placement. This is based somewhat on the second algorithm, but only loosely. It is more heavily based on the last discussion I had with Andy. It continues to walk from the inner-most loop outward, but there is a key difference. With this algorithm we ensure that as we visit each loop, the entire loop is merged into a single chain. At the end, the entire function is treated as a "loop", and merged into a single chain. This chain forms the desired sequence of blocks within the function. Switching to a single algorithm removes my biggest problem with the previous approaches -- they had different behavior depending on which system triggered the layout. Now there is exactly one algorithm and one basis for the decision making.
The other key difference is how the chain is formed. This is based heavily on the idea Andy mentioned of keeping a worklist of blocks that are viable layout successors based on the CFG. Having this set allows us to consistently select the best layout successor for each block. It is expensive though.
The code here remains very rough. There is a lot that needs to be done to clean up the code, and to make the runtime cost of this pass much lower. Very much WIP, but this was a giant chunk of code and I'd rather folks see it sooner than later. Everything remains behind a flag of course.
I've added a couple of tests to exercise the issues that this iteration was motivated by: loop structure preservation. I've also fixed one test that was exhibiting the broken behavior of the previous version.
llvm-svn: 144495
show more ...
|
Revision tags: llvmorg-3.0.0-rc3 |
|
#
ae4e800c |
| 02-Nov-2011 |
Chandler Carruth <chandlerc@gmail.com> |
Begin collecting some of the statistics for block placement discussed on the mailing list. Suggestions for other statistics to collect would be awesome. =]
Currently these are implemented as a separ
Begin collecting some of the statistics for block placement discussed on the mailing list. Suggestions for other statistics to collect would be awesome. =]
Currently these are implemented as a separate pass guarded by a separate flag. I'm not thrilled by that, but I wanted to be able to collect the statistics for the old code placement as well as the new in order to have a point of comparison. I'm planning on folding them into the single pass if / when there is only one pass of interest.
llvm-svn: 143537
show more ...
|