Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r73265:8b404466566d Date: 2014-09-01 12:03 +0200 http://bitbucket.org/pypy/pypy/changeset/8b404466566d/
Log: Detect and special-case in the JIT the greater-than kind of comparisons between two single characters (or unichars). diff --git a/rpython/jit/codewriter/effectinfo.py b/rpython/jit/codewriter/effectinfo.py --- a/rpython/jit/codewriter/effectinfo.py +++ b/rpython/jit/codewriter/effectinfo.py @@ -36,6 +36,7 @@ OS_STREQ_NONNULL_CHAR = 29 # s1 == char (assert s1!=NULL) OS_STREQ_CHECKNULL_CHAR = 30 # s1!=NULL and s1==char OS_STREQ_LENGTHOK = 31 # s1 == s2 (assert len(s1)==len(s2)) + OS_STR_CMP = 32 # "stroruni.cmp" # OS_UNI_CONCAT = 42 # OS_UNI_SLICE = 43 # @@ -47,6 +48,7 @@ OS_UNIEQ_NONNULL_CHAR = 49 # (must be the same amount as for OS_UNIEQ_CHECKNULL_CHAR = 50 # STR, in the same order) OS_UNIEQ_LENGTHOK = 51 # + OS_UNI_CMP = 52 _OS_offset_uni = OS_UNI_CONCAT - OS_STR_CONCAT # OS_LIBFFI_CALL = 62 diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py --- a/rpython/jit/codewriter/jtransform.py +++ b/rpython/jit/codewriter/jtransform.py @@ -1767,6 +1767,7 @@ dict = {"stroruni.concat": EffectInfo.OS_STR_CONCAT, "stroruni.slice": EffectInfo.OS_STR_SLICE, "stroruni.equal": EffectInfo.OS_STR_EQUAL, + "stroruni.cmp": EffectInfo.OS_STR_CMP, "stroruni.copy_string_to_raw": EffectInfo.OS_STR_COPY_TO_RAW, } CHR = lltype.Char @@ -1774,6 +1775,7 @@ dict = {"stroruni.concat": EffectInfo.OS_UNI_CONCAT, "stroruni.slice": EffectInfo.OS_UNI_SLICE, "stroruni.equal": EffectInfo.OS_UNI_EQUAL, + "stroruni.cmp": EffectInfo.OS_UNI_CMP, "stroruni.copy_string_to_raw": EffectInfo.OS_UNI_COPY_TO_RAW } CHR = lltype.UniChar diff --git a/rpython/jit/metainterp/optimizeopt/vstring.py b/rpython/jit/metainterp/optimizeopt/vstring.py --- a/rpython/jit/metainterp/optimizeopt/vstring.py +++ b/rpython/jit/metainterp/optimizeopt/vstring.py @@ -733,6 +733,25 @@ return True return False + def opt_call_stroruni_STR_CMP(self, op, mode): + v1 = self.getvalue(op.getarg(1)) + v2 = self.getvalue(op.getarg(2)) + l1box = v1.getstrlen(None, mode, None) + l2box = v2.getstrlen(None, mode, None) + if (l1box is not None and l2box is not None and + isinstance(l1box, ConstInt) and + isinstance(l2box, ConstInt) and + l1box.value == l2box.value == 1): + # comparing two single chars + vchar1 = self.strgetitem(v1, optimizer.CVAL_ZERO, mode) + vchar2 = self.strgetitem(v2, optimizer.CVAL_ZERO, mode) + seo = self.optimizer.send_extra_operation + seo(ResOperation(rop.INT_SUB, [vchar1.force_box(self), + vchar2.force_box(self)], + op.result)) + return True + return False + def opt_call_SHRINK_ARRAY(self, op): v1 = self.getvalue(op.getarg(1)) v2 = self.getvalue(op.getarg(2)) 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 @@ -846,6 +846,27 @@ 'jump': 1, 'guard_true': 2, 'int_ge': 2, 'int_add': 2, 'int_sub': 2 }) + def test_compare_single_char_for_ordering(self): + jitdriver = JitDriver(reds=['result', 'n'], greens=[]) + _str = self._str + constant1 = _str("abcdefghij") + + def cmpstr(x, y): + return x > _str(y) + + def f(n): + cmpstr(_str("abc"), "def") # force x and y to be annot as strings + result = 0 + while n >= 0: + jitdriver.jit_merge_point(n=n, result=result) + c = constant1[n] + result += cmpstr(c, "c") + n -= 1 + return result + + res = self.meta_interp(f, [9]) + assert res == f(9) + self.check_resops(newstr=0, newunicode=0, call=0) class TestLLtype(StringTests, LLJitMixin): diff --git a/rpython/rtyper/lltypesystem/rstr.py b/rpython/rtyper/lltypesystem/rstr.py --- a/rpython/rtyper/lltypesystem/rstr.py +++ b/rpython/rtyper/lltypesystem/rstr.py @@ -531,6 +531,7 @@ return diff i += 1 return len1 - len2 + ll_strcmp.oopspec = 'stroruni.cmp(s1, s2)' @jit.elidable def ll_streq(s1, s2): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit