mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
GH-130415: Improve the JIT's unneeded uop removal pass (GH-132333)
This commit is contained in:
parent
9be3645688
commit
4f7f72ce34
5 changed files with 46 additions and 18 deletions
|
@ -1283,7 +1283,7 @@ class TestUopsOptimization(unittest.TestCase):
|
||||||
load_attr_top = opnames.index("_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES", 0, call)
|
load_attr_top = opnames.index("_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES", 0, call)
|
||||||
load_attr_bottom = opnames.index("_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES", call)
|
load_attr_bottom = opnames.index("_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES", call)
|
||||||
self.assertEqual(opnames[:load_attr_top].count("_GUARD_TYPE_VERSION"), 1)
|
self.assertEqual(opnames[:load_attr_top].count("_GUARD_TYPE_VERSION"), 1)
|
||||||
self.assertEqual(opnames[call:load_attr_bottom].count("_CHECK_VALIDITY"), 1)
|
self.assertEqual(opnames[call:load_attr_bottom].count("_CHECK_VALIDITY"), 2)
|
||||||
|
|
||||||
def test_guard_type_version_removed_escaping(self):
|
def test_guard_type_version_removed_escaping(self):
|
||||||
|
|
||||||
|
@ -1306,7 +1306,7 @@ class TestUopsOptimization(unittest.TestCase):
|
||||||
load_attr_top = opnames.index("_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES", 0, call)
|
load_attr_top = opnames.index("_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES", 0, call)
|
||||||
load_attr_bottom = opnames.index("_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES", call)
|
load_attr_bottom = opnames.index("_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES", call)
|
||||||
self.assertEqual(opnames[:load_attr_top].count("_GUARD_TYPE_VERSION"), 1)
|
self.assertEqual(opnames[:load_attr_top].count("_GUARD_TYPE_VERSION"), 1)
|
||||||
self.assertEqual(opnames[call:load_attr_bottom].count("_CHECK_VALIDITY"), 1)
|
self.assertEqual(opnames[call:load_attr_bottom].count("_CHECK_VALIDITY"), 2)
|
||||||
|
|
||||||
def test_guard_type_version_executor_invalidated(self):
|
def test_guard_type_version_executor_invalidated(self):
|
||||||
"""
|
"""
|
||||||
|
@ -1601,7 +1601,7 @@ class TestUopsOptimization(unittest.TestCase):
|
||||||
self.assertIsNotNone(ex)
|
self.assertIsNotNone(ex)
|
||||||
uops = get_opnames(ex)
|
uops = get_opnames(ex)
|
||||||
self.assertNotIn("_COMPARE_OP_INT", uops)
|
self.assertNotIn("_COMPARE_OP_INT", uops)
|
||||||
self.assertIn("_POP_TWO_LOAD_CONST_INLINE_BORROW", uops)
|
self.assertNotIn("_POP_TWO_LOAD_CONST_INLINE_BORROW", uops)
|
||||||
|
|
||||||
def test_to_bool_bool_contains_op_set(self):
|
def test_to_bool_bool_contains_op_set(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Improve the JIT's ability to remove unused constant and local variable
|
||||||
|
loads, and fix an issue where deallocating unused values could cause JIT
|
||||||
|
code to crash or behave incorrectly.
|
|
@ -555,28 +555,47 @@ remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case _POP_TOP:
|
case _POP_TOP:
|
||||||
|
case _POP_TOP_LOAD_CONST_INLINE:
|
||||||
|
case _POP_TOP_LOAD_CONST_INLINE_BORROW:
|
||||||
|
case _POP_TWO_LOAD_CONST_INLINE_BORROW:
|
||||||
|
optimize_pop_top_again:
|
||||||
{
|
{
|
||||||
_PyUOpInstruction *last = &buffer[pc-1];
|
_PyUOpInstruction *last = &buffer[pc-1];
|
||||||
while (last->opcode == _NOP) {
|
while (last->opcode == _NOP) {
|
||||||
last--;
|
last--;
|
||||||
}
|
}
|
||||||
if (last->opcode == _LOAD_CONST_INLINE ||
|
switch (last->opcode) {
|
||||||
last->opcode == _LOAD_CONST_INLINE_BORROW ||
|
case _POP_TWO_LOAD_CONST_INLINE_BORROW:
|
||||||
last->opcode == _LOAD_FAST ||
|
last->opcode = _POP_TOP;
|
||||||
last->opcode == _LOAD_FAST_BORROW ||
|
break;
|
||||||
last->opcode == _COPY
|
case _POP_TOP_LOAD_CONST_INLINE:
|
||||||
) {
|
case _POP_TOP_LOAD_CONST_INLINE_BORROW:
|
||||||
last->opcode = _NOP;
|
last->opcode = _NOP;
|
||||||
buffer[pc].opcode = _NOP;
|
goto optimize_pop_top_again;
|
||||||
|
case _COPY:
|
||||||
|
case _LOAD_CONST_INLINE:
|
||||||
|
case _LOAD_CONST_INLINE_BORROW:
|
||||||
|
case _LOAD_FAST:
|
||||||
|
case _LOAD_FAST_BORROW:
|
||||||
|
case _LOAD_SMALL_INT:
|
||||||
|
last->opcode = _NOP;
|
||||||
|
if (opcode == _POP_TOP) {
|
||||||
|
opcode = buffer[pc].opcode = _NOP;
|
||||||
|
}
|
||||||
|
else if (opcode == _POP_TOP_LOAD_CONST_INLINE) {
|
||||||
|
opcode = buffer[pc].opcode = _LOAD_CONST_INLINE;
|
||||||
|
}
|
||||||
|
else if (opcode == _POP_TOP_LOAD_CONST_INLINE_BORROW) {
|
||||||
|
opcode = buffer[pc].opcode = _LOAD_CONST_INLINE_BORROW;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert(opcode == _POP_TWO_LOAD_CONST_INLINE_BORROW);
|
||||||
|
opcode = buffer[pc].opcode = _POP_TOP_LOAD_CONST_INLINE_BORROW;
|
||||||
|
goto optimize_pop_top_again;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (last->opcode == _REPLACE_WITH_TRUE) {
|
_Py_FALLTHROUGH;
|
||||||
last->opcode = _NOP;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case _JUMP_TO_TOP:
|
|
||||||
case _EXIT_TRACE:
|
|
||||||
return pc + 1;
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
/* _PUSH_FRAME doesn't escape or error, but it
|
/* _PUSH_FRAME doesn't escape or error, but it
|
||||||
|
@ -591,7 +610,11 @@ remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size)
|
||||||
buffer[last_set_ip].opcode = _SET_IP;
|
buffer[last_set_ip].opcode = _SET_IP;
|
||||||
last_set_ip = -1;
|
last_set_ip = -1;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
case _JUMP_TO_TOP:
|
||||||
|
case _EXIT_TRACE:
|
||||||
|
return pc + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Py_UNREACHABLE();
|
Py_UNREACHABLE();
|
||||||
|
|
|
@ -912,6 +912,7 @@ dummy_func(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_REPLACE_WITH_TRUE, (value -- res)) {
|
op(_REPLACE_WITH_TRUE, (value -- res)) {
|
||||||
|
REPLACE_OP(this_instr, _POP_TOP_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)Py_True);
|
||||||
res = sym_new_const(ctx, Py_True);
|
res = sym_new_const(ctx, Py_True);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1
Python/optimizer_cases.c.h
generated
1
Python/optimizer_cases.c.h
generated
|
@ -274,6 +274,7 @@
|
||||||
|
|
||||||
case _REPLACE_WITH_TRUE: {
|
case _REPLACE_WITH_TRUE: {
|
||||||
JitOptSymbol *res;
|
JitOptSymbol *res;
|
||||||
|
REPLACE_OP(this_instr, _POP_TOP_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)Py_True);
|
||||||
res = sym_new_const(ctx, Py_True);
|
res = sym_new_const(ctx, Py_True);
|
||||||
stack_pointer[-1] = res;
|
stack_pointer[-1] = res;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue