[pypy-commit] pypy optresult: A bunch of progress

fijal noreply at buildbot.pypy.org
Sun Nov 23 08:52:40 CET 2014


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: optresult
Changeset: r74644:2806b8d08734
Date: 2014-11-23 09:52 +0200
http://bitbucket.org/pypy/pypy/changeset/2806b8d08734/

Log:	A bunch of progress

diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py
--- a/rpython/jit/backend/llgraph/runner.py
+++ b/rpython/jit/backend/llgraph/runner.py
@@ -497,7 +497,9 @@
         array = a._obj
         return support.cast_result(descr.A.OF, array.getitem(index))
 
-    bh_getarrayitem_gc_pure = bh_getarrayitem_gc
+    bh_getarrayitem_gc_pure_i = bh_getarrayitem_gc
+    bh_getarrayitem_gc_pure_r = bh_getarrayitem_gc
+    bh_getarrayitem_gc_pure_f = bh_getarrayitem_gc
     bh_getarrayitem_gc_i = bh_getarrayitem_gc
     bh_getarrayitem_gc_r = bh_getarrayitem_gc
     bh_getarrayitem_gc_f = bh_getarrayitem_gc
diff --git a/rpython/jit/metainterp/executor.py b/rpython/jit/metainterp/executor.py
--- a/rpython/jit/metainterp/executor.py
+++ b/rpython/jit/metainterp/executor.py
@@ -466,6 +466,15 @@
     else:
         assert lltype.typeOf(value) == llmemory.GCREF
         return ConstPtr(value)
+
+def constant_from_op(op):
+    if op.type == 'i':
+        return ConstInt(op.getint())
+    elif op.type == 'r':
+        return ConstPtr(op.getref_base())
+    else:
+        assert op.type == 'f'
+        return ConstFloat(op.getfloatstorage())
     
 def execute_nonspec_const(cpu, metainterp, opnum, argboxes, descr=None,
                           type='i'):
diff --git a/rpython/jit/metainterp/history.py b/rpython/jit/metainterp/history.py
--- a/rpython/jit/metainterp/history.py
+++ b/rpython/jit/metainterp/history.py
@@ -780,6 +780,11 @@
         self.operations.append(op)
         return op
 
+    def record_default_val(self, opnum, argboxes, descr=None):
+        op = ResOperation(opnum, argboxes, descr)
+        self.operations.append(op)
+        return op        
+
     def substitute_operation(self, position, opnum, argboxes, descr=None):
         resbox = self.operations[position].result
         op = ResOperation(opnum, argboxes, resbox, descr)
diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py
--- a/rpython/jit/metainterp/optimizeopt/optimizer.py
+++ b/rpython/jit/metainterp/optimizeopt/optimizer.py
@@ -340,20 +340,6 @@
             return self.optimizer.optpure.get_pure_result(key)
         return None
 
-    def getfield_pure_for_descr(self, descr):
-        if descr.is_pointer_field():
-            return rop.GETFIELD_GC_PURE_R
-        elif descr.is_float_field():
-            return rop.GETFIELD_GC_PURE_F
-        return rop.GETFIELD_GC_PURE_I
-
-    def getarrayitem_pure_for_descr(self, descr):
-        if descr.is_array_of_pointers():
-            return rop.GETARRAYITEM_GC_PURE_R
-        elif descr.is_array_of_floats():
-            return rop.GETARRAYITEM_GC_PURE_F
-        return rop.GETARRAYITEM_GC_PURE_I
-
     def setup(self):
         pass
 
@@ -716,7 +702,7 @@
     # dissabled and unrolling emits some SAME_AS ops to setup the
     # optimizier state. These needs to always be optimized out.
     def optimize_SAME_AS_I(self, op):
-        self.make_equal_to(op.result, self.getvalue(op.getarg(0)))
+        self.make_equal_to(op, self.getvalue(op.getarg(0)))
     optimize_SAME_AS_R = optimize_SAME_AS_I
     optimize_SAME_AS_F = optimize_SAME_AS_I
 
diff --git a/rpython/jit/metainterp/optimizeopt/simplify.py b/rpython/jit/metainterp/optimizeopt/simplify.py
--- a/rpython/jit/metainterp/optimizeopt/simplify.py
+++ b/rpython/jit/metainterp/optimizeopt/simplify.py
@@ -1,6 +1,6 @@
 from rpython.jit.metainterp.optimizeopt.optimizer import Optimization
 from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
-from rpython.jit.metainterp.resoperation import ResOperation, rop
+from rpython.jit.metainterp.resoperation import ResOperation, rop, OpHelpers
 from rpython.jit.metainterp.history import TargetToken, JitCellToken
 
 class OptSimplify(Optimization):
@@ -15,9 +15,9 @@
         Optimization.emit_operation(self, op)
 
     def optimize_CALL_PURE_I(self, op):
-        args = op.getarglist()
-        self.emit_operation(ResOperation(rop.CALL, args, op.result,
-                                         op.getdescr()))
+        opnum = OpHelpers.call_for_descr(op.getdescr())
+        newop = self.optimizer.replace_op_with(op, opnum)
+        self.emit_operation(newop)
     optimize_CALL_PURE_R = optimize_CALL_PURE_I
     optimize_CALL_PURE_F = optimize_CALL_PURE_I
     optimize_CALL_PURE_N = optimize_CALL_PURE_I
diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py
--- a/rpython/jit/metainterp/pyjitpl.py
+++ b/rpython/jit/metainterp/pyjitpl.py
@@ -157,13 +157,13 @@
         return env
 
     def replace_active_box_in_frame(self, oldbox, newbox):
-        if isinstance(oldbox, history.BoxInt):
+        if oldbox.type == 'i':
             count = self.jitcode.num_regs_i()
             registers = self.registers_i
-        elif isinstance(oldbox, history.BoxPtr):
+        elif oldbox.type == 'r':
             count = self.jitcode.num_regs_r()
             registers = self.registers_r
-        elif isinstance(oldbox, history.BoxFloat):
+        elif oldbox.type == 'f':
             count = self.jitcode.num_regs_f()
             registers = self.registers_f
         else:
@@ -377,7 +377,7 @@
             if not isinstance(box, Const):
                 self.metainterp.generate_guard(rop.GUARD_ISNULL, box,
                                                resumepc=orgpc)
-                promoted_box = box.constbox()
+                promoted_box = executor.constant_from_op(box)
                 self.metainterp.replace_box(box, promoted_box)
         return value
 
@@ -440,23 +440,30 @@
         if tobox:
             # sanity check: see whether the current array value
             # corresponds to what the cache thinks the value is
+            xxx
             resbox = executor.execute(self.metainterp.cpu, self.metainterp, op,
                                       arraydescr, arraybox, indexbox)
             assert resbox.constbox().same_constant(tobox.constbox())
             return tobox
-        resbox = self.execute_with_descr(op, arraydescr, arraybox, indexbox)
+        resop = self.execute_with_descr(op, arraydescr, arraybox, indexbox)
         self.metainterp.heapcache.getarrayitem_now_known(
-                arraybox, indexbox, resbox, arraydescr)
-        return resbox
+                arraybox, indexbox, resop, arraydescr)
+        return resop
 
     @arguments("box", "box", "descr")
-    def _opimpl_getarrayitem_gc_any(self, arraybox, indexbox, arraydescr):
-        return self._do_getarrayitem_gc_any(rop.GETARRAYITEM_GC, arraybox,
+    def opimpl_getarrayitem_gc_i(self, arraybox, indexbox, arraydescr):
+        return self._do_getarrayitem_gc_any(rop.GETARRAYITEM_GC_I, arraybox,
                                             indexbox, arraydescr)
 
-    opimpl_getarrayitem_gc_i = _opimpl_getarrayitem_gc_any
-    opimpl_getarrayitem_gc_r = _opimpl_getarrayitem_gc_any
-    opimpl_getarrayitem_gc_f = _opimpl_getarrayitem_gc_any
+    @arguments("box", "box", "descr")
+    def opimpl_getarrayitem_gc_r(self, arraybox, indexbox, arraydescr):
+        return self._do_getarrayitem_gc_any(rop.GETARRAYITEM_GC_R, arraybox,
+                                            indexbox, arraydescr)
+
+    @arguments("box", "box", "descr")
+    def opimpl_getarrayitem_gc_f(self, arraybox, indexbox, arraydescr):
+        return self._do_getarrayitem_gc_any(rop.GETARRAYITEM_GC_F, arraybox,
+                                            indexbox, arraydescr)
 
     @arguments("box", "box", "descr")
     def _opimpl_getarrayitem_raw_any(self, arraybox, indexbox, arraydescr):
@@ -476,20 +483,40 @@
     opimpl_getarrayitem_raw_f_pure = _opimpl_getarrayitem_raw_pure_any
 
     @arguments("box", "box", "descr")
-    def _opimpl_getarrayitem_gc_pure_any(self, arraybox, indexbox, arraydescr):
+    def opimpl_getarrayitem_gc_i_pure(self, arraybox, indexbox, arraydescr):
         if isinstance(arraybox, ConstPtr) and isinstance(indexbox, ConstInt):
             # if the arguments are directly constants, bypass the heapcache
             # completely
-            resbox = executor.execute(self.metainterp.cpu, self.metainterp,
-                                      rop.GETARRAYITEM_GC_PURE, arraydescr,
+            val = executor.execute(self.metainterp.cpu, self.metainterp,
+                                      rop.GETARRAYITEM_GC_PURE_I, arraydescr,
                                       arraybox, indexbox)
-            return resbox.constbox()
-        return self._do_getarrayitem_gc_any(rop.GETARRAYITEM_GC_PURE, arraybox,
-                                            indexbox, arraydescr)
+            return executor.wrap_constant(val)
+        return self._do_getarrayitem_gc_any(rop.GETARRAYITEM_GC_PURE_I,
+                                            arraybox, indexbox, arraydescr)
 
-    opimpl_getarrayitem_gc_i_pure = _opimpl_getarrayitem_gc_pure_any
-    opimpl_getarrayitem_gc_r_pure = _opimpl_getarrayitem_gc_pure_any
-    opimpl_getarrayitem_gc_f_pure = _opimpl_getarrayitem_gc_pure_any
+    @arguments("box", "box", "descr")
+    def opimpl_getarrayitem_gc_f_pure(self, arraybox, indexbox, arraydescr):
+        if isinstance(arraybox, ConstPtr) and isinstance(indexbox, ConstInt):
+            # if the arguments are directly constants, bypass the heapcache
+            # completely
+            resval = executor.execute(self.metainterp.cpu, self.metainterp,
+                                      rop.GETARRAYITEM_GC_PURE_F, arraydescr,
+                                      arraybox, indexbox)
+            return executor.wrap_constant(resval)
+        return self._do_getarrayitem_gc_any(rop.GETARRAYITEM_GC_PURE_F,
+                                            arraybox, indexbox, arraydescr)
+
+    @arguments("box", "box", "descr")
+    def opimpl_getarrayitem_gc_r_pure(self, arraybox, indexbox, arraydescr):
+        if isinstance(arraybox, ConstPtr) and isinstance(indexbox, ConstInt):
+            # if the arguments are directly constants, bypass the heapcache
+            # completely
+            val = executor.execute(self.metainterp.cpu, self.metainterp,
+                                      rop.GETARRAYITEM_GC_PURE_R, arraydescr,
+                                      arraybox, indexbox)
+            return executor.wrap_constant(val)
+        return self._do_getarrayitem_gc_any(rop.GETARRAYITEM_GC_PURE_R,
+                                            arraybox, indexbox, arraydescr)
 
     @arguments("box", "box", "box", "descr")
     def _opimpl_setarrayitem_gc_any(self, arraybox, indexbox, itembox,
@@ -1355,7 +1382,7 @@
         if isinstance(box, Const):
             return box     # no promotion needed, already a Const
         else:
-            promoted_box = box.constbox()
+            promoted_box = executor.constant_from_op(box)
             self.metainterp.generate_guard(rop.GUARD_VALUE, box, [promoted_box],
                                            resumepc=orgpc)
             self.metainterp.replace_box(box, promoted_box)
@@ -1375,20 +1402,20 @@
     @specialize.arg(1)
     def execute_varargs(self, opnum, argboxes, descr, exc, pure):
         self.metainterp.clear_exception()
-        resbox = self.metainterp.execute_and_record_varargs(opnum, argboxes,
+        op = self.metainterp.execute_and_record_varargs(opnum, argboxes,
                                                             descr=descr)
-        if pure and self.metainterp.last_exc_value_box is None and resbox:
-            resbox = self.metainterp.record_result_of_call_pure(resbox)
-            exc = exc and not isinstance(resbox, Const)
+        if pure and self.metainterp.last_exc_value_box is None and op:
+            op = self.metainterp.record_result_of_call_pure(op)
+            exc = exc and not isinstance(op, Const)
         if exc:
-            if resbox is not None:
-                self.make_result_of_lastop(resbox)
+            if op is not None:
+                self.make_result_of_lastop(op)
                 # ^^^ this is done before handle_possible_exception() because we
                 # need the box to show up in get_list_of_active_boxes()
             self.metainterp.handle_possible_exception()
         else:
             self.metainterp.assert_no_exception()
-        return resbox
+        return op
 
     def _build_allboxes(self, funcbox, argboxes, descr):
         allboxes = [None] * (len(argboxes)+1)
@@ -2158,10 +2185,9 @@
         for i in range(endindex):
             box = boxes[i]
             if isinstance(box, Const) or box in duplicates:
-                oldbox = box
-                box = oldbox.clonebox()
-                boxes[i] = box
-                self.history.record(rop.SAME_AS, [oldbox], box)
+                opnum = OpHelpers.same_as_for_type(box.type)
+                op = self.history.record_default_val(opnum, [box])
+                boxes[i] = op
             else:
                 duplicates[box] = None
 
@@ -2708,7 +2734,6 @@
                                 None, descr=vinfo.vable_token_descr)
 
     def replace_box(self, oldbox, newbox):
-        assert isinstance(oldbox, Box)
         for frame in self.framestack:
             frame.replace_active_box_in_frame(oldbox, newbox)
         boxes = self.virtualref_boxes
@@ -2745,12 +2770,12 @@
                 max_key = key
         return max_key
 
-    def record_result_of_call_pure(self, resbox):
+    def record_result_of_call_pure(self, op):
         """ Patch a CALL into a CALL_PURE.
         """
-        op = self.history.operations[-1]
-        assert op.getopnum() == rop.CALL
-        resbox_as_const = resbox.constbox()
+        opnum = op.getopnum()
+        assert opnum in [rop.CALL_R, rop.CALL_N, rop.CALL_I, rop.CALL_F]
+        resbox_as_const = executor.constant_from_op(op)
         for i in range(op.numargs()):
             if not isinstance(op.getarg(i), Const):
                 break
@@ -2761,11 +2786,12 @@
             return resbox_as_const
         # not all constants (so far): turn CALL into CALL_PURE, which might
         # be either removed later by optimizeopt or turned back into CALL.
-        arg_consts = [a.constbox() for a in op.getarglist()]
+        arg_consts = [executor.constant_from_op(a) for a in op.getarglist()]
         self.call_pure_results[arg_consts] = resbox_as_const
-        newop = op.copy_and_change(rop.CALL_PURE, args=op.getarglist())
+        opnum = OpHelpers.call_pure_for_descr(op.getdescr())
+        newop = op._copy_and_change(opnum, args=op.getarglist())
         self.history.operations[-1] = newop
-        return resbox
+        return newop
 
     def direct_assembler_call(self, targetjitdriver_sd):
         """ Generate a direct call to assembler for portal entry point,
diff --git a/rpython/jit/metainterp/resoperation.py b/rpython/jit/metainterp/resoperation.py
--- a/rpython/jit/metainterp/resoperation.py
+++ b/rpython/jit/metainterp/resoperation.py
@@ -1,6 +1,7 @@
 from rpython.rlib.objectmodel import we_are_translated, specialize
 from rpython.rlib.objectmodel import compute_identity_hash
 from rpython.rtyper.lltypesystem import lltype, llmemory
+from rpython.jit.codewriter import longlong
 
 class AbstractValue(object):
     def _get_hash_(self):
@@ -303,6 +304,9 @@
     def copy_value_from(self, other):
         self.setint(other.getint())
 
+    def nonnull(self):
+        return self._resint != 0
+
 class FloatOp(object):
     _mixin_ = True
 
@@ -319,6 +323,9 @@
     def copy_value_from(self, other):
         self.setfloatstorage(other.getfloatstorage())
 
+    def nonnull(self):
+        return bool(longlong.extract_bits(self._resfloat))
+
 class RefOp(object):
     _mixin_ = True
 
@@ -335,6 +342,9 @@
     def copy_value_from(self, other):
         self.setref_base(other.getref_base())
 
+    def nonnull(self):
+        return bool(self._resref)
+
 class AbstractInputArg(AbstractValue):    
     def repr(self, memo):
         try:
@@ -880,3 +890,41 @@
             return rop.CALL_F
         assert tp == 'v'
         return rop.CALL_N
+
+    @staticmethod
+    def call_pure_for_descr(descr):
+        tp = descr.get_result_type()
+        if tp == 'i':
+            return rop.CALL_PURE_I
+        elif tp == 'r':
+            return rop.CALL_PURE_R
+        elif tp == 'f':
+            return rop.CALL_PURE_F
+        assert tp == 'v'
+        return rop.CALL_PURE_N
+
+    @staticmethod
+    def getfield_pure_for_descr(descr):
+        if descr.is_pointer_field():
+            return rop.GETFIELD_GC_PURE_R
+        elif descr.is_float_field():
+            return rop.GETFIELD_GC_PURE_F
+        return rop.GETFIELD_GC_PURE_I
+
+    @staticmethod
+    def getarrayitem_pure_for_descr(descr):
+        if descr.is_array_of_pointers():
+            return rop.GETARRAYITEM_GC_PURE_R
+        elif descr.is_array_of_floats():
+            return rop.GETARRAYITEM_GC_PURE_F
+        return rop.GETARRAYITEM_GC_PURE_I
+
+    @staticmethod
+    def same_as_for_type(tp):
+        if tp == 'i':
+            return rop.SAME_AS_I
+        elif tp == 'r':
+            return rop.SAME_AS_R
+        else:
+            assert tp == 'f'
+            return rop.SAME_AS_F
diff --git a/rpython/jit/metainterp/test/test_loop.py b/rpython/jit/metainterp/test/test_loop.py
--- a/rpython/jit/metainterp/test/test_loop.py
+++ b/rpython/jit/metainterp/test/test_loop.py
@@ -191,8 +191,8 @@
                 if op.getopname() == 'guard_true':
                     liveboxes = op.getfailargs()
                     assert len(liveboxes) == 2     # x, y (in some order)
-                    assert isinstance(liveboxes[0], history.BoxInt)
-                    assert isinstance(liveboxes[1], history.BoxInt)
+                    assert liveboxes[0].type == 'i'
+                    assert liveboxes[1].type == 'i'
                     found += 1
             if 'unroll' in self.enable_opts:
                 assert found == 2
diff --git a/rpython/jit/metainterp/typesystem.py b/rpython/jit/metainterp/typesystem.py
--- a/rpython/jit/metainterp/typesystem.py
+++ b/rpython/jit/metainterp/typesystem.py
@@ -66,7 +66,8 @@
         return llmemory.cast_ptr_to_adr(fnptr)
 
     def cls_of_box(self, box):
-        obj = box.getref(lltype.Ptr(rclass.OBJECT))
+        PTR = lltype.Ptr(rclass.OBJECT)
+        obj = lltype.cast_opaque_ptr(PTR, box.getref_base())
         cls = llmemory.cast_ptr_to_adr(obj.typeptr)
         return history.ConstInt(heaptracker.adr2int(cls))
 


More information about the pypy-commit mailing list