[pypy-svn] pypy jit-virtual_state: Stores the OptValue states of all arguments to the loop and use them to deciede which specialized version of the loop to jump to (work in progress, only non virtuals fully supoprted so far). The intbounds creates a lot of (most of the time) identical specialized version. We need to generalize that somehow.

hakanardo commits-noreply at bitbucket.org
Thu Feb 3 21:42:15 CET 2011


Author: Hakan Ardo <hakan at debian.org>
Branch: jit-virtual_state
Changeset: r41587:057bd6a641f3
Date: 2011-02-03 21:40 +0100
http://bitbucket.org/pypy/pypy/changeset/057bd6a641f3/

Log:	Stores the OptValue states of all arguments to the loop and use them
	to deciede which specialized version of the loop to jump to (work in
	progress, only non virtuals fully supoprted so far). The intbounds
	creates a lot of (most of the time) identical specialized version.
	We need to generalize that somehow.

diff --git a/pypy/jit/metainterp/optimizeopt/unroll.py b/pypy/jit/metainterp/optimizeopt/unroll.py
--- a/pypy/jit/metainterp/optimizeopt/unroll.py
+++ b/pypy/jit/metainterp/optimizeopt/unroll.py
@@ -125,6 +125,64 @@
         self.snapshot_map[snapshot] = new_snapshot
         return new_snapshot
 
+class VirtualStateAdder(resume.ResumeDataVirtualAdder):
+    def __init__(self, optimizer):
+        self.fieldboxes = {}
+        self.optimizer = optimizer
+        self.info = {}
+
+    def register_virtual_fields(self, keybox, fieldboxes):
+        self.fieldboxes[keybox] = fieldboxes
+        
+    def already_seen_virtual(self, keybox):
+        return keybox in self.fieldboxes
+
+    def getvalue(self, box):
+        return self.optimizer.getvalue(box)
+
+    def state(self, box):
+        try:
+            info = self.info[box]
+        except KeyError:
+            value = self.getvalue(box)
+            self.info[box] = info = value.make_virtual_info(self, [])
+            if box in self.fieldboxes:
+                info.fieldstate = [self.state(b) for b in self.fieldboxes[box]]
+                # FIXME: Do we realy want to add fields to the VirtualInfo's?
+        return info
+
+    def get_virtual_state(self, jump_args):
+        for box in jump_args:
+            value = self.getvalue(box)
+            value.get_args_for_fail(self)
+        return [self.state(box) for box in jump_args]
+
+
+    def make_not_virtual(self, value):
+        return NotVirtualInfo(value)
+
+class NotVirtualInfo(resume.AbstractVirtualInfo):
+    def __init__(self, value):
+        self.known_class = value.known_class
+        self.level = value.level
+        self.intbound = value.intbound.clone()
+        if value.is_constant():
+            self.constbox = value.box.clonebox()
+        else:
+            self.constbox = None
+
+    def more_general_than(self, other):
+        # XXX This will always retrace instead of forcing anything which
+        # might be what we want sometimes?
+        if not isinstance(other, NotVirtualInfo):
+            return False
+        if self.constbox:
+            if not self.constbox.same_const(other):
+                return False
+        return (self.known_class == other.known_class and
+                self.level == other.level and
+                self.intbound.contains_bound(other.intbound))
+            
 
 class UnrollOptimizer(Optimization):
     """Unroll the loop into two iterations. The first one will
@@ -139,7 +197,6 @@
             self.cloned_operations.append(newop)
             
     def propagate_all_forward(self):
-        self.make_short_preamble = True
         loop = self.optimizer.loop
         jumpop = loop.operations[-1]
         if jumpop.getopnum() == rop.JUMP:
@@ -154,7 +211,9 @@
             assert jumpop.getdescr() is loop.token
             jump_args = jumpop.getarglist()
             jumpop.initarglist([])
-            virtual_state = [self.getvalue(a).is_virtual() for a in jump_args]
+            #virtual_state = [self.getvalue(a).is_virtual() for a in jump_args]
+            modifier = VirtualStateAdder(self.optimizer)
+            virtual_state = modifier.get_virtual_state(jump_args)
 
             loop.preamble.operations = self.optimizer.newoperations
             self.optimizer = self.optimizer.reconstruct_for_next_iteration()
@@ -221,7 +280,6 @@
                     if op.result:
                         op.result.forget_value()
                 
-
     def inline(self, loop_operations, loop_args, jump_args):
         self.inliner = inliner = Inliner(loop_args, jump_args)
            
@@ -236,8 +294,6 @@
             for a in boxes:
                 if not isinstance(a, Const):
                     inputargs.append(a)
-                else:
-                    self.make_short_preamble = False
 
         # This loop is equivalent to the main optimization loop in
         # Optimizer.propagate_all_forward
@@ -304,8 +360,6 @@
         return True
 
     def create_short_preamble(self, preamble, loop):
-        if not self.make_short_preamble:
-            return None
         #return None # Dissable
 
         preamble_ops = preamble.operations
@@ -532,20 +586,15 @@
             short = descr.short_preamble
             if short:
                 args = op.getarglist()
-                virtual_state = [self.getvalue(a).is_virtual() for a in args]
+                modifier = VirtualStateAdder(self.optimizer)
+                virtual_state = modifier.get_virtual_state(args)
+                print 'len', len(short)
                 for sh in short:
                     assert len(virtual_state) == len(sh.virtual_state)
+                    
                     for i in range(len(virtual_state)):
-                        if sh.virtual_state[i] and not virtual_state[i]:
+                        if not sh.virtual_state[i].more_general_than(virtual_state[i]):
                             break
-                        elif not sh.virtual_state[i] and virtual_state[i]:
-                            # XXX Here, this bridge has made some box virtual
-                            # that is not virtual in the original loop. These
-                            # will be forced below. However we could choose
-                            # to raise RetraceLoop here to create a new 
-                            # specialized version of the loop where more
-                            # boxes will be virtual.
-                            pass
                     else:
                         if self.inline(sh.operations, sh.inputargs,
                                        op.getarglist(), dryrun=True):

diff --git a/pypy/jit/metainterp/optimizeopt/intbounds.py b/pypy/jit/metainterp/optimizeopt/intbounds.py
--- a/pypy/jit/metainterp/optimizeopt/intbounds.py
+++ b/pypy/jit/metainterp/optimizeopt/intbounds.py
@@ -94,21 +94,27 @@
         v2 = self.getvalue(op.getarg(1))
         self.emit_operation(op)
         r = self.getvalue(op.result)
-        r.intbound.intersect(v1.intbound.sub_bound(v2.intbound))
+        b = v1.intbound.sub_bound(v2.intbound)
+        if b.bounded():
+            r.intbound.intersect(b)
 
     def optimize_INT_ADD(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
         self.emit_operation(op)
         r = self.getvalue(op.result)
-        r.intbound.intersect(v1.intbound.add_bound(v2.intbound))
+        b = v1.intbound.add_bound(v2.intbound)
+        if b.bounded():
+            r.intbound.intersect(b)
 
     def optimize_INT_MUL(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
         self.emit_operation(op)
         r = self.getvalue(op.result)
-        r.intbound.intersect(v1.intbound.mul_bound(v2.intbound))
+        b = v1.intbound.mul_bound(v2.intbound)
+        if b.bounded():
+            r.intbound.intersect(b)
 
     def optimize_INT_FLOORDIV(self, op):
         v1 = self.getvalue(op.getarg(0))
@@ -300,7 +306,7 @@
             if r.box.same_constant(CONST_1):
                 self.make_int_gt(op.getarg(0), op.getarg(1))
             else:
-                self.make_int_le(op.getarg(0), op.getarg(1))
+                self.make_int_le(op.getarg(0), op.getarg(1))        
 
     def propagate_bounds_INT_LE(self, op):
         r = self.getvalue(op.result)

diff --git a/pypy/jit/metainterp/optimizeopt/intutils.py b/pypy/jit/metainterp/optimizeopt/intutils.py
--- a/pypy/jit/metainterp/optimizeopt/intutils.py
+++ b/pypy/jit/metainterp/optimizeopt/intutils.py
@@ -42,6 +42,9 @@
         self.has_lower = False
         self.has_upper = False
 
+    def bounded(self):
+        return self.has_lower and self.has_upper
+
     def known_lt(self, other):
         if self.has_upper and other.has_lower and self.upper < other.lower:
             return True
@@ -76,7 +79,7 @@
         return r
     
     def add(self, offset):
-        res = self.copy()
+        res = self.clone()
         try:
             res.lower = ovfcheck(res.lower + offset)
         except OverflowError:
@@ -91,7 +94,7 @@
         return self.mul_bound(IntBound(value, value))
     
     def add_bound(self, other):
-        res = self.copy()
+        res = self.clone()
         if other.has_upper:
             try:
                 res.upper = ovfcheck(res.upper + other.upper)
@@ -109,7 +112,7 @@
         return res
 
     def sub_bound(self, other):
-        res = self.copy()
+        res = self.clone()
         if other.has_lower:
             try:
                 res.upper = ovfcheck(res.upper - other.lower)
@@ -192,6 +195,19 @@
         if self.has_upper and val > self.upper:
             return False
         return True
+
+    def contains_bound(self, other):
+        if other.has_lower:
+            if not self.contains(other.lower):
+                return False
+        elif self.has_lower:
+            return False
+        if other.has_upper:
+            if not self.contains(other.upper):
+                return False
+        elif self.has_upper:
+            return False
+        return True
         
     def __repr__(self):
         if self.has_lower:
@@ -204,7 +220,7 @@
             u = 'Inf'
         return '%s <= x <= %s' % (l, u)
 
-    def copy(self):
+    def clone(self):
         res = IntBound(self.lower, self.upper)
         res.has_lower = self.has_lower
         res.has_upper = self.has_upper

diff --git a/pypy/jit/metainterp/optimizeopt/optimizer.py b/pypy/jit/metainterp/optimizeopt/optimizer.py
--- a/pypy/jit/metainterp/optimizeopt/optimizer.py
+++ b/pypy/jit/metainterp/optimizeopt/optimizer.py
@@ -69,7 +69,8 @@
         pass
 
     def make_virtual_info(self, modifier, fieldnums):
-        raise NotImplementedError # should not be called on this level
+        #raise NotImplementedError # should not be called on this level
+        return modifier.make_not_virtual(self)
 
     def is_constant(self):
         return self.level == LEVEL_CONSTANT


More information about the Pypy-commit mailing list