GH-131729: Code-gen better liveness analysis (GH-131732)

* Rename 'defined' attribute to 'in_local' to more accurately reflect how it is used

* Make death of variables explicit even for array variables.

* Convert in_memory from boolean to stack offset

* Don't apply liveness analysis to optimizer generated code

* Fix RETURN_VALUE in optimizer
This commit is contained in:
Mark Shannon 2025-03-26 15:21:35 +00:00 committed by GitHub
parent b9ca438daa
commit 1b8bb1ed0c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 344 additions and 399 deletions

View file

@ -285,9 +285,11 @@ class TestGeneratedCases(unittest.TestCase):
def test_predictions(self):
input = """
inst(OP1, (arg -- res)) {
DEAD(arg);
res = Py_None;
}
inst(OP3, (arg -- res)) {
DEAD(arg);
DEOPT_IF(xxx);
res = Py_None;
}
@ -303,7 +305,9 @@ class TestGeneratedCases(unittest.TestCase):
next_instr += 1;
INSTRUCTION_STATS(OP1);
PREDICTED_OP1:;
_PyStackRef arg;
_PyStackRef res;
arg = stack_pointer[-1];
res = Py_None;
stack_pointer[-1] = res;
DISPATCH();
@ -320,7 +324,9 @@ class TestGeneratedCases(unittest.TestCase):
next_instr += 1;
INSTRUCTION_STATS(OP3);
static_assert(INLINE_CACHE_ENTRIES_OP1 == 0, "incorrect cache size");
_PyStackRef arg;
_PyStackRef res;
arg = stack_pointer[-1];
if (xxx) {
UPDATE_MISS_STATS(OP1);
assert(_PyOpcode_Deopt[opcode] == (OP1));
@ -336,11 +342,13 @@ class TestGeneratedCases(unittest.TestCase):
def test_sync_sp(self):
input = """
inst(A, (arg -- res)) {
DEAD(arg);
SYNC_SP();
escaping_call();
res = Py_None;
}
inst(B, (arg -- res)) {
DEAD(arg);
res = Py_None;
SYNC_SP();
escaping_call();
@ -355,7 +363,9 @@ class TestGeneratedCases(unittest.TestCase):
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(A);
_PyStackRef arg;
_PyStackRef res;
arg = stack_pointer[-1];
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
_PyFrame_SetStackPointer(frame, stack_pointer);
@ -376,7 +386,9 @@ class TestGeneratedCases(unittest.TestCase):
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(B);
_PyStackRef arg;
_PyStackRef res;
arg = stack_pointer[-1];
res = Py_None;
stack_pointer[-1] = res;
_PyFrame_SetStackPointer(frame, stack_pointer);
@ -522,6 +534,7 @@ class TestGeneratedCases(unittest.TestCase):
def test_cache_effect(self):
input = """
inst(OP, (counter/1, extra/2, value --)) {
DEAD(value);
}
"""
output = """
@ -535,6 +548,8 @@ class TestGeneratedCases(unittest.TestCase):
frame->instr_ptr = next_instr;
next_instr += 4;
INSTRUCTION_STATS(OP);
_PyStackRef value;
value = stack_pointer[-1];
uint16_t counter = read_u16(&this_instr[1].cache);
(void)counter;
uint32_t extra = read_u32(&this_instr[2].cache);
@ -793,6 +808,9 @@ class TestGeneratedCases(unittest.TestCase):
input = """
inst(OP, (below, values[oparg*2], above --)) {
SPAM(values, oparg);
DEAD(below);
DEAD(values);
DEAD(above);
}
"""
output = """
@ -804,8 +822,12 @@ class TestGeneratedCases(unittest.TestCase):
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(OP);
_PyStackRef below;
_PyStackRef *values;
_PyStackRef above;
above = stack_pointer[-1];
values = &stack_pointer[-1 - oparg*2];
below = stack_pointer[-2 - oparg*2];
SPAM(values, oparg);
stack_pointer += -2 - oparg*2;
assert(WITHIN_STACK_BOUNDS());
@ -879,6 +901,8 @@ class TestGeneratedCases(unittest.TestCase):
def test_array_error_if(self):
input = """
inst(OP, (extra, values[oparg] --)) {
DEAD(extra);
DEAD(values);
ERROR_IF(oparg == 0, somewhere);
}
"""
@ -891,6 +915,10 @@ class TestGeneratedCases(unittest.TestCase):
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(OP);
_PyStackRef extra;
_PyStackRef *values;
values = &stack_pointer[-oparg];
extra = stack_pointer[-1 - oparg];
if (oparg == 0) {
stack_pointer += -1 - oparg;
assert(WITHIN_STACK_BOUNDS());
@ -1056,6 +1084,7 @@ class TestGeneratedCases(unittest.TestCase):
input = """
inst(OP, (arg[1] -- out[1])) {
out[0] = arg[0];
DEAD(arg);
}
"""
output = """