Skip to content

Commit 5e74d92

Browse files
authored
gh-148285: Allow recording uops after specializing uops (GH-148482)
1 parent d24ce17 commit 5e74d92

File tree

2 files changed

+66
-4
lines changed

2 files changed

+66
-4
lines changed

Lib/test/test_generated_cases.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1890,6 +1890,64 @@ def test_reassigning_dead_inputs(self):
18901890
"""
18911891
self.run_cases_test(input, output)
18921892

1893+
def test_recording_after_specializing_with_cache(self):
1894+
input = """
1895+
specializing op(SPEC, (counter/1 --)) {
1896+
spam;
1897+
}
1898+
1899+
tier2 op(REC, (--)) {
1900+
RECORD_VALUE(0);
1901+
}
1902+
1903+
op(BODY, (--)) {
1904+
ham;
1905+
}
1906+
1907+
macro(OP) = SPEC + unused/2 + REC + BODY;
1908+
"""
1909+
output = """
1910+
TARGET(OP) {
1911+
#if _Py_TAIL_CALL_INTERP
1912+
int opcode = OP;
1913+
(void)(opcode);
1914+
#endif
1915+
_Py_CODEUNIT* const this_instr = next_instr;
1916+
(void)this_instr;
1917+
frame->instr_ptr = next_instr;
1918+
next_instr += 4;
1919+
INSTRUCTION_STATS(OP);
1920+
// SPEC
1921+
{
1922+
uint16_t counter = read_u16(&this_instr[1].cache);
1923+
(void)counter;
1924+
spam;
1925+
}
1926+
/* Skip 2 cache entries */
1927+
// BODY
1928+
{
1929+
ham;
1930+
}
1931+
DISPATCH();
1932+
}
1933+
"""
1934+
self.run_cases_test(input, output)
1935+
1936+
def test_recording_after_non_specializing(self):
1937+
input = """
1938+
op(REGULAR, (--)) {
1939+
spam;
1940+
}
1941+
1942+
tier2 op(REC, (--)) {
1943+
RECORD_VALUE(0);
1944+
}
1945+
1946+
macro(OP) = REGULAR + REC;
1947+
"""
1948+
with self.assertRaisesRegex(SyntaxError, "Recording uop"):
1949+
self.run_cases_test(input, "")
1950+
18931951

18941952
class TestGeneratedAbstractCases(unittest.TestCase):
18951953
def setUp(self) -> None:

Tools/cases_generator/analyzer.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,7 +1132,9 @@ def add_macro(
11321132
macro: parser.Macro, instructions: dict[str, Instruction], uops: dict[str, Uop]
11331133
) -> None:
11341134
parts: list[Part] = []
1135-
first = True
1135+
# Track the last non-specializing uop seen, so that recording uops
1136+
# can follow specializing ones without triggering the position check.
1137+
prev_uop: Uop | None = None
11361138
for part in macro.uops:
11371139
match part:
11381140
case parser.OpName():
@@ -1144,12 +1146,14 @@ def add_macro(
11441146
f"No Uop named {part.name}", macro.tokens[0]
11451147
)
11461148
uop = uops[part.name]
1147-
if uop.properties.records_value and not first:
1149+
if uop.properties.records_value and prev_uop is not None:
11481150
raise analysis_error(
1149-
f"Recording uop {part.name} must be first in macro",
1151+
f"Recording uop {part.name} is not allowed "
1152+
f"after non-specializing uops in macro",
11501153
macro.tokens[0])
11511154
parts.append(uop)
1152-
first = False
1155+
if "specializing" not in uop.annotations:
1156+
prev_uop = uop
11531157
case parser.CacheEffect():
11541158
parts.append(Skip(part.size))
11551159
case _:

0 commit comments

Comments
 (0)