Skip to content

Commit ebd2c01

Browse files
ljfpCopilot
andcommitted
pythongh-133672: Allow LOAD_FAST to be optimized to LOAD_FAST_BORROW
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 85d3bcd commit ebd2c01

3 files changed

Lines changed: 540 additions & 9 deletions

File tree

Lib/test/test_peepholer.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2598,6 +2598,36 @@ def test_for_iter(self):
25982598
("LOAD_CONST", 0, 7),
25992599
("RETURN_VALUE", None, 8),
26002600
]
2601+
expected = [
2602+
("LOAD_FAST_BORROW", 0, 1),
2603+
top := self.Label(),
2604+
("FOR_ITER", end := self.Label(), 2),
2605+
("STORE_FAST", 2, 3),
2606+
("JUMP", top, 4),
2607+
end,
2608+
("END_FOR", None, 5),
2609+
("POP_TOP", None, 6),
2610+
("LOAD_CONST", 0, 7),
2611+
("RETURN_VALUE", None, 8),
2612+
]
2613+
self.cfg_optimization_test(insts, expected, consts=[None])
2614+
2615+
def test_for_iter_checks_fallthrough(self):
2616+
insts = [
2617+
("LOAD_FAST", 0, 1),
2618+
("GET_ITER", 0, 2),
2619+
top := self.Label(),
2620+
("FOR_ITER", end := self.Label(), 3),
2621+
("STORE_FAST", 1, 4),
2622+
("LOAD_CONST", 0, 5),
2623+
("STORE_FAST", 0, 6),
2624+
("JUMP", top, 7),
2625+
end,
2626+
("END_FOR", None, 8),
2627+
("POP_ITER", None, 9),
2628+
("LOAD_CONST", 0, 10),
2629+
("RETURN_VALUE", None, 11),
2630+
]
26012631
self.cfg_optimization_test(insts, insts, consts=[None])
26022632

26032633
def test_load_attr(self):
@@ -2675,6 +2705,69 @@ def test_send(self):
26752705
]
26762706
self.cfg_optimization_test(insts, expected, consts=[None])
26772707

2708+
def test_borrow_checks_exception_handler_edges(self):
2709+
insts = [
2710+
("LOAD_FAST", 0, 1),
2711+
("JUMP", start := self.Label(), 2),
2712+
start,
2713+
("SETUP_FINALLY", handler := self.Label(), 3),
2714+
("LOAD_CONST", 0, 4),
2715+
("BINARY_OP", 0, 5),
2716+
("POP_BLOCK", None, 6),
2717+
("RETURN_VALUE", None, 7),
2718+
handler,
2719+
("STORE_FAST", 1, 8),
2720+
("LOAD_CONST", 0, 9),
2721+
("STORE_FAST", 0, 10),
2722+
("POP_TOP", None, 11),
2723+
("LOAD_CONST", 0, 12),
2724+
("RETURN_VALUE", None, 13),
2725+
]
2726+
expected = [
2727+
("LOAD_FAST", 0, 1),
2728+
("NOP", None, 2),
2729+
("SETUP_FINALLY", handler := self.Label(), 3),
2730+
("LOAD_CONST", 0, 4),
2731+
("BINARY_OP", 0, 5),
2732+
("NOP", None, 6),
2733+
("RETURN_VALUE", None, 7),
2734+
handler,
2735+
("STORE_FAST", 1, 8),
2736+
("LOAD_CONST", 0, 9),
2737+
("STORE_FAST", 0, 10),
2738+
("POP_TOP", None, 11),
2739+
("LOAD_CONST", 0, 12),
2740+
("RETURN_VALUE", None, 13),
2741+
]
2742+
self.cfg_optimization_test(insts, expected, consts=[None])
2743+
2744+
def test_copied_reference_is_not_borrowed(self):
2745+
insts = [
2746+
("LOAD_FAST", 0, 1),
2747+
("COPY", 1, 1),
2748+
("TO_BOOL", None, 1),
2749+
("POP_JUMP_IF_TRUE", target := self.Label(), 1),
2750+
("POP_TOP", None, 1),
2751+
("LOAD_FAST", 1, 1),
2752+
target,
2753+
("STORE_FAST", 0, 1),
2754+
("LOAD_CONST", 0, 2),
2755+
("RETURN_VALUE", None, 2),
2756+
]
2757+
expected = [
2758+
("LOAD_FAST", 0, 1),
2759+
("COPY", 1, 1),
2760+
("TO_BOOL", None, 1),
2761+
("POP_JUMP_IF_TRUE", target := self.Label(), 1),
2762+
("POP_TOP", None, 1),
2763+
("LOAD_FAST", 1, 1),
2764+
target,
2765+
("STORE_FAST", 0, 1),
2766+
("LOAD_CONST", 0, 2),
2767+
("RETURN_VALUE", None, 2),
2768+
]
2769+
self.cfg_optimization_test(insts, expected, consts=[None])
2770+
26782771
def test_format_simple(self):
26792772
# FORMAT_SIMPLE will leave its operand on the stack if it's a unicode
26802773
# object. We treat it conservatively and assume that it always leaves
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
The peephole optimizer now converts LOAD_FAST to LOAD_FAST_BORROW more aggressively. This optimization is applied even if the loaded variable remains live on the stack at the end of a basic block, as long as the borrow is otherwise determined to be safe. This can reduce reference counting overhead in certain code patterns, such as with iterables in loops.

0 commit comments

Comments
 (0)