[pypy-commit] pypy result-in-resops: improve hashing, a bit tricky

fijal noreply at buildbot.pypy.org
Wed Sep 26 14:37:02 CEST 2012


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: result-in-resops
Changeset: r57606:d60b8107bede
Date: 2012-09-26 13:38 +0200
http://bitbucket.org/pypy/pypy/changeset/d60b8107bede/

Log:	improve hashing, a bit tricky

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
@@ -40,14 +40,13 @@
                 return
 
             # did we do the exact same operation already?
-            import pdb
-            pdb.set_trace()
-            oldop = self.pure_operations.get(op)
+            key_op = op.get_key_op(self.optimizer)
+            oldop = self.pure_operations.get(key_op)
             if oldop is not None:
                 self.replace(op, oldop)
                 return
             else:
-                self.pure_operations.set(op, op)
+                self.pure_operations.set(key_op, op)
                 self.remember_emitting_pure(op)
 
         # otherwise, the operation remains
@@ -68,7 +67,8 @@
                 self.last_emitted_operation = REMOVED
                 return
             else:
-                self.pure_operations.set(op, op)
+                new_op = op.copy_if_modified_by_optimization(self.optimizer)
+                self.pure_operations.set(new_op, op)
                 self.remember_emitting_pure(op)
 
             # replace CALL_PURE with just CALL
@@ -98,6 +98,9 @@
 
     @specialize.arg(2)
     def pure(self, oldop, opnum, arg0, arg1=None):
+        arg0 = arg0.get_key_op(self.optimizer)
+        if arg1 is not None:
+            arg1 = arg1.get_key_op(self.optimizer)
         result = example_for_opnum(opnum)
         if arg1 is None:
             op = create_resop_1(opnum, result, arg0)
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
@@ -93,6 +93,7 @@
         else:
             self.emit_operation(op)
             # Synthesize the reverse ops for optimize_default to reuse
+            self.pure(op.getarg(0), rop.INT_ADD, op.getarg(1), op)
             self.pure(op.getarg(0), rop.INT_ADD, op, op.getarg(1))
             self.pure(op.getarg(1), rop.INT_SUB, op.getarg(0), op)
 
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
@@ -3638,7 +3638,7 @@
     def test_framestackdepth_overhead(self):
         ops = """
         [p0, i22]
-        i1 = getfield_gc(p0, descr=valuedescr)
+        i1 = getfield_gc_i(p0, descr=valuedescr)
         i2 = int_gt(i1, i22)
         guard_false(i2) []
         i3 = int_add(i1, 1)
@@ -3655,7 +3655,7 @@
         """
         expected = """
         [p0, i22]
-        i1 = getfield_gc(p0, descr=valuedescr)
+        i1 = getfield_gc_i(p0, descr=valuedescr)
         i2 = int_gt(i1, i22)
         guard_false(i2) []
         i3 = int_add(i1, 1)
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
@@ -94,7 +94,7 @@
 
 # ____________________________________________________________
 
-BUCKET_SIZE = 1024
+BUCKET_SIZE = 8192
 
 def new_args_set(has_value=False):
     class ArgsSet(object):
@@ -124,6 +124,9 @@
         if has_value:
             def set(self, op, v):
                 hash = op._get_hash_() & self.bucket_size
+                if self.buckets[hash] is not None and not self.buckets[hash].eq(op):
+                    import pdb
+                    pdb.set_trace()
                 self.buckets[hash] = op # don't care about collisions
                 self.values[hash] = v
         else:
@@ -148,6 +151,9 @@
             def __repr__(self):
                 return 'ArgsSet(%s)' % ([item for item in self.buckets
                                          if item is not None],)
+
+        def __len__(self):
+            return len([item for item in self.buckets if item is not None])
     return ArgsSet
 ArgsSet = new_args_set()
 ArgsDict = new_args_set(True)
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
@@ -244,6 +244,9 @@
     def get_extra(self, key):
         raise KeyError
 
+    def get_key_op(self, optimizer):
+        return self
+
 def getkind(TYPE, supports_floats=True,
                   supports_longlong=True,
                   supports_singlefloats=True):
@@ -711,7 +714,7 @@
         hash = (self.getopnum() ^
                 intmask(self.get_result_hash() << 4) ^
                 self.get_descr_hash() ^
-                self.get_arg_hash())
+                intmask(self.get_arg_hash() << 1))
         if hash == 0:
             hash = -1
         self._hash = hash
@@ -1089,6 +1092,9 @@
     def copy_if_modified_by_optimization(self, opt):
         return self
 
+    def get_key_op(self, opt):
+        return self
+
     def get_arg_hash(self):
         return 0
 
@@ -1129,6 +1135,14 @@
             res.set_rd_snapshot(self.get_rd_snapshot())
         return res
 
+    def get_key_op(self, opt):
+        new_arg = opt.getvalue(self._arg0).get_key_box()
+        if new_arg is self._arg0:
+            return self
+        res = create_resop_1(self.opnum, self.getresult(), new_arg,
+                             self.getdescr())
+        return res        
+
     @specialize.arg(1)
     def copy_and_change(self, newopnum=-1, arg0=None, descr=None):
         if newopnum == -1:
@@ -1188,6 +1202,15 @@
             res.set_rd_snapshot(self.get_rd_snapshot())
         return res
 
+    @specialize.argtype(1)
+    def get_key_op(self, opt):
+        new_arg0 = opt.getvalue(self._arg0).get_key_box()
+        new_arg1 = opt.getvalue(self._arg1).get_key_box()
+        if new_arg0 is self._arg0 and new_arg1 is self._arg0:
+            return self
+        return create_resop_2(self.opnum, self.getresult(),
+                              new_arg0, new_arg1, self.getdescr())
+
     @specialize.arg(1)
     def copy_and_change(self, newopnum=-1, arg0=None, arg1=None, descr=None):
         if newopnum == -1:
@@ -1201,7 +1224,7 @@
         return res
 
     def get_arg_hash(self):
-        return (intmask(self._arg0._get_hash_() << 1) ^
+        return (intmask(self._arg0._get_hash_() << 3) ^
                 self._arg1._get_hash_())
 
     def args_eq(self, other):
@@ -1252,6 +1275,17 @@
                               new_arg2 or self._arg2,
                               self.getdescr())
 
+    @specialize.argtype(1)
+    def get_key_op(self, opt):
+        new_arg0 = opt.getvalue(self._arg0).get_key_box()
+        new_arg1 = opt.getvalue(self._arg1).get_key_box()
+        new_arg2 = opt.getvalue(self._arg2).get_key_box()
+        if (new_arg0 is self._arg0 and new_arg1 is self._arg1 and
+            new_arg2 is self._arg2):
+            return self
+        return create_resop_3(self.opnum, self.getresult(),
+                              new_arg0, new_arg1, new_arg2, self.getdescr())
+
     @specialize.arg(1)
     def copy_and_change(self, newopnum=-1, arg0=None, arg1=None, arg2=None,
                         descr=None):
@@ -1264,8 +1298,8 @@
         return r
 
     def get_arg_hash(self):
-        return (intmask(self._arg0._get_hash_() << 2) ^
-                intmask(self._arg1._get_hash_() << 1) ^
+        return (intmask(self._arg0._get_hash_() << 5) ^
+                intmask(self._arg1._get_hash_() << 2) ^
                 self._arg2._get_hash_())
 
     def args_eq(self, other):
@@ -1303,7 +1337,6 @@
                     newargs = newlist_hint(len(self._args))
                     for k in range(i):
                         newargs.append(self._args[k])
-                    self._args[:i]
                 newargs.append(new_arg)
             elif newargs is not None:
                 newargs.append(arg)
@@ -1312,6 +1345,24 @@
         return create_resop(self.opnum, self.getresult(),
                             newargs, self.getdescr())
 
+    @specialize.argtype(1)
+    def get_key_op(self, opt):
+        newargs = None
+        for i, arg in enumerate(self._args):
+            new_arg = opt.getvalue(arg).get_key_box()
+            if new_arg is not arg:
+                if newargs is None:
+                    newargs = newlist_hint(len(self._args))
+                    for k in range(i):
+                        newargs.append(self._args[k])
+                newargs.append(new_arg)
+            elif newargs is not None:
+                newargs.append(arg)
+        if newargs is None:
+            return self
+        return create_resop(self.opnum, self.getresult(),
+                            newargs, self.getdescr())        
+
     @specialize.arg(1)
     def copy_and_change(self, newopnum=-1, newargs=None, descr=None):
         if newopnum == -1:
@@ -1325,7 +1376,7 @@
     def get_arg_hash(self):
         hash = 0
         for i, arg in enumerate(self._args):
-            hash += intmask(arg._get_hash_() << (i & 15))
+            hash ^= intmask(arg._get_hash_() << (i & 15))
         return hash
 
     def args_eq(self, other):


More information about the pypy-commit mailing list