VEX register allocator: allocate caller-save registers for short lived vregs.

Allocate caller-saved registers for short lived vregs and callee-save registers
for vregs which span accross helper calls.
Fixes BZ#384987.
This commit is contained in:
Ivo Raisr
2017-09-23 09:46:40 +02:00
parent 83cabd3249
commit 074de238d4
2 changed files with 22 additions and 10 deletions

1
NEWS
View File

@@ -58,6 +58,7 @@ where XXXXXX is the bug number as listed below.
384526 reduce number of spill instructions generated by VEX register allocator v3
384584 Callee saved registers listed first for AMD64, X86, and PPC architectures
n-i-bz Fix missing workq_ops operations (macOS)
384987 VEX register allocator: allocate caller-save registers for short lived vregs
385182 PPC64 is missing support for the DSCR
385207 PPC64, generate_store_FPRF() generates too many Iops
385208 PPC64, xxperm instruction exhausts temporary memory

View File

@@ -408,22 +408,27 @@ static inline HReg find_vreg_to_spill(
}
/* Find a free rreg of the correct class.
Tries to find an rreg whose live range (if any) is as far ahead in the
incoming instruction stream as possible. An ideal rreg candidate is
a callee-save register because it won't be used for parameter passing
around helper function calls. */
Tries to find an rreg whose hard live range (if any) starts after the vreg's
live range ends. If that is not possible, then at least whose live range
is as far ahead in the incoming instruction stream as possible.
An ideal rreg candidate is a caller-save register for short-lived vregs
and a callee-save register for long-lived vregs because it won't need to
be spilled around helper calls. */
static Bool find_free_rreg(
const VRegState* vreg_state, UInt n_vregs,
const RRegState* rreg_state, UInt n_rregs,
const RRegLRState* rreg_lr_state,
UInt current_ii, HRegClass target_hregclass,
UInt v_idx, UInt current_ii, HRegClass target_hregclass,
Bool reserve_phase, const RegAllocControl* con, UInt* r_idx_found)
{
Bool found = False;
UInt distance_so_far = 0; /* running max for |live_after - current_ii| */
const VRegState* vreg = &vreg_state[v_idx];
for (UInt r_idx = con->univ->allocable_start[target_hregclass];
r_idx <= con->univ->allocable_end[target_hregclass]; r_idx++) {
/* Assume majority of vregs are short-lived. Start scannig from caller-save
registers first. */
for (Int r_idx = (Int) con->univ->allocable_end[target_hregclass];
r_idx >= (Int) con->univ->allocable_start[target_hregclass]; r_idx--) {
const RRegState* rreg = &rreg_state[r_idx];
const RRegLRState* rreg_lrs = &rreg_lr_state[r_idx];
if (rreg->disp == Free) {
@@ -434,7 +439,12 @@ static Bool find_free_rreg(
} else {
const RRegLR* lr = rreg_lrs->lr_current;
if (lr->live_after > (Short) current_ii) {
/* Not live, yet. */
/* RReg's hard live range is not live, yet. */
if (vreg->effective_dead_before <= lr->live_after) {
found = True;
*r_idx_found = r_idx;
break; /* VReg is short-lived; it fits in. */
}
if ((lr->live_after - (Short) current_ii) > distance_so_far) {
distance_so_far = lr->live_after - (Short) current_ii;
found = True;
@@ -548,8 +558,9 @@ HInstrArray* doRegisterAllocation_v3(
({ \
UInt _r_free_idx; \
Bool free_rreg_found = find_free_rreg( \
vreg_state, n_vregs, rreg_state, n_rregs, rreg_lr_state, \
(_ii), (_reg_class), (_reserve_phase), con, &_r_free_idx); \
vreg_state, n_vregs, rreg_state, n_rregs, rreg_lr_state, \
(_v_idx), (_ii), (_reg_class), (_reserve_phase), \
con, &_r_free_idx); \
if (!free_rreg_found) { \
HReg vreg_to_spill = find_vreg_to_spill( \
vreg_state, n_vregs, rreg_state, n_rregs, \