Skip to content

Commit b98c47e

Browse files
authored
[mypyc] Add BinaryIntOp for low-level integer operations (#9108)
Related: mypyc/mypyc#741 This PR introduces BinaryIntOp to represent all low-level integer binary operations. The block-like logic described in mypyc/mypyc#743 would be handled differently, BinaryIntOp would be the building block of it.
1 parent 259e0cf commit b98c47e

File tree

10 files changed

+117
-33
lines changed

10 files changed

+117
-33
lines changed

mypyc/analysis.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
BasicBlock, OpVisitor, Assign, LoadInt, LoadErrorValue, RegisterOp, Goto, Branch, Return, Call,
1010
Environment, Box, Unbox, Cast, Op, Unreachable, TupleGet, TupleSet, GetAttr, SetAttr,
1111
LoadStatic, InitStatic, PrimitiveOp, MethodCall, RaiseStandardError, CallC, LoadGlobal,
12-
Truncate
12+
Truncate, BinaryIntOp
1313
)
1414

1515

@@ -205,6 +205,9 @@ def visit_truncate(self, op: Truncate) -> GenAndKill:
205205
def visit_load_global(self, op: LoadGlobal) -> GenAndKill:
206206
return self.visit_register_op(op)
207207

208+
def visit_binary_int_op(self, op: BinaryIntOp) -> GenAndKill:
209+
return self.visit_register_op(op)
210+
208211

209212
class DefinedVisitor(BaseAnalysisVisitor):
210213
"""Visitor for finding defined registers.

mypyc/codegen/emitfunc.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
OpVisitor, Goto, Branch, Return, Assign, LoadInt, LoadErrorValue, GetAttr, SetAttr,
1212
LoadStatic, InitStatic, TupleGet, TupleSet, Call, IncRef, DecRef, Box, Cast, Unbox,
1313
BasicBlock, Value, MethodCall, PrimitiveOp, EmitterInterface, Unreachable, NAMESPACE_STATIC,
14-
NAMESPACE_TYPE, NAMESPACE_MODULE, RaiseStandardError, CallC, LoadGlobal, Truncate
14+
NAMESPACE_TYPE, NAMESPACE_MODULE, RaiseStandardError, CallC, LoadGlobal, Truncate,
15+
BinaryIntOp
1516
)
1617
from mypyc.ir.rtypes import RType, RTuple, is_int32_rprimitive, is_int64_rprimitive
1718
from mypyc.ir.func_ir import FuncIR, FuncDecl, FUNC_STATICMETHOD, FUNC_CLASSMETHOD
@@ -436,6 +437,12 @@ def visit_load_global(self, op: LoadGlobal) -> None:
436437
ann = ' /* %s */' % s
437438
self.emit_line('%s = %s;%s' % (dest, op.identifier, ann))
438439

440+
def visit_binary_int_op(self, op: BinaryIntOp) -> None:
441+
dest = self.reg(op)
442+
lhs = self.reg(op.lhs)
443+
rhs = self.reg(op.rhs)
444+
self.emit_line('%s = %s %s %s;' % (dest, lhs, op.op_str[op.op], rhs))
445+
439446
# Helpers
440447

441448
def label(self, label: BasicBlock) -> str:

mypyc/ir/ops.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,6 +1252,70 @@ def accept(self, visitor: 'OpVisitor[T]') -> T:
12521252
return visitor.visit_load_global(self)
12531253

12541254

1255+
class BinaryIntOp(RegisterOp):
1256+
"""Binary operations on integer types
1257+
1258+
These ops are low-level and will be eventually generated to simple x op y form.
1259+
The left and right values should be of low-level integer types that support those ops
1260+
"""
1261+
error_kind = ERR_NEVER
1262+
1263+
# arithmetic
1264+
ADD = 0 # type: Final
1265+
SUB = 1 # type: Final
1266+
MUL = 2 # type: Final
1267+
DIV = 3 # type: Final
1268+
MOD = 4 # type: Final
1269+
# logical
1270+
EQ = 100 # type: Final
1271+
NEQ = 101 # type: Final
1272+
LT = 102 # type: Final
1273+
GT = 103 # type: Final
1274+
LEQ = 104 # type: Final
1275+
GEQ = 105 # type: Final
1276+
# bitwise
1277+
AND = 200 # type: Final
1278+
OR = 201 # type: Final
1279+
XOR = 202 # type: Final
1280+
LEFT_SHIFT = 203 # type: Final
1281+
RIGHT_SHIFT = 204 # type: Final
1282+
1283+
op_str = {
1284+
ADD: '+',
1285+
SUB: '-',
1286+
MUL: '*',
1287+
DIV: '/',
1288+
MOD: '%',
1289+
EQ: '==',
1290+
NEQ: '!=',
1291+
LT: '<',
1292+
GT: '>',
1293+
LEQ: '<=',
1294+
GEQ: '>=',
1295+
AND: '&',
1296+
OR: '|',
1297+
XOR: '^',
1298+
LEFT_SHIFT: '<<',
1299+
RIGHT_SHIFT: '>>',
1300+
} # type: Final
1301+
1302+
def __init__(self, type: RType, lhs: Value, rhs: Value, op: int, line: int = -1) -> None:
1303+
super().__init__(line)
1304+
self.type = type
1305+
self.lhs = lhs
1306+
self.rhs = rhs
1307+
self.op = op
1308+
1309+
def sources(self) -> List[Value]:
1310+
return [self.lhs, self.rhs]
1311+
1312+
def to_str(self, env: Environment) -> str:
1313+
return env.format('%r = %r %s %r', self, self.lhs, self.op_str[self.op], self.rhs)
1314+
1315+
def accept(self, visitor: 'OpVisitor[T]') -> T:
1316+
return visitor.visit_binary_int_op(self)
1317+
1318+
12551319
@trait
12561320
class OpVisitor(Generic[T]):
12571321
"""Generic visitor over ops (uses the visitor design pattern)."""
@@ -1354,6 +1418,10 @@ def visit_truncate(self, op: Truncate) -> T:
13541418
def visit_load_global(self, op: LoadGlobal) -> T:
13551419
raise NotImplementedError
13561420

1421+
@abstractmethod
1422+
def visit_binary_int_op(self, op: BinaryIntOp) -> T:
1423+
raise NotImplementedError
1424+
13571425

13581426
# TODO: Should this live somewhere else?
13591427
LiteralsMap = Dict[Tuple[Type[object], Union[int, float, str, bytes, complex]], str]

mypyc/irbuild/builder.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,9 @@ def load_module(self, name: str) -> Value:
232232
def call_c(self, desc: CFunctionDescription, args: List[Value], line: int) -> Value:
233233
return self.builder.call_c(desc, args, line)
234234

235+
def binary_int_op(self, type: RType, lhs: Value, rhs: Value, op: int, line: int) -> Value:
236+
return self.builder.binary_int_op(type, lhs, rhs, op, line)
237+
235238
@property
236239
def environment(self) -> Environment:
237240
return self.builder.environment

mypyc/irbuild/for_helpers.py

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,16 @@
1313
)
1414
from mypyc.ir.ops import (
1515
Value, BasicBlock, LoadInt, Branch, Register, AssignmentTarget, TupleGet,
16-
AssignmentTargetTuple, TupleSet, OpDescription
16+
AssignmentTargetTuple, TupleSet, OpDescription, BinaryIntOp
1717
)
1818
from mypyc.ir.rtypes import (
1919
RType, is_short_int_rprimitive, is_list_rprimitive, is_sequence_rprimitive,
20-
RTuple, is_dict_rprimitive
20+
RTuple, is_dict_rprimitive, short_int_rprimitive
2121
)
2222
from mypyc.primitives.dict_ops import (
2323
dict_next_key_op, dict_next_value_op, dict_next_item_op, dict_check_size_op,
2424
dict_key_iter_op, dict_value_iter_op, dict_item_iter_op
2525
)
26-
from mypyc.primitives.int_ops import unsafe_short_add
2726
from mypyc.primitives.list_ops import new_list_op, list_append_op, list_get_item_unsafe_op
2827
from mypyc.primitives.generic_ops import iter_op, next_op
2928
from mypyc.primitives.exc_ops import no_err_occurred_op
@@ -465,10 +464,10 @@ def gen_step(self) -> None:
465464
builder = self.builder
466465
line = self.line
467466
step = 1 if not self.reverse else -1
468-
builder.assign(self.index_target, builder.primitive_op(
469-
unsafe_short_add,
470-
[builder.read(self.index_target, line),
471-
builder.add(LoadInt(step))], line), line)
467+
add = builder.binary_int_op(short_int_rprimitive,
468+
builder.read(self.index_target, line),
469+
builder.add(LoadInt(step)), BinaryIntOp.ADD, line)
470+
builder.assign(self.index_target, add, line)
472471

473472

474473
class ForDictionaryCommon(ForGenerator):
@@ -635,9 +634,9 @@ def gen_step(self) -> None:
635634
# short ints.
636635
if (is_short_int_rprimitive(self.start_reg.type)
637636
and is_short_int_rprimitive(self.end_reg.type)):
638-
new_val = builder.primitive_op(
639-
unsafe_short_add, [builder.read(self.index_reg, line),
640-
builder.add(LoadInt(self.step))], line)
637+
new_val = builder.binary_int_op(short_int_rprimitive,
638+
builder.read(self.index_reg, line),
639+
builder.add(LoadInt(self.step)), BinaryIntOp.ADD, line)
641640

642641
else:
643642
new_val = builder.binary_op(
@@ -665,9 +664,9 @@ def gen_step(self) -> None:
665664
# We can safely assume that the integer is short, since we are not going to wrap
666665
# around a 63-bit integer.
667666
# NOTE: This would be questionable if short ints could be 32 bits.
668-
new_val = builder.primitive_op(
669-
unsafe_short_add, [builder.read(self.index_reg, line),
670-
builder.add(LoadInt(1))], line)
667+
new_val = builder.binary_int_op(short_int_rprimitive,
668+
builder.read(self.index_reg, line),
669+
builder.add(LoadInt(1)), BinaryIntOp.ADD, line)
671670
builder.assign(self.index_reg, new_val, line)
672671
builder.assign(self.index_target, new_val, line)
673672

mypyc/irbuild/ll_builder.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
Assign, Branch, Goto, Call, Box, Unbox, Cast, GetAttr,
2222
LoadStatic, MethodCall, PrimitiveOp, OpDescription, RegisterOp, CallC, Truncate,
2323
RaiseStandardError, Unreachable, LoadErrorValue, LoadGlobal,
24-
NAMESPACE_TYPE, NAMESPACE_MODULE, NAMESPACE_STATIC,
24+
NAMESPACE_TYPE, NAMESPACE_MODULE, NAMESPACE_STATIC, BinaryIntOp
2525
)
2626
from mypyc.ir.rtypes import (
2727
RType, RUnion, RInstance, optional_value_type, int_rprimitive, float_rprimitive,
@@ -750,6 +750,9 @@ def matching_call_c(self,
750750
return target
751751
return None
752752

753+
def binary_int_op(self, type: RType, lhs: Value, rhs: Value, op: int, line: int) -> Value:
754+
return self.add(BinaryIntOp(type, lhs, rhs, op, line))
755+
753756
# Internal helpers
754757

755758
def decompose_union_helper(self,

mypyc/test-data/irbuild-basic.test

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1917,7 +1917,7 @@ L6:
19171917
r20 = r0.append(r19) :: list
19181918
L7:
19191919
r21 = 1
1920-
r22 = r9 + r21 :: short_int
1920+
r22 = r9 + r21
19211921
r9 = r22
19221922
goto L1
19231923
L8:
@@ -1982,7 +1982,7 @@ L6:
19821982
r21 = r0.__setitem__(r19, r20) :: dict
19831983
L7:
19841984
r22 = 1
1985-
r23 = r9 + r22 :: short_int
1985+
r23 = r9 + r22
19861986
r9 = r23
19871987
goto L1
19881988
L8:
@@ -2032,7 +2032,7 @@ L2:
20322032
z = r8
20332033
L3:
20342034
r9 = 1
2035-
r10 = r1 + r9 :: short_int
2035+
r10 = r1 + r9
20362036
r1 = r10
20372037
goto L1
20382038
L4:
@@ -2058,7 +2058,7 @@ L6:
20582058
r24 = r11.append(r23) :: list
20592059
L7:
20602060
r25 = 1
2061-
r26 = r13 + r25 :: short_int
2061+
r26 = r13 + r25
20622062
r13 = r26
20632063
goto L5
20642064
L8:

mypyc/test-data/irbuild-lists.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ L2:
195195
r8 = CPyList_SetItem(l, i, r7)
196196
L3:
197197
r9 = 1
198-
r10 = r2 + r9 :: short_int
198+
r10 = r2 + r9
199199
r2 = r10
200200
i = r10
201201
goto L1

mypyc/test-data/irbuild-statements.test

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ L2:
2828
x = r5
2929
L3:
3030
r6 = 1
31-
r7 = r3 + r6 :: short_int
31+
r7 = r3 + r6
3232
r3 = r7
3333
i = r7
3434
goto L1
@@ -58,7 +58,7 @@ L1:
5858
L2:
5959
L3:
6060
r4 = -1
61-
r5 = r2 + r4 :: short_int
61+
r5 = r2 + r4
6262
r2 = r5
6363
i = r5
6464
goto L1
@@ -113,7 +113,7 @@ L2:
113113
goto L4
114114
L3:
115115
r4 = 1
116-
r5 = r2 + r4 :: short_int
116+
r5 = r2 + r4
117117
r2 = r5
118118
n = r5
119119
goto L1
@@ -202,7 +202,7 @@ L1:
202202
L2:
203203
L3:
204204
r4 = 1
205-
r5 = r2 + r4 :: short_int
205+
r5 = r2 + r4
206206
r2 = r5
207207
n = r5
208208
goto L1
@@ -281,7 +281,7 @@ L2:
281281
y = r7
282282
L3:
283283
r8 = 1
284-
r9 = r2 + r8 :: short_int
284+
r9 = r2 + r8
285285
r2 = r9
286286
goto L1
287287
L4:
@@ -868,11 +868,11 @@ L2:
868868
r8 = CPyTagged_Add(i, x)
869869
L3:
870870
r9 = 1
871-
r10 = r1 + r9 :: short_int
871+
r10 = r1 + r9
872872
r1 = r10
873873
i = r10
874874
r11 = 1
875-
r12 = r3 + r11 :: short_int
875+
r12 = r3 + r11
876876
r3 = r12
877877
goto L1
878878
L4:
@@ -901,7 +901,7 @@ L2:
901901
n = r4
902902
L3:
903903
r5 = 1
904-
r6 = r1 + r5 :: short_int
904+
r6 = r1 + r5
905905
r1 = r6
906906
i = r6
907907
goto L1
@@ -961,7 +961,7 @@ L4:
961961
L5:
962962
L6:
963963
r11 = 1
964-
r12 = r1 + r11 :: short_int
964+
r12 = r1 + r11
965965
r1 = r12
966966
goto L1
967967
L7:
@@ -1012,10 +1012,10 @@ L4:
10121012
x = r13
10131013
L5:
10141014
r14 = 1
1015-
r15 = r2 + r14 :: short_int
1015+
r15 = r2 + r14
10161016
r2 = r15
10171017
r16 = 1
1018-
r17 = r5 + r16 :: short_int
1018+
r17 = r5 + r16
10191019
r5 = r17
10201020
z = r17
10211021
goto L1
@@ -1024,3 +1024,4 @@ L6:
10241024
L7:
10251025
r19 = None
10261026
return r19
1027+

mypyc/test-data/irbuild-tuple.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ L2:
155155
x = r5
156156
L3:
157157
r6 = 1
158-
r7 = r1 + r6 :: short_int
158+
r7 = r1 + r6
159159
r1 = r7
160160
goto L1
161161
L4:

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy