From f0728cf9c23935e4f51e848909581d3bd5a18083 Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Mon, 28 Nov 2022 08:24:03 -0800 Subject: [PATCH 1/3] Handle NaNs in COMPARE_OP_FLOAT_JUMP --- Python/bytecodes.c | 11 ++++++----- Python/generated_cases.c.h | 11 ++++++----- Python/specialize.c | 15 ++++++++------- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index c56f1d3ef9f498..7e5b52faf5e88c 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -2024,13 +2024,14 @@ dummy_func( // Combined: COMPARE_OP (float ? float) + POP_JUMP_IF_(true/false) DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP); DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_OP); + STAT_INC(COMPARE_OP, hit); double dleft = PyFloat_AS_DOUBLE(left); double dright = PyFloat_AS_DOUBLE(right); - // 1 if <, 2 if ==, 4 if >; this matches when _to_jump_mask - int sign_ish = 2*(dleft > dright) + 2 - (dleft < dright); - DEOPT_IF(isnan(dleft), COMPARE_OP); - DEOPT_IF(isnan(dright), COMPARE_OP); - STAT_INC(COMPARE_OP, hit); + // 1 if <, 2 if ==, 4 if >, 8 if unordered; this matches when_to_jump_mask + int sign_ish = (+ 6 * (Py_IS_NAN(dleft) | Py_IS_NAN(dright)) + + 2 * (dleft > dright) + - 1 * (dleft < dright) + + 2); _Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc); _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc); jump = sign_ish & when_to_jump_mask; diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 45382a466b1ca9..4d88abb5fdf941 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -2214,13 +2214,14 @@ // Combined: COMPARE_OP (float ? float) + POP_JUMP_IF_(true/false) DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP); DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_OP); + STAT_INC(COMPARE_OP, hit); double dleft = PyFloat_AS_DOUBLE(left); double dright = PyFloat_AS_DOUBLE(right); - // 1 if <, 2 if ==, 4 if >; this matches when _to_jump_mask - int sign_ish = 2*(dleft > dright) + 2 - (dleft < dright); - DEOPT_IF(isnan(dleft), COMPARE_OP); - DEOPT_IF(isnan(dright), COMPARE_OP); - STAT_INC(COMPARE_OP, hit); + // 1 if <, 2 if ==, 4 if >, 8 if unordered; this matches when_to_jump_mask + int sign_ish = (+ 6 * (Py_IS_NAN(dleft) | Py_IS_NAN(dright)) + + 2 * (dleft > dright) + - 1 * (dleft < dright) + + 2); _Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc); _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc); jump = sign_ish & when_to_jump_mask; diff --git a/Python/specialize.c b/Python/specialize.c index 7545a7712493e6..b9977b0d70a4e1 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -1927,12 +1927,13 @@ static int compare_masks[] = { // 1-bit: jump if less than // 2-bit: jump if equal // 4-bit: jump if greater - [Py_LT] = 1 | 0 | 0, - [Py_LE] = 1 | 2 | 0, - [Py_EQ] = 0 | 2 | 0, - [Py_NE] = 1 | 0 | 4, - [Py_GT] = 0 | 0 | 4, - [Py_GE] = 0 | 2 | 4, + // 8-bit: jump if unordered + [Py_LT] = 1 | 0 | 0 | 0, + [Py_LE] = 1 | 2 | 0 | 0, + [Py_EQ] = 0 | 2 | 0 | 0, + [Py_NE] = 1 | 0 | 4 | 8, + [Py_GT] = 0 | 0 | 4 | 0, + [Py_GE] = 0 | 2 | 4 | 0, }; void @@ -1953,7 +1954,7 @@ _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, assert(oparg <= Py_GE); int when_to_jump_mask = compare_masks[oparg]; if (next_opcode == POP_JUMP_IF_FALSE) { - when_to_jump_mask = (1 | 2 | 4) & ~when_to_jump_mask; + when_to_jump_mask = (1 | 2 | 4 | 8) & ~when_to_jump_mask; } if (Py_TYPE(lhs) != Py_TYPE(rhs)) { SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs)); From 2665c9a82699614cadc78529fe7ced82c90bc5e8 Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Wed, 30 Nov 2022 04:09:17 -0800 Subject: [PATCH 2/3] Remove NaN checks! --- Python/bytecodes.c | 11 ++++------- Python/generated_cases.c.h | 11 ++++------- Python/specialize.c | 18 +++++++++--------- 3 files changed, 17 insertions(+), 23 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 7e5b52faf5e88c..8e95b737030252 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -2027,11 +2027,8 @@ dummy_func( STAT_INC(COMPARE_OP, hit); double dleft = PyFloat_AS_DOUBLE(left); double dright = PyFloat_AS_DOUBLE(right); - // 1 if <, 2 if ==, 4 if >, 8 if unordered; this matches when_to_jump_mask - int sign_ish = (+ 6 * (Py_IS_NAN(dleft) | Py_IS_NAN(dright)) - + 2 * (dleft > dright) - - 1 * (dleft < dright) - + 2); + // 1 if NaN, 2 if <, 4 if >, 8 if ==; this matches when_to_jump_mask + int sign_ish = 1 << (2 * (dleft >= dright) + (dleft <= dright)); _Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc); _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc); jump = sign_ish & when_to_jump_mask; @@ -2058,8 +2055,8 @@ dummy_func( assert(Py_ABS(Py_SIZE(left)) <= 1 && Py_ABS(Py_SIZE(right)) <= 1); Py_ssize_t ileft = Py_SIZE(left) * ((PyLongObject *)left)->ob_digit[0]; Py_ssize_t iright = Py_SIZE(right) * ((PyLongObject *)right)->ob_digit[0]; - // 1 if <, 2 if ==, 4 if >; this matches when _to_jump_mask - int sign_ish = 2*(ileft > iright) + 2 - (ileft < iright); + // 2 if <, 4 if >, 8 if ==; this matches when_to_jump_mask + int sign_ish = 1 << (2 * (ileft >= iright) + (ileft <= iright)); _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); jump = sign_ish & when_to_jump_mask; diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 4d88abb5fdf941..48261d9093331a 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -2217,11 +2217,8 @@ STAT_INC(COMPARE_OP, hit); double dleft = PyFloat_AS_DOUBLE(left); double dright = PyFloat_AS_DOUBLE(right); - // 1 if <, 2 if ==, 4 if >, 8 if unordered; this matches when_to_jump_mask - int sign_ish = (+ 6 * (Py_IS_NAN(dleft) | Py_IS_NAN(dright)) - + 2 * (dleft > dright) - - 1 * (dleft < dright) - + 2); + // 1 if NaN, 2 if <, 4 if >, 8 if ==; this matches when_to_jump_mask + int sign_ish = 1 << (2 * (dleft >= dright) + (dleft <= dright)); _Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc); _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc); jump = sign_ish & when_to_jump_mask; @@ -2259,8 +2256,8 @@ assert(Py_ABS(Py_SIZE(left)) <= 1 && Py_ABS(Py_SIZE(right)) <= 1); Py_ssize_t ileft = Py_SIZE(left) * ((PyLongObject *)left)->ob_digit[0]; Py_ssize_t iright = Py_SIZE(right) * ((PyLongObject *)right)->ob_digit[0]; - // 1 if <, 2 if ==, 4 if >; this matches when _to_jump_mask - int sign_ish = 2*(ileft > iright) + 2 - (ileft < iright); + // 2 if <, 4 if >, 8 if ==; this matches when_to_jump_mask + int sign_ish = 1 << (2 * (ileft >= iright) + (ileft <= iright)); _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); jump = sign_ish & when_to_jump_mask; diff --git a/Python/specialize.c b/Python/specialize.c index b9977b0d70a4e1..5ab964e749dcfd 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -1924,16 +1924,16 @@ compare_op_fail_kind(PyObject *lhs, PyObject *rhs) static int compare_masks[] = { - // 1-bit: jump if less than - // 2-bit: jump if equal + // 1-bit: jump if unordered + // 2-bit: jump if less // 4-bit: jump if greater - // 8-bit: jump if unordered - [Py_LT] = 1 | 0 | 0 | 0, - [Py_LE] = 1 | 2 | 0 | 0, - [Py_EQ] = 0 | 2 | 0 | 0, - [Py_NE] = 1 | 0 | 4 | 8, + // 8-bit: jump if equal + [Py_LT] = 0 | 2 | 0 | 0, + [Py_LE] = 0 | 2 | 0 | 8, + [Py_EQ] = 0 | 0 | 0 | 8, + [Py_NE] = 1 | 2 | 4 | 0, [Py_GT] = 0 | 0 | 4 | 0, - [Py_GE] = 0 | 2 | 4 | 0, + [Py_GE] = 0 | 0 | 4 | 8, }; void @@ -1983,7 +1983,7 @@ _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, } else { _Py_SET_OPCODE(*instr, COMPARE_OP_STR_JUMP); - cache->mask = (when_to_jump_mask & 2) == 0; + cache->mask = (when_to_jump_mask & 8) == 0; goto success; } } From 9dc68aa3b3bc23309f879729c5a23ab6f3402514 Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Thu, 15 Dec 2022 00:50:35 -0800 Subject: [PATCH 3/3] blurb add --- .../2022-12-15-00-50-25.gh-issue-90043.gyoKdx.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-12-15-00-50-25.gh-issue-90043.gyoKdx.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-12-15-00-50-25.gh-issue-90043.gyoKdx.rst b/Misc/NEWS.d/next/Core and Builtins/2022-12-15-00-50-25.gh-issue-90043.gyoKdx.rst new file mode 100644 index 00000000000000..9a4f896e2cf51f --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-12-15-00-50-25.gh-issue-90043.gyoKdx.rst @@ -0,0 +1,2 @@ +Handle NaNs when specializing :opcode:`COMPARE_OP` for :class:`float` +values.