[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