]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
VEX register allocator: allocate caller-save registers for short lived vregs.
authorIvo Raisr <ivosh@ivosh.net>
Sat, 23 Sep 2017 07:46:40 +0000 (09:46 +0200)
committerIvo Raisr <ivosh@ivosh.net>
Wed, 11 Oct 2017 18:56:49 +0000 (20:56 +0200)
Allocate caller-saved registers for short lived vregs and callee-save registers
for vregs which span accross helper calls.
Fixes BZ#384987.

NEWS
VEX/priv/host_generic_reg_alloc3.c

diff --git a/NEWS b/NEWS
index 097930a20dadffdec26671ad65bf7250f38e9c48..b043c580cd2677ebc1a0a63e8a521336e26bc5c6 100644 (file)
--- 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
index 9ab95497a69ad89965323552c1453c6a15cb8751..0d35c62ef2589fa074f26750a1b3e299949c13cd 100644 (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, \