[pypy-svn] r33122 - in pypy/dist/pypy/jit: codegen/llgraph codegen/llgraph/test timeshifter
pedronis at codespeak.net
pedronis at codespeak.net
Tue Oct 10 18:06:08 CEST 2006
Author: pedronis
Date: Tue Oct 10 18:05:57 2006
New Revision: 33122
Modified:
pypy/dist/pypy/jit/codegen/llgraph/llimpl.py
pypy/dist/pypy/jit/codegen/llgraph/rgenop.py
pypy/dist/pypy/jit/codegen/llgraph/test/test_rgenop.py
pypy/dist/pypy/jit/timeshifter/rtimeshift.py
Log:
(arre, arigo, pedronis)
Change slightly the flexswitch interface. Now there's an explicit add_default case
operation on the flexswitch. There's no need anymore for stop_replay, saving the code gen vars
before the switch is enough to be able to restart adding new cases to a pre-existing switch.
Added a flexswitch test to the llgraph codegen tests.
Modified: pypy/dist/pypy/jit/codegen/llgraph/llimpl.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/llgraph/llimpl.py (original)
+++ pypy/dist/pypy/jit/codegen/llgraph/llimpl.py Tue Oct 10 18:05:57 2006
@@ -260,11 +260,8 @@
'cast_ptr_to_int', [exitswitch], v1))
exitswitch = v1
block.exitswitch = exitswitch
- default_link = flowmodel.Link([], None)
- default_link.exitcase = "default"
- default_link.llexitcase = None
- block.closeblock(default_link)
- return to_opaque_object(default_link)
+ block.closeblock()
+ return
def add_case(block, exitcase):
block = from_opaque_object(block)
@@ -278,10 +275,26 @@
exitvalue = lltype.cast_ptr_to_int(exitvalue)
case_link.exitcase = exitvalue
case_link.llexitcase = exitvalue
- exits = block.exits[:-1] + (case_link,) + block.exits[-1:]
+ if block.exits and block.exits[-1].exitcase == 'default':
+ exits = block.exits[:-1] + (case_link,) + block.exits[-1:]
+ else:
+ exits = block.exits + (case_link,)
block.recloseblock(*exits)
return to_opaque_object(case_link)
+def add_default(block):
+ block = from_opaque_object(block)
+ assert isinstance(block.exitswitch, flowmodel.Variable)
+ default_link = flowmodel.Link([], None)
+ default_link.exitcase = 'default'
+ default_link.llexitcase = None
+ if block.exits and block.exits[-1].exitcase == 'default':
+ raise ValueError
+ else:
+ exits = block.exits + (default_link,)
+ block.recloseblock(*exits)
+ return to_opaque_object(default_link)
+
class pseudotuple(object):
# something that looks both like a hl and a ll tuple
def __init__(self, *items):
@@ -460,8 +473,9 @@
setannotation(isconst, annmodel.SomeBool())
setannotation(closeblock1, s_Link)
setannotation(closeblock2, s_LinkPair)
-setannotation(closeblockswitch, s_Link)
+setannotation(closeblockswitch, None)
setannotation(add_case, s_Link)
+setannotation(add_default, s_Link)
setannotation(closelink, None)
setannotation(closereturnlink, None)
Modified: pypy/dist/pypy/jit/codegen/llgraph/rgenop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/llgraph/rgenop.py (original)
+++ pypy/dist/pypy/jit/codegen/llgraph/rgenop.py Tue Oct 10 18:05:57 2006
@@ -48,6 +48,11 @@
builder.lnk = l_case
return builder
+ def add_default(self):
+ l_default = llimpl.add_default(self.b)
+ builder = LLBuilder(self.g)
+ builder.lnk = l_default
+ return builder
class LLBuilder(CodeGenerator):
lnk = llimpl.nulllink
@@ -165,10 +170,10 @@
return later_builder
def flexswitch(self, gv_switchvar):
- l_default = llimpl.closeblockswitch(self.b, gv_switchvar.v)
+ llimpl.closeblockswitch(self.b, gv_switchvar.v)
flexswitch = LLFlexSwitch(self.b, self.g)
self.b = llimpl.nullblock
- self.lnk = l_default
+ self.lnk = llimpl.nulllink
return flexswitch
def show_incremental_progress(self):
@@ -243,9 +248,9 @@
args_gv = builder._newblock(kinds)
return builder, args_gv
- def stop_replay(self, endblock, kinds):
- return [LLVar(llimpl.getinputarg(endblock.b, i))
- for i in range(len(kinds))]
+ #def stop_replay(self, endblock, kinds):
+ # return [LLVar(llimpl.getinputarg(endblock.b, i))
+ # for i in range(len(kinds))]
# not RPython, just for debugging. Specific to llgraph.
@staticmethod
Modified: pypy/dist/pypy/jit/codegen/llgraph/test/test_rgenop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/llgraph/test/test_rgenop.py (original)
+++ pypy/dist/pypy/jit/codegen/llgraph/test/test_rgenop.py Tue Oct 10 18:05:57 2006
@@ -18,7 +18,9 @@
return _interpret(fn, args, policy=genconst_policy)
F1 = lltype.FuncType([lltype.Signed], lltype.Signed)
+F2 = lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed)
f1_token = rgenop.sigToken(F1)
+f2_token = rgenop.sigToken(F2)
signed_tok = rgenop.kindToken(lltype.Signed)
def runner(build):
@@ -27,6 +29,12 @@
return fptr(x)
return run
+def runner2(build):
+ def run(x, y):
+ fptr = build()
+ return fptr(x, y)
+ return run
+
def build_square():
"""def square(v0): return v0*v0"""
@@ -145,3 +153,65 @@
s = lltype.malloc(S)
res = interpret(hide_and_reveal_p, [s])
assert res == s
+
+
+def build_switch():
+ """
+ def f(v0, v1):
+ if v0 == 0: # switch
+ return 21*v1
+ elif v0 == 1:
+ return 21+v1
+ else:
+ return v1
+ """
+ builder, graph, (gv0, gv1) = rgenop.newgraph(f2_token)
+
+ flexswitch = builder.flexswitch(gv0)
+ const21 = rgenop.genconst(21)
+
+ # case == 0
+ const0 = rgenop.genconst(0)
+ case_builder = flexswitch.add_case(const0)
+ case_args_gv = [gv1]
+ case_builder.enter_next_block([signed_tok], case_args_gv)
+ [gv1_case0] = case_args_gv
+ gv_res_case0 = case_builder.genop2('int_mul', const21, gv1_case0)
+ case_builder.finish_and_return(f2_token, gv_res_case0)
+ # case == 1
+ const1 = rgenop.genconst(1)
+ case_builder = flexswitch.add_case(const1)
+ case_args_gv = [gv1]
+ case_builder.enter_next_block([signed_tok], case_args_gv)
+ [gv1_case1] = case_args_gv
+ gv_res_case1 = case_builder.genop2('int_add', const21, gv1_case1)
+ case_builder.finish_and_return(f2_token, gv_res_case1)
+ # default
+ default_builder = flexswitch.add_default()
+ default_args_gv = [gv1]
+ default_builder.enter_next_block([signed_tok], default_args_gv)
+ [gv1_default] = default_args_gv
+ default_builder.finish_and_return(f2_token, gv1_default)
+
+ gv_switch = rgenop.gencallableconst(f2_token, "switch", graph)
+ switch_ptr = gv_switch.revealconst(lltype.Ptr(F2))
+ return switch_ptr
+
+def test_switch():
+ switch_ptr = build_switch()
+ switch_graph = switch_ptr._obj.graph
+ res = testgengraph(switch_graph, [0, 2])
+ assert res == 42
+ res = testgengraph(switch_graph, [1, 16])
+ assert res == 37
+ res = testgengraph(switch_graph, [42, 16])
+ assert res == 16
+
+def test_interpret_switch():
+ run_switch = runner2(build_switch)
+ res = interpret(run_switch, [0, 2])
+ assert res == 42
+ res = interpret(run_switch, [1, 15])
+ assert res == 36
+ res = interpret(run_switch, [42, 5])
+ assert res == 5
Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtimeshift.py (original)
+++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py Tue Oct 10 18:05:57 2006
@@ -410,10 +410,10 @@
class PromotionPoint(object):
- def __init__(self, flexswitch, switchblock, promotion_path):
+ def __init__(self, flexswitch, incoming_gv, promotion_path):
assert promotion_path is not None
self.flexswitch = flexswitch
- self.switchblock = switchblock
+ self.incoming_gv = incoming_gv
self.promotion_path = promotion_path
class AbstractPromotionPath(object):
@@ -538,24 +538,27 @@
memo = rvalue.enter_block_memo()
jitstate.enter_block(incoming, memo)
switchblock = enter_next_block(jitstate, incoming)
-
+ gv_switchvar = promotebox.genvar
+ flexswitch = builder.flexswitch(gv_switchvar)
+
if jitstate.resuming is None:
- gv_switchvar = promotebox.genvar
- flexswitch = builder.flexswitch(gv_switchvar)
+ incoming_gv = [box.genvar for box in incoming]
+ default_builder = flexswitch.add_default()
+ jitstate.curbuilder = default_builder
# default case of the switch:
enter_block(jitstate)
- pm = PromotionPoint(flexswitch, switchblock,
+ pm = PromotionPoint(flexswitch, incoming_gv,
jitstate.promotion_path)
ll_pm = cast_instance_to_base_ptr(pm)
- gv_pm = builder.rgenop.genconst(ll_pm)
+ gv_pm = default_builder.rgenop.genconst(ll_pm)
gv_switchvar = promotebox.genvar
- builder.genop_call(promotiondesc.sigtoken,
+ default_builder.genop_call(promotiondesc.sigtoken,
promotiondesc.gv_continue_compilation,
[gv_pm, gv_switchvar])
linkargs = []
for box in incoming:
- linkargs.append(box.getgenvar(builder))
- builder.finish_and_goto(linkargs, switchblock)
+ linkargs.append(box.getgenvar(default_builder))
+ default_builder.finish_and_goto(linkargs, switchblock)
return True
else:
assert jitstate.promotion_path is None
@@ -576,23 +579,20 @@
f = f.backframe
if len(resuming.path) == 0:
- # XXX we need to do something around the switch in the 'else'
- # case too
- kinds = [box.kind for box in incoming]
- vars_gv = jitstate.curbuilder.rgenop.stop_replay(
- pm.switchblock,
- kinds)
+ incoming_gv = pm.incoming_gv
for i in range(len(incoming)):
- incoming[i].genvar = vars_gv[i]
+ incoming[i].genvar = incoming_gv[i]
+ flexswitch = pm.flexswitch
promotebox.genvar = promotenode.gv_value
- newbuilder = pm.flexswitch.add_case(promotenode.gv_value)
jitstate.resuming = None
node = PromotionPathMergesToSee(promotenode, 0)
jitstate.promotion_path = node
- jitstate.curbuilder = newbuilder
else:
resuming.merges_to_see()
promotebox.genvar = promotenode.gv_value
+
+ newbuilder = flexswitch.add_case(promotenode.gv_value)
+ jitstate.curbuilder = newbuilder
enter_block(jitstate)
return False
More information about the Pypy-commit
mailing list