diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index b31c9f68d01bec..6d0a0c7545ec1a 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -2340,6 +2340,21 @@ def testfunc(n): self.assertIn("_BINARY_OP_SUBSCR_DICT_KNOWN_HASH", uops) self.assertNotIn("_BINARY_OP_SUBSCR_DICT", uops) + + def test_binary_op_subscr_constant_frozendict_known_hash(self): + def testfunc(n): + x = 0 + for _ in range(n): + x += FROZEN_DICT_CONST['x'] + return x + + res, ex = self._run_with_optimizer(testfunc, 2 * TIER2_THRESHOLD) + self.assertEqual(res, 2 * TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertNotIn("_BINARY_OP_SUBSCR_DICT_KNOWN_HASH", uops) + self.assertNotIn("_BINARY_OP_SUBSCR_DICT", uops) + def test_store_subscr_dict_known_hash(self): # str, int, bytes, float, complex, tuple and any python object which has generic hash def testfunc(n): diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 58b50707e55cee..9f0584c50bebf5 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -515,18 +515,18 @@ dummy_func(void) { } op(_BINARY_OP_SUBSCR_DICT, (dict_st, sub_st -- res, ds, ss)) { - PyObject *sub = sym_get_const(ctx, sub_st); - if (sub != NULL) { - optimize_dict_known_hash(ctx, dependencies, this_instr, - sub, _BINARY_OP_SUBSCR_DICT_KNOWN_HASH); - } res = sym_new_not_null(ctx); ds = dict_st; ss = sub_st; + PyObject *sub = sym_get_const(ctx, sub_st); if (sym_is_not_container(sub_st) && sym_matches_type(dict_st, &PyFrozenDict_Type)) { REPLACE_OPCODE_IF_EVALUATES_PURE(dict_st, sub_st, res); } + else if (sub != NULL) { + optimize_dict_known_hash(ctx, dependencies, this_instr, + sub, _BINARY_OP_SUBSCR_DICT_KNOWN_HASH); + } } op(_BINARY_OP_SUBSCR_LIST_SLICE, (list_st, sub_st -- res, ls, ss)) { diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 891887301119d7..bb588457d22d5c 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -1462,14 +1462,10 @@ JitOptRef ss; sub_st = stack_pointer[-1]; dict_st = stack_pointer[-2]; - PyObject *sub = sym_get_const(ctx, sub_st); - if (sub != NULL) { - optimize_dict_known_hash(ctx, dependencies, this_instr, - sub, _BINARY_OP_SUBSCR_DICT_KNOWN_HASH); - } res = sym_new_not_null(ctx); ds = dict_st; ss = sub_st; + PyObject *sub = sym_get_const(ctx, sub_st); if (sym_is_not_container(sub_st) && sym_matches_type(dict_st, &PyFrozenDict_Type)) { if ( @@ -1519,6 +1515,10 @@ break; } } + else if (sub != NULL) { + optimize_dict_known_hash(ctx, dependencies, this_instr, + sub, _BINARY_OP_SUBSCR_DICT_KNOWN_HASH); + } CHECK_STACK_BOUNDS(1); stack_pointer[-2] = res; stack_pointer[-1] = ds;