Author: Maciej Fijalkowski <[email protected]>
Branch: result-in-resops
Changeset: r58398:e286cf78805e
Date: 2012-10-24 18:30 +0200
http://bitbucket.org/pypy/pypy/changeset/e286cf78805e/
Log: Start attacking the optimizer chain
diff --git a/pypy/jit/metainterp/optimizeopt/earlyforce.py
b/pypy/jit/metainterp/optimizeopt/earlyforce.py
--- a/pypy/jit/metainterp/optimizeopt/earlyforce.py
+++ b/pypy/jit/metainterp/optimizeopt/earlyforce.py
@@ -8,6 +8,8 @@
class OptEarlyForce(Optimization):
def propagate_forward(self, op):
+ self.emit_operation(op)
+ return
opnum = op.getopnum()
if (opnum != rop.SETFIELD_GC and
opnum != rop.SETARRAYITEM_GC and
diff --git a/pypy/jit/metainterp/optimizeopt/heap.py
b/pypy/jit/metainterp/optimizeopt/heap.py
--- a/pypy/jit/metainterp/optimizeopt/heap.py
+++ b/pypy/jit/metainterp/optimizeopt/heap.py
@@ -229,17 +229,17 @@
cf = submap[index] = CachedField()
return cf
- def emit_operation(self, op):
- self.emitting_operation(op)
- if self.posponedop:
- posponedop = self.posponedop
- self.posponedop = None
- self.next_optimization.propagate_forward(posponedop)
- if (op.is_comparison() or op.getopnum() in opgroups.CALL_MAY_FORCE
- or op.is_ovf()):
- self.posponedop = op
- else:
- Optimization.emit_operation(self, op)
+ #def emit_operation(self, op):
+ # self.emitting_operation(op)
+ # if self.posponedop:
+ # posponedop = self.posponedop
+ # self.posponedop = None
+ # self.next_optimization.propagate_forward(posponedop)
+ # if (op.is_comparison() or op.getopnum() in opgroups.CALL_MAY_FORCE
+ # or op.is_ovf()):
+ # self.posponedop = op
+ # else:
+ # Optimization.emit_operation(self, op)
def emitting_operation(self, op):
if op.has_no_side_effect():
@@ -540,6 +540,6 @@
self.emit_operation(op)
-dispatch_opt = make_dispatcher_method(OptHeap, 'optimize_',
- default=OptHeap.emit_operation)
-OptHeap.propagate_forward = dispatch_opt
+#dispatch_opt = make_dispatcher_method(OptHeap, 'optimize_',
+# default=OptHeap.emit_operation)
+#OptHeap.propagate_forward = dispatch_opt
diff --git a/pypy/jit/metainterp/optimizeopt/intbounds.py
b/pypy/jit/metainterp/optimizeopt/intbounds.py
--- a/pypy/jit/metainterp/optimizeopt/intbounds.py
+++ b/pypy/jit/metainterp/optimizeopt/intbounds.py
@@ -15,12 +15,12 @@
def new(self):
return OptIntBounds()
- def propagate_forward(self, op):
- dispatch_opt(self, op)
+ #def propagate_forward(self, op):
+ # dispatch_opt(self, op)
- def opt_default(self, op):
- assert not op.is_ovf()
- self.emit_operation(op)
+ #def opt_default(self, op):
+ # assert not op.is_ovf()
+ # self.emit_operation(op)
def propagate_bounds_backward(self, box):
@@ -471,6 +471,6 @@
propagate_bounds_INT_MUL_OVF = propagate_bounds_INT_MUL
-dispatch_opt = make_dispatcher_method(OptIntBounds, 'optimize_',
- default=OptIntBounds.opt_default)
-dispatch_bounds_ops = make_dispatcher_method(OptIntBounds, 'propagate_bounds_')
+#dispatch_opt = make_dispatcher_method(OptIntBounds, 'optimize_',
+# default=OptIntBounds.opt_default)
+#dispatch_bounds_ops = make_dispatcher_method(OptIntBounds,
'propagate_bounds_')
diff --git a/pypy/jit/metainterp/optimizeopt/optimizer.py
b/pypy/jit/metainterp/optimizeopt/optimizer.py
--- a/pypy/jit/metainterp/optimizeopt/optimizer.py
+++ b/pypy/jit/metainterp/optimizeopt/optimizer.py
@@ -2,13 +2,12 @@
""" This file implements the entry point to optimizations - the Optimizer.
optimizations are dispatched in order they're passed and for each operation
optimize_XYZ where XYZ is the name of resop is called. The method can choose
-to return None (optimized away) or call self.emit_operation which means
+to return None (optimized away) or return the operation to emit.
it'll be passed onto the next one.
-Each resop can have an extra attribute optimize_replace, which points to
-a new version of the same resop. Also each one can have optimize_value,
-which is valid when optimize_replace is not set. There is 1-1 mapping, which
-means that two resops cannot share the optimize_value extra attribute
+Each resop can have an extra attribute _forwarded, which points to
+a new version of the same resop. It can be a mutable resop (from optmodel)
+or a constant.
"""
from pypy.jit.metainterp import jitprof, resume, compile
@@ -19,10 +18,9 @@
IntLowerBound, MININT,
MAXINT
from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method
from pypy.jit.metainterp.resoperation import rop, AbstractResOp, opgroups,\
- Const, ConstInt, ConstFloat, AbstractValue
+ Const, ConstInt, opname
from pypy.jit.metainterp.typesystem import llhelper
-from pypy.jit.codewriter import longlong
-from pypy.rlib.objectmodel import specialize, we_are_translated
+from pypy.rlib.objectmodel import specialize
from pypy.tool.pairtype import extendabletype
LEVEL_UNKNOWN = '\x00'
@@ -43,11 +41,6 @@
def clone(self):
return LenBound(self.mode, self.descr, self.bound.clone())
-class exploder(object):
- def __getattribute__(self, attr):
- import pdb
- pdb.set_trace()
-
class OptValue(object):
_attrs_ = ('known_class', 'last_guard', 'level', 'intbound', 'lenbound',
'is_bool_box')
@@ -58,17 +51,6 @@
known_class = None
intbound = ImmutableIntUnbounded()
lenbound = None
- is_bool_box = False
-
- def getbox(self):
- import pdb
- pdb.set_trace()
-
- def setbox(self, x):
- import pdb
- pdb.set_trace()
-
- box = property(getbox, setbox)
def __init__(self, op, level=None, known_class=None, intbound=None):
self.op = op
@@ -196,6 +178,7 @@
self.intbound = IntUnbounded()
def get_constant_class(self, cpu):
+ xxx
level = self.level
if level == LEVEL_KNOWNCLASS:
return self.known_class
@@ -291,21 +274,32 @@
class Optimization(object):
- next_optimization = None
+ optimize_default = None
def __init__(self):
pass # make rpython happy
- def propagate_forward(self, op):
- raise NotImplementedError
+ #def propagate_forward(self, op):
+ # raise NotImplementedError
- def emit_operation(self, op):
- self.last_emitted_operation = op
- self.next_optimization.propagate_forward(op)
+ #def emit_operation(self, op):
+ # self.last_emitted_operation = op
+ # self.next_optimization.propagate_forward(op)
+
+ def optimize_operation(self, op):
+ name = 'optimize_' + opname[op.getopnum()]
+ next_func = getattr(self, name, self.optimize_default)
+ if next_func is not None:
+ op = next_func(op)
+ if op is None:
+ return
+ else:
+ self.last_emitted_operation = op
+ return op
# FIXME: Move some of these here?
- def getvalue(self, box, create=True):
- return self.optimizer.getvalue(box, create=create)
+ def getforwarded(self, op):
+ return self.optimizer.getforwarded(op)
def setvalue(self, box, value):
self.optimizer.setvalue(box, value)
@@ -319,8 +313,8 @@
def replace(self, box, value):
return self.optimizer.replace(box, value)
- def get_constant_box(self, box):
- return self.optimizer.get_constant_box(box)
+ def get_constant_op(self, op):
+ return self.optimizer.get_constant_op(op)
def new_box(self, fieldofs):
return self.optimizer.new_box(fieldofs)
@@ -392,25 +386,11 @@
if loop is not None:
self.call_pure_results = loop.call_pure_results
- self.set_optimizations(optimizations)
+ self.optimizations = optimizations
+ for opt in optimizations:
+ opt.optimizer = self
self.setup()
- def set_optimizations(self, optimizations):
- if optimizations:
- self.first_optimization = optimizations[0]
- for i in range(1, len(optimizations)):
- optimizations[i - 1].next_optimization = optimizations[i]
- optimizations[-1].next_optimization = self
- for o in optimizations:
- o.optimizer = self
- o.last_emitted_operation = None
- o.setup()
- else:
- optimizations = []
- self.first_optimization = self
-
- self.optimizations = optimizations
-
def force_at_end_of_preamble(self):
for o in self.optimizations:
o.force_at_end_of_preamble()
@@ -441,20 +421,29 @@
self.metainterp_sd.profiler.count(jitprof.Counters.OPT_FORCINGS)
self.resumedata_memo.forget_numberings(virtualbox)
- def getvalue(self, box):
- if box.is_constant():
- if box.type == REF:
- if not box.getref_base():
+ def getforwarded(self, op):
+ if op.is_constant():
+ if op.type == REF:
+ if not op.getref_base():
return CONST_NULL
try:
- return self.interned_refs[box.getref_base()]
+ return self.interned_refs[op.getref_base()]
except KeyError:
- self.interned_refs[box.getref_base()] = box
- return box
- return box
- value = box._forwarded
+ self.interned_refs[op.getref_base()] = op
+ return op
+ return op
+ value = op._forwarded
if value is None:
- value = box.make_forwarded_copy()
+ value = op.make_forwarded_copy()
+ else:
+ if value._forwarded:
+ while value._forwarded:
+ value = value._forwarded
+ to_patch = op
+ while to_patch._forwarded:
+ next = to_patch._forwarded
+ to_patch._forwarded = value
+ to_patch = next
#self.ensure_imported(value)
return value
@@ -465,13 +454,15 @@
box.set_extra("optimize_value", value)
def copy_op_if_modified_by_optimization(self, op):
+ xxxx
new_op = op.copy_if_modified_by_optimization(self)
if new_op is not op:
self.replace(op, new_op)
return new_op
# XXX some RPython magic needed
- def copy_and_change(self, op, *args, **kwds):
+ def copy_and_change(self, op, *args, **kwds):
+ xxx
new_op = op.copy_and_change(*args, **kwds)
if new_op is not op:
self.replace(op, new_op)
@@ -481,19 +472,10 @@
pass
@specialize.argtype(0)
- def get_constant_box(self, box):
- if isinstance(box, Const):
- return box
- try:
- value = self.getvalue(box)
- self.ensure_imported(value)
- except KeyError:
- return None
- if value.is_constant():
- constbox = value.op
- assert isinstance(constbox, Const)
- return constbox
- return None
+ def get_constant_op(self, op):
+ op = self.getforwarded(op)
+ if isinstance(op, Const):
+ return op
def get_newoperations(self):
self.flush()
@@ -502,20 +484,6 @@
def clear_newoperations(self):
self._newoperations = []
- def replace(self, what, with_):
- assert isinstance(what, AbstractValue)
- assert isinstance(with_, AbstractValue)
- assert not what.has_extra("optimize_replace")
- assert not what.is_constant()
- if what.has_extra("optimize_value"):
- v = what.get_extra("optimize_value")
- v.op = with_
- with_.set_extra("optimize_value", v)
- #if not we_are_translated():
- # if what.has_extra("optimize_value"):
- # what.get_extra("optimize_value").__class__ = exploder
- what.set_extra("optimize_replace", with_)
-
def make_constant(self, box, constbox):
self.getvalue(box).make_constant(constbox)
@@ -560,14 +528,16 @@
def propagate_all_forward(self, clear=True):
if clear:
self.clear_newoperations()
- for op in self.loop.operations:
- self.first_optimization.propagate_forward(op)
- for arg in self.loop.inputargs:
- arg.del_extra("optimize_value")
- arg.del_extra("optimize_replace")
- for op in self.loop.operations:
- op.del_extra("optimize_value")
- op.del_extra("optimize_replace")
+ i = 0
+ while i < len(self.loop.operations):
+ op = self.loop.operations[i]
+ for opt in self.optimizations:
+ op = opt.optimize_operation(op)
+ if op is None:
+ break
+ else:
+ self.emit_operation(op)
+ i += 1
self.loop.operations = self.get_newoperations()
self.loop.quasi_immutable_deps = self.quasi_immutable_deps
# accumulate counters
@@ -584,22 +554,10 @@
self.getvalue(op).is_bool_box = True
self._emit_operation(op)
- def get_value_replacement(self, box):
- try:
- value = self.getvalue(box)
- except KeyError:
- return None
- else:
- self.ensure_imported(value)
- forced_box = value.force_box(self)
- if forced_box is box:
- return None
- return forced_box
-
@specialize.argtype(0)
def _emit_operation(self, op):
assert op.getopnum() not in opgroups.CALL_PURE
- op = self.copy_op_if_modified_by_optimization(op)
+ assert not op._forwarded
if isinstance(op, Const):
return
self.metainterp_sd.profiler.count(jitprof.Counters.OPT_OPS)
@@ -613,6 +571,7 @@
self._newoperations.append(op)
def store_final_boxes_in_guard(self, op):
+ return # XXX we disable it for tests
assert op.getdescr() is None
descr = op.invent_descr(self.jitdriver_sd, self.metainterp_sd)
op.setdescr(descr)
diff --git a/pypy/jit/metainterp/optimizeopt/pure.py
b/pypy/jit/metainterp/optimizeopt/pure.py
--- a/pypy/jit/metainterp/optimizeopt/pure.py
+++ b/pypy/jit/metainterp/optimizeopt/pure.py
@@ -11,9 +11,6 @@
self.pure_operations = ArgsDict()
self.emitted_pure_operations = []
- def propagate_forward(self, op):
- dispatch_opt(self, op)
-
def optimize_default(self, op):
canfold = op.is_always_pure()
if op.is_ovf():
@@ -27,9 +24,10 @@
else:
nextop = None
+ newop = self.getforwarded(op)
if canfold:
for i in range(op.numargs()):
- if self.get_constant_box(op.getarg(i)) is None:
+ if self.get_constant_op(op.getarg(i)) is None:
break
else:
# all constant arguments: constant-fold away
@@ -40,21 +38,20 @@
return
# did we do the exact same operation already?
- key_op = op.get_key_op(self.optimizer)
- oldop = self.pure_operations.get(key_op)
+ oldop = self.pure_operations.get(newop)
if oldop is not None:
self.replace(op, oldop)
return
else:
- self.pure_operations.set(key_op, op)
+ self.pure_operations.set(newop, op)
self.remember_emitting_pure(op)
# otherwise, the operation remains
- self.emit_operation(op)
if op.returns_bool_result():
- self.getvalue(op).is_bool_box = True
+ newop.is_bool_box = True
if nextop:
self.emit_operation(nextop)
+ return newop
def _new_optimize_call_pure(opnum):
def optimize_CALL_PURE(self, op):
@@ -131,5 +128,5 @@
continue
sb.add_potential(op)
-dispatch_opt = make_dispatcher_method(OptPure, 'optimize_',
- default=OptPure.optimize_default)
+#dispatch_opt = make_dispatcher_method(OptPure, 'optimize_',
+# default=OptPure.optimize_default)
diff --git a/pypy/jit/metainterp/optimizeopt/rewrite.py
b/pypy/jit/metainterp/optimizeopt/rewrite.py
--- a/pypy/jit/metainterp/optimizeopt/rewrite.py
+++ b/pypy/jit/metainterp/optimizeopt/rewrite.py
@@ -524,6 +524,6 @@
optimize_SAME_AS_r = optimize_SAME_AS_i
optimize_SAME_AS_f = optimize_SAME_AS_i
-dispatch_opt = make_dispatcher_method(OptRewrite, 'optimize_',
- default=OptRewrite.emit_operation)
-optimize_guards = _findall(OptRewrite, 'optimize_', 'GUARD')
+#dispatch_opt = make_dispatcher_method(OptRewrite, 'optimize_',
+# default=OptRewrite.emit_operation)
+#optimize_guards = _findall(OptRewrite, 'optimize_', 'GUARD')
diff --git a/pypy/jit/metainterp/optimizeopt/simplify.py
b/pypy/jit/metainterp/optimizeopt/simplify.py
--- a/pypy/jit/metainterp/optimizeopt/simplify.py
+++ b/pypy/jit/metainterp/optimizeopt/simplify.py
@@ -64,6 +64,6 @@
descr=newdescr)
self.emit_operation(op)
-dispatch_opt = make_dispatcher_method(OptSimplify, 'optimize_',
- default=OptSimplify.emit_operation)
-OptSimplify.propagate_forward = dispatch_opt
+#dispatch_opt = make_dispatcher_method(OptSimplify, 'optimize_',
+# default=OptSimplify.emit_operation)
+#OptSimplify.propagate_forward = dispatch_opt
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -134,13 +134,13 @@
ops = """
[i]
i0 = int_sub(i, 1)
- guard_value(i0, 0) [i0]
+ guard_value(i0, 0)
jump(i)
"""
expected = """
[i]
i0 = int_sub(i, 1)
- guard_value(i0, 0) [i0]
+ guard_value(i0, 0)
jump(1)
"""
self.optimize_loop(ops, expected)
diff --git a/pypy/jit/metainterp/optimizeopt/unroll.py
b/pypy/jit/metainterp/optimizeopt/unroll.py
--- a/pypy/jit/metainterp/optimizeopt/unroll.py
+++ b/pypy/jit/metainterp/optimizeopt/unroll.py
@@ -28,6 +28,7 @@
imp.import_value(value)
def emit_operation(self, op):
+ xxx
if op.returns_bool_result():
self.bool_boxes[self.getvalue(op)] = None
if self.emitting_dissabled:
diff --git a/pypy/jit/metainterp/optimizeopt/util.py
b/pypy/jit/metainterp/optimizeopt/util.py
--- a/pypy/jit/metainterp/optimizeopt/util.py
+++ b/pypy/jit/metainterp/optimizeopt/util.py
@@ -172,8 +172,8 @@
text_right = text_right or 'expected'
print '%s| %s' % ('optimized'.center(width), text_right.center(width))
for op1, op2 in zip(oplist1, oplist2):
- txt1 = str(op1)
- txt2 = str(op2)
+ txt1 = repr(op1)
+ txt2 = repr(op2)
while txt1 or txt2:
print '%s| %s' % (txt1[:width].ljust(width), txt2[:width])
txt1 = txt1[width:]
diff --git a/pypy/jit/metainterp/optimizeopt/virtualize.py
b/pypy/jit/metainterp/optimizeopt/virtualize.py
--- a/pypy/jit/metainterp/optimizeopt/virtualize.py
+++ b/pypy/jit/metainterp/optimizeopt/virtualize.py
@@ -558,7 +558,7 @@
self.emit_operation(op)
-dispatch_opt = make_dispatcher_method(OptVirtualize, 'optimize_',
- default=OptVirtualize.emit_operation)
+#dispatch_opt = make_dispatcher_method(OptVirtualize, 'optimize_',
+# default=OptVirtualize.emit_operation)
-OptVirtualize.propagate_forward = dispatch_opt
+#OptVirtualize.propagate_forward = dispatch_opt
diff --git a/pypy/jit/metainterp/optimizeopt/vstring.py
b/pypy/jit/metainterp/optimizeopt/vstring.py
--- a/pypy/jit/metainterp/optimizeopt/vstring.py
+++ b/pypy/jit/metainterp/optimizeopt/vstring.py
@@ -728,8 +728,8 @@
def propagate_forward(self, op):
dispatch_opt(self, op)
-dispatch_opt = make_dispatcher_method(OptString, 'optimize_',
- default=OptString.emit_operation)
+#dispatch_opt = make_dispatcher_method(OptString, 'optimize_',
+# default=OptString.emit_operation)
def _findall_call_oopspec():
prefix = 'opt_call_stroruni_'
diff --git a/pypy/jit/metainterp/resoperation.py
b/pypy/jit/metainterp/resoperation.py
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -474,7 +474,7 @@
# XXX this is a hack kill me
import sys
co_fname = sys._getframe(1).f_code.co_filename
- if co_fname.endswith('resume.py') or
co_fname.endswith('optimizeopt/util.py') or 'backend/llgraph' in co_fname or
'backend/test' in co_fname:
+ if co_fname.endswith('resume.py') or
co_fname.endswith('optimizeopt/util.py') or 'backend/llgraph' in co_fname or
'backend/test' in co_fname or 'test/test_util' in co_fname:
return object.__hash__(self)
raise Exception("Should not hash resops, use get/set extra instead")
@@ -650,6 +650,13 @@
return False # for tests
return opboolresult[opnum]
+ # some debugging help
+
+ def __setattr__(self, attr, val):
+ if attr not in ['_hash', '_str']:
+ assert self._forwarded is None
+ object.__setattr__(self, attr, val)
+
# ===========
# type mixins
# ===========
diff --git a/pypy/jit/metainterp/resume.py b/pypy/jit/metainterp/resume.py
--- a/pypy/jit/metainterp/resume.py
+++ b/pypy/jit/metainterp/resume.py
@@ -198,9 +198,8 @@
length = len(boxes)
numb = lltype.malloc(NUMBERING, length)
for i in range(length):
- box = boxes[i]
- value = optimizer.getvalue(box)
- box = value.get_key_box()
+ op = boxes[i]
+ optimized_op = optimizer.get_optimized_op(op)
if isinstance(box, Const):
tagged = self.getconst(box)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit