[llvm-commits] Tuning LLVM Greedy Register Allocator to optimize for code size when targeting ARM Thumb 2 instruction set

Zino Benaissa zinob at codeaurora.org
Tue Jan 31 14:39:56 PST 2012




>>> As I am reading your changes to the eviction policy, you are completely
>>> replacing spill weights with a code size metric for live ranges with
>>> Virteg.bytes > 0. Is that the intention?

>> It depends why the eviction is invoked. Currently there are three reasons
>> for invoking eviction: enabling coalescing, preventing spill/split,
>> preventing a costPerUse register. Note all these evections where already
put
>> in place before my heuristic.
>> 1) Both for coalescing or for preventing split/spill: VirtReg.bytes=0 and
>> the heuristic is ignored and only the pair <hint,weight> is considered.
>> Whatever were put in place is still managing these type of evictions. 
>> 2) This heuristic is ON only when a candidate gets a register that has a
>> CostPerUse. In this case, When the RA attempts to trade it for a register
>> with no cost, Now with this heuristic it has a metric to evaluate whether
>> there is a trade worth evicting for. 

> Here is the problem: Whenever you do a 'luxury' eviction because you got a
physreg with a CostPerUse, you could be evicting virtregs with very high
spill weight.  These are the 'used in a hot loop' virtregs you were talking
about.  Whenever VirtReg.bytes > 0, you are effectively replacing the spill
weights with code size metrics.  That is very heavily biased towards
optimizing for code size, and I think it is too aggressive.

> Live range splitting is going to save you some of the time. It still uses
speed metrics, but the overall behavior of the greedy algorithm becomes very
erratic.

> Spill weights are used in two different ways when evicting:

> 1. The shouldEvict() policy function prevents a VirtReg from evicting
something with a higher spill weight. (But you are overriding it!)

> 2. The tryEvict() function selects the eviction candidate that would cause
the lowest maximum spill weight to be evicted.

> I don't think it is safe to override the shouldEvict() policy. You can get
away with changing the candidate selection in 2., though.


The policy you described was designed for register coalescing. Initially the
priority is given to the hint over spill weight but then the eviction policy
ensures hotter candidate are getting a register.  I am aware that my
"luxury" eviction (interesting nomenclature :-)) is overriding the eviction
policy. The reason is because it was designed differently: The way to look
it is as a register trading (win-win) instead of an eviction (Win-lose). It
works in two steps: 

First, Candidate gets a register (Note here my heuristic is silenced and
policy is enforced). 

Second, if it gets a register and it happen to be a CostPerUse register
(R8-R15), then try to trade this register with some other candidate's
register (in this case, does it matter if this candidate has higher weight?
Answer is no!) 

The register trade implementation leverages the eviction and RA register
assignment functions and also happens in two steps: 

First try to evict a candidate (that would cost cheaper using my heuristic).

Second if eviction occurs then because the evictee has highest spill weight,
it is first on the list and it will get the register that the evictor is
giving up. 

I have carefully followed this in the debugger and verified these steps.
Furthermore I looked at hundreds of diffs and I have not seen any evidence
of increase of stack size or spilling activity (including some pretty large
complex functions). 

If we decide to enforce the eviction policy to this type of eviction then we
are simply walking away from performance and better usage of these
registers. I have tested enforcing the policy on EEMBC and SPEC and I have
seen consistent loss in code size and runtime performance. 

 > Here is what I suggest you do:

> - Don't override shouldEvict(). That policy should always stay in place.

See above
 
> - Use code size metrics to select among multiple eviction candidates when
evicting from 'cheap' physregs.

Can you be more precise? 

> - Don't evict from two physregs in selectOrSplit() and then only use one
of them. You may be able to use code size metrics for selecting the best
eviction candidate, but don't evict two different physregs needlessly.

Same applies here it is a register trade (not two evictions! Even if it
looks as two evictions) and it is safe. The way I came through this is by
looking at some assembly in EEMBC and SPEC, some candidate occurred
frequently in a function but still failed to get R0-7. Once I added this
call it looked nice...  

At a high-level this framework+heuristic achieves the following. As some
point of RA, we get this allocation: 

t1(R0) = ...
t2(R8) = ...
       =  OP1 t1 (R0)  
       = OP2 t2(R8)
       = OP3 t2(R8)
       = OP4 t2(R8)

Heuristics allows to  trade R8 with R0 (to better usage of R0) and we get:

t1(R8) = ...
t2(R0) = ...
       =  OP1 t1 (R8)  
       = OP2 t2(R0)
       = OP3 t2(R0)
       = OP4 t2(R0)

I understand that from reading the code, it may look like it is a needless
eviction. I have added a comment to explain this. Please let me know if
there is a phrasing or better way to help readability?

> You should also make sure that the patch works for x86-64. There is a
similar code size penalty to using r8-r15 and xmm8-15.

Before submitting, I have done the testing due diligence for x86-64 with the
patch I am submitting (FYI, attached the test result).
Yes, x86-64 could benefit from this framework to minimize REX prefix and
optimize usage of old x86 registers. Unfortunately, I don't have the
bandwidth to do the implementation. Of course, I will be happy to hear about
and/or review the enabling work for X86-64.

Thanks again for the great code review, 

-Zino

-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: RACodeSize.txt
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20120131/91451aa6/attachment.txt>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: X86LLVMTestSuite.report
Type: application/octet-stream
Size: 1159 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20120131/91451aa6/attachment.obj>


More information about the llvm-commits mailing list