Skip to content

Commit

Permalink
[mypyc] Expand int ops when operation contains at least one tagged int (
Browse files Browse the repository at this point in the history
#9187)

Follow-up of #9108 and #9127, generates the new inlined style ops when there is at 
least one tagged integer present (the previous two PRs actually specialized two ints 
and two short_ints cases). After this and the remaining merge, we will get rid of 
`CPyTagged_IsEq`, `CPyTagged_IsNe`, `CPyTagged_IsLt`, `CPyTagged_IsLe`, 
`CPyTagged_IsGt` and `CPyTagged_IsGe`.
  • Loading branch information
TH3CHARLie authored Jul 22, 2020
1 parent c2e20e9 commit 32a6377
Show file tree
Hide file tree
Showing 9 changed files with 719 additions and 258 deletions.
13 changes: 7 additions & 6 deletions 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, is_short_int_rprimitive
c_pyssize_t_rprimitive, is_short_int_rprimitive, is_tagged
)
from mypyc.ir.func_ir import FuncDecl, FuncSignature
from mypyc.ir.class_ir import ClassIR, all_concrete_classes
Expand Down Expand Up @@ -547,11 +547,8 @@ 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)
if is_tagged(lreg.type) and is_tagged(rreg.type) and expr_op in int_logical_op_mapping:
return self.compare_tagged(lreg, rreg, expr_op, line)

call_c_ops_candidates = c_binary_ops.get(expr_op, [])
target = self.matching_call_c(call_c_ops_candidates, [lreg, rreg], line)
Expand All @@ -573,6 +570,10 @@ def check_tagged_short_int(self, val: Value, line: int) -> Value:

def compare_tagged(self, lhs: Value, rhs: Value, op: str, line: int) -> Value:
"""Compare two tagged integers using given op"""
# generate fast binary logic ops on short ints
if is_short_int_rprimitive(lhs.type) and is_short_int_rprimitive(rhs.type):
return self.binary_int_op(bool_rprimitive, lhs, rhs,
int_logical_op_mapping[op][0], line)
op_type, c_func_desc, negate_result, swap_op = int_logical_op_mapping[op]
result = self.alloc_temp(bool_rprimitive)
short_int_block, int_block, out = BasicBlock(), BasicBlock(), BasicBlock()
Expand Down
3 changes: 0 additions & 3 deletions mypyc/primitives/int_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,6 @@ def int_compare_op(name: str, c_function_name: str) -> None:
int_binary_op('//=', 'CPyTagged_FloorDivide', error_kind=ERR_MAGIC)
int_binary_op('%=', 'CPyTagged_Remainder', error_kind=ERR_MAGIC)

int_compare_op('==', 'CPyTagged_IsEq')
int_compare_op('!=', 'CPyTagged_IsNe')
int_compare_op('<', 'CPyTagged_IsLt')
int_compare_op('<=', 'CPyTagged_IsLe')
int_compare_op('>', 'CPyTagged_IsGt')
int_compare_op('>=', 'CPyTagged_IsGe')
Expand Down
270 changes: 205 additions & 65 deletions mypyc/test-data/analysis.test
Original file line number Diff line number Diff line change
Expand Up @@ -74,24 +74,46 @@ def f(a):
a :: int
x :: int
r0 :: bool
r1 :: native_int
r2, r3, r4 :: bool
L0:
x = 2
r0 = CPyTagged_IsEq(x, 2)
if r0 goto L1 else goto L2 :: bool
r1 = x & 1
r2 = r1 == 0
if r2 goto L1 else goto L2 :: bool
L1:
return a
r3 = x == 2
r0 = r3
goto L3
L2:
return x
r4 = CPyTagged_IsEq_(x, 2)
r0 = r4
L3:
if r0 goto L4 else goto L5 :: bool
L4:
return a
L5:
return x
L6:
unreachable
(0, 0) {a} {a, i0}
(0, 1) {a, i0} {a, x}
(0, 2) {a, x} {a, i1, x}
(0, 3) {a, i1, x} {a, r0, x}
(0, 4) {a, r0, x} {a, x}
(1, 0) {a} {}
(2, 0) {x} {}
(3, 0) {} {}
(0, 3) {a, i1, x} {a, i1, i2, x}
(0, 4) {a, i1, i2, x} {a, i1, r1, x}
(0, 5) {a, i1, r1, x} {a, i1, i3, r1, x}
(0, 6) {a, i1, i3, r1, x} {a, i1, r2, x}
(0, 7) {a, i1, r2, x} {a, i1, x}
(1, 0) {a, i1, x} {a, r3, x}
(1, 1) {a, r3, x} {a, r0, x}
(1, 2) {a, r0, x} {a, r0, x}
(2, 0) {a, i1, x} {a, r4, x}
(2, 1) {a, r4, x} {a, r0, x}
(2, 2) {a, r0, x} {a, r0, x}
(3, 0) {a, r0, x} {a, x}
(4, 0) {a} {}
(5, 0) {x} {}
(6, 0) {} {}

