Skip to content

Port RPython simplify_graph parity and track remaining graph/codewriter parity gaps #112

Description

@youknowone

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

  1. Add a small parity test harness for graph simplification outputs.
  2. Port remove_trivial_links and remove_identical_vars_SSA first.
  3. Port or classify SSA_to_SSI and simplify_exceptions.
  4. Re-audit regalloc coalescing after graph normalization changes.
  5. Add label-origin diagnostics for the unmarked-label panic.
  6. Split any clearly independent backend-only finding into a separate issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions