Skip to content

gh-146381: Constant-fold frozendict subscript lookups via REPLACE_OPCODE_IF_EVALUATES_PURE#146490

Merged
corona10 merged 4 commits intopython:mainfrom
corona10:gh-146381-jit
Mar 28, 2026
Merged

gh-146381: Constant-fold frozendict subscript lookups via REPLACE_OPCODE_IF_EVALUATES_PURE#146490
corona10 merged 4 commits intopython:mainfrom
corona10:gh-146381-jit

Conversation

@corona10
Copy link
Copy Markdown
Member

@corona10 corona10 commented Mar 26, 2026

@corona10
Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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.

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
Copy Markdown
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
Copy Markdown
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...

@corona10
Copy link
Copy Markdown
Member Author

corona10 commented Mar 27, 2026

@Fidget-Spinner
I've addressed your code review.
uops are optimized very well! Awesome :)

['_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', '_INSERT_2_LOAD_CONST_INLINE_BORROW', '_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', '_DEOPT', '_DEOPT', '_EXIT_TRACE']

@corona10 corona10 changed the title gh-146381: Fold frozendict subscript via _BINARY_OP_SUBSCR_FROZEN_DICT gh-146381: Constant-fold frozendict subscript lookups via REPLACE_OPCODE_IF_EVALUATES_PURE Mar 27, 2026
@corona10 corona10 requested a review from Fidget-Spinner March 27, 2026 16:26
Copy link
Copy Markdown
Member

@Fidget-Spinner Fidget-Spinner left a comment

Choose a reason for hiding this comment

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

The power of the JIT optimizer :).

@corona10 corona10 merged commit 5992238 into python:main Mar 28, 2026
71 checks passed
@corona10 corona10 deleted the gh-146381-jit branch March 28, 2026 00:49
@bedevere-bot
Copy link
Copy Markdown

⚠️⚠️⚠️ Buildbot failure ⚠️⚠️⚠️

Hi! The buildbot AMD64 Windows PGO NoGIL Tailcall 3.x (tier-1) has failed when building commit 5992238.

What do you need to do:

  1. Don't panic.
  2. Check the buildbot page in the devguide if you don't know what the buildbots are or how they work.
  3. Go to the page of the buildbot that failed (https://buildbot.python.org/#/builders/1871/builds/270) and take a look at the build logs.
  4. Check if the failure is related to this commit (5992238) or if it is a false positive.
  5. If the failure is related to this commit, please, reflect that on the issue and make a new Pull Request with a fix.

You can take a look at the buildbot page here:

https://buildbot.python.org/#/builders/1871/builds/270

Failed tests:

  • test_profiling

Summary of the results of the build (if available):

==

Click to see traceback logs
Traceback (most recent call last):
  File "C:\bbarea\3.x.itamaro-win64-srv-22-aws.nogil.tailcall.pgo\build\Lib\test\test_profiling\test_sampling_profiler\test_advanced.py", line 169, in test_native_frames_enabled
    self.assertFalse(any(stack.endswith(";<native>") for stack in stacks))
    ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: True is not false

Copy link
Copy Markdown

@Dustin4444 Dustin4444 left a comment

Choose a reason for hiding this comment

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

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.

5 participants