Author: Maciej Fijalkowski <[email protected]>
Branch: result-in-resops
Changeset: r58398:e286cf78805e
Date: 2012-10-24 18:30 +0200
http://bitbucket.org/pypy/pypy/changeset/e286cf78805e/

Log:    Start attacking the optimizer chain

diff --git a/pypy/jit/metainterp/optimizeopt/earlyforce.py 
b/pypy/jit/metainterp/optimizeopt/earlyforce.py
--- a/pypy/jit/metainterp/optimizeopt/earlyforce.py
+++ b/pypy/jit/metainterp/optimizeopt/earlyforce.py
@@ -8,6 +8,8 @@
 
 class OptEarlyForce(Optimization):
     def propagate_forward(self, op):
+        self.emit_operation(op)
+        return
         opnum = op.getopnum()
         if (opnum != rop.SETFIELD_GC and 
             opnum != rop.SETARRAYITEM_GC and
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
@@ -229,17 +229,17 @@
             cf = submap[index] = CachedField()
         return cf
 
-    def emit_operation(self, op):
-        self.emitting_operation(op)
-        if self.posponedop:
-            posponedop = self.posponedop
-            self.posponedop = None
-            self.next_optimization.propagate_forward(posponedop)
-        if (op.is_comparison() or op.getopnum() in opgroups.CALL_MAY_FORCE
-            or op.is_ovf()):
-            self.posponedop = op
-        else:
-            Optimization.emit_operation(self, op)
+    #def emit_operation(self, op):
+    #    self.emitting_operation(op)
+    #    if self.posponedop:
+    #        posponedop = self.posponedop
+    #        self.posponedop = None
+    #        self.next_optimization.propagate_forward(posponedop)
+    #    if (op.is_comparison() or op.getopnum() in opgroups.CALL_MAY_FORCE
+    #        or op.is_ovf()):
+    #        self.posponedop = op
+    #    else:
+    #        Optimization.emit_operation(self, op)
 
     def emitting_operation(self, op):
         if op.has_no_side_effect():
@@ -540,6 +540,6 @@
         self.emit_operation(op)
 
 
-dispatch_opt = make_dispatcher_method(OptHeap, 'optimize_',
-        default=OptHeap.emit_operation)
-OptHeap.propagate_forward = dispatch_opt
+#dispatch_opt = make_dispatcher_method(OptHeap, 'optimize_',
+#        default=OptHeap.emit_operation)
+#OptHeap.propagate_forward = dispatch_opt
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
@@ -15,12 +15,12 @@
     def new(self):
         return OptIntBounds()
 
-    def propagate_forward(self, op):
-        dispatch_opt(self, op)
+    #def propagate_forward(self, op):
+    #    dispatch_opt(self, op)
 
-    def opt_default(self, op):
-        assert not op.is_ovf()
-        self.emit_operation(op)
+    #def opt_default(self, op):
+    #    assert not op.is_ovf()
+    #    self.emit_operation(op)
 
 
     def propagate_bounds_backward(self, box):
@@ -471,6 +471,6 @@
     propagate_bounds_INT_MUL_OVF  = propagate_bounds_INT_MUL
 
 
-dispatch_opt = make_dispatcher_method(OptIntBounds, 'optimize_',
-        default=OptIntBounds.opt_default)
-dispatch_bounds_ops = make_dispatcher_method(OptIntBounds, 'propagate_bounds_')
+#dispatch_opt = make_dispatcher_method(OptIntBounds, 'optimize_',
+#        default=OptIntBounds.opt_default)
+#dispatch_bounds_ops = make_dispatcher_method(OptIntBounds, 
'propagate_bounds_')
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
@@ -2,13 +2,12 @@
 """ This file implements the entry point to optimizations - the Optimizer.
 optimizations are dispatched in order they're passed and for each operation
 optimize_XYZ where XYZ is the name of resop is called. The method can choose
-to return None (optimized away) or call self.emit_operation which means
+to return None (optimized away) or return the operation to emit.
 it'll be passed onto the next one.
 
-Each resop can have an extra attribute optimize_replace, which points to
-a new version of the same resop. Also each one can have optimize_value,
-which is valid when optimize_replace is not set. There is 1-1 mapping, which
-means that two resops cannot share the optimize_value extra attribute
+Each resop can have an extra attribute _forwarded, which points to
+a new version of the same resop. It can be a mutable resop (from optmodel)
+or a constant.
 """
 
 from pypy.jit.metainterp import jitprof, resume, compile
@@ -19,10 +18,9 @@
                                                      IntLowerBound, MININT, 
MAXINT
 from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method
 from pypy.jit.metainterp.resoperation import rop, AbstractResOp, opgroups,\
-     Const, ConstInt, ConstFloat, AbstractValue
+     Const, ConstInt, opname
 from pypy.jit.metainterp.typesystem import llhelper
-from pypy.jit.codewriter import longlong
-from pypy.rlib.objectmodel import specialize, we_are_translated
+from pypy.rlib.objectmodel import specialize
 from pypy.tool.pairtype import extendabletype
 
 LEVEL_UNKNOWN    = '\x00'
@@ -43,11 +41,6 @@
     def clone(self):
         return LenBound(self.mode, self.descr, self.bound.clone())
 
-class exploder(object):
-    def __getattribute__(self, attr):
-        import pdb
-        pdb.set_trace()
-
 class OptValue(object):
     _attrs_ = ('known_class', 'last_guard', 'level', 'intbound', 'lenbound', 
'is_bool_box')
 
@@ -58,17 +51,6 @@
     known_class = None
     intbound = ImmutableIntUnbounded()
     lenbound = None
-    is_bool_box = False
-
-    def getbox(self):
-        import pdb
-        pdb.set_trace()
-
-    def setbox(self, x):
-        import pdb
-        pdb.set_trace()
-
-    box = property(getbox, setbox)
 
     def __init__(self, op, level=None, known_class=None, intbound=None):
         self.op = op
@@ -196,6 +178,7 @@
             self.intbound = IntUnbounded()
 
     def get_constant_class(self, cpu):
+        xxx
         level = self.level
         if level == LEVEL_KNOWNCLASS:
             return self.known_class
@@ -291,21 +274,32 @@
 
 
 class Optimization(object):
-    next_optimization = None
+    optimize_default = None
 
     def __init__(self):
         pass # make rpython happy
 
-    def propagate_forward(self, op):
-        raise NotImplementedError
+    #def propagate_forward(self, op):
+    #    raise NotImplementedError
 
-    def emit_operation(self, op):
-        self.last_emitted_operation = op
-        self.next_optimization.propagate_forward(op)
+    #def emit_operation(self, op):
+    #    self.last_emitted_operation = op
+    #    self.next_optimization.propagate_forward(op)
+
+    def optimize_operation(self, op):
+        name = 'optimize_' + opname[op.getopnum()]
+        next_func = getattr(self, name, self.optimize_default)
+        if next_func is not None:
+            op = next_func(op)
+            if op is None:
+                return
+            else:
+                self.last_emitted_operation = op
+        return op
 
     # FIXME: Move some of these here?
-    def getvalue(self, box, create=True):
-        return self.optimizer.getvalue(box, create=create)
+    def getforwarded(self, op):
+        return self.optimizer.getforwarded(op)
 
     def setvalue(self, box, value):
         self.optimizer.setvalue(box, value)
@@ -319,8 +313,8 @@
     def replace(self, box, value):
         return self.optimizer.replace(box, value)
 
-    def get_constant_box(self, box):
-        return self.optimizer.get_constant_box(box)
+    def get_constant_op(self, op):
+        return self.optimizer.get_constant_op(op)
 
     def new_box(self, fieldofs):
         return self.optimizer.new_box(fieldofs)
@@ -392,25 +386,11 @@
         if loop is not None:
             self.call_pure_results = loop.call_pure_results
 
-        self.set_optimizations(optimizations)
+        self.optimizations = optimizations
+        for opt in optimizations:
+            opt.optimizer = self
         self.setup()
 
-    def set_optimizations(self, optimizations):
-        if optimizations:
-            self.first_optimization = optimizations[0]
-            for i in range(1, len(optimizations)):
-                optimizations[i - 1].next_optimization = optimizations[i]
-            optimizations[-1].next_optimization = self
-            for o in optimizations:
-                o.optimizer = self
-                o.last_emitted_operation = None
-                o.setup()
-        else:
-            optimizations = []
-            self.first_optimization = self
-
-        self.optimizations  = optimizations
-
     def force_at_end_of_preamble(self):
         for o in self.optimizations:
             o.force_at_end_of_preamble()
