[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