Skip to content

Commit c8f860f

Browse files
eendebakptclaude
andcommitted
Use sym_new_null for consumed operand slots in inplace float ops
The inplace ops set l or r to PyStackRef_NULL at runtime, so the optimizer should model this as sym_new_null(ctx) rather than PyJitRef_Borrow(). Both produce _POP_TOP_NOP but sym_new_null correctly matches the runtime semantics. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 7bfdedb commit c8f860f

File tree

5 files changed

+52
-56
lines changed

5 files changed

+52
-56
lines changed

Include/internal/pycore_uop_metadata.h

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

Python/bytecodes.c

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -785,13 +785,12 @@ dummy_func(
785785
macro(BINARY_OP_SUBTRACT_FLOAT) =
786786
_GUARD_TOS_FLOAT + _GUARD_NOS_FLOAT + unused/5 + _BINARY_OP_SUBTRACT_FLOAT + _POP_TOP_FLOAT + _POP_TOP_FLOAT;
787787

788-
// Inplace float ops: mutate the uniquely-referenced left operand
788+
// Inplace float ops: mutate the uniquely-referenced operand
789789
// instead of allocating a new float. Tier 2 only.
790-
// The optimizer sets l to null so the following _POP_TOP_FLOAT
791-
// becomes _POP_TOP_NOP.
792790
// Note: read into a local double and write back to avoid compound
793791
// assignment (+=) on ob_fval, which generates problematic JIT
794792
// stencils on i686-pc-windows-msvc.
793+
795794
tier2 op(_BINARY_OP_ADD_FLOAT_INPLACE, (left, right -- res, l, r)) {
796795
PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
797796
PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
@@ -801,12 +800,10 @@ dummy_func(
801800
STAT_INC(BINARY_OP, hit);
802801
double dres = ((PyFloatObject *)left_o)->ob_fval + ((PyFloatObject *)right_o)->ob_fval;
803802
((PyFloatObject *)left_o)->ob_fval = dres;
804-
// Transfer ownership of left to res.
805-
// Original left is now dead.
806803
res = left;
804+
INPUTS_DEAD();
807805
l = PyStackRef_NULL;
808806
r = right;
809-
INPUTS_DEAD();
810807
}
811808

812809
tier2 op(_BINARY_OP_SUBTRACT_FLOAT_INPLACE, (left, right -- res, l, r)) {
@@ -819,9 +816,9 @@ dummy_func(
819816
double dres = ((PyFloatObject *)left_o)->ob_fval - ((PyFloatObject *)right_o)->ob_fval;
820817
((PyFloatObject *)left_o)->ob_fval = dres;
821818
res = left;
819+
INPUTS_DEAD();
822820
l = PyStackRef_NULL;
823821
r = right;
824-
INPUTS_DEAD();
825822
}
826823

827824
tier2 op(_BINARY_OP_MULTIPLY_FLOAT_INPLACE, (left, right -- res, l, r)) {
@@ -834,12 +831,11 @@ dummy_func(
834831
double dres = ((PyFloatObject *)left_o)->ob_fval * ((PyFloatObject *)right_o)->ob_fval;
835832
((PyFloatObject *)left_o)->ob_fval = dres;
836833
res = left;
834+
INPUTS_DEAD();
837835
l = PyStackRef_NULL;
838836
r = right;
839-
INPUTS_DEAD();
840837
}
841838

842-
// Inplace RIGHT variants: mutate the uniquely-referenced right operand.
843839
tier2 op(_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT, (left, right -- res, l, r)) {
844840
PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
845841
PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
@@ -850,39 +846,39 @@ dummy_func(
850846
double dres = ((PyFloatObject *)left_o)->ob_fval + ((PyFloatObject *)right_o)->ob_fval;
851847
((PyFloatObject *)right_o)->ob_fval = dres;
852848
res = right;
849+
INPUTS_DEAD();
853850
l = left;
854851
r = PyStackRef_NULL;
855-
INPUTS_DEAD();
856852
}
857853

858-
tier2 op(_BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT, (left, right -- res, l, r)) {
854+
tier2 op(_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT, (left, right -- res, l, r)) {
859855
PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
860856
PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
861857
assert(PyFloat_CheckExact(left_o));
862858
assert(PyFloat_CheckExact(right_o));
863859
assert(_PyObject_IsUniquelyReferenced(right_o));
864860
STAT_INC(BINARY_OP, hit);
865-
double dres = ((PyFloatObject *)left_o)->ob_fval * ((PyFloatObject *)right_o)->ob_fval;
861+
double dres = ((PyFloatObject *)left_o)->ob_fval - ((PyFloatObject *)right_o)->ob_fval;
866862
((PyFloatObject *)right_o)->ob_fval = dres;
867863
res = right;
864+
INPUTS_DEAD();
868865
l = left;
869866
r = PyStackRef_NULL;
870-
INPUTS_DEAD();
871867
}
872868

873-
tier2 op(_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT, (left, right -- res, l, r)) {
869+
tier2 op(_BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT, (left, right -- res, l, r)) {
874870
PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
875871
PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
876872
assert(PyFloat_CheckExact(left_o));
877873
assert(PyFloat_CheckExact(right_o));
878874
assert(_PyObject_IsUniquelyReferenced(right_o));
879875
STAT_INC(BINARY_OP, hit);
880-
double dres = ((PyFloatObject *)left_o)->ob_fval - ((PyFloatObject *)right_o)->ob_fval;
876+
double dres = ((PyFloatObject *)left_o)->ob_fval * ((PyFloatObject *)right_o)->ob_fval;
881877
((PyFloatObject *)right_o)->ob_fval = dres;
882878
res = right;
879+
INPUTS_DEAD();
883880
l = left;
884881
r = PyStackRef_NULL;
885-
INPUTS_DEAD();
886882
}
887883

888884
pure op(_BINARY_OP_ADD_UNICODE, (left, right -- res, l, r)) {

Python/executor_cases.c.h

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

Python/optimizer_bytecodes.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -327,13 +327,13 @@ dummy_func(void) {
327327
op(_BINARY_OP_ADD_FLOAT, (left, right -- res, l, r)) {
328328
if (PyJitRef_IsUnique(left)) {
329329
ADD_OP(_BINARY_OP_ADD_FLOAT_INPLACE, 0, 0);
330-
l = PyJitRef_Borrow(left);
330+
l = sym_new_null(ctx);
331331
r = right;
332332
}
333333
else if (PyJitRef_IsUnique(right)) {
334334
ADD_OP(_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT, 0, 0);
335335
l = left;
336-
r = PyJitRef_Borrow(right);
336+
r = sym_new_null(ctx);
337337
}
338338
else {
339339
l = left;
@@ -345,13 +345,13 @@ dummy_func(void) {
345345
op(_BINARY_OP_SUBTRACT_FLOAT, (left, right -- res, l, r)) {
346346
if (PyJitRef_IsUnique(left)) {
347347
ADD_OP(_BINARY_OP_SUBTRACT_FLOAT_INPLACE, 0, 0);
348-
l = PyJitRef_Borrow(left);
348+
l = sym_new_null(ctx);
349349
r = right;
350350
}
351351
else if (PyJitRef_IsUnique(right)) {
352352
ADD_OP(_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT, 0, 0);
353353
l = left;
354-
r = PyJitRef_Borrow(right);
354+
r = sym_new_null(ctx);
355355
}
356356
else {
357357
l = left;
@@ -363,13 +363,13 @@ dummy_func(void) {
363363
op(_BINARY_OP_MULTIPLY_FLOAT, (left, right -- res, l, r)) {
364364
if (PyJitRef_IsUnique(left)) {
365365
ADD_OP(_BINARY_OP_MULTIPLY_FLOAT_INPLACE, 0, 0);
366-
l = PyJitRef_Borrow(left);
366+
l = sym_new_null(ctx);
367367
r = right;
368368
}
369369
else if (PyJitRef_IsUnique(right)) {
370370
ADD_OP(_BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT, 0, 0);
371371
l = left;
372-
r = PyJitRef_Borrow(right);
372+
r = sym_new_null(ctx);
373373
}
374374
else {
375375
l = left;

Python/optimizer_cases.c.h

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

0 commit comments

Comments
 (0)