Skip to content

Prototype: a generic dispatch opcode to bring tier-2 specializations into tier 1 - #161240

Closed
eendebakpt wants to merge 2 commits into
python:mainfrom
eendebakpt:binary-op-inplace-kindop
Closed

eendebakpt wants to merge 2 commits into
python:mainfrom
eendebakpt:binary-op-inplace-kindop

Conversation

@eendebakpt

Copy link
Copy Markdown
Contributor

No description provided.

eendebakpt and others added 2 commits November 3, 2026 09:49
Specializations marked `kind_op` in bytecodes.c get no opcode of their
own. The cases generator emits them as cases of a single KIND_OP
instruction, numbers them, and generates the tables that map a kind back
to its family's generic instruction, its name and its tier-2 expansion.
Each kind keeps the cache layout of its family, so the instruction length
and the cache entries after the first are what the generic instruction
uses. A `kind_candidate` annotation marks a specialization that is folded
only when the generator runs with KIND_OPS=2, so the number of real
opcodes is a one-word choice per specialization.

The kind lives in the first cache entry, in the high bits of the adaptive
counter's value field, next to a six-bit miss counter. A failed guard
re-executes the generic instruction, whose ADVANCE_ADAPTIVE_COUNTER counts
the miss down; when the misses run out the instruction returns to its
adaptive form with a triggering counter and re-specializes on the operands
that missed, the same life cycle as an ordinary specialized instruction.

Pseudo-opcodes `NAME = 512 + KIND_NAME` keep `specialize(instr, NAME)`
call sites unchanged. Instrumentation, _Py_GetBaseCodeUnit, unspecialize,
the tier-2 trace translator and dis map KIND_OP through its kind, and
test_opcache recognizes kinds by the name dis prints.

Two kinds come with the mechanism:

- BINARY_OP_INPLACE: in-place float and compact-int arithmetic, including
  float true division, when one operand is a uniquely referenced temporary
- TO_BOOL_SIZED: truthiness of dict, tuple and set read from the size field

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Eleven kinds, all tier-1 counterparts of existing tier-2 uops or of open
specialization proposals:

- UNARY_NEGATIVE_INPLACE: negate a uniquely referenced float in place
  (UNARY_NEGATIVE gains an inline cache)
- BINARY_OP_TRUEDIV_FLOAT: float / float when the operands are shared
- BINARY_OP_FLOOR_DIVIDE_INT, BINARY_OP_REMAINDER_INT: compact ints,
  nonzero divisor, floor semantics
- BINARY_OP_LSHIFT_INT, BINARY_OP_RSHIFT_INT: compact ints, shift count
  within range
- BINARY_OP_SUBSCR_BYTES_INT, BINARY_OP_SUBSCR_BYTEARRAY_INT,
  STORE_SUBSCR_BYTEARRAY_INT: byte access with a compact in-range index
- UNPACK_SEQUENCE_STEAL_TWO_TUPLE, UNPACK_SEQUENCE_STEAL_TUPLE: a tuple
  referenced only from the stack gives up its items without refcount
  traffic; a shared tuple takes the increfing path

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@eendebakpt eendebakpt closed this Nov 3, 2026
@eendebakpt
eendebakpt deleted the binary-op-inplace-kindop branch November 3, 2026 18:07
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.

1 participant