[pypy-svn] r17903 - in pypy/dist/pypy/translator: backendopt backendopt/test llvm llvm/backendopt llvm/module

ericvrp at codespeak.net ericvrp at codespeak.net
Tue Sep 27 15:33:12 CEST 2005


Author: ericvrp
Date: Tue Sep 27 15:33:10 2005
New Revision: 17903

Added:
   pypy/dist/pypy/translator/backendopt/removezerobytemalloc.py
   pypy/dist/pypy/translator/backendopt/test/test_removezerobytemalloc.py
   pypy/dist/pypy/translator/llvm/backendopt/mergemallocs.py
   pypy/dist/pypy/translator/llvm/backendopt/removeexcmallocs.py
Modified:
   pypy/dist/pypy/translator/backendopt/all.py
   pypy/dist/pypy/translator/llvm/exception.py
   pypy/dist/pypy/translator/llvm/funcnode.py
   pypy/dist/pypy/translator/llvm/genllvm.py
   pypy/dist/pypy/translator/llvm/module/extfunction.py
Log:
working on experimental transformations. disabled for now!


Modified: pypy/dist/pypy/translator/backendopt/all.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/all.py	(original)
+++ pypy/dist/pypy/translator/backendopt/all.py	Tue Sep 27 15:33:10 2005
@@ -4,23 +4,34 @@
 from pypy.translator.backendopt.malloc import remove_simple_mallocs
 from pypy.translator.backendopt.ssa import SSI_to_SSA
 from pypy.translator.backendopt.propagate import propagate_all
+from pypy.translator.backendopt.removezerobytemalloc import remove_zero_byte_mallocs
 from pypy.translator import simplify
 
 
 def backend_optimizations(translator, inline_threshold=1,
                                       mallocs=True,
                                       ssa_form=True,
-                                      propagate=False):
+                                      propagate=False,
+                                      removezerobytemallocs=False):
     # remove obvious no-ops
     for graph in translator.flowgraphs.values():
         remove_same_as(graph)
         simplify.eliminate_empty_blocks(graph)
         simplify.transform_dead_op_vars(graph, translator)
-    # inline functions in each other
+
+    # remove allocation of empty structs
+    if removezerobytemallocs:
+        for graph in translator.flowgraphs.values():
+            remove_zero_byte_mallocs(graph)
+
+    # ...
     if propagate:
         propagate_all(translator)
+
+    # inline functions in each other
     if inline_threshold:
         auto_inlining(translator, inline_threshold)
+
     # vaporize mallocs
     if mallocs:
         for graph in translator.flowgraphs.values():

Added: pypy/dist/pypy/translator/backendopt/removezerobytemalloc.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/backendopt/removezerobytemalloc.py	Tue Sep 27 15:33:10 2005
@@ -0,0 +1,16 @@
+from pypy.objspace.flow.model import Constant, Block, flatten
+from pypy.objspace.flow.model import SpaceOperation
+from pypy.rpython import lltype
+
+def remove_zero_byte_mallocs(graph):
+    blocks = [x for x in flatten(graph) if isinstance(x, Block)]
+    for block in blocks:
+        for i, op in enumerate(block.operations):
+            if op.opname != 'malloc':
+                continue
+            arg = op.args[0].value
+            if True: #isinstance(arg, lltype.Struct) and arg._names_without_voids() == []:
+                print 'remove_zero_byte_mallocs: removed malloc(%s) from previous line' % arg
+                nullresulttype = op.result.concretetype
+                nullresult     = Constant(nullresulttype._defl(), nullresulttype)
+                block.operations[i] = SpaceOperation('cast_null_to_ptr', [nullresult], op.result)

Added: pypy/dist/pypy/translator/backendopt/test/test_removezerobytemalloc.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/backendopt/test/test_removezerobytemalloc.py	Tue Sep 27 15:33:10 2005
@@ -0,0 +1,21 @@
+from pypy.objspace.flow.model import traverse, Block, Link, Variable, Constant
+from pypy.translator.backendopt.removezerobytemalloc import remove_zero_byte_mallocs
+from pypy.translator.translator import Translator
+from pypy.rpython.llinterp import LLInterpreter
+from pypy.translator.test.snippet import is_perfect_number
+
+def test_removezerobytemalloc():
+    x = ()
+    def func2(q):
+        return q
+    def zerobytemalloc():
+        y = func2(x)
+        return len(x)
+    t = Translator(zerobytemalloc)
+    a = t.annotate([])
+    t.specialize()
+    remove_zero_byte_mallocs(t.flowgraphs[zerobytemalloc])
+    #t.view()
+    lli = LLInterpreter(t.flowgraphs, t.rtyper)
+    res = lli.eval_function(zerobytemalloc, ())
+    assert res == 0

Added: pypy/dist/pypy/translator/llvm/backendopt/mergemallocs.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/llvm/backendopt/mergemallocs.py	Tue Sep 27 15:33:10 2005
@@ -0,0 +1,22 @@
+from pypy.objspace.flow.model import Block, flatten, SpaceOperation
+
+
+def merge_mallocs(translator, graph):
+    """Merge all mallocs of identical in a block into one.
+    Thus all mallocs of atomic data are merged and all mallocs of
+    non-atomic data are also merged into one. This reasoning behind this is
+    that data allocated in the same block will probably have about the same
+    livespan. So we hope that this does not increase the memory appetite
+    of your program by much.
+
+    warning: some will consider this a dirty hack, that's ok! :)
+    """
+    blocks = [x for x in flatten(graph) if isinstance(x, Block)]
+    for block in blocks:
+        n_mallocs_in_block = 0
+        for op in block.operations:
+            if op.opname != 'malloc':
+                continue
+            n_mallocs_in_block += 1
+        if n_mallocs_in_block >= 2:
+            print 'merge_mallocs: n_mallocs_in_block=%d' % n_mallocs_in_block

Added: pypy/dist/pypy/translator/llvm/backendopt/removeexcmallocs.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/llvm/backendopt/removeexcmallocs.py	Tue Sep 27 15:33:10 2005
@@ -0,0 +1,37 @@
+from pypy.objspace.flow.model import Block, Constant, flatten, SpaceOperation
+from pypy.translator.backendopt.inline import _find_exception_type
+
+
+def _llvm_structsize(struct):
+    #XXX TODO take a save guess
+    return 16
+
+def remove_exception_mallocs(translator, graph, ringbuffer_entry_maxsize=16, ringbuffer_n_entries=1024):
+    """Remove mallocs that occur because an exception is raised.
+    Typically this data is shortlived and occuring often in highlevel
+    languages like Python. So it would be preferable if we would not need
+    to call a malloc function. We can not allocate the data on the stack
+    because a global pointer (last_exception_type) is pointing to it.
+
+    Here we use a ringbuffer of fixed size to contain exception instances.
+    Our ringbuffer entries have fixed (maximum)size so all malloc over that
+    amount are not affected by this code.
+    
+    warning: this code will not work when your code references
+             an exception instance 'long' after it has been raised.
+    """
+    blocks = [x for x in flatten(graph) if isinstance(x, Block)]
+    for block in blocks:
+        ops = block.operations
+        if (len(ops) < 3 or
+            ops[0].opname != 'malloc'   or ops[1].opname != 'cast_pointer'   or
+            ops[2].opname != 'setfield' or ops[2].args[1].value != 'typeptr' or
+            not isinstance(ops[2].args[1], Constant) or
+            _llvm_structsize(ops[0].args[0]) > ringbuffer_entry_maxsize): #todo: ops[2].args[2] to vtable
+            continue
+        print 'remove_exception_malloc: ', str(ops[0].args[0]), ops[2].args[2]
+        #ops = [SpaceOperation('ops[0].result = load sbyte** %exception_ringbuffer'),
+        #       SpaceOperation('%tmpptr.0 = add sbyte* ops[0].result, ringbuffer_entry_maxsize'),
+        #       SpaceOperation('%tmpptr.1 = and sbyte* tmpptr.0, ~(ringbuffer_n_entries*ringbuffer_entry_maxsize)'),
+        #       SpaceOperation('store sbyte* %tmpptr.1, sbyte** %exception_ringbuffer),
+        #       ops[1:]]

Modified: pypy/dist/pypy/translator/llvm/exception.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/exception.py	(original)
+++ pypy/dist/pypy/translator/llvm/exception.py	Tue Sep 27 15:33:10 2005
@@ -2,6 +2,9 @@
 
 
 class ExceptionPolicy:
+    RINGBUFFER_ENTRY_MAXSIZE = 16
+    RINGBUGGER_N_ENTRIES = 1024
+
     def __init__(self):
         raise Exception, 'ExceptionPolicy should not be used directly'
 

Modified: pypy/dist/pypy/translator/llvm/funcnode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/funcnode.py	(original)
+++ pypy/dist/pypy/translator/llvm/funcnode.py	Tue Sep 27 15:33:10 2005
@@ -5,6 +5,8 @@
 from pypy.translator.llvm.node import LLVMNode, ConstantLLVMNode
 from pypy.translator.llvm.opwriter import OpWriter
 from pypy.translator.llvm.log import log 
+from pypy.translator.llvm.backendopt.removeexcmallocs import remove_exception_mallocs
+from pypy.translator.llvm.backendopt.mergemallocs import merge_mallocs
 from pypy.translator.unsimplify import remove_double_links
 log = log.funcnode
 
@@ -38,6 +40,8 @@
         self.ref   = self.make_ref('%pypy_', value.graph.name)
         self.graph = value.graph
         self.db.genllvm.exceptionpolicy.transform(self.db.translator, self.graph)
+        #remove_exception_mallocs(self.db.translator, self.graph)
+        #merge_mallocs(self.db.translator, self.graph)
         remove_double_links(self.db.translator, self.graph)
 
     def __str__(self):

Modified: pypy/dist/pypy/translator/llvm/genllvm.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/genllvm.py	(original)
+++ pypy/dist/pypy/translator/llvm/genllvm.py	Tue Sep 27 15:33:10 2005
@@ -253,7 +253,7 @@
     a = t.annotate(annotation)
     a.simplify()
     t.specialize()
-    t.backend_optimizations(ssa_form=False)
+    t.backend_optimizations(ssa_form=False, propagate=False, removezerobytemallocs=False)
     if view:    #note: this is without policy transforms
         t.view()
     return genllvm(t, **kwds)

Modified: pypy/dist/pypy/translator/llvm/module/extfunction.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/module/extfunction.py	(original)
+++ pypy/dist/pypy/translator/llvm/module/extfunction.py	Tue Sep 27 15:33:10 2005
@@ -1,6 +1,9 @@
 extdeclarations =  '''
 %last_exception_type  = internal global %RPYTHON_EXCEPTION_VTABLE* null
 %last_exception_value = internal global %RPYTHON_EXCEPTION* null
+
+%exception_ringbuffer = internal global [8192 x sbyte] zeroinitializer
+%exception_ringbuffer_index = internal global int 0
 '''
 
 extfunctions = {}   #dependencies, llvm-code



More information about the Pypy-commit mailing list