Skip to content

Commit 97889f5

Browse files
eendebakptclaude
andcommitted
Mark results of float-producing _BINARY_OP as unique
Operations that always return a new float (true division, float**int, int**negative_int, mixed int/float arithmetic) now mark their result as PyJitRef_MakeUnique. This enables downstream operations to mutate the result in place instead of allocating a new float. Int results are NOT marked unique because small ints are cached/immortal. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent c846269 commit 97889f5

File tree

2 files changed

+13
-19
lines changed

2 files changed

+13
-19
lines changed

Python/optimizer_bytecodes.c

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -254,40 +254,37 @@ dummy_func(void) {
254254
bool rhs_int = sym_matches_type(rhs, &PyLong_Type);
255255
bool lhs_float = sym_matches_type(lhs, &PyFloat_Type);
256256
bool rhs_float = sym_matches_type(rhs, &PyFloat_Type);
257-
// Specialize float/float true division in tier 2.
258-
// We insert guards for operands not yet known to be float.
257+
// Specialize inplace float/float true division in tier 2.
258+
// Only enter when we can emit an inplace op (one operand is unique).
259+
// Guards are inserted for operands not yet known to be float.
259260
if ((oparg == NB_TRUE_DIVIDE || oparg == NB_INPLACE_TRUE_DIVIDE)
260-
&& (lhs_float || rhs_float)) {
261+
&& (lhs_float || rhs_float)
262+
&& (PyJitRef_IsUnique(lhs) || PyJitRef_IsUnique(rhs))) {
261263
if (!rhs_float) {
262264
ADD_OP(_GUARD_TOS_FLOAT, 0, 0);
263265
sym_set_type(rhs, &PyFloat_Type);
264-
rhs_float = true;
265266
}
266267
if (!lhs_float) {
267268
ADD_OP(_GUARD_NOS_FLOAT, 0, 0);
268269
sym_set_type(lhs, &PyFloat_Type);
269-
lhs_float = true;
270270
}
271271
if (PyJitRef_IsUnique(lhs)) {
272272
ADD_OP(_BINARY_OP_TRUEDIV_FLOAT_INPLACE, 0, 0);
273273
l = sym_new_null(ctx);
274274
r = rhs;
275275
}
276-
else if (PyJitRef_IsUnique(rhs)) {
276+
else {
277277
ADD_OP(_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT, 0, 0);
278278
l = lhs;
279279
r = sym_new_null(ctx);
280280
}
281-
else {
282-
// Neither operand is unique — keep as generic _BINARY_OP.
283-
// Type and uniqueness are still set so downstream ops benefit.
284-
}
285281
res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type));
286282
}
287283
else if (oparg == NB_TRUE_DIVIDE || oparg == NB_INPLACE_TRUE_DIVIDE) {
288284
// True division always returns a new float, regardless of operand
289-
// types. Mark as unique so downstream ops can mutate it in place.
290-
res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type));
285+
// types. Set type for downstream ops. Don't mark unique here —
286+
// the generic _BINARY_OP handles its own l/r outputs.
287+
res = sym_new_type(ctx, &PyFloat_Type);
291288
}
292289
else if (!((lhs_int || lhs_float) && (rhs_int || rhs_float))) {
293290
// There's something other than an int or float involved:

Python/optimizer_cases.c.h

Lines changed: 4 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)