[pypy-svn] r65464 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test
fijal at codespeak.net
fijal at codespeak.net
Wed May 27 23:27:06 CEST 2009
Author: fijal
Date: Wed May 27 23:27:02 2009
New Revision: 65464
Modified:
pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py
pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py
Log:
implement escape analysis (all startboxes do escape as of now)
Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py
==============================================================================
--- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py (original)
+++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py Wed May 27 23:27:02 2009
@@ -13,7 +13,7 @@
pass
class InstanceNode(object):
- def __init__(self, source, const=False):
+ def __init__(self, source, const=False, escaped=False):
self.source = source
if const:
assert isinstance(source, Const)
@@ -24,10 +24,11 @@
self.virtualized = False
self.allocated_in_loop = False
self.vdesc = None
+ self.escaped = escaped
def __repr__(self):
flags = ''
- #if self.escaped: flags += 'e'
+ if self.escaped: flags += 'e'
#if self.startbox: flags += 's'
if self.const: flags += 'c'
#if self.virtual: flags += 'v'
@@ -41,11 +42,17 @@
def __init__(self, opts):
# NOT_RPYTHON
self.optimizations = [[] for i in range(rop._LAST)]
+ self.find_nodes_funcs = [[] for i in range(rop._LAST)]
for opt in opts:
for opnum, name in opname.iteritems():
meth = getattr(opt, 'optimize_' + name.lower(), None)
if meth is not None:
self.optimizations[opnum].append(meth)
+ for opt in opts:
+ for opnum, name in opname.iteritems():
+ meth = getattr(opt, 'find_nodes_' + name.lower(), None)
+ if meth is not None:
+ self.find_nodes_funcs[opnum].append(meth)
def getnode(self, box):
try:
@@ -54,7 +61,7 @@
if isinstance(box, Const):
node = InstanceNode(box, const=True)
else:
- node = InstanceNode(box)
+ node = InstanceNode(box, escaped=True)
self.nodes[box] = node
return node
@@ -65,6 +72,13 @@
def find_nodes(self):
for op in self.loop.operations:
+ res = False
+ for f in self.find_nodes_funcs[op.opnum]:
+ res = f(op, self)
+ if res:
+ break
+ if res:
+ continue
if op.is_always_pure():
is_pure = True
for arg in op.args:
@@ -81,10 +95,13 @@
self.getnode(arg)
# default case
for box in op.args:
- self.getnode(box)
+ node = self.getnode(box)
+ if not op.has_no_side_effect() and not op.is_guard():
+ node.escaped = True
box = op.result
if box is not None:
node = self.getnode(box)
+ node.escaped = False
if op.opnum == rop.NEW or op.opnum == rop.NEW_WITH_VTABLE:
node.allocated_in_loop = True
self.nodes[box] = node
@@ -190,11 +207,40 @@
class SimpleVirtualizableOpt(object):
@staticmethod
- def optimize_guard_nonvirtualized(op, spec):
+ def find_nodes_setfield_gc(op, spec):
+ instnode = spec.getnode(op.args[0])
+ if not instnode.virtualized:
+ return False
+ field = op.descr
+ if field not in instnode.vdesc.virtuals:
+ return False
+ return True
+
+ @staticmethod
+ def find_nodes_getfield_gc(op, spec):
+ instnode = spec.getnode(op.args[0])
+ if not instnode.virtualized:
+ return False
+ field = op.descr
+ if field not in instnode.vdesc.virtuals:
+ return False
+ spec.getnode(op.result).virtualized = True
+ return False
+
+ @staticmethod
+ def find_nodes_setarrayitem_gc(op, spec):
+ return False
+
+ @staticmethod
+ def find_nodes_guard_nonvirtualized(op, spec):
instnode = spec.getnode(op.args[0])
if not instnode.allocated_in_loop:
instnode.virtualized = True
instnode.vdesc = op.vdesc
+ return False
+
+ @staticmethod
+ def optimize_guard_nonvirtualized(op, spec):
return True
@staticmethod
@@ -210,7 +256,6 @@
spec.nodes[op.result] = node
return True
node = spec.getnode(op.result)
- node.virtualized = True
instnode.cleanfields[field] = node
return False
@@ -260,6 +305,12 @@
d[field] = (fieldnode, op.descr)
return True
+class SimpleVirtualOpt(object):
+ def optimize_new_with_vtable(op, spec):
+ xxx
+ node = spec.getnode(op.result)
+ node.escaped = False
+
specializer = Specializer([SimpleVirtualizableOpt(),
ConsecutiveGuardClassRemoval()])
Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py
==============================================================================
--- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py (original)
+++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py Wed May 27 23:27:02 2009
@@ -9,7 +9,8 @@
from pypy.jit.backend.llgraph import runner
from pypy.jit.metainterp.optimize2 import (optimize_loop,
- ConsecutiveGuardClassRemoval, Specializer, SimpleVirtualizableOpt)
+ ConsecutiveGuardClassRemoval, Specializer, SimpleVirtualizableOpt,
+ SimpleVirtualOpt)
from pypy.jit.metainterp.test.test_optimize import ANY
from pypy.jit.metainterp.test.oparser import parse
@@ -309,6 +310,72 @@
self.assert_equal(self.optimize(pre_op, [SimpleVirtualizableOpt()]),
expected)
+ def test_escape_analysis(self):
+ ops = """
+ [i0]
+ i1 = int_add(i0, i0)
+ """
+ spec = Specializer([])
+ loop = self.parse(ops)
+ optimize_loop(None, [], loop, self.cpu, spec=spec)
+ assert spec.nodes[loop.operations[0].args[0]].escaped
+ ops = """
+ [p0]
+ i1 = getfield_gc(p0, descr=field_desc)
+ i2 = int_add(i1, i1)
+ """
+ spec = Specializer([])
+ loop = self.parse(ops)
+ optimize_loop(None, [], loop, self.cpu, spec=spec)
+ assert not spec.nodes[loop.operations[0].result].escaped
+ ops = """
+ [p0]
+ i1 = getfield_gc(p0, descr=field_desc)
+ fail(i1)
+ """
+ spec = Specializer([])
+ loop = self.parse(ops)
+ optimize_loop(None, [], loop, self.cpu, spec=spec)
+ assert spec.nodes[loop.operations[0].result].escaped
+ ops = """
+ [p0]
+ i1 = getfield_gc(p0, descr=field_desc)
+ guard_true(i1)
+ fail()
+ """
+ spec = Specializer([])
+ loop = self.parse(ops)
+ optimize_loop(None, [], loop, self.cpu, spec=spec)
+ assert not spec.nodes[loop.operations[0].result].escaped
+
+ def test_escape_analysis_on_virtualizable(self):
+ ops = """
+ [p0]
+ guard_nonvirtualized(p0, vdesc=vdesc)
+ fail()
+ i1 = getfield_gc(p0, descr=field_desc)
+ setfield_gc(p0, i1, descr=field_desc)
+ i2 = int_add(i1, i1)
+ """
+ spec = Specializer([SimpleVirtualizableOpt()])
+ loop = self.parse(ops)
+ optimize_loop(None, [], loop, self.cpu, spec=spec)
+ assert not spec.nodes[loop.operations[0].result].escaped
+
+# def test_simple_virtual(self):
+# pre_op = """
+# []
+# p0 = new_with_vtable(13, ConstClass(node_vtable))
+# setfield_gc(p0, 1, descr=field_desc)
+# i2 = getfield_gc(p0, descr=field_desc)
+# fail(i2)
+# """
+# expected = """
+# []
+# fail(1)
+# """
+# self.assert_equal(self.optimize(pre_op, [SimpleVirtualOpt()]),
+# expected)
class TestLLtype(LLtypeMixin, BaseTestOptimize2):
pass
More information about the Pypy-commit
mailing list