@@ -441,20 +421,29 @@
         self.metainterp_sd.profiler.count(jitprof.Counters.OPT_FORCINGS)
         self.resumedata_memo.forget_numberings(virtualbox)
 
-    def getvalue(self, box):
-        if box.is_constant():
-            if box.type == REF:
-                if not box.getref_base():
+    def getforwarded(self, op):
+        if op.is_constant():
+            if op.type == REF:
+                if not op.getref_base():
                     return CONST_NULL
                 try:
-                    return self.interned_refs[box.getref_base()]
+                    return self.interned_refs[op.getref_base()]
                 except KeyError:
-                    self.interned_refs[box.getref_base()] = box
-                    return box
-            return box
-        value = box._forwarded
+                    self.interned_refs[op.getref_base()] = op
+                    return op
+            return op
+        value = op._forwarded
         if value is None:
-            value = box.make_forwarded_copy()
+            value = op.make_forwarded_copy()
+        else:
+            if value._forwarded:
+                while value._forwarded:
+                    value = value._forwarded
+                to_patch = op
+                while to_patch._forwarded:
+                    next = to_patch._forwarded
+                    to_patch._forwarded = value
+                    to_patch = next
         #self.ensure_imported(value)
         return value
 
@@ -465,13 +454,15 @@
         box.set_extra("optimize_value", value)
 
     def copy_op_if_modified_by_optimization(self, op):
+        xxxx
         new_op = op.copy_if_modified_by_optimization(self)
         if new_op is not op:
             self.replace(op, new_op)
         return new_op
 
     # XXX some RPython magic needed
-    def copy_and_change(self, op, *args, **kwds): 
+    def copy_and_change(self, op, *args, **kwds):
+        xxx
         new_op = op.copy_and_change(*args, **kwds)
         if new_op is not op:
             self.replace(op, new_op)
@@ -481,19 +472,10 @@
         pass
 
     @specialize.argtype(0)
-    def get_constant_box(self, box):
-        if isinstance(box, Const):
-            return box
-        try:
-            value = self.getvalue(box)
-            self.ensure_imported(value)
-        except KeyError:
-            return None
-        if value.is_constant():
-            constbox = value.op
-            assert isinstance(constbox, Const)
-            return constbox
-        return None
+    def get_constant_op(self, op):
+        op = self.getforwarded(op)
+        if isinstance(op, Const):
+            return op
 
     def get_newoperations(self):
         self.flush()
@@ -502,20 +484,6 @@
     def clear_newoperations(self):
         self._newoperations = []
 
-    def replace(self, what, with_):
-        assert isinstance(what, AbstractValue)
-        assert isinstance(with_, AbstractValue)
-        assert not what.has_extra("optimize_replace")
-        assert not what.is_constant()
-        if what.has_extra("optimize_value"):
-            v = what.get_extra("optimize_value")
-            v.op = with_
-            with_.set_extra("optimize_value", v)
-        #if not we_are_translated():
-        #    if what.has_extra("optimize_value"):
-        #        what.get_extra("optimize_value").__class__ = exploder
-        what.set_extra("optimize_replace", with_)
-
     def make_constant(self, box, constbox):
         self.getvalue(box).make_constant(constbox)
 
@@ -560,14 +528,16 @@
     def propagate_all_forward(self, clear=True):
         if clear:
             self.clear_newoperations()
-        for op in self.loop.operations:
-            self.first_optimization.propagate_forward(op)
-        for arg in self.loop.inputargs:
-            arg.del_extra("optimize_value")
-            arg.del_extra("optimize_replace")
-        for op in self.loop.operations:
-            op.del_extra("optimize_value")
-            op.del_extra("optimize_replace")
+        i = 0
+        while i < len(self.loop.operations):
+            op = self.loop.operations[i]
+            for opt in self.optimizations:
+                op = opt.optimize_operation(op)
+                if op is None:
+                    break
+            else:
+                self.emit_operation(op)
+            i += 1
         self.loop.operations = self.get_newoperations()
         self.loop.quasi_immutable_deps = self.quasi_immutable_deps
         # accumulate counters
@@ -584,22 +554,10 @@
             self.getvalue(op).is_bool_box = True
         self._emit_operation(op)
 
