Commit Graph

26 Commits

Author SHA1 Message Date
Quentin Colombet
a499216ab6 Reapply r263460: [SpillPlacement] Fix a quadratic behavior in spill placement.
Using Chandler's words from r265331:
This commit was greatly exacerbating PR17409 and effectively regressed
build time for lot of (very large) code when compiled with ASan or MSan.

PR17409 is fixed by r269249, so this is fine to reapply r263460.

Original commit message:
The bad behavior happens when we have a function with a long linear
chain of basic blocks, and have a live range spanning most of this
chain, but with very few uses.

Let say we have only 2 uses.

The Hopfield network is only seeded with two active blocks where the
uses are, and each iteration of the outer loop in
`RAGreedy::growRegion()` only adds two new nodes to the network due to
the completely linear shape of the CFG.  Meanwhile,
`SpillPlacer->iterate()` visits the whole set of discovered nodes, which
adds up to a quadratic algorithm.

This is an historical accident effect from r129188.

When the Hopfield network is expanding, most of the action is happening
on the frontier where new nodes are being added. The internal nodes in
the network are not likely to be flip-flopping much, or they will at
least settle down very quickly. This means that while
`SpillPlacer->iterate()` is recomputing all the nodes in the network, it
is probably only the two frontier nodes that are changing their output.

Instead of recomputing the whole network on each iteration, we can
maintain a SparseSet of nodes that need to be updated:

- `SpillPlacement::activate()` adds the node to the todo list.
- When a node changes value (i.e., `update()` returns true), its
  neighbors are added to the todo list.
- `SpillPlacement::iterate()` only updates the nodes in the list.

The result of Hopfield iterations is not necessarily exact. It should
converge to a local minimum, but there is no guarantee that it will find
a global minimum. It is possible that updating nodes in a different
order will cause us to switch to a different local minimum. In other
words, this is not NFC, but although I saw a few runtime improvements
and regressions when I benchmarked this change, those were side effects
and actually the performance change is in the noise as expected.

Huge thanks to Jakob Stoklund Olesen <stoklund@2pi.dk> for his
feedbacks, guidance and time for the review.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@270149 91177308-0d34-0410-b5e6-96231b3b80d8
2016-05-19 22:40:37 +00:00
Chandler Carruth
f0a58295f3 Revert r263460: [SpillPlacement] Fix a quadratic behavior in spill placement.
That commit looks wonderful and awesome. Sadly, it greatly exacerbates
PR17409 and effectively regresses build time for a lot of (very large)
code when compiled with ASan or MSan.

We thought this could be fixed forward by landing D15302 which at last
fixes that PR, but some issues were discovered and it looks like that
got reverted, so reverting this as well temporarily. As soon as the fix
for PR17409 lands and sticks, we should re-land this patch as it won't
trigger more significant test cases hitting that bug.

Many thanks to Quentin and Wei here as they're doing all the awesome
hard work!!!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@265331 91177308-0d34-0410-b5e6-96231b3b80d8
2016-04-04 18:57:50 +00:00
Quentin Colombet
058d8f885a [SpillPlacement] Fix a quadratic behavior in spill placement.
The bad behavior happens when we have a function with a long linear chain of
basic blocks, and have a live range spanning most of this chain, but with very
few uses.
Let say we have only 2 uses.
The Hopfield network is only seeded with two active blocks where the uses are,
and each iteration of the outer loop in `RAGreedy::growRegion()` only adds two
new nodes to the network due to the completely linear shape of the CFG.
Meanwhile, `SpillPlacer->iterate()` visits the whole set of discovered nodes,
which adds up to a quadratic algorithm.

This is an historical accident effect from r129188.

When the Hopfield network is expanding, most of the action is happening on the
frontier where new nodes are being added. The internal nodes in the network are
not likely to be flip-flopping much, or they will at least settle down very
quickly. This means that while `SpillPlacer->iterate()` is recomputing all the
nodes in the network, it is probably only the two frontier nodes that are
changing their output.

Instead of recomputing the whole network on each iteration, we can maintain a
SparseSet of nodes that need to be updated:

- `SpillPlacement::activate()` adds the node to the todo list.
- When a node changes value (i.e., `update()` returns true), its neighbors are
  added to the todo list.
- `SpillPlacement::iterate()` only updates the nodes in the list.

The result of Hopfield iterations is not necessarily exact. It should converge
to a local minimum, but there is no guarantee that it will find a global
minimum. It is possible that updating nodes in a different order will cause us
to switch to a different local minimum. In other words, this is not NFC, but
although I saw a few runtime improvements and regressions when I benchmarked
this change, those were side effects and actually the performance change is in
the noise as expected.

Huge thanks to Jakob Stoklund Olesen <stoklund@2pi.dk> for his feedbacks,
guidance and time for the review.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@263460 91177308-0d34-0410-b5e6-96231b3b80d8
2016-03-14 18:21:25 +00:00
Alexander Kornienko
c16fc54851 Use 'override/final' instead of 'virtual' for overridden methods
The patch is generated using clang-tidy misc-use-override check.

This command was used:

  tools/clang/tools/extra/clang-tidy/tool/run-clang-tidy.py \
    -checks='-*,misc-use-override' -header-filter='llvm|clang' \
    -j=32 -fix -format

http://reviews.llvm.org/D8925



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@234679 91177308-0d34-0410-b5e6-96231b3b80d8
2015-04-11 02:11:45 +00:00
Chandler Carruth
bbb28e7e98 Fix the threshold added in r186434 (a re-apply of r185393) and updaated
to be a ManagedStatic in r218163 to not be a global variable written and
read to from within the innards of SpillPlacement.

This will fix a really scary race condition for anyone that has two
copies of LLVM running spill placement concurrently. Yikes!

This will also fix a really significant compile time hit that r218163
caused because the spill placement threshold read is actually in the
*very* hot path of this code. The memory fence on each read was showing
up as huge compile time regressions when spilling is responsible for
most of the compile time. For example, optimizing sanitized code showed
over 50% compile time regressions here. =/

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@218921 91177308-0d34-0410-b5e6-96231b3b80d8
2014-10-02 22:23:14 +00:00
Benjamin Kramer
00e08fcaa0 Canonicalize header guards into a common format.
Add header guards to files that were missing guards. Remove #endif comments
as they don't seem common in LLVM (we can easily add them back if we decide
they're useful)

Changes made by clang-tidy with minor tweaks.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@215558 91177308-0d34-0410-b5e6-96231b3b80d8
2014-08-13 16:26:38 +00:00
Hans Wennborg
e4506cddc5 Increase the size of SpillPlacement::BlockFrequencies.
This SmallVector's median size during a Clang build was 7.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@215338 91177308-0d34-0410-b5e6-96231b3b80d8
2014-08-11 02:21:30 +00:00
Craig Topper
695aa80f07 [C++11] More 'nullptr' conversion. In some cases just using a boolean check instead of comparing to nullptr.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206356 91177308-0d34-0410-b5e6-96231b3b80d8
2014-04-16 04:21:27 +00:00
Craig Topper
9f998de891 [C++11] Add 'override' keyword to virtual methods that override their base class.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203220 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-07 09:26:03 +00:00
Michael Gottesman
1a938c2beb [block-freq] Store MBFI as a field on SpillPlacement so we can access it to get the entry frequency while processing data.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@197291 91177308-0d34-0410-b5e6-96231b3b80d8
2013-12-14 00:25:47 +00:00
Benjamin Kramer
55c06ae7af Revert "Give internal classes hidden visibility."
It works with clang, but GCC has different rules so we can't make all of those
hidden. This reverts commit r190534.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@190536 91177308-0d34-0410-b5e6-96231b3b80d8
2013-09-11 18:05:11 +00:00
Benjamin Kramer
15f387c93e Give internal classes hidden visibility.
Worth 100k on a linux/x86_64 Release+Asserts clang.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@190534 91177308-0d34-0410-b5e6-96231b3b80d8
2013-09-11 17:42:27 +00:00
Jakob Stoklund Olesen
03ef600623 Remove floats from live range splitting costs.
These floats all represented block frequencies anyway, so just use the
BlockFrequency class directly.

Some floating point computations remain in tryLocalSplit(). They are
estimating spill weights which are still floats.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186435 91177308-0d34-0410-b5e6-96231b3b80d8
2013-07-16 18:26:18 +00:00
Jakob Stoklund Olesen
6d9fe79afe Reapply r185393.
Original commit message:

Remove floating point computations from SpillPlacement.cpp.

Patch by Benjamin Kramer!

Use the BlockFrequency class instead of floats in the Hopfield network
computations. This rescales the node Bias field from a [-2;2] float
range to two block frequencies BiasN and BiasP pulling in opposite
directions. This construct has a more predictable behavior when block
frequencies saturate.

The per-node scaling factors are no longer necessary, assuming the block
frequencies around a bundle are consistent.

This patch can cause the register allocator to make different spilling
decisions. The differences should be small.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186434 91177308-0d34-0410-b5e6-96231b3b80d8
2013-07-16 18:26:15 +00:00
Jakob Stoklund Olesen
92879a8cb1 Revert (most of) r185393 and r185395.
"Remove floating point computations form SpillPlacement.cpp."

These commits caused test failures in lencod on clang-native-arm-lnt.

I suspect these changes are only exposing an existing issue, but
reverting anyway to keep the bots passing while we investigate.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185447 91177308-0d34-0410-b5e6-96231b3b80d8
2013-07-02 17:31:58 +00:00
Jakob Stoklund Olesen
74d2a3e1a0 Remove floating point computations form SpillPlacement.cpp.
Patch by Benjamin Kramer!

Use the BlockFrequency class instead of floats in the Hopfield network
computations. This rescales the node Bias field from a [-2;2] float
range to two block frequencies BiasN and BiasP pulling in opposite
directions. This construct has a more predictable behavior when block
frequencies saturate.

The per-node scaling factors are no longer necessary, assuming the block
frequencies around a bundle are consistent.

This patch can cause the register allocator to make different spilling
decisions. The differences should be small.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185393 91177308-0d34-0410-b5e6-96231b3b80d8
2013-07-01 23:19:39 +00:00
Jakob Stoklund Olesen
b87f91b063 Be more conservative when forming compact regions.
Apply twice the negative bias on transparent blocks when computing the
compact regions. This excludes loop backedges from the region when only
one of the loop blocks uses the register.

Previously, we would include the backedge in the region if the loop
preheader and the loop latch both used the register, but the loop header
didn't.

When both the header and latch blocks use the register, we still keep it
live on the backedge.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@136832 91177308-0d34-0410-b5e6-96231b3b80d8
2011-08-03 23:09:38 +00:00
Jakob Stoklund Olesen
0e0a8806d4 Extend the SpillPlacement interface with two new features.
The PrefBoth constraint is used for blocks that ideally want a live-in
value both on the stack and in a register. This would be used by a block
that has a use before interference forces a spill.

Secondly, add the ChangesValue flag to BlockConstraint. This tells
SpillPlacement if a live-in value on the stack can be reused as a
live-out stack value for free. If the block redefines the virtual
register, a spill would be required for that.

This extra information will be used by SpillPlacement to more accurately
calculate spill costs when a value can exist both on the stack and in a
register.

The simplest example is a basic block that reads the virtual register,
but doesn't change its value. Spilling around such a block requires a
reload, but no spill in the block.

The spiller already knows this, but the spill placer doesn't. That can
sometimes lead to suboptimal regions.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@136731 91177308-0d34-0410-b5e6-96231b3b80d8
2011-08-02 21:53:03 +00:00
Jakob Stoklund Olesen
e60f103d2d Add a simple method for marking blocks with interference in and out.
This method matches addLinks - All the listed blocks are considered to
have interference, so they add a negative bias to their bundles.

This could also be done by addConstraints, but that requires building a
separate BlockConstraint array.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@135844 91177308-0d34-0410-b5e6-96231b3b80d8
2011-07-23 03:10:19 +00:00
Jakob Stoklund Olesen
f4afdfc501 Build the Hopfield network incrementally when splitting global live ranges.
It is common for large live ranges to have few basic blocks with register uses
and many live-through blocks without any uses. This approach grows the Hopfield
network incrementally around the use blocks, completely avoiding checking
interference for some through blocks.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@129188 91177308-0d34-0410-b5e6-96231b3b80d8
2011-04-09 02:59:09 +00:00
Jakob Stoklund Olesen
7b41fbe872 Extract SpillPlacement::addLinks for handling the special transparent blocks.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@129079 91177308-0d34-0410-b5e6-96231b3b80d8
2011-04-07 17:27:46 +00:00
Jakob Stoklund Olesen
70d4370b47 Keep track of the number of positively biased nodes when adding constraints.
If there are no positive nodes, the algorithm can be aborted early.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@129021 91177308-0d34-0410-b5e6-96231b3b80d8
2011-04-06 19:14:00 +00:00
Jakob Stoklund Olesen
9efa2a263e Break the spill placement algorithm into three parts: prepare, addConstraints, and finish.
This will allow us to abort the algorithm early if it is determined to be futile.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@129020 91177308-0d34-0410-b5e6-96231b3b80d8
2011-04-06 19:13:57 +00:00
Jakob Stoklund Olesen
40a42a2cca Precompute block frequencies, pow() isn't free.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@126975 91177308-0d34-0410-b5e6-96231b3b80d8
2011-03-04 00:58:40 +00:00
Jakob Stoklund Olesen
b5fa933343 Add RAGreedy methods for splitting live ranges around regions.
Analyze the live range's behavior entering and leaving basic blocks. Compute an
interference pattern for each allocation candidate, and use SpillPlacement to
find an optimal region where that register can be live.

This code is still not enabled.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@123774 91177308-0d34-0410-b5e6-96231b3b80d8
2011-01-18 21:13:27 +00:00
Jakob Stoklund Olesen
8bfe50871f Add the SpillPlacement analysis pass.
This pass precomputes CFG block frequency information that can be used by the
register allocator to find optimal spill code placement.

Given an interference pattern, placeSpills() will compute which basic blocks
should have the current variable enter or exit in a register, and which blocks
prefer the stack.

The algorithm is ready to consume block frequencies from profiling data, but for
now it gets by with the static estimates used for spill weights.

This is a work in progress and still not hooked up to RegAllocGreedy.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122938 91177308-0d34-0410-b5e6-96231b3b80d8
2011-01-06 01:21:53 +00:00