Author: Carl Friedrich Bolz <cfb...@gmx.de>
Branch: guard-compatible
Changeset: r85357:625f490451ee
Date: 2016-06-22 17:14 +0200
http://bitbucket.org/pypy/pypy/changeset/625f490451ee/

Log:    start doing loop-invariant code motion of guard_compatible

        (something is currently very broken, but wanted to commit an
        intermediate step)

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
@@ -33,15 +33,26 @@
         self.last_quasi_immut_field_op = None
         # -1 means "stay on the original trace"
         self.jump_target = -1
+        self.frozen = False
+
+    def frozen_copy(self):
+        res = CompatibilityCondition(self.known_valid)
+        res.conditions = self.conditions[:]
+        assert self.jump_target == -1
+        res.frozen = True
+        return res
 
     def record_condition(self, cond, res, optimizer):
         for oldcond in self.conditions:
             if oldcond.same_cond(cond, res):
-                return
+                return True
+        if self.frozen:
+            False
         cond.activate(res, optimizer)
         if self.conditions and self.conditions[-1].debug_mp_str == 
cond.debug_mp_str:
             cond.debug_mp_str = ''
         self.conditions.append(cond)
+        return True
 
     def register_quasi_immut_field(self, op):
         self.last_quasi_immut_field_op = op
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
@@ -121,8 +121,8 @@
         assert self.get_last_guard(optimizer).is_guard()
 
     def make_guards(self, op, short, optimizer):
-        op = ResOperation(rop.GUARD_NONNULL, [op])
-        short.append(op)
+        guard_op = ResOperation(rop.GUARD_NONNULL, [op])
+        short.append(guard_op)
         return PtrInfo.make_guards(self, op, short, optimizer)
 
 class AbstractVirtualPtrInfo(NonNullPtrInfo):
diff --git a/rpython/jit/metainterp/optimizeopt/pure.py 
b/rpython/jit/metainterp/optimizeopt/pure.py
--- a/rpython/jit/metainterp/optimizeopt/pure.py
+++ b/rpython/jit/metainterp/optimizeopt/pure.py
@@ -147,10 +147,12 @@
                         if copied_op:
                             result = self._can_optimize_call_pure(copied_op)
                             if result is not None:
-                                self.make_constant(op, result)
-                                self.last_emitted_operation = REMOVED
-                                ccond.record_condition(cond, result, 
self.optimizer)
-                                return
+                                recorded = ccond.record_condition(
+                                        cond, result, self.optimizer)
+                                if recorded:
+                                    self.make_constant(op, result)
+                                    self.last_emitted_operation = REMOVED
+                                    return
 
         # Step 1: check if all arguments are constant
         for arg in op.getarglist():
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_compatible.py 
b/rpython/jit/metainterp/optimizeopt/test/test_compatible.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_compatible.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_compatible.py
@@ -302,3 +302,80 @@
         """
         self.optimize_loop(ops, expected, expected_preamble=preamble)
 
+
+    def test_guard_compatible_call_pure(self):
+        call_pure_results = {
+            (ConstInt(123), ConstPtr(self.myptr)): ConstInt(5),
+            (ConstInt(124), ConstPtr(self.myptr)): ConstInt(7),
+        }
+        ops = """
+        [p1]
+        guard_compatible(p1, ConstPtr(myptr)) []
+        i3 = call_pure_i(123, p1, descr=plaincalldescr)
+        escape_n(i3)
+        guard_compatible(p1, ConstPtr(myptr)) []
+        i5 = call_pure_i(124, p1, descr=plaincalldescr)
+        escape_n(i5)
+        jump(p1)
+        """
+        preamble = """
+        [p1]
+        guard_compatible(p1, ConstPtr(myptr)) []
+        escape_n(5)
+        escape_n(7)
+        jump(p1)
+        """
+        expected = """
+        [p0]
+        escape_n(5)
+        escape_n(7)
+        jump(p0)
+        """
+        self.optimize_loop(ops, expected, expected_preamble=preamble, 
call_pure_results=call_pure_results)
+        # whitebox-test the guard_compatible descr a bit
+        descr = self.preamble.operations[1].getdescr()
+        assert descr._compatibility_conditions is not None
+        assert 
descr._compatibility_conditions.known_valid.same_constant(ConstPtr(self.myptr))
+        assert len(descr._compatibility_conditions.conditions) == 2
+
+    def test_quasiimmut(self):
+        ops = """
+        [p1]
+        guard_compatible(p1, ConstPtr(quasiptr)) []
+        quasiimmut_field(p1, descr=quasiimmutdescr)
+        guard_not_invalidated() []
+        i0 = getfield_gc_i(p1, descr=quasifielddescr)
+        i1 = call_pure_i(123, p1, i0, descr=nonwritedescr)
+        quasiimmut_field(p1, descr=quasiimmutdescr)
+        guard_not_invalidated() []
+        i3 = getfield_gc_i(p1, descr=quasifielddescr)
+        i4 = call_pure_i(123, p1, i3, descr=nonwritedescr)
+        escape_n(i1)
+        escape_n(i4)
+        jump(p1)
+        """
+        preamble = """
+        [p1]
+        guard_compatible(p1, ConstPtr(quasiptr)) []
+        guard_not_invalidated() []
+        i0 = getfield_gc_i(p1, descr=quasifielddescr) # will be removed by the 
backend
+        escape_n(5)
+        escape_n(5)
+        jump(p1)
+        """
+        expected = """
+        [p1]
+        guard_not_invalidated() []
+        escape_n(5)
+        escape_n(5)
+        jump(p1)
+        """
+
+        call_pure_results = {
+            (ConstInt(123), ConstPtr(self.quasiptr), ConstInt(-4247)): 
ConstInt(5),
+        }
+        self.optimize_loop(ops, expected, expected_preamble=preamble, 
call_pure_results=call_pure_results)
+        descr = self.preamble.operations[1].getdescr()
+        assert descr._compatibility_conditions is not None
+        assert 
descr._compatibility_conditions.known_valid.same_constant(ConstPtr(self.quasiptr))
+        assert len(descr._compatibility_conditions.conditions) == 1
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py 
b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -60,6 +60,7 @@
 
         info = self.unroll_and_optimize(loop, call_pure_results, jump_values)
         preamble = info.preamble
+        self.preamble = preamble
         preamble.check_consistency(check_descr=False)
 
         #
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
@@ -88,7 +88,9 @@
             if preamble_info._compatibility_conditions:
                 info_in_loop = op.get_forwarded()
                 if info_in_loop is not None:
-                    info_in_loop._compatibility_conditions = 
preamble_info._compatibility_conditions
+                    ccond = preamble_info._compatibility_conditions
+                    ccond = ccond.frozen_copy()
+                    info_in_loop._compatibility_conditions = ccond
         elif isinstance(preamble_info, intutils.IntBound):
             if preamble_info.lower > MININT/2 or preamble_info.upper < 
MAXINT/2:
                 intbound = self.getintbound(op)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to