Author: Hakan Ardo <ha...@debian.org>
Branch: jit-short_from_state
Changeset: r45642:f443c6b9ddb5
Date: 2011-07-15 19:38 +0200
http://bitbucket.org/pypy/pypy/changeset/f443c6b9ddb5/

Log:    Setup the state of new optimizer chain for the peeled loop by
        emitting the short preamble operations. This becomes a lot simpler
        and less errorprone than trying to copy the exact subset of the
        preamble optimizer state that would corespond to having executed
        those ops in the (short) preamble.

diff --git a/pypy/jit/metainterp/optimizeopt/fficall.py 
b/pypy/jit/metainterp/optimizeopt/fficall.py
--- a/pypy/jit/metainterp/optimizeopt/fficall.py
+++ b/pypy/jit/metainterp/optimizeopt/fficall.py
@@ -86,6 +86,9 @@
         debug_stop('jit-log-ffiopt')
         Optimization.propagate_end_forward(self)
 
+    def new(self):
+        return OptFfiCall()
+    
     def reconstruct_for_next_iteration(self, short_boxes, surviving_boxes,
                                        optimizer, valuemap):
         return OptFfiCall()
diff --git a/pypy/jit/metainterp/optimizeopt/heap.py 
b/pypy/jit/metainterp/optimizeopt/heap.py
--- a/pypy/jit/metainterp/optimizeopt/heap.py
+++ b/pypy/jit/metainterp/optimizeopt/heap.py
@@ -163,6 +163,9 @@
 
     def flush(self):
         self.force_all_lazy_setfields_and_arrayitems()
+
+    def new(self):
+        return OptHeap()
         
     def reconstruct_for_next_iteration(self,  short_boxes, surviving_boxes,
                                        optimizer, valuemap):
@@ -170,7 +173,7 @@
 
         for descr, d in self.cached_fields.items():
             new.cached_fields[descr] = d.get_cloned(optimizer, valuemap, 
short_boxes)
-
+        
         for descr, submap in self.cached_arrayitems.items():
             newdict = {}
             for index, d in submap.items():
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
@@ -13,6 +13,10 @@
         self.posponedop = None
         self.nextop = None
 
+    def new(self):
+        assert self.posponedop is None
+        return OptIntBounds()
+        
     def reconstruct_for_next_iteration(self,  short_boxes, surviving_boxes, 
optimizer,
                                        valuemap):
         assert self.posponedop is None
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
@@ -303,6 +303,9 @@
         pass
 
     # It is too late to force stuff here, it must be done in 
force_at_end_of_preamble
+    def new(self):
+        raise NotImplementedError
+
     def reconstruct_for_next_iteration(self, short_boxes, surviving_boxes=None,
                                        optimizer=None, valuemap=None):
         raise NotImplementedError
@@ -335,6 +338,7 @@
         self.exception_might_have_happened = False
         self.quasi_immutable_deps = None
         self.newoperations = []
+        self.emitting_dissabled = False
         if loop is not None:
             self.call_pure_results = loop.call_pure_results
 
@@ -363,7 +367,15 @@
         for o in self.optimizations:
             o.flush()
         assert self.posponedop is None
-            
+
+    def new(self):
+        assert self.posponedop is None
+        new = Optimizer(self.metainterp_sd, self.loop)
+        optimizations = [o.new() for o in self.optimizations]
+        new.set_optimizations(optimizations)
+        new.quasi_immutable_deps = self.quasi_immutable_deps
+        return new
+        
     def reconstruct_for_next_iteration(self, short_boxes, surviving_boxes=None,
                                        optimizer=None, valuemap=None):
         assert optimizer is None
@@ -575,10 +587,11 @@
         return True
 
     def emit_operation(self, op):
-        ###self.heap_op_optimizer.emitting_operation(op)
-        self._emit_operation(op)
-
-    def _emit_operation(self, op):
+        if op.returns_bool_result():
+            self.bool_boxes[self.getvalue(op.result)] = None
+        if self.emitting_dissabled:
+            return
+        
         for i in range(op.numargs()):
             arg = op.getarg(i)
             if arg in self.values:
@@ -590,8 +603,6 @@
             op = self.store_final_boxes_in_guard(op)
         elif op.can_raise():
             self.exception_might_have_happened = True
-        elif op.returns_bool_result():
-            self.bool_boxes[self.getvalue(op.result)] = None
         self.newoperations.append(op)
 
     def store_final_boxes_in_guard(self, op):
diff --git a/pypy/jit/metainterp/optimizeopt/rewrite.py 
b/pypy/jit/metainterp/optimizeopt/rewrite.py
--- a/pypy/jit/metainterp/optimizeopt/rewrite.py
+++ b/pypy/jit/metainterp/optimizeopt/rewrite.py
@@ -14,8 +14,11 @@
     """
     def __init__(self):
         self.loop_invariant_results = {}
-        self.loop_invariant_producer = {}        
+        self.loop_invariant_producer = {}
 
+    def new(self):
+        return OptRewrite()
+        
     def reconstruct_for_next_iteration(self, short_boxes, surviving_boxes,
                                        optimizer, valuemap):
         new = OptRewrite()
@@ -24,7 +27,7 @@
                                  value.get_cloned(new, valuemap)
         return new
 
-    def produce_potential_short_preamble_ops(self, potential_ops):        
+    def produce_potential_short_preamble_ops(self, potential_ops):
         for op in self.loop_invariant_producer.values():
             potential_ops[op.result] = op
 
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py 
b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -5092,32 +5092,38 @@
 
     def test_invariant_ovf(self):
         ops = """
-        [i0, i1, i10, i11, i12]
+        [i0, i1, i10, i11, i20, i21]
         i2 = int_add_ovf(i0, i1)
         guard_no_overflow() []
         i3 = int_sub_ovf(i0, i1)
         guard_no_overflow() []
         i4 = int_mul_ovf(i0, i1)
         guard_no_overflow() []
+        escape(i2)
+        escape(i3)
+        escape(i4)
         i24 = int_mul_ovf(i10, i11)
         guard_no_overflow() []
         i23 = int_sub_ovf(i10, i11)
         guard_no_overflow() []
         i22 = int_add_ovf(i10, i11)
         guard_no_overflow() []
-        jump(i0, i1, i2, i3, i4)
-        """
-        expected = """
-        [i0, i1, i10, i11, i12]
+        jump(i0, i1, i20, i21, i20, i21)
+        """
+        expected = """
+        [i0, i1, i10, i11, i2, i3, i4]
+        escape(i2)
+        escape(i3)
+        escape(i4)        
         i24 = int_mul_ovf(i10, i11)
         guard_no_overflow() []
         i23 = int_sub_ovf(i10, i11)
         guard_no_overflow() []
         i22 = int_add_ovf(i10, i11)
         guard_no_overflow() []
-        jump(i0, i1, i10, i11, i12)
-        """
-        self.optimize_loop(ops, expected, ops)
+        jump(i0, i1, i10, i11, i2, i3, i4) 
+        """
+        self.optimize_loop(ops, expected)
 
     def test_value_proven_to_be_constant_after_two_iterations(self):
         class FakeDescr(AbstractDescr):
@@ -6213,6 +6219,22 @@
         self.optimize_loop(ops, expected, ops)
         # FIXME: check jumparg 0 == getfield_gc()
 
+    def test_constant_getfield1bis(self):
+        ops = """
+        [p1, p187, i184]
+        p188 = getarrayitem_gc(p187, 42, descr=<GcPtrArrayDescr>)
+        guard_value(p188, ConstPtr(myptr)) []
+        p25 = getfield_gc(ConstPtr(myptr), descr=otherdescr)
+        p26 = call(p25, descr=nonwritedescr)
+        jump(p26, p187, i184)
+        """
+        expected = """
+        [p24, p187, i184, p25]
+        p26 = call(p25, descr=nonwritedescr)
+        jump(p26, p187, i184, p25)
+        """
+        self.optimize_loop(ops, expected)
+
     def test_constant_getfield2(self):
         ops = """
         [p19]
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
@@ -147,9 +147,6 @@
         snapshot_args = snapshot.boxes 
         new_snapshot_args = []
         for a in snapshot_args:
-            if not isinstance(a, Const):
-                a = loop.preamble.inputargs[jump_args.index(a)]
-            a = self.inliner.inline_arg(a)
             a = self.getvalue(a).get_key_box()
             new_snapshot_args.append(a)
         prev = self.fix_snapshot(loop, jump_args, snapshot.prev)
@@ -173,13 +170,21 @@
             self.optimizer.flush()
 
             KillHugeIntBounds(self.optimizer).apply()
+            
+            loop.preamble.operations = self.optimizer.newoperations
+            jump_args = [self.getvalue(a).get_key_box() for a in jump_args]
 
-            loop.preamble.operations = self.optimizer.newoperations
+            start_resumedescr = 
loop.preamble.start_resumedescr.clone_if_mutable()
+            self.start_resumedescr = start_resumedescr
+            assert isinstance(start_resumedescr, ResumeGuardDescr)
+            start_resumedescr.rd_snapshot = self.fix_snapshot(loop, jump_args,
+                                                              
start_resumedescr.rd_snapshot)
 
             modifier = VirtualStateAdder(self.optimizer)
             virtual_state = modifier.get_virtual_state(jump_args)
             values = [self.getvalue(arg) for arg in jump_args]
             inputargs = virtual_state.make_inputargs(values)
+            short_inputargs = virtual_state.make_inputargs(values, 
keyboxes=True)            
 
             self.constant_inputargs = {}
             for box in jump_args: 
@@ -193,21 +198,44 @@
             preamble_optimizer = self.optimizer
             loop.preamble.quasi_immutable_deps = (
                 self.optimizer.quasi_immutable_deps)
-            self.optimizer = self.optimizer.reconstruct_for_next_iteration(sb, 
jump_args)
+            self.optimizer = self.optimizer.new()
             loop.quasi_immutable_deps = self.optimizer.quasi_immutable_deps
 
+            # Force virtuals amoung the jump_args of the preamble to get the
+            # operations needed to setup the proper state of those virtuals
+            # in the peeled loop
+            inputarg_setup_ops = []
+            preamble_optimizer.newoperations = []
+            for box in short_inputargs:
+                value = preamble_optimizer.getvalue(box)
+                if value.is_virtual():
+                    value.force_box()
+                else:
+                    inputarg_setup_ops.extend(value.make_guards(box))
+            preamble_optimizer.flush()
+            inputarg_setup_ops += preamble_optimizer.newoperations
+
+            # Setup the state of the new optimizer by emiting the
+            # short preamble operations and discarding the result
+            self.optimizer.emitting_dissabled = True
+            for op in inputarg_setup_ops:
+                self.optimizer.send_extra_operation(op)
+            seen = {}
+            for op in self.short_boxes.values():
+                self.ensure_short_op_emitted(op, self.optimizer, seen)
+                if op and op.result:
+                    value = preamble_optimizer.getvalue(op.result)
+                    for guard in value.make_guards(op.result):
+                        self.optimizer.send_extra_operation(guard)
+            self.optimizer.flush()
+            self.optimizer.emitting_dissabled = False
+            
             initial_inputargs_len = len(inputargs)
             self.inliner = Inliner(loop.inputargs, jump_args)
 
-            start_resumedescr = 
loop.preamble.start_resumedescr.clone_if_mutable()
-            self.start_resumedescr = start_resumedescr
-            assert isinstance(start_resumedescr, ResumeGuardDescr)
-            start_resumedescr.rd_snapshot = self.fix_snapshot(loop, jump_args,
-                                                              
start_resumedescr.rd_snapshot)
-
-            inputargs, short_inputargs, short = 
self.inline(self.cloned_operations,
-                                           loop.inputargs, jump_args,
-                                           virtual_state)
+            short = self.inline(inputargs, self.cloned_operations,
+                                loop.inputargs, short_inputargs,
+                                virtual_state)
             
             #except KeyError:
             #    debug_print("Unrolling failed.")
@@ -267,13 +295,10 @@
                     if op.result:
                         op.result.forget_value()
                 
-    def inline(self, loop_operations, loop_args, jump_args, virtual_state):
+    def inline(self, inputargs, loop_operations, loop_args, short_inputargs, 
virtual_state):
         inliner = self.inliner
 
-        values = [self.getvalue(arg) for arg in jump_args]
-        inputargs = virtual_state.make_inputargs(values)
         short_jumpargs = inputargs[:]
-        short_inputargs = virtual_state.make_inputargs(values, keyboxes=True)
 
         short = []
         short_seen = {}
@@ -360,8 +385,22 @@
             raise InvalidLoop
         debug_stop('jit-log-virtualstate')
         
-        return inputargs, short_inputargs, short
+        return short
 
+    def ensure_short_op_emitted(self, op, optimizer, seen):
+        if op is None:
+            return
+        if op.result is not None and op.result in seen:
+            return
+        for a in op.getarglist():
+            if not isinstance(a, Const) and a not in seen:
+                self.ensure_short_op_emitted(self.short_boxes[a], optimizer, 
seen)
+        optimizer.send_extra_operation(op)
+        seen[op.result] = True
+        if op.is_ovf():
+            guard = ResOperation(rop.GUARD_NO_OVERFLOW, [], None)
+            optimizer.send_extra_operation(guard)
+        
     def add_op_to_short(self, op, short, short_seen, emit=True, 
guards_needed=False):
         if op is None:
             return None
@@ -656,7 +695,10 @@
 class OptInlineShortPreamble(Optimization):
     def __init__(self, retraced):
         self.retraced = retraced
-    
+
+    def new(self):
+        return OptInlineShortPreamble(self.retraced)
+        
     def reconstruct_for_next_iteration(self,  short_boxes, surviving_boxes,
                                        optimizer, valuemap):
         return OptInlineShortPreamble(self.retraced)
diff --git a/pypy/jit/metainterp/optimizeopt/virtualize.py 
b/pypy/jit/metainterp/optimizeopt/virtualize.py
--- a/pypy/jit/metainterp/optimizeopt/virtualize.py
+++ b/pypy/jit/metainterp/optimizeopt/virtualize.py
@@ -311,6 +311,9 @@
 class OptVirtualize(optimizer.Optimization):
     "Virtualize objects until they escape."
 
+    def new(self):
+        return OptVirtualize()
+        
     def reconstruct_for_next_iteration(self, short_boxes,  surviving_boxes,
                                        optimizer, valuemap):
         return OptVirtualize()
diff --git a/pypy/jit/metainterp/optimizeopt/vstring.py 
b/pypy/jit/metainterp/optimizeopt/vstring.py
--- a/pypy/jit/metainterp/optimizeopt/vstring.py
+++ b/pypy/jit/metainterp/optimizeopt/vstring.py
@@ -366,6 +366,9 @@
     "Handling of strings and unicodes."
     enabled = True
 
+    def new(self):
+        return OptString()
+    
     def reconstruct_for_next_iteration(self, short_boxes, surviving_boxes,
                                        optimizer, valuemap):
         return OptString()
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to