[pypy-svn] r36257 - in pypy/branch/jit-codegen-refactor/pypy/jit/codegen: . llgraph llgraph/test

arigo at codespeak.net arigo at codespeak.net
Mon Jan 8 13:04:25 CET 2007


Author: arigo
Date: Mon Jan  8 13:04:19 2007
New Revision: 36257

Modified:
   pypy/branch/jit-codegen-refactor/pypy/jit/codegen/llgraph/llimpl.py
   pypy/branch/jit-codegen-refactor/pypy/jit/codegen/llgraph/rgenop.py
   pypy/branch/jit-codegen-refactor/pypy/jit/codegen/llgraph/test/test_rgenop.py
   pypy/branch/jit-codegen-refactor/pypy/jit/codegen/model.py
Log:
(mwh, arigo)

New rgenop interface, implemented for the llgraph backend.


Modified: pypy/branch/jit-codegen-refactor/pypy/jit/codegen/llgraph/llimpl.py
==============================================================================
--- pypy/branch/jit-codegen-refactor/pypy/jit/codegen/llgraph/llimpl.py	(original)
+++ pypy/branch/jit-codegen-refactor/pypy/jit/codegen/llgraph/llimpl.py	Mon Jan  8 13:04:19 2007
@@ -350,6 +350,31 @@
     graph = _getgraph(gv_func)
     _closelink(link, [returnvar], graph.prereturnblock)
 
+def closelinktofreshblock(link, inputargs=None):
+    link = from_opaque_object(link)
+    vars = link.prevblock.getvariables()
+    if inputargs is not None:
+        existing_vars = dict.fromkeys(vars)
+        vars = _inputvars(inputargs)
+        for v in vars:
+            assert v in existing_vars
+    nextblock = flowmodel.Block(list(vars))
+    link.args = vars
+    link.target = nextblock
+    return to_opaque_object(nextblock)
+
+def closelinktofreshblockwithsameargsasotherlink(link, otherlink):
+    link = from_opaque_object(link)
+    otherlink = from_opaque_object(otherlink)
+    existing_vars = dict.fromkeys(link.prevblock.getvariables())
+    vars = list(otherlink.args)
+    for v in vars:
+        assert v in existing_vars
+    nextblock = flowmodel.Block(list(vars))
+    link.args = vars
+    link.target = nextblock
+    return to_opaque_object(nextblock)
+
 def casting_link(source, sourcevars, target):
     assert len(sourcevars) == len(target.inputargs)
     linkargs = []
@@ -372,7 +397,27 @@
         from pypy.rpython.typesystem import LowLevelTypeSystem
         self.type_system = LowLevelTypeSystem.instance
 
+def fixduplicatevars(graph):
+    incomingvars = {}   # {block: {var_from_link_args: True}}
+    for link in graph.iterlinks():
+        vars = incomingvars.setdefault(link.target, {})
+        for v in link.args:
+            if isinstance(v, flowmodel.Variable):
+                vars[v] = True
+    for block, vars in incomingvars.items():
+        for v in block.inputargs:
+            if v in vars:
+                # this block needs renaming of all its input variables
+                mapping = {}
+                for a in block.inputargs:
+                    mapping[a] = a1 = flowmodel.Variable(a)
+                    a1.concretetype = a.concretetype
+                block.renamevariables(mapping)
+                break
+
 def _buildgraph(graph):
+    # rgenop makes graphs that use the same variable in several blocks,
+    fixduplicatevars(graph)                             # fix this now
     flowmodel.checkgraph(graph)
     eliminate_empty_blocks(graph)
     join_blocks(graph)
@@ -486,6 +531,8 @@
 setannotation(add_default, s_Link)
 setannotation(closelink, None)
 setannotation(closereturnlink, None)
+setannotation(closelinktofreshblock, s_Block)
+setannotation(closelinktofreshblockwithsameargsasotherlink, s_Block)
 
 setannotation(isptrtype, annmodel.SomeBool())
 

Modified: pypy/branch/jit-codegen-refactor/pypy/jit/codegen/llgraph/rgenop.py
==============================================================================
--- pypy/branch/jit-codegen-refactor/pypy/jit/codegen/llgraph/rgenop.py	(original)
+++ pypy/branch/jit-codegen-refactor/pypy/jit/codegen/llgraph/rgenop.py	Mon Jan  8 13:04:19 2007
@@ -55,22 +55,22 @@
     def add_case(self, gv_case):
         self.cases_gv.append(gv_case)  # not used so far, but keeps ptrs alive
         l_case = llimpl.add_case(self.b, gv_case.v)
-        builder = LLBuilder(self.gv_f)
-        builder.lnk = l_case
-        return builder
+        b = llimpl.closelinktofreshblockwithsameargsasotherlink(l_case,
+                                                                self.l_default)
+        return LLBuilder(self.gv_f, b)
 
-    def add_default(self):
+    def _add_default(self, args_gv):
         l_default = llimpl.add_default(self.b)
-        builder = LLBuilder(self.gv_f)
-        builder.lnk = l_default
-        return builder
+        self.l_default = l_default
+        b = llimpl.closelinktofreshblock(l_default, args_gv)
+        return LLBuilder(self.gv_f, b)
 
 class LLBuilder(GenBuilder):
-    lnk = llimpl.nulllink
 
-    def __init__(self, g):
+    def __init__(self, g, block):
         self.rgenop = rgenop
         self.gv_f = g
+        self.b = block
 
     def end(self):
         llimpl.end(self.gv_f)
@@ -156,8 +156,7 @@
         return [LLVar(llimpl.geninputarg(newb, kind.v)) for kind in kinds]
 
     def enter_next_block(self, kinds, args_gv):
-        lnk = self.lnk or llimpl.closeblock1(self.b)
-        self.lnk = llimpl.nulllink
+        lnk = llimpl.closeblock1(self.b)
         newb_args_gv = self._newblock(kinds) 
         llimpl.closelink(lnk, args_gv, self.b)
         for i in range(len(args_gv)):
@@ -165,38 +164,35 @@
         return LLLabel(self.b, self.gv_f)
 
     def finish_and_goto(self, args_gv, target):
-        lnk = self.lnk or llimpl.closeblock1(self.b)
-        self.lnk = llimpl.nulllink
+        lnk = llimpl.closeblock1(self.b)
+        self.b = llimpl.nullblock
         llimpl.closelink(lnk, args_gv, target.b)
 
     def finish_and_return(self, sigtoken, gv_returnvar):
         gv_returnvar = gv_returnvar or gv_dummy_placeholder
-        lnk = self.lnk or llimpl.closeblock1(self.b)
-        self.lnk = llimpl.nulllink
+        lnk = llimpl.closeblock1(self.b)
+        self.b = llimpl.nullblock
         llimpl.closereturnlink(lnk, gv_returnvar.v, self.gv_f)
 
-    def jump_if_true(self, gv_cond):
+    def jump_if_true(self, gv_cond, args_for_jump_gv):
         l_false, l_true = llimpl.closeblock2(self.b, gv_cond.v)
-        self.b = llimpl.nullblock
-        later_builder = LLBuilder(self.gv_f)
-        later_builder.lnk = l_true
-        self.lnk = l_false
+        self.b = llimpl.closelinktofreshblock(l_false, None)
+        b2 = llimpl.closelinktofreshblock(l_true, args_for_jump_gv)
+        later_builder = LLBuilder(self.gv_f, b2)
         return later_builder
 
-    def jump_if_false(self, gv_cond):
+    def jump_if_false(self, gv_cond, args_for_jump_gv):
         l_false, l_true = llimpl.closeblock2(self.b, gv_cond.v)
-        self.b = llimpl.nullblock
-        later_builder = LLBuilder(self.gv_f)
-        later_builder.lnk = l_false
-        self.lnk = l_true
+        self.b = llimpl.closelinktofreshblock(l_true, None)
+        b2 = llimpl.closelinktofreshblock(l_false, args_for_jump_gv)
+        later_builder = LLBuilder(self.gv_f, b2)
         return later_builder
 
-    def flexswitch(self, gv_switchvar):
+    def flexswitch(self, gv_switchvar, args_gv):
         llimpl.closeblockswitch(self.b, gv_switchvar.v)
         flexswitch = LLFlexSwitch(self.b, self.gv_f)
         self.b = llimpl.nullblock
-        self.lnk = llimpl.nulllink
-        return flexswitch
+        return (flexswitch, flexswitch._add_default(args_gv))
 
     def show_incremental_progress(self):
         llimpl.show_incremental_progress(self.gv_f)
@@ -208,8 +204,7 @@
 
     def newgraph(self, (ARGS_gv, gv_RESULT, gv_FUNCTYPE), name):
         gv_func = llimpl.newgraph(gv_FUNCTYPE.v, name)
-        builder = LLBuilder(gv_func)
-        builder.b = llimpl.getstartblock(gv_func)
+        builder = LLBuilder(gv_func, llimpl.getstartblock(gv_func))
         inputargs_gv = [LLVar(llimpl.getinputarg(builder.b, i))
                         for i in range(len(ARGS_gv))]
         return builder, LLConst(gv_func), inputargs_gv

Modified: pypy/branch/jit-codegen-refactor/pypy/jit/codegen/llgraph/test/test_rgenop.py
==============================================================================
--- pypy/branch/jit-codegen-refactor/pypy/jit/codegen/llgraph/test/test_rgenop.py	(original)
+++ pypy/branch/jit-codegen-refactor/pypy/jit/codegen/llgraph/test/test_rgenop.py	Mon Jan  8 13:04:19 2007
@@ -67,7 +67,7 @@
  
     const0 = rgenop.genconst(0)
     gv1 = builder.genop2('int_lt', gv0, const0)
-    false_builder = builder.jump_if_false(gv1)
+    false_builder = builder.jump_if_false(gv1, [gv0])
     builder.finish_and_return(f1_token, const0)
     false_builder.finish_and_return(f1_token, gv0)
     builder.end()
@@ -110,7 +110,7 @@
     gv_result1 = builder.genop2('int_mul', gv_result0, gv_i0)
     gv_i1 = builder.genop2('int_add', gv_i0, const1)
     gv2 = builder.genop2('int_le', gv_i1, gv1)
-    loop_builder = builder.jump_if_true(gv2)
+    loop_builder = builder.jump_if_true(gv2, [gv_result1, gv_i1, gv1])
     builder.finish_and_return(f1_token, gv_result1)
     loop_builder.finish_and_goto([gv_result1, gv_i1, gv1], loopblock)
 
@@ -167,31 +167,21 @@
     """
     builder, gv_switch, (gv0, gv1) = rgenop.newgraph(f2_token, "switch")
 
-    flexswitch = builder.flexswitch(gv0)
+    flexswitch, default_builder = builder.flexswitch(gv0, [gv1])
     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)
+    gv_res_case0 = case_builder.genop2('int_mul', const21, gv1)
     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)
+    gv_res_case1 = case_builder.genop2('int_add', const21, gv1)
     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)
+    default_builder.finish_and_return(f2_token, gv1)
 
     builder.end()
     switch_ptr = gv_switch.revealconst(lltype.Ptr(F2))

Modified: pypy/branch/jit-codegen-refactor/pypy/jit/codegen/model.py
==============================================================================
--- pypy/branch/jit-codegen-refactor/pypy/jit/codegen/model.py	(original)
+++ pypy/branch/jit-codegen-refactor/pypy/jit/codegen/model.py	Mon Jan  8 13:04:19 2007
@@ -86,22 +86,27 @@
         zip(kinds, args_gv) gives the kindtoken and GenVarOrConst for
         each inputarg of the block.
 
-        The Obscure Bit: args_gv must be mutated in place to replace
-        GenConsts with GenVars and optionally GenVars can be replaced
-        with new GenVars, for example if the same value might live in
-        different locations (registers, places on the stack) in
-        different basic blocks.
+        The Obscure Bit: args_gv must be mutated in place until it is a
+        list of unique GenVars.  So GenConsts must be replaced with
+        GenVars, and duplicate GenVars must be made unique.  Optionally,
+        *all* GenVars can be replaced with new GenVars, for example if
+        the same value might live in different locations (registers,
+        places on the stack) in different basic blocks.
 
         Returns an instance of GenLabel that can later be jumped to.
         '''
 
-    def jump_if_false(self, gv_condition):
+    def jump_if_false(self, gv_condition, args_for_jump_gv):
         '''Make a fresh builder, insert in the current block a
         check of gv_condition and a conditional jump to the new block
         that is taken if gv_condition is false and return the new
-        builder.'''
+        builder.
 
-    def jump_if_true(self, gv_condition):
+        The current builder stays open, and it must be closed before
+        the fresh builder is used at all, to make the backend\'s life
+        easier.'''
+
+    def jump_if_true(self, gv_condition, args_for_jump_gv):
         '''See above, with the obvious difference :)'''
 
     def finish_and_return(self, sigtoken, gv_returnvar):
@@ -120,14 +125,20 @@
         This "closes" the current builder.
         '''
 
-    def flexswitch(self, gv_exitswitch):
+    def flexswitch(self, gv_exitswitch, args_gv):
         '''The Fun Stuff.
 
         Generates a switch on the value of gv_exitswitch that can have
         cases added to it later, i.e. even after it\'s been executed a
         few times.
 
-        Returns an instance of CodeGenSwitch, see below.
+        args_gv is the list of live variables.  It\'s the list of
+        variables that can be used in each switch case.
+
+        Returns a tuple:
+        - an instance of CodeGenSwitch (see below)
+        - a new builder for the default case, that will be jumped to
+          when the switched-on GenVar does not take the value of any case.
 
         This "closes" the current builder.
         '''
@@ -258,8 +269,3 @@
     def add_case(self, gv_case):
         '''Make a new builder that will be jumped to when the
         switched-on GenVar takes the value of the GenConst gv_case.'''
-
-    def add_default(self):
-        '''Make a new builder that will be jumped to when the
-        switched-on GenVar does not take the value of any case.'''
-



More information about the Pypy-commit mailing list