diff options
author | Mark Shannon <mark@hotpy.org> | 2025-03-20 15:39:38 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-03-20 15:39:38 +0000 |
commit | 7ebd71ee14a497bb5dc7a693dd00f074a9f4831f (patch) | |
tree | 15c6214a266592b9ade709dd45c818a5f972f0a4 /Tools | |
parent | 443c0cd17c5b0c71ee45c3621777454c6b8b0cbd (diff) | |
download | cpython-7ebd71ee14a497bb5dc7a693dd00f074a9f4831f.tar.gz cpython-7ebd71ee14a497bb5dc7a693dd00f074a9f4831f.zip |
GH-131498: Remove conditional stack effects (GH-131499)
* Adds some missing #includes
Diffstat (limited to 'Tools')
-rw-r--r-- | Tools/cases_generator/analyzer.py | 54 | ||||
-rw-r--r-- | Tools/cases_generator/generators_common.py | 2 | ||||
-rw-r--r-- | Tools/cases_generator/lexer.py | 1 | ||||
-rw-r--r-- | Tools/cases_generator/optimizer_generator.py | 10 | ||||
-rw-r--r-- | Tools/cases_generator/parsing.py | 14 | ||||
-rw-r--r-- | Tools/cases_generator/stack.py | 34 | ||||
-rw-r--r-- | Tools/cases_generator/tier1_generator.py | 5 | ||||
-rw-r--r-- | Tools/cases_generator/tier2_generator.py | 12 | ||||
-rw-r--r-- | Tools/jit/template.c | 8 |
9 files changed, 20 insertions, 120 deletions
diff --git a/Tools/cases_generator/analyzer.py b/Tools/cases_generator/analyzer.py index e0ef198c164..ac2cfb7b50b 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 @@ class Flush: 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 8e6bc5a8995..fc0b4682660 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 6afca750be9..b4bcd73fdbf 100644 --- a/Tools/cases_generator/lexer.py +++ b/Tools/cases_generator/lexer.py @@ -227,7 +227,6 @@ annotations = { "register", "replaced", "pure", - "split", "replicate", "tier1", "tier2", diff --git a/Tools/cases_generator/optimizer_generator.py b/Tools/cases_generator/optimizer_generator.py index b265847a26c..15be7608e93 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 011f34de288..84aed49d491 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 @@ class Parser(PLexer): 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 51c4c810e20..70fa8abe513 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 @@ class Local: 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 @@ class Stack: 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 @@ class Stack: ) -> 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 @@ class Storage: 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 @@ class Storage: 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 0f0addb3d99..ee375681b50 100644 --- a/Tools/cases_generator/tier1_generator.py +++ b/Tools/cases_generator/tier1_generator.py @@ -40,10 +40,7 @@ LABEL_END_MARKER = "/* END LABELS */" 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 d378815f6af..572c636e84c 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 0b7d077d78c..adc08f3cc5f 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" |