-
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
feat: simplify jmpif
s by reversing branches if condition is negated
#5891
base: master
Are you sure you want to change the base?
Conversation
Changes to Brillig bytecode sizes
🧾 Summary (10% most significant diffs)
Full diff report 👇
|
I'm really unsure on why exactly this is causing test failures. The ordering of the branches in a jmpif shouldn't cause any changes to behaviour afaik. |
This branch changes the order of the jmpif as expected in the simplify_cfg pass however the issue comes up in flattening as we end up merging the values incorrectly. Master
This branch
|
If we do not see an simple or obvious way to have this optimization work w/ flattening we could make this optimization just work on Brillig for now. |
I'd like if we investigated why flattening isn't adapting to the new changes. Could be related to the bug I've been looking at. |
Agreed, we should at least understand the root cause of this first. |
* master: (60 commits) fix: suggest trait attributes in LSP (#5972) fix: Error when `quote` is used in runtime code (#5978) chore: document HashMap (#5984) fix: Restrict keccak256_injective test input to 8 bits (#5977) fix: Error when comptime functions are used in runtime code (#5976) chore: document BoundedVec (#5974) feat: add `Expr::as_let` (#5964) chore: remove 3 unused functions warnings in the stdlib (#5973) feat: let `nargo` and LSP work well in the stdlib (#5969) feat: show doc comments in LSP (#5968) feat: add a `panic` method to the stdlib (#5966) fix: LSP document symbol didn't work for primitive impls (#5970) fix(mem2reg): Handle aliases in function last store cleanup and additional alias unit test (#5967) fix: let `derive(Eq)` work for empty structs (#5965) feat: add `FunctionDefinition` methods `is_unconstrained` and `set_unconstrained` (#5962) feat: LSP autocompletion for attributes (#5963) feat: `Module::add_item` (#5947) feat: Add `StructDefinition::add_generic` (#5961) feat: Add `StructDefinition::name` (#5960) fix(mem2reg): Handle aliases better when setting a known value for a load (#5959) ...
I was able to narrow down one of the failing tests to the following: This fails the final assertion: // x == 5
fn main(x: Field) {
let mut z = false;
if x != 20 {
z = true;
}
assert(x != 20);
// fails here
assert(z);
} But this succeeds: // x == 5
fn main(x: Field) {
let mut z = false;
if x != 20 {
z = true;
} else {
}
assert(x != 20);
assert(z);
} So there appears to be a bug around single-block |
I was able to narrow the above case slightly to the following, which executes successfully on fn main(x: bool) {
let mut z = false;
if !x {
z = true;
}
assert(!x);
assert(z);
}
Dumping the SSA (skipping unused variables):
// After Simplifying:
acir(inline) fn main f0 {
// v0 = 0
b0(v0: u1):
v1 = allocate
store u1 0 at v1
// v1 = 0
jmpif v0 then: b2, else: b1
b2():
// (skipped)
store u1 0 at v1
jmp b3()
b3():
constrain v0 == u1 0
v6 = load v1
// v6 = 1
constrain v6 == u1 1
return
b1():
// branch taken
store u1 1 at v1
// v1 = 1
jmp b3()
} But flatting gives SSA that unconditionally fails (see final // After Flattening:
acir(inline) fn main f0 {
// v0 = 0
b0(v0: u1):
v1 = allocate
store u1 0 at v1
// v1 = 0
enable_side_effects v0
// no side effects
v4 = load v1
// v4 = 0
store u1 1 at v1
// not stored?
v6 = not v0
// v6 = 1
store v4 at v1
// not stored? either way, it's 0
enable_side_effects v6
store u1 0 at v1
// v1 = 0
enable_side_effects u1 1
store v0 at v1
// v1 = 0
constrain v0 == u1 0
v9 = load v1
// v9 = 0
constrain v9 == u1 1
return
} |
Changes to number of Brillig opcodes executed
🧾 Summary (10% most significant diffs)
Full diff report 👇
|
Description
Problem*
Resolves
Summary*
Currently if an
if-else
block has a negated condition we generate an extra instruction to calculate the condition rather than just swapping the "if" and "else" branches. I've added a check for this in thesimplify_cfg
pass.Additional Context
Documentation*
Check one:
PR Checklist*
cargo fmt
on default settings.