GH-128914: Remove conditional stack effects from bytecodes.c and the code generators (GH-128918)

This commit is contained in:
Mark Shannon 2025-01-20 17:09:23 +00:00 committed by GitHub
parent 0a6412f9cc
commit ab61d3f430
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
44 changed files with 1460 additions and 1679 deletions

View file

@ -25,7 +25,6 @@ class Properties:
side_exit: bool
pure: bool
tier: int | None = None
oparg_and_1: bool = False
const_oparg: int = -1
needs_prev: bool = False
no_save_ip: bool = False
@ -124,16 +123,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 != ""
@ -315,25 +312,19 @@ 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)
def convert_stack_item(item: parser.StackEffect) -> StackItem:
return StackItem(item.name, item.type, item.size)
def analyze_stack(
op: parser.InstDef | parser.Pseudo, replace_op_arg_1: str | None = None
) -> StackEffect:
op: parser.InstDef | parser.Pseudo) -> StackEffect:
inputs: list[StackItem] = [
convert_stack_item(i, replace_op_arg_1)
convert_stack_item(i)
for i in op.inputs
if isinstance(i, parser.StackEffect)
]
outputs: list[StackItem] = [
convert_stack_item(i, replace_op_arg_1) for i in op.outputs
convert_stack_item(i) for i in op.outputs
]
# Mark variables with matching names at the base of the stack as "peek"
modified = False
@ -756,40 +747,6 @@ def always_exits(op: parser.InstDef) -> bool:
return True
return False
def stack_effect_only_peeks(instr: parser.InstDef) -> bool:
stack_inputs = [s for s in instr.inputs if not isinstance(s, parser.CacheEffect)]
if len(stack_inputs) != len(instr.outputs):
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.InstDef) -> Properties:
escaping_calls = find_escaping_api_calls(op)
has_free = (
@ -863,29 +820,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])