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