[pypy-commit] pypy optresult: a minor rewrite + minor progress here, not sure about the correct API yet
fijal
noreply at buildbot.pypy.org
Sat Nov 29 13:49:38 CET 2014
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: optresult
Changeset: r74758:4ce71001d704
Date: 2014-11-29 14:49 +0200
http://bitbucket.org/pypy/pypy/changeset/4ce71001d704/
Log: a minor rewrite + minor progress here, not sure about the correct
API yet
diff --git a/rpython/jit/metainterp/history.py b/rpython/jit/metainterp/history.py
--- a/rpython/jit/metainterp/history.py
+++ b/rpython/jit/metainterp/history.py
@@ -185,6 +185,9 @@
class Const(AbstractValue):
__slots__ = ()
+ is_source_op = True
+ source_op = None
+
@staticmethod
def _new(x):
"NOT_RPYTHON"
diff --git a/rpython/jit/metainterp/optimizeopt/intbounds.py b/rpython/jit/metainterp/optimizeopt/intbounds.py
--- a/rpython/jit/metainterp/optimizeopt/intbounds.py
+++ b/rpython/jit/metainterp/optimizeopt/intbounds.py
@@ -49,11 +49,10 @@
assert not op.is_ovf()
self.emit_operation(op)
- def propagate_bounds_backward(self, box):
+ def propagate_bounds_backward(self, box, v):
# FIXME: This takes care of the instruction where box is the reuslt
# but the bounds produced by all instructions where box is
# an argument might also be tighten
- v = self.getvalue(box)
b = v.intbound
if b.has_lower and b.has_upper and b.lower == b.upper:
v.make_constant(ConstInt(b.lower))
@@ -62,8 +61,9 @@
dispatch_bounds_ops(self, box)
def optimize_GUARD_TRUE(self, op):
+ v = self.getvalue(op.getarg(0))
self.emit_operation(op)
- self.propagate_bounds_backward(op.getarg(0))
+ self.propagate_bounds_backward(op.getarg(0), v)
optimize_GUARD_FALSE = optimize_GUARD_TRUE
optimize_GUARD_VALUE = optimize_GUARD_TRUE
@@ -237,25 +237,33 @@
v1 = self.getvalue(op.getarg(0))
v2 = self.getvalue(op.getarg(1))
resbound = v1.intbound.add_bound(v2.intbound)
+ r = self.getvalue(op)
if resbound.bounded():
# Transform into INT_ADD. The following guard will be killed
# by optimize_GUARD_NO_OVERFLOW; if we see instead an
# optimize_GUARD_OVERFLOW, then InvalidLoop.
- op = self.optimizer.replace_op_with(op, rop.INT_ADD)
- self.emit_operation(op) # emit the op
+ newop = op.copy_and_change(rop.INT_ADD)
+ r.box = newop
+ else:
+ newop = op
+ self.emit_operation(newop) # emit the op
r = self.getvalue(op)
r.intbound.intersect(resbound)
def optimize_INT_SUB_OVF(self, op):
v1 = self.getvalue(op.getarg(0))
v2 = self.getvalue(op.getarg(1))
+ r = self.getvalue(op)
if v1 is v2:
self.make_constant_int(op, 0)
return
resbound = v1.intbound.sub_bound(v2.intbound)
if resbound.bounded():
- op = self.optimizer.replace_op_with(op, rop.INT_SUB)
- self.emit_operation(op) # emit the op
+ newop = op.copy_and_change(rop.INT_SUB)
+ r.box = newop
+ else:
+ newop = op
+ self.emit_operation(newop) # emit the op
r = self.getvalue(op)
r.intbound.intersect(resbound)
@@ -410,17 +418,17 @@
v1 = self.getvalue(box1)
v2 = self.getvalue(box2)
if v1.intbound.make_lt(v2.intbound):
- self.propagate_bounds_backward(box1)
+ self.propagate_bounds_backward(box1, v1)
if v2.intbound.make_gt(v1.intbound):
- self.propagate_bounds_backward(box2)
+ self.propagate_bounds_backward(box2, v2)
def make_int_le(self, box1, box2):
v1 = self.getvalue(box1)
v2 = self.getvalue(box2)
if v1.intbound.make_le(v2.intbound):
- self.propagate_bounds_backward(box1)
+ self.propagate_bounds_backward(box1, v1)
if v2.intbound.make_ge(v1.intbound):
- self.propagate_bounds_backward(box2)
+ self.propagate_bounds_backward(box2, v2)
def make_int_gt(self, box1, box2):
self.make_int_lt(box2, box1)
@@ -467,9 +475,9 @@
v1 = self.getvalue(op.getarg(0))
v2 = self.getvalue(op.getarg(1))
if v1.intbound.intersect(v2.intbound):
- self.propagate_bounds_backward(op.getarg(0))
+ self.propagate_bounds_backward(op.getarg(0), v1)
if v2.intbound.intersect(v1.intbound):
- self.propagate_bounds_backward(op.getarg(1))
+ self.propagate_bounds_backward(op.getarg(1), v2)
def propagate_bounds_INT_NE(self, op):
r = self.getvalue(op)
@@ -489,7 +497,7 @@
v1 = self.getvalue(op.getarg(0))
if v1.intbound.known_ge(IntBound(0, 0)):
v1.intbound.make_gt(IntBound(0, 0))
- self.propagate_bounds_backward(op.getarg(0))
+ self.propagate_bounds_backward(op.getarg(0), v1)
def propagate_bounds_INT_IS_ZERO(self, op):
r = self.getvalue(op)
@@ -501,7 +509,7 @@
# an assert, this is a clever way of expressing the same thing.
v1.intbound.make_ge(IntBound(0, 0))
v1.intbound.make_lt(IntBound(1, 1))
- self.propagate_bounds_backward(op.getarg(0))
+ self.propagate_bounds_backward(op.getarg(0), v1)
def propagate_bounds_INT_ADD(self, op):
v1 = self.getvalue(op.getarg(0))
@@ -509,10 +517,10 @@
r = self.getvalue(op)
b = r.intbound.sub_bound(v2.intbound)
if v1.intbound.intersect(b):
- self.propagate_bounds_backward(op.getarg(0))
+ self.propagate_bounds_backward(op.getarg(0), v1)
b = r.intbound.sub_bound(v1.intbound)
if v2.intbound.intersect(b):
- self.propagate_bounds_backward(op.getarg(1))
+ self.propagate_bounds_backward(op.getarg(1), v2)
def propagate_bounds_INT_SUB(self, op):
v1 = self.getvalue(op.getarg(0))
@@ -520,10 +528,10 @@
r = self.getvalue(op)
b = r.intbound.add_bound(v2.intbound)
if v1.intbound.intersect(b):
- self.propagate_bounds_backward(op.getarg(0))
+ self.propagate_bounds_backward(op.getarg(0), v1)
b = r.intbound.sub_bound(v1.intbound).mul(-1)
if v2.intbound.intersect(b):
- self.propagate_bounds_backward(op.getarg(1))
+ self.propagate_bounds_backward(op.getarg(1), v2)
def propagate_bounds_INT_MUL(self, op):
v1 = self.getvalue(op.getarg(0))
diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py
--- a/rpython/jit/metainterp/optimizeopt/optimizer.py
+++ b/rpython/jit/metainterp/optimizeopt/optimizer.py
@@ -64,15 +64,6 @@
self.make_constant(box)
# invariant: box is a Const if and only if level == LEVEL_CONSTANT
- def copy_attributes_from(self, other):
- assert other.__class__ is OptValue
- self.level = other.level
- self.known_class = other.known_class
- self.intbound = other.intbound
- self.lenbound = other.lenbound
- self.box = other.box
- self.last_guard = other.last_guard
-
def make_len_gt(self, mode, descr, val):
if self.lenbound:
assert self.lenbound.mode == mode
@@ -454,6 +445,9 @@
@specialize.argtype(0)
def getvalue(self, box):
+ while box.source_op is not None:
+ box = box.source_op
+ assert box.is_source_op
box = self.getinterned(box)
try:
value = self.values[box]
@@ -487,19 +481,13 @@
def clear_newoperations(self):
self._newoperations = []
- def make_equal_to(self, box, newvalue):
- if box in self.values:
- v = self.getvalue(box)
- v.copy_attributes_from(newvalue)
- else:
- self.values[box] = newvalue
-
- def replace_op_with(self, oldop, newopnum, args=None):
- newop = oldop._copy_and_change(newopnum, args=args)
- v = self.getvalue(oldop)
- v.box = newop
- self.values[newop] = v
- return newop
+ def make_equal_to(self, box, value, replace=False):
+ assert isinstance(value, OptValue)
+ assert replace or box not in self.values
+ while box.source_op is not None:
+ box = box.source_op
+ assert box.is_source_op
+ self.values[box] = value
def make_constant(self, box, constbox):
try:
@@ -574,6 +562,10 @@
@specialize.argtype(0)
def _emit_operation(self, op):
assert not op.is_call_pure()
+ if op.getopnum() == rop.GUARD_VALUE:
+ val = self.getvalue(op.getarg(0))
+ else:
+ val = None
for i in range(op.numargs()):
arg = op.getarg(i)
try:
@@ -593,7 +585,7 @@
del self.replaces_guard[op]
return
else:
- op = self.store_final_boxes_in_guard(op, pendingfields)
+ op = self.store_final_boxes_in_guard(op, pendingfields, val)
elif op.can_raise():
self.exception_might_have_happened = True
self._newoperations.append(op)
@@ -609,7 +601,7 @@
else:
assert False
- def store_final_boxes_in_guard(self, op, pendingfields):
+ def store_final_boxes_in_guard(self, op, pendingfields, val):
assert pendingfields is not None
descr = op.getdescr()
assert isinstance(descr, compile.ResumeGuardDescr)
@@ -624,7 +616,7 @@
descr.store_final_boxes(op, newboxes, self.metainterp_sd)
#
if op.getopnum() == rop.GUARD_VALUE:
- if self.getvalue(op.getarg(0)) in self.bool_boxes:
+ if val in self.bool_boxes:
# Hack: turn guard_value(bool) into guard_true/guard_false.
# This is done after the operation is emitted to let
# store_final_boxes_in_guard set the guard_opnum field of the
diff --git a/rpython/jit/metainterp/optimizeopt/pure.py b/rpython/jit/metainterp/optimizeopt/pure.py
--- a/rpython/jit/metainterp/optimizeopt/pure.py
+++ b/rpython/jit/metainterp/optimizeopt/pure.py
@@ -42,7 +42,7 @@
op.getarglist(), op.getdescr())
oldop = self.pure_operations.get(args, None)
if oldop is not None and oldop.getdescr() is op.getdescr():
- self.optimizer.make_equal_to(op, self.getvalue(oldop))
+ self.optimizer.make_equal_to(op, self.getvalue(oldop), True)
return
else:
self.pure_operations[args] = op
@@ -84,6 +84,7 @@
args = op.getarglist()
opnum = OpHelpers.call_for_descr(op.getdescr())
newop = ResOperation(opnum, args, op.getdescr())
+ newop.source_op = op
self.getvalue(op).box = newop
self.emit_operation(newop)
optimize_CALL_PURE_R = optimize_CALL_PURE_I
diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py b/rpython/jit/metainterp/optimizeopt/rewrite.py
--- a/rpython/jit/metainterp/optimizeopt/rewrite.py
+++ b/rpython/jit/metainterp/optimizeopt/rewrite.py
@@ -220,8 +220,8 @@
self.make_equal_to(op, v2)
return
elif v1.box.getfloatstorage() == -1.0:
- newop = self.optimizer.replace_op_with(op, rop.FLOAT_NEG,
- args=[rhs])
+ newop = op.copy_and_change(rop.FLOAT_NEG, args=[rhs])
+ self.getvalue(op).box = newop
self.emit_operation(newop)
return
self.emit_operation(op)
@@ -233,6 +233,7 @@
v2 = self.getvalue(arg2)
# replace "x / const" by "x * (1/const)" if possible
+ newop = op
if v2.is_constant():
divisor = v2.box.getfloatstorage()
fraction = math.frexp(divisor)[0]
@@ -243,9 +244,9 @@
rfraction = math.frexp(reciprocal)[0]
if rfraction == 0.5 or rfraction == -0.5:
c = ConstFloat(longlong.getfloatstorage(reciprocal))
- op = self.optimizer.replace_op_with(op, rop.FLOAT_MUL,
- args=[arg1, c])
- self.emit_operation(op)
+ newop = op.copy_and_change(rop.FLOAT_MUL, args=[arg1, c])
+ self.getvalue(op).box = newop
+ self.emit_operation(newop)
def optimize_FLOAT_NEG(self, op):
v1 = op.getarg(0)
@@ -291,6 +292,7 @@
def optimize_GUARD_VALUE(self, op):
value = self.getvalue(op.getarg(0))
+ opv = self.getvalue(op)
if value.is_virtual():
arg = value.get_constant_class(self.optimizer.cpu)
if arg:
@@ -316,10 +318,8 @@
r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op)
raise InvalidLoop('A GUARD_VALUE (%s) was proven to always fail' % r)
arglist = [old_guard_op.getarg(0), op.getarg(1)]
- op = self.optimizer.replace_op_with(old_guard_op,
- rop.GUARD_VALUE,
- args=arglist)
- self.getvalue(old_guard_op).box = op
+ op = old_guard_op.copy_and_change(rop.GUARD_VALUE, args=arglist)
+ opv.box = op
self.optimizer.replaces_guard[op] = old_guard_op
# hack hack hack. Change the guard_opnum on
# new_guard_op.getdescr() so that when resuming,
@@ -351,6 +351,7 @@
value.make_constant_class(expectedclassbox, None)
def optimize_GUARD_CLASS(self, op):
+ opv = self.getvalue(op)
value = self.getvalue(op.getarg(0))
expectedclassbox = op.getarg(1)
assert isinstance(expectedclassbox, Const)
@@ -369,9 +370,8 @@
# it was a guard_nonnull, which we replace with a
# guard_nonnull_class.
args = [old_guard_op.getarg(0), op.getarg(1)]
- op = self.optimizer.replace_op_with(old_guard_op,
- rop.GUARD_NONNULL_CLASS,
- args)
+ op = old_guard_op.copy_and_change(rop.GUARD_NONNULL_CLASS, args)
+ opv.box = op
self.optimizer.replaces_guard[op] = old_guard_op
# hack hack hack. Change the guard_opnum on
# new_guard_op.getdescr() so that when resuming,
@@ -406,10 +406,10 @@
# there is no reason to have a separate operation for this
self.loop_invariant_producer[key] = op
opnum = OpHelpers.call_for_descr(op.getdescr())
- newop = self.optimizer.replace_op_with(op, opnum)
+ newop = op.copy_and_change(opnum)
+ resvalue = self.optimizer.getvalue(op)
+ resvalue.box = newop
self.emit_operation(newop)
- resvalue = self.getvalue(op)
- resvalue.box = newop
self.loop_invariant_results[key] = resvalue
optimize_CALL_LOOPINVARIANT_R = optimize_CALL_LOOPINVARIANT_I
optimize_CALL_LOOPINVARIANT_F = optimize_CALL_LOOPINVARIANT_I
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -27,7 +27,7 @@
snapshot0 = resume.Snapshot(None, [b0])
fdescr.rd_snapshot = resume.Snapshot(snapshot0, [b1])
#
- opt.store_final_boxes_in_guard(op, [])
+ opt.store_final_boxes_in_guard(op, [], None)
if op.getfailargs() == [b0, b1]:
assert list(fdescr.rd_numb.nums) == [tag(1, TAGBOX)]
assert list(fdescr.rd_numb.prev.nums) == [tag(0, TAGBOX)]
diff --git a/rpython/jit/metainterp/resoperation.py b/rpython/jit/metainterp/resoperation.py
--- a/rpython/jit/metainterp/resoperation.py
+++ b/rpython/jit/metainterp/resoperation.py
@@ -39,6 +39,9 @@
boolreflex = -1
boolinverse = -1
+ is_source_op = False
+ source_op = None
+
_attrs_ = ()
def getopnum(self):
@@ -87,7 +90,7 @@
# common methods
# --------------
- def _copy_and_change(self, opnum, args=None, descr=None):
+ def copy_and_change(self, opnum, args=None, descr=None):
"shallow copy: the returned operation is meant to be used in place of self"
if args is None:
args = self.getarglist()
@@ -96,6 +99,7 @@
newop = ResOperation(opnum, args, descr)
if self.type != 'v':
newop.copy_value_from(self)
+ newop.source_op = self
return newop
@specialize.argtype(1)
@@ -279,8 +283,8 @@
def setfailargs(self, fail_args):
self._fail_args = fail_args
- def _copy_and_change(self, opnum, args=None, descr=None):
- newop = AbstractResOp._copy_and_change(self, opnum, args, descr)
+ def copy_and_change(self, opnum, args=None, descr=None):
+ newop = AbstractResOp.copy_and_change(self, opnum, args, descr)
newop.setfailargs(self.getfailargs())
return newop
@@ -359,7 +363,10 @@
def nonnull(self):
return bool(self._resref)
-class AbstractInputArg(AbstractValue):
+class AbstractInputArg(AbstractValue):
+ is_source_op = True
+ source_op = None
+
def repr(self, memo):
try:
return memo[self]
diff --git a/rpython/jit/tool/oparser.py b/rpython/jit/tool/oparser.py
--- a/rpython/jit/tool/oparser.py
+++ b/rpython/jit/tool/oparser.py
@@ -17,6 +17,7 @@
OPNUM = -123
type = 'i'
+ is_source_op = True
def getopnum(self):
return self.OPNUM
@@ -32,6 +33,7 @@
class FORCE_SPILL(UnaryOp, PlainResOp):
OPNUM = -124
+ is_source_op = True
def getopnum(self):
return self.OPNUM
@@ -277,7 +279,9 @@
assert descr is None
return op
else:
- return ResOperation(opnum, args, descr)
+ res = ResOperation(opnum, args, descr)
+ res.is_source_op = True
+ return res
def parse_result_op(self, line):
res, op = line.split("=", 1)
More information about the pypy-commit
mailing list