Skip to content

Commit 2787d49

Browse files
[mypyc] Faster set creation with generator expression (#10261)
Closes mypyc/mypyc#771 and #9707. Changes: * Move code from tranform_set_comprehension to translate_set_comprehension * Fix the unnecessary set creation (#9707 (comment))
1 parent bab4e22 commit 2787d49

File tree

5 files changed

+442
-19
lines changed

5 files changed

+442
-19
lines changed

mypyc/irbuild/expression.py

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,15 @@
3030
from mypyc.primitives.list_ops import list_append_op, list_extend_op, list_slice_op
3131
from mypyc.primitives.tuple_ops import list_tuple_op, tuple_slice_op
3232
from mypyc.primitives.dict_ops import dict_new_op, dict_set_item_op, dict_get_item_op
33-
from mypyc.primitives.set_ops import new_set_op, set_add_op, set_update_op
33+
from mypyc.primitives.set_ops import set_add_op, set_update_op
3434
from mypyc.primitives.str_ops import str_slice_op
3535
from mypyc.primitives.int_ops import int_comparison_op_mapping
3636
from mypyc.irbuild.specialize import specializers
3737
from mypyc.irbuild.builder import IRBuilder
38-
from mypyc.irbuild.for_helpers import translate_list_comprehension, comprehension_helper
38+
from mypyc.irbuild.for_helpers import (
39+
translate_list_comprehension, translate_set_comprehension,
40+
comprehension_helper
41+
)
3942

4043

4144
# Name and attribute references
@@ -656,16 +659,7 @@ def transform_list_comprehension(builder: IRBuilder, o: ListComprehension) -> Va
656659

657660

658661
def transform_set_comprehension(builder: IRBuilder, o: SetComprehension) -> Value:
659-
gen = o.generator
660-
set_ops = builder.call_c(new_set_op, [], o.line)
661-
loop_params = list(zip(gen.indices, gen.sequences, gen.condlists))
662-
663-
def gen_inner_stmts() -> None:
664-
e = builder.accept(gen.left_expr)
665-
builder.call_c(set_add_op, [set_ops, e], o.line)
666-
667-
comprehension_helper(builder, loop_params, gen_inner_stmts, o.line)
668-
return set_ops
662+
return translate_set_comprehension(builder, o.generator)
669663

670664

671665
def transform_dictionary_comprehension(builder: IRBuilder, o: DictionaryComprehension) -> Value:

mypyc/irbuild/for_helpers.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
dict_key_iter_op, dict_value_iter_op, dict_item_iter_op
2525
)
2626
from mypyc.primitives.list_ops import list_append_op, list_get_item_unsafe_op
27+
from mypyc.primitives.set_ops import set_add_op
2728
from mypyc.primitives.generic_ops import iter_op, next_op
2829
from mypyc.primitives.exc_ops import no_err_occurred_op
2930
from mypyc.irbuild.builder import IRBuilder
@@ -142,6 +143,18 @@ def gen_inner_stmts() -> None:
142143
return list_ops
143144

144145

146+
def translate_set_comprehension(builder: IRBuilder, gen: GeneratorExpr) -> Value:
147+
set_ops = builder.new_set_op([], gen.line)
148+
loop_params = list(zip(gen.indices, gen.sequences, gen.condlists))
149+
150+
def gen_inner_stmts() -> None:
151+
e = builder.accept(gen.left_expr)
152+
builder.call_c(set_add_op, [set_ops, e], gen.line)
153+
154+
comprehension_helper(builder, loop_params, gen_inner_stmts, gen.line)
155+
return set_ops
156+
157+
145158
def comprehension_helper(builder: IRBuilder,
146159
loop_params: List[Tuple[Lvalue, Expression, List[Expression]]],
147160
gen_inner_stmts: Callable[[], None],

mypyc/irbuild/specialize.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828
from mypyc.primitives.tuple_ops import new_tuple_set_item_op
2929
from mypyc.irbuild.builder import IRBuilder
3030
from mypyc.irbuild.for_helpers import (
31-
translate_list_comprehension, comprehension_helper,
32-
for_loop_helper_with_index
31+
translate_list_comprehension, translate_set_comprehension,
32+
comprehension_helper, for_loop_helper_with_index,
3333
)
3434

3535

@@ -112,8 +112,19 @@ def dict_methods_fast_path(
112112
return builder.call_c(dict_items_op, [obj], expr.line)
113113

114114

115-
@specialize_function('builtins.tuple')
116115
@specialize_function('builtins.set')
116+
def translate_set_from_generator_call(
117+
builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Optional[Value]:
118+
# Special case for set creation from a generator:
119+
# set(f(...) for ... in iterator/nested_generators...)
120+
if (len(expr.args) == 1
121+
and expr.arg_kinds[0] == ARG_POS
122+
and isinstance(expr.args[0], GeneratorExpr)):
123+
return translate_set_comprehension(builder, expr.args[0])
124+
return None
125+
126+
127+
@specialize_function('builtins.tuple')
117128
@specialize_function('builtins.frozenset')
118129
@specialize_function('builtins.dict')
119130
@specialize_function('builtins.sum')
@@ -143,6 +154,7 @@ def translate_safe_generator_call(
143154
val = tuple_from_generator_helper(builder, expr.args[0])
144155
if val is not None:
145156
return val
157+
146158
return builder.call_refexpr_with_args(
147159
expr, callee,
148160
([translate_list_comprehension(builder, expr.args[0])]

0 commit comments

Comments
 (0)