Skip to content

Commit 029c92b

Browse files
Add deopt and error_if, and tests
1 parent efb9888 commit 029c92b

File tree

6 files changed

+288
-33
lines changed

6 files changed

+288
-33
lines changed

Lib/test/test_generated_cases.py

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2263,7 +2263,95 @@ def test_pure_uop_body_copied_in(self):
22632263
"""
22642264
self.run_cases_test(input, input2, output)
22652265

2266-
def test_pure_uop_body_copied_in_complex(self):
2266+
def test_pure_uop_body_copied_in_deopt(self):
2267+
# Note: any non-escaping call works.
2268+
# In this case, we use PyStackRef_IsNone.
2269+
input = """
2270+
pure op(OP, (foo -- res)) {
2271+
DEOPT_IF(PyStackRef_IsNull(foo));
2272+
res = foo;
2273+
}
2274+
"""
2275+
input2 = """
2276+
op(OP, (foo -- res)) {
2277+
REPLACE_OPCODE_IF_EVALUATES_PURE(foo);
2278+
res = foo;
2279+
}
2280+
"""
2281+
output = """
2282+
case OP: {
2283+
JitOptSymbol *foo;
2284+
JitOptSymbol *res;
2285+
foo = stack_pointer[-1];
2286+
if (
2287+
sym_is_safe_const(ctx, foo)
2288+
) {
2289+
JitOptSymbol *foo_sym = foo;
2290+
_PyStackRef foo = sym_get_const_as_stackref(ctx, foo_sym);
2291+
_PyStackRef res_stackref;
2292+
/* Start of uop copied from bytecodes for constant evaluation */
2293+
if (PyStackRef_IsNull(foo)) {
2294+
ctx->done = true;
2295+
break;
2296+
}
2297+
res_stackref = foo;
2298+
/* End of uop copied from bytecodes for constant evaluation */
2299+
res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref));
2300+
stack_pointer[-1] = res;
2301+
break;
2302+
}
2303+
res = foo;
2304+
stack_pointer[-1] = res;
2305+
break;
2306+
}
2307+
"""
2308+
self.run_cases_test(input, input2, output)
2309+
2310+
def test_pure_uop_body_copied_in_error_if(self):
2311+
# Note: any non-escaping call works.
2312+
# In this case, we use PyStackRef_IsNone.
2313+
input = """
2314+
pure op(OP, (foo -- res)) {
2315+
ERROR_IF(PyStackRef_IsNull(foo));
2316+
res = foo;
2317+
}
2318+
"""
2319+
input2 = """
2320+
op(OP, (foo -- res)) {
2321+
REPLACE_OPCODE_IF_EVALUATES_PURE(foo);
2322+
res = foo;
2323+
}
2324+
"""
2325+
output = """
2326+
case OP: {
2327+
JitOptSymbol *foo;
2328+
JitOptSymbol *res;
2329+
foo = stack_pointer[-1];
2330+
if (
2331+
sym_is_safe_const(ctx, foo)
2332+
) {
2333+
JitOptSymbol *foo_sym = foo;
2334+
_PyStackRef foo = sym_get_const_as_stackref(ctx, foo_sym);
2335+
_PyStackRef res_stackref;
2336+
/* Start of uop copied from bytecodes for constant evaluation */
2337+
if (PyStackRef_IsNull(foo)) {
2338+
goto error;
2339+
}
2340+
res_stackref = foo;
2341+
/* End of uop copied from bytecodes for constant evaluation */
2342+
res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref));
2343+
stack_pointer[-1] = res;
2344+
break;
2345+
}
2346+
res = foo;
2347+
stack_pointer[-1] = res;
2348+
break;
2349+
}
2350+
"""
2351+
self.run_cases_test(input, input2, output)
2352+
2353+
2354+
def test_replace_opcode_uop_body_copied_in_complex(self):
22672355
input = """
22682356
pure op(OP, (foo -- res)) {
22692357
if (foo) {
@@ -2310,7 +2398,7 @@ def test_pure_uop_body_copied_in_complex(self):
23102398
"""
23112399
self.run_cases_test(input, input2, output)
23122400

2313-
def test_pure_uop_reject_array_effects(self):
2401+
def test_replace_opocode_uop_reject_array_effects(self):
23142402
input = """
23152403
pure op(OP, (foo[2] -- res)) {
23162404
if (foo) {

Python/optimizer_analysis.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,6 @@ optimize_uops(
536536
}
537537
return trace_len;
538538

539-
pop_2_error:
540539
error:
541540
DPRINTF(3, "\n");
542541
DPRINTF(1, "Encountered error in abstract interpreter\n");

Python/optimizer_bytecodes.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,14 +222,17 @@ dummy_func(void) {
222222
}
223223

224224
op(_BINARY_OP_ADD_INT, (left, right -- res)) {
225+
REPLACE_OPCODE_IF_EVALUATES_PURE(left, right);
225226
res = sym_new_type(ctx, &PyLong_Type);
226227
}
227228

228229
op(_BINARY_OP_SUBTRACT_INT, (left, right -- res)) {
230+
REPLACE_OPCODE_IF_EVALUATES_PURE(left, right);
229231
res = sym_new_type(ctx, &PyLong_Type);
230232
}
231233

232234
op(_BINARY_OP_MULTIPLY_INT, (left, right -- res)) {
235+
REPLACE_OPCODE_IF_EVALUATES_PURE(left, right);
233236
res = sym_new_type(ctx, &PyLong_Type);
234237
}
235238

Python/optimizer_cases.c.h

Lines changed: 115 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Tools/cases_generator/generators_common.py

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -139,30 +139,6 @@ def __init__(self, out: CWriter, labels: dict[str, Label]):
139139
self.out = out
140140
self.labels = labels
141141

142-
def emit_to_with_replacement(
143-
self,
144-
out: CWriter,
145-
tkn_iter: TokenIterator,
146-
end: str,
147-
uop: CodeSection,
148-
storage: Storage,
149-
inst: Instruction | None
150-
) -> Token:
151-
parens = 0
152-
for tkn in tkn_iter:
153-
if tkn.kind == end and parens == 0:
154-
return tkn
155-
if tkn.kind == "LPAREN":
156-
parens += 1
157-
if tkn.kind == "RPAREN":
158-
parens -= 1
159-
if tkn.text in self._replacers:
160-
self._replacers[tkn.text](tkn, tkn_iter, uop, storage, inst)
161-
else:
162-
out.emit(tkn)
163-
raise analysis_error(f"Expecting {end}. Reached end of file", tkn)
164-
165-
166142
def dispatch(
167143
self,
168144
tkn: Token,
@@ -190,7 +166,7 @@ def deopt_if(
190166
lparen = next(tkn_iter)
191167
assert lparen.kind == "LPAREN"
192168
first_tkn = tkn_iter.peek()
193-
self.emit_to_with_replacement(self.out, tkn_iter, "RPAREN", uop, storage, inst)
169+
emit_to(self.out, tkn_iter, "RPAREN")
194170
self.emit(") {\n")
195171
next(tkn_iter) # Semi colon
196172
assert inst is not None
@@ -230,7 +206,7 @@ def error_if(
230206
else:
231207
self.out.emit_at("if ", tkn)
232208
self.emit(lparen)
233-
self.emit_to_with_replacement(self.out, tkn_iter, "RPAREN", uop, storage, inst)
209+
emit_to(self.out, tkn_iter, "RPAREN")
234210
self.out.emit(") {\n")
235211
next(tkn_iter) # Semi colon
236212
storage.clear_inputs("at ERROR_IF")

0 commit comments

Comments
 (0)