Skip to content

Commit

Permalink
Merge branch 'llvm' into dani/VAN-517-circom-llvm-fails-to-compile-we…
Browse files Browse the repository at this point in the history
…bb-tools-circuits
  • Loading branch information
0xddom authored Aug 29, 2023
2 parents 2545e71 + 2a69d6a commit 5589e6a
Show file tree
Hide file tree
Showing 59 changed files with 1,747 additions and 1,072 deletions.
497 changes: 134 additions & 363 deletions Cargo.lock

Large diffs are not rendered by default.

16 changes: 12 additions & 4 deletions circom/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,27 @@ fn main() {
let path = entry.unwrap();
create_dir_all(Path::new(&out_dir).join(path.parent().unwrap())).unwrap();
copy(path.clone(), Path::new(&out_dir).join(path.clone())).unwrap();
let test_name = path.to_str().unwrap()
let test_name = path
.to_str()
.unwrap()
.replace("/", "_")
.replace(".circom", "")
.replace("-", "_")
.to_lowercase();

test_code = format!("
test_code = format!(
"
{}
#[test]
fn {}() -> LitResult<()> {{
lit_test(include_str!(\"{}\"), \"{}\")
}}", test_code, test_name, path.to_str().unwrap(), test_name);
}}",
test_code,
test_name,
path.to_str().unwrap(),
test_name
);
}

generate_file(&dest_path, test_code.as_bytes());
Expand All @@ -35,4 +43,4 @@ fn main() {
fn generate_file<P: AsRef<Path>>(path: P, text: &[u8]) {
let mut f = File::create(path).unwrap();
f.write_all(text).unwrap()
}
}
22 changes: 22 additions & 0 deletions circom/tests/controlflow/van544.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
pragma circom 2.0.0;
// REQUIRES: circom
// RUN: rm -rf %t && mkdir %t && %circom --llvm -o %t %s | sed -n 's/.*Written successfully:.* \(.*\)/\1/p' | xargs cat | FileCheck %s

template Conditional() {
signal input inp;
var q;
if (inp) {
q = 0;
} else {
q = 1;
}
}

component main = Conditional();

//CHECK-LABEL: define void @Conditional_{{[0-9]+}}_run
//CHECK-SAME: ([0 x i256]* %0)
//CHECK: %[[INP_PTR:.*]] = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 0
//CHECK: %[[INP:.*]] = load i256, i256* %2
//CHECK: %[[COND:.*]] = icmp ne i256 %[[INP]], 0
//CHECK: br i1 %[[COND]], label %if.then, label %if.else
3 changes: 1 addition & 2 deletions circom/tests/lit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ use std::fs;
use std::fs::File;
use std::path::{Path, PathBuf};
use assert_cmd::Command;
use assert_fs::fixture::ChildPath;
use assert_fs::NamedTempFile;
use assert_fs::prelude::{FileTouch, FileWriteStr, PathChild};
use assert_fs::prelude::FileWriteStr;
use lazy_static::lazy_static;
use regex::Regex;
use rand::{distributions::Alphanumeric, Rng}; // 0.8
Expand Down
16 changes: 13 additions & 3 deletions circom/tests/loops/fib_input.circom
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pragma circom 2.0.0;
// REQUIRES: circom
// RUN: rm -rf %t && mkdir %t && %circom --llvm -o %t %s
// RUN: rm -rf %t && mkdir %t && %circom --llvm -o %t %s | sed -n 's/.*Written successfully:.* \(.*\)/\1/p' | xargs cat | FileCheck %s

template Fibonacci() {
signal input nth_fib;
Expand All @@ -11,7 +11,7 @@ template Fibonacci() {
var next = 0;

var counter = nth_fib;
while (counter > 2) {
while (counter > 2) { // unknown iteration count
next = a + b;
a = b;
b = next;
Expand All @@ -22,4 +22,14 @@ template Fibonacci() {
out <-- (nth_fib == 0) ? 0 : (nth_fib == 1 ? 1 : a + b);
}

component main = Fibonacci();
component main = Fibonacci();

//// Use the block labels to check that the loop is NOT unrolled
//CHECK-LABEL: define void @Fibonacci_{{[0-9]+}}_run
//CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]])
//CHECK-NOT: unrolled_loop{{.*}}:
//CHECK: loop.cond{{.*}}:
//CHECK: loop.body{{.*}}:
//CHECK: loop.end{{.*}}:
//CHECK-NOT: unrolled_loop{{.*}}:
//CHECK: }
22 changes: 19 additions & 3 deletions circom/tests/loops/fib_template.circom
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pragma circom 2.0.0;
// REQUIRES: circom
// RUN: rm -rf %t && mkdir %t && %circom --llvm -o %t %s
// RUN: rm -rf %t && mkdir %t && %circom --llvm -o %t %s | sed -n 's/.*Written successfully:.* \(.*\)/\1/p' | xargs cat | FileCheck %s

template FibonacciTmpl(N) {
signal output out;
Expand All @@ -10,7 +10,7 @@ template FibonacciTmpl(N) {
var next = 0;

var counter = N;
while (counter > 2) {
while (counter > 2) { // known iteration count
next = a + b;
a = b;
b = next;
Expand All @@ -27,4 +27,20 @@ template FibonacciTmpl(N) {
}
}

component main = FibonacciTmpl(5);
component main = FibonacciTmpl(5);

//CHECK-LABEL: define void @FibonacciTmpl_{{[0-9]+}}_run
//CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]])
//// Use the block labels to check that the loop is unrolled
//CHECK-NOT: loop.cond{{.*}}:
//CHECK-NOT: loop.body{{.*}}:
//CHECK-NOT: loop.end{{.*}}:
//CHECK: unrolled_loop{{.*}}:
//CHECK-NOT: loop.cond{{.*}}:
//CHECK-NOT: loop.body{{.*}}:
//CHECK-NOT: loop.end{{.*}}:
//// Check that final value stored to 'out' is computed correctly via unrolling
//CHECK: store{{[0-9]+}}:
//CHECK: %[[T:[0-9]+]] = getelementptr [0 x i256], [0 x i256]* %{{.*}}[[ARG]], i32 0, i32 0
//CHECK: store i256 5, i256* %{{.*}}[[T]], align 4
//CHECK: }
20 changes: 18 additions & 2 deletions circom/tests/loops/for_known.circom
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pragma circom 2.0.0;
// REQUIRES: circom
// RUN: rm -rf %t && mkdir %t && %circom --llvm -o %t %s
// RUN: rm -rf %t && mkdir %t && %circom --llvm -o %t %s | sed -n 's/.*Written successfully:.* \(.*\)/\1/p' | xargs cat | FileCheck %s

template ForKnown(N) {
signal output out;
Expand All @@ -13,4 +13,20 @@ template ForKnown(N) {
out <-- acc;
}

component main = ForKnown(10);
component main = ForKnown(10);

//CHECK-LABEL: define void @ForKnown_{{[0-9]+}}_run
//CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]])
//// Use the block labels to check that the loop is unrolled
//CHECK-NOT: loop.cond{{.*}}:
//CHECK-NOT: loop.body{{.*}}:
//CHECK-NOT: loop.end{{.*}}:
//CHECK: unrolled_loop{{.*}}:
//CHECK-NOT: loop.cond{{.*}}:
//CHECK-NOT: loop.body{{.*}}:
//CHECK-NOT: loop.end{{.*}}:
//// Check that final value stored to 'out' is computed correctly via unrolling
//CHECK: store{{[0-9]+}}:
//CHECK: %[[T:[0-9]+]] = getelementptr [0 x i256], [0 x i256]* %{{.*}}[[ARG]], i32 0, i32 0
//CHECK: store i256 55, i256* %{{.*}}[[T]], align 4
//CHECK: }
14 changes: 12 additions & 2 deletions circom/tests/loops/for_unknown.circom
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pragma circom 2.0.0;
// REQUIRES: circom
// RUN: rm -rf %t && mkdir %t && %circom --llvm -o %t %s
// RUN: rm -rf %t && mkdir %t && %circom --llvm -o %t %s | sed -n 's/.*Written successfully:.* \(.*\)/\1/p' | xargs cat | FileCheck %s

template ForUnknown() {
signal input in;
Expand All @@ -14,4 +14,14 @@ template ForUnknown() {
out <-- acc;
}

component main = ForUnknown();
component main = ForUnknown();

//// Use the block labels to check that the loop is NOT unrolled
//CHECK-LABEL: define void @ForUnknown_{{[0-9]+}}_run
//CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]])
//CHECK-NOT: unrolled_loop{{.*}}:
//CHECK: loop.cond{{.*}}:
//CHECK: loop.body{{.*}}:
//CHECK: loop.end{{.*}}:
//CHECK-NOT: unrolled_loop{{.*}}:
//CHECK: }
14 changes: 12 additions & 2 deletions circom/tests/loops/for_unknown_index.circom
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pragma circom 2.0.0;
// REQUIRES: circom
// RUN: rm -rf %t && mkdir %t && %circom --llvm -o %t %s
// RUN: rm -rf %t && mkdir %t && %circom --llvm -o %t %s | sed -n 's/.*Written successfully:.* \(.*\)/\1/p' | xargs cat | FileCheck %s

template ForUnknownIndex() {
signal input in;
Expand All @@ -17,4 +17,14 @@ template ForUnknownIndex() {
out <-- arr[acc];
}

component main = ForUnknownIndex();
component main = ForUnknownIndex();

//// Use the block labels to check that the loop is NOT unrolled
//CHECK-LABEL: define void @ForUnknownIndex_{{[0-9]+}}_run
//CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]])
//CHECK-NOT: unrolled_loop{{.*}}:
//CHECK: loop.cond{{.*}}:
//CHECK: loop.body{{.*}}:
//CHECK: loop.end{{.*}}:
//CHECK-NOT: unrolled_loop{{.*}}:
//CHECK: }
71 changes: 68 additions & 3 deletions circom/tests/loops/inner_loops.circom
Original file line number Diff line number Diff line change
@@ -1,16 +1,81 @@
pragma circom 2.0.0;
// REQUIRES: circom
// RUN: rm -rf %t && mkdir %t && %circom --llvm -o %t %s
// RUN: rm -rf %t && mkdir %t && %circom --llvm -o %t %s | sed -n 's/.*Written successfully:.* \(.*\)/\1/p' | xargs cat | FileCheck %s

template InnerLoops(n) {
signal input a[n];
var b[n];

for (var i = 0; i < n; i++) {
for (var j = 0; j <= i; j++) {
b[i] = a[i - j];
b[i] += a[i - j];
}
}
}

component main = InnerLoops(2);
component main = InnerLoops(2);
//
//ARG = { a[0], a[1] }
//lvars = { n, b[0], b[1], i, j }
//unrolled code:
// b[0] = b[0] + a[0 - 0 = 0];
// b[1] = b[1] + a[1 - 0 = 1];
// b[1] = b[1] + a[1 - 1 = 0];
//
//
//CHECK-LABEL: define void @InnerLoops_{{[0-9]+}}_run
//CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]])
//// Use the block labels to check that the loop is unrolled and check the unrolled body
//CHECK-NOT: loop.cond{{.*}}:
//CHECK-NOT: loop.body{{.*}}:
//CHECK-NOT: loop.end{{.*}}:
//CHECK: unrolled_loop{{.*}}:
// // j = 0
//CHECK-NEXT: %[[T01:[[:alnum:]_.]+]] = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4
//CHECK-NEXT: store i256 0, i256* %{{.*}}[[T01]], align 4
// // b[0] = b[0] + a[0]
//CHECK-NEXT: %[[T02:[[:alnum:]_.]+]] = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 1
//CHECK-NEXT: %[[T03:[[:alnum:]_.]+]] = load i256, i256* %{{.*}}[[T02]], align 4
//CHECK-NEXT: %[[T04:[[:alnum:]_.]+]] = getelementptr [0 x i256], [0 x i256]* %{{.*}}[[ARG]], i32 0, i32 0
//CHECK-NEXT: %[[T05:[[:alnum:]_.]+]] = load i256, i256* %{{.*}}[[T04]], align 4
//CHECK-NEXT: %[[T06:[[:alnum:]_.]+]] = call i256 @fr_add(i256 %{{.*}}[[T03]], i256 %{{.*}}[[T05]])
//CHECK-NEXT: %[[T07:[[:alnum:]_.]+]] = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 1
//CHECK-NEXT: store i256 %{{.*}}[[T06]], i256* %{{.*}}[[T07]], align 4
// // j = 1
//CHECK-NEXT: %[[T08:[[:alnum:]_.]+]] = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4
//CHECK-NEXT: store i256 1, i256* %{{.*}}[[T08]], align 4
// // i = 1
//CHECK-NEXT: %[[T09:[[:alnum:]_.]+]] = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 3
//CHECK-NEXT: store i256 1, i256* %{{.*}}[[T09]], align 4
// // j = 0
//CHECK-NEXT: %[[T10:[[:alnum:]_.]+]] = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4
//CHECK-NEXT: store i256 0, i256* %{{.*}}[[T10]], align 4
// // b[1] = b[1] + a[1]
//CHECK-NEXT: %[[T11:[[:alnum:]_.]+]] = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 2
//CHECK-NEXT: %[[T12:[[:alnum:]_.]+]] = load i256, i256* %{{.*}}[[T11]], align 4
//CHECK-NEXT: %[[T13:[[:alnum:]_.]+]] = getelementptr [0 x i256], [0 x i256]* %{{.*}}[[ARG]], i32 0, i32 1
//CHECK-NEXT: %[[T14:[[:alnum:]_.]+]] = load i256, i256* %{{.*}}[[T13]], align 4
//CHECK-NEXT: %[[T15:[[:alnum:]_.]+]] = call i256 @fr_add(i256 %{{.*}}[[T12]], i256 %{{.*}}[[T14]])
//CHECK-NEXT: %[[T16:[[:alnum:]_.]+]] = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 2
//CHECK-NEXT: store i256 %{{.*}}[[T15]], i256* %{{.*}}[[T16]], align 4
// // j = 1
//CHECK-NEXT: %[[T17:[[:alnum:]_.]+]] = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4
//CHECK-NEXT: store i256 1, i256* %{{.*}}[[T17]], align 4
// // b[1] = b[1] + a[0]
//CHECK-NEXT: %[[T18:[[:alnum:]_.]+]] = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 2
//CHECK-NEXT: %[[T19:[[:alnum:]_.]+]] = load i256, i256* %{{.*}}[[T18]], align 4
//CHECK-NEXT: %[[T20:[[:alnum:]_.]+]] = getelementptr [0 x i256], [0 x i256]* %{{.*}}[[ARG]], i32 0, i32 0
//CHECK-NEXT: %[[T21:[[:alnum:]_.]+]] = load i256, i256* %{{.*}}[[T20]], align 4
//CHECK-NEXT: %[[T22:[[:alnum:]_.]+]] = call i256 @fr_add(i256 %{{.*}}[[T19]], i256 %{{.*}}[[T21]])
//CHECK-NEXT: %[[T23:[[:alnum:]_.]+]] = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 2
//CHECK-NEXT: store i256 %{{.*}}[[T22]], i256* %{{.*}}[[T23]], align 4
// // j = 2
//CHECK-NEXT: %[[T24:[[:alnum:]_.]+]] = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4
//CHECK-NEXT: store i256 2, i256* %{{.*}}[[T24]], align 4
// // i = 2
//CHECK-NEXT: %[[T25:[[:alnum:]_.]+]] = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 3
//CHECK-NEXT: store i256 2, i256* %{{.*}}[[T25]], align 4
//CHECK-NOT: loop.cond{{.*}}:
//CHECK-NOT: loop.body{{.*}}:
//CHECK-NOT: loop.end{{.*}}:
//CHECK: }
2 changes: 1 addition & 1 deletion circom/tests/loops/inner_loops2.circom
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ template InnerLoops(n) {
i++; // 5
}

component main = InnerLoops(5);
component main = InnerLoops(5);
2 changes: 1 addition & 1 deletion circom/tests/loops/inner_loops3.circom
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ template InnerLoops(n) {
}
}

component main = InnerLoops(5);
component main = InnerLoops(5);
2 changes: 1 addition & 1 deletion circom/tests/loops/inner_loops4.circom
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ template InnerLoops(n) {
}
}

component main = InnerLoops(2);
component main = InnerLoops(2);
48 changes: 48 additions & 0 deletions circom/tests/loops/known_function.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
pragma circom 2.0.0;
// REQUIRES: circom
// RUN: rm -rf %t && mkdir %t && %circom --llvm -o %t %s | sed -n 's/.*Written successfully:.* \(.*\)/\1/p' | xargs cat | FileCheck %s

function funWithLoop(n) {
var acc = 0;
for (var i = 1; i <= n; i++) {
acc += i;
}
return acc;
}

template KnownFunctionArgs() {
signal output out[3];

out[0] <-- funWithLoop(4); // 0 + 1 + 2 + 3 + 4 = 10
out[1] <-- funWithLoop(5); // 0 + 1 + 2 + 3 + 4 + 5 = 15

var acc = 1;
for (var i = 2; i <= funWithLoop(3); i++) {
acc *= i;
}
out[2] <-- acc; // 1 * 2 * 3 * 4 * 5 * 6 = 720
}

component main = KnownFunctionArgs();

//CHECK-LABEL: define void @KnownFunctionArgs_{{[0-9]+}}_run
//CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]])
//// Check storing initial constant values to 'out'
//CHECK: store{{[0-9]+}}:
//CHECK: %[[T1:[0-9]+]] = getelementptr [0 x i256], [0 x i256]* %{{.*}}[[ARG]], i32 0, i32 0
//CHECK: store i256 10, i256* %{{.*}}[[T1]], align 4
//CHECK: store{{[0-9]+}}:
//CHECK: %[[T2:[0-9]+]] = getelementptr [0 x i256], [0 x i256]* %{{.*}}[[ARG]], i32 0, i32 1
//CHECK: store i256 15, i256* %{{.*}}[[T2]], align 4
//// Use the block labels to check that the loop is unrolled
//CHECK-NOT: loop.cond{{.*}}:
//CHECK-NOT: loop.body{{.*}}:
//CHECK-NOT: loop.end{{.*}}:
//CHECK: unrolled_loop{{.*}}:
//CHECK-NOT: loop.cond{{.*}}:
//CHECK-NOT: loop.body{{.*}}:
//CHECK-NOT: loop.end{{.*}}:
//// Check that final value stored to 'out' is computed correctly via unrolling
//CHECK: store{{[0-9]+}}:
//CHECK: %[[T3:[0-9]+]] = getelementptr [0 x i256], [0 x i256]* %{{.*}}[[ARG]], i32 0, i32 2
//CHECK: store i256 720, i256* %{{.*}}[[T3]], align 4
Loading

0 comments on commit 5589e6a

Please sign in to comment.