Skip to content

Commit 36a4d78

Browse files
committed
[mypyc] Optimize int()/float() on native classes
int() and float() calls on native classes can simply call the associated dunder if the RInstance defines it, no need to load the type and call it. bool() calls were already optimized merely a few days ago, but there wasn't an IRbuild test verifying this so I added one.
1 parent 28e5436 commit 36a4d78

File tree

2 files changed

+26
-13
lines changed

2 files changed

+26
-13
lines changed

mypyc/irbuild/specialize.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,14 +157,19 @@ def translate_globals(builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Va
157157

158158

159159
@specialize_function("builtins.abs")
160-
def translate_abs(builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Value | None:
161-
"""Specialize calls on native classes that implement __abs__."""
160+
@specialize_function("builtins.int")
161+
@specialize_function("builtins.float")
162+
def translate_builtins_with_unary_dunder(
163+
builder: IRBuilder, expr: CallExpr, callee: RefExpr
164+
) -> Value | None:
165+
"""Specialize calls on native classes that implement the associated dunder."""
162166
if len(expr.args) == 1 and expr.arg_kinds == [ARG_POS]:
163167
arg = expr.args[0]
164168
arg_typ = builder.node_type(arg)
165-
if isinstance(arg_typ, RInstance) and arg_typ.class_ir.has_method("__abs__"):
169+
method = f"__{callee.name}__"
170+
if isinstance(arg_typ, RInstance) and arg_typ.class_ir.has_method(method):
166171
obj = builder.accept(arg)
167-
return builder.gen_method_call(obj, "__abs__", [], None, expr.line)
172+
return builder.gen_method_call(obj, method, [], None, expr.line)
168173

169174
return None
170175

mypyc/test-data/irbuild-dunders.test

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -154,13 +154,17 @@ class C:
154154
def __abs__(self) -> int:
155155
return 6
156156

157+
def __bool__(self) -> bool:
158+
return False
159+
157160
def f(c: C) -> None:
158161
-c
159162
~c
160163
int(c)
161164
float(c)
162165
+c
163166
abs(c)
167+
bool(c)
164168
[out]
165169
def C.__neg__(self):
166170
self :: __main__.C
@@ -188,19 +192,23 @@ def C.__abs__(self):
188192
self :: __main__.C
189193
L0:
190194
return 12
195+
def C.__bool__(self):
196+
self :: __main__.C
197+
L0:
198+
return 0
191199
def f(c):
192200
c :: __main__.C
193-
r0, r1 :: int
194-
r2, r3, r4, r5 :: object
195-
r6, r7 :: int
201+
r0, r1, r2 :: int
202+
r3 :: float
203+
r4, r5 :: int
204+
r6 :: bool
196205
L0:
197206
r0 = c.__neg__()
198207
r1 = c.__invert__()
199-
r2 = load_address PyLong_Type
200-
r3 = PyObject_CallFunctionObjArgs(r2, c, 0)
201-
r4 = load_address PyFloat_Type
202-
r5 = PyObject_CallFunctionObjArgs(r4, c, 0)
203-
r6 = c.__pos__()
204-
r7 = c.__abs__()
208+
r2 = c.__int__()
209+
r3 = c.__float__()
210+
r4 = c.__pos__()
211+
r5 = c.__abs__()
212+
r6 = c.__bool__()
205213
return 1
206214

0 commit comments

Comments
 (0)