From e0d8c95de4aac5cad1221a5852c56c4179c331a3 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Thu, 20 Mar 2025 10:45:47 +0000 Subject: [PATCH 1/6] Remove conditional stack effects -- We no longer need them --- Python/bytecodes.c | 7 +- Python/executor_cases.c.h | 8 +- Python/generated_cases.c.h | 88 ++++++++++++-------- Python/optimizer.c | 6 +- Python/optimizer_bytecodes.c | 14 ++-- Python/optimizer_cases.c.h | 14 ++-- Tools/cases_generator/analyzer.py | 54 +----------- Tools/cases_generator/generators_common.py | 2 - Tools/cases_generator/lexer.py | 1 - Tools/cases_generator/optimizer_generator.py | 10 +-- Tools/cases_generator/parsing.py | 14 +--- Tools/cases_generator/stack.py | 34 +------- Tools/cases_generator/tier1_generator.py | 5 +- Tools/cases_generator/tier2_generator.py | 12 +-- 14 files changed, 95 insertions(+), 174 deletions(-) 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/optimizer.c b/Python/optimizer.c index 6fc5eabdf8b44e..aa60f538bbe5c0 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -1226,11 +1226,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_bytecodes.c b/Python/optimizer_bytecodes.c index ea7c39bd01ea07..486751847a43cf 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); + } } 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..f8962b6054f94e 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); + } stack_pointer += (oparg & 1); assert(WITHIN_STACK_BOUNDS()); break; 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 eb7d1967eb75c3..2f0b00d657f1bf 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: @@ -665,7 +639,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": @@ -678,8 +652,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() From accf4c9130cc8bd290fc16ce93d22cfee7b16ea9 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Thu, 20 Mar 2025 11:17:06 +0000 Subject: [PATCH 2/6] Update test --- Lib/test/test_generated_cases.py | 137 ++----------------------------- 1 file changed, 6 insertions(+), 131 deletions(-) diff --git a/Lib/test/test_generated_cases.py b/Lib/test/test_generated_cases.py index 32d14548159cce..69967f1d6c19bf 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) @@ -104,20 +104,6 @@ def test_push_one(self): """ self.check(input, output) - def test_cond_push(self): - input = """ - inst(OP, (a -- b, c if (oparg))) { - SPAM(); - } - """ - output = """ - case OP: { - *effect = ((oparg) ? 1 : 0); - return 0; - } - """ - self.check(input, output) - def test_ops_pass_two(self): input = """ op(A, (-- val1)) { @@ -138,25 +124,6 @@ def test_ops_pass_two(self): """ self.check(input, output) - def test_ops_pass_two_cond_push(self): - input = """ - op(A, (-- val1, val2)) { - val1 = 0; - val2 = 1; - } - op(B, (val1, val2 -- val1, val2, val3 if (oparg))) { - val3 = SPAM(); - } - macro(OP) = A + B; - """ - output = """ - case OP: { - *effect = Py_MAX(2, 2 + ((oparg) ? 1 : 0)); - return 0; - } - """ - self.check(input, output) - def test_pop_push_array(self): input = """ inst(OP, (values[oparg] -- values[oparg], above)) { @@ -1074,98 +1041,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)) { From 6b3bbf18edc912cde0a7d1fdef5af910d00f5a3b Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Thu, 20 Mar 2025 12:00:29 +0000 Subject: [PATCH 3/6] Add missing include --- Objects/codeobject.c | 1 + 1 file changed, 1 insertion(+) 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() From dfaba30fbf18796172389f480e573b790c17e6df Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Thu, 20 Mar 2025 12:13:38 +0000 Subject: [PATCH 4/6] Add missing #includes --- Modules/_testinternalcapi.c | 1 + Python/optimizer.c | 4 ++++ Python/optimizer_analysis.c | 1 + Python/optimizer_bytecodes.c | 2 +- Python/optimizer_cases.c.h | 2 +- Python/optimizer_symbols.c | 1 + Python/pylifecycle.c | 1 + 7 files changed, 10 insertions(+), 2 deletions(-) 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/Python/optimizer.c b/Python/optimizer.c index aa60f538bbe5c0..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 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 486751847a43cf..cfa0a733cda21d 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -552,7 +552,7 @@ dummy_func(void) { null[0] = sym_new_null(ctx); } else { - REPLACE_OP(this_instr, _NOP); + REPLACE_OP(this_instr, _NOP, 0, 0); } } diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index f8962b6054f94e..fc70ee31a80002 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -928,7 +928,7 @@ null[0] = sym_new_null(ctx); } else { - REPLACE_OP(this_instr, _NOP); + REPLACE_OP(this_instr, _NOP, 0, 0); } stack_pointer += (oparg & 1); assert(WITHIN_STACK_BOUNDS()); 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 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() From 7add005ee61e4764f7f200cc550c921fd0f2ae0e Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Thu, 20 Mar 2025 14:00:13 +0000 Subject: [PATCH 5/6] Add jit includes --- Include/internal/pycore_jit.h | 4 ++++ 1 file changed, 4 insertions(+) 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 From b6ab21ebff428ad3ce76b0af967d6787ea91406e Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Thu, 20 Mar 2025 14:32:50 +0000 Subject: [PATCH 6/6] Add more JIT includes --- Python/jit.c | 7 +++++++ Tools/jit/template.c | 8 ++++++++ 2 files changed, 15 insertions(+) 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/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" pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy