Skip to content
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

chore(ssa refactor): Add code to handle array equality #1635

Closed
wants to merge 39 commits into from

Conversation

kevaundray
Copy link
Contributor

Description

Problem*

Resolves

Summary*

This PR sets out to

Example

Before:


After:


Documentation

  • This PR requires documentation updates when merged.

    • I will submit a noir-lang/docs PR.
    • I will request for and support Dev Rel's help in documenting this PR.

Additional Context

PR Checklist*

  • I have tested the changes locally.
  • I have formatted the changes with Prettier and/or cargo fmt on default settings.

@kevaundray kevaundray changed the base branch from master to kw/refactor-brillig-abstraction-layer June 11, 2023 19:31
Comment on lines 187 to 195
Instruction::ArrayGet { array, index } => {
let array_ptr = self.convert_ssa_value(*array, dfg);
let index = self.convert_ssa_value(*index, dfg);

let result_ids = dfg.instruction_results(instruction_id);
let destination = self.get_or_create_register(result_ids[0]);

self.context.array_get(array_ptr, index, destination)
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will remove this is not needed for array_eq example

match operator {
BinaryOp::Eq => {
// TODO:
// Add a for loop which does roughly
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently this code returns 1 for array equality; just need to implement the for-loop noted below

Comment on lines 127 to 136
// Note: We could insert a const instruction to initialize the register
// because the VM will not expand the register space automatically.
//
// In most cases, the register created is used in another instruction
// which will cause the VM to expand the register space, but this is not
// a guarantee.
//
// TODO: check if the above can be true if we just return a constant for example
// TODO from a program
// self.const_instruction(register, 0u128.into());
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will remove, noting it here as it deserves a separate issue. It can only lead to bugs, if we create a register and then not store a value in it, or not store a value in a register whose index is larger than that register.

Base automatically changed from kw/refactor-brillig-abstraction-layer to kw/brillig-main June 12, 2023 10:17
BinaryOp::Eq => {
// Allocate one array for the equality comparisons
let comparisons_array_ptr = self.context.create_register();
self.context.allocate_array(comparisons_array_ptr, num_elements, false);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems we are doing something akin to inlining the bytecode since the num_elements is known -- we probably want to do it the way that assembly does it which is by using a for-loop with labels. I can push an unoptimized version

let allocation = self.memory.allocate(size as usize);

// If the array is prefilled (for example, parameter arrays), then we do not need to expand memory
if !prefilled {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see how this fixes the bug, though I wonder if this is leaking an abstraction -- ie parameter arrays are not a concept in this part of the code.

Will investigate the ssa ir!

start
Allocation {
start_address: MemoryAddress(start),
end_address: MemoryAddress(self.free_mem_pointer - 1),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch ser

// The features being tested is using array equality on brillig
fn main(x: [Field;3], y : [Field;3]) {
assert(array_eq(x, y));
assert(!array_eq(x, [1,2,4]));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably want to add the edge case here, for empty arrays -- it should return true in that case.

An issue to open is to check if the ssa ir will give a compiler error on arrays of different lengths. If it gets to brillig ir, then it will panic in the type_of_binary_operation function

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty arrays don't seem to be allowed
error: Arrays must have at least one element
And with different sizes the compiler issues
error: Can only compare arrays of the same length. Here LHS is of length 3, and RHS is 2

@jfecher
Copy link
Contributor

jfecher commented Jun 14, 2023

I believe this PR will no longer be necessary when #1704 is merged

@kevaundray
Copy link
Contributor Author

#1704 has been merged so closing

@kevaundray kevaundray closed this Jun 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants