Repository navigation
Eliminate redundant refcounting in the JIT #134584
Description
Feature or enhancement
Proposal:
Thanks to Matt's work on borrowed LOAD_FAST, we can now eliminate reference counting trivially in the JIT.
Reference counting is expensive, Matt found that eliminating 90% of refcounts in LOAD_FAST meant a 2-3% speedup in the interpreter. So the speedup for the JIT should be quite a bit too.
The other problem is that reference counts block register allocation/TOS caching. As they force spills to the stack more often.
This issue has the potential to speedup up JIT benchmarks by several percent.
How to contribute.
Now that reference tracking in the JIT optimizer is in place, the first thing we need to do is to convert ops to make the decref an explicit uop.
For escaping decref ops (ie, ops that decref could run the GC), we would need to refactor them so their decrefs are eliminated via specialization of pops. For example: the following op (which is not an escaping op, but just purely for demonstration!):
macro(BINARY_OP_ADD_INT) =
_GUARD_TOS_INT + _GUARD_NOS_INT + unused/5 + _BINARY_OP_ADD_INT;
becomes
macro(BINARY_OP_ADD_INT) =
_GUARD_TOS_INT + _GUARD_NOS_INT + unused/5 + _BINARY_OP_ADD_INT + _POP_TOP_INT + _POP_TOP_INT;
Previously _BINARY_OP_ADD_INT's stack effect looked like this: (left, right -- res). The new version should look like (left, right -- res, left, right).
So for all the decref specializations, we would just need a _POP_X of their variants! This means no explosion of uop and their decref variants. We just specialize _POP_X to _POP_X_NO_DECREF in the JIT. Keeping things clean
These are open for contributors to take:
- POP_TOP @Fidget-Spinner
- STORE_FAST @Fidget-Spinner
- _BINARY_OP_X_FLOAT @Fidget-Spinner
- _BINARY_OP_X_INT @Fidget-Spinner
- _BINARY_OP_ADD_UNICODE @corona10
- _BINARY_OP_SUBSCR_LIST_INT @cocolato
- _BINARY_OP_SUBSCR_TUPLE_INT @cocolato
- _BINARY_OP_SUBSCR_STR_INT @savannahostrowski
- _BINARY_OP_SUBSCR_DICT @caje731
- _COMPARE_OP_X @cocolato
- _CALL_TYPE_1 @tomasr8
- _CALL_STR_1 @Zheaoli
- _CALL_TUPLE_1 @noamcohen97
- _CALL_BUILTIN_O @AndPuQing
- _CALL_LEN @corona10
- _CALL_LIST_APPEND
- _CALL_METHOD_DESCRIPTOR_O @corona10
- _STORE_SUBSCR_DICT @corona10
- _STORE_SUBSCR_LIST_INT @corona10
- _LOAD_ATTR_INSTANCE_VALUE @Zheaoli
- _LOAD_ATTR_WITH_HINT @cocolato
- _LOAD_ATTR_SLOT @Zheaoli
- _STORE_ATTR_INSTANCE_VALUE @Zheaoli
- _STORE_ATTR_SLOT @savannahostrowski
- _STORE_ATTR_WITH_HINT @Zheaoli
- IS_OP @cocolato
- TO_BOOL_ALWAYS_TRUE @reidenong
- TO_BOOL_INT @reidenong
- TO_BOOL_LIST @reidenong
- TO_BOOL_STR @Zheaoli
- _CONTAINS_OP @Zheaoli
- _CONTAINS_OP_SET @Zheaoli
- _CONTAINS_OP_DICT @Zheaoli
- _UNARY_NEGATIVE @Fidget-Spinner
- _UNARY_INVERT @Fidget-Spinner
Once that's done, we can think about further ops.
Has this already been discussed elsewhere?
No response given
Links to previous discussion of this feature:
No response
Linked PRs
- gh-134584: Decref elimination for float ops in the JIT #134588
- gh-134584: Specialize POP_TOP by reference and type in JIT #135761
- gh-134584: Eliminate redundant refcounting from _BINARY_OP_ADD_UNICODE #135817
- gh-134584: Eliminate redundant refcounting from
_CALL_TYPE_1#135818 - gh-134584: Eliminate redundant refcounting from
_CALL_TUPLE_1#135860 - gh-134584: Eliminate redundant refcounting from _STORE_SUBSCR_LIST_INT #135907
- gh-134584: Eliminate redundant refcounting from
_CALL_BUILTION_O#136056 - gh-134584: Eliminate redundant refcounting from
_CALL_STR_1#136070 - gh-134584: Eliminate redundant refcounting from
_CALL_ISINSTANCE#136077 - gh-134584: Eliminate redundant refcounting from
_CALL_LEN#136104 - gh-134584: Remove custom float decref ops #142576
- gh-134584: Cleanups for refcount elimination #135860 #142604
- gh-134584: Revert partially #135860 #142620
- gh-134584: Eliminate redundant refcounting from
_CALL_BUILTIN_O#142695 - gh-134584: Eliminate redundant refcounting from _STORE_SUBSCR_LIST_INT #142703
- gh-134584: Eliminate redundant refcounting from _CALL_LIST_APPEND #142711
- gh-134584: Eliminate redundant refcounting from _STORE_SUBSCR_DICT #142712
- GH-134584: Remove redundant refcount from
_STORE_ATTR_SLOT#142729 - gh-134584: Eliminate redundant refcounting from
_STORE_ATTR_INSTANCE_VALUE#142759 - gh-134584: JIT: Eliminate redundant refcount ops for X_INT #142765
- gh-134584: Eliminate redundant refcounting from
_STORE_ATTR_WITH_HINT#142767 - gh-134584: Eliminate redundant refcounting from
_LOAD_ATTR_INSTANCE_VALUE#142769 - gh-134584: Remove redundant refcount from _BINARY_OP_ADD_UNICODE #142825
- GH-134584: Remove redundant refcount for
BINARY_OP_SUBSCR_STR_INT#142844 - gh-134584: JIT: Borrow references for immortal promoted globals #142921
- gh-134584: Eliminate redundant refcounting from _BINARY_OP_SUBSCR_LIST_INT #142926
- gh-134584:Eliminate redundant refcounting from
UNPACK_SEQUENCEfamily #142949 - gh-134584: Eliminate redundant refcounting from
_UNPACK_SEQUENCE_TWO_TUPLE#142952 - gh-134584: Eliminate redundant refcounting from
_LOAD_ATTR_WITH_HINT#143062 - gh-134584: Eliminate redundant refcounting from
_BINARY_OP_SUBSCR_TUPLE_INT#143094 - gh-134584: Add another contributor to whats new 3.15 #143107
- gh-134584: Eliminate redundant refcounting from
IS_OP#143171 - gh-134584: Eliminate redundant refcounting from
_COMPARE_OP_X#143186 - gh-134584: Eliminate redundant refcounting from
_LOAD_ATTR_SLOT#143320 - gh-134584: Eliminate redundant refcounting from _CALL{_BUILTIN_O, _METHOD_DESCRIPTOR_O} #143330
- gh-134584: Fix _CALL_BUILTIN_O test to reflect real-world usage #143333
- gh-134584: JIT: Remove redundant refcount from STORE_FAST #143336
- gh-134584: Eliminate redundant refcounting from
TO_BOOL_STR#143417 - gh-134584: Eliminate redundant refcounting in TO_BOOL_ALWAYS_TRUE #143427
- gh-134584: JIT: Remove redundant refcounting for UNARY_{INVERT|NEGATIVE} #143704
- gh-134584: Remove redundant refcount for _BINARY_OP_SUBSCR_DICT #143724
- gh-134584: Eliminate redundant refcounting from
_CONTAINS_{OP|OP_SET|OP_DICT}#143731 - gh-134584: Eliminate redundant refcounting in TO_BOOL_INT, TO_BOOL_LIST #143759
- gh-134584: Add more contributors for JIT refcounting work #143760
- gh-134584: Eliminate redundant refcounting from BINARY_SLICE #144596
- gh-134584: Optimize
_BINARY_OP_SUBSCR_LIST_SLICE#144659 - gh-134584: Eliminate redundant refcounting in JIT for
MATCH_CLASS#144821 - gh-134584 : Optimize and eliminate redundant ref-counting for
MAKE_FUNCTIONin the JIT #144963
Activity
Fidget-Spinner commentedon May 23, 2025
@tomasr8 @brandtbucher this is gonna be a pretty sweet optimization :)
Before:
After:
gh-134584: Decref elimination for float ops in the JIT (GH-134588)
pythongh-134584: Decref elimination for float ops in the JIT (pythonG…
pythongh-134584: Elimiate redundant refcounting from _BINARY_OP_X_UNI…
gh-134584: Specialize POP_TOP by reference and type in JIT (GH-135761)
Merge remote-tracking branch 'upstream/main' into pythongh-134584-uni…
Zheaoli commentedon Jun 23, 2025
FYI here #131798 (comment)
100% want to take a part into this issue. BTW I may need a little bit time to read the whole context and the previous PR made by others.
So maybe I will send the first PR in this weekend. If this is acceptable, 100% want to join into this
Fidget-Spinner commentedon Jun 23, 2025
@Zheaoli and anyone else reading this thread who wants to contribute. No worries, I'm happy to explain and answer any questions over email or video if you want to. My email is on my GH profile.
Zheaoli commentedon Jun 23, 2025
Just for joking: This is 100% facts(lol. @Fidget-Spinner is a supper nice guy(lol
127 remaining items
pythongh-134584: JIT: Remove redundant refcount for _BINARY_OP_SUBSCR…
pythongh-134584: Eliminate redundant refcounting from `_CONTAINS_{OP|…
pythongh-134584: Eliminate redundant refcounting in TO_BOOL_INT, TO_B…
pythongh-134584: Add more contributors for JIT refcounting work (pyth…
pythongh-134584: Optimize `_BINARY_OP_SUBSCR_LIST_SLICE` (pythonGH-14…
pythongh-134584: Optimize `_BINARY_OP_SUBSCR_LIST_SLICE` (pythonGH-14…
gh-134584: Eliminate redundant refcounting in JIT for `MATCH_CLASS` (G…
gh-134584 : Optimize and eliminate redundant ref-counting for `MAKE_F…
pythongh-134584: Optimize `_BINARY_OP_SUBSCR_LIST_SLICE` (pythonGH-14…
pythongh-134584: Eliminate redundant refcounting in JIT for `MATCH_CL…
pythongh-134584 : Optimize and eliminate redundant ref-counting for `…
gh-NNNNN: Make _STORE_ATTR_SLOT lock-free on the free-threaded build
gh-NNNNN: Make _STORE_ATTR_SLOT lock-free on the free-threaded build
gh-NNNNN: Make _STORE_ATTR_SLOT lock-free on the free-threaded build
gh-NNNNN: Make _STORE_ATTR_SLOT lock-free on the free-threaded build