Skip to content

Unbox Ref/STRef cells across function boundaries (interprocedural escape summary) #319

Description

@Unisay

Problem

The cell unboxing of #239 is a per-binding analysis: a cell qualifies only when every occurrence in its own Let scope is a recognised operation. A cell passed to a named function is a whole-value occurrence, so it stays boxed even when the callee only ever applies recognised operations to its parameter. Bench.RefLoop (the shape #239 targets) unboxes, but Bench.EffectStep — the same hot ST loop with the step factored into functions — does not, because ref flows into step/go as an argument:

go :: forall r. Int -> STRef r Int -> ST r Int
go i ref = do
  step ref
  if i <= 1 then STRef.read ref else go (i - 1) ref

run :: Int -> Int
run n = ST.run do
  ref <- STRef.new 0
  go n ref

Every iteration therefore keeps the cell-table field accesses (and, in step, the boxed read/write foreign calls), while the structurally identical inlined loop is straight-line arithmetic on a local after #239.

Approach

Interprocedural extension: a per-function summary saying "this parameter is only used through recognised cell operations (and passed to parameters with the same property)", computed bottom-up over the call graph with recursive groups resolved to a fixpoint. A cell then unboxes when every occurrence is a recognised operation or an argument in a summarised-safe position, and the callee is specialised (worker/wrapper style) to take the raw value with writes returned — which for ST is exactly a state-threading transformation. Substantially more machinery than #239; worth measuring demand first (the Bench.EffectStep counters give the baseline).

Relations

Extends #239. The specialisation half overlaps with the uncurrying worker/wrapper infrastructure (#200) and the CPR result split (#206), which already know how to rewrite call sites to workers with different conventions.

Verification

Bench.EffectStep's committed TNEW/trace oracles move: the cell table disappears and the hot loop trace-compiles. A golden pins a factored ref loop compiling without {value = …} tables.

Metadata

Metadata

Assignees

No one assigned

    Labels

    OptimisationA Compiler Optimisationarea: codegenLua code generation / printingenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions