Skip to content

Commit 637803c

Browse files
eendebakptclaude
andcommitted
Fix JIT stencil compilation on i686-pc-windows-msvc
Avoid compound assignment (+=, -=, *=) directly on ob_fval in inplace float ops. On 32-bit Windows, this generates JIT stencils with _xmm register references that MSVC cannot parse. Instead, read into a local double, compute, and write back. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 42d12b7 commit 637803c

File tree

2 files changed

+60
-32
lines changed

2 files changed

+60
-32
lines changed

Python/bytecodes.c

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,8 @@ dummy_func(
467467
assert(PyFloat_CheckExact(val_o));
468468
assert(_PyObject_IsUniquelyReferenced(val_o));
469469
STAT_INC(UNARY_NEGATIVE, hit);
470-
((PyFloatObject *)val_o)->ob_fval = -((PyFloatObject *)val_o)->ob_fval;
470+
double dres = -((PyFloatObject *)val_o)->ob_fval;
471+
((PyFloatObject *)val_o)->ob_fval = dres;
471472
res = value;
472473
v = PyStackRef_NULL;
473474
INPUTS_DEAD();
@@ -788,14 +789,18 @@ dummy_func(
788789
// instead of allocating a new float. Tier 2 only.
789790
// The optimizer sets l to null so the following _POP_TOP_FLOAT
790791
// becomes _POP_TOP_NOP.
792+
// Note: read into a local double and write back to avoid compound
793+
// assignment (+=) on ob_fval, which generates problematic JIT
794+
// stencils on i686-pc-windows-msvc.
791795
tier2 op(_BINARY_OP_ADD_FLOAT_INPLACE, (left, right -- res, l, r)) {
792796
PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
793797
PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
794798
assert(PyFloat_CheckExact(left_o));
795799
assert(PyFloat_CheckExact(right_o));
796800
assert(_PyObject_IsUniquelyReferenced(left_o));
797801
STAT_INC(BINARY_OP, hit);
798-
((PyFloatObject *)left_o)->ob_fval += ((PyFloatObject *)right_o)->ob_fval;
802+
double dres = ((PyFloatObject *)left_o)->ob_fval + ((PyFloatObject *)right_o)->ob_fval;
803+
((PyFloatObject *)left_o)->ob_fval = dres;
799804
res = left;
800805
l = PyStackRef_NULL;
801806
r = right;
@@ -809,7 +814,8 @@ dummy_func(
809814
assert(PyFloat_CheckExact(right_o));
810815
assert(_PyObject_IsUniquelyReferenced(left_o));
811816
STAT_INC(BINARY_OP, hit);
812-
((PyFloatObject *)left_o)->ob_fval -= ((PyFloatObject *)right_o)->ob_fval;
817+
double dres = ((PyFloatObject *)left_o)->ob_fval - ((PyFloatObject *)right_o)->ob_fval;
818+
((PyFloatObject *)left_o)->ob_fval = dres;
813819
res = left;
814820
l = PyStackRef_NULL;
815821
r = right;
@@ -823,23 +829,24 @@ dummy_func(
823829
assert(PyFloat_CheckExact(right_o));
824830
assert(_PyObject_IsUniquelyReferenced(left_o));
825831
STAT_INC(BINARY_OP, hit);
826-
((PyFloatObject *)left_o)->ob_fval *= ((PyFloatObject *)right_o)->ob_fval;
832+
double dres = ((PyFloatObject *)left_o)->ob_fval * ((PyFloatObject *)right_o)->ob_fval;
833+
((PyFloatObject *)left_o)->ob_fval = dres;
827834
res = left;
828835
l = PyStackRef_NULL;
829836
r = right;
830837
INPUTS_DEAD();
831838
}
832839

833-
// Inplace RIGHT variants for commutative ops (add, multiply).
834-
// Mutate the uniquely-referenced right operand instead.
840+
// Inplace RIGHT variants: mutate the uniquely-referenced right operand.
835841
tier2 op(_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT, (left, right -- res, l, r)) {
836842
PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
837843
PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
838844
assert(PyFloat_CheckExact(left_o));
839845
assert(PyFloat_CheckExact(right_o));
840846
assert(_PyObject_IsUniquelyReferenced(right_o));
841847
STAT_INC(BINARY_OP, hit);
842-
((PyFloatObject *)right_o)->ob_fval += ((PyFloatObject *)left_o)->ob_fval;
848+
double dres = ((PyFloatObject *)left_o)->ob_fval + ((PyFloatObject *)right_o)->ob_fval;
849+
((PyFloatObject *)right_o)->ob_fval = dres;
843850
res = right;
844851
l = left;
845852
r = PyStackRef_NULL;
@@ -853,23 +860,23 @@ dummy_func(
853860
assert(PyFloat_CheckExact(right_o));
854861
assert(_PyObject_IsUniquelyReferenced(right_o));
855862
STAT_INC(BINARY_OP, hit);
856-
((PyFloatObject *)right_o)->ob_fval *= ((PyFloatObject *)left_o)->ob_fval;
863+
double dres = ((PyFloatObject *)left_o)->ob_fval * ((PyFloatObject *)right_o)->ob_fval;
864+
((PyFloatObject *)right_o)->ob_fval = dres;
857865
res = right;
858866
l = left;
859867
r = PyStackRef_NULL;
860868
INPUTS_DEAD();
861869
}
862870

863-
// Inplace RIGHT variant for subtract (non-commutative):
864-
// right->ob_fval = left->ob_fval - right->ob_fval
865871
tier2 op(_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT, (left, right -- res, l, r)) {
866872
PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
867873
PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
868874
assert(PyFloat_CheckExact(left_o));
869875
assert(PyFloat_CheckExact(right_o));
870876
assert(_PyObject_IsUniquelyReferenced(right_o));
871877
STAT_INC(BINARY_OP, hit);
872-
((PyFloatObject *)right_o)->ob_fval = ((PyFloatObject *)left_o)->ob_fval - ((PyFloatObject *)right_o)->ob_fval;
878+
double dres = ((PyFloatObject *)left_o)->ob_fval - ((PyFloatObject *)right_o)->ob_fval;
879+
((PyFloatObject *)right_o)->ob_fval = dres;
873880
res = right;
874881
l = left;
875882
r = PyStackRef_NULL;

Python/executor_cases.c.h

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

0 commit comments

Comments
 (0)