-
Notifications
You must be signed in to change notification settings - Fork 5.7k
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SOT][3.12] replace POP_JUMP_{BACKWARD,FORWARD}_IF_{TRUE,FALSE}
to POP_JUMP_IF_{TRUE,FALSE}
#62155
Changes from all commits
ef4f58d
ec6c2aa
601a67a
c4e53a3
234ef7a
123abe8
b1e1477
5a4b1fa
cd1ec5c
fc254de
29d3960
e40f30e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1686,8 +1686,9 @@ def FOR_ITER(self, instr): | |
|
||
self._inline_call_for_loop(iterator, instr) | ||
self._lasti = self.indexof(instr.jump_to) | ||
next_instr = self._instructions[self._lasti] | ||
self._lasti += int(next_instr.opname == 'END_FOR') | ||
if sys.version_info >= (3, 12): | ||
assert self._instructions[self._lasti].opname == "END_FOR" | ||
self._lasti += 1 | ||
except BreakGraphError as e: | ||
log(3, f"[BreakGraph] FOR_ITER sim for loop failed for: {e}\n") | ||
if backup_iter_idx: | ||
|
@@ -2060,10 +2061,17 @@ def create_after_loop_fn(): | |
return None | ||
pycode_gen = PyCodeGen(self._frame) | ||
origin_instrs = get_instructions(pycode_gen._origin_code) | ||
resume_fn_end_idx = loop_body_end_idx | ||
|
||
# skip resume END_FOR in python3.12 | ||
if sys.version_info >= (3, 12): | ||
assert origin_instrs[loop_body_end_idx].opname == "END_FOR" | ||
resume_fn_end_idx += 1 | ||
|
||
pycode_gen.set_function_inputs( | ||
after_loop_fn_inputs, stack_size=len(self.stack) - 1 | ||
) | ||
pycode_gen.extend_instrs(origin_instrs[loop_body_end_idx:]) | ||
pycode_gen.extend_instrs(origin_instrs[resume_fn_end_idx:]) | ||
# the resume_fn contains return code, so we don't need set output here | ||
# global vars are updated correctly, and need local vars will return | ||
after_loop_fn = pycode_gen.create_function() | ||
|
@@ -2127,8 +2135,13 @@ def create_after_loop_fn(): | |
self._graph.pycode_gen.gen_jump( | ||
for_iter, direction=JumpDirection.BACKWARD | ||
) | ||
|
||
if sys.version_info >= (3, 12): | ||
end_for = self._graph.pycode_gen.add_instr("END_FOR") | ||
|
||
nop = self._graph.pycode_gen.add_instr("NOP") | ||
for_iter.jump_to = nop | ||
|
||
for_iter.jump_to = end_for if sys.version_info >= (3, 12) else nop | ||
jump_if_break.jump_to = nop | ||
|
||
# 9. prepare inputs and call after_loop_fn | ||
|
@@ -2198,6 +2211,8 @@ def create_inline_call_fn(): | |
for_iter_instr, direction=JumpDirection.BACKWARD | ||
) | ||
|
||
if sys.version_info >= (3, 12): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 我在测 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 是的这个 PR 就是来解决这个问题的,具体表现情况为下面三种情况:
[Resumed Function]: Inline call for loop function $resume_1@for_list_1_af1a0
39 0 RESUME 0
2 LOAD_FAST 2 (object_168)
>> 4 FOR_ITER 24 (to 56)
...
54 END_FOR
>> 56 LOAD_FAST 1 (i)
58 LOAD_FAST 0 (x)
60 LOAD_FAST 2 (object_168)
62 BUILD_TUPLE 3
64 RETURN_VALUE
[Resumed Function]: Inline call for loop function $resume_1@undefined_var_case_0_af1a0
269 0 RESUME 0
2 LOAD_FAST 2 (object_165)
>> 4 FOR_ITER 38 (84)
...
74 JUMP_FORWARD 1 (to 78)
76 JUMP_FORWARD 2 (to 82)
>> 78 NOP
80 JUMP_BACKWARD 39 (to 4)
>> 82 NOP
86 LOAD_FAST 0 (i)
...
在 Python3.12 下 13 0 RESUME 0
2 END_FOR # <-- 这里 resume 错误
4 LOAD_FAST_CHECK 0 (zzz)
6 LOAD_CONST 2 (1)
8 BINARY_OP 0 (+)
10 RETURN_VALUE 在 Python3.11 下 13 0 RESUME 0
2 LOAD_FAST 0 (zzz)
4 LOAD_CONST 2 (1)
6 BINARY_OP 0 (+)
14 10 STORE_FAST 0 (zzz)
12 LOAD_FAST 0 (zzz)
14 RETURN_VALUE 在 python3.12 39 0 RESUME 0
2 LOAD_FAST 2 (object_168)
>> 4 FOR_ITER 27 (to 60)
41 8 STORE_FAST 1 (i)
10 LOAD_FAST 0 (x)
12 LOAD_FAST 1 (i)
14 BINARY_OP 13 (+=)
43 18 STORE_FAST 0 (x)
20 LOAD_FAST 0 (x)
22 LOAD_CONST 2 (2)
24 COMPARE_OP 68 (>)
44 28 POP_JUMP_IF_FALSE 6 (to 42)
30 LOAD_FAST 0 (x)
32 LOAD_CONST 3 (1)
34 BINARY_OP 13 (+=)
38 STORE_FAST 0 (x)
46 40 JUMP_FORWARD 7 (to 56)
>> 42 LOAD_FAST 0 (x)
44 LOAD_CONST 3 (1)
46 BINARY_OP 23 (-=)
50 STORE_FAST 0 (x)
52 JUMP_FORWARD 1 (to 56)
54 JUMP_FORWARD 2 (to 62) # 无用
>> 56 NOP
58 JUMP_BACKWARD 28 (to 4)
>> 60 END_FOR
>> 62 NOP
64 LOAD_FAST 1 (i)
66 LOAD_FAST 0 (x)
68 LOAD_FAST 2 (object_168)
70 BUILD_TUPLE 3
72 RETURN_VALUE 在 python3.11 39 0 RESUME 0
2 LOAD_FAST 2 (object_168)
>> 4 FOR_ITER 27 (to 60)
41 6 STORE_FAST 1 (i)
8 LOAD_FAST 0 (x)
10 LOAD_FAST 1 (i)
12 BINARY_OP 13 (+=)
43 16 STORE_FAST 0 (x)
18 LOAD_FAST 0 (x)
20 LOAD_CONST 2 (2)
22 COMPARE_OP 4 (>)
44 28 POP_JUMP_FORWARD_IF_FALSE 6 (to 42)
30 LOAD_FAST 0 (x)
32 LOAD_CONST 3 (1)
34 BINARY_OP 13 (+=)
38 STORE_FAST 0 (x)
46 40 JUMP_FORWARD 7 (to 56)
>> 42 LOAD_FAST 0 (x)
44 LOAD_CONST 3 (1)
46 BINARY_OP 23 (-=)
50 STORE_FAST 0 (x)
52 JUMP_FORWARD 1 (to 56)
54 JUMP_FORWARD 2 (to 60)
>> 56 NOP
58 JUMP_BACKWARD 28 (to 4)
>> 60 NOP
62 LOAD_FAST 1 (i)
64 LOAD_FAST 0 (x)
66 LOAD_FAST 2 (object_168)
68 BUILD_TUPLE 3
70 RETURN_VALUE 我们可以看到 下面的内容可能说的不对:
因为需要与 # 2.2. copy main logic
pycode_gen.extend_instrs(origin_instrs[start_idx:end_idx+1])
这个我目前是定位到 code gen 的 |
||
end_for = pycode_gen.add_instr("END_FOR") | ||
nop_for_break = pycode_gen.add_instr("NOP") | ||
|
||
# 2.4. relocate jumps | ||
|
@@ -2212,6 +2227,8 @@ def create_inline_call_fn(): | |
instr.jump_to = nop_for_break | ||
|
||
jump.jump_to = for_iter_instr | ||
if sys.version_info >= (3, 12): | ||
for_iter_instr.jump_to = end_for | ||
|
||
pycode_gen.set_function_outputs(output_var_names) | ||
inline_call_fn = pycode_gen.create_function() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,4 @@ | ||
./test_11_jumps.py | ||
./test_12_for_loop.py | ||
./test_builtin_zip.py | ||
./test_inplace_api.py | ||
./test_min_graph_size.py | ||
./test_side_effects.py | ||
./test_sot_cost_model.py | ||
./test_sot_resnet.py | ||
./test_sot_resnet50_backward.py |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3.12 能否直接用
END_FOR
呢,就不需要先插一个NOP
再插一个END_FOR
了,这里的NOP
应该是冗余的变量名直接统一用
end_for
就好,也不需要两个版本一个用end_for
一个用nop
了There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
POP_JUMP_IF_FALSE
并不能跳到END_FOR
啊