[pypy-commit] pypy default: Remove the need for the RPython manual optimization of writing "x in (2,

arigo noreply at buildbot.pypy.org
Sun Aug 12 23:30:28 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r56715:6363bce133c9
Date: 2012-08-12 23:30 +0200
http://bitbucket.org/pypy/pypy/changeset/6363bce133c9/

Log:	Remove the need for the RPython manual optimization of writing "x in
	(2, 3, 4, 5)" because it is more efficient than "x in [2, 3, 4, 5]".

diff --git a/pypy/rpython/test/test_rlist.py b/pypy/rpython/test/test_rlist.py
--- a/pypy/rpython/test/test_rlist.py
+++ b/pypy/rpython/test/test_rlist.py
@@ -686,6 +686,31 @@
                 res = self.interpret(fn, [i, case])
                 assert res is fn(i, case)
 
+    def test_constant_list_contains(self):
+        # a 'contains' operation on list containing only annotation-time
+        # constants should be optimized into the equivalent code of
+        # 'in prebuilt-dictionary'.  Hard to test directly...
+        def g():
+            return 16
+        def f(i):
+            return i in [1, 2, 4, 8, g()]
+        res = self.interpret(f, [2])
+        assert res is True
+        res = self.interpret(f, [15])
+        assert res is False
+        res = self.interpret(f, [16])
+        assert res is True
+
+    def test_nonconstant_list_contains(self):
+        def f(i):
+            return i in [1, -i, 2, 4, 8]
+        res = self.interpret(f, [2])
+        assert res is True
+        res = self.interpret(f, [15])
+        assert res is False
+        res = self.interpret(f, [0])
+        assert res is True
+
 
     def test_not_a_char_list_after_all(self):
         def fn():
diff --git a/pypy/translator/transform.py b/pypy/translator/transform.py
--- a/pypy/translator/transform.py
+++ b/pypy/translator/transform.py
@@ -109,6 +109,32 @@
                                         op.result)
                 block.operations[i] = new_op
 
+# x in [2, 3]
+# -->
+# b = newlist(2, 3)
+# c = contains(b, x)
+# -->
+# c = contains(Constant((2, 3)), x)
+
+def transform_list_contains(self, block_subset):
+    """Transforms x in [2, 3]"""
+    for block in block_subset:
+        newlist_sources = {}    # maps b to [2, 3] in the above notation
+        for i in range(len(block.operations)):
+            op = block.operations[i]
+            if op.opname == 'newlist':
+                newlist_sources[op.result] = op.args
+            elif op.opname == 'contains' and op.args[0] in newlist_sources:
+                items = {}
+                for v in newlist_sources[op.args[0]]:
+                    s = self.binding(v)
+                    if not s.is_immutable_constant():
+                        break
+                    items[s.const] = None
+                else:
+                    # all arguments of the newlist are annotation constants
+                    op.args[0] = Constant(items)
+
 
 def transform_dead_op_vars(self, block_subset):
     # we redo the same simplification from simplify.py,
@@ -221,6 +247,7 @@
     transform_allocate,
     transform_extend_with_str_slice,
     transform_extend_with_char_count,
+    transform_list_contains,
     ]
 
 def transform_graph(ann, extra_passes=None, block_subset=None):


More information about the pypy-commit mailing list