Skip to content

gh-146381: Fold frozendict subscript via _BINARY_OP_SUBSCR_FROZEN_DICT#146490

Open
corona10 wants to merge 3 commits intopython:mainfrom
corona10:gh-146381-jit
Open

gh-146381: Fold frozendict subscript via _BINARY_OP_SUBSCR_FROZEN_DICT#146490
corona10 wants to merge 3 commits intopython:mainfrom
corona10:gh-146381-jit

Conversation

@corona10
Copy link
Member

@corona10 corona10 commented Mar 26, 2026

@corona10
Copy link
Member Author

@Fidget-Spinner
I added _BINARY_OP_SUBSCR_FROZEN_DICT as a lowered uop for frozendict lookups. When the optimizer sees _BINARY_OP_SUBSCR_DICT with a frozendict operand, it replaces it with _BINARY_OP_SUBSCR_FROZEN_DICT, then folds the result to a constant via sym_frozendict_getitem if both dict and key are known constants.

@corona10
Copy link
Member Author

main

['_START_EXECUTOR', '_MAKE_WARM', '_SET_IP', '_CHECK_PERIODIC', '_CHECK_VALIDITY', '_ITER_CHECK_RANGE', '_GUARD_NOT_EXHAUSTED_RANGE', '_ITER_NEXT_RANGE', '_SET_IP', '_SWAP_FAST_2', '_SPILL_OR_RELOAD', '_POP_TOP', '_CHECK_VALIDITY', '_GUARD_GLOBALS_VERSION', '_LOAD_CONST_INLINE', '_LOAD_CONST_INLINE_BORROW', '_SET_IP', '_BINARY_OP_SUBSCR_DICT', '_POP_TOP_NOP', '_SPILL_OR_RELOAD', '_POP_TOP', '_CHECK_VALIDITY', '_LOAD_CONST_INLINE_BORROW', '_GUARD_NOS_INT', '_COMPARE_OP_INT', '_POP_TOP_NOP', '_POP_TOP_INT', '_GUARD_BIT_IS_SET_POP_5', '_LOAD_FAST_BORROW_1', '_LOAD_CONST_INLINE_BORROW', '_GUARD_NOS_INT', '_BINARY_OP_ADD_INT', '_POP_TOP_NOP', '_POP_TOP_NOP', '_SWAP_FAST_1', '_POP_TOP_INT', '_JUMP_TO_TOP', '_DEOPT', '_ERROR_POP_N', '_DEOPT', '_EXIT_TRACE', '_EXIT_TRACE', '_ERROR_POP_N', '_DEOPT', '_ERROR_POP_N', '_DEOPT', '_EXIT_TRACE', '_EXIT_TRACE', '_EXIT_TRACE']

PR

['_START_EXECUTOR', '_MAKE_WARM', '_SET_IP', '_CHECK_PERIODIC', '_CHECK_VALIDITY', '_ITER_CHECK_RANGE', '_GUARD_NOT_EXHAUSTED_RANGE', '_ITER_NEXT_RANGE', '_SET_IP', '_SWAP_FAST_2', '_SPILL_OR_RELOAD', '_POP_TOP', '_CHECK_VALIDITY', '_GUARD_GLOBALS_VERSION', '_LOAD_CONST_INLINE', '_LOAD_CONST_INLINE_BORROW', '_SET_IP', '_BINARY_OP_SUBSCR_FROZEN_DICT', '_POP_TOP_NOP', '_SPILL_OR_RELOAD', '_POP_TOP', '_CHECK_VALIDITY', '_LOAD_CONST_INLINE_BORROW', '_INSERT_2_LOAD_CONST_INLINE_BORROW', '_POP_TOP_NOP', '_POP_TOP_INT', '_SET_IP', '_POP_TOP', '_CHECK_VALIDITY', '_LOAD_FAST_BORROW_1', '_LOAD_CONST_INLINE_BORROW', '_GUARD_NOS_INT', '_BINARY_OP_ADD_INT', '_POP_TOP_NOP', '_POP_TOP_NOP', '_SWAP_FAST_1', '_POP_TOP_INT', '_JUMP_TO_TOP', '_DEOPT', '_ERROR_POP_N', '_DEOPT', '_EXIT_TRACE', '_EXIT_TRACE', '_ERROR_POP_N', '_DEOPT', '_ERROR_POP_N', '_DEOPT', '_DEOPT', '_EXIT_TRACE']

extern PyTypeObject *_Py_uop_sym_get_type(JitOptRef sym);
extern JitOptRef _Py_uop_sym_new_tuple(JitOptContext *ctx, int size, JitOptRef *args);
extern JitOptRef _Py_uop_sym_tuple_getitem(JitOptContext *ctx, JitOptRef sym, Py_ssize_t item);
extern JitOptRef _Py_uop_sym_frozendict_getitem(JitOptContext *ctx, JitOptRef sym, JitOptRef key);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need this function.

return _Py_uop_sym_new_not_null(ctx);
}

JitOptRef
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, we don't need this function.

Comment on lines +490 to +491
REPLACE_OP(this_instr, _BINARY_OP_SUBSCR_FROZEN_DICT, oparg, 0);
res = sym_frozendict_getitem(ctx, dict_st, sub_st);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
REPLACE_OP(this_instr, _BINARY_OP_SUBSCR_FROZEN_DICT, oparg, 0);
res = sym_frozendict_getitem(ctx, dict_st, sub_st);
REPLACE_OPCODE_IF_EVALUATES_PURE(dict_st, sub_st, res);

Check out what is the generated code in executor_cases.c.h after this :).

Comment on lines +495 to 500
op(_BINARY_OP_SUBSCR_FROZEN_DICT, (dict_st, sub_st -- res, ds, ss)) {
res = sym_new_not_null(ctx);
ds = dict_st;
ss = sub_st;
REPLACE_OPCODE_IF_EVALUATES_PURE(dict_st, sub_st, res);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be removed.

self.assertEqual(res, TIER2_THRESHOLD)
self.assertIsNotNone(ex)
uops = get_opnames(ex)
self.assertIn("_BINARY_OP_SUBSCR_FROZEN_DICT", uops)
Copy link
Member

@Fidget-Spinner Fidget-Spinner Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After the correct replacement, this should just become POP_TOP_LOAD_CONST...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants