From b2b261ab2a2d4ff000c6248dbc52247c78cfa5ab Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Mon, 17 Jul 2023 10:06:05 -0700 Subject: [PATCH] gh-106529: Generate uops for POP_JUMP_IF_[NOT_]NONE (#106796) These aren't automatically translated because (ironically) they are macros deferring to POP_JUMP_IF_{TRUE,FALSE}, which are not viable uops (being manually translated). The hack is that we emit IS_NONE and then set opcode and jump to the POP_JUMP_IF_{TRUE,FALSE} translation code. --- Lib/test/test_capi/test_misc.py | 30 ++++++++++++++++++++++++++++++ Python/optimizer.c | 17 +++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py index 6df918997b2b19..c0dcff825758ad 100644 --- a/Lib/test/test_capi/test_misc.py +++ b/Lib/test/test_capi/test_misc.py @@ -2532,6 +2532,36 @@ def testfunc(n): uops = {opname for opname, _ in ex} self.assertIn("_POP_JUMP_IF_FALSE", uops) + def test_pop_jump_if_none(self): + def testfunc(a): + for x in a: + if x is None: + x = 0 + + opt = _testinternalcapi.get_uop_optimizer() + with temporary_optimizer(opt): + testfunc([1, 2, 3]) + + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + uops = {opname for opname, _ in ex} + self.assertIn("_POP_JUMP_IF_TRUE", uops) + + def test_pop_jump_if_not_none(self): + def testfunc(a): + for x in a: + if x is not None: + x = 0 + + opt = _testinternalcapi.get_uop_optimizer() + with temporary_optimizer(opt): + testfunc([1, 2, 3]) + + ex = get_first_executor(testfunc) + self.assertIsNotNone(ex) + uops = {opname for opname, _ in ex} + self.assertIn("_POP_JUMP_IF_FALSE", uops) + def test_pop_jump_if_true(self): def testfunc(n): i = 0 diff --git a/Python/optimizer.c b/Python/optimizer.c index 289b202f806ae1..693ba375971ae7 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -464,9 +464,26 @@ translate_bytecode_to_trace( switch (opcode) { + case POP_JUMP_IF_NONE: + { + RESERVE(2, 2); + ADD_TO_TRACE(IS_NONE, 0); + opcode = POP_JUMP_IF_TRUE; + goto pop_jump_if_bool; + } + + case POP_JUMP_IF_NOT_NONE: + { + RESERVE(2, 2); + ADD_TO_TRACE(IS_NONE, 0); + opcode = POP_JUMP_IF_FALSE; + goto pop_jump_if_bool; + } + case POP_JUMP_IF_FALSE: case POP_JUMP_IF_TRUE: { +pop_jump_if_bool: // Assume jump unlikely (TODO: handle jump likely case) RESERVE(1, 2); _Py_CODEUNIT *target_instr =