[pypy-svn] r32919 - in pypy/dist/pypy/translator/cli: . test

antocuni at codespeak.net antocuni at codespeak.net
Thu Oct 5 21:06:05 CEST 2006


Author: antocuni
Date: Thu Oct  5 21:06:04 2006
New Revision: 32919

Modified:
   pypy/dist/pypy/translator/cli/ilgenerator.py
   pypy/dist/pypy/translator/cli/stackopt.py
   pypy/dist/pypy/translator/cli/test/test_stackopt.py
Log:
Minor stackopt improvements.



Modified: pypy/dist/pypy/translator/cli/ilgenerator.py
==============================================================================
--- pypy/dist/pypy/translator/cli/ilgenerator.py	(original)
+++ pypy/dist/pypy/translator/cli/ilgenerator.py	Thu Oct  5 21:06:04 2006
@@ -99,6 +99,7 @@
 
     def begin_function(self, name, arglist, returntype, is_entrypoint = False, *args, **kwds):
         # TODO: .maxstack
+        self.func_name = name
         runtime = kwds.get('runtime', False)
         if runtime:
             method_type = 'runtime'
@@ -141,9 +142,9 @@
         self.writeline(')')
 
     def label(self, lbl):
-        self.writeline()
-        self.write(lbl + ':', indent=-1)
-        self.writeline()
+        self.code.writeline()
+        self.code.write(lbl + ':', indent=-1)
+        self.code.writeline()
 
     def leave(self, lbl):
         self.opcode('leave', lbl)
@@ -160,7 +161,7 @@
         self.opcode(opcode, lbl)
 
     def call(self, func):
-        self.opcode('call ', func)
+        self.opcode('call', func)
 
     def call_method(self, meth, virtual):
         if virtual:

Modified: pypy/dist/pypy/translator/cli/stackopt.py
==============================================================================
--- pypy/dist/pypy/translator/cli/stackopt.py	(original)
+++ pypy/dist/pypy/translator/cli/stackopt.py	Thu Oct  5 21:06:04 2006
@@ -1,9 +1,7 @@
 from pypy.translator.cli.ilgenerator import IlasmGenerator
 
 class StackOptMixin(object):
-    LOADS = set(['ldloc', 'ldarg']) # maybe ldarg.0?
-    STORES = set(['stloc'])
-    
+
     def __init__(self, *args):
         self.super = super(StackOptMixin, self)
         self.super.__init__(*args)
@@ -28,38 +26,69 @@
     def closeblock(self):
         self.pending_ops.append(('SUPER', ('closeblock',)))
 
+    def label(self, lbl):
+        self.pending_ops.append(('LABEL', (lbl,)))            
+
+    def _varname(self, op, args):
+        if op in ('ldloc', 'ldarg', 'stloc'):
+            return args[0]
+        elif op.startswith('ld'):
+            return ('PLACEHOLDER', op, args)
+        else:
+            assert False, "undefined varname of %s" % op
+
+    def _is_load(self, op):
+        return op is not None and op.startswith('ld')
+
+    def _is_simple_load(self, op):
+        return op is not None and (op.startswith('ldloc') or
+                                   op.startswith('ldarg') or
+                                   op.startswith('ldsfld') or
+                                   op.startswith('ldc'))
+
     def _optimize(self):
+        self._collect_stats()
+        self._remove_renaming()
+
+    def _collect_stats(self):
         assign_count = {}
         read_count = {}
-        for op, args in self.pending_ops:
-            if op in self.STORES:
+        for item in self.pending_ops:
+            if item is None:
+                continue
+            op, args = item
+            if op == 'stloc':
                 varname, = args
                 assign_count[varname] = assign_count.get(varname, 0) + 1
-            elif op in self.LOADS:
+            elif op == 'ldloc':
                 varname, = args
                 read_count[varname] = read_count.get(varname, 0) + 1
+        self.assign_count = assign_count
+        self.read_count = read_count
 
+    def _remove_renaming(self):
+        assign_count = self.assign_count
+        read_count = self.read_count
         prev_op, prev_args = None, None
         for i, (op, args) in enumerate(self.pending_ops):
-            if op in self.STORES and prev_op in self.LOADS:
+            if op == 'stloc' and self._is_simple_load(prev_op):
                 # ldloc x, stloc x0 --> remove both, map x0 to x
                 varname, = args
                 if assign_count[varname] == 1:
-                    self.mapping[varname] = self.mapping.get(prev_args[0], (prev_op, prev_args))
+                    self.mapping[varname] = self.mapping.get(self._varname(prev_op, prev_args), (prev_op, prev_args))
                     self.pending_ops[i-1] = None
                     self.pending_ops[i] = None
                     op, args = None, None # to prevent the next opcode thinking the previous was a store
-            elif op in self.LOADS:
-                if prev_op in self.STORES and args == prev_args and read_count[args[0]] == 1:
+            elif op == 'ldloc':
+                if prev_op == 'stloc' and args == prev_args and read_count[args[0]] == 1:
                     # stloc x, ldloc x --> remove both
                     self.pending_ops[i-1] = None
                     self.pending_ops[i] = None
                     op, args = None, None # to prevent the next opcode thinking the previous was a load
                 else:
                     # ldloc x, stloc x1, ..., ldloc x1 --> ..., ldloc x
-                    varname, = args
                     try:
-                        self.pending_ops[i] = self.mapping[varname]
+                        self.pending_ops[i] = self.mapping[self._varname(op, args)]
                     except KeyError:
                         pass
             prev_op, prev_args = op, args
@@ -73,6 +102,8 @@
             if opcode == 'SUPER':
                 method = args[0]
                 getattr(self.super, method)(*args[1:])
+            elif opcode == 'LABEL':
+                self.super.label(*args)
             else:
                 self.super.opcode(opcode, *args)
         self._reset()

Modified: pypy/dist/pypy/translator/cli/test/test_stackopt.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/test_stackopt.py	(original)
+++ pypy/dist/pypy/translator/cli/test/test_stackopt.py	Thu Oct  5 21:06:04 2006
@@ -99,3 +99,12 @@
     ilasm.opcode('ldloc', 'x')
     ilasm.flush()
     assert ilasm.opcodes[0] == ('stloc', ('x',))
+
+def test_ldarg0():
+    ilasm = TestStackOpt()
+    ilasm.opcode('ldarg.0')
+    ilasm.opcode('stloc', 'x')
+    ilasm.opcode('ldloc', 'x')
+    ilasm.flush()
+    assert ilasm.opcodes == [('ldarg.0', ())]
+



More information about the Pypy-commit mailing list