[compiler] isolate mutable state across dynamic if branches - #1003
Merged
Conversation
Contributor
Author
|
Hi @coderfeli @sjfeng1999 , please help review this PR |
xudoyuan
requested changes
Aug 14, 2026
Rebuild Python container state from carried IR values for each branch so in-place updates during tracing cannot leak into sibling branches.
kefan203
force-pushed
the
kefan.cao/list-branch-state
branch
from
August 14, 2026 04:26
4612cf4 to
13fb55f
Compare
Contributor
Author
|
Hi @xudoyuan @coderfeli , all CI checks have passed now. Could you please help merge this PR when you have time? Thanks! |
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.
[compiler] isolate mutable state across dynamic if branches
Motivation
Dynamic
ifalready carries Python containers (list/dict/SimpleNamespace/ nested) asscf.ifresults by unpacking their leaves intoSSA values. That is enough for whole-container rebinding such as
lst = [a, b], but not for in-place updates:Both branches of
scf_if_dispatchpreviously received the same Pythoncontainer object. During tracing, an in-place write in the then-branch mutated
the shared object before the else-branch ran, so the else-branch observed the
updated element even though its SSA path never assigned it. The resulting
scf.iftherefore merged contaminated state and produced wrong values when thecondition was false.
This PR clones the mutable container structure once per branch before the
branch body runs, so in-place updates stay local to that branch’s tracing
inputs. DSL / IR leaves are shared by identity (they are already SSA-managed);
only the Python container skeleton is duplicated.
Technical Details
_clone_mutable_stateinpython/flydsl/compiler/ast_rewriter.py.It deep-clones
list,dict,SimpleNamespace, andtuplestructure whilepreserving cycles via an
id-keyed memo and leaving non-container leaves(DSL values, IR values, scalars) untouched.
ReplaceIfWithDispatch.scf_if_dispatch, each dynamic branch now receivesbranch_inputs = _clone_mutable_state(result_values)instead of the sharedentry
result_values._normalize_branch_resultfalls back through that per-branch map, so aname omitted from a branch return dict resolves to the branch’s own clone,
not the contaminated entry container.
Test Plan
tests/unit/test_dynamic_controlflow_list_carry.py::test_if_inplace_list_updates_do_not_contaminate_branchesasserts then/else receive distinct clones, the entry list is untouched, and
the else-branch still sees the original element after the then-branch stores.
tests/system/test_dynamic_controlflow_list_carry_e2e.pytest_if_inplace_list_taken→[10, 2]test_if_inplace_list_not_taken→[1, 2]Test Result
Submission Checklist