Cherry pick 074de238d4 from master.

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 966b228b27
commit 20a98b48c5
2 changed files with 22 additions and 11 deletions

1
NEWS
View File

@@ -49,6 +49,7 @@ where XXXXXX is the bug number as listed below.
382998 xml-socket doesn't work
383275 massif valgrind: m_xarray.c:162 (ensureSpaceXA): Assertion '!xa->arr' failed
384584 Callee saved registers listed first for AMD64, X86, and PPC architectures
384987 VEX register allocator: allocate caller-save registers for short lived vregs
Release 3.13.0 (15 June 2017)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -632,20 +632,25 @@ 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 inline Bool find_free_rreg(
const RegAllocChunk* chunk, const RegAllocState* state,
Short ii_chunk_current, HRegClass target_hregclass,
UInt v_idx, Short ii_chunk_current, HRegClass target_hregclass,
Bool reserve_phase, const RegAllocControl* con, UInt* r_idx_found)
{
Bool found = False;
Short distance_so_far = 0; /* running max for |live_after - current_ii| */
const VRegState* vreg = &state->vregs[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 = &state->rregs[r_idx];
const RRegLRState* rreg_lrs = &chunk->rreg_lr_state[r_idx];
if (rreg->disp == Free) {
@@ -656,7 +661,12 @@ static inline Bool find_free_rreg(
} else {
const RRegLR* lr = rreg_lrs->lr_current;
if (lr->live_after > ii_chunk_current) {
/* 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 - ii_chunk_current) > distance_so_far) {
distance_so_far = lr->live_after - ii_chunk_current;
found = True;
@@ -1294,9 +1304,9 @@ static void stage5_chunk(RegAllocChunk* chunk, RegAllocState* state,
# define FIND_OR_MAKE_FREE_RREG(_v_idx, _reg_class, _reserve_phase) \
({ \
UInt _r_free_idx; \
Bool free_rreg_found = find_free_rreg(chunk, state, \
ii_chunk, (_reg_class), (_reserve_phase), \
con, &_r_free_idx); \
Bool free_rreg_found = find_free_rreg(chunk, state, (_v_idx), ii_chunk, \
(_reg_class), (_reserve_phase), \
con, &_r_free_idx); \
if (!free_rreg_found) { \
HReg vreg_to_spill = find_vreg_to_spill(chunk, state, \
&chunk->reg_usage[ii_chunk], (_reg_class), \