Skip to content

Commit da86db5

Browse files
authored
gh-106529: Implement JUMP_FORWARD in uops (with test) (#106651)
Note that this may generate two SAVE_IP uops in a row. Removing unneeded SAVE_IP uops is the optimizer's job.
1 parent d0972c7 commit da86db5

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

Lib/test/test_capi/test_misc.py

+25
Original file line numberDiff line numberDiff line change
@@ -2553,6 +2553,7 @@ def testfunc(n):
25532553
i = 0
25542554
while i < n:
25552555
i += 1
2556+
25562557
opt = _testinternalcapi.get_uop_optimizer()
25572558
with temporary_optimizer(opt):
25582559
testfunc(10)
@@ -2562,6 +2563,30 @@ def testfunc(n):
25622563
uops = {opname for opname, _ in ex}
25632564
self.assertIn("JUMP_TO_TOP", uops)
25642565

2566+
def test_jump_forward(self):
2567+
def testfunc(n):
2568+
a = 0
2569+
while a < n:
2570+
if a < 0:
2571+
a = -a
2572+
else:
2573+
a = +a
2574+
a += 1
2575+
return a
2576+
2577+
opt = _testinternalcapi.get_uop_optimizer()
2578+
with temporary_optimizer(opt):
2579+
testfunc(10)
2580+
2581+
ex = get_first_executor(testfunc)
2582+
self.assertIsNotNone(ex)
2583+
# for i, (opname, oparg) in enumerate(ex):
2584+
# print(f"{i:4d}: {opname:<20s} {oparg:4d}")
2585+
uops = {opname for opname, _ in ex}
2586+
# Since there is no JUMP_FORWARD instruction,
2587+
# look for indirect evidence: the += operator
2588+
self.assertIn("_BINARY_OP_ADD_INT", uops)
2589+
25652590

25662591
if __name__ == "__main__":
25672592
unittest.main()

Python/optimizer.c

+7
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,13 @@ translate_bytecode_to_trace(
472472
goto done;
473473
}
474474

475+
case JUMP_FORWARD:
476+
{
477+
// This will emit two SAVE_IP instructions; leave it to the optimizer
478+
instr += oparg;
479+
break;
480+
}
481+
475482
default:
476483
{
477484
const struct opcode_macro_expansion *expansion = &_PyOpcode_macro_expansion[opcode];

0 commit comments

Comments
 (0)