https://github.com/python/cpython/commit/7ebd71ee14a497bb5dc7a693dd00f074a9f4831f
commit: 7ebd71ee14a497bb5dc7a693dd00f074a9f4831f
branch: main
author: Mark Shannon <[email protected]>
committer: markshannon <[email protected]>
date: 2025-03-20T15:39:38Z
summary:
GH-131498: Remove conditional stack effects (GH-131499)
* Adds some missing #includes
files:
M Include/internal/pycore_jit.h
M Lib/test/test_generated_cases.py
M Modules/_testinternalcapi.c
M Objects/codeobject.c
M Python/bytecodes.c
M Python/executor_cases.c.h
M Python/generated_cases.c.h
M Python/jit.c
M Python/optimizer.c
M Python/optimizer_analysis.c
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h
M Python/optimizer_symbols.c
M Python/pylifecycle.c
M Tools/cases_generator/analyzer.py
M Tools/cases_generator/generators_common.py
M Tools/cases_generator/lexer.py
M Tools/cases_generator/optimizer_generator.py
M Tools/cases_generator/parsing.py
M Tools/cases_generator/stack.py
M Tools/cases_generator/tier1_generator.py
M Tools/cases_generator/tier2_generator.py
M Tools/jit/template.c
diff --git a/Include/internal/pycore_jit.h b/Include/internal/pycore_jit.h
index 4d6cc35a7a3de7..8a88cbf607ba4b 100644
--- a/Include/internal/pycore_jit.h
+++ b/Include/internal/pycore_jit.h
@@ -5,6 +5,10 @@
extern "C" {
#endif
+#include "pycore_interp.h"
+#include "pycore_optimizer.h"
+#include "pycore_stackref.h"
+
#ifndef Py_BUILD_CORE
# error "this header requires Py_BUILD_CORE define"
#endif
diff --git a/Lib/test/test_generated_cases.py b/Lib/test/test_generated_cases.py
index 39ad07ff79be31..3eb650bf3e6942 100644
--- a/Lib/test/test_generated_cases.py
+++ b/Lib/test/test_generated_cases.py
@@ -59,14 +59,14 @@ class TestEffects(unittest.TestCase):
def test_effect_sizes(self):
stack = Stack()
inputs = [
- x := StackItem("x", None, "", "1"),
- y := StackItem("y", None, "", "oparg"),
- z := StackItem("z", None, "", "oparg*2"),
+ x := StackItem("x", None, "1"),
+ y := StackItem("y", None, "oparg"),
+ z := StackItem("z", None, "oparg*2"),
]
outputs = [
- StackItem("x", None, "", "1"),
- StackItem("b", None, "", "oparg*4"),
- StackItem("c", None, "", "1"),
+ StackItem("x", None, "1"),
+ StackItem("b", None, "oparg*4"),
+ StackItem("c", None, "1"),
]
stack.pop(z)
stack.pop(y)
@@ -903,98 +903,6 @@ def test_array_error_if(self):
"""
self.run_cases_test(input, output)
- def test_cond_effect(self):
- input = """
- inst(OP, (aa, input if ((oparg & 1) == 1), cc -- xx, output if (oparg
& 2), zz)) {
- output = SPAM(oparg, aa, cc, input);
- INPUTS_DEAD();
- xx = 0;
- zz = 0;
- }
- """
- output = """
- TARGET(OP) {
- #if Py_TAIL_CALL_INTERP
- int opcode = OP;
- (void)(opcode);
- #endif
- frame->instr_ptr = next_instr;
- next_instr += 1;
- INSTRUCTION_STATS(OP);
- _PyStackRef aa;
- _PyStackRef input = PyStackRef_NULL;
- _PyStackRef cc;
- _PyStackRef xx;
- _PyStackRef output = PyStackRef_NULL;
- _PyStackRef zz;
- cc = stack_pointer[-1];
- if ((oparg & 1) == 1) { input = stack_pointer[-1 - (((oparg & 1)
== 1) ? 1 : 0)]; }
- aa = stack_pointer[-2 - (((oparg & 1) == 1) ? 1 : 0)];
- output = SPAM(oparg, aa, cc, input);
- xx = 0;
- zz = 0;
- stack_pointer[-2 - (((oparg & 1) == 1) ? 1 : 0)] = xx;
- if (oparg & 2) stack_pointer[-1 - (((oparg & 1) == 1) ? 1 : 0)] =
output;
- stack_pointer[-1 - (((oparg & 1) == 1) ? 1 : 0) + ((oparg & 2) ? 1
: 0)] = zz;
- stack_pointer += -(((oparg & 1) == 1) ? 1 : 0) + ((oparg & 2) ? 1
: 0);
- assert(WITHIN_STACK_BOUNDS());
- DISPATCH();
- }
- """
- self.run_cases_test(input, output)
-
- def test_macro_cond_effect(self):
- input = """
- op(A, (left, middle, right --)) {
- USE(left, middle, right);
- INPUTS_DEAD();
- }
- op(B, (-- deep, extra if (oparg), res)) {
- deep = -1;
- res = 0;
- extra = 1;
- INPUTS_DEAD();
- }
- macro(M) = A + B;
- """
- output = """
- TARGET(M) {
- #if Py_TAIL_CALL_INTERP
- int opcode = M;
- (void)(opcode);
- #endif
- frame->instr_ptr = next_instr;
- next_instr += 1;
- INSTRUCTION_STATS(M);
- _PyStackRef left;
- _PyStackRef middle;
- _PyStackRef right;
- _PyStackRef deep;
- _PyStackRef extra = PyStackRef_NULL;
- _PyStackRef res;
- // A
- {
- right = stack_pointer[-1];
- middle = stack_pointer[-2];
- left = stack_pointer[-3];
- USE(left, middle, right);
- }
- // B
- {
- deep = -1;
- res = 0;
- extra = 1;
- }
- stack_pointer[-3] = deep;
- if (oparg) stack_pointer[-2] = extra;
- stack_pointer[-2 + ((oparg) ? 1 : 0)] = res;
- stack_pointer += -1 + ((oparg) ? 1 : 0);
- assert(WITHIN_STACK_BOUNDS());
- DISPATCH();
- }
- """
- self.run_cases_test(input, output)
-
def test_macro_push_push(self):
input = """
op(A, (-- val1)) {
diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c
index 5f39ed11b57e5c..56e3408652a6a0 100644
--- a/Modules/_testinternalcapi.c
+++ b/Modules/_testinternalcapi.c
@@ -28,6 +28,7 @@
#include "pycore_instruction_sequence.h" // _PyInstructionSequence_New()
#include "pycore_interpframe.h" // _PyFrame_GetFunction()
#include "pycore_object.h" // _PyObject_IsFreed()
+#include "pycore_optimizer.h" // _Py_Executor_DependsOn
#include "pycore_pathconfig.h" // _PyPathConfig_ClearGlobal()
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
#include "pycore_pylifecycle.h" // _PyInterpreterConfig_InitFromDict()
diff --git a/Objects/codeobject.c b/Objects/codeobject.c
index c55ab6b9b28e9e..635da094e37a29 100644
--- a/Objects/codeobject.c
+++ b/Objects/codeobject.c
@@ -9,6 +9,7 @@
#include "pycore_interpframe.h" // FRAME_SPECIALS_SIZE
#include "pycore_opcode_metadata.h" // _PyOpcode_Caches
#include "pycore_opcode_utils.h" // RESUME_AT_FUNC_START
+#include "pycore_optimizer.h" // _Py_ExecutorDetach
#include "pycore_pymem.h" // _PyMem_FreeDelayed()
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "pycore_setobject.h" // _PySet_NextEntry()
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 66546080b1f5fe..cdd4d5bdd46b43 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -59,7 +59,6 @@
#define guard
#define override
#define specializing
-#define split
#define replicate(TIMES)
#define tier1
#define no_save_ip
@@ -1686,8 +1685,10 @@ dummy_func(
ERROR_IF(PyStackRef_IsNull(*res), error);
}
- op(_PUSH_NULL_CONDITIONAL, ( -- null if (oparg & 1))) {
- null = PyStackRef_NULL;
+ op(_PUSH_NULL_CONDITIONAL, ( -- null[oparg & 1])) {
+ if (oparg & 1) {
+ null[0] = PyStackRef_NULL;
+ }
}
macro(LOAD_GLOBAL) =
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index ff9f33b6db0187..42a3d6d4be9ba4 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -2285,10 +2285,12 @@
}
case _PUSH_NULL_CONDITIONAL: {
- _PyStackRef null = PyStackRef_NULL;
+ _PyStackRef *null;
oparg = CURRENT_OPARG();
- null = PyStackRef_NULL;
- if (oparg & 1) stack_pointer[0] = null;
+ null = &stack_pointer[0];
+ if (oparg & 1) {
+ null[0] = PyStackRef_NULL;
+ }
stack_pointer += (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
break;
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 558b0b48ceaa71..9ce2b633d5e506 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -6982,7 +6982,7 @@
_PyStackRef class_st;
_PyStackRef self_st;
_PyStackRef attr;
- _PyStackRef null = PyStackRef_NULL;
+ _PyStackRef *null;
/* Skip 1 cache entry */
// _LOAD_SUPER_ATTR
{
@@ -7078,10 +7078,12 @@
}
// _PUSH_NULL_CONDITIONAL
{
- null = PyStackRef_NULL;
+ null = &stack_pointer[1];
+ if (oparg & 1) {
+ null[0] = PyStackRef_NULL;
+ }
}
stack_pointer[0] = attr;
- if (oparg & 1) stack_pointer[1] = null;
stack_pointer += 1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
@@ -7840,7 +7842,7 @@
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect
cache size");
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef null = PyStackRef_NULL;
+ _PyStackRef *null;
/* Skip 1 cache entry */
// _CHECK_ATTR_CLASS
{
@@ -7876,9 +7878,11 @@
}
// _PUSH_NULL_CONDITIONAL
{
- null = PyStackRef_NULL;
+ null = &stack_pointer[0];
+ if (oparg & 1) {
+ null[0] = PyStackRef_NULL;
+ }
}
- if (oparg & 1) stack_pointer[0] = null;
stack_pointer += (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
@@ -7897,7 +7901,7 @@
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect
cache size");
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef null = PyStackRef_NULL;
+ _PyStackRef *null;
/* Skip 1 cache entry */
// _CHECK_ATTR_CLASS
{
@@ -7943,9 +7947,11 @@
}
// _PUSH_NULL_CONDITIONAL
{
- null = PyStackRef_NULL;
+ null = &stack_pointer[0];
+ if (oparg & 1) {
+ null[0] = PyStackRef_NULL;
+ }
}
- if (oparg & 1) stack_pointer[0] = null;
stack_pointer += (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
@@ -8022,7 +8028,7 @@
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect
cache size");
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef null = PyStackRef_NULL;
+ _PyStackRef *null;
/* Skip 1 cache entry */
// _GUARD_TYPE_VERSION
{
@@ -8078,9 +8084,11 @@
/* Skip 5 cache entries */
// _PUSH_NULL_CONDITIONAL
{
- null = PyStackRef_NULL;
+ null = &stack_pointer[0];
+ if (oparg & 1) {
+ null[0] = PyStackRef_NULL;
+ }
}
- if (oparg & 1) stack_pointer[0] = null;
stack_pointer += (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
@@ -8270,7 +8278,7 @@
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect
cache size");
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef null = PyStackRef_NULL;
+ _PyStackRef *null;
/* Skip 1 cache entry */
// _LOAD_ATTR_MODULE
{
@@ -8321,9 +8329,11 @@
/* Skip 5 cache entries */
// _PUSH_NULL_CONDITIONAL
{
- null = PyStackRef_NULL;
+ null = &stack_pointer[0];
+ if (oparg & 1) {
+ null[0] = PyStackRef_NULL;
+ }
}
- if (oparg & 1) stack_pointer[0] = null;
stack_pointer += (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
@@ -8552,7 +8562,7 @@
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect
cache size");
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef null = PyStackRef_NULL;
+ _PyStackRef *null;
/* Skip 1 cache entry */
// _GUARD_TYPE_VERSION
{
@@ -8599,9 +8609,11 @@
/* Skip 5 cache entries */
// _PUSH_NULL_CONDITIONAL
{
- null = PyStackRef_NULL;
+ null = &stack_pointer[0];
+ if (oparg & 1) {
+ null[0] = PyStackRef_NULL;
+ }
}
- if (oparg & 1) stack_pointer[0] = null;
stack_pointer += (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
@@ -8620,7 +8632,7 @@
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect
cache size");
_PyStackRef owner;
_PyStackRef attr;
- _PyStackRef null = PyStackRef_NULL;
+ _PyStackRef *null;
/* Skip 1 cache entry */
// _GUARD_TYPE_VERSION
{
@@ -8700,9 +8712,11 @@
/* Skip 5 cache entries */
// _PUSH_NULL_CONDITIONAL
{
- null = PyStackRef_NULL;
+ null = &stack_pointer[0];
+ if (oparg & 1) {
+ null[0] = PyStackRef_NULL;
+ }
}
- if (oparg & 1) stack_pointer[0] = null;
stack_pointer += (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
@@ -9080,7 +9094,7 @@
_Py_CODEUNIT* const this_instr = next_instr - 5;
(void)this_instr;
_PyStackRef *res;
- _PyStackRef null = PyStackRef_NULL;
+ _PyStackRef *null;
// _SPECIALIZE_LOAD_GLOBAL
{
uint16_t counter = read_u16(&this_instr[1].cache);
@@ -9114,9 +9128,11 @@
}
// _PUSH_NULL_CONDITIONAL
{
- null = PyStackRef_NULL;
+ null = &stack_pointer[1];
+ if (oparg & 1) {
+ null[0] = PyStackRef_NULL;
+ }
}
- if (oparg & 1) stack_pointer[1] = null;
stack_pointer += 1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
@@ -9134,7 +9150,7 @@
INSTRUCTION_STATS(LOAD_GLOBAL_BUILTIN);
static_assert(INLINE_CACHE_ENTRIES_LOAD_GLOBAL == 4, "incorrect
cache size");
_PyStackRef res;
- _PyStackRef null = PyStackRef_NULL;
+ _PyStackRef *null;
/* Skip 1 cache entry */
// _GUARD_GLOBALS_VERSION
{
@@ -9191,10 +9207,12 @@
}
// _PUSH_NULL_CONDITIONAL
{
- null = PyStackRef_NULL;
+ null = &stack_pointer[1];
+ if (oparg & 1) {
+ null[0] = PyStackRef_NULL;
+ }
}
stack_pointer[0] = res;
- if (oparg & 1) stack_pointer[1] = null;
stack_pointer += 1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
@@ -9212,7 +9230,7 @@
INSTRUCTION_STATS(LOAD_GLOBAL_MODULE);
static_assert(INLINE_CACHE_ENTRIES_LOAD_GLOBAL == 4, "incorrect
cache size");
_PyStackRef res;
- _PyStackRef null = PyStackRef_NULL;
+ _PyStackRef *null;
/* Skip 1 cache entry */
// _NOP
{
@@ -9256,10 +9274,12 @@
}
// _PUSH_NULL_CONDITIONAL
{
- null = PyStackRef_NULL;
+ null = &stack_pointer[1];
+ if (oparg & 1) {
+ null[0] = PyStackRef_NULL;
+ }
}
stack_pointer[0] = res;
- if (oparg & 1) stack_pointer[1] = null;
stack_pointer += 1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
@@ -9387,7 +9407,7 @@
_PyStackRef class_st;
_PyStackRef self_st;
_PyStackRef attr;
- _PyStackRef null = PyStackRef_NULL;
+ _PyStackRef *null;
// _SPECIALIZE_LOAD_SUPER_ATTR
{
class_st = stack_pointer[-2];
@@ -9499,10 +9519,12 @@
}
// _PUSH_NULL_CONDITIONAL
{
- null = PyStackRef_NULL;
+ null = &stack_pointer[1];
+ if (oparg & 1) {
+ null[0] = PyStackRef_NULL;
+ }
}
stack_pointer[0] = attr;
- if (oparg & 1) stack_pointer[1] = null;
stack_pointer += 1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
diff --git a/Python/jit.c b/Python/jit.c
index 95b5a1b52b8b65..1f4873ee63a88f 100644
--- a/Python/jit.c
+++ b/Python/jit.c
@@ -8,7 +8,11 @@
#include "pycore_ceval.h"
#include "pycore_critical_section.h"
#include "pycore_dict.h"
+#include "pycore_floatobject.h"
+#include "pycore_frame.h"
+#include "pycore_interpframe.h"
#include "pycore_intrinsics.h"
+#include "pycore_list.h"
#include "pycore_long.h"
#include "pycore_opcode_metadata.h"
#include "pycore_opcode_utils.h"
@@ -16,6 +20,9 @@
#include "pycore_pyerrors.h"
#include "pycore_setobject.h"
#include "pycore_sliceobject.h"
+#include "pycore_tuple.h"
+#include "pycore_unicodeobject.h"
+
#include "pycore_jit.h"
// Memory management stuff:
////////////////////////////////////////////////////
diff --git a/Python/optimizer.c b/Python/optimizer.c
index 6fc5eabdf8b44e..e2fe0f6cff7464 100644
--- a/Python/optimizer.c
+++ b/Python/optimizer.c
@@ -6,11 +6,15 @@
#include "pycore_interp.h"
#include "pycore_backoff.h"
#include "pycore_bitutils.h" // _Py_popcount32()
+#include "pycore_code.h" // _Py_GetBaseCodeUnit
+#include "pycore_interpframe.h"
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
#include "pycore_opcode_metadata.h" // _PyOpcode_OpName[]
#include "pycore_opcode_utils.h" // MAX_REAL_OPCODE
#include "pycore_optimizer.h" // _Py_uop_analyze_and_optimize()
#include "pycore_pystate.h" // _PyInterpreterState_GET()
+#include "pycore_tuple.h" // _PyTuple_FromArraySteal
+#include "pycore_unicodeobject.h" // _PyUnicode_FromASCII
#include "pycore_uop_ids.h"
#include "pycore_jit.h"
#include <stdbool.h>
@@ -1226,11 +1230,7 @@ uop_optimize(
for (int pc = 0; pc < length; pc++) {
int opcode = buffer[pc].opcode;
int oparg = buffer[pc].oparg;
- if (_PyUop_Flags[opcode] & HAS_OPARG_AND_1_FLAG) {
- buffer[pc].opcode = opcode + 1 + (oparg & 1);
- assert(strncmp(_PyOpcode_uop_name[buffer[pc].opcode],
_PyOpcode_uop_name[opcode], strlen(_PyOpcode_uop_name[opcode])) == 0);
- }
- else if (oparg < _PyUop_Replication[opcode]) {
+ if (oparg < _PyUop_Replication[opcode]) {
buffer[pc].opcode = opcode + oparg + 1;
assert(strncmp(_PyOpcode_uop_name[buffer[pc].opcode],
_PyOpcode_uop_name[opcode], strlen(_PyOpcode_uop_name[opcode])) == 0);
}
diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c
index 67bf8d11b3f9ac..017a2eeca0741e 100644
--- a/Python/optimizer_analysis.c
+++ b/Python/optimizer_analysis.c
@@ -21,6 +21,7 @@
#include "pycore_uop_metadata.h"
#include "pycore_dict.h"
#include "pycore_long.h"
+#include "pycore_interpframe.h" // _PyFrame_GetCode
#include "pycore_optimizer.h"
#include "pycore_object.h"
#include "pycore_dict.h"
diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index ea7c39bd01ea07..cfa0a733cda21d 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -546,10 +546,14 @@ dummy_func(void) {
}
}
- op (_PUSH_NULL_CONDITIONAL, ( -- null if (oparg & 1))) {
- int opcode = (oparg & 1) ? _PUSH_NULL : _NOP;
- REPLACE_OP(this_instr, opcode, 0, 0);
- null = sym_new_null(ctx);
+ op (_PUSH_NULL_CONDITIONAL, ( -- null[oparg & 1])) {
+ if (oparg & 1) {
+ REPLACE_OP(this_instr, _PUSH_NULL, 0, 0);
+ null[0] = sym_new_null(ctx);
+ }
+ else {
+ REPLACE_OP(this_instr, _NOP, 0, 0);
+ }
}
op(_LOAD_ATTR, (owner -- attr, self_or_null[oparg&1])) {
@@ -765,7 +769,7 @@ dummy_func(void) {
Py_UNREACHABLE();
}
- op(_PUSH_FRAME, (new_frame: _Py_UOpsAbstractFrame * -- unused if (0))) {
+ op(_PUSH_FRAME, (new_frame: _Py_UOpsAbstractFrame * -- )) {
SYNC_SP();
ctx->frame->stack_pointer = stack_pointer;
ctx->frame = new_frame;
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index 3f315901a5beb8..fc70ee31a80002 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -921,11 +921,15 @@
}
case _PUSH_NULL_CONDITIONAL: {
- JitOptSymbol *null = NULL;
- int opcode = (oparg & 1) ? _PUSH_NULL : _NOP;
- REPLACE_OP(this_instr, opcode, 0, 0);
- null = sym_new_null(ctx);
- if (oparg & 1) stack_pointer[0] = null;
+ JitOptSymbol **null;
+ null = &stack_pointer[0];
+ if (oparg & 1) {
+ REPLACE_OP(this_instr, _PUSH_NULL, 0, 0);
+ null[0] = sym_new_null(ctx);
+ }
+ else {
+ REPLACE_OP(this_instr, _NOP, 0, 0);
+ }
stack_pointer += (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
break;
diff --git a/Python/optimizer_symbols.c b/Python/optimizer_symbols.c
index 8445546ffdf716..c50f98cb99b396 100644
--- a/Python/optimizer_symbols.c
+++ b/Python/optimizer_symbols.c
@@ -6,6 +6,7 @@
#include "pycore_frame.h"
#include "pycore_long.h"
#include "pycore_optimizer.h"
+#include "pycore_stats.h"
#include "pycore_tuple.h" // _PyTuple_FromArray()
#include <stdbool.h>
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index 8fe58c320a33b2..ed21fce335c99d 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -18,6 +18,7 @@
#include "pycore_long.h" // _PyLong_InitTypes()
#include "pycore_object.h" // _PyDebug_PrintTotalRefs()
#include "pycore_obmalloc.h" // _PyMem_init_obmalloc()
+#include "pycore_optimizer.h" // _Py_Executors_InvalidateAll
#include "pycore_pathconfig.h" // _PyPathConfig_UpdateGlobal()
#include "pycore_pyerrors.h" // _PyErr_Occurred()
#include "pycore_pylifecycle.h" // _PyErr_Print()
diff --git a/Tools/cases_generator/analyzer.py
b/Tools/cases_generator/analyzer.py
index e0ef198c1646c2..ac2cfb7b50be40 100644
--- a/Tools/cases_generator/analyzer.py
+++ b/Tools/cases_generator/analyzer.py
@@ -33,7 +33,6 @@ class Properties:
pure: bool
uses_opcode: bool
tier: int | None = None
- oparg_and_1: bool = False
const_oparg: int = -1
needs_prev: bool = False
no_save_ip: bool = False
@@ -136,16 +135,14 @@ def size(self) -> int:
class StackItem:
name: str
type: str | None
- condition: str | None
size: str
peek: bool = False
used: bool = False
def __str__(self) -> str:
- cond = f" if ({self.condition})" if self.condition else ""
size = f"[{self.size}]" if self.size else ""
type = "" if self.type is None else f"{self.type} "
- return f"{type}{self.name}{size}{cond} {self.peek}"
+ return f"{type}{self.name}{size} {self.peek}"
def is_array(self) -> bool:
return self.size != ""
@@ -348,10 +345,7 @@ def override_error(
def convert_stack_item(
item: parser.StackEffect, replace_op_arg_1: str | None
) -> StackItem:
- cond = item.cond
- if replace_op_arg_1 and OPARG_AND_1.match(item.cond):
- cond = replace_op_arg_1
- return StackItem(item.name, item.type, cond, item.size)
+ return StackItem(item.name, item.type, item.size)
def check_unused(stack: list[StackItem], input_names: dict[str, lexer.Token])
-> None:
"Unused items cannot be on the stack above used, non-peek items"
@@ -815,33 +809,12 @@ def stack_effect_only_peeks(instr: parser.InstDef) ->
bool:
return False
if len(stack_inputs) == 0:
return False
- if any(s.cond for s in stack_inputs) or any(s.cond for s in instr.outputs):
- return False
return all(
(s.name == other.name and s.type == other.type and s.size ==
other.size)
for s, other in zip(stack_inputs, instr.outputs)
)
-OPARG_AND_1 = re.compile("\\(*oparg *& *1")
-
-
-def effect_depends_on_oparg_1(op: parser.InstDef) -> bool:
- for effect in op.inputs:
- if isinstance(effect, parser.CacheEffect):
- continue
- if not effect.cond:
- continue
- if OPARG_AND_1.match(effect.cond):
- return True
- for effect in op.outputs:
- if not effect.cond:
- continue
- if OPARG_AND_1.match(effect.cond):
- return True
- return False
-
-
def compute_properties(op: parser.CodeDef) -> Properties:
escaping_calls = find_escaping_api_calls(op)
has_free = (
@@ -908,29 +881,6 @@ def make_uop(
body=op.block.tokens,
properties=compute_properties(op),
)
- if effect_depends_on_oparg_1(op) and "split" in op.annotations:
- result.properties.oparg_and_1 = True
- for bit in ("0", "1"):
- name_x = name + "_" + bit
- properties = compute_properties(op)
- if properties.oparg:
- # May not need oparg anymore
- properties.oparg = any(
- token.text == "oparg" for token in op.block.tokens
- )
- rep = Uop(
- name=name_x,
- context=op.context,
- annotations=op.annotations,
- stack=analyze_stack(op, bit),
- caches=analyze_caches(inputs),
- deferred_refs=analyze_deferred_refs(op),
- output_stores=find_stores_outputs(op),
- body=op.block.tokens,
- properties=properties,
- )
- rep.replicates = result
- uops[name_x] = rep
for anno in op.annotations:
if anno.startswith("replicate"):
result.replicated = int(anno[10:-1])
diff --git a/Tools/cases_generator/generators_common.py
b/Tools/cases_generator/generators_common.py
index 8e6bc5a8995dc9..fc0b468266078d 100644
--- a/Tools/cases_generator/generators_common.py
+++ b/Tools/cases_generator/generators_common.py
@@ -648,8 +648,6 @@ def cflags(p: Properties) -> str:
flags.append("HAS_PURE_FLAG")
if p.no_save_ip:
flags.append("HAS_NO_SAVE_IP_FLAG")
- if p.oparg_and_1:
- flags.append("HAS_OPARG_AND_1_FLAG")
if flags:
return " | ".join(flags)
else:
diff --git a/Tools/cases_generator/lexer.py b/Tools/cases_generator/lexer.py
index 6afca750be9b19..b4bcd73fdbfe52 100644
--- a/Tools/cases_generator/lexer.py
+++ b/Tools/cases_generator/lexer.py
@@ -227,7 +227,6 @@ def choice(*opts: str) -> str:
"register",
"replaced",
"pure",
- "split",
"replicate",
"tier1",
"tier2",
diff --git a/Tools/cases_generator/optimizer_generator.py
b/Tools/cases_generator/optimizer_generator.py
index b265847a26c971..15be7608e93937 100644
--- a/Tools/cases_generator/optimizer_generator.py
+++ b/Tools/cases_generator/optimizer_generator.py
@@ -48,19 +48,13 @@ def declare_variables(uop: Uop, out: CWriter, skip_inputs:
bool) -> None:
for var in reversed(uop.stack.inputs):
if var.used and var.name not in variables:
variables.add(var.name)
- if var.condition:
- out.emit(f"{type_name(var)}{var.name} = NULL;\n")
- else:
- out.emit(f"{type_name(var)}{var.name};\n")
+ out.emit(f"{type_name(var)}{var.name};\n")
for var in uop.stack.outputs:
if var.peek:
continue
if var.name not in variables:
variables.add(var.name)
- if var.condition:
- out.emit(f"{type_name(var)}{var.name} = NULL;\n")
- else:
- out.emit(f"{type_name(var)}{var.name};\n")
+ out.emit(f"{type_name(var)}{var.name};\n")
def decref_inputs(
diff --git a/Tools/cases_generator/parsing.py b/Tools/cases_generator/parsing.py
index 011f34de288871..84aed49d491e01 100644
--- a/Tools/cases_generator/parsing.py
+++ b/Tools/cases_generator/parsing.py
@@ -77,12 +77,11 @@ class Block(Node):
class StackEffect(Node):
name: str = field(compare=False) # __eq__ only uses type, cond, size
type: str = "" # Optional `:type`
- cond: str = "" # Optional `if (cond)`
size: str = "" # Optional `[size]`
# Note: size cannot be combined with type or cond
def __repr__(self) -> str:
- items = [self.name, self.type, self.cond, self.size]
+ items = [self.name, self.type, self.size]
while items and items[-1] == "":
del items[-1]
return f"StackEffect({', '.join(repr(item) for item in items)})"
@@ -299,22 +298,15 @@ def stack_effect(self) -> StackEffect | None:
type_text = self.require(lx.IDENTIFIER).text.strip()
if self.expect(lx.TIMES):
type_text += " *"
- cond_text = ""
- if self.expect(lx.IF):
- self.require(lx.LPAREN)
- if not (cond := self.expression()):
- raise self.make_syntax_error("Expected condition")
- self.require(lx.RPAREN)
- cond_text = cond.text.strip()
size_text = ""
if self.expect(lx.LBRACKET):
- if type_text or cond_text:
+ if type_text:
raise self.make_syntax_error("Unexpected [")
if not (size := self.expression()):
raise self.make_syntax_error("Expected expression")
self.require(lx.RBRACKET)
size_text = size.text.strip()
- return StackEffect(tkn.text, type_text, cond_text, size_text)
+ return StackEffect(tkn.text, type_text, size_text)
return None
@contextual
diff --git a/Tools/cases_generator/stack.py b/Tools/cases_generator/stack.py
index 51c4c810e20714..70fa8abe513953 100644
--- a/Tools/cases_generator/stack.py
+++ b/Tools/cases_generator/stack.py
@@ -23,17 +23,7 @@ def maybe_parenthesize(sym: str) -> str:
def var_size(var: StackItem) -> str:
- if var.condition:
- # Special case simplifications
- if var.condition == "0":
- return "0"
- elif var.condition == "1":
- return var.get_size()
- elif var.condition == "oparg & 1" and not var.size:
- return f"({var.condition})"
- else:
- return f"(({var.condition}) ? {var.get_size()} : 0)"
- elif var.size:
+ if var.size:
return var.size
else:
return "1"
@@ -89,10 +79,6 @@ def size(self) -> str:
def name(self) -> str:
return self.item.name
- @property
- def condition(self) -> str | None:
- return self.item.condition
-
def is_array(self) -> bool:
return self.item.is_array()
@@ -275,15 +261,7 @@ def pop(self, var: StackItem) -> tuple[str, Local]:
cast = f"({var.type})" if (not indirect and var.type) else ""
bits = ".bits" if cast and self.extract_bits else ""
assign = f"{var.name} =
{cast}{indirect}stack_pointer[{self.base_offset.to_c()}]{bits};"
- if var.condition:
- if var.condition == "1":
- assign = f"{assign}\n"
- elif var.condition == "0":
- return "", Local.unused(var)
- else:
- assign = f"if ({var.condition}) {{ {assign} }}\n"
- else:
- assign = f"{assign}\n"
+ assign = f"{assign}\n"
return assign, Local.from_memory(var)
def push(self, var: Local) -> None:
@@ -303,10 +281,6 @@ def _do_emit(
) -> None:
cast = f"({cast_type})" if var.type else ""
bits = ".bits" if cast and extract_bits else ""
- if var.condition == "0":
- return
- if var.condition and var.condition != "1":
- out.emit(f"if ({var.condition}) ")
out.emit(f"stack_pointer[{base_offset.to_c()}]{bits} =
{cast}{var.name};\n")
def _adjust_stack_pointer(self, out: CWriter, number: str) -> None:
@@ -655,7 +629,7 @@ def close_named(close: str, name: str, overwrite: str) ->
None:
def close_variable(var: Local, overwrite: str) -> None:
nonlocal tmp_defined
close = "PyStackRef_CLOSE"
- if "null" in var.name or var.condition and var.condition != "1":
+ if "null" in var.name:
close = "PyStackRef_XCLOSE"
if var.size:
if var.size == "1":
@@ -668,8 +642,6 @@ def close_variable(var: Local, overwrite: str) -> None:
close_named(close, f"{var.name}[_i]", overwrite)
out.emit("}\n")
else:
- if var.condition and var.condition == "0":
- return
close_named(close, var.name, overwrite)
self.clear_dead_inputs()
diff --git a/Tools/cases_generator/tier1_generator.py
b/Tools/cases_generator/tier1_generator.py
index 0f0addb3d99589..ee375681b50f0b 100644
--- a/Tools/cases_generator/tier1_generator.py
+++ b/Tools/cases_generator/tier1_generator.py
@@ -40,10 +40,7 @@
def declare_variable(var: StackItem, out: CWriter) -> None:
type, null = type_and_null(var)
space = " " if type[-1].isalnum() else ""
- if var.condition:
- out.emit(f"{type}{space}{var.name} = {null};\n")
- else:
- out.emit(f"{type}{space}{var.name};\n")
+ out.emit(f"{type}{space}{var.name};\n")
def declare_variables(inst: Instruction, out: CWriter) -> None:
diff --git a/Tools/cases_generator/tier2_generator.py
b/Tools/cases_generator/tier2_generator.py
index d378815f6af391..572c636e84c0ca 100644
--- a/Tools/cases_generator/tier2_generator.py
+++ b/Tools/cases_generator/tier2_generator.py
@@ -41,14 +41,7 @@ def declare_variable(
required.remove(var.name)
type, null = type_and_null(var)
space = " " if type[-1].isalnum() else ""
- if var.condition:
- out.emit(f"{type}{space}{var.name} = {null};\n")
- if uop.replicates:
- # Replicas may not use all their conditional variables
- # So avoid a compiler warning with a fake use
- out.emit(f"(void){var.name};\n")
- else:
- out.emit(f"{type}{space}{var.name};\n")
+ out.emit(f"{type}{space}{var.name};\n")
def declare_variables(uop: Uop, out: CWriter) -> None:
@@ -189,9 +182,6 @@ def generate_tier2(
for name, uop in analysis.uops.items():
if uop.properties.tier == 1:
continue
- if uop.properties.oparg_and_1:
- out.emit(f"/* {uop.name} is split on (oparg & 1) */\n\n")
- continue
if uop.is_super():
continue
why_not_viable = uop.why_not_viable()
diff --git a/Tools/jit/template.c b/Tools/jit/template.c
index 0b7d077d78ce7d..adc08f3cc5f2a5 100644
--- a/Tools/jit/template.c
+++ b/Tools/jit/template.c
@@ -4,10 +4,16 @@
#include "pycore_call.h"
#include "pycore_ceval.h"
#include "pycore_cell.h"
+#include "pycore_code.h"
#include "pycore_dict.h"
+#include "pycore_floatobject.h"
#include "pycore_emscripten_signal.h"
+#include "pycore_frame.h"
+#include "pycore_genobject.h"
+#include "pycore_interpframe.h"
#include "pycore_intrinsics.h"
#include "pycore_jit.h"
+#include "pycore_list.h"
#include "pycore_long.h"
#include "pycore_opcode_metadata.h"
#include "pycore_opcode_utils.h"
@@ -18,6 +24,8 @@
#include "pycore_sliceobject.h"
#include "pycore_descrobject.h"
#include "pycore_stackref.h"
+#include "pycore_tuple.h"
+#include "pycore_unicodeobject.h"
#include "ceval_macros.h"
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]