[pypy-svn] pypy default: don't repeat strlen ops.
alex_gaynor
commits-noreply at bitbucket.org
Thu Mar 24 05:40:58 CET 2011
Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch:
Changeset: r42886:3fe1b82365a3
Date: 2011-03-23 23:35 -0400
http://bitbucket.org/pypy/pypy/changeset/3fe1b82365a3/
Log: don't repeat strlen ops.
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
@@ -27,7 +27,7 @@
def optimize_loop_1(metainterp_sd, loop, enable_opts,
inline_short_preamble=True, retraced=False):
- """Optimize loop.operations to remove internal overheadish operations.
+ """Optimize loop.operations to remove internal overheadish operations.
"""
optimizations = []
unroll = 'unroll' in enable_opts
@@ -43,7 +43,7 @@
if 'rewrite' not in enable_opts or 'virtualize' not in enable_opts:
optimizations.append(OptSimplify())
-
+
if inline_short_preamble:
optimizations = [OptInlineShortPreamble(retraced)] + optimizations
diff --git a/pypy/jit/metainterp/optimizeopt/string.py b/pypy/jit/metainterp/optimizeopt/string.py
--- a/pypy/jit/metainterp/optimizeopt/string.py
+++ b/pypy/jit/metainterp/optimizeopt/string.py
@@ -47,7 +47,7 @@
class __extend__(optimizer.OptValue):
"""New methods added to the base class OptValue for this file."""
- def getstrlen(self, newoperations, mode):
+ def getstrlen(self, optimization, mode):
if mode is mode_string:
s = self.get_constant_string_spec(mode_string)
if s is not None:
@@ -56,12 +56,12 @@
s = self.get_constant_string_spec(mode_unicode)
if s is not None:
return ConstInt(len(s))
- if newoperations is None:
+ if optimization is None:
return None
self.ensure_nonnull()
box = self.force_box()
lengthbox = BoxInt()
- newoperations.append(ResOperation(mode.STRLEN, [box], lengthbox))
+ optimization.emit_operation(ResOperation(mode.STRLEN, [box], lengthbox))
return lengthbox
@specialize.arg(1)
@@ -72,13 +72,13 @@
else:
return None
- def string_copy_parts(self, newoperations, targetbox, offsetbox, mode):
+ def string_copy_parts(self, optimization, targetbox, offsetbox, mode):
# Copies the pointer-to-string 'self' into the target string
# given by 'targetbox', at the specified offset. Returns the offset
# at the end of the copy.
- lengthbox = self.getstrlen(newoperations, mode)
+ lengthbox = self.getstrlen(optimization, mode)
srcbox = self.force_box()
- return copy_str_content(newoperations, srcbox, targetbox,
+ return copy_str_content(optimization, srcbox, targetbox,
CONST_0, offsetbox, lengthbox, mode)
@@ -105,13 +105,12 @@
return
assert self.source_op is not None
self.box = box = self.source_op.result
- newoperations = self.optimizer.newoperations
- lengthbox = self.getstrlen(newoperations, self.mode)
+ lengthbox = self.getstrlen(self.optimizer, self.mode)
op = ResOperation(self.mode.NEWSTR, [lengthbox], box)
if not we_are_translated():
op.name = 'FORCE'
- newoperations.append(op)
- self.string_copy_parts(newoperations, box, CONST_0, self.mode)
+ self.optimizer.emit_operation(op)
+ self.string_copy_parts(self.optimizer, box, CONST_0, self.mode)
class VStringPlainValue(VAbstractStringValue):
@@ -145,14 +144,14 @@
return mode.emptystr.join([mode.chr(c.box.getint())
for c in self._chars])
- def string_copy_parts(self, newoperations, targetbox, offsetbox, mode):
+ def string_copy_parts(self, optimizer, targetbox, offsetbox, mode):
for i in range(len(self._chars)):
charbox = self._chars[i].force_box()
- newoperations.append(ResOperation(mode.STRSETITEM, [targetbox,
+ optimizer.emit_operation(ResOperation(mode.STRSETITEM, [targetbox,
offsetbox,
charbox],
None))
- offsetbox = _int_add(newoperations, offsetbox, CONST_1)
+ offsetbox = _int_add(optimizer, offsetbox, CONST_1)
return offsetbox
def get_args_for_fail(self, modifier):
@@ -186,16 +185,16 @@
self.left = left
self.right = right
- def getstrlen(self, newoperations, mode):
+ def getstrlen(self, optimizer, mode):
if self.lengthbox is None:
- len1box = self.left.getstrlen(newoperations, mode)
+ len1box = self.left.getstrlen(optimizer, mode)
if len1box is None:
return None
- len2box = self.right.getstrlen(newoperations, mode)
+ len2box = self.right.getstrlen(optimizer, mode)
if len2box is None:
return None
- self.lengthbox = _int_add(newoperations, len1box, len2box)
- # ^^^ may still be None, if newoperations is None
+ self.lengthbox = _int_add(optimizer, len1box, len2box)
+ # ^^^ may still be None, if optimizer is None
return self.lengthbox
@specialize.arg(1)
@@ -208,10 +207,10 @@
return None
return s1 + s2
- def string_copy_parts(self, newoperations, targetbox, offsetbox, mode):
- offsetbox = self.left.string_copy_parts(newoperations, targetbox,
+ def string_copy_parts(self, optimizer, targetbox, offsetbox, mode):
+ offsetbox = self.left.string_copy_parts(optimizer, targetbox,
offsetbox, mode)
- offsetbox = self.right.string_copy_parts(newoperations, targetbox,
+ offsetbox = self.right.string_copy_parts(optimizer, targetbox,
offsetbox, mode)
return offsetbox
@@ -266,9 +265,9 @@
return s1[start : start + length]
return None
- def string_copy_parts(self, newoperations, targetbox, offsetbox, mode):
- lengthbox = self.getstrlen(newoperations, mode)
- return copy_str_content(newoperations,
+ def string_copy_parts(self, optimizer, targetbox, offsetbox, mode):
+ lengthbox = self.getstrlen(optimizer, mode)
+ return copy_str_content(optimizer,
self.vstr.force_box(), targetbox,
self.vstart.force_box(), offsetbox,
lengthbox, mode)
@@ -299,7 +298,7 @@
return modifier.make_vstrslice(self.mode is mode_unicode)
-def copy_str_content(newoperations, srcbox, targetbox,
+def copy_str_content(optimizer, srcbox, targetbox,
srcoffsetbox, offsetbox, lengthbox, mode):
if isinstance(srcbox, ConstPtr) and isinstance(srcoffsetbox, Const):
M = 5
@@ -309,23 +308,23 @@
# up to M characters are done "inline", i.e. with STRGETITEM/STRSETITEM
# instead of just a COPYSTRCONTENT.
for i in range(lengthbox.value):
- charbox = _strgetitem(newoperations, srcbox, srcoffsetbox, mode)
- srcoffsetbox = _int_add(newoperations, srcoffsetbox, CONST_1)
- newoperations.append(ResOperation(mode.STRSETITEM, [targetbox,
+ charbox = _strgetitem(optimizer, srcbox, srcoffsetbox, mode)
+ srcoffsetbox = _int_add(optimizer, srcoffsetbox, CONST_1)
+ optimizer.emit_operation(ResOperation(mode.STRSETITEM, [targetbox,
offsetbox,
charbox],
None))
- offsetbox = _int_add(newoperations, offsetbox, CONST_1)
+ offsetbox = _int_add(optimizer, offsetbox, CONST_1)
else:
- nextoffsetbox = _int_add(newoperations, offsetbox, lengthbox)
+ nextoffsetbox = _int_add(optimizer, offsetbox, lengthbox)
op = ResOperation(mode.COPYSTRCONTENT, [srcbox, targetbox,
srcoffsetbox, offsetbox,
lengthbox], None)
- newoperations.append(op)
+ optimizer.emit_operation(op)
offsetbox = nextoffsetbox
return offsetbox
-def _int_add(newoperations, box1, box2):
+def _int_add(optimizer, box1, box2):
if isinstance(box1, ConstInt):
if box1.value == 0:
return box2
@@ -333,23 +332,23 @@
return ConstInt(box1.value + box2.value)
elif isinstance(box2, ConstInt) and box2.value == 0:
return box1
- if newoperations is None:
+ if optimizer is None:
return None
resbox = BoxInt()
- newoperations.append(ResOperation(rop.INT_ADD, [box1, box2], resbox))
+ optimizer.emit_operation(ResOperation(rop.INT_ADD, [box1, box2], resbox))
return resbox
-def _int_sub(newoperations, box1, box2):
+def _int_sub(optimizer, box1, box2):
if isinstance(box2, ConstInt):
if box2.value == 0:
return box1
if isinstance(box1, ConstInt):
return ConstInt(box1.value - box2.value)
resbox = BoxInt()
- newoperations.append(ResOperation(rop.INT_SUB, [box1, box2], resbox))
+ optimizer.emit_operation(ResOperation(rop.INT_SUB, [box1, box2], resbox))
return resbox
-def _strgetitem(newoperations, strbox, indexbox, mode):
+def _strgetitem(optimizer, strbox, indexbox, mode):
if isinstance(strbox, ConstPtr) and isinstance(indexbox, ConstInt):
if mode is mode_string:
s = strbox.getref(lltype.Ptr(rstr.STR))
@@ -358,7 +357,7 @@
s = strbox.getref(lltype.Ptr(rstr.UNICODE))
return ConstInt(ord(s.chars[indexbox.getint()]))
resbox = BoxInt()
- newoperations.append(ResOperation(mode.STRGETITEM, [strbox, indexbox],
+ optimizer.emit_operation(ResOperation(mode.STRGETITEM, [strbox, indexbox],
resbox))
return resbox
@@ -370,7 +369,7 @@
def reconstruct_for_next_iteration(self, optimizer, valuemap):
self.enabled = True
return self
-
+
def make_vstring_plain(self, box, source_op, mode):
vvalue = VStringPlainValue(self.optimizer, box, source_op, mode)
self.make_equal_to(box, vvalue)
@@ -431,7 +430,7 @@
value.ensure_nonnull()
#
if value.is_virtual() and isinstance(value, VStringSliceValue):
- fullindexbox = _int_add(self.optimizer.newoperations,
+ fullindexbox = _int_add(self.optimizer,
value.vstart.force_box(),
vindex.force_box())
value = value.vstr
@@ -441,7 +440,7 @@
if vindex.is_constant():
return value.getitem(vindex.box.getint())
#
- resbox = _strgetitem(self.optimizer.newoperations,
+ resbox = _strgetitem(self.optimizer,
value.force_box(),vindex.force_box(), mode)
return self.getvalue(resbox)
@@ -452,7 +451,7 @@
def _optimize_STRLEN(self, op, mode):
value = self.getvalue(op.getarg(0))
- lengthbox = value.getstrlen(self.optimizer.newoperations, mode)
+ lengthbox = value.getstrlen(self, mode)
self.make_equal_to(op.result, self.getvalue(lengthbox))
def optimize_CALL(self, op):
@@ -498,13 +497,11 @@
vright = self.getvalue(op.getarg(2))
vleft.ensure_nonnull()
vright.ensure_nonnull()
- newoperations = self.optimizer.newoperations
value = self.make_vstring_concat(op.result, op, mode)
value.setup(vleft, vright)
return True
def opt_call_stroruni_STR_SLICE(self, op, mode):
- newoperations = self.optimizer.newoperations
vstr = self.getvalue(op.getarg(1))
vstart = self.getvalue(op.getarg(2))
vstop = self.getvalue(op.getarg(3))
@@ -518,14 +515,14 @@
return True
#
vstr.ensure_nonnull()
- lengthbox = _int_sub(newoperations, vstop.force_box(),
+ lengthbox = _int_sub(self.optimizer, vstop.force_box(),
vstart.force_box())
#
if isinstance(vstr, VStringSliceValue):
# double slicing s[i:j][k:l]
vintermediate = vstr
vstr = vintermediate.vstr
- startbox = _int_add(newoperations,
+ startbox = _int_add(self.optimizer,
vintermediate.vstart.force_box(),
vstart.force_box())
vstart = self.getvalue(startbox)
@@ -574,7 +571,7 @@
l2box = v2.getstrlen(None, mode)
if isinstance(l2box, ConstInt):
if l2box.value == 0:
- lengthbox = v1.getstrlen(self.optimizer.newoperations, mode)
+ lengthbox = v1.getstrlen(self.optimizer, mode)
seo = self.optimizer.send_extra_operation
seo(ResOperation(rop.INT_EQ, [lengthbox, CONST_0], resultbox))
return True
@@ -609,7 +606,7 @@
op = ResOperation(rop.PTR_EQ, [v1.force_box(),
llhelper.CONST_NULL],
resultbox)
- self.optimizer.newoperations.append(op)
+ self.optimizer.emit_operation(op)
return True
#
return False
@@ -646,7 +643,7 @@
calldescr, func = cic.callinfo_for_oopspec(oopspecindex)
op = ResOperation(rop.CALL, [ConstInt(func)] + args, result,
descr=calldescr)
- self.optimizer.newoperations.append(op)
+ self.optimizer.emit_operation(op)
def propagate_forward(self, op):
if not self.enabled:
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
@@ -3693,13 +3693,16 @@
guard_true(i1) []
jump(p0)
"""
- # The dead strlen will be eliminated be the backend.
- expected = """
+ preamble = """
[p0]
i0 = strlen(p0)
jump(p0)
"""
- self.optimize_strunicode_loop(ops, expected, expected)
+ expected = """
+ [p0]
+ jump(p0)
+ """
+ self.optimize_strunicode_loop(ops, expected, preamble)
def test_addsub_const(self):
ops = """
@@ -5150,7 +5153,21 @@
"""
expected = """
[p0]
+ jump(p0)
+ """
+ self.optimize_loop(ops, expected)
+
+ def test_strlen_repeated(self):
+ ops = """
+ [p0]
i0 = strlen(p0)
+ i1 = strlen(p0)
+ i2 = int_eq(i0, i1)
+ guard_true(i2) []
+ jump(p0)
+ """
+ expected = """
+ [p0]
jump(p0)
"""
self.optimize_loop(ops, expected)
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
@@ -174,7 +174,7 @@
def __init__(self):
pass # make rpython happy
-
+
def propagate_forward(self, op):
raise NotImplementedError
@@ -183,7 +183,7 @@
def test_emittable(self, op):
return self.is_emittable(op)
-
+
def is_emittable(self, op):
return self.next_optimization.test_emittable(op)
@@ -239,7 +239,7 @@
def reconstruct_for_next_iteration(self, optimizer=None, valuemap=None):
#return self.__class__()
raise NotImplementedError
-
+
class Optimizer(Optimization):
@@ -275,20 +275,20 @@
else:
optimizations = []
self.first_optimization = self
-
- self.optimizations = optimizations
+
+ self.optimizations = optimizations
def force_at_end_of_preamble(self):
self.resumedata_memo = resume.ResumeDataLoopMemo(self.metainterp_sd)
for o in self.optimizations:
o.force_at_end_of_preamble()
-
+
def reconstruct_for_next_iteration(self, optimizer=None, valuemap=None):
assert optimizer is None
assert valuemap is None
valuemap = {}
new = Optimizer(self.metainterp_sd, self.loop)
- optimizations = [o.reconstruct_for_next_iteration(new, valuemap) for o in
+ optimizations = [o.reconstruct_for_next_iteration(new, valuemap) for o in
self.optimizations]
new.set_optimizations(optimizations)
@@ -305,7 +305,7 @@
for key, value in self.loop_invariant_results.items():
new.loop_invariant_results[key] = \
value.get_reconstructed(new, valuemap)
-
+
new.pure_operations = self.pure_operations
new.producer = self.producer
assert self.posponedop is None
@@ -429,7 +429,7 @@
def test_emittable(self, op):
return True
-
+
def emit_operation(self, op):
###self.heap_op_optimizer.emitting_operation(op)
self._emit_operation(op)
@@ -507,7 +507,7 @@
canfold = nextop.getopnum() == rop.GUARD_NO_OVERFLOW
else:
nextop = None
-
+
if canfold:
for i in range(op.numargs()):
if self.get_constant_box(op.getarg(i)) is None:
More information about the Pypy-commit
mailing list