[GHC] #16243: Improve fregs-graph.
GHC
ghc-devs at haskell.org
Sun Jan 27 00:29:23 UTC 2019
#16243: Improve fregs-graph.
-------------------------------------+-------------------------------------
Reporter: AndreasK | Owner: (none)
Type: task | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 8.6.3
(CodeGen) |
Keywords: fregs-graph | Operating System: Unknown/Multiple
Architecture: | Type of failure: None/Unknown
Unknown/Multiple |
Test Case: | Blocked By:
Blocking: | Related Tickets:
Differential Rev(s): | Wiki Page:
-------------------------------------+-------------------------------------
I'm creating this as a way to keep track of shortcomings of the current
implementation.
Some of these are directly taken from TODOS, other are my own opinions.
= Things that could be looked at.
== Compress spill slots.
Currently we assign each vreg a fixed spill slot. This is terrible for
cache performance.
It's possible to end up with sequences like this:
{{{#!asm
block_ca01_info:
_ca01:
movq 16(%rbp),%r14
movq 24(%rbp),%rax
movq %rax,144(%rsp)
movq 32(%rbp),%rsi
movq 40(%rbp),%rdi
movq 64(%rbp),%rbx
movq 56(%rbp),%rax
movq %rax,208(%rsp)
movq 48(%rbp),%rax
movq %rax,168(%rsp)
movq 8(%rbp),%rax
movq %rax,216(%rsp)
addq $8,%rbp
}}}
Which splits spill slots over multiple cache lines increasing cache
pressure.
Things possibly worth trying:
* Assign spill slots in the order they appear - hopefully reducing the
average spread within code blocks.
* Dynamically assign vregs to spill slots.
For the later if we have large independent subgraphs we will sometimes get
away with using far fewer slots.
The reason simply being that non overlapping vregs can share spill slots.
Doing this in an efficient manner however isn't easy.
== We sometimes load + spill vregs when we could use memory addressing.
One example I've seen a few times in nofib is this:
{{{
movq 208(%rsp),%rax
incq %rax
movq %rax,208(%rsp)
}}}
Which we should replace with a single `inc` operating on memory.
== Lift the stack size limit.
There is already a patch
[https://gitlab.haskell.org/ghc/ghc/merge_requests/219 in flight].
== Revisit spill costs.
Currently the allocator always spills the longest live range. Which often
works but is certainly not a great metric.
Ideas:
=== Consider loop membership.
At least for x86/64 this would be easy to achieve on basic block
granularity using the CFG that is also used for block layout.
=== Revisit chaitins cost model.
There have been major changes to cpus (amd64 becoming the norm) and the
backend
so at a minimum this cost model should be reevaluated.
== Try splitting long live ranges instead of simply spilling the complete
live range.
After all long live ranges were the original reason to switch to a life
range only based cost heuristic.
== Use a different spill algorithm altogether.
Maybe Chows live range splitting based approach would be an option.
See "The priority based coloring approach to register allocation" for
details.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/16243>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list