diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py index 9cbd5506bf6..9c14a501875 100644 --- a/Lib/test/test_capi/test_misc.py +++ b/Lib/test/test_capi/test_misc.py @@ -2553,6 +2553,7 @@ class TestUops(unittest.TestCase): i = 0 while i < n: i += 1 + opt = _testinternalcapi.get_uop_optimizer() with temporary_optimizer(opt): testfunc(10) @@ -2562,6 +2563,30 @@ class TestUops(unittest.TestCase): uops = {opname for opname, _ in ex} self.assertIn("JUMP_TO_TOP", uops) + def test_jump_forward(self): + def testfunc(n): + a = 0 + while a < n: + if a < 0: + a = -a + else: + a = +a + a += 1 + return a + + opt = _testinternalcapi.get_uop_optimizer() + with temporary_optimizer(opt): + testfunc(10) + + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + # for i, (opname, oparg) in enumerate(ex): + # print(f"{i:4d}: {opname:<20s} {oparg:4d}") + uops = {opname for opname, _ in ex} + # Since there is no JUMP_FORWARD instruction, + # look for indirect evidence: the += operator + self.assertIn("_BINARY_OP_ADD_INT", uops) + if __name__ == "__main__": unittest.main() diff --git a/Python/optimizer.c b/Python/optimizer.c index e2b92e68d39..7fc40e66057 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -472,6 +472,13 @@ translate_bytecode_to_trace( goto done; } + case JUMP_FORWARD: + { + // This will emit two SAVE_IP instructions; leave it to the optimizer + instr += oparg; + break; + } + default: { const struct opcode_macro_expansion *expansion = &_PyOpcode_macro_expansion[opcode];