Summary
Static parity review found that Pyre still lacks several RPython/PyPy graph/codewriter normalization properties that are assumed before flatten_graph runs upstream.
This issue tracks the newly identified work as one umbrella issue. Existing issues cover the broader tracer/codewriter architecture (#50, #73, #97) and tuple specialization (#59); this issue is specifically for the remaining graph/codewriter parity gaps found during the review.
Background
RPython's normal pipeline is:
build_flow(func)
-> simplify_graph(graph)
-> perform_register_allocation(graph)
-> flatten_graph(graph, regallocs)
-> compute_liveness(ssarepr)
-> assemble(ssarepr)
flatten_graph assumes it receives a graph already normalized by rpython/translator/simplify.py::simplify_graph. Pyre currently has a split path where the Python-bytecode walker emits SSARepr inline while graph dual-writes are later used for regalloc/canonical checks. That split makes missing graph normalization visible as label/renaming/liveness repair logic that PyPy does not need.
The recent dead-forwarder work is one example: eliminate_empty_blocks graph collapse is PyPy-orthodox, but Pyre also needs a pyre-only TLabel retarget bridge because the walker may already have emitted labels before the graph reaches the final simplified shape.
Scope
1. Port missing simplify_graph passes
PyPy/RPython runs the pass list in rpython/translator/simplify.py before codewriter flattening:
transform_dead_op_vars
eliminate_empty_blocks
remove_assertion_errors
remove_identical_vars_SSA
constfold_exitswitch
remove_trivial_links
SSA_to_SSI
coalesce_bool
transform_ovfcheck
simplify_exceptions
transform_xxxitem
remove_dead_exceptions
Pyre should port the passes that are relevant to its graph/codewriter pipeline, with explicit structural-adaptation notes where a 1:1 port is impossible.
Initial priority candidates:
remove_trivial_links
remove_identical_vars_SSA
SSA_to_SSI
simplify_exceptions
constfold_exitswitch
Acceptance criteria for each ported pass:
- document the corresponding RPython source function and any intentional adaptation;
- add focused graph-shape tests where feasible;
- ensure downstream regalloc/flatten sees the normalized shape;
- avoid adding walker-only byte-stream repairs when a graph-level normalization is the PyPy source of truth.
2. Match PyPy regalloc coalesce semantics
Static review found an existing parity gap in CFG coalescing.
PyPy regalloc.py coalesces after dependency/interference analysis and rejects a candidate when the two variables interfere. Pyre currently pre-merges CFG link.args <-> target.inputargs pairs alongside walker pin pairs in a way that can bypass the equivalent interference check.
Work needed:
- compare Pyre coalescing against PyPy
regalloc.py _try_coalesce semantics;
- avoid unconditional pre-merge for CFG pairs that PyPy would reject;
- preserve or replace performance-sensitive walker pinning with an orthodox equivalent;
- measure whether extra
ref_copy emission comes from correct PyPy parity or from a remaining walker/regalloc mismatch.
This is related to #50 and #73, but it can be investigated independently at the graph/regalloc layer.
3. Investigate unmarked JitCode label panic
A pre-existing panic has been observed in the assembler patching path:
majit/majit-metainterp/src/jitcode/assembler.rs:4121
jitcode label was never marked
This should be tracked here as a graph/codewriter/label parity gap until proven otherwise.
Work needed:
- trace every
TLabel / patch allocation path to a corresponding emitted Label / mark_label path;
- classify whether the missing label originates in graph shape, flatten emission order, switch/default handling, trampoline/forwarder handling, or assembler bookkeeping;
- add an invariant or diagnostic that reports the originating opname/label name/graph before the final
patch_labels panic;
- determine whether any missing
simplify_graph pass makes the problematic label shape reachable.
If investigation proves this is purely backend assembler state unrelated to graph/codewriter parity, split it out into a narrower follow-up issue.
4. Keep structural adaptations explicit
Some Pyre/PyPy differences are structural and should not be forced into a literal port:
Each pass or repair should say whether it is:
Related existing issues / PRs
Non-goals
Suggested execution order
- Add a small parity test harness for graph simplification outputs.
- Port
remove_trivial_links and remove_identical_vars_SSA first.
- Port or classify
SSA_to_SSI and simplify_exceptions.
- Re-audit regalloc coalescing after graph normalization changes.
- Add label-origin diagnostics for the unmarked-label panic.
- Split any clearly independent backend-only finding into a separate issue.
Summary
Static parity review found that Pyre still lacks several RPython/PyPy graph/codewriter normalization properties that are assumed before
flatten_graphruns upstream.This issue tracks the newly identified work as one umbrella issue. Existing issues cover the broader tracer/codewriter architecture (#50, #73, #97) and tuple specialization (#59); this issue is specifically for the remaining graph/codewriter parity gaps found during the review.
Background
RPython's normal pipeline is:
flatten_graphassumes it receives a graph already normalized byrpython/translator/simplify.py::simplify_graph. Pyre currently has a split path where the Python-bytecode walker emits SSARepr inline while graph dual-writes are later used for regalloc/canonical checks. That split makes missing graph normalization visible as label/renaming/liveness repair logic that PyPy does not need.The recent dead-forwarder work is one example:
eliminate_empty_blocksgraph collapse is PyPy-orthodox, but Pyre also needs a pyre-onlyTLabelretarget bridge because the walker may already have emitted labels before the graph reaches the final simplified shape.Scope
1. Port missing
simplify_graphpassesPyPy/RPython runs the pass list in
rpython/translator/simplify.pybefore codewriter flattening:transform_dead_op_varseliminate_empty_blocksremove_assertion_errorsremove_identical_vars_SSAconstfold_exitswitchremove_trivial_linksSSA_to_SSIcoalesce_booltransform_ovfchecksimplify_exceptionstransform_xxxitemremove_dead_exceptionsPyre should port the passes that are relevant to its graph/codewriter pipeline, with explicit structural-adaptation notes where a 1:1 port is impossible.
Initial priority candidates:
remove_trivial_linksremove_identical_vars_SSASSA_to_SSIsimplify_exceptionsconstfold_exitswitchAcceptance criteria for each ported pass:
2. Match PyPy regalloc coalesce semantics
Static review found an existing parity gap in CFG coalescing.
PyPy
regalloc.pycoalesces after dependency/interference analysis and rejects a candidate when the two variables interfere. Pyre currently pre-merges CFGlink.args <-> target.inputargspairs alongside walker pin pairs in a way that can bypass the equivalent interference check.Work needed:
regalloc.py_try_coalescesemantics;ref_copyemission comes from correct PyPy parity or from a remaining walker/regalloc mismatch.This is related to #50 and #73, but it can be investigated independently at the graph/regalloc layer.
3. Investigate unmarked JitCode label panic
A pre-existing panic has been observed in the assembler patching path:
This should be tracked here as a graph/codewriter/label parity gap until proven otherwise.
Work needed:
TLabel/ patch allocation path to a corresponding emittedLabel/mark_labelpath;patch_labelspanic;simplify_graphpass makes the problematic label shape reachable.If investigation proves this is purely backend assembler state unrelated to graph/codewriter parity, split it out into a narrower follow-up issue.
4. Keep structural adaptations explicit
Some Pyre/PyPy differences are structural and should not be forced into a literal port:
pc_mapand per-PC labels by switching the tracer to interpret JitCode bytecode #73 retires it.Each pass or repair should say whether it is:
pc_mapand per-PC labels by switching the tracer to interpret JitCode bytecode #73/Replace syn-AST front-end with Charon-extracted MIR for the JIT lowering pipeline #97.Related existing issues / PRs
pc_mapand per-PC labels by switching the tracer to interpret JitCode bytecode #73: tracer/codewriter coordinate mismatch createspc_map, per-PC labels, and label-side repair pressure.Non-goals
pc_mapand per-PC labels by switching the tracer to interpret JitCode bytecode #73.Suggested execution order
remove_trivial_linksandremove_identical_vars_SSAfirst.SSA_to_SSIandsimplify_exceptions.