Skip to content

Commit 9ec1e65

Browse files
committed
feat: cache len for iterating over immutable types
1 parent 2e5d7ee commit 9ec1e65

File tree

1 file changed

+21
-4
lines changed

1 file changed

+21
-4
lines changed

mypyc/irbuild/for_helpers.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -792,10 +792,23 @@ def init(self, expr_reg: Value, target_type: RType, reverse: bool) -> None:
792792
# for the for-loop. If we are inside of a generator function, spill these into the
793793
# environment class.
794794
self.expr_target = builder.maybe_spill(expr_reg)
795+
if (
796+
is_tuple_rprimitive(expr_reg.type)
797+
or is_str_rprimitive(expr_reg.type)
798+
or is_bytes_rprimitive(expr_reg.type)
799+
or is_frozenset_rprimitive(expr_reg.type)
800+
):
801+
self.length_reg = builder.maybe_spill(self.load_len(self.expr_target))
802+
else:
803+
self.length_reg = None
795804
if not reverse:
796805
index_reg: Value = Integer(0, c_pyssize_t_rprimitive)
797806
else:
798-
index_reg = builder.builder.int_sub(self.load_len(self.expr_target), 1)
807+
if self.length_reg is not None:
808+
len_val = builder.read(self.length_reg)
809+
else:
810+
len_val = self.load_len(self.expr_target)
811+
index_reg = builder.builder.int_sub(len_val, 1)
799812
self.index_target = builder.maybe_spill_assignable(index_reg)
800813
self.target_type = target_type
801814

@@ -814,9 +827,13 @@ def gen_condition(self) -> None:
814827
second_check = BasicBlock()
815828
builder.add_bool_branch(comparison, second_check, self.loop_exit)
816829
builder.activate_block(second_check)
817-
# For compatibility with python semantics we recalculate the length
818-
# at every iteration.
819-
len_reg = self.load_len(self.expr_target)
830+
if self.length_reg is None:
831+
# For compatibility with python semantics we recalculate the length
832+
# at every iteration.
833+
len_reg = self.load_len(self.expr_target)
834+
else:
835+
# (unless input is immutable type).
836+
len_reg = builder.read(self.length_reg, line)
820837
comparison = builder.binary_op(builder.read(self.index_target, line), len_reg, "<", line)
821838
builder.add_bool_branch(comparison, self.body_block, self.loop_exit)
822839

0 commit comments

Comments
 (0)