Author: Carl Friedrich Bolz <cfb...@gmx.de>
Branch: guard-compatible
Changeset: r85359:497da7b013d3
Date: 2016-06-23 14:49 +0200
http://bitbucket.org/pypy/pypy/changeset/497da7b013d3/

Log:    a test for a bridge that jumps to the loop. causes all kinds of
        problems.

diff --git a/rpython/jit/metainterp/compatible.py 
b/rpython/jit/metainterp/compatible.py
--- a/rpython/jit/metainterp/compatible.py
+++ b/rpython/jit/metainterp/compatible.py
@@ -131,6 +131,10 @@
     def emit_conditions(self, op, short, optimizer):
         """ re-emit the conditions about variable op into the short preamble
         """
+        from rpython.jit.metainterp.resoperation import rop, ResOperation
+        short.append(
+            ResOperation(rop.GUARD_COMPATIBLE, [
+                op, self.known_valid]))
         for cond in self.conditions:
             cond.emit_condition(op, short, optimizer)
 
@@ -140,13 +144,22 @@
         do nothing. If it is not, check whether ref matches the condition. If
         not return False, otherwise emit guards for the condition. Return True
         at the end. """
+        from rpython.jit.metainterp.resoperation import rop, ResOperation
+        have_guard = False
         for cond in self.conditions:
             if other is None or not other.contains_condition(cond):
                 if const is None:
                     return False
                 ref = const.getref_base()
                 if cond.check(cpu, ref):
-                    cond.emit_condition(op, short, optimizer)
+                    if not have_guard:
+                        # NB: the guard_compatible here needs to use const,
+                        # otherwise the optimizer will just complain
+                        extra_guards.append(ResOperation(
+                            rop.GUARD_COMPATIBLE,
+                                [op, const]))
+                        have_guard = True
+                    cond.emit_condition(op, extra_guards, optimizer, const)
                 else:
                     return False
         return True
@@ -185,7 +198,7 @@
     def repr(self):
         return ""
 
-    def emit_condition(self, op, short, optimizer):
+    def emit_condition(self, op, short, optimizer, const=None):
         raise NotImplementedError("abstract base class")
 
     def _repr_const(self, arg):
@@ -263,7 +276,7 @@
                 return False
         return True
 
-    def emit_condition(self, op, short, optimizer):
+    def emit_condition(self, op, short, optimizer, const=None):
         from rpython.jit.metainterp.history import INT, REF, FLOAT, VOID
         from rpython.jit.metainterp.resoperation import rop, ResOperation
         # woah, mess
@@ -283,6 +296,11 @@
             call_op = ResOperation(rop.CALL_PURE_R, args, descr)
             short.append(call_op)
             return
+        # add result to call_pure_results
+        if const is not None:
+            args = args[:]
+            args[1] = const
+            optimizer.call_pure_results[args] = self.res
         short.append(call_op)
         short.append(ResOperation(rop.GUARD_VALUE, [call_op, self.res]))
 
@@ -375,7 +393,7 @@
                 return False
         return True
 
-    def emit_condition(self, op, short, optimizer):
+    def emit_condition(self, op, short, optimizer, const=None):
         from rpython.jit.metainterp.resoperation import rop, ResOperation
         # more mess
         fielddescr = self.fielddescr
@@ -395,12 +413,18 @@
                 rop.GUARD_NOT_INVALIDATED, []),
             getfield_op])
         index = len(short)
-        PureCallCondition.emit_condition(self, op, short, optimizer)
+        PureCallCondition.emit_condition(self, op, short, optimizer, const)
         call_op = short[index]
+        # puh, not pretty
+        args = call_op.getarglist()
+        if const is not None:
+            del optimizer.call_pure_results[args]
         assert call_op.opnum in (
                 rop.CALL_PURE_I, rop.CALL_PURE_R,
                 rop.CALL_PURE_F, rop.CALL_PURE_N)
         call_op.setarg(2, getfield_op)
+        if const is not None:
+            optimizer.call_pure_results[call_op.getarglist()] = self.res
 
     def repr(self, argrepr="?"):
         addr = self.args[0].getaddr()
diff --git a/rpython/jit/metainterp/optimizeopt/info.py 
b/rpython/jit/metainterp/optimizeopt/info.py
--- a/rpython/jit/metainterp/optimizeopt/info.py
+++ b/rpython/jit/metainterp/optimizeopt/info.py
@@ -81,9 +81,6 @@
         compat_cond = self._compatibility_conditions
         if compat_cond is None:
             return
-        short.append(
-            ResOperation(rop.GUARD_COMPATIBLE, [
-                op, compat_cond.known_valid]))
         compat_cond.emit_conditions(op, short, optimizer)
 
     @specialize.arg(2)
diff --git a/rpython/jit/metainterp/optimizeopt/unroll.py 
b/rpython/jit/metainterp/optimizeopt/unroll.py
--- a/rpython/jit/metainterp/optimizeopt/unroll.py
+++ b/rpython/jit/metainterp/optimizeopt/unroll.py
@@ -310,7 +310,10 @@
                 for guard in extra_guards.extra_guards:
                     if isinstance(guard, GuardResOp):
                         guard.rd_resume_position = 
patchguardop.rd_resume_position
-                        guard.setdescr(compile.ResumeAtPositionDescr())
+                        if guard.opnum == rop.GUARD_COMPATIBLE:
+                            guard.setdescr(compile.GuardCompatibleDescr())
+                        else:
+                            guard.setdescr(compile.ResumeAtPositionDescr())
                     self.send_extra_operation(guard)
             except VirtualStatesCantMatch:
                 continue
@@ -375,8 +378,12 @@
                 sop = short[i]
                 arglist = self._map_args(mapping, sop.getarglist())
                 if sop.is_guard():
+                    if sop.opnum == rop.GUARD_COMPATIBLE:
+                        descr = compile.GuardCompatibleDescr()
+                    else:
+                        descr = compile.ResumeAtPositionDescr()
                     op = sop.copy_and_change(sop.getopnum(), arglist,
-                                    descr=compile.ResumeAtPositionDescr())
+                                    descr=descr)
                     assert isinstance(op, GuardResOp)
                     op.rd_resume_position = patchguardop.rd_resume_position
                 else:
diff --git a/rpython/jit/metainterp/optimizeopt/virtualstate.py 
b/rpython/jit/metainterp/optimizeopt/virtualstate.py
--- a/rpython/jit/metainterp/optimizeopt/virtualstate.py
+++ b/rpython/jit/metainterp/optimizeopt/virtualstate.py
@@ -355,7 +355,7 @@
     if type == 'i':
         return NotVirtualStateInfoInt(cpu, type, info)
     if type == 'r':
-        if info._compatibility_conditions is not None:
+        if info is not None and info._compatibility_conditions is not None:
             return NotVirtualStateInfoPtrCompatible(cpu, type, info)
         return NotVirtualStateInfoPtr(cpu, type, info)
     return NotVirtualStateInfo(cpu, type, info)
diff --git a/rpython/jit/metainterp/test/test_compatible.py 
b/rpython/jit/metainterp/test/test_compatible.py
--- a/rpython/jit/metainterp/test/test_compatible.py
+++ b/rpython/jit/metainterp/test/test_compatible.py
@@ -319,5 +319,46 @@
         x = self.meta_interp(main, [])
 
         # trace, two bridges, a finish bridge
+        self.check_trace_count(3)
+        assert x < 30
+
+    def test_merge(self):
+        S = lltype.GcStruct('S', ('x', lltype.Signed))
+        p1 = lltype.malloc(S)
+        p1.x = 1
+
+        p2 = lltype.malloc(S)
+        p2.x = 1
+
+        driver = jit.JitDriver(greens = [], reds = ['n', 'x'])
+
+        class A(object):
+            pass
+
+        c = A()
+        c.count = 0
+        @jit.elidable_compatible()
+        def g(s, ignored):
+            c.count += 1
+            return s.x
+
+        def f(n, x):
+            while n > 0:
+                driver.can_enter_jit(n=n, x=x)
+                driver.jit_merge_point(n=n, x=x)
+                n -= g(x, "abc")
+                if n & 2:
+                    n -= 2
+
+        def main():
+            g(p1, "def") # make annotator not make argument constant
+            f(1000, p1)
+            f(1000, p2)
+            return c.count
+
+        x = self.meta_interp(main, [])
+
+        assert x < 30
+        # trace, two bridges, a finish bridge
         self.check_trace_count(4)
-        assert x < 50
+
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to