-    def get_value_replacement(self, box):
-        try:
-            value = self.getvalue(box)
-        except KeyError:
-            return None
-        else:
-            self.ensure_imported(value)
-            forced_box = value.force_box(self)
-            if forced_box is box:
-                return None
-            return forced_box
-
     @specialize.argtype(0)
     def _emit_operation(self, op):
         assert op.getopnum() not in opgroups.CALL_PURE
-        op = self.copy_op_if_modified_by_optimization(op)
+        assert not op._forwarded
         if isinstance(op, Const):
             return
         self.metainterp_sd.profiler.count(jitprof.Counters.OPT_OPS)
@@ -613,6 +571,7 @@
         self._newoperations.append(op)
 
     def store_final_boxes_in_guard(self, op):
+        return # XXX we disable it for tests
         assert op.getdescr() is None
         descr = op.invent_descr(self.jitdriver_sd, self.metainterp_sd)
         op.setdescr(descr)
diff --git a/pypy/jit/metainterp/optimizeopt/pure.py 
b/pypy/jit/metainterp/optimizeopt/pure.py
--- a/pypy/jit/metainterp/optimizeopt/pure.py
+++ b/pypy/jit/metainterp/optimizeopt/pure.py
@@ -11,9 +11,6 @@
         self.pure_operations = ArgsDict()
         self.emitted_pure_operations = []
 
-    def propagate_forward(self, op):
-        dispatch_opt(self, op)
-
     def optimize_default(self, op):
         canfold = op.is_always_pure()
         if op.is_ovf():
@@ -27,9 +24,10 @@
         else:
             nextop = None
 
+        newop = self.getforwarded(op)
         if canfold:
             for i in range(op.numargs()):
-                if self.get_constant_box(op.getarg(i)) is None:
+                if self.get_constant_op(op.getarg(i)) is None:
                     break
             else:
                 # all constant arguments: constant-fold away
@@ -40,21 +38,20 @@
                 return
 
             # did we do the exact same operation already?
-            key_op = op.get_key_op(self.optimizer)
-            oldop = self.pure_operations.get(key_op)
+            oldop = self.pure_operations.get(newop)
             if oldop is not None:
                 self.replace(op, oldop)
                 return
             else:
-                self.pure_operations.set(key_op, op)
+                self.pure_operations.set(newop, op)
                 self.remember_emitting_pure(op)
 
         # otherwise, the operation remains
-        self.emit_operation(op)
         if op.returns_bool_result():
-            self.getvalue(op).is_bool_box = True
+            newop.is_bool_box = True
         if nextop:
             self.emit_operation(nextop)
+        return newop
 
     def _new_optimize_call_pure(opnum):
         def optimize_CALL_PURE(self, op):
@@ -131,5 +128,5 @@
                     continue
             sb.add_potential(op)
 
-dispatch_opt = make_dispatcher_method(OptPure, 'optimize_',
-                                      default=OptPure.optimize_default)
+#dispatch_opt = make_dispatcher_method(OptPure, 'optimize_',
+#                                      default=OptPure.optimize_default)
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
@@ -524,6 +524,6 @@
     optimize_SAME_AS_r = optimize_SAME_AS_i
     optimize_SAME_AS_f = optimize_SAME_AS_i
 
-dispatch_opt = make_dispatcher_method(OptRewrite, 'optimize_',
-        default=OptRewrite.emit_operation)
-optimize_guards = _findall(OptRewrite, 'optimize_', 'GUARD')
+#dispatch_opt = make_dispatcher_method(OptRewrite, 'optimize_',
+#        default=OptRewrite.emit_operation)
+#optimize_guards = _findall(OptRewrite, 'optimize_', 'GUARD')
diff --git a/pypy/jit/metainterp/optimizeopt/simplify.py 
b/pypy/jit/metainterp/optimizeopt/simplify.py
--- a/pypy/jit/metainterp/optimizeopt/simplify.py
+++ b/pypy/jit/metainterp/optimizeopt/simplify.py
@@ -64,6 +64,6 @@
                                                     descr=newdescr)
         self.emit_operation(op)
 
-dispatch_opt = make_dispatcher_method(OptSimplify, 'optimize_',
-        default=OptSimplify.emit_operation)
-OptSimplify.propagate_forward = dispatch_opt
+#dispatch_opt = make_dispatcher_method(OptSimplify, 'optimize_',
+#        default=OptSimplify.emit_operation)
+#OptSimplify.propagate_forward = dispatch_opt
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py 
b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -134,13 +134,13 @@
         ops = """
         [i]
         i0 = int_sub(i, 1)
-        guard_value(i0, 0) [i0]
+        guard_value(i0, 0)
         jump(i)
         """
         expected = """
         [i]
         i0 = int_sub(i, 1)
-        guard_value(i0, 0) [i0]
+        guard_value(i0, 0)
         jump(1)
         """
         self.optimize_loop(ops, expected)
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
@@ -28,6 +28,7 @@
             imp.import_value(value)
 
     def emit_operation(self, op):
+        xxx
         if op.returns_bool_result():
             self.bool_boxes[self.getvalue(op)] = None
         if self.emitting_dissabled:
diff --git a/pypy/jit/metainterp/optimizeopt/util.py 
b/pypy/jit/metainterp/optimizeopt/util.py
--- a/pypy/jit/metainterp/optimizeopt/util.py
+++ b/pypy/jit/metainterp/optimizeopt/util.py
@@ -172,8 +172,8 @@
     text_right = text_right or 'expected'
     print '%s| %s' % ('optimized'.center(width), text_right.center(width))
     for op1, op2 in zip(oplist1, oplist2):
-        txt1 = str(op1)
-        txt2 = str(op2)
+        txt1 = repr(op1)
+        txt2 = repr(op2)
         while txt1 or txt2:
             print '%s| %s' % (txt1[:width].ljust(width), txt2[:width])
             txt1 = txt1[width:]
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
@@ -558,7 +558,7 @@
         self.emit_operation(op)
 
 
-dispatch_opt = make_dispatcher_method(OptVirtualize, 'optimize_',
-        default=OptVirtualize.emit_operation)
+#dispatch_opt = make_dispatcher_method(OptVirtualize, 'optimize_',
+#        default=OptVirtualize.emit_operation)
 
-OptVirtualize.propagate_forward = dispatch_opt
+#OptVirtualize.propagate_forward = dispatch_opt
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
@@ -728,8 +728,8 @@
     def propagate_forward(self, op):
         dispatch_opt(self, op)
 
-dispatch_opt = make_dispatcher_method(OptString, 'optimize_',
-        default=OptString.emit_operation)
+#dispatch_opt = make_dispatcher_method(OptString, 'optimize_',
+#        default=OptString.emit_operation)
 
 def _findall_call_oopspec():
     prefix = 'opt_call_stroruni_'
diff --git a/pypy/jit/metainterp/resoperation.py 
b/pypy/jit/metainterp/resoperation.py
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -474,7 +474,7 @@
         # XXX this is a hack kill me
         import sys
         co_fname = sys._getframe(1).f_code.co_filename
-        if co_fname.endswith('resume.py') or 
co_fname.endswith('optimizeopt/util.py') or 'backend/llgraph' in co_fname or 
'backend/test' in co_fname:
+        if co_fname.endswith('resume.py') or 
co_fname.endswith('optimizeopt/util.py') or 'backend/llgraph' in co_fname or 
'backend/test' in co_fname or 'test/test_util' in co_fname:
             return object.__hash__(self)
         raise Exception("Should not hash resops, use get/set extra instead")
 
@@ -650,6 +650,13 @@
             return False     # for tests
         return opboolresult[opnum]
 
+    # some debugging help
+
+    def __setattr__(self, attr, val):
+        if attr not in ['_hash', '_str']:
+            assert self._forwarded is None
+        object.__setattr__(self, attr, val)
+
 # ===========
 # type mixins
 # ===========
diff --git a/pypy/jit/metainterp/resume.py b/pypy/jit/metainterp/resume.py
--- a/pypy/jit/metainterp/resume.py
+++ b/pypy/jit/metainterp/resume.py
@@ -198,9 +198,8 @@
         length = len(boxes)
         numb = lltype.malloc(NUMBERING, length)
         for i in range(length):
-            box = boxes[i]
-            value = optimizer.getvalue(box)
-            box = value.get_key_box()
+            op = boxes[i]
+            optimized_op = optimizer.get_optimized_op(op)
 
             if isinstance(box, Const):
                 tagged = self.getconst(box)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to