mirror of
https://github.com/python/cpython.git
synced 2025-07-07 19:35:27 +00:00
gh-136183: Deal with escapes in JIT optimizer's constant evaluator (GH-136184)
Some checks failed
Tests / Docs (push) Blocked by required conditions
Tests / Address sanitizer (push) Blocked by required conditions
Tests / (push) Blocked by required conditions
Tests / Undefined behavior sanitizer (push) Blocked by required conditions
Tests / Cross build Linux (push) Blocked by required conditions
Tests / Windows MSI (push) Blocked by required conditions
Tests / Ubuntu SSL tests with OpenSSL (push) Blocked by required conditions
Tests / WASI (push) Blocked by required conditions
Tests / Hypothesis tests on Ubuntu (push) Blocked by required conditions
Tests / Change detection (push) Waiting to run
Tests / Check if Autoconf files are up to date (push) Blocked by required conditions
Tests / Check if generated files are up to date (push) Blocked by required conditions
Tests / CIFuzz (push) Blocked by required conditions
Tests / All required checks pass (push) Blocked by required conditions
Lint / lint (push) Waiting to run
mypy / Run mypy on Lib/_pyrepl (push) Waiting to run
mypy / Run mypy on Lib/test/libregrtest (push) Waiting to run
mypy / Run mypy on Lib/tomllib (push) Waiting to run
mypy / Run mypy on Tools/build (push) Waiting to run
mypy / Run mypy on Tools/cases_generator (push) Waiting to run
mypy / Run mypy on Tools/clinic (push) Waiting to run
mypy / Run mypy on Tools/jit (push) Waiting to run
mypy / Run mypy on Tools/peg_generator (push) Waiting to run
JIT / Interpreter (Debug) (push) Has been cancelled
JIT / x86_64-apple-darwin/clang (Release) (push) Has been cancelled
JIT / x86_64-unknown-linux-gnu/gcc (Release) (push) Has been cancelled
JIT / x86_64-apple-darwin/clang (Debug) (push) Has been cancelled
JIT / x86_64-unknown-linux-gnu/gcc (Debug) (push) Has been cancelled
JIT / aarch64-pc-windows-msvc/msvc (Release) (push) Has been cancelled
JIT / aarch64-pc-windows-msvc/msvc (Debug) (push) Has been cancelled
JIT / i686-pc-windows-msvc/msvc (Release) (push) Has been cancelled
JIT / i686-pc-windows-msvc/msvc (Debug) (push) Has been cancelled
JIT / aarch64-apple-darwin/clang (Release) (push) Has been cancelled
JIT / aarch64-unknown-linux-gnu/gcc (Release) (push) Has been cancelled
JIT / aarch64-apple-darwin/clang (Debug) (push) Has been cancelled
JIT / aarch64-unknown-linux-gnu/gcc (Debug) (push) Has been cancelled
JIT / x86_64-pc-windows-msvc/msvc (Release) (push) Has been cancelled
JIT / x86_64-pc-windows-msvc/msvc (Debug) (push) Has been cancelled
Some checks failed
Tests / Docs (push) Blocked by required conditions
Tests / Address sanitizer (push) Blocked by required conditions
Tests / (push) Blocked by required conditions
Tests / Undefined behavior sanitizer (push) Blocked by required conditions
Tests / Cross build Linux (push) Blocked by required conditions
Tests / Windows MSI (push) Blocked by required conditions
Tests / Ubuntu SSL tests with OpenSSL (push) Blocked by required conditions
Tests / WASI (push) Blocked by required conditions
Tests / Hypothesis tests on Ubuntu (push) Blocked by required conditions
Tests / Change detection (push) Waiting to run
Tests / Check if Autoconf files are up to date (push) Blocked by required conditions
Tests / Check if generated files are up to date (push) Blocked by required conditions
Tests / CIFuzz (push) Blocked by required conditions
Tests / All required checks pass (push) Blocked by required conditions
Lint / lint (push) Waiting to run
mypy / Run mypy on Lib/_pyrepl (push) Waiting to run
mypy / Run mypy on Lib/test/libregrtest (push) Waiting to run
mypy / Run mypy on Lib/tomllib (push) Waiting to run
mypy / Run mypy on Tools/build (push) Waiting to run
mypy / Run mypy on Tools/cases_generator (push) Waiting to run
mypy / Run mypy on Tools/clinic (push) Waiting to run
mypy / Run mypy on Tools/jit (push) Waiting to run
mypy / Run mypy on Tools/peg_generator (push) Waiting to run
JIT / Interpreter (Debug) (push) Has been cancelled
JIT / x86_64-apple-darwin/clang (Release) (push) Has been cancelled
JIT / x86_64-unknown-linux-gnu/gcc (Release) (push) Has been cancelled
JIT / x86_64-apple-darwin/clang (Debug) (push) Has been cancelled
JIT / x86_64-unknown-linux-gnu/gcc (Debug) (push) Has been cancelled
JIT / aarch64-pc-windows-msvc/msvc (Release) (push) Has been cancelled
JIT / aarch64-pc-windows-msvc/msvc (Debug) (push) Has been cancelled
JIT / i686-pc-windows-msvc/msvc (Release) (push) Has been cancelled
JIT / i686-pc-windows-msvc/msvc (Debug) (push) Has been cancelled
JIT / aarch64-apple-darwin/clang (Release) (push) Has been cancelled
JIT / aarch64-unknown-linux-gnu/gcc (Release) (push) Has been cancelled
JIT / aarch64-apple-darwin/clang (Debug) (push) Has been cancelled
JIT / aarch64-unknown-linux-gnu/gcc (Debug) (push) Has been cancelled
JIT / x86_64-pc-windows-msvc/msvc (Release) (push) Has been cancelled
JIT / x86_64-pc-windows-msvc/msvc (Debug) (push) Has been cancelled
This commit is contained in:
parent
f41e9c750e
commit
b3308973e3
6 changed files with 77 additions and 7 deletions
4
.github/workflows/jit.yml
vendored
4
.github/workflows/jit.yml
vendored
|
@ -5,6 +5,8 @@ on:
|
|||
- '**jit**'
|
||||
- 'Python/bytecodes.c'
|
||||
- 'Python/optimizer*.c'
|
||||
- 'Python/executor_cases.c.h'
|
||||
- 'Python/optimizer_cases.c.h'
|
||||
- '!Python/perf_jit_trampoline.c'
|
||||
- '!**/*.md'
|
||||
- '!**/*.ini'
|
||||
|
@ -13,6 +15,8 @@ on:
|
|||
- '**jit**'
|
||||
- 'Python/bytecodes.c'
|
||||
- 'Python/optimizer*.c'
|
||||
- 'Python/executor_cases.c.h'
|
||||
- 'Python/optimizer_cases.c.h'
|
||||
- '!Python/perf_jit_trampoline.c'
|
||||
- '!**/*.md'
|
||||
- '!**/*.ini'
|
||||
|
|
|
@ -2451,6 +2451,21 @@ class TestUopsOptimization(unittest.TestCase):
|
|||
self.assertNotIn("_GUARD_TOS_FLOAT", uops)
|
||||
self.assertNotIn("_GUARD_NOS_FLOAT", uops)
|
||||
|
||||
def test_binary_op_constant_evaluate(self):
|
||||
def testfunc(n):
|
||||
for _ in range(n):
|
||||
2 ** 65
|
||||
|
||||
testfunc(TIER2_THRESHOLD)
|
||||
|
||||
ex = get_first_executor(testfunc)
|
||||
self.assertIsNotNone(ex)
|
||||
uops = get_opnames(ex)
|
||||
|
||||
# For now... until we constant propagate it away.
|
||||
self.assertIn("_BINARY_OP", uops)
|
||||
|
||||
|
||||
def global_identity(x):
|
||||
return x
|
||||
|
||||
|
|
|
@ -2398,6 +2398,53 @@ class TestGeneratedAbstractCases(unittest.TestCase):
|
|||
"""
|
||||
self.run_cases_test(input, input2, output)
|
||||
|
||||
def test_replace_opcode_escaping_uop_body_copied_in_complex(self):
|
||||
input = """
|
||||
pure op(OP, (foo -- res)) {
|
||||
if (foo) {
|
||||
res = ESCAPING_CODE(foo);
|
||||
}
|
||||
else {
|
||||
res = 1;
|
||||
}
|
||||
}
|
||||
"""
|
||||
input2 = """
|
||||
op(OP, (foo -- res)) {
|
||||
REPLACE_OPCODE_IF_EVALUATES_PURE(foo);
|
||||
res = sym_new_known(ctx, foo);
|
||||
}
|
||||
"""
|
||||
output = """
|
||||
case OP: {
|
||||
JitOptRef foo;
|
||||
JitOptRef res;
|
||||
foo = stack_pointer[-1];
|
||||
if (
|
||||
sym_is_safe_const(ctx, foo)
|
||||
) {
|
||||
JitOptRef foo_sym = foo;
|
||||
_PyStackRef foo = sym_get_const_as_stackref(ctx, foo_sym);
|
||||
_PyStackRef res_stackref;
|
||||
/* Start of uop copied from bytecodes for constant evaluation */
|
||||
if (foo) {
|
||||
res_stackref = ESCAPING_CODE(foo);
|
||||
}
|
||||
else {
|
||||
res_stackref = 1;
|
||||
}
|
||||
/* End of uop copied from bytecodes for constant evaluation */
|
||||
res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref));
|
||||
stack_pointer[-1] = res;
|
||||
break;
|
||||
}
|
||||
res = sym_new_known(ctx, foo);
|
||||
stack_pointer[-1] = res;
|
||||
break;
|
||||
}
|
||||
"""
|
||||
self.run_cases_test(input, input2, output)
|
||||
|
||||
def test_replace_opocode_uop_reject_array_effects(self):
|
||||
input = """
|
||||
pure op(OP, (foo[2] -- res)) {
|
||||
|
|
6
Python/optimizer_cases.c.h
generated
6
Python/optimizer_cases.c.h
generated
|
@ -2723,9 +2723,6 @@
|
|||
PyObject *lhs_o = PyStackRef_AsPyObjectBorrow(lhs);
|
||||
PyObject *rhs_o = PyStackRef_AsPyObjectBorrow(rhs);
|
||||
assert(_PyEval_BinaryOps[oparg]);
|
||||
stack_pointer[-2] = res;
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
PyObject *res_o = _PyEval_BinaryOps[oparg](lhs_o, rhs_o);
|
||||
if (res_o == NULL) {
|
||||
JUMP_TO_LABEL(error);
|
||||
|
@ -2733,6 +2730,9 @@
|
|||
res_stackref = PyStackRef_FromPyObjectSteal(res_o);
|
||||
/* End of uop copied from bytecodes for constant evaluation */
|
||||
res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref));
|
||||
stack_pointer[-2] = res;
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
break;
|
||||
}
|
||||
bool lhs_int = sym_matches_type(lhs, &PyLong_Type);
|
||||
|
|
|
@ -106,8 +106,9 @@ class Emitter:
|
|||
out: CWriter
|
||||
labels: dict[str, Label]
|
||||
_replacers: dict[str, ReplacementFunctionType]
|
||||
cannot_escape: bool
|
||||
|
||||
def __init__(self, out: CWriter, labels: dict[str, Label]):
|
||||
def __init__(self, out: CWriter, labels: dict[str, Label], cannot_escape: bool = False):
|
||||
self._replacers = {
|
||||
"EXIT_IF": self.exit_if,
|
||||
"DEOPT_IF": self.deopt_if,
|
||||
|
@ -127,6 +128,7 @@ class Emitter:
|
|||
}
|
||||
self.out = out
|
||||
self.labels = labels
|
||||
self.cannot_escape = cannot_escape
|
||||
|
||||
def dispatch(
|
||||
self,
|
||||
|
@ -238,6 +240,7 @@ class Emitter:
|
|||
next(tkn_iter)
|
||||
self._print_storage("DECREF_INPUTS", storage)
|
||||
try:
|
||||
if not self.cannot_escape:
|
||||
storage.close_inputs(self.out)
|
||||
except StackError as ex:
|
||||
raise analysis_error(ex.args[0], tkn)
|
||||
|
@ -476,7 +479,7 @@ class Emitter:
|
|||
reachable = True
|
||||
tkn = stmt.contents[-1]
|
||||
try:
|
||||
if stmt in uop.properties.escaping_calls:
|
||||
if stmt in uop.properties.escaping_calls and not self.cannot_escape:
|
||||
escape = uop.properties.escaping_calls[stmt]
|
||||
if escape.kills is not None:
|
||||
self.stackref_kill(escape.kills, storage, True)
|
||||
|
@ -513,7 +516,7 @@ class Emitter:
|
|||
self.out.emit(tkn)
|
||||
else:
|
||||
self.out.emit(tkn)
|
||||
if stmt in uop.properties.escaping_calls:
|
||||
if stmt in uop.properties.escaping_calls and not self.cannot_escape:
|
||||
self.emit_reload(storage)
|
||||
return reachable, None, storage
|
||||
except StackError as ex:
|
||||
|
|
|
@ -245,6 +245,7 @@ class OptimizerConstantEmitter(OptimizerEmitter):
|
|||
outp.name: self.emit_stackref_override for outp in self.original_uop.stack.outputs
|
||||
}
|
||||
self._replacers = {**self._replacers, **overrides}
|
||||
self.cannot_escape = True
|
||||
|
||||
def emit_to_with_replacement(
|
||||
self,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue