Author: Carl Friedrich Bolz <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit