aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Tools/cases_generator/optimizer_generator.py
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/cases_generator/optimizer_generator.py')
-rw-r--r--Tools/cases_generator/optimizer_generator.py78
1 files changed, 46 insertions, 32 deletions
diff --git a/Tools/cases_generator/optimizer_generator.py b/Tools/cases_generator/optimizer_generator.py
index b74f627235a..7a1dfe1b85b 100644
--- a/Tools/cases_generator/optimizer_generator.py
+++ b/Tools/cases_generator/optimizer_generator.py
@@ -18,11 +18,12 @@ from generators_common import (
ROOT,
write_header,
Emitter,
+ TokenIterator,
)
from cwriter import CWriter
from typing import TextIO, Iterator
from lexer import Token
-from stack import Local, Stack, StackError
+from stack import Local, Stack, StackError, Storage
DEFAULT_OUTPUT = ROOT / "Python/optimizer_cases.c.h"
DEFAULT_ABSTRACT_INPUT = (ROOT / "Python/optimizer_bytecodes.c").absolute().as_posix()
@@ -45,7 +46,7 @@ def declare_variables(uop: Uop, out: CWriter, skip_inputs: bool) -> None:
variables = {"unused"}
if not skip_inputs:
for var in reversed(uop.stack.inputs):
- if var.name not in variables:
+ 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")
@@ -65,7 +66,7 @@ def declare_variables(uop: Uop, out: CWriter, skip_inputs: bool) -> None:
def decref_inputs(
out: CWriter,
tkn: Token,
- tkn_iter: Iterator[Token],
+ tkn_iter: TokenIterator,
uop: Uop,
stack: Stack,
inst: Instruction | None,
@@ -76,13 +77,27 @@ def decref_inputs(
out.emit_at("", tkn)
-def emit_default(out: CWriter, uop: Uop) -> None:
- for i, var in enumerate(uop.stack.outputs):
+def emit_default(out: CWriter, uop: Uop, stack: Stack) -> None:
+ for var in reversed(uop.stack.inputs):
+ stack.pop(var)
+ top_offset = stack.top_offset.copy()
+ for var in uop.stack.outputs:
+ if var.is_array() and not var.peek and not var.name == "unused":
+ c_offset = top_offset.to_c()
+ out.emit(f"{var.name} = &stack_pointer[{c_offset}];\n")
+ top_offset.push(var)
+ for var in uop.stack.outputs:
+ local = Local.undefined(var)
+ stack.push(local)
if var.name != "unused" and not var.peek:
+ local.defined = True
if var.is_array():
- out.emit(f"for (int _i = {var.size}; --_i >= 0;) {{\n")
- out.emit(f"{var.name}[_i] = sym_new_not_null(ctx);\n")
- out.emit("}\n")
+ if var.size == "1":
+ out.emit(f"{var.name}[0] = sym_new_not_null(ctx);\n")
+ else:
+ out.emit(f"for (int _i = {var.size}; --_i >= 0;) {{\n")
+ out.emit(f"{var.name}[_i] = sym_new_not_null(ctx);\n")
+ out.emit("}\n")
elif var.name == "null":
out.emit(f"{var.name} = sym_new_null(ctx);\n")
else:
@@ -90,7 +105,12 @@ def emit_default(out: CWriter, uop: Uop) -> None:
class OptimizerEmitter(Emitter):
- pass
+
+ def emit_save(self, storage: Storage) -> None:
+ storage.flush(self.out)
+
+ def emit_reload(self, storage: Storage) -> None:
+ pass
def write_uop(
@@ -102,22 +122,18 @@ def write_uop(
skip_inputs: bool,
) -> None:
locals: dict[str, Local] = {}
+ prototype = override if override else uop
try:
- prototype = override if override else uop
- is_override = override is not None
out.start_line()
- for var in reversed(prototype.stack.inputs):
- code, local = stack.pop(var, extract_bits=True)
- if not skip_inputs:
+ if override:
+ code_list, storage = Storage.for_uop(stack, prototype, extract_bits=False)
+ for code in code_list:
out.emit(code)
- if local.defined:
- locals[local.name] = local
- out.emit(stack.define_output_arrays(prototype.stack.outputs))
if debug:
args = []
- for var in prototype.stack.inputs:
- if not var.peek or is_override:
- args.append(var.name)
+ for input in prototype.stack.inputs:
+ if not input.peek or override:
+ args.append(input.name)
out.emit(f'DEBUG_PRINTF({", ".join(args)});\n')
if override:
for cache in uop.caches:
@@ -130,20 +146,18 @@ def write_uop(
out.emit(f"{type}{cache.name} = ({cast})this_instr->operand;\n")
if override:
emitter = OptimizerEmitter(out)
- emitter.emit_tokens(override, stack, None)
+ # No reference management of inputs needed.
+ for var in storage.inputs: # type: ignore[possibly-undefined]
+ var.defined = False
+ storage = emitter.emit_tokens(override, storage, None)
+ out.start_line()
+ storage.flush(out, cast_type="_Py_UopsSymbol *", extract_bits=False)
else:
- emit_default(out, uop)
-
- for var in prototype.stack.outputs:
- if var.name in locals:
- local = locals[var.name]
- else:
- local = Local.local(var)
- stack.push(local)
- out.start_line()
- stack.flush(out, cast_type="_Py_UopsSymbol *", extract_bits=True)
+ emit_default(out, uop, stack)
+ out.start_line()
+ stack.flush(out, cast_type="_Py_UopsSymbol *", extract_bits=False)
except StackError as ex:
- raise analysis_error(ex.args[0], uop.body[0])
+ raise analysis_error(ex.args[0], prototype.body[0]) # from None
SKIPS = ("_EXTENDED_ARG",)