Author: Carl Friedrich Bolz <cfb...@gmx.de> Branch: guard-compatible Changeset: r85432:f9d5045ab715 Date: 2016-06-27 19:10 +0200 http://bitbucket.org/pypy/pypy/changeset/f9d5045ab715/
Log: simply call @elidable_compatible functions where we don't have a result (this can only happen when inlining the short preamble into a bridge) 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 @@ -78,6 +78,20 @@ return True def prepare_const_arg_call(self, op, optimizer): + copied_op, cond = self._prepare_const_arg_call(op, optimizer) + if copied_op: + result = optimizer._can_optimize_call_pure(copied_op) + if result is None: + # just call it, we can do that with an @elidable_compatible + # function + result = do_call( + optimizer.cpu, copied_op.getarglist(), + copied_op.getdescr()) + return copied_op, cond, result + else: + return None, None, None + + def _prepare_const_arg_call(self, op, optimizer): from rpython.jit.metainterp.quasiimmut import QuasiImmutDescr # replace further arguments by constants, if the optimizer knows them # already 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 @@ -142,17 +142,15 @@ ccond = info._compatibility_conditions if ccond: # it's subject to guard_compatible - copied_op, cond = ccond.prepare_const_arg_call( + copied_op, cond, result = ccond.prepare_const_arg_call( op, self.optimizer) if copied_op: - result = self._can_optimize_call_pure(copied_op) - if result is not None: - recorded = ccond.record_condition( - cond, result, self.optimizer) - if recorded: - self.make_constant(op, result) - self.last_emitted_operation = REMOVED - 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/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 @@ -528,3 +528,78 @@ self.check_trace_count(7) + def test_quasi_immutable_merge_short_preamble(self): + from rpython.rlib.objectmodel import we_are_translated + class C(object): + _immutable_fields_ = ['version?'] + + class Version(object): + def __init__(self, cls): + self.cls = cls + p1 = C() + p1.version = Version(p1) + p1.x = 1 + p2 = C() + p2.version = Version(p2) + p2.x = 1 + p3 = C() + p3.version = Version(p3) + p3.x = 3 + + driver = jit.JitDriver(greens = [], reds = ['n']) + + class Counter(object): + pass + + c = Counter() + c.count = 0 + @jit.elidable_compatible() + def g(cls, v): + if we_are_translated(): + c.count += 1 + return cls.x + + class B(object): + pass + + glob_b = B() + + def f(n, x): + glob_b.x = x + res = 0 + while n > 0: + driver.can_enter_jit(n=n) + driver.jit_merge_point(n=n) + x = jit.hint(glob_b.x, promote_compatible=True) + v = x.version + res = g(x, v) + n -= res + if n % 11 == 5: + n -= 1 + return res + + def main(x): + res = f(100, p1) + assert res == 1 + res = f(100, p2) + assert res == 1 + res = f(100, p3) + assert res == 3 + main(True) + main(False) + + x = self.meta_interp(main, [True]) + assert x < 70 + x = self.meta_interp(main, [True]) + assert x < 70 + x = self.meta_interp(main, [True]) + assert x < 70 + x = self.meta_interp(main, [True]) + assert x < 70 + + x = self.meta_interp(main, [False]) + assert x < 70 + self.check_trace_count(9) + self.check_resops(call_i=0) + + _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit