Skip to content

Commit 358522e

Browse files
authored
[mypyc] Generates inline compare statement on short ints and fix sieve performance regression (#9127)
Related: mypyc/mypyc#750 Generate almost identical code as before be01236 Before: ```c CPyL1: ; cpy_r_r4 = (Py_ssize_t)cpy_r_r3 < (Py_ssize_t)cpy_r_r2; if (cpy_r_r4) { goto CPyL2; } else goto CPyL5; ``` Now with this PR: ```c CPyL1: ; cpy_r_r4 = cpy_r_r3 < cpy_r_r2; if (cpy_r_r4) { goto CPyL2; } else goto CPyL5; ```
1 parent 08cd1d6 commit 358522e

12 files changed

+332
-144
lines changed

mypyc/irbuild/ll_builder.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
from mypyc.ir.rtypes import (
2727
RType, RUnion, RInstance, optional_value_type, int_rprimitive, float_rprimitive,
2828
bool_rprimitive, list_rprimitive, str_rprimitive, is_none_rprimitive, object_rprimitive,
29-
c_pyssize_t_rprimitive
29+
c_pyssize_t_rprimitive, is_short_int_rprimitive
3030
)
3131
from mypyc.ir.func_ir import FuncDecl, FuncSignature
3232
from mypyc.ir.class_ir import ClassIR, all_concrete_classes
@@ -547,6 +547,12 @@ def binary_op(self,
547547
if value is not None:
548548
return value
549549

550+
# generate fast binary logic ops on short ints
551+
if (is_short_int_rprimitive(lreg.type) and is_short_int_rprimitive(rreg.type)
552+
and expr_op in int_logical_op_mapping.keys()):
553+
return self.binary_int_op(bool_rprimitive, lreg, rreg,
554+
int_logical_op_mapping[expr_op][0], line)
555+
550556
call_c_ops_candidates = c_binary_ops.get(expr_op, [])
551557
target = self.matching_call_c(call_c_ops_candidates, [lreg, rreg], line)
552558
if target:

mypyc/primitives/int_ops.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,15 @@ def int_unary_op(name: str, c_function_name: str) -> CFunctionDescription:
150150
c_function_name='CPyTagged_IsEq_',
151151
error_kind=ERR_NEVER)
152152

153+
int_less_than_ = c_custom_op(
154+
arg_types=[int_rprimitive, int_rprimitive],
155+
return_type=bool_rprimitive,
156+
c_function_name='CPyTagged_IsLt_',
157+
error_kind=ERR_NEVER)
158+
153159
# provide mapping from textual op to short int's op variant and boxed int's description
154160
# note these are not complete implementations
155161
int_logical_op_mapping = {
156-
'==': (BinaryIntOp.EQ, int_equal_)
162+
'==': (BinaryIntOp.EQ, int_equal_),
163+
'<': (BinaryIntOp.LT, int_less_than_)
157164
} # type: Dict[str, Tuple[int, CFunctionDescription]]

mypyc/test-data/analysis.test

+70-22
Original file line numberDiff line numberDiff line change
@@ -368,38 +368,86 @@ def f(a: int) -> None:
368368
[out]
369369
def f(a):
370370
a :: int
371-
r0, r1 :: bool
371+
r0 :: bool
372+
r1, r2, r3 :: native_int
373+
r4, r5, r6, r7 :: bool
374+
r8, r9, r10 :: native_int
375+
r11, r12, r13 :: bool
372376
y, x :: int
373-
r2 :: None
377+
r14 :: None
374378
L0:
375379
L1:
376-
r0 = CPyTagged_IsLt(a, a)
377-
if r0 goto L2 else goto L6 :: bool
380+
r1 = 1
381+
r2 = a & r1
382+
r3 = 0
383+
r4 = r2 == r3
384+
if r4 goto L2 else goto L3 :: bool
378385
L2:
386+
r5 = a < a
387+
r0 = r5
388+
goto L4
379389
L3:
380-
r1 = CPyTagged_IsLt(a, a)
381-
if r1 goto L4 else goto L5 :: bool
390+
r6 = CPyTagged_IsLt_(a, a)
391+
r0 = r6
382392
L4:
383-
y = a
384-
goto L3
393+
if r0 goto L5 else goto L12 :: bool
385394
L5:
395+
L6:
396+
r8 = 1
397+
r9 = a & r8
398+
r10 = 0
399+
r11 = r9 == r10
400+
if r11 goto L7 else goto L8 :: bool
401+
L7:
402+
r12 = a < a
403+
r7 = r12
404+
goto L9
405+
L8:
406+
r13 = CPyTagged_IsLt_(a, a)
407+
r7 = r13
408+
L9:
409+
if r7 goto L10 else goto L11 :: bool
410+
L10:
411+
y = a
412+
goto L6
413+
L11:
386414
x = a
387415
goto L1
388-
L6:
389-
r2 = None
390-
return r2
416+
L12:
417+
r14 = None
418+
return r14
391419
(0, 0) {a} {a}
392-
(1, 0) {a, x, y} {a, x, y}
393-
(1, 1) {a, x, y} {a, x, y}
394-
(2, 0) {a, x, y} {a, x, y}
395-
(3, 0) {a, x, y} {a, x, y}
396-
(3, 1) {a, x, y} {a, x, y}
397-
(4, 0) {a, x, y} {a, x, y}
398-
(4, 1) {a, x, y} {a, x, y}
399-
(5, 0) {a, x, y} {a, x, y}
400-
(5, 1) {a, x, y} {a, x, y}
401-
(6, 0) {a, x, y} {a, x, y}
402-
(6, 1) {a, x, y} {a, x, y}
420+
(1, 0) {a, r0, r7, x, y} {a, r0, r7, x, y}
421+
(1, 1) {a, r0, r7, x, y} {a, r0, r7, x, y}
422+
(1, 2) {a, r0, r7, x, y} {a, r0, r7, x, y}
423+
(1, 3) {a, r0, r7, x, y} {a, r0, r7, x, y}
424+
(1, 4) {a, r0, r7, x, y} {a, r0, r7, x, y}
425+
(2, 0) {a, r0, r7, x, y} {a, r0, r7, x, y}
426+
(2, 1) {a, r0, r7, x, y} {a, r0, r7, x, y}
427+
(2, 2) {a, r0, r7, x, y} {a, r0, r7, x, y}
428+
(3, 0) {a, r0, r7, x, y} {a, r0, r7, x, y}
429+
(3, 1) {a, r0, r7, x, y} {a, r0, r7, x, y}
430+
(3, 2) {a, r0, r7, x, y} {a, r0, r7, x, y}
431+
(4, 0) {a, r0, r7, x, y} {a, r0, r7, x, y}
432+
(5, 0) {a, r0, r7, x, y} {a, r0, r7, x, y}
433+
(6, 0) {a, r0, r7, x, y} {a, r0, r7, x, y}
434+
(6, 1) {a, r0, r7, x, y} {a, r0, r7, x, y}
435+
(6, 2) {a, r0, r7, x, y} {a, r0, r7, x, y}
436+
(6, 3) {a, r0, r7, x, y} {a, r0, r7, x, y}
437+
(6, 4) {a, r0, r7, x, y} {a, r0, r7, x, y}
438+
(7, 0) {a, r0, r7, x, y} {a, r0, r7, x, y}
439+
(7, 1) {a, r0, r7, x, y} {a, r0, r7, x, y}
440+
(7, 2) {a, r0, r7, x, y} {a, r0, r7, x, y}
441+
(8, 0) {a, r0, r7, x, y} {a, r0, r7, x, y}
442+
(8, 1) {a, r0, r7, x, y} {a, r0, r7, x, y}
443+
(8, 2) {a, r0, r7, x, y} {a, r0, r7, x, y}
444+
(9, 0) {a, r0, r7, x, y} {a, r0, r7, x, y}
445+
(10, 0) {a, r0, r7, x, y} {a, r0, r7, x, y}
446+
(10, 1) {a, r0, r7, x, y} {a, r0, r7, x, y}
447+
(11, 0) {a, r0, r7, x, y} {a, r0, r7, x, y}
448+
(11, 1) {a, r0, r7, x, y} {a, r0, r7, x, y}
449+
(12, 0) {a, r0, r7, x, y} {a, r0, r7, x, y}
450+
(12, 1) {a, r0, r7, x, y} {a, r0, r7, x, y}
403451

404452
[case testTrivial_BorrowedArgument]
405453
def f(a: int, b: int) -> int:

mypyc/test-data/exceptions.test

+39-25
Original file line numberDiff line numberDiff line change
@@ -131,47 +131,61 @@ def sum(a, l):
131131
r1 :: short_int
132132
i :: int
133133
r2 :: bool
134-
r3 :: object
135-
r4, r5 :: int
136-
r6 :: short_int
137-
r7, r8 :: int
134+
r3, r4, r5 :: native_int
135+
r6, r7, r8 :: bool
136+
r9 :: object
137+
r10, r11 :: int
138+
r12 :: short_int
139+
r13, r14 :: int
138140
L0:
139141
r0 = 0
140142
sum = r0
141143
r1 = 0
142144
i = r1
143145
L1:
144-
r2 = CPyTagged_IsLt(i, l)
145-
if r2 goto L2 else goto L7 :: bool
146+
r3 = 1
147+
r4 = i & r3
148+
r5 = 0
149+
r6 = r4 == r5
150+
if r6 goto L2 else goto L3 :: bool
146151
L2:
147-
r3 = CPyList_GetItem(a, i)
148-
if is_error(r3) goto L8 (error at sum:6) else goto L3
152+
r7 = i < l
153+
r2 = r7
154+
goto L4
149155
L3:
150-
r4 = unbox(int, r3)
151-
dec_ref r3
152-
if is_error(r4) goto L8 (error at sum:6) else goto L4
156+
r8 = CPyTagged_IsLt_(i, l)
157+
r2 = r8
153158
L4:
154-
r5 = CPyTagged_Add(sum, r4)
155-
dec_ref sum :: int
156-
dec_ref r4 :: int
157-
sum = r5
158-
r6 = 1
159-
r7 = CPyTagged_Add(i, r6)
160-
dec_ref i :: int
161-
i = r7
162-
goto L1
159+
if r2 goto L5 else goto L10 :: bool
163160
L5:
164-
return sum
161+
r9 = CPyList_GetItem(a, i)
162+
if is_error(r9) goto L11 (error at sum:6) else goto L6
165163
L6:
166-
r8 = <error> :: int
167-
return r8
164+
r10 = unbox(int, r9)
165+
dec_ref r9
166+
if is_error(r10) goto L11 (error at sum:6) else goto L7
168167
L7:
168+
r11 = CPyTagged_Add(sum, r10)
169+
dec_ref sum :: int
170+
dec_ref r10 :: int
171+
sum = r11
172+
r12 = 1
173+
r13 = CPyTagged_Add(i, r12)
169174
dec_ref i :: int
170-
goto L5
175+
i = r13
176+
goto L1
171177
L8:
178+
return sum
179+
L9:
180+
r14 = <error> :: int
181+
return r14
182+
L10:
183+
dec_ref i :: int
184+
goto L8
185+
L11:
172186
dec_ref sum :: int
173187
dec_ref i :: int
174-
goto L6
188+
goto L9
175189

176190
[case testTryExcept]
177191
def g() -> None:

0 commit comments

Comments
 (0)