[case testSpecial_Liveness]
def f() -> int:
Expand Down Expand Up @@ -149,34 +171,56 @@ def f(a: int) -> None:
def f(a):
a :: int
r0 :: bool
r1 :: native_int
r2, r3, r4 :: bool
y :: int
x :: int
r1 :: None
r5 :: None
L0:
r0 = CPyTagged_IsEq(a, 2)
if r0 goto L1 else goto L2 :: bool
r1 = a & 1
r2 = r1 == 0
if r2 goto L1 else goto L2 :: bool
L1:
y = 2
x = 4
r3 = a == 2
r0 = r3
goto L3
L2:
x = 4
r4 = CPyTagged_IsEq_(a, 2)
r0 = r4
L3:
r1 = None
return r1
if r0 goto L4 else goto L5 :: bool
L4:
y = 2
x = 4
goto L6
L5:
x = 4
L6:
r5 = None
return r5
(0, 0) {a} {a}
(0, 1) {a} {a}
(0, 2) {a} {a}
(0, 3) {a} {a}
(0, 4) {a} {a}
(0, 5) {a} {a}
(1, 0) {a} {a}
(1, 1) {a} {a, y}
(1, 2) {a, y} {a, y}
(1, 3) {a, y} {a, x, y}
(1, 4) {a, x, y} {a, x, y}
(1, 1) {a} {a, r0}
(1, 2) {a, r0} {a, r0}
(2, 0) {a} {a}
(2, 1) {a} {a, x}
(2, 2) {a, x} {a, x}
(3, 0) {a, x} {a, x}
(3, 1) {a, x} {a, x}
(2, 1) {a} {a, r0}
(2, 2) {a, r0} {a, r0}
(3, 0) {a, r0} {a, r0}
(4, 0) {a, r0} {a, r0}
(4, 1) {a, r0} {a, r0, y}
(4, 2) {a, r0, y} {a, r0, y}
(4, 3) {a, r0, y} {a, r0, x, y}
(4, 4) {a, r0, x, y} {a, r0, x, y}
(5, 0) {a, r0} {a, r0}
(5, 1) {a, r0} {a, r0, x}
(5, 2) {a, r0, x} {a, r0, x}
(6, 0) {a, r0, x} {a, r0, x}
(6, 1) {a, r0, x} {a, r0, x}

[case testTwoArgs_MustDefined]
def f(x: int, y: int) -> int:
Expand All @@ -197,31 +241,63 @@ def f(n: int) -> None:
def f(n):
n :: int
r0 :: bool
r1, m :: int
r2 :: None
r1 :: native_int
r2 :: bool
r3 :: native_int
r4, r5, r6, r7 :: bool
r8, m :: int
r9 :: None
L0:
L1:
r0 = CPyTagged_IsLt(n, 10)
if r0 goto L2 else goto L3 :: bool
r1 = n & 1
r2 = r1 == 0
r3 = 10 & 1
r4 = r3 == 0
r5 = r2 & r4
if r5 goto L2 else goto L3 :: bool
L2:
r1 = CPyTagged_Add(n, 2)
n = r1
r6 = n < 10 :: signed
r0 = r6
goto L4
L3:
r7 = CPyTagged_IsLt_(n, 10)
r0 = r7
L4:
if r0 goto L5 else goto L6 :: bool
L5:
r8 = CPyTagged_Add(n, 2)
n = r8
m = n
goto L1
L3:
r2 = None
return r2
L6:
r9 = None
return r9
(0, 0) {n} {n}
(1, 0) {n} {n}
(1, 1) {n} {n}
(1, 2) {n} {n}
(1, 3) {n} {n}
(1, 4) {n} {n}
(1, 5) {n} {n}
(1, 6) {n} {n}
(1, 7) {n} {n}
(1, 8) {n} {n}
(1, 9) {n} {n}
(1, 10) {n} {n}
(2, 0) {n} {n}
(2, 1) {n} {n}
(2, 2) {n} {n}
(2, 3) {n} {m, n}
(2, 4) {m, n} {m, n}
(2, 1) {n} {n, r0}
(2, 2) {n, r0} {n, r0}
(3, 0) {n} {n}
(3, 1) {n} {n}
(3, 1) {n} {n, r0}
(3, 2) {n, r0} {n, r0}
(4, 0) {n, r0} {n, r0}
(5, 0) {n, r0} {n, r0}
(5, 1) {n, r0} {n, r0}
(5, 2) {n, r0} {n, r0}
(5, 3) {n, r0} {m, n, r0}
(5, 4) {m, n, r0} {m, n, r0}
(6, 0) {n, r0} {n, r0}
(6, 1) {n, r0} {n, r0}

[case testMultiPass_Liveness]
def f(n: int) -> None:
Expand All @@ -238,48 +314,112 @@ def f(n):
x :: int
y :: int
r0 :: bool
r1 :: bool
r2 :: None
r1 :: native_int
r2 :: bool
r3 :: native_int
r4, r5, r6, r7 :: bool
r8 :: bool
r9 :: native_int
r10 :: bool
r11 :: native_int
r12, r13, r14, r15 :: bool
r16 :: None
L0:
x = 2
y = 2
L1:
r0 = CPyTagged_IsLt(n, 2)
if r0 goto L2 else goto L6 :: bool
r1 = n & 1
r2 = r1 == 0
r3 = 2 & 1
r4 = r3 == 0
r5 = r2 & r4
if r5 goto L2 else goto L3 :: bool
L2:
n = y
r6 = n < 2 :: signed
r0 = r6
goto L4
L3:
r1 = CPyTagged_IsLt(n, 4)
if r1 goto L4 else goto L5 :: bool
r7 = CPyTagged_IsLt_(n, 2)
r0 = r7
L4:
if r0 goto L5 else goto L12 :: bool
L5:
n = y
L6:
r9 = n & 1
r10 = r9 == 0
r11 = 4 & 1
r12 = r11 == 0
r13 = r10 & r12
if r13 goto L7 else goto L8 :: bool
L7:
r14 = n < 4 :: signed
r8 = r14
goto L9
L8:
r15 = CPyTagged_IsLt_(n, 4)
r8 = r15
L9:
if r8 goto L10 else goto L11 :: bool
L10:
n = 2
n = x
goto L3
L5:
goto L6
L11:
goto L1
L6:
r2 = None
return r2
L12:
r16 = None
return r16
(0, 0) {n} {i0, n}
(0, 1) {i0, n} {n, x}
(0, 2) {n, x} {i1, n, x}
(0, 3) {i1, n, x} {n, x, y}
(0, 4) {n, x, y} {n, x, y}
(1, 0) {n, x, y} {i2, n, x, y}
(1, 1) {i2, n, x, y} {r0, x, y}
(1, 2) {r0, x, y} {x, y}
(2, 0) {x, y} {n, x, y}
(2, 1) {n, x, y} {n, x, y}
(3, 0) {n, x, y} {i3, n, x, y}
(3, 1) {i3, n, x, y} {n, r1, x, y}
(3, 2) {n, r1, x, y} {n, x, y}
(4, 0) {x, y} {i4, x, y}
(4, 1) {i4, x, y} {x, y}
(4, 2) {x, y} {n, x, y}
(4, 3) {n, x, y} {n, x, y}
(5, 0) {n, x, y} {n, x, y}
(6, 0) {} {r2}
(6, 1) {r2} {}
(1, 1) {i2, n, x, y} {i2, i3, n, x, y}
(1, 2) {i2, i3, n, x, y} {i2, n, r1, x, y}
(1, 3) {i2, n, r1, x, y} {i2, i4, n, r1, x, y}
(1, 4) {i2, i4, n, r1, x, y} {i2, n, r2, x, y}
(1, 5) {i2, n, r2, x, y} {i2, i5, n, r2, x, y}
(1, 6) {i2, i5, n, r2, x, y} {i2, n, r2, r3, x, y}
(1, 7) {i2, n, r2, r3, x, y} {i2, i6, n, r2, r3, x, y}
(1, 8) {i2, i6, n, r2, r3, x, y} {i2, n, r2, r4, x, y}
(1, 9) {i2, n, r2, r4, x, y} {i2, n, r5, x, y}
(1, 10) {i2, n, r5, x, y} {i2, n, x, y}
(2, 0) {i2, n, x, y} {r6, x, y}
(2, 1) {r6, x, y} {r0, x, y}
(2, 2) {r0, x, y} {r0, x, y}
(3, 0) {i2, n, x, y} {r7, x, y}
(3, 1) {r7, x, y} {r0, x, y}
(3, 2) {r0, x, y} {r0, x, y}
(4, 0) {r0, x, y} {x, y}
(5, 0) {x, y} {n, x, y}
(5, 1) {n, x, y} {n, x, y}
(6, 0) {n, x, y} {i7, n, x, y}
(6, 1) {i7, n, x, y} {i7, i8, n, x, y}
(6, 2) {i7, i8, n, x, y} {i7, n, r9, x, y}
(6, 3) {i7, n, r9, x, y} {i7, i9, n, r9, x, y}
(6, 4) {i7, i9, n, r9, x, y} {i7, n, r10, x, y}
(6, 5) {i7, n, r10, x, y} {i10, i7, n, r10, x, y}
(6, 6) {i10, i7, n, r10, x, y} {i7, n, r10, r11, x, y}
(6, 7) {i7, n, r10, r11, x, y} {i11, i7, n, r10, r11, x, y}
(6, 8) {i11, i7, n, r10, r11, x, y} {i7, n, r10, r12, x, y}
(6, 9) {i7, n, r10, r12, x, y} {i7, n, r13, x, y}
(6, 10) {i7, n, r13, x, y} {i7, n, x, y}
(7, 0) {i7, n, x, y} {n, r14, x, y}
(7, 1) {n, r14, x, y} {n, r8, x, y}
(7, 2) {n, r8, x, y} {n, r8, x, y}
(8, 0) {i7, n, x, y} {n, r15, x, y}
(8, 1) {n, r15, x, y} {n, r8, x, y}
(8, 2) {n, r8, x, y} {n, r8, x, y}
(9, 0) {n, r8, x, y} {n, x, y}
(10, 0) {x, y} {i12, x, y}
(10, 1) {i12, x, y} {x, y}
(10, 2) {x, y} {n, x, y}
(10, 3) {n, x, y} {n, x, y}
(11, 0) {n, x, y} {n, x, y}
(12, 0) {} {r16}
(12, 1) {r16} {}

[case testCall_Liveness]
def f(x: int) -> int:
Expand Down
Loading

0 comments on commit 32a6377

Please sign in to comment.