gh-146306: JIT: Optimize float operations by mutating uniquely-referenced operands in place (GH-146307)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Pieter Eendebak 2026-03-24 14:16:02 +01:00 committed by GitHub
parent 68c7fad757
commit 951675c18a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 2349 additions and 1231 deletions

View file

@ -460,6 +460,20 @@ dummy_func(
DEAD(value);
}
// Inplace negation: negate a uniquely-referenced float in place.
// Tier 2 only.
tier2 op(_UNARY_NEGATIVE_FLOAT_INPLACE, (value -- res, v)) {
PyObject *val_o = PyStackRef_AsPyObjectBorrow(value);
assert(PyFloat_CheckExact(val_o));
assert(_PyObject_IsUniquelyReferenced(val_o));
STAT_INC(UNARY_NEGATIVE, hit);
double dres = -((PyFloatObject *)val_o)->ob_fval;
((PyFloatObject *)val_o)->ob_fval = dres;
res = value;
v = PyStackRef_NULL;
INPUTS_DEAD();
}
inst(UNARY_NOT, (value -- res)) {
assert(PyStackRef_BoolCheck(value));
res = PyStackRef_IsFalse(value)
@ -771,6 +785,59 @@ dummy_func(
macro(BINARY_OP_SUBTRACT_FLOAT) =
_GUARD_TOS_FLOAT + _GUARD_NOS_FLOAT + unused/5 + _BINARY_OP_SUBTRACT_FLOAT + _POP_TOP_FLOAT + _POP_TOP_FLOAT;
// Inplace float ops: mutate the uniquely-referenced left operand
// instead of allocating a new float. Tier 2 only.
// The optimizer sets l to a borrowed value so the following _POP_TOP_FLOAT
// becomes _POP_TOP_NOP.
tier2 op(_BINARY_OP_ADD_FLOAT_INPLACE, (left, right -- res, l, r)) {
FLOAT_INPLACE_OP(left, right, left, +);
res = left;
l = PyStackRef_NULL;
r = right;
INPUTS_DEAD();
}
tier2 op(_BINARY_OP_SUBTRACT_FLOAT_INPLACE, (left, right -- res, l, r)) {
FLOAT_INPLACE_OP(left, right, left, -);
res = left;
l = PyStackRef_NULL;
r = right;
INPUTS_DEAD();
}
tier2 op(_BINARY_OP_MULTIPLY_FLOAT_INPLACE, (left, right -- res, l, r)) {
FLOAT_INPLACE_OP(left, right, left, *);
res = left;
l = PyStackRef_NULL;
r = right;
INPUTS_DEAD();
}
// Inplace RIGHT variants: mutate the uniquely-referenced right operand.
tier2 op(_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT, (left, right -- res, l, r)) {
FLOAT_INPLACE_OP(left, right, right, +);
res = right;
l = left;
r = PyStackRef_NULL;
INPUTS_DEAD();
}
tier2 op(_BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT, (left, right -- res, l, r)) {
FLOAT_INPLACE_OP(left, right, right, *);
res = right;
l = left;
r = PyStackRef_NULL;
INPUTS_DEAD();
}
tier2 op(_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT, (left, right -- res, l, r)) {
FLOAT_INPLACE_OP(left, right, right, -);
res = right;
l = left;
r = PyStackRef_NULL;
INPUTS_DEAD();
}
pure op(_BINARY_OP_ADD_UNICODE, (left, right -- res, l, r)) {
PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);

View file

@ -543,3 +543,22 @@ gen_try_set_executing(PyGenObject *gen)
}
return false;
}
// Macro for inplace float binary ops (tier 2 only).
// Mutates the uniquely-referenced TARGET operand in place.
// TARGET must be either left or right.
#define FLOAT_INPLACE_OP(left, right, TARGET, OP) \
do { \
PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); \
PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); \
assert(PyFloat_CheckExact(left_o)); \
assert(PyFloat_CheckExact(right_o)); \
assert(_PyObject_IsUniquelyReferenced( \
PyStackRef_AsPyObjectBorrow(TARGET))); \
STAT_INC(BINARY_OP, hit); \
double _dres = \
((PyFloatObject *)left_o)->ob_fval \
OP ((PyFloatObject *)right_o)->ob_fval; \
((PyFloatObject *)PyStackRef_AsPyObjectBorrow(TARGET)) \
->ob_fval = _dres; \
} while (0)

View file

@ -2663,6 +2663,78 @@
break;
}
case _UNARY_NEGATIVE_FLOAT_INPLACE_r02: {
CHECK_CURRENT_CACHED_VALUES(0);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef value;
_PyStackRef res;
_PyStackRef v;
value = stack_pointer[-1];
PyObject *val_o = PyStackRef_AsPyObjectBorrow(value);
assert(PyFloat_CheckExact(val_o));
assert(_PyObject_IsUniquelyReferenced(val_o));
STAT_INC(UNARY_NEGATIVE, hit);
double dres = -((PyFloatObject *)val_o)->ob_fval;
((PyFloatObject *)val_o)->ob_fval = dres;
res = value;
v = PyStackRef_NULL;
_tos_cache1 = v;
_tos_cache0 = res;
SET_CURRENT_CACHED_VALUES(2);
stack_pointer += -1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _UNARY_NEGATIVE_FLOAT_INPLACE_r12: {
CHECK_CURRENT_CACHED_VALUES(1);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef value;
_PyStackRef res;
_PyStackRef v;
_PyStackRef _stack_item_0 = _tos_cache0;
value = _stack_item_0;
PyObject *val_o = PyStackRef_AsPyObjectBorrow(value);
assert(PyFloat_CheckExact(val_o));
assert(_PyObject_IsUniquelyReferenced(val_o));
STAT_INC(UNARY_NEGATIVE, hit);
double dres = -((PyFloatObject *)val_o)->ob_fval;
((PyFloatObject *)val_o)->ob_fval = dres;
res = value;
v = PyStackRef_NULL;
_tos_cache1 = v;
_tos_cache0 = res;
SET_CURRENT_CACHED_VALUES(2);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _UNARY_NEGATIVE_FLOAT_INPLACE_r23: {
CHECK_CURRENT_CACHED_VALUES(2);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef value;
_PyStackRef res;
_PyStackRef v;
_PyStackRef _stack_item_0 = _tos_cache0;
_PyStackRef _stack_item_1 = _tos_cache1;
value = _stack_item_1;
PyObject *val_o = PyStackRef_AsPyObjectBorrow(value);
assert(PyFloat_CheckExact(val_o));
assert(_PyObject_IsUniquelyReferenced(val_o));
STAT_INC(UNARY_NEGATIVE, hit);
double dres = -((PyFloatObject *)val_o)->ob_fval;
((PyFloatObject *)val_o)->ob_fval = dres;
res = value;
v = PyStackRef_NULL;
_tos_cache2 = v;
_tos_cache1 = res;
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(3);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _UNARY_NOT_r01: {
CHECK_CURRENT_CACHED_VALUES(0);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
@ -4954,6 +5026,444 @@
break;
}
case _BINARY_OP_ADD_FLOAT_INPLACE_r03: {
CHECK_CURRENT_CACHED_VALUES(0);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef right;
_PyStackRef left;
_PyStackRef res;
_PyStackRef l;
_PyStackRef r;
right = stack_pointer[-1];
left = stack_pointer[-2];
FLOAT_INPLACE_OP(left, right, left, +);
res = left;
l = PyStackRef_NULL;
r = right;
_tos_cache2 = r;
_tos_cache1 = l;
_tos_cache0 = res;
SET_CURRENT_CACHED_VALUES(3);
stack_pointer += -2;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _BINARY_OP_ADD_FLOAT_INPLACE_r13: {
CHECK_CURRENT_CACHED_VALUES(1);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef right;
_PyStackRef left;
_PyStackRef res;
_PyStackRef l;
_PyStackRef r;
_PyStackRef _stack_item_0 = _tos_cache0;
right = _stack_item_0;
left = stack_pointer[-1];
FLOAT_INPLACE_OP(left, right, left, +);
res = left;
l = PyStackRef_NULL;
r = right;
_tos_cache2 = r;
_tos_cache1 = l;
_tos_cache0 = res;
SET_CURRENT_CACHED_VALUES(3);
stack_pointer += -1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _BINARY_OP_ADD_FLOAT_INPLACE_r23: {
CHECK_CURRENT_CACHED_VALUES(2);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef right;
_PyStackRef left;
_PyStackRef res;
_PyStackRef l;
_PyStackRef r;
_PyStackRef _stack_item_0 = _tos_cache0;
_PyStackRef _stack_item_1 = _tos_cache1;
right = _stack_item_1;
left = _stack_item_0;
FLOAT_INPLACE_OP(left, right, left, +);
res = left;
l = PyStackRef_NULL;
r = right;
_tos_cache2 = r;
_tos_cache1 = l;
_tos_cache0 = res;
SET_CURRENT_CACHED_VALUES(3);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r03: {
CHECK_CURRENT_CACHED_VALUES(0);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef right;
_PyStackRef left;
_PyStackRef res;
_PyStackRef l;
_PyStackRef r;
right = stack_pointer[-1];
left = stack_pointer[-2];
FLOAT_INPLACE_OP(left, right, left, -);
res = left;
l = PyStackRef_NULL;
r = right;
_tos_cache2 = r;
_tos_cache1 = l;
_tos_cache0 = res;
SET_CURRENT_CACHED_VALUES(3);
stack_pointer += -2;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r13: {
CHECK_CURRENT_CACHED_VALUES(1);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef right;
_PyStackRef left;
_PyStackRef res;
_PyStackRef l;
_PyStackRef r;
_PyStackRef _stack_item_0 = _tos_cache0;
right = _stack_item_0;
left = stack_pointer[-1];
FLOAT_INPLACE_OP(left, right, left, -);
res = left;
l = PyStackRef_NULL;
r = right;
_tos_cache2 = r;
_tos_cache1 = l;
_tos_cache0 = res;
SET_CURRENT_CACHED_VALUES(3);
stack_pointer += -1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r23: {
CHECK_CURRENT_CACHED_VALUES(2);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef right;
_PyStackRef left;
_PyStackRef res;
_PyStackRef l;
_PyStackRef r;
_PyStackRef _stack_item_0 = _tos_cache0;
_PyStackRef _stack_item_1 = _tos_cache1;
right = _stack_item_1;
left = _stack_item_0;
FLOAT_INPLACE_OP(left, right, left, -);
res = left;
l = PyStackRef_NULL;
r = right;
_tos_cache2 = r;
_tos_cache1 = l;
_tos_cache0 = res;
SET_CURRENT_CACHED_VALUES(3);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r03: {
CHECK_CURRENT_CACHED_VALUES(0);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef right;
_PyStackRef left;
_PyStackRef res;
_PyStackRef l;
_PyStackRef r;
right = stack_pointer[-1];
left = stack_pointer[-2];
FLOAT_INPLACE_OP(left, right, left, *);
res = left;
l = PyStackRef_NULL;
r = right;
_tos_cache2 = r;
_tos_cache1 = l;
_tos_cache0 = res;
SET_CURRENT_CACHED_VALUES(3);
stack_pointer += -2;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r13: {
CHECK_CURRENT_CACHED_VALUES(1);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef right;
_PyStackRef left;
_PyStackRef res;
_PyStackRef l;
_PyStackRef r;
_PyStackRef _stack_item_0 = _tos_cache0;
right = _stack_item_0;
left = stack_pointer[-1];
FLOAT_INPLACE_OP(left, right, left, *);
res = left;
l = PyStackRef_NULL;
r = right;
_tos_cache2 = r;
_tos_cache1 = l;
_tos_cache0 = res;
SET_CURRENT_CACHED_VALUES(3);
stack_pointer += -1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r23: {
CHECK_CURRENT_CACHED_VALUES(2);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef right;
_PyStackRef left;
_PyStackRef res;
_PyStackRef l;
_PyStackRef r;
_PyStackRef _stack_item_0 = _tos_cache0;
_PyStackRef _stack_item_1 = _tos_cache1;
right = _stack_item_1;
left = _stack_item_0;
FLOAT_INPLACE_OP(left, right, left, *);
res = left;
l = PyStackRef_NULL;
r = right;
_tos_cache2 = r;
_tos_cache1 = l;
_tos_cache0 = res;
SET_CURRENT_CACHED_VALUES(3);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r03: {
CHECK_CURRENT_CACHED_VALUES(0);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef right;
_PyStackRef left;
_PyStackRef res;
_PyStackRef l;
_PyStackRef r;
right = stack_pointer[-1];
left = stack_pointer[-2];
FLOAT_INPLACE_OP(left, right, right, +);
res = right;
l = left;
r = PyStackRef_NULL;
_tos_cache2 = r;
_tos_cache1 = l;
_tos_cache0 = res;
SET_CURRENT_CACHED_VALUES(3);
stack_pointer += -2;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r13: {
CHECK_CURRENT_CACHED_VALUES(1);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef right;
_PyStackRef left;
_PyStackRef res;
_PyStackRef l;
_PyStackRef r;
_PyStackRef _stack_item_0 = _tos_cache0;
right = _stack_item_0;
left = stack_pointer[-1];
FLOAT_INPLACE_OP(left, right, right, +);
res = right;
l = left;
r = PyStackRef_NULL;
_tos_cache2 = r;
_tos_cache1 = l;
_tos_cache0 = res;
SET_CURRENT_CACHED_VALUES(3);
stack_pointer += -1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r23: {
CHECK_CURRENT_CACHED_VALUES(2);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef right;
_PyStackRef left;
_PyStackRef res;
_PyStackRef l;
_PyStackRef r;
_PyStackRef _stack_item_0 = _tos_cache0;
_PyStackRef _stack_item_1 = _tos_cache1;
right = _stack_item_1;
left = _stack_item_0;
FLOAT_INPLACE_OP(left, right, right, +);
res = right;
l = left;
r = PyStackRef_NULL;
_tos_cache2 = r;
_tos_cache1 = l;
_tos_cache0 = res;
SET_CURRENT_CACHED_VALUES(3);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r03: {
CHECK_CURRENT_CACHED_VALUES(0);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef right;
_PyStackRef left;
_PyStackRef res;
_PyStackRef l;
_PyStackRef r;
right = stack_pointer[-1];
left = stack_pointer[-2];
FLOAT_INPLACE_OP(left, right, right, *);
res = right;
l = left;
r = PyStackRef_NULL;
_tos_cache2 = r;
_tos_cache1 = l;
_tos_cache0 = res;
SET_CURRENT_CACHED_VALUES(3);
stack_pointer += -2;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r13: {
CHECK_CURRENT_CACHED_VALUES(1);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef right;
_PyStackRef left;
_PyStackRef res;
_PyStackRef l;
_PyStackRef r;
_PyStackRef _stack_item_0 = _tos_cache0;
right = _stack_item_0;
left = stack_pointer[-1];
FLOAT_INPLACE_OP(left, right, right, *);
res = right;
l = left;
r = PyStackRef_NULL;
_tos_cache2 = r;
_tos_cache1 = l;
_tos_cache0 = res;
SET_CURRENT_CACHED_VALUES(3);
stack_pointer += -1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r23: {
CHECK_CURRENT_CACHED_VALUES(2);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef right;
_PyStackRef left;
_PyStackRef res;
_PyStackRef l;
_PyStackRef r;
_PyStackRef _stack_item_0 = _tos_cache0;
_PyStackRef _stack_item_1 = _tos_cache1;
right = _stack_item_1;
left = _stack_item_0;
FLOAT_INPLACE_OP(left, right, right, *);
res = right;
l = left;
r = PyStackRef_NULL;
_tos_cache2 = r;
_tos_cache1 = l;
_tos_cache0 = res;
SET_CURRENT_CACHED_VALUES(3);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r03: {
CHECK_CURRENT_CACHED_VALUES(0);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef right;
_PyStackRef left;
_PyStackRef res;
_PyStackRef l;
_PyStackRef r;
right = stack_pointer[-1];
left = stack_pointer[-2];
FLOAT_INPLACE_OP(left, right, right, -);
res = right;
l = left;
r = PyStackRef_NULL;
_tos_cache2 = r;
_tos_cache1 = l;
_tos_cache0 = res;
SET_CURRENT_CACHED_VALUES(3);
stack_pointer += -2;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r13: {
CHECK_CURRENT_CACHED_VALUES(1);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef right;
_PyStackRef left;
_PyStackRef res;
_PyStackRef l;
_PyStackRef r;
_PyStackRef _stack_item_0 = _tos_cache0;
right = _stack_item_0;
left = stack_pointer[-1];
FLOAT_INPLACE_OP(left, right, right, -);
res = right;
l = left;
r = PyStackRef_NULL;
_tos_cache2 = r;
_tos_cache1 = l;
_tos_cache0 = res;
SET_CURRENT_CACHED_VALUES(3);
stack_pointer += -1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r23: {
CHECK_CURRENT_CACHED_VALUES(2);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef right;
_PyStackRef left;
_PyStackRef res;
_PyStackRef l;
_PyStackRef r;
_PyStackRef _stack_item_0 = _tos_cache0;
_PyStackRef _stack_item_1 = _tos_cache1;
right = _stack_item_1;
left = _stack_item_0;
FLOAT_INPLACE_OP(left, right, right, -);
res = right;
l = left;
r = PyStackRef_NULL;
_tos_cache2 = r;
_tos_cache1 = l;
_tos_cache0 = res;
SET_CURRENT_CACHED_VALUES(3);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _BINARY_OP_ADD_UNICODE_r03: {
CHECK_CURRENT_CACHED_VALUES(0);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());

View file

@ -325,21 +325,57 @@ dummy_func(void) {
}
op(_BINARY_OP_ADD_FLOAT, (left, right -- res, l, r)) {
res = sym_new_type(ctx, &PyFloat_Type);
l = left;
r = right;
if (PyJitRef_IsUnique(left)) {
ADD_OP(_BINARY_OP_ADD_FLOAT_INPLACE, 0, 0);
l = PyJitRef_Borrow(sym_new_null(ctx));
r = right;
}
else if (PyJitRef_IsUnique(right)) {
ADD_OP(_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT, 0, 0);
l = left;
r = PyJitRef_Borrow(sym_new_null(ctx));
}
else {
l = left;
r = right;
}
res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type));
}
op(_BINARY_OP_SUBTRACT_FLOAT, (left, right -- res, l, r)) {
res = sym_new_type(ctx, &PyFloat_Type);
l = left;
r = right;
if (PyJitRef_IsUnique(left)) {
ADD_OP(_BINARY_OP_SUBTRACT_FLOAT_INPLACE, 0, 0);
l = PyJitRef_Borrow(sym_new_null(ctx));
r = right;
}
else if (PyJitRef_IsUnique(right)) {
ADD_OP(_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT, 0, 0);
l = left;
r = PyJitRef_Borrow(sym_new_null(ctx));
}
else {
l = left;
r = right;
}
res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type));
}
op(_BINARY_OP_MULTIPLY_FLOAT, (left, right -- res, l, r)) {
res = sym_new_type(ctx, &PyFloat_Type);
l = left;
r = right;
if (PyJitRef_IsUnique(left)) {
ADD_OP(_BINARY_OP_MULTIPLY_FLOAT_INPLACE, 0, 0);
l = PyJitRef_Borrow(sym_new_null(ctx));
r = right;
}
else if (PyJitRef_IsUnique(right)) {
ADD_OP(_BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT, 0, 0);
l = left;
r = PyJitRef_Borrow(sym_new_null(ctx));
}
else {
l = left;
r = right;
}
res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type));
}
op(_BINARY_OP_ADD_UNICODE, (left, right -- res, l, r)) {
@ -531,7 +567,12 @@ dummy_func(void) {
op(_UNARY_NEGATIVE, (value -- res, v)) {
v = value;
REPLACE_OPCODE_IF_EVALUATES_PURE(value, res);
if (sym_is_compact_int(value)) {
if (sym_matches_type(value, &PyFloat_Type) && PyJitRef_IsUnique(value)) {
ADD_OP(_UNARY_NEGATIVE_FLOAT_INPLACE, 0, 0);
v = PyJitRef_Borrow(sym_new_null(ctx));
res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type));
}
else if (sym_is_compact_int(value)) {
res = sym_new_compact_int(ctx);
}
else {

View file

@ -257,7 +257,12 @@
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
break;
}
if (sym_is_compact_int(value)) {
if (sym_matches_type(value, &PyFloat_Type) && PyJitRef_IsUnique(value)) {
ADD_OP(_UNARY_NEGATIVE_FLOAT_INPLACE, 0, 0);
v = PyJitRef_Borrow(sym_new_null(ctx));
res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type));
}
else if (sym_is_compact_int(value)) {
res = sym_new_compact_int(ctx);
}
else {
@ -277,6 +282,19 @@
break;
}
case _UNARY_NEGATIVE_FLOAT_INPLACE: {
JitOptRef res;
JitOptRef v;
res = sym_new_not_null(ctx);
v = sym_new_not_null(ctx);
CHECK_STACK_BOUNDS(1);
stack_pointer[-1] = res;
stack_pointer[0] = v;
stack_pointer += 1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
break;
}
case _UNARY_NOT: {
JitOptRef value;
JitOptRef res;
@ -790,9 +808,21 @@
JitOptRef r;
right = stack_pointer[-1];
left = stack_pointer[-2];
res = sym_new_type(ctx, &PyFloat_Type);
l = left;
r = right;
if (PyJitRef_IsUnique(left)) {
ADD_OP(_BINARY_OP_MULTIPLY_FLOAT_INPLACE, 0, 0);
l = PyJitRef_Borrow(sym_new_null(ctx));
r = right;
}
else if (PyJitRef_IsUnique(right)) {
ADD_OP(_BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT, 0, 0);
l = left;
r = PyJitRef_Borrow(sym_new_null(ctx));
}
else {
l = left;
r = right;
}
res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type));
CHECK_STACK_BOUNDS(1);
stack_pointer[-2] = res;
stack_pointer[-1] = l;
@ -810,9 +840,21 @@
JitOptRef r;
right = stack_pointer[-1];
left = stack_pointer[-2];
res = sym_new_type(ctx, &PyFloat_Type);
l = left;
r = right;
if (PyJitRef_IsUnique(left)) {
ADD_OP(_BINARY_OP_ADD_FLOAT_INPLACE, 0, 0);
l = PyJitRef_Borrow(sym_new_null(ctx));
r = right;
}
else if (PyJitRef_IsUnique(right)) {
ADD_OP(_BINARY_OP_ADD_FLOAT_INPLACE_RIGHT, 0, 0);
l = left;
r = PyJitRef_Borrow(sym_new_null(ctx));
}
else {
l = left;
r = right;
}
res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type));
CHECK_STACK_BOUNDS(1);
stack_pointer[-2] = res;
stack_pointer[-1] = l;
@ -830,9 +872,117 @@
JitOptRef r;
right = stack_pointer[-1];
left = stack_pointer[-2];
res = sym_new_type(ctx, &PyFloat_Type);
l = left;
r = right;
if (PyJitRef_IsUnique(left)) {
ADD_OP(_BINARY_OP_SUBTRACT_FLOAT_INPLACE, 0, 0);
l = PyJitRef_Borrow(sym_new_null(ctx));
r = right;
}
else if (PyJitRef_IsUnique(right)) {
ADD_OP(_BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT, 0, 0);
l = left;
r = PyJitRef_Borrow(sym_new_null(ctx));
}
else {
l = left;
r = right;
}
res = PyJitRef_MakeUnique(sym_new_type(ctx, &PyFloat_Type));
CHECK_STACK_BOUNDS(1);
stack_pointer[-2] = res;
stack_pointer[-1] = l;
stack_pointer[0] = r;
stack_pointer += 1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
break;
}
case _BINARY_OP_ADD_FLOAT_INPLACE: {
JitOptRef res;
JitOptRef l;
JitOptRef r;
res = sym_new_not_null(ctx);
l = sym_new_not_null(ctx);
r = sym_new_not_null(ctx);
CHECK_STACK_BOUNDS(1);
stack_pointer[-2] = res;
stack_pointer[-1] = l;
stack_pointer[0] = r;
stack_pointer += 1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
break;
}
case _BINARY_OP_SUBTRACT_FLOAT_INPLACE: {
JitOptRef res;
JitOptRef l;
JitOptRef r;
res = sym_new_not_null(ctx);
l = sym_new_not_null(ctx);
r = sym_new_not_null(ctx);
CHECK_STACK_BOUNDS(1);
stack_pointer[-2] = res;
stack_pointer[-1] = l;
stack_pointer[0] = r;
stack_pointer += 1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
break;
}
case _BINARY_OP_MULTIPLY_FLOAT_INPLACE: {
JitOptRef res;
JitOptRef l;
JitOptRef r;
res = sym_new_not_null(ctx);
l = sym_new_not_null(ctx);
r = sym_new_not_null(ctx);
CHECK_STACK_BOUNDS(1);
stack_pointer[-2] = res;
stack_pointer[-1] = l;
stack_pointer[0] = r;
stack_pointer += 1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
break;
}
case _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT: {
JitOptRef res;
JitOptRef l;
JitOptRef r;
res = sym_new_not_null(ctx);
l = sym_new_not_null(ctx);
r = sym_new_not_null(ctx);
CHECK_STACK_BOUNDS(1);
stack_pointer[-2] = res;
stack_pointer[-1] = l;
stack_pointer[0] = r;
stack_pointer += 1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
break;
}
case _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT: {
JitOptRef res;
JitOptRef l;
JitOptRef r;
res = sym_new_not_null(ctx);
l = sym_new_not_null(ctx);
r = sym_new_not_null(ctx);
CHECK_STACK_BOUNDS(1);
stack_pointer[-2] = res;
stack_pointer[-1] = l;
stack_pointer[0] = r;
stack_pointer += 1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
break;
}
case _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT: {
JitOptRef res;
JitOptRef l;
JitOptRef r;
res = sym_new_not_null(ctx);
l = sym_new_not_null(ctx);
r = sym_new_not_null(ctx);
CHECK_STACK_BOUNDS(1);
stack_pointer[-2] = res;
stack_pointer[-1] = l;