[pypy-commit] pypy default: (fijal, hodgestar) merge inline-simple-generators. that branch peels one loop iteration out of generators and inlines this into outer loop
fijal
noreply at buildbot.pypy.org
Sun Jul 24 21:47:08 CEST 2011
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch:
Changeset: r45951:c8bb44739101
Date: 2011-07-24 21:47 +0200
http://bitbucket.org/pypy/pypy/changeset/c8bb44739101/
Log: (fijal, hodgestar) merge inline-simple-generators. that branch peels
one loop iteration out of generators and inlines this into outer
loop
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -56,6 +56,8 @@
# for resume.py operation
self.parent_resumedata_snapshot = None
self.parent_resumedata_frame_info_list = None
+ # counter for unrolling inlined loops
+ self.unroll_iterations = 1
@specialize.arg(3)
def copy_constants(self, registers, constants, ConstClass):
@@ -931,6 +933,10 @@
# 'redboxes' back into the registers where it comes from.
put_back_list_of_boxes3(self, jcposition, redboxes)
else:
+ if jitdriver_sd.warmstate.should_unroll_one_iteration(greenboxes):
+ if self.unroll_iterations > 0:
+ self.unroll_iterations -= 1
+ return
# warning! careful here. We have to return from the current
# frame containing the jit_merge_point, and then use
# do_recursive_call() to follow the recursive call. This is
diff --git a/pypy/jit/metainterp/test/test_ajit.py b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -508,6 +508,32 @@
assert res == 84 - 61 - 62
self.check_history(call=1) # because the trace starts immediately
+ def test_unroll_one_loop_iteration(self):
+ def unroll(code):
+ return code == 0
+ myjitdriver = JitDriver(greens = ['code'],
+ reds = ['loops', 'inner_loops', 's'],
+ should_unroll_one_iteration=unroll)
+
+ def f(code, loops, inner_loops):
+ s = 0
+ while loops > 0:
+ myjitdriver.jit_merge_point(code=code, loops=loops,
+ inner_loops=inner_loops, s=s)
+ if code == 1:
+ s += f(0, inner_loops, 0)
+ loops -= 1
+ s += 1
+ return s
+
+ res = self.meta_interp(f, [1, 4, 1], enable_opts="", inline=True)
+ assert res == f(1, 4, 1)
+ self.check_history(call_assembler=0)
+
+ res = self.meta_interp(f, [1, 4, 2], enable_opts="", inline=True)
+ assert res == f(1, 4, 2)
+ self.check_history(call_assembler=1)
+
def test_format(self):
def f(n):
return len("<%d>" % n)
diff --git a/pypy/jit/metainterp/warmspot.py b/pypy/jit/metainterp/warmspot.py
--- a/pypy/jit/metainterp/warmspot.py
+++ b/pypy/jit/metainterp/warmspot.py
@@ -468,6 +468,9 @@
onlygreens=False)
jd._can_never_inline_ptr = self._make_hook_graph(jd,
annhelper, jd.jitdriver.can_never_inline, annmodel.s_Bool)
+ jd._should_unroll_one_iteration_ptr = self._make_hook_graph(jd,
+ annhelper, jd.jitdriver.should_unroll_one_iteration,
+ annmodel.s_Bool)
annhelper.finish()
def _make_hook_graph(self, jitdriver_sd, annhelper, func,
diff --git a/pypy/jit/metainterp/warmstate.py b/pypy/jit/metainterp/warmstate.py
--- a/pypy/jit/metainterp/warmstate.py
+++ b/pypy/jit/metainterp/warmstate.py
@@ -572,6 +572,19 @@
return can_inline_greenargs(*greenargs)
self.can_inline_greenargs = can_inline_greenargs
self.can_inline_callable = can_inline_callable
+
+ if jd._should_unroll_one_iteration_ptr is None:
+ def should_unroll_one_iteration(greenkey):
+ return False
+ else:
+ rtyper = self.warmrunnerdesc.rtyper
+ inline_ptr = jd._should_unroll_one_iteration_ptr
+ def should_unroll_one_iteration(greenkey):
+ greenargs = unwrap_greenkey(greenkey)
+ fn = support.maybe_on_top_of_llinterp(rtyper, inline_ptr)
+ return fn(*greenargs)
+ self.should_unroll_one_iteration = should_unroll_one_iteration
+
if hasattr(jd.jitdriver, 'on_compile'):
def on_compile(logger, token, operations, type, greenkey):
greenargs = unwrap_greenkey(greenkey)
diff --git a/pypy/module/pypyjit/interp_jit.py b/pypy/module/pypyjit/interp_jit.py
--- a/pypy/module/pypyjit/interp_jit.py
+++ b/pypy/module/pypyjit/interp_jit.py
@@ -44,9 +44,11 @@
ec.w_tracefunc is None)
def can_never_inline(next_instr, is_being_profiled, bytecode):
+ return False
+
+def should_unroll_one_iteration(next_instr, is_being_profiled, bytecode):
return (bytecode.co_flags & CO_GENERATOR) != 0
-
def wrap_oplist(space, logops, operations):
list_w = []
for op in operations:
@@ -110,7 +112,9 @@
get_jitcell_at = get_jitcell_at,
set_jitcell_at = set_jitcell_at,
confirm_enter_jit = confirm_enter_jit,
- can_never_inline = can_never_inline)
+ can_never_inline = can_never_inline,
+ should_unroll_one_iteration =
+ should_unroll_one_iteration)
class __extend__(PyFrame):
diff --git a/pypy/module/pypyjit/test_pypy_c/test_generators.py b/pypy/module/pypyjit/test_pypy_c/test_generators.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/pypyjit/test_pypy_c/test_generators.py
@@ -0,0 +1,25 @@
+from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC
+
+
+class TestGenerators(BaseTestPyPyC):
+ def test_simple_generator(self):
+ def main(n):
+ def f():
+ for i in range(10000):
+ yield i
+
+ def g():
+ for i in f(): # ID: generator
+ pass
+
+ g()
+
+ log = self.run(main, [500])
+ loop, = log.loops_by_filename(self.filepath)
+ assert loop.match_by_id("generator", """
+ i16 = force_token()
+ p45 = new_with_vtable(ConstClass(W_IntObject))
+ setfield_gc(p45, i29, descr=<SignedFieldDescr .*>)
+ setarrayitem_gc(p8, 0, p45, descr=<GcPtrArrayDescr>)
+ jump(..., descr=...)
+ """)
diff --git a/pypy/rlib/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -315,7 +315,7 @@
def __init__(self, greens=None, reds=None, virtualizables=None,
get_jitcell_at=None, set_jitcell_at=None,
get_printable_location=None, confirm_enter_jit=None,
- can_never_inline=None):
+ can_never_inline=None, should_unroll_one_iteration=None):
if greens is not None:
self.greens = greens
if reds is not None:
@@ -334,6 +334,7 @@
self.get_printable_location = get_printable_location
self.confirm_enter_jit = confirm_enter_jit
self.can_never_inline = can_never_inline
+ self.should_unroll_one_iteration = should_unroll_one_iteration
def _freeze_(self):
return True
More information about the pypy-commit
mailing list