Skip to content

[mypyc] Generates inline compare statement on short ints and fix sieve performance regression #9127

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion mypyc/irbuild/ll_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from mypyc.ir.rtypes import (
RType, RUnion, RInstance, optional_value_type, int_rprimitive, float_rprimitive,
bool_rprimitive, list_rprimitive, str_rprimitive, is_none_rprimitive, object_rprimitive,
c_pyssize_t_rprimitive
c_pyssize_t_rprimitive, is_short_int_rprimitive
)
from mypyc.ir.func_ir import FuncDecl, FuncSignature
from mypyc.ir.class_ir import ClassIR, all_concrete_classes
Expand Down Expand Up @@ -547,6 +547,12 @@ def binary_op(self,
if value is not None:
return value

# generate fast binary logic ops on short ints
if (is_short_int_rprimitive(lreg.type) and is_short_int_rprimitive(rreg.type)
and expr_op in int_logical_op_mapping.keys()):
return self.binary_int_op(bool_rprimitive, lreg, rreg,
int_logical_op_mapping[expr_op][0], line)

call_c_ops_candidates = c_binary_ops.get(expr_op, [])
target = self.matching_call_c(call_c_ops_candidates, [lreg, rreg], line)
if target:
Expand Down
9 changes: 8 additions & 1 deletion mypyc/primitives/int_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,15 @@ def int_unary_op(name: str, c_function_name: str) -> CFunctionDescription:
c_function_name='CPyTagged_IsEq_',
error_kind=ERR_NEVER)

int_less_than_ = c_custom_op(
arg_types=[int_rprimitive, int_rprimitive],
return_type=bool_rprimitive,
c_function_name='CPyTagged_IsLt_',
error_kind=ERR_NEVER)

# provide mapping from textual op to short int's op variant and boxed int's description
# note these are not complete implementations
int_logical_op_mapping = {
'==': (BinaryIntOp.EQ, int_equal_)
'==': (BinaryIntOp.EQ, int_equal_),
'<': (BinaryIntOp.LT, int_less_than_)
} # type: Dict[str, Tuple[int, CFunctionDescription]]
92 changes: 70 additions & 22 deletions mypyc/test-data/analysis.test
Original file line number Diff line number Diff line change
Expand Up @@ -368,38 +368,86 @@ def f(a: int) -> None:
[out]
def f(a):
a :: int
r0, r1 :: bool
r0 :: bool
r1, r2, r3 :: native_int
r4, r5, r6, r7 :: bool
r8, r9, r10 :: native_int
r11, r12, r13 :: bool
y, x :: int
r2 :: None
r14 :: None
L0:
L1:
r0 = CPyTagged_IsLt(a, a)
if r0 goto L2 else goto L6 :: bool
r1 = 1
r2 = a & r1
r3 = 0
r4 = r2 == r3
if r4 goto L2 else goto L3 :: bool
L2:
r5 = a < a
r0 = r5
goto L4
L3:
r1 = CPyTagged_IsLt(a, a)
if r1 goto L4 else goto L5 :: bool
r6 = CPyTagged_IsLt_(a, a)
r0 = r6
L4:
y = a
goto L3
if r0 goto L5 else goto L12 :: bool
L5:
L6:
r8 = 1
r9 = a & r8
r10 = 0
r11 = r9 == r10
if r11 goto L7 else goto L8 :: bool
L7:
r12 = a < a
r7 = r12
goto L9
L8:
r13 = CPyTagged_IsLt_(a, a)
r7 = r13
L9:
if r7 goto L10 else goto L11 :: bool
L10:
y = a
goto L6
L11:
x = a
goto L1
L6:
r2 = None
return r2
L12:
r14 = None
return r14
(0, 0) {a} {a}
(1, 0) {a, x, y} {a, x, y}
(1, 1) {a, x, y} {a, x, y}
(2, 0) {a, x, y} {a, x, y}
(3, 0) {a, x, y} {a, x, y}
(3, 1) {a, x, y} {a, x, y}
(4, 0) {a, x, y} {a, x, y}
(4, 1) {a, x, y} {a, x, y}
(5, 0) {a, x, y} {a, x, y}
(5, 1) {a, x, y} {a, x, y}
(6, 0) {a, x, y} {a, x, y}
(6, 1) {a, x, y} {a, x, y}
(1, 0) {a, r0, r7, x, y} {a, r0, r7, x, y}
(1, 1) {a, r0, r7, x, y} {a, r0, r7, x, y}
(1, 2) {a, r0, r7, x, y} {a, r0, r7, x, y}
(1, 3) {a, r0, r7, x, y} {a, r0, r7, x, y}
(1, 4) {a, r0, r7, x, y} {a, r0, r7, x, y}
(2, 0) {a, r0, r7, x, y} {a, r0, r7, x, y}
(2, 1) {a, r0, r7, x, y} {a, r0, r7, x, y}
(2, 2) {a, r0, r7, x, y} {a, r0, r7, x, y}
(3, 0) {a, r0, r7, x, y} {a, r0, r7, x, y}
(3, 1) {a, r0, r7, x, y} {a, r0, r7, x, y}
(3, 2) {a, r0, r7, x, y} {a, r0, r7, x, y}
(4, 0) {a, r0, r7, x, y} {a, r0, r7, x, y}
(5, 0) {a, r0, r7, x, y} {a, r0, r7, x, y}
(6, 0) {a, r0, r7, x, y} {a, r0, r7, x, y}
(6, 1) {a, r0, r7, x, y} {a, r0, r7, x, y}
(6, 2) {a, r0, r7, x, y} {a, r0, r7, x, y}
(6, 3) {a, r0, r7, x, y} {a, r0, r7, x, y}
(6, 4) {a, r0, r7, x, y} {a, r0, r7, x, y}
(7, 0) {a, r0, r7, x, y} {a, r0, r7, x, y}
(7, 1) {a, r0, r7, x, y} {a, r0, r7, x, y}
(7, 2) {a, r0, r7, x, y} {a, r0, r7, x, y}
(8, 0) {a, r0, r7, x, y} {a, r0, r7, x, y}
(8, 1) {a, r0, r7, x, y} {a, r0, r7, x, y}
(8, 2) {a, r0, r7, x, y} {a, r0, r7, x, y}
(9, 0) {a, r0, r7, x, y} {a, r0, r7, x, y}
(10, 0) {a, r0, r7, x, y} {a, r0, r7, x, y}
(10, 1) {a, r0, r7, x, y} {a, r0, r7, x, y}
(11, 0) {a, r0, r7, x, y} {a, r0, r7, x, y}
(11, 1) {a, r0, r7, x, y} {a, r0, r7, x, y}
(12, 0) {a, r0, r7, x, y} {a, r0, r7, x, y}
(12, 1) {a, r0, r7, x, y} {a, r0, r7, x, y}

[case testTrivial_BorrowedArgument]
def f(a: int, b: int) -> int:
Expand Down
64 changes: 39 additions & 25 deletions mypyc/test-data/exceptions.test
Original file line number Diff line number Diff line change
Expand Up @@ -131,47 +131,61 @@ def sum(a, l):
r1 :: short_int
i :: int
r2 :: bool
r3 :: object
r4, r5 :: int
r6 :: short_int
r7, r8 :: int
r3, r4, r5 :: native_int
r6, r7, r8 :: bool
r9 :: object
r10, r11 :: int
r12 :: short_int
r13, r14 :: int
L0:
r0 = 0
sum = r0
r1 = 0
i = r1
L1:
r2 = CPyTagged_IsLt(i, l)
if r2 goto L2 else goto L7 :: bool
r3 = 1
r4 = i & r3
r5 = 0
r6 = r4 == r5
if r6 goto L2 else goto L3 :: bool
L2:
r3 = CPyList_GetItem(a, i)
if is_error(r3) goto L8 (error at sum:6) else goto L3
r7 = i < l
r2 = r7
goto L4
L3:
r4 = unbox(int, r3)
dec_ref r3
if is_error(r4) goto L8 (error at sum:6) else goto L4
r8 = CPyTagged_IsLt_(i, l)
r2 = r8
L4:
r5 = CPyTagged_Add(sum, r4)
dec_ref sum :: int
dec_ref r4 :: int
sum = r5
r6 = 1
r7 = CPyTagged_Add(i, r6)
dec_ref i :: int
i = r7
goto L1
if r2 goto L5 else goto L10 :: bool
L5:
return sum
r9 = CPyList_GetItem(a, i)
if is_error(r9) goto L11 (error at sum:6) else goto L6
L6:
r8 = <error> :: int
return r8
r10 = unbox(int, r9)
dec_ref r9
if is_error(r10) goto L11 (error at sum:6) else goto L7
L7:
r11 = CPyTagged_Add(sum, r10)
dec_ref sum :: int
dec_ref r10 :: int
sum = r11
r12 = 1
r13 = CPyTagged_Add(i, r12)
dec_ref i :: int
goto L5
i = r13
goto L1
L8:
return sum
L9:
r14 = <error> :: int
return r14
L10:
dec_ref i :: int
goto L8
L11:
dec_ref sum :: int
dec_ref i :: int
goto L6
goto L9

[case testTryExcept]
def g() -> None:
Expand Down
Loading