Skip to content

GH-130415: Improve the JIT's unneeded uop removal pass #132333

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

brandtbucher
Copy link
Member

@brandtbucher brandtbucher commented Apr 9, 2025

This improves our ability to remove unused constant and local variable loads during the remove_unneeded_uops pass in the JIT's optimizer.

It now handles all combinations of:

  • _COPY
  • _LOAD_CONST_INLINE
  • _LOAD_CONST_INLINE_BORROW
  • _LOAD_FAST
  • _LOAD_FAST_BORROW
  • _LOAD_SMALL_INT

...followed by...

  • _POP_TOP
  • _POP_TOP_LOAD_CONST_INLINE
  • _POP_TOP_LOAD_CONST_INLINE_BORROW
  • _POP_TWO_LOAD_CONST_INLINE_BORROW

(It also fixes an issue where CHECK_VALIDITY wasn't being added after these latter four instructions, due to how the old switch-case was structured.)

According to the stats, this results in:

  • 1% reduction in _LOAD_FAST
  • 94% reduction in _POP_TOP_LOAD_CONST_INLINE_BORROW
  • 100% reduction in _POP_TOP_LOAD_CONST_INLINE

@savannahostrowski: We should see even more impact once you start using _POP_TWO_LOAD_CONST_INLINE_BORROW in more places. I'm currently working on turning basically all cached class attribute/method loads into constants too, which should help here as well.

@brandtbucher brandtbucher added performance Performance or resource usage interpreter-core (Objects, Python, Grammar, and Parser dirs) topic-JIT labels Apr 9, 2025
@brandtbucher brandtbucher self-assigned this Apr 9, 2025
Copy link
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.

I think this should be fine? optimize_pop_top_again should reach a fixpoint (there are only a finite number of last we can change to _NOP).

Copy link
Member

@markshannon markshannon left a comment

Choose a reason for hiding this comment

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

I have a few questions.
The overall design looks good.

@@ -1283,7 +1283,7 @@ class Bar:
load_attr_top = opnames.index("_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES", 0, call)
load_attr_bottom = opnames.index("_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES", call)
self.assertEqual(opnames[:load_attr_top].count("_GUARD_TYPE_VERSION"), 1)
self.assertEqual(opnames[call:load_attr_bottom].count("_CHECK_VALIDITY"), 1)
self.assertEqual(opnames[call:load_attr_bottom].count("_CHECK_VALIDITY"), 2)
Copy link
Member

Choose a reason for hiding this comment

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

Why do we have two _CHECK_VALIDITYs now?

switch (last->opcode) {
case _POP_TWO_LOAD_CONST_INLINE_BORROW:
last->opcode = _POP_TOP;
goto optimize_pop_top_again;
Copy link
Member

Choose a reason for hiding this comment

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

Do we want to optimize again here?
If the previous instruction is _POP_TOP I see no further optimization to apply here.

last->opcode = _NOP;
buffer[pc].opcode = _NOP;
}
if (last->opcode == _REPLACE_WITH_TRUE) {
Copy link
Member

Choose a reason for hiding this comment

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

Are we not optimizing this any more? I would have thought it would go in the same case as _POP_TOP_LOAD_CONST_INLINE_BORROW.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting merge interpreter-core (Objects, Python, Grammar, and Parser dirs) performance Performance or resource usage topic-JIT
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants