fix(ssa): store function purities on the Ssa so entry-point clones keep their purity - #13493
Open
asterite wants to merge 3 commits into
Open
fix(ssa): store function purities on the Ssa so entry-point clones keep their purity#13493asterite wants to merge 3 commits into
asterite wants to merge 3 commits into
Conversation
…ep their purity `brillig_entry_point_analysis` clones Brillig functions under fresh `FunctionId`s, but the purity table is keyed by id and the pass runs after the last `purity_analysis`, so every clone finished compilation with `purity_of() == None`. All consumers treat a missing purity as impure, so the drift was only a missed optimization, but it silently broke the "every function has a purity status" invariant that `purity_analysis_post_check` asserts. Fix this structurally by reviving the design of #9357: `FunctionPurities` now lives once on `Ssa` instead of behind an `Arc` shared into every `DataFlowGraph`, so passes that mint functions can keep the map in sync directly. `brillig_entry_point_analysis` now copies each original's purity and Brillig membership onto its clones, and the `duplicate_recursive_shared_entry_points*` snapshots show the clones keeping `predicate_pure`. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
asterite
marked this pull request as draft
August 10, 2026 14:00
asterite
marked this pull request as ready for review
August 10, 2026 14:18
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This ends up in a bit more code, but like this there's no chance of us forgetting to copy purities across all function dfgs.
Problem Resolved
Resolves https://github.com/noir-lang/noir-claude/issues/1652
brillig_entry_point_analysisclones Brillig functions under freshFunctionIds, but function purities are stored in an id-keyed table and the pass runs after the lastpurity_analysis, so nothing ever registers the clones: they finish compilation withpurity_of() == None. Every consumer treats a missing purity as impure, so the drift is only a missed optimization, but it silently breaks the "every function has a purity status" invariant thatpurity_analysis_post_checkasserts — the check just never runs after the cloning pass. The in-treeduplicate_recursive_shared_entry_pointssnapshot had the drift baked in (clones printed withoutpredicate_pure).Summary of Changes
This revives the design of #9357:
FunctionPuritiesnow lives once onSsaas a plain field rather than behind anArcshared into everyDataFlowGraph. That removes the whole class of "forgot to redistribute the purity Arc" bugs and lets passes that mint functions keep the map in sync directly:Ssa::purity_analysiswritesself.function_purities; the per-DFGfunction_purities/set_function_purities/purity_ofandFunctionBuilder::set_puritiesplumbing is gone.Instruction::has_side_effectsandInstruction::can_flatten_in_conditionaltake a&FunctionPuritiesparameter, threaded from each pass (requires_acir_gen_predicateno longer consults purity, so it is unchanged).defunctionalizeandnormalize_value_idsupdate/remapssa.function_puritiesdirectly instead of cloning and redistributing the shared Arc.brillig_entry_point_analysiscopies each original's intrinsic purity and Brillig membership onto the clone's new id — sound because a clone's body is instruction-for-instruction identical to its original's at creation.cloned_functions_keep_their_purityasserts that after the pass every function has a purity equal to its original's (verified failing before the fix), and theduplicate_recursive_shared_entry_points*snapshots now show the clones keepingpredicate_pure.One cosmetic consequence: the standalone
impl Display for Functionno longer prints a purity keyword (a loneFunctioncannot reach theSsa-owned map); theSsa-level printer is unaffected.User Documentation
Check one:
PR Checklist
cargo fmton default settings.🤖 Generated with Claude Code