[pypy-commit] pypy record-known-result: optimize int(str(i)) and same for rbigints. (Note that the other direction is

cfbolz pypy.commits at gmail.com
Sat Feb 8 05:19:02 EST 2020


Author: Carl Friedrich Bolz-Tereick <cfbolz at gmx.de>
Branch: record-known-result
Changeset: r98682:452d076e43fa
Date: 2020-02-06 23:55 +0100
http://bitbucket.org/pypy/pypy/changeset/452d076e43fa/

Log:	optimize int(str(i)) and same for rbigints. (Note that the other
	direction is not necessarily correct, because int(" 123") == 123)

	(this is actually more useful than it appears, as the decimal module
	converts its numbers back and forth between ints/longs and strs all
	the time)

diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py
--- a/rpython/jit/metainterp/pyjitpl.py
+++ b/rpython/jit/metainterp/pyjitpl.py
@@ -312,6 +312,7 @@
         # this is a weird op! we don't want to execute anything, so just record
         # an operation
         self.metainterp._record_helper_nonpure_varargs(rop.RECORD_KNOWN_RESULT, None, calldescr, allboxes)
+    opimpl_record_known_result_r_ir_v = opimpl_record_known_result_i_ir_v
 
     @arguments("box", "box")
     def opimpl_record_exact_value_r(self, box, const_box):
diff --git a/rpython/jit/metainterp/test/test_string.py b/rpython/jit/metainterp/test/test_string.py
--- a/rpython/jit/metainterp/test/test_string.py
+++ b/rpython/jit/metainterp/test/test_string.py
@@ -1075,3 +1075,33 @@
         assert res == f(1)
         self.check_simple_loop(int_sub=1, guard_false=1)
 
+    def test_int_to_str_and_back(self):
+        driver = JitDriver(greens = [], reds = ['n', 'res'])
+
+        def f(n):
+            res = 0
+            while n < 21:
+                driver.jit_merge_point(n=n, res=res)
+                n += 1
+                res += int(str(n))
+            return res
+
+        res = self.meta_interp(f, [1], backendopt=True)
+        assert res == f(1)
+        self.check_simple_loop(call_r=1, call_i=0)
+
+    def test_rbigint_to_str_and_back(self):
+        from rpython.rlib.rbigint import rbigint
+        driver = JitDriver(greens = [], reds = ['n', 'res'])
+
+        def f(n):
+            res = rbigint.fromint(0)
+            while n < 21:
+                driver.jit_merge_point(n=n, res=res)
+                n += 1
+                res = res.add(rbigint.fromstr(res.str(), 10))
+            return res.int_and_(0xffff).toint()
+
+        res = self.meta_interp(f, [1], backendopt=True)
+        assert res == f(1)
+        self.check_simple_loop(call_r=2) # one add, one str, the fromstr is gone
diff --git a/rpython/rlib/rbigint.py b/rpython/rlib/rbigint.py
--- a/rpython/rlib/rbigint.py
+++ b/rpython/rlib/rbigint.py
@@ -509,8 +509,13 @@
             return self.format(BASE10, suffix="L")
         return str(x) + "L"
 
+    def str(self):
+        res = self._str_impl()
+        jit.record_known_result(self, rbigint.fromstr, res, 10, False)
+        return res
+
     @jit.elidable
-    def str(self):
+    def _str_impl(self):
         try:
             x = self.toint()
         except OverflowError:
diff --git a/rpython/rtyper/rint.py b/rpython/rtyper/rint.py
--- a/rpython/rtyper/rint.py
+++ b/rpython/rtyper/rint.py
@@ -146,10 +146,12 @@
         hop.exception_cannot_occur()
         return vlist[0]
 
-    @jit.elidable
     def ll_str(self, i):
         from rpython.rtyper.lltypesystem.ll_str import ll_int2dec
-        return ll_int2dec(i)
+        from rpython.rtyper.lltypesystem.rstr import LLHelpers
+        res = ll_int2dec(i)
+        jit.record_known_result(i, LLHelpers.ll_int, res, 10)
+        return res
 
     def rtype_hex(self, hop):
         from rpython.rtyper.lltypesystem.ll_str import ll_int2hex


More information about the pypy-commit mailing list