[pypy-commit] pypy fix-longevity: (plan_rich, remi) start implementing heuristic for choosing callee vs caller registers

Raemi pypy.commits at gmail.com
Tue Feb 23 10:10:48 EST 2016


Author: Remi Meier <remi.meier at gmail.com>
Branch: fix-longevity
Changeset: r82444:b5c6184fc5e6
Date: 2016-02-23 16:10 +0100
http://bitbucket.org/pypy/pypy/changeset/b5c6184fc5e6/

Log:	(plan_rich,remi) start implementing heuristic for choosing callee vs
	caller registers

diff --git a/rpython/jit/backend/llsupport/regalloc.py b/rpython/jit/backend/llsupport/regalloc.py
--- a/rpython/jit/backend/llsupport/regalloc.py
+++ b/rpython/jit/backend/llsupport/regalloc.py
@@ -671,16 +671,24 @@
             return [self.loc(op.getarg(0))]
 
 
-def compute_vars_longevity(inputargs, operations):
+class LiveRanges(object):
+    def __init__(self, longevity, last_real_usage, dist_to_next_call):
+        self.longevity = longevity
+        self.last_real_usage = last_real_usage
+        self.dist_to_next_call = dist_to_next_call
+
+def compute_var_live_ranges(inputargs, operations):
     # compute a dictionary that maps variables to index in
     # operations that is a "last-time-seen"
 
-    # returns a pair longevity/useful. Non-useful variables are ones that
+    # returns a Longevity object with longevity/useful. Non-useful variables are ones that
     # never appear in the assembler or it does not matter if they appear on
     # stack or in registers. Main example is loop arguments that go
     # only to guard operations or to jump or to finish
     last_used = {}
     last_real_usage = {}
+    dist_to_next_call = [0] * len(operations)
+    last_call_pos = -1
     for i in range(len(operations)-1, -1, -1):
         op = operations[i]
         if op.type != 'v':
@@ -703,6 +711,9 @@
                 assert not isinstance(arg, Const)
                 if arg not in last_used:
                     last_used[arg] = i
+        if op.is_call():
+            last_call_pos = i
+        dist_to_next_call[i] = last_call_pos - i
     #
     longevity = {}
     for i, arg in enumerate(operations):
@@ -729,8 +740,8 @@
                 if not isinstance(arg, Const):
                     assert arg in produced
             produced[op] = None
-    
-    return longevity, last_real_usage
+
+    return LiveRanges(longevity, last_real_usage, dist_to_next_call)
 
 def is_comparison_or_ovf_op(opnum):
     from rpython.jit.metainterp.resoperation import opclasses
diff --git a/rpython/jit/backend/llsupport/test/test_regalloc_call.py b/rpython/jit/backend/llsupport/test/test_regalloc_call.py
--- a/rpython/jit/backend/llsupport/test/test_regalloc_call.py
+++ b/rpython/jit/backend/llsupport/test/test_regalloc_call.py
@@ -141,8 +141,9 @@
         FPTR = lltype.Ptr(lltype.FuncType([rffi.UINT], rffi.UINT))
         func_ptr = llhelper(FPTR, x)
         calldescr = cpu.calldescrof(FPTR.TO, FPTR.TO.ARGS, FPTR.TO.RESULT, EffectInfo.MOST_GENERAL)
+        targettoken = TargetToken()
 
-        ns = {'calldescr': calldescr}
+        ns = {'calldescr': calldescr, 'targettoken':targettoken}
         self.namespace = ns
 
     def test_allocate_register_into_jump_register(self):
@@ -187,3 +188,22 @@
         assert trace_alloc.initial_register(i2) != edx
         assert trace_alloc.move_count() == 1
 
+    def test_call_allocate_first_param_to_callee2(self):
+        tt, ops = parse_loop("""
+        [p0,i0]
+
+        label(p0,i0,descr=targettoken)
+
+        i1 = int_add(i0,i0)
+        i2 = int_add(i0,i1)
+        call_n(p0, i1, descr=calldescr)
+        guard_true(i2) []
+
+        jump(p0,i1,descr=targettoken)
+        """, namespace=self.namespace)
+        i1 = ops.operations[0]
+        i2 = ops.operations[1]
+        trace_alloc = TraceAllocation(ops, [eax, edx], [r8, r9], [eax, edx], tt)
+        assert trace_alloc.initial_register(i1) == edx
+        assert trace_alloc.initial_register(i2) != edx
+        assert trace_alloc.move_count() == 1
diff --git a/rpython/jit/backend/x86/regalloc.py b/rpython/jit/backend/x86/regalloc.py
--- a/rpython/jit/backend/x86/regalloc.py
+++ b/rpython/jit/backend/x86/regalloc.py
@@ -7,7 +7,7 @@
 from rpython.jit.backend.llsupport.descr import CallDescr, unpack_arraydescr
 from rpython.jit.backend.llsupport.gcmap import allocate_gcmap
 from rpython.jit.backend.llsupport.regalloc import (FrameManager, BaseRegalloc,
-     RegisterManager, TempVar, compute_vars_longevity, is_comparison_or_ovf_op,
+     RegisterManager, TempVar, compute_var_live_ranges, is_comparison_or_ovf_op,
      valid_addressing_size)
 from rpython.jit.backend.x86 import rx86
 from rpython.jit.backend.x86.arch import (WORD, JITFRAME_FIXED_SIZE, IS_X86_32,
@@ -164,10 +164,10 @@
         operations = cpu.gc_ll_descr.rewrite_assembler(cpu, operations,
                                                        allgcrefs)
         # compute longevity of variables
-        longevity, last_real_usage = compute_vars_longevity(
-                                                    inputargs, operations)
-        self.longevity = longevity
-        self.last_real_usage = last_real_usage
+        live_ranges = compute_var_live_ranges(inputargs, operations)
+        self.live_ranges = live_ranges
+        self.longevity = live_ranges.longevity
+        self.last_real_usage = live_ranges.last_real_usage
         self.rm = gpr_reg_mgr_cls(self.longevity,
                                   frame_manager = self.fm,
                                   assembler = self.assembler)


More information about the pypy-commit mailing list