Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[mypyc] Precompute set literals for "in" ops against / iteration over set literals#14409

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
JukkaL merged 17 commits intopython:masterfromichard26:faster-in-for-set-literals
Jan 10, 2023
Merged
Show file tree
Hide file tree
Changes from1 commit
Commits
Show all changes
17 commits
Select commitHold shift + click to select a range
b0f57ab
mypyc: cherry picked wip from a year ago
ichard26Aug 12, 2021
c8d2dda
[wip] [mypyc] Precompute set literals for in ops
ichard26Aug 24, 2022
779a598
Stablize pprint of frozenset literals
ichard26Jan 6, 2023
7fabcfe
Fix byte literals & clean up precompute_set_literal()
ichard26Jan 6, 2023
97faab5
[wip] more tests
ichard26Jan 6, 2023
3ccf951
Update irbuild and add run tests
ichard26Jan 6, 2023
de47fef
Merge branch 'master' into faster-in-for-set-literals
ichard26Jan 6, 2023
0036e20
Clean up patch & add boolean to tests
ichard26Jan 6, 2023
e1527e2
Optimize for ... in <set-literal>
ichard26Jan 7, 2023
e3d3045
Oh look, I found constant_fold_expr()
ichard26Jan 7, 2023
8d68a7b
Run flake8/isort
ichard26Jan 7, 2023
1b75b7d
I forgot Final is a 3.8+ feature >.<
ichard26Jan 7, 2023
1a55fa4
Work around mypyc bug ...
ichard26Jan 7, 2023
3d44293
Work around mypyc bug ... attempt 2
ichard26Jan 7, 2023
fefac47
Work around mypyc bug ... attempt 3
ichard26Jan 7, 2023
9cdfc98
Add error handling + use test_* syntax instead
ichard26Jan 9, 2023
2f18f30
Improve precompute_set_literal() docstring
ichard26Jan 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
PrevPrevious commit
NextNext commit
Optimize for ... in <set-literal>
  • Loading branch information
@ichard26
ichard26 committedJan 7, 2023
commite1527e2a5f9882100cee2af703e3d15ad777486c
15 changes: 13 additions & 2 deletionsmypyc/irbuild/for_helpers.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -17,6 +17,7 @@
Lvalue,
MemberExpr,
RefExpr,
SetExpr,
TupleExpr,
TypeAlias,
)
Expand DownExpand Up@@ -469,12 +470,22 @@ def make_for_loop_generator(
for_dict_gen.init(expr_reg, target_type)
return for_dict_gen

iterable_expr_reg: Value | None = None
if isinstance(expr, SetExpr):
# Special case "for x in <set literal>".
from mypyc.irbuild.expression import precompute_set_literal

set_literal = precompute_set_literal(builder, expr)
if set_literal is not None:
iterable_expr_reg = set_literal

# Default to a generic for loop.
expr_reg = builder.accept(expr)
if iterable_expr_reg is None:
iterable_expr_reg = builder.accept(expr)
for_obj = ForIterable(builder, index, body_block, loop_exit, line, nested)
item_type = builder._analyze_iterable_item_type(expr)
item_rtype = builder.type_to_rtype(item_type)
for_obj.init(expr_reg, item_rtype)
for_obj.init(iterable_expr_reg, item_rtype)
return for_obj


Expand Down
121 changes: 120 additions & 1 deletionmypyc/test-data/irbuild-set.test
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -656,7 +656,7 @@ L0:
r13 = r12 >= 0 :: signed
return r0

[casetestOperatorInLiteral]
[casetestOperatorInSetLiteral]
from typing import Final

CONST: Final = "daylily"
Expand DownExpand Up@@ -766,3 +766,122 @@ L0:
r6 = r5 >= 0 :: signed
r7 = truncate r5: int32 to builtins.bool
return r7

[case testForSetLiteral]
from typing import Final

CONST: Final = 10
non_const = 20

def precomputed() -> None:
for _ in {"None", "True", "False"}:
pass

def precomputed2() -> None:
for _ in {None, False, 1, 2.0, "4", b"5", (6,), 7j, CONST}:
pass

def not_precomputed() -> None:
for not_optimized in {1 + 1}:
pass
for not_optimized in {non_const}:
pass

[out]
def precomputed():
r0 :: set
r1, r2 :: object
r3 :: str
_ :: object
r4 :: bit
L0:
r0 = frozenset({'False', 'None', 'True'})
r1 = PyObject_GetIter(r0)
L1:
r2 = PyIter_Next(r1)
if is_error(r2) goto L4 else goto L2
L2:
r3 = cast(str, r2)
_ = r3
L3:
goto L1
L4:
r4 = CPy_NoErrOccured()
L5:
return 1
def precomputed2():
r0 :: set
r1, r2, _ :: object
r3 :: bit
L0:
r0 = frozenset({(6,), 1, 10, 2.0, '4', 7j, False, None, b'5'})
r1 = PyObject_GetIter(r0)
L1:
r2 = PyIter_Next(r1)
if is_error(r2) goto L4 else goto L2
L2:
_ = r2
L3:
goto L1
L4:
r3 = CPy_NoErrOccured()
L5:
return 1
def not_precomputed():
r0 :: set
r1 :: object
r2 :: int32
r3 :: bit
r4, r5 :: object
r6, not_optimized :: int
r7 :: bit
r8 :: dict
r9 :: str
r10 :: object
r11 :: int
r12 :: set
r13 :: object
r14 :: int32
r15 :: bit
r16, r17 :: object
r18 :: int
r19 :: bit
L0:
r0 = PySet_New(0)
r1 = object 2
r2 = PySet_Add(r0, r1)
r3 = r2 >= 0 :: signed
r4 = PyObject_GetIter(r0)
L1:
r5 = PyIter_Next(r4)
if is_error(r5) goto L4 else goto L2
L2:
r6 = unbox(int, r5)
not_optimized = r6
L3:
goto L1
L4:
r7 = CPy_NoErrOccured()
L5:
r8 = __main__.globals :: static
r9 = 'non_const'
r10 = CPyDict_GetItem(r8, r9)
r11 = unbox(int, r10)
r12 = PySet_New(0)
r13 = box(int, r11)
r14 = PySet_Add(r12, r13)
r15 = r14 >= 0 :: signed
r16 = PyObject_GetIter(r12)
L6:
r17 = PyIter_Next(r16)
if is_error(r17) goto L9 else goto L7
L7:
r18 = unbox(int, r17)
not_optimized = r18
L8:
goto L6
L9:
r19 = CPy_NoErrOccured()
L10:
return 1

6 changes: 6 additions & 0 deletionsmypyc/test-data/run-sets.test
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -131,6 +131,10 @@ def main_negated_set(item: Any) -> bool:
def non_final_name_set(item: Any) -> bool:
return item in {non_const}

s = set()
for i in {None, False, 1, 2.0, "3", b"4", 5j, (6,), CONST}:
s.add(i)

[file driver.py]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Style nit: Instead of having the assertions indriver.py, could you add them into the main[case ...] section insidetest_* functions?

I'd like to move towards writing tests this way, since it makes larger test cases easier to read, and there's less risk that contributors forget that code indriver.py doesn't get compiled.

Copy link
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Makes sense, PTAL9cdfc98.

import native
from native import CONST, main_set, main_negated_set, non_final_name_set
Expand All@@ -142,3 +146,5 @@ for item in (None, False, 1, 2.0, "3", b"4", 5j, (6,), ((7,),), (), CONST):
assert non_final_name_set(native.non_const)
native.non_const = "updated"
assert non_final_name_set("updated")

assert not native.s ^ {None, False, 1, 2.0, "3", b"4", 5j, (6,), CONST}, native.s

[8]ページ先頭

©2009-2025 Movatter.jp