Author: Remi Meier <remi.me...@gmail.com>
Branch: fix-longevity
Changeset: r82464:2feb1ca9c35c
Date: 2016-02-23 22:36 +0100
http://bitbucket.org/pypy/pypy/changeset/2feb1ca9c35c/

Log:    (plan_rich,remi) fix broken commit

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
@@ -1,7 +1,7 @@
 import os
-from rpython.jit.metainterp.history import Const, Box, REF, JitCellToken
+from rpython.jit.metainterp.history import Const, REF, JitCellToken
 from rpython.rlib.objectmodel import we_are_translated, specialize
-from rpython.jit.metainterp.resoperation import rop
+from rpython.jit.metainterp.resoperation import rop, AbstractValue
 from rpython.rtyper.lltypesystem import lltype
 from rpython.rtyper.lltypesystem.lloperation import llop
 
@@ -10,7 +10,7 @@
 except ImportError:
     OrderedDict = dict # too bad
 
-class TempBox(Box):
+class TempVar(AbstractValue):
     def __init__(self):
         pass
 
@@ -267,6 +267,7 @@
         raise NotImplementedError("Purely abstract")
 
 class RegisterManager(object):
+
     """ Class that keeps track of register allocations
     """
     box_types             = None       # or a list of acceptable types
@@ -292,19 +293,19 @@
     def is_still_alive(self, v):
         # Check if 'v' is alive at the current position.
         # Return False if the last usage is strictly before.
-        return self.longevity[v][1] >= self.position
+        return self.longevity.last_use(v) >= self.position
 
     def stays_alive(self, v):
         # Check if 'v' stays alive after the current position.
         # Return False if the last usage is before or at position.
-        return self.longevity[v][1] > self.position
+        return self.longevity.last_use(v) > self.position
 
     def next_instruction(self, incr=1):
         self.position += incr
 
     def _check_type(self, v):
         if not we_are_translated() and self.box_types is not None:
-            assert isinstance(v, TempBox) or v.type in self.box_types
+            assert isinstance(v, TempVar) or v.type in self.box_types
 
     def possibly_free_var(self, v):
         """ If v is stored in a register and v is not used beyond the
@@ -314,7 +315,7 @@
         self._check_type(v)
         if isinstance(v, Const):
             return
-        if v not in self.longevity or self.longevity[v][1] <= self.position:
+        if not self.longevity.exists(v) or self.longevity.last_use(v) <= 
self.position:
             if v in self.reg_bindings:
                 self.free_regs.append(self.reg_bindings[v])
                 del self.reg_bindings[v]
@@ -348,7 +349,7 @@
         assert len(self.temp_boxes) == 0
         if self.longevity:
             for v in self.reg_bindings:
-                assert self.longevity[v][1] > self.position
+                assert self.longevity.last_use(v) > self.position
 
     def try_allocate_reg(self, v, selected_reg=None, need_lower_byte=False):
         """ Try to allocate a register, if we have one free.
@@ -424,7 +425,7 @@
                     continue
             if need_lower_byte and reg in self.no_lower_byte_regs:
                 continue
-            max_age = self.longevity[next][1]
+            max_age = self.longevity.last_use(next)
             if cur_max_age < max_age:
                 cur_max_age = max_age
                 candidate = next
@@ -442,8 +443,8 @@
         Will not spill a variable from 'forbidden_vars'.
         """
         self._check_type(v)
-        if isinstance(v, TempBox):
-            self.longevity[v] = (self.position, self.position)
+        if isinstance(v, TempVar):
+            self.longevity.new_live_range(v, self.position, self.position)
         loc = self.try_allocate_reg(v, selected_reg,
                                     need_lower_byte=need_lower_byte)
         if loc:
@@ -553,13 +554,14 @@
             loc = self.force_allocate_reg(v, forbidden_vars)
             self.assembler.regalloc_mov(prev_loc, loc)
         assert v in self.reg_bindings
-        if self.longevity[v][1] > self.position:
+        if self.longevity.last_use(v) > self.position:
             # we need to find a new place for variable v and
             # store result in the same place
             loc = self.reg_bindings[v]
             del self.reg_bindings[v]
-            if self.frame_manager.get(v) is None:
+            if self.frame_manager.get(v) is None or self.free_regs:
                 self._move_variable_away(v, loc)
+
             self.reg_bindings[result_v] = loc
         else:
             self._reallocate_from_to(v, result_v)
@@ -581,7 +583,7 @@
         1 (save all), or 2 (save default+PTRs).
         """
         for v, reg in self.reg_bindings.items():
-            if v not in force_store and self.longevity[v][1] <= self.position:
+            if v not in force_store and self.longevity.last_use(v) <= 
self.position:
                 # variable dies
                 del self.reg_bindings[v]
                 self.free_regs.append(reg)
@@ -633,69 +635,79 @@
         locs = []
         base_ofs = self.assembler.cpu.get_baseofs_of_frame_field()
         for box in inputargs:
-            assert isinstance(box, Box)
+            assert not isinstance(box, Const)
             loc = self.fm.get_new_loc(box)
             locs.append(loc.value - base_ofs)
         if looptoken.compiled_loop_token is not None:
             # for tests
             looptoken.compiled_loop_token._ll_initial_locs = locs
 
-    def can_merge_with_next_guard(self, op, i, operations):
-        if (op.getopnum() == rop.CALL_MAY_FORCE or
-            op.getopnum() == rop.CALL_ASSEMBLER or
-            op.getopnum() == rop.CALL_RELEASE_GIL):
-            assert operations[i + 1].getopnum() == rop.GUARD_NOT_FORCED
-            return True
-        if not op.is_comparison():
-            if op.is_ovf():
-                if (operations[i + 1].getopnum() != rop.GUARD_NO_OVERFLOW and
-                    operations[i + 1].getopnum() != rop.GUARD_OVERFLOW):
-                    not_implemented("int_xxx_ovf not followed by "
-                                    "guard_(no)_overflow")
-                return True
+    def next_op_can_accept_cc(self, operations, i):
+        op = operations[i]
+        next_op = operations[i + 1]
+        opnum = next_op.getopnum()
+        if (opnum != rop.GUARD_TRUE and opnum != rop.GUARD_FALSE
+                                    and opnum != rop.COND_CALL):
             return False
-        if (operations[i + 1].getopnum() != rop.GUARD_TRUE and
-            operations[i + 1].getopnum() != rop.GUARD_FALSE):
+        if next_op.getarg(0) is not op:
             return False
-        if operations[i + 1].getarg(0) is not op.result:
+        if self.longevity[op][1] > i + 1:
             return False
-        if (self.longevity[op.result][1] > i + 1 or
-            op.result in operations[i + 1].getfailargs()):
-            return False
+        if opnum != rop.COND_CALL:
+            if op in operations[i + 1].getfailargs():
+                return False
+        else:
+            if op in operations[i + 1].getarglist()[1:]:
+                return False
         return True
 
-    def locs_for_call_assembler(self, op, guard_op):
+    def locs_for_call_assembler(self, op):
         descr = op.getdescr()
         assert isinstance(descr, JitCellToken)
         if op.numargs() == 2:
             self.rm._sync_var(op.getarg(1))
             return [self.loc(op.getarg(0)), self.fm.loc(op.getarg(1))]
         else:
+            assert op.numargs() == 1
             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 exists(self, var):
+         return var in self.longevity
+
+    def last_use(self, var):
+         return self.longevity[var][1]
+
+    def new_live_range(self, var, start, end):
+         self.longevity[var] = (start, end)
+
+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
-    produced = {}
     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.result:
-            if op.result not in last_used and op.has_no_side_effect():
+        if op.type != 'v':
+            if op not in last_used and op.has_no_side_effect():
                 continue
-            assert op.result not in produced
-            produced[op.result] = i
         opnum = op.getopnum()
         for j in range(op.numargs()):
             arg = op.getarg(j)
-            if not isinstance(arg, Box):
+            if isinstance(arg, Const):
                 continue
             if arg not in last_used:
                 last_used[arg] = i
@@ -706,26 +718,40 @@
             for arg in op.getfailargs():
                 if arg is None: # hole
                     continue
-                assert isinstance(arg, Box)
+                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 arg in produced:
-        if arg in last_used:
-            assert isinstance(arg, Box)
-            assert produced[arg] < last_used[arg]
-            longevity[arg] = (produced[arg], last_used[arg])
+    for i, arg in enumerate(operations):
+        if arg.type != 'v' and arg in last_used:
+            assert not isinstance(arg, Const)
+            assert i < last_used[arg]
+            longevity[arg] = (i, last_used[arg])
             del last_used[arg]
     for arg in inputargs:
-        assert isinstance(arg, Box)
+        assert not isinstance(arg, Const)
         if arg not in last_used:
             longevity[arg] = (-1, -1)
         else:
             longevity[arg] = (0, last_used[arg])
             del last_used[arg]
     assert len(last_used) == 0
-    return longevity, last_real_usage
+
+    if not we_are_translated():
+        produced = {}
+        for arg in inputargs:
+            produced[arg] = None
+        for op in operations:
+            for arg in op.getarglist():
+                if not isinstance(arg, Const):
+                    assert arg in produced
+            produced[op] = None
+
+    return LiveRanges(longevity, last_real_usage, dist_to_next_call)
 
 def is_comparison_or_ovf_op(opnum):
     from rpython.jit.metainterp.resoperation import opclasses
@@ -734,7 +760,7 @@
     # any instance field, we can use a fake object
     class Fake(cls):
         pass
-    op = Fake(None)
+    op = Fake()
     return op.is_comparison() or op.is_ovf()
 
 def valid_addressing_size(size):
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
@@ -515,7 +515,7 @@
         # and won't be used after the current operation finishes,
         # then swap the role of 'x' and 'y'
         if (symm and isinstance(argloc, RegLoc) and
-                self.rm.live_ranges.last_use(y) == self.rm.position):
+                self.rm.longevity.last_use(y) == self.rm.position):
             x, y = y, x
             argloc = self.loc(y)
         #
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to