Hakan Ardo avatar Hakan Ardo committed 3dee5e3

Made mess of trying to pass data from a loop to its bridges using VInvariantOpInfo :(

Comments (0)

Files changed (6)

pypy/jit/metainterp/optimizeopt/invariant.py

 from pypy.jit.metainterp.compile import prebuiltNotSpecNode
 from pypy.rlib.debug import debug_print
 from pypy.jit.metainterp.history import Const
+from pypy.jit.metainterp.optimizeopt.virtualize import AbstractVirtualValue
 
+class VInvariantOpValue(AbstractVirtualValue):
+    def setup(self, op):
+        self.op = op
+        v = self.optimizer.getvalue(self.keybox)
+        self.intbound = v.intbound
+
+    def get_args_for_fail(self, modifier):
+        if self.box is None and not modifier.already_seen_virtual(self.keybox):
+            modifier.register_virtual_fields(self.keybox, [self.keybox])
+
+    def _make_virtual(self, modifier):
+        return modifier.make_vinvop(self.op)
+
+    def force_box(self):
+        return self.keybox
+    
 class OptInvariant(Optimization):
     """Move loop invariant code into a preamble.
     """
                     box = v.force_box() 
                     if box and box not in self.invariant_boxes:
                         self.invariant_boxes.append(box)
+                    box = op.result
+                    vvalue = VInvariantOpValue(self.optimizer, box, op)
+                    vvalue.setup(op)
+                    del self.optimizer.values[box]
+                    self.make_equal_to(box, vvalue)
 
                 return
 

pypy/jit/metainterp/optimizeopt/invariant.py.try1

+from pypy.jit.metainterp.optimizeopt.optimizer import *
+from pypy.jit.metainterp.resoperation import rop, ResOperation
+from pypy.jit.metainterp.compile import prebuiltNotSpecNode
+from pypy.rlib.debug import debug_print
+from pypy.jit.metainterp.history import Const
+
+class OptInvariant(Optimization):
+    """Move loop invariant code into a preamble.
+    """
+    def setup(self, virtuals):
+        if not virtuals:
+            return
+        
+        #inputargs = self.optimizer.original_inputargs
+        inputargs = self.optimizer.loop.inputargs
+        if not inputargs:
+            return
+        
+        jump_op = self.optimizer.loop.operations[-1]
+        if jump_op.opnum != rop.JUMP:
+            return 
+
+        for i in range(len(inputargs)):
+            arg_in, arg_out = inputargs[i], jump_op.args[i]
+            if arg_in is arg_out:
+                v = self.getvalue(arg_in)
+                v.invariant = True
+
+        self.invariant_boxes = []
+
+    def propagate_forward(self, op):
+    
+        if op.opnum == rop.JUMP:
+            loop = self.optimizer.loop
+            if loop.preamble and len(self.optimizer.preamble)>0:
+                # First trace through loop, create preamble
+                self.emit_operation(op)
+                preamble = loop.preamble
+                preamble.inputargs = loop.inputargs[:]
+
+                invariant_boxes = self.invariant_boxes
+                loop.inputargs.extend(invariant_boxes)
+                op.args = op.args + invariant_boxes
+                preamble.operations = self.optimizer.preamble
+                preamble.token.specnodes = loop.token.specnodes 
+                loop.token.specnodes = loop.token.specnodes + \
+                                       [prebuiltNotSpecNode] * len(invariant_boxes)
+
+                print
+                print loop.token.number
+                print len(loop.token.specnodes)
+                jmp = ResOperation(rop.JUMP,
+                                   loop.inputargs[:],
+                                   None)
+                jmp.descr = loop.token
+                preamble.operations.append(jmp)
+                preamble.token.preamble = preamble
+                return
+
+            elif op.descr.inlinable:
+                # Bridge calling a loop with preamble, inline it
+                #
+                debug_print("Inlining: ", op, "into", loop)
+                self.inline(op.descr.inlinable, op.args)
+                return
+
+        elif (op.is_always_pure()):# or op.is_foldable_guard() or op.is_ovf()):
+            if self.has_invariant_args(op):
+                op.invariant = True
+                self.emit_operation(op)
+                if self.get_constant_box(op.result) is None:
+                    v = self.getvalue(op.result)
+                    v.invariant = True
+                    box = v.force_box() 
+                    if box and box not in self.invariant_boxes:
+                        self.invariant_boxes.append(box)
+
+                return
+
+
+        #elif op.is_guard_overflow():
+        #    prev_op = self.optimizer.loop.operations[self.optimizer.i - 1]
+        #    v = self.getvalue(prev_op.result)
+        #    if v.invariant:
+        #        self.emit_invariant(op)
+        #        return
+            
+        self.emit_operation(op)
+
+    def has_invariant_args(self, op):
+        for a in op.args:
+            if self.get_constant_box(a) is None:
+                if a not in self.optimizer.values:
+                    return False
+                v = self.getvalue(a)
+                if not v.invariant:
+                    return False
+        return True
+
+    def inline(self, loop, inputargs):
+        argmap = {}
+        for i in range(len(inputargs)):
+           argmap[loop.inputargs[i]] = inputargs[i]
+        for op in loop.operations:
+            newop = op.clone()
+            for i in range(len(op.args)):
+                a = op.args[i]
+                if not isinstance(a, Const):
+                    newop.args[i] = argmap[a]
+            if op.result:
+                newop.result = op.result.clonebox()
+                argmap[op.result] = newop.result
+            debug_print("  ", newop)
+            self.emit_operation(newop)
+        
+        

pypy/jit/metainterp/optimizeopt/optimizer.py

         assert isinstance(descr, compile.ResumeGuardDescr)
         modifier = resume.ResumeDataVirtualAdder(descr, self.resumedata_memo)
         newboxes = modifier.finish(self.values, self.pendingfields)
+        debug_print('\ndescr:', descr)
         if len(newboxes) > self.metainterp_sd.options.failargs_limit: # XXX be careful here
             compile.giveup()
         descr.store_final_boxes(op, newboxes)

pypy/jit/metainterp/resume.py

         self.storage = storage
         self.memo = memo
 
+    def make_vinvop(self, op):
+        return VInvariantOpInfo(op)
+
     def make_virtual(self, known_class, fielddescrs):
         return VirtualInfo(known_class, fielddescrs)
 
 
         storage.rd_consts = self.memo.consts
         dump_storage(storage, liveboxes)
+        debug_print('liveboxes:', liveboxes)
+        debug_print('liveboxes:', [l.__class__ for l in liveboxes])
         return liveboxes[:]
 
     def _number_virtuals(self, liveboxes, values, num_env_virtuals):
     def debug_prints(self):
         raise NotImplementedError
 
+class VFromStartInfo(AbstractVirtualInfo):
+    def __init__(self, box, idx=-1):
+        self.set_content([fieldnums])
+        self.index = idx
+
 class AbstractVirtualStructInfo(AbstractVirtualInfo):
     def __init__(self, fielddescrs):
         self.fielddescrs = fielddescrs
         debug_print("\tvirtualinfo", self.known_class.repr_rpython())
         AbstractVirtualStructInfo.debug_prints(self)
 
+class VInvariantOpInfo(AbstractVirtualInfo):
+    def __init__(self, op):
+        self.op = op
+
+    @specialize.argtype(1)
+    def allocate(self, decoder):
+        #return decoder.allocate_op(self.op)
+        #raise
+        return None
+
+    def debug_prints(self):
+        debug_print("\tVInvariantOpInfo", self.op)
+
+    @specialize.argtype(1)
+    def setfields(self, decoder, array):
+        pass
+
 class VStructInfo(AbstractVirtualStructInfo):
     def __init__(self, typedescr, fielddescrs):
         AbstractVirtualStructInfo.__init__(self, fielddescrs)
         self.cur_numb = self.cur_numb.prev
 
     def _callback_i(self, index, register_index):
+        print "I: ", self.cur_numb.nums[index]
         value = self.decode_int(self.cur_numb.nums[index])
         self.write_an_int(register_index, value)
 
     def allocate_with_vtable(self, known_class):
         return self.metainterp.execute_and_record(rop.NEW_WITH_VTABLE,
                                                   None, known_class)
+    #def allocate_op(self, op):
+    #    return self.metainterp.execute_and_record_varargs(
+    #        op.opnum, op.args, op.descr)
 
     def allocate_struct(self, typedescr):
         return self.metainterp.execute_and_record(rop.NEW, typedescr)

pypy/jit/metainterp/test/test_basic.py

         assert res == 919
         self.check_loop_count(3)
 
-    def test_loop_invariant_mul_bridge_maintaining(self):
+    def test_loop_invariant_mul_bridge_maintaining1(self):
         myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
         def f(x, y):
             res = 0
                           'int_sub': 2, 'int_mul': 2, 'int_add': 2,
                           'jump': 3})
 
+    def test_loop_invariant_mul_bridge_maintaining2(self):
+        myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
+        def f(x, y):
+            res = 0
+            while y > 0:
+                myjitdriver.can_enter_jit(x=x, y=y, res=res)
+                myjitdriver.jit_merge_point(x=x, y=y, res=res)
+                z = x * x
+                res += z
+                if y<8:
+                    res += z
+                y -= 1
+            return res
+        res = self.meta_interp(f, [6, 16])
+        assert res == 828
+        self.check_loop_count(3)
+        self.check_loops({'int_lt': 1, 'int_gt': 1,
+                          'guard_false': 1, 'guard_true': 1,
+                          'int_sub': 2, 'int_mul': 2, 'int_add': 2,
+                          'jump': 3})
+
     def test_loop_invariant_intbox(self):
         myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
         class I:

pypy/jit/metainterp/test/test_virtual.py

     def _freeze_(self):
         return True
 
-    def test_virtualized(self):
+    def test_virtualized1(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'node'])
         def f(n):
             node = self._new()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.