-
Notifications
You must be signed in to change notification settings - Fork 206
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Correctness issue with reference counters #6123
Comments
The code snippet passes if we disable removing RC instructions during DIE. e.g. doing so gives us the following SSA:
We can see the largest difference is that we have two extra This PR #6088 looks to actually also cause this program to execute successfully. It ends with the following SSA:
We can see it maintains the same necessary |
Also noting that I do not think the rc optimization should be causing any problems here. It looks to be operating correctly. The only changes from its inputs to the outputted SSA is the following:
After Removing Paired rc_inc & rc_decs:
|
Turning off inlining for this case it becomes more clear why #6088 solves this correctness issue for inc_rc. Before DIE we have the following function:
After DIE we get the following SSA where the inc_rc will be removed:
#6088 fixed this case by merging the repeat loads that are used in later instructions, into the first parameter rcs load and increment. Thus I see a few ways forward (all values reference the SSA before DIE):
|
I see, so IIUC the issue stems from the fact that we are codegening redundant work in ssa gen but it's incomplete (we are loading v0 multiple times but only inc_rc the first load). Note that any solution that we choose should work both when inlining and when not inlining (because in the future the inliner won't be boolean, we'd have some configuration and heuristics to wether inline a call or not) My gut feeling is that we should codegen a correct program (thus going with option 1 and whenever we load an array from a reference, increasing its rc, and decreasing its rc when it goes out of scope) but then optimize any redundant work (removing the redundant loads with their associated inc_rc and dec_rc) but I might be missing something |
So for example: unconstrained fn main(mut arr: [Field; 2], from_index: u32, to_index: u32) {
let tmp = arr[from_index];
arr[from_index] = arr[to_index];
arr[to_index] = tmp;
} We codegen this:
Which I think is incorrect, v0 has a total of 5 aliases and its RC is two. What I'd expect is:
And then, when a later optimization pass removes the 4 redundant loads that it'd remove the associated inc_rc and dec_rc, leaving
|
And then we could also remove the inc_rc and dec_rc pairs for array arguments to the entrypoint (only in the entrypoint, no callees) but I think that's separate |
Yes partially. It is more that due to the redundant work the initial inc_rc which we place on the parameter we want to stay. Simply restricting DIE to check whether the inc_rc comes from a block parameter load will not work post inlining.
Yes makes sense. I want to verify whether #6088 can work with some extra checks in DIE on block params. Otherwise, it does look like option (1) and eating a regression for now until we can optimize further may be our best choice. |
# Description ## Problem\* Resolves #6123 ## Summary\* Still a draft as I want to test it a bit more and am not fully sure if it is the best solution. ## Additional Context ## Documentation\* Check one: - [X] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[For Experimental Features]** Documentation to be submitted in a separate PR. # PR Checklist\* - [X] I have tested the changes locally. - [X] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings.
Aim
Run the following program succesfully (It's a minimal reproduction of a failing test in the protocol circuits tests):
Expected Behavior
The program should run succesfully
Bug
note_hashes is mutated when swapping items on builder.note_hashes.
This is the SSA generated:
By "executing" the SSA by hand, I think the SSA generated is incorrect:
The SSA generated is outputting enough dec_rc to wraparound rc, and in general I think the reference counter management in this SSA doesn't make much sense to me. In the end the program fails because
note_hashes
(v11) has been mutated inside swap_items.Bisecting the compiler, the program stopped working after this PR:
#4560
But simply deactivating this pass does not fix it anymore.
To Reproduce
No response
Workaround
None
Workaround Description
No response
Additional Context
No response
Project Impact
None
Blocker Context
No response
Nargo Version
No response
NoirJS Version
No response
Proving Backend Tooling & Version
No response
Would you like to submit a PR for this Issue?
None
Support Needs
No response
The text was updated successfully, but these errors were encountered: