[pypy-commit] pypy guard-compatible: test and fix: deal with quasiimmut correctly
cfbolz
pypy.commits at gmail.com
Wed Feb 21 12:18:38 EST 2018
Author: Carl Friedrich Bolz-Tereick <cfbolz at gmx.de>
Branch: guard-compatible
Changeset: r93855:5b83d5703851
Date: 2018-02-21 17:21 +0100
http://bitbucket.org/pypy/pypy/changeset/5b83d5703851/
Log: test and fix: deal with quasiimmut correctly
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
@@ -62,8 +62,12 @@
self.conditions.append(cond)
return True
- def register_quasi_immut_field(self, op):
- self.last_quasi_immut_field_op = op
+ def register_quasi_immut_field(self, op, optimizer):
+ from rpython.jit.metainterp.quasiimmut import QuasiImmutDescr
+ assert optimizer.ensure_ptr_info_arg0(op)._compatibility_conditions is self
+ descr = op.getdescr()
+ assert isinstance(descr, QuasiImmutDescr)
+ self.last_quasi_immut_field_descr = descr
def check_compat(self, cpu, ref):
for i, cond in enumerate(self.conditions):
@@ -152,13 +156,12 @@
# even though the second argument is not constant
if arg2.getopnum() not in (rop.GETFIELD_GC_R, rop.GETFIELD_GC_I, rop.GETFIELD_GC_F):
return None, None, "arg2 not a getfield"
- if not self.last_quasi_immut_field_op:
+ if not self.last_quasi_immut_field_descr:
return None, None, "no quasiimut op known"
- qmutdescr = self.last_quasi_immut_field_op.getdescr()
+ qmutdescr = self.last_quasi_immut_field_descr
assert isinstance(qmutdescr, QuasiImmutDescr)
fielddescr = qmutdescr.fielddescr # XXX
- same_arg = self.last_quasi_immut_field_op.getarg(0) is arg2.getarg(0)
- if arg2.getdescr() is not fielddescr or not same_arg:
+ if arg2.getdescr() is not fielddescr:
return None, None, "fielddescr doesn't match"
if not qmutdescr.is_still_valid_for(self.known_valid):
return None, None, "qmutdescr invalid"
diff --git a/rpython/jit/metainterp/optimizeopt/heap.py b/rpython/jit/metainterp/optimizeopt/heap.py
--- a/rpython/jit/metainterp/optimizeopt/heap.py
+++ b/rpython/jit/metainterp/optimizeopt/heap.py
@@ -677,7 +677,7 @@
# the getfield_gc on the object, since it's not constant.
# However, if the quasi-immutable field is passed to a pure
# function call, we can treat it as constant then
- ccond.register_quasi_immut_field(op)
+ ccond.register_quasi_immut_field(op, self.optimizer)
# don't remove the guard_not_invalidated, the guard_compatible
# needs it
self._remove_guard_not_invalidated = False
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
@@ -281,6 +281,55 @@
}
self.optimize_loop(ops, expected, call_pure_results)
+ def test_quasiimmut_bug(self):
+ # bug that happened because we hade quasiimmut_field on two different
+ # boxes (that turn out to be the same after other optimizations)
+ 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)
+
+ # get an alias p2 to p1
+ p3 = new_with_vtable(descr=nodesize)
+ setfield_gc(p3, p1, descr=nextdescr)
+ p2 = getfield_gc_r(p3, descr=nextdescr)
+
+ # a condition via the alias
+ guard_compatible(p2, ConstPtr(quasiptr)) []
+ quasiimmut_field(p2, descr=quasiimmutdescr)
+ guard_not_invalidated() []
+ i3 = getfield_gc_i(p2, descr=quasifielddescr)
+ i4 = call_pure_i(123, p2, i3, descr=nonwritedescr)
+
+ # and now the original box
+ i5 = call_pure_i(123, p1, i0, descr=nonwritedescr)
+ escape_n(i1)
+ escape_n(i4)
+ escape_n(i5)
+ jump(p1)
+ """
+ expected = """
+ [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)
+ escape_n(5)
+ jump(p1)
+ """
+ call_pure_results = {
+ (ConstInt(123), ConstPtr(self.quasiptr), ConstInt(-4247)): ConstInt(5),
+ }
+ self.optimize_loop(ops, expected, call_pure_results)
+ descr = self.loop.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
+
class TestCompatibleUnroll(BaseTestWithUnroll, LLtypeMixin):
More information about the pypy-commit
mailing list