[pypy-svn] pypy fold_intadd: First commit of optimization and test.
ademan
commits-noreply at bitbucket.org
Wed Mar 16 08:27:01 CET 2011
Author: Daniel Roberts <Ademan555 at gmail.com>
Branch: fold_intadd
Changeset: r42692:a1e30d4f9658
Date: 2011-03-16 00:26 -0700
http://bitbucket.org/pypy/pypy/changeset/a1e30d4f9658/
Log: First commit of optimization and test.
diff --git a/pypy/jit/metainterp/optimizeopt/__init__.py b/pypy/jit/metainterp/optimizeopt/__init__.py
--- a/pypy/jit/metainterp/optimizeopt/__init__.py
+++ b/pypy/jit/metainterp/optimizeopt/__init__.py
@@ -2,67 +2,43 @@
from pypy.jit.metainterp.optimizeopt.rewrite import OptRewrite
from pypy.jit.metainterp.optimizeopt.intbounds import OptIntBounds
from pypy.jit.metainterp.optimizeopt.virtualize import OptVirtualize
+from pypy.jit.metainterp.optimizeopt.fold_intadd import OptAddition
from pypy.jit.metainterp.optimizeopt.heap import OptHeap
from pypy.jit.metainterp.optimizeopt.string import OptString
from pypy.jit.metainterp.optimizeopt.unroll import optimize_unroll, OptInlineShortPreamble
-from pypy.jit.metainterp.optimizeopt.fficall import OptFfiCall
-from pypy.jit.metainterp.optimizeopt.simplify import OptSimplify
-from pypy.rlib.jit import PARAMETERS
-from pypy.rlib.unroll import unrolling_iterable
-ALL_OPTS = [('intbounds', OptIntBounds),
- ('rewrite', OptRewrite),
- ('virtualize', OptVirtualize),
- ('string', OptString),
- ('heap', OptHeap),
- ('ffi', OptFfiCall),
- ('unroll', None)]
-# no direct instantiation of unroll
-unroll_all_opts = unrolling_iterable(ALL_OPTS)
-
-ALL_OPTS_DICT = dict.fromkeys([name for name, _ in ALL_OPTS])
-
-ALL_OPTS_NAMES = ':'.join([name for name, _ in ALL_OPTS])
-PARAMETERS['enable_opts'] = ALL_OPTS_NAMES
-
-def optimize_loop_1(metainterp_sd, loop, enable_opts,
+def optimize_loop_1(metainterp_sd, loop, unroll=True,
inline_short_preamble=True, retraced=False):
"""Optimize loop.operations to remove internal overheadish operations.
"""
- optimizations = []
- unroll = 'unroll' in enable_opts
- for name, opt in unroll_all_opts:
- if name in enable_opts:
- if opt is not None:
- o = opt()
- if unroll and name == 'string':
- o.enabled = False
- # FIXME: Workaround to disable string optimisation
- # during preamble but to keep it during the loop
- optimizations.append(o)
-
- if 'rewrite' not in enable_opts or 'virtualize' not in enable_opts:
- optimizations.append(OptSimplify())
-
+ opt_str = OptString()
+ optimizations = [
+ OptAddition(),
+ OptIntBounds(),
+ OptRewrite(),
+ OptVirtualize(),
+ opt_str,
+ OptHeap(),
+ ]
if inline_short_preamble:
- optimizations = [OptInlineShortPreamble(retraced)] + optimizations
+ optimizations = [OptInlineShortPreamble(retraced)] + optimizations
+
+ if metainterp_sd.jit_ffi:
+ from pypy.jit.metainterp.optimizeopt.fficall import OptFfiCall
+ optimizations = optimizations + [
+ OptFfiCall(),
+ ]
if unroll:
+ opt_str.enabled = False # FIXME: Workaround to disable string optimisation
+ # during preamble but to keep it during the loop
optimize_unroll(metainterp_sd, loop, optimizations)
else:
optimizer = Optimizer(metainterp_sd, loop, optimizations)
optimizer.propagate_all_forward()
-def optimize_bridge_1(metainterp_sd, bridge, enable_opts,
- inline_short_preamble=True, retraced=False):
+def optimize_bridge_1(metainterp_sd, bridge, inline_short_preamble=True,
+ retraced=False):
"""The same, but for a bridge. """
- enable_opts = enable_opts.copy()
- try:
- del enable_opts['unroll']
- except KeyError:
- pass
- optimize_loop_1(metainterp_sd, bridge, enable_opts,
- inline_short_preamble, retraced)
-
-if __name__ == '__main__':
- print ALL_OPTS_NAMES
+ optimize_loop_1(metainterp_sd, bridge, False, inline_short_preamble,
+ retraced)
diff --git a/pypy/jit/metainterp/test/test_optimizeopt.py b/pypy/jit/metainterp/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/test/test_optimizeopt.py
@@ -5,7 +5,7 @@
BaseTest)
import pypy.jit.metainterp.optimizeopt.optimizer as optimizeopt
import pypy.jit.metainterp.optimizeopt.virtualize as virtualize
-from pypy.jit.metainterp.optimizeopt import optimize_loop_1, ALL_OPTS_DICT
+from pypy.jit.metainterp.optimizeopt import optimize_loop_1
from pypy.jit.metainterp.optimizeutil import InvalidLoop
from pypy.jit.metainterp.history import AbstractDescr, ConstInt, BoxInt
from pypy.jit.metainterp.history import TreeLoop, LoopToken
@@ -163,10 +163,7 @@
def optimize_loop(self, ops, optops, expected_preamble=None):
loop = self.parse(ops)
- if optops != "crash!":
- expected = self.parse(optops)
- else:
- expected = "crash!"
+ expected = self.parse(optops)
if expected_preamble:
expected_preamble = self.parse(expected_preamble)
#
@@ -188,18 +185,17 @@
def clone_if_mutable(self):
return self
loop.preamble.start_resumedescr = FakeDescr()
- optimize_loop_1(metainterp_sd, loop, ALL_OPTS_DICT)
+ optimize_loop_1(metainterp_sd, loop)
#
print
print loop.preamble.inputargs
print '\n'.join([str(o) for o in loop.preamble.operations])
- print
+ print
print loop.inputargs
print '\n'.join([str(o) for o in loop.operations])
print
-
- assert expected != "crash!", "should have raised an exception"
+
self.assert_equal(loop, expected)
if expected_preamble:
self.assert_equal(loop.preamble, expected_preamble,
@@ -833,7 +829,7 @@
i3 = getfield_gc(p2, descr=valuedescr)
escape(i3)
p3 = new_with_vtable(ConstClass(node_vtable))
- setfield_gc(p3, i1, descr=valuedescr)
+ setfield_gc(p3, i1, descr=valuedescr)
jump(i1, p3)
"""
# We cannot track virtuals that survive for more than two iterations.
@@ -893,7 +889,7 @@
escape(i3)
p2sub = new_with_vtable(ConstClass(node_vtable2))
setfield_gc(p2sub, i1, descr=valuedescr)
- setfield_gc(p2, p2sub, descr=nextdescr)
+ setfield_gc(p2, p2sub, descr=nextdescr)
jump(i1, p2, p2sub)
"""
expected = """
@@ -1018,7 +1014,7 @@
"""
preamble = """
[i, p0]
- i0 = getfield_gc(p0, descr=valuedescr)
+ i0 = getfield_gc(p0, descr=valuedescr)
i1 = int_add(i0, i)
jump(i, i1)
"""
@@ -1350,26 +1346,6 @@
self.node.value = 5
self.optimize_loop(ops, expected)
- def test_getfield_gc_pure_3(self):
- ops = """
- []
- p1 = escape()
- p2 = getfield_gc_pure(p1, descr=nextdescr)
- escape(p2)
- p3 = getfield_gc_pure(p1, descr=nextdescr)
- escape(p3)
- jump()
- """
- expected = """
- []
- p1 = escape()
- p2 = getfield_gc_pure(p1, descr=nextdescr)
- escape(p2)
- escape(p2)
- jump()
- """
- self.optimize_loop(ops, expected)
-
def test_getfield_gc_nonpure_2(self):
ops = """
[i]
@@ -3464,7 +3440,7 @@
guard_true(i1) []
i2 = int_sub(i0, 10)
i3 = int_lt(i2, -5)
- guard_true(i3) []
+ guard_true(i3) []
jump(i0)
"""
expected = """
@@ -3490,7 +3466,7 @@
i1 = int_lt(i0, 4)
guard_true(i1) []
i1p = int_gt(i0, -4)
- guard_true(i1p) []
+ guard_true(i1p) []
i2 = int_sub(i0, 10)
jump(i0)
"""
@@ -3773,7 +3749,7 @@
ops = """
[p4, p7, i30]
p16 = getfield_gc(p4, descr=valuedescr)
- p17 = getarrayitem_gc(p4, 1, descr=arraydescr)
+ p17 = getarrayitem_gc(p4, 1, descr=arraydescr)
guard_value(p16, ConstPtr(myptr), descr=<Guard3>) []
i1 = getfield_raw(p7, descr=nextdescr)
i2 = int_add(i1, i30)
@@ -3830,47 +3806,6 @@
self.node.value = 5
self.optimize_loop(ops, expected)
- def test_complains_getfieldpure_setfield(self):
- from pypy.jit.metainterp.optimizeopt.heap import BogusPureField
- ops = """
- [p3]
- p1 = escape()
- p2 = getfield_gc_pure(p1, descr=nextdescr)
- setfield_gc(p1, p3, descr=nextdescr)
- jump(p3)
- """
- py.test.raises(BogusPureField, self.optimize_loop, ops, "crash!")
-
- def test_dont_complains_different_field(self):
- ops = """
- [p3]
- p1 = escape()
- p2 = getfield_gc_pure(p1, descr=nextdescr)
- setfield_gc(p1, p3, descr=otherdescr)
- escape(p2)
- jump(p3)
- """
- expected = """
- [p3]
- p1 = escape()
- p2 = getfield_gc_pure(p1, descr=nextdescr)
- setfield_gc(p1, p3, descr=otherdescr)
- escape(p2)
- jump(p3)
- """
- self.optimize_loop(ops, expected)
-
- def test_dont_complains_different_object(self):
- ops = """
- []
- p1 = escape()
- p2 = getfield_gc_pure(p1, descr=nextdescr)
- p3 = escape()
- setfield_gc(p3, p1, descr=nextdescr)
- jump()
- """
- self.optimize_loop(ops, ops)
-
def test_getfield_guard_const(self):
ops = """
[p0]
@@ -3940,7 +3875,7 @@
jump(p0)
"""
self.optimize_loop(ops, expected, expected)
-
+
def test_addsub_ovf(self):
ops = """
[i0]
@@ -4060,7 +3995,7 @@
"""
expected = """
[i0, i1, i2]
- jump(i0, i1, i2)
+ jump(i0, i1, i2)
"""
self.optimize_loop(ops, expected, preamble)
@@ -4099,7 +4034,7 @@
"""
expected = """
[i0, i1, i2]
- jump(i0, i1, i2)
+ jump(i0, i1, i2)
"""
self.optimize_loop(ops, expected, preamble)
@@ -4117,7 +4052,7 @@
guard_false(i7) []
i8 = int_gt(i2c, -7)
guard_true(i8) []
- i9 = int_is_zero(i2c)
+ i9 = int_is_zero(i2c)
jump(i1, i2a, i2b, i2c)
"""
preamble = """
@@ -4129,12 +4064,12 @@
guard_true(i6) []
i8 = int_gt(i2c, -7)
guard_true(i8) []
- i9 = int_is_zero(i2c)
+ i9 = int_is_zero(i2c)
jump(i1, i2a, i2b, i2c)
"""
expected = """
[i0, i1, i2, i3]
- jump(i0, i1, i2, i3)
+ jump(i0, i1, i2, i3)
"""
self.optimize_loop(ops, expected, preamble)
@@ -4192,7 +4127,7 @@
def test_division_to_rshift(self):
ops = """
[i1, i2]
- it = int_gt(i1, 0)
+ it = int_gt(i1, 0)
guard_true(it)[]
i3 = int_floordiv(i1, i2)
i4 = int_floordiv(2, i2)
@@ -4210,15 +4145,15 @@
"""
expected = """
[i1, i2]
- it = int_gt(i1, 0)
- guard_true(it)[]
+ it = int_gt(i1, 0)
+ guard_true(it)[]
i3 = int_floordiv(i1, i2)
i4 = int_floordiv(2, i2)
i5 = int_rshift(i1, 1)
i6 = int_floordiv(3, i2)
i7 = int_floordiv(i1, 3)
i8 = int_floordiv(4, i2)
- i9 = int_rshift(i1, 2)
+ i9 = int_rshift(i1, 2)
i10 = int_floordiv(i1, 0)
i11 = int_rshift(i1, 0)
i12 = int_floordiv(i2, 2)
@@ -4259,7 +4194,7 @@
i9 = int_lt(i1b, 100)
guard_true(i9) []
i10 = int_gt(i1b, -100)
- guard_true(i10) []
+ guard_true(i10) []
i13 = int_lshift(i1b, i2)
i14 = int_rshift(i13, i2)
i15 = int_lshift(i1b, 2)
@@ -4283,19 +4218,16 @@
i9 = int_lt(i1b, 100)
guard_true(i9) []
i10 = int_gt(i1b, -100)
- guard_true(i10) []
+ guard_true(i10) []
i13 = int_lshift(i1b, i2)
i14 = int_rshift(i13, i2)
i15 = int_lshift(i1b, 2)
- i16 = int_rshift(i15, 2)
i17 = int_lshift(i1b, 100)
i18 = int_rshift(i17, 100)
- i19 = int_eq(i1b, i16)
- guard_true(i19) []
jump(i2, i3, i1b, i2b)
"""
self.optimize_loop(ops, expected)
-
+
def test_subsub_ovf(self):
ops = """
[i0]
@@ -4479,7 +4411,7 @@
jump(i0, i1, i1b, i2, i3)
"""
preamble = """
- [i0, i1, i1b, i2, i3]
+ [i0, i1, i1b, i2, i3]
i4 = int_lt(i1, 7)
guard_true(i4) []
i4b = int_lt(i1b, 7)
@@ -4507,9 +4439,9 @@
"""
expected = """
[i0, i1, i1b, i2, i3]
- jump(i0, i1, i1b, i2, i3)
- """
- self.optimize_loop(ops, expected, preamble)
+ jump(i0, i1, i1b, i2, i3)
+ """
+ self.optimize_loop(ops, expected, preamble)
def test_bound_rshift(self):
ops = """
@@ -4544,7 +4476,7 @@
jump(i0, i1, i1b, i2, i3)
"""
preamble = """
- [i0, i1, i1b, i2, i3]
+ [i0, i1, i1b, i2, i3]
i4 = int_lt(i1, 7)
guard_true(i4) []
i4b = int_lt(i1b, 7)
@@ -4572,9 +4504,9 @@
"""
expected = """
[i0, i1, i1b, i2, i3]
- jump(i0, i1, i1b, i2, i3)
- """
- self.optimize_loop(ops, expected, preamble)
+ jump(i0, i1, i1b, i2, i3)
+ """
+ self.optimize_loop(ops, expected, preamble)
def test_bound_dont_backpropagate_rshift(self):
ops = """
@@ -4587,7 +4519,7 @@
"""
self.optimize_loop(ops, ops, ops)
-
+
def test_mul_ovf(self):
ops = """
[i0, i1]
@@ -4726,7 +4658,7 @@
def sort_key(self):
return id(self)
-
+
for n in ('inst_w_seq', 'inst_index', 'inst_w_list', 'inst_length',
'inst_start', 'inst_step'):
self.namespace[n] = FakeDescr(n)
@@ -4768,7 +4700,7 @@
i87 = int_add(i84, i86)
i91 = int_add(i80, 1)
setfield_gc(p75, i91, descr=inst_index)
-
+
p110 = same_as(ConstPtr(myptr))
i112 = same_as(3)
i114 = same_as(39)
@@ -4788,13 +4720,13 @@
p1 = getfield_gc(p0, descr=valuedescr)
setfield_gc(p0, p1, descr=valuedescr)
setfield_gc(p0, p1, descr=valuedescr)
- setfield_gc(p0, p0, descr=valuedescr)
+ setfield_gc(p0, p0, descr=valuedescr)
jump(p0)
"""
preamble = """
[p0]
p1 = getfield_gc(p0, descr=valuedescr)
- setfield_gc(p0, p0, descr=valuedescr)
+ setfield_gc(p0, p0, descr=valuedescr)
jump(p0)
"""
expected = """
@@ -4807,7 +4739,7 @@
ops = """
[p0]
p1 = getfield_gc(p0, descr=valuedescr)
- setfield_gc(p0, p0, descr=valuedescr)
+ setfield_gc(p0, p0, descr=valuedescr)
setfield_gc(p0, p1, descr=valuedescr)
setfield_gc(p0, p1, descr=valuedescr)
jump(p0)
@@ -4831,7 +4763,7 @@
p2 = new_with_vtable(ConstClass(node_vtable))
setfield_gc(p2, i1, descr=nextdescr)
"""
-
+
# ----------
def optimize_strunicode_loop(self, ops, optops, preamble=None):
if not preamble:
@@ -5113,40 +5045,6 @@
"""
self.optimize_strunicode_loop(ops, expected)
- def test_strgetitem_small(self):
- ops = """
- [p0, i0]
- i1 = strgetitem(p0, i0)
- i2 = int_lt(i1, 256)
- guard_true(i2) []
- i3 = int_ge(i1, 0)
- guard_true(i3) []
- jump(p0, i0)
- """
- expected = """
- [p0, i0]
- i1 = strgetitem(p0, i0)
- jump(p0, i0)
- """
- self.optimize_loop(ops, expected)
-
- def test_strlen_positive(self):
- ops = """
- [p0]
- i0 = strlen(p0)
- i1 = int_ge(i0, 0)
- guard_true(i1) []
- i2 = int_gt(i0, -1)
- guard_true(i2) []
- jump(p0)
- """
- expected = """
- [p0]
- i0 = strlen(p0)
- jump(p0)
- """
- self.optimize_loop(ops, expected)
-
# ----------
def optimize_strunicode_loop_extradescrs(self, ops, optops, preamble=None):
from pypy.jit.metainterp.optimizeopt import string
@@ -5506,9 +5404,24 @@
# more generally, supporting non-constant but virtual cases is
# not obvious, because of the exception UnicodeDecodeError that
# can be raised by ll_str2unicode()
-
-
-
+
+
+class TestFoldIntAdds(OptimizeOptTest, LLtypeMixin):
+ def test_fold(self):
+ ops = """
+ [i0]
+ i1 = int_add(i0, 3)
+ i2 = int_add(i1, 16)
+ i3 = int_add(i2, 9)
+ jump(i3)
+ """
+
+ expected = """
+ [i0]
+ i3 = int_add(i0, 28)
+ jump(i3)
+ """
+ self.optimize_loop(ops, expected)
##class TestOOtype(OptimizeOptTest, OOtypeMixin):
diff --git a/pypy/jit/metainterp/optimizeopt/fold_intadd.py b/pypy/jit/metainterp/optimizeopt/fold_intadd.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/metainterp/optimizeopt/fold_intadd.py
@@ -0,0 +1,77 @@
+from pypy.jit.metainterp.optimizeopt.optimizer import *
+from pypy.jit.metainterp.resoperation import opboolinvers, opboolreflex
+from pypy.jit.metainterp.history import ConstInt
+from pypy.jit.metainterp.optimizeutil import _findall
+from pypy.jit.metainterp.resoperation import rop, ResOperation
+from pypy.jit.codewriter.effectinfo import EffectInfo
+from pypy.jit.metainterp.optimizeopt.intutils import IntBound
+from pypy.rlib.rarithmetic import highest_bit
+
+class OptAddition(Optimization):
+ def __init__(self):
+ self.args = {}
+
+ def reconstruct_for_next_iteration(self, optimizer, valuemap):
+ return OptAddition()
+
+ def propagate_forward(self, op):
+ opnum = op.getopnum()
+ for value, func in optimize_ops:
+ if opnum == value:
+ func(self, op)
+ break
+ else:
+ self.optimize_default(op)
+
+ def _int_add(self, variable, constant, result):
+ return ResOperation(rop.INT_ADD, [variable, constant], result)
+
+ def _store_add(self, variable, constant, result):
+ try:
+ root, stored_constant = self.args[variable]
+ constant = constant + stored_constant
+ except KeyError:
+ root = variable
+
+ self.args[result] = root, constant
+
+ def optimize_INT_ADD(self, op):
+ lv = self.getvalue(op.getarg(0))
+ rv = self.getvalue(op.getarg(1))
+ print "lv = %s rv = %s" % (lv.box, rv.box)
+ result = op.result
+ if lv.is_constant() and rv.is_constant():
+ self.emit_operation(op) # XXX: there's support for optimizing this elsewhere, right?
+ elif lv.is_constant():
+ constant = lv.box.getint()
+ self._store_add(op.getarg(1), constant, result)
+ elif rv.is_constant():
+ constant = rv.box.getint()
+ self._store_add(op.getarg(0), constant, result)
+ else:
+ self.emit_operation(op)
+
+ def optimize_default(self, op):
+ for i in range(op.numargs()):
+ arg = self.getvalue(op.getarg(i))
+ print 'type(%s) = %s' % (arg.box, type(arg))
+ if arg.is_constant():
+ continue
+
+ try:
+ variable = op.getarg(i)
+ root, constant = self.args[variable]
+ del self.args[variable] # TODO: mark as used instead of deleting
+
+ constant = ConstInt(constant)
+ new_op = self._int_add(root, constant, variable)
+ print new_op
+ self.emit_operation(new_op)
+ except KeyError:
+ pass
+ print op
+ self.emit_operation(op)
+
+ #def optimize_INT_SUB(self, op): pass
+
+optimize_ops = _findall(OptAddition, 'optimize_')
More information about the Pypy-commit
mailing list