[pypy-svn] r42363 - in pypy/dist/pypy: config objspace/flow translator/backendopt translator/cli translator/cli/test translator/oosupport

antocuni at codespeak.net antocuni at codespeak.net
Thu Apr 26 21:22:47 CEST 2007


Author: antocuni
Date: Thu Apr 26 21:22:46 2007
New Revision: 42363

Modified:
   pypy/dist/pypy/config/translationoption.py
   pypy/dist/pypy/objspace/flow/model.py
   pypy/dist/pypy/translator/backendopt/all.py
   pypy/dist/pypy/translator/cli/function.py
   pypy/dist/pypy/translator/cli/test/runtest.py
   pypy/dist/pypy/translator/cli/test/test_snippet.py
   pypy/dist/pypy/translator/oosupport/function.py
   pypy/dist/pypy/translator/oosupport/treebuilder.py
Log:
A backend optimization for gencli, which turns SSI graphs into
stack-based machine friendly graphs.



Modified: pypy/dist/pypy/config/translationoption.py
==============================================================================
--- pypy/dist/pypy/config/translationoption.py	(original)
+++ pypy/dist/pypy/config/translationoption.py	Thu Apr 26 21:22:46 2007
@@ -17,6 +17,7 @@
     ChoiceOption("type_system", "Type system to use when RTyping",
                  ["lltype", "ootype"], cmdline=None,
                  requires={
+                     "lltype": [("translation.backendopt.stack_optimization", False)],
                      "ootype": [("translation.backendopt.raisingop2direct_call", False),
                                 ("translation.backendopt.constfold", False),
                                 ("translation.backendopt.heap2stack", False),
@@ -30,10 +31,14 @@
                                 ("translation.gc", "boehm"),
                                 ("translation.backendopt.raisingop2direct_call", True)],
                      "cli":    [("translation.type_system", "ootype")],
-                     "jvm":    [("translation.type_system", "ootype")],
-                     "js":     [("translation.type_system", "ootype")],
-                     "squeak": [("translation.type_system", "ootype")],
-                     "cl":     [("translation.type_system", "ootype")],
+                     "jvm":    [("translation.type_system", "ootype"),
+                                ("translation.backendopt.stack_optimization", False)],
+                     "js":     [("translation.type_system", "ootype"),
+                                ("translation.backendopt.stack_optimization", False)],
+                     "squeak": [("translation.type_system", "ootype"),
+                                ("translation.backendopt.stack_optimization", False)],
+                     "cl":     [("translation.type_system", "ootype"),
+                                ("translation.backendopt.stack_optimization", False)],
                      },
                  cmdline="-b --backend"),
     BoolOption("llvm_via_c", "compile llvm via C",
@@ -166,6 +171,14 @@
                    "which lets the C optimizer remove the asserts",
                    default=False),
 
+        BoolOption("stack_optimization",
+                   "Tranform graphs in SSI form into graphs tailored for "
+                   "stack based virtual machines",
+                   default=True,
+                   cmdline="--stackopt",
+                   requires=[("translation.type_system", "ootype"),
+                             ("translation.backend", "cli")]),
+
         BoolOption("none",
                    "Do not run any backend optimizations",
                    requires=[('translation.backendopt.inline', False),

Modified: pypy/dist/pypy/objspace/flow/model.py
==============================================================================
--- pypy/dist/pypy/objspace/flow/model.py	(original)
+++ pypy/dist/pypy/objspace/flow/model.py	Thu Apr 26 21:22:46 2007
@@ -573,6 +573,8 @@
 
 def checkgraph(graph):
     "Check the consistency of a flow graph."
+
+    from pypy.translator.oosupport.treebuilder import SubOperation
     if not __debug__:
         return
     try:
@@ -608,19 +610,24 @@
                 if in_link is not None:
                     assert vars[v] is None or vars[v] is in_link
 
-            for v in block.inputargs:
-                definevar(v)
-
-            for op in block.operations:
+            def checkop(op):
                 for v in op.args:
-                    assert isinstance(v, (Constant, Variable))
-                    if isinstance(v, Variable):
+                    assert isinstance(v, (Constant, Variable, SubOperation))
+                    if isinstance(v, SubOperation):
+                        checkop(v.op)
+                    elif isinstance(v, Variable):
                         usevar(v)
                     else:
                         assert v.value is not last_exception
                         #assert v.value != last_exc_value
                 if op.opname == 'direct_call':
                     assert isinstance(op.args[0], Constant)
+
+            for v in block.inputargs:
+                definevar(v)
+
+            for op in block.operations:
+                checkop(op)
                 definevar(op.result)
 
             exc_links = {}

Modified: pypy/dist/pypy/translator/backendopt/all.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/all.py	(original)
+++ pypy/dist/pypy/translator/backendopt/all.py	Thu Apr 26 21:22:46 2007
@@ -11,6 +11,8 @@
 from pypy.translator.backendopt.removeassert import remove_asserts
 from pypy.translator.backendopt.support import log
 from pypy.translator.backendopt.checkvirtual import check_virtual_methods
+from pypy.translator.backendopt.ssa import SSI_to_SSA
+from pypy.translator.oosupport.treebuilder import build_trees
 from pypy.objspace.flow.model import checkgraph
 
 INLINE_THRESHOLD_FOR_TEST = 33
@@ -125,6 +127,11 @@
         print "after if-to-switch:"
         print_statistics(translator.graphs[0], translator)
 
+    if config.stack_optimization:
+        for graph in graphs:
+            SSI_to_SSA(graph)
+            build_trees(graph)
+
     for graph in graphs:
         checkgraph(graph)
 

Modified: pypy/dist/pypy/translator/cli/function.py
==============================================================================
--- pypy/dist/pypy/translator/cli/function.py	(original)
+++ pypy/dist/pypy/translator/cli/function.py	Thu Apr 26 21:22:46 2007
@@ -6,6 +6,7 @@
 from pypy.objspace.flow import model as flowmodel
 from pypy.rpython.lltypesystem.lltype import Void
 from pypy.rpython.ootypesystem import ootype
+from pypy.translator.oosupport.treebuilder import SubOperation
 from pypy.translator.oosupport.function import Function as OOFunction
 from pypy.translator.oosupport.constant import push_constant
 from pypy.translator.cli.option import getoption
@@ -127,17 +128,18 @@
         else:
             self.ilasm.opcode('br', self._get_block_name(self.return_block))
 
-
     def _render_op(self, op):
-        from pypy.rpython.ootypesystem import ootype        
-        instr_list = self.db.genoo.opcodes.get(op.opname, None)
-        assert instr_list is not None, 'Unknown opcode: %s ' % op
-        assert isinstance(instr_list, InstructionList)
-        instr_list.render(self.generator, op)
+        OOFunction._render_op(self, op)
         if op.opname in ('direct_call', 'oosend', 'indirect_call') and not self.in_try:
             self._premature_return()
 
-    def _premature_return(self):
+    def _render_sub_op(self, sub_op):
+        OOFunction._render_sub_op(self, sub_op)
+        if sub_op.op.opname in ('direct_call', 'oosend', 'indirect_call') and not self.in_try:
+            self._premature_return(need_pop=sub_op.op.result is not ootype.Void)
+
+
+    def _premature_return(self, need_pop=False):
         try:
             return_block = self._get_block_name(self.graph.returnblock)
         except KeyError:
@@ -205,6 +207,23 @@
             self.load(return_var)
         self.ilasm.opcode('ret')
 
+    # XXX: this method should be moved into oosupport, but other
+    # backends are not ready :-(
+    def render_bool_switch(self, block):
+        assert len(block.exits) == 2
+        for link in block.exits:
+            if link.exitcase:
+                link_true = link
+            else:
+                link_false = link
+
+        true_label = self.next_label('link_true')
+        self.generator.load(block.exitswitch)
+        self.generator.branch_conditionally(link.exitcase, true_label)
+        self._follow_link(link_false) # if here, the exitswitch is false
+        self.set_label(true_label)
+        self._follow_link(link_true)  # if here, the exitswitch is true
+
     def render_numeric_switch(self, block):
         if block.exitswitch.concretetype in (ootype.SignedLongLong, ootype.UnsignedLongLong):
             # TODO: it could be faster to check is the values fit in
@@ -269,7 +288,8 @@
                     self.ilasm.load_arg(v)
             else:
                 self.ilasm.load_local(v)
-
+        elif isinstance(v, SubOperation):
+            self._render_sub_op(v)
         else:
             super(Function, self).load(v)
 

Modified: pypy/dist/pypy/translator/cli/test/runtest.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/runtest.py	(original)
+++ pypy/dist/pypy/translator/cli/test/runtest.py	Thu Apr 26 21:22:46 2007
@@ -166,16 +166,7 @@
 
     t.buildrtyper(type_system="ootype").specialize()
     check_virtual_methods(ootype.ROOT)
-    backend_opt_default = dict(
-        raisingop2direct_call=False,
-        inline_threshold=1,
-        mallocs=True,
-        merge_if_blocks=True,
-        constfold=True,
-        heap2stack=False,
-        clever_malloc_removal=False)
-    backend_opt_default.update(backend_opt)
-    #backend_optimizations(t, **backend_opt_default)
+    backend_optimizations(t)
     
     main_graph = t.graphs[0]
 

Modified: pypy/dist/pypy/translator/cli/test/test_snippet.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/test_snippet.py	(original)
+++ pypy/dist/pypy/translator/cli/test/test_snippet.py	Thu Apr 26 21:22:46 2007
@@ -2,5 +2,14 @@
 from pypy.translator.oosupport.test_template.snippets import BaseTestSnippets
 
 class TestSnippets(BaseTestSnippets, CliTest):
-    pass
+    def test_link_SSA(self):
+        def fn():
+            lst = [42, 43, 44]
+            for i in range(len(lst)):
+                item = lst[i]
+                if i < 10:
+                    lst[i] = item+10
+            return lst
+        res = self.ll_to_list(self.interpret(fn, []))
+        assert res == [52, 53, 54]
 

Modified: pypy/dist/pypy/translator/oosupport/function.py
==============================================================================
--- pypy/dist/pypy/translator/oosupport/function.py	(original)
+++ pypy/dist/pypy/translator/oosupport/function.py	Thu Apr 26 21:22:46 2007
@@ -5,7 +5,8 @@
 
 from pypy.objspace.flow import model as flowmodel
 from pypy.rpython.ootypesystem import ootype
-from pypy.translator.oosupport.metavm import InstructionList
+from pypy.translator.oosupport.treebuilder import SubOperation
+from pypy.translator.oosupport.metavm import InstructionList, StoreResult
 
 class Function(object):
 
@@ -194,6 +195,8 @@
         else:
             assert False, 'Unknonw exitswitch type: %s' % block.exitswitch.concretetype
 
+    # XXX: soon or later we should use the implementation in
+    # cli/function.py, but at the moment jvm and js fail with it.
     def render_bool_switch(self, block):
         for link in block.exits:
             self._setup_link(link)
@@ -221,15 +224,21 @@
                 self.generator.load(block.exitswitch)
                 self.generator.branch_if_equal(target_label)
 
+    def _follow_link(self, link):
+        target_label = self._get_block_name(link.target)
+        self._setup_link(link)
+        self.generator.branch_unconditionally(target_label)
+
     def _setup_link(self, link):
-        self.generator.add_comment("Setup link")
         target = link.target
         for to_load, to_store in zip(link.args, target.inputargs):
-            if to_load.concretetype is not ootype.Void:
-                self.generator.add_comment("  to_load=%r to_store=%r" % (
-                    to_load, to_store))
-                self.generator.load(to_load)
-                self.generator.store(to_store)
+            if isinstance(to_load, flowmodel.Variable) and to_load.name == to_store.name:
+                continue
+            if to_load.concretetype is ootype.Void:
+                continue
+            self.generator.add_comment("%r --> %r" % (to_load, to_store))
+            self.generator.load(to_load)
+            self.generator.store(to_store)
 
     def _render_op(self, op):
         instr_list = self.db.genoo.opcodes.get(op.opname, None)
@@ -237,6 +246,16 @@
         assert isinstance(instr_list, InstructionList)
         instr_list.render(self.generator, op)
 
+    def _render_sub_op(self, sub_op):
+        op = sub_op.op
+        instr_list = self.db.genoo.opcodes.get(op.opname, None)
+        assert instr_list is not None, 'Unknown opcode: %s ' % op
+        assert isinstance(instr_list, InstructionList)
+        assert instr_list[-1] is StoreResult, "Cannot inline an operation that doesn't store the result"
+        instr_list = InstructionList(instr_list[:-1]) # leave the value on the stack if this is a sub-op
+        instr_list.render(self.generator, op)
+        # now the value is on the stack
+
     # ---------------------------------------------------------#
     # These methods are quite backend independent, but not     #
     # used in all backends. Invoke them from your __init__ if  #

Modified: pypy/dist/pypy/translator/oosupport/treebuilder.py
==============================================================================
--- pypy/dist/pypy/translator/oosupport/treebuilder.py	(original)
+++ pypy/dist/pypy/translator/oosupport/treebuilder.py	Thu Apr 26 21:22:46 2007
@@ -50,7 +50,7 @@
                 if can_be_inlined(sub_op):
                     op.args[i] = SubOperation(sub_op)
                     block.operations[sub_i] = None
-    block.operations = [op for op in block.operations if op is not None]
+    block.operations = [op for op in block.operations if op is not None] or ()
 
 def build_trees(graph):
     if not getattr(graph, 'tree_built', False):



More information about the Pypy-commit mailing list