From: Ivo Raisr Date: Sat, 23 Sep 2017 07:46:40 +0000 (+0200) Subject: VEX register allocator: allocate caller-save registers for short lived vregs. X-Git-Tag: VALGRIND_3_14_0~227 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=074de238d44c0cdaf394489ea69a67b76916fbce;p=thirdparty%2Fvalgrind.git 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. --- diff --git a/NEWS b/NEWS index 097930a20d..b043c580cd 100644 --- a/NEWS +++ b/NEWS @@ -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 diff --git a/VEX/priv/host_generic_reg_alloc3.c b/VEX/priv/host_generic_reg_alloc3.c index 9ab95497a6..0d35c62ef2 100644 --- a/VEX/priv/host_generic_reg_alloc3.c +++ b/VEX/priv/host_generic_reg_alloc3.c @@ -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, \