From f68e4f08a98c7bc4d1b28bab0656f29b1872929e Mon Sep 17 00:00:00 2001 From: Tim Hoffman Date: Tue, 24 Oct 2023 12:51:40 -0500 Subject: [PATCH 1/9] Revert "turn off loop body extraction" This reverts commit bbe89b69d342dda858dc5fce93f766358a482e4d. --- circom/tests/loops/call_inside_loop.circom | 1 - circom/tests/loops/inner_conditional_1.circom | 1 - circom/tests/loops/inner_conditional_2.circom | 1 - circom/tests/loops/inner_conditional_3.circom | 1 - circom/tests/loops/inner_conditional_4.circom | 1 - circom/tests/loops/inner_conditional_5.circom | 1 - circom/tests/loops/inner_conditional_6.circom | 1 - circom/tests/loops/inner_conditional_7.circom | 1 - circom/tests/loops/inner_conditional_8.circom | 1 - circom/tests/loops/inner_conditional_9.circom | 1 - circom/tests/loops/inner_loop_simple.circom | 1 - circom/tests/loops/inner_loops.circom | 1 - circom/tests/loops/inner_loops2.circom | 1 - circom/tests/loops/inner_loops3.circom | 1 - circom/tests/loops/inner_loops4.circom | 1 - circom/tests/loops/inner_loops5.circom | 1 - circom/tests/loops/inner_loops6.circom | 1 - circom/tests/loops/simple_variant_idx.circom | 1 - circom/tests/loops/vanguard-uc-comp.circom | 1 - circom/tests/loops/variant_idx_in_loop_A.circom | 1 - circom/tests/loops/variant_idx_in_loop_B.circom | 1 - circom/tests/subcmps/subcmps0A.circom | 1 - circom/tests/subcmps/subcmps0B.circom | 1 - circom/tests/subcmps/subcmps0C.circom | 1 - circom/tests/subcmps/subcmps0D.circom | 1 - circom/tests/subcmps/subcmps1.circom | 1 - circom/tests/subcmps/subcmps2.circom | 1 + circuit_passes/src/passes/loop_unroll/mod.rs | 17 ++++++++--------- 28 files changed, 9 insertions(+), 35 deletions(-) diff --git a/circom/tests/loops/call_inside_loop.circom b/circom/tests/loops/call_inside_loop.circom index c29412d57..912ce3287 100644 --- a/circom/tests/loops/call_inside_loop.circom +++ b/circom/tests/loops/call_inside_loop.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false //arena = { a[0], a[1], n, b, c, d, e, f, g} function fun(a, n, b, c, d, e, f, g) { diff --git a/circom/tests/loops/inner_conditional_1.circom b/circom/tests/loops/inner_conditional_1.circom index ef025cb04..85c98fca5 100644 --- a/circom/tests/loops/inner_conditional_1.circom +++ b/circom/tests/loops/inner_conditional_1.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false // IF condition can be known via in-place unrolling but not when body is extracted to a new function template InnerConditional1(N) { diff --git a/circom/tests/loops/inner_conditional_2.circom b/circom/tests/loops/inner_conditional_2.circom index 71421fb7b..5f0a7648f 100644 --- a/circom/tests/loops/inner_conditional_2.circom +++ b/circom/tests/loops/inner_conditional_2.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false // if condition is known constant template InnerConditional2(N, T) { diff --git a/circom/tests/loops/inner_conditional_3.circom b/circom/tests/loops/inner_conditional_3.circom index ec6ffcc7a..554282a24 100644 --- a/circom/tests/loops/inner_conditional_3.circom +++ b/circom/tests/loops/inner_conditional_3.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false // if condition is NOT known template InnerConditional3(N) { diff --git a/circom/tests/loops/inner_conditional_4.circom b/circom/tests/loops/inner_conditional_4.circom index be22d5214..54f13c096 100644 --- a/circom/tests/loops/inner_conditional_4.circom +++ b/circom/tests/loops/inner_conditional_4.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false // if condition can be known via unrolling, arrays used inside indexed on iteration variable template InnerConditional4(N) { diff --git a/circom/tests/loops/inner_conditional_5.circom b/circom/tests/loops/inner_conditional_5.circom index a2887b8d9..37748c52d 100644 --- a/circom/tests/loops/inner_conditional_5.circom +++ b/circom/tests/loops/inner_conditional_5.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false // if condition is known constant, arrays used inside indexed on iteration variable template InnerConditional5(N, T) { diff --git a/circom/tests/loops/inner_conditional_6.circom b/circom/tests/loops/inner_conditional_6.circom index cd42cb635..233e74b44 100644 --- a/circom/tests/loops/inner_conditional_6.circom +++ b/circom/tests/loops/inner_conditional_6.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false // if condition is NOT known, arrays used inside indexed on iteration variable // UPDATE: Circom compiler does not allow the commented block diff --git a/circom/tests/loops/inner_conditional_7.circom b/circom/tests/loops/inner_conditional_7.circom index fbc399e05..2ce359d33 100644 --- a/circom/tests/loops/inner_conditional_7.circom +++ b/circom/tests/loops/inner_conditional_7.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false template InnerConditional7(N) { signal output out; diff --git a/circom/tests/loops/inner_conditional_8.circom b/circom/tests/loops/inner_conditional_8.circom index 7dc46fd06..2f7c3f217 100644 --- a/circom/tests/loops/inner_conditional_8.circom +++ b/circom/tests/loops/inner_conditional_8.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false // like inner_conditional_7 but with 'i' and 'j' uses swapped template InnerConditional8(N) { diff --git a/circom/tests/loops/inner_conditional_9.circom b/circom/tests/loops/inner_conditional_9.circom index 6e3c81db0..345e26d0c 100644 --- a/circom/tests/loops/inner_conditional_9.circom +++ b/circom/tests/loops/inner_conditional_9.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false template InnerConditional9(N) { signal output out; diff --git a/circom/tests/loops/inner_loop_simple.circom b/circom/tests/loops/inner_loop_simple.circom index 670db5be6..d1e0b00c8 100644 --- a/circom/tests/loops/inner_loop_simple.circom +++ b/circom/tests/loops/inner_loop_simple.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false template InnerLoops(n, m) { signal input in[m]; diff --git a/circom/tests/loops/inner_loops.circom b/circom/tests/loops/inner_loops.circom index bee25691a..c2cef8c42 100644 --- a/circom/tests/loops/inner_loops.circom +++ b/circom/tests/loops/inner_loops.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false template InnerLoops(n) { signal input a[n]; diff --git a/circom/tests/loops/inner_loops2.circom b/circom/tests/loops/inner_loops2.circom index f84ab58b8..df0775c1d 100644 --- a/circom/tests/loops/inner_loops2.circom +++ b/circom/tests/loops/inner_loops2.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false template InnerLoops(n) { signal input a[n]; diff --git a/circom/tests/loops/inner_loops3.circom b/circom/tests/loops/inner_loops3.circom index 0a611d0fd..558d94961 100644 --- a/circom/tests/loops/inner_loops3.circom +++ b/circom/tests/loops/inner_loops3.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false template InnerLoops(n) { signal input a[n]; diff --git a/circom/tests/loops/inner_loops4.circom b/circom/tests/loops/inner_loops4.circom index e45d50e48..6c33e35a4 100644 --- a/circom/tests/loops/inner_loops4.circom +++ b/circom/tests/loops/inner_loops4.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false template InnerLoops(n) { signal input a[n]; diff --git a/circom/tests/loops/inner_loops5.circom b/circom/tests/loops/inner_loops5.circom index 5a886c77a..8cee6ce78 100644 --- a/circom/tests/loops/inner_loops5.circom +++ b/circom/tests/loops/inner_loops5.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false // %0 (i.e. signal arena) = [ out, in ] // %lvars = [ n, temp, i, j ] diff --git a/circom/tests/loops/inner_loops6.circom b/circom/tests/loops/inner_loops6.circom index 367bc0409..ee885c37f 100644 --- a/circom/tests/loops/inner_loops6.circom +++ b/circom/tests/loops/inner_loops6.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false // %0 (i.e. signal arena) = [ out[0], out[1], out[2], out[3], in ] // %lvars = [ n, i, j ] diff --git a/circom/tests/loops/simple_variant_idx.circom b/circom/tests/loops/simple_variant_idx.circom index a6f72c3da..b72bbc2fe 100644 --- a/circom/tests/loops/simple_variant_idx.circom +++ b/circom/tests/loops/simple_variant_idx.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false template SimpleVariantIdx(n) { signal input in; diff --git a/circom/tests/loops/vanguard-uc-comp.circom b/circom/tests/loops/vanguard-uc-comp.circom index 27e7ff0fb..b67e6c122 100644 --- a/circom/tests/loops/vanguard-uc-comp.circom +++ b/circom/tests/loops/vanguard-uc-comp.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false template Num2Bits(n) { signal input in; diff --git a/circom/tests/loops/variant_idx_in_loop_A.circom b/circom/tests/loops/variant_idx_in_loop_A.circom index 64c8237db..b35250f72 100644 --- a/circom/tests/loops/variant_idx_in_loop_A.circom +++ b/circom/tests/loops/variant_idx_in_loop_A.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false template VariantIndex(n) { signal input in; diff --git a/circom/tests/loops/variant_idx_in_loop_B.circom b/circom/tests/loops/variant_idx_in_loop_B.circom index 52625cfad..b85223b1d 100644 --- a/circom/tests/loops/variant_idx_in_loop_B.circom +++ b/circom/tests/loops/variant_idx_in_loop_B.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false template VariantIndex(n) { signal input in; diff --git a/circom/tests/subcmps/subcmps0A.circom b/circom/tests/subcmps/subcmps0A.circom index 03c59c530..4f33801b3 100644 --- a/circom/tests/subcmps/subcmps0A.circom +++ b/circom/tests/subcmps/subcmps0A.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false // Like SubCmps1 but simpler (no constraints and fewer operations) template IsZero() { diff --git a/circom/tests/subcmps/subcmps0B.circom b/circom/tests/subcmps/subcmps0B.circom index 915b5c9c3..f858f60e8 100644 --- a/circom/tests/subcmps/subcmps0B.circom +++ b/circom/tests/subcmps/subcmps0B.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false // Like SubCmps1 but simpler (no constraints and fewer operations) template IsZero() { diff --git a/circom/tests/subcmps/subcmps0C.circom b/circom/tests/subcmps/subcmps0C.circom index 4f68af91a..c62cdff92 100644 --- a/circom/tests/subcmps/subcmps0C.circom +++ b/circom/tests/subcmps/subcmps0C.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false template IsZero() { signal input in; diff --git a/circom/tests/subcmps/subcmps0D.circom b/circom/tests/subcmps/subcmps0D.circom index e8e255c7f..c2eeee5f5 100644 --- a/circom/tests/subcmps/subcmps0D.circom +++ b/circom/tests/subcmps/subcmps0D.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false template Add() { signal input in1; diff --git a/circom/tests/subcmps/subcmps1.circom b/circom/tests/subcmps/subcmps1.circom index 8d40d004d..883d3d290 100644 --- a/circom/tests/subcmps/subcmps1.circom +++ b/circom/tests/subcmps/subcmps1.circom @@ -1,7 +1,6 @@ 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 --enable-var-scope -// XFAIL:.* // TEMPORARY: because EXTRACT_LOOP_BODY_TO_NEW_FUNC == false template IsZero() { signal input in; // subcmp signal 1 diff --git a/circom/tests/subcmps/subcmps2.circom b/circom/tests/subcmps/subcmps2.circom index 098fc09f9..23f932c8e 100644 --- a/circom/tests/subcmps/subcmps2.circom +++ b/circom/tests/subcmps/subcmps2.circom @@ -1,6 +1,7 @@ pragma circom 2.0.6; // REQUIRES: circom // RUN: rm -rf %t && mkdir %t && %circom --llvm -o %t %s | sed -n 's/.*Written successfully:.* \(.*\)/\1/p' | xargs cat | FileCheck %s --enable-var-scope +// XFAIL:.* // pending https://veridise.atlassian.net/browse/VAN-670 template Sum(n) { signal input inp[n]; diff --git a/circuit_passes/src/passes/loop_unroll/mod.rs b/circuit_passes/src/passes/loop_unroll/mod.rs index ded6e9695..0d433dee0 100644 --- a/circuit_passes/src/passes/loop_unroll/mod.rs +++ b/circuit_passes/src/passes/loop_unroll/mod.rs @@ -19,7 +19,7 @@ use crate::passes::loop_unroll::loop_env_recorder::EnvRecorder; use super::{CircuitTransformationPass, GlobalPassData}; use self::body_extractor::LoopBodyExtractor; -const EXTRACT_LOOP_BODY_TO_NEW_FUNC: bool = false; +const EXTRACT_LOOP_BODY_TO_NEW_FUNC: bool = true; pub const LOOP_BODY_FN_PREFIX: &str = const_format::concatcp!(GENERATED_FN_PREFIX, "loop.body."); @@ -256,14 +256,13 @@ mod test { assert_ne!(circuit, new_circuit); match new_circuit.templates[0].body.last().unwrap().as_ref() { Instruction::Block(b) => { - // // 5 iterations unrolled into 5 call statements targeting extracted loop body functions - // assert_eq!(b.body.len(), 5); - // assert!(b.body.iter().all(|s| if let Instruction::Call(c) = s.as_ref() { - // c.symbol.starts_with(LOOP_BODY_FN_PREFIX) - // } else { - // false - // })); - assert_eq!(b.body.len(), 10); + // 5 iterations unrolled into 5 call statements targeting extracted loop body functions + assert_eq!(b.body.len(), 5); + assert!(b.body.iter().all(|s| if let Instruction::Call(c) = s.as_ref() { + c.symbol.starts_with(LOOP_BODY_FN_PREFIX) + } else { + false + })); } _ => assert!(false), } From 7971ed937a5e2605d3e2fbf16c14a27b1b992d9b Mon Sep 17 00:00:00 2001 From: Tim Hoffman Date: Tue, 24 Oct 2023 13:02:49 -0500 Subject: [PATCH 2/9] fix build --- circuit_passes/src/passes/loop_unroll/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circuit_passes/src/passes/loop_unroll/mod.rs b/circuit_passes/src/passes/loop_unroll/mod.rs index 0d433dee0..6947b6b52 100644 --- a/circuit_passes/src/passes/loop_unroll/mod.rs +++ b/circuit_passes/src/passes/loop_unroll/mod.rs @@ -238,7 +238,7 @@ mod test { OperatorType, StoreBucket, ValueBucket, ValueType, }; use crate::passes::{CircuitTransformationPass, GlobalPassData}; - use crate::passes::loop_unroll::LoopUnrollPass; + use crate::passes::loop_unroll::{LoopUnrollPass, LOOP_BODY_FN_PREFIX}; #[test] fn test_loop_unrolling() { From b5f98f614afd9911724c2e5e45550a313cac296a Mon Sep 17 00:00:00 2001 From: Ian Neal Date: Tue, 24 Oct 2023 13:25:34 -0500 Subject: [PATCH 3/9] [VAN-723] Track array load/store info to only generate used functions (#63) * Update array function tracking * Update test * Clean up compiler output --- .../arrays/unknown_index_load_store.circom | 15 ++++++-- .../src/passes/conditional_flattening.rs | 8 ++-- .../deterministic_subcomponent_invocation.rs | 8 ++-- circuit_passes/src/passes/loop_unroll/mod.rs | 8 ++-- circuit_passes/src/passes/mod.rs | 15 +++++++- .../src/passes/unknown_index_sanitization.rs | 38 ++++++++++++++----- .../src/llvm_elements/array_switch.rs | 19 +++++++--- code_producers/src/llvm_elements/mod.rs | 8 +++- compiler/src/circuit_design/circuit.rs | 34 +++++------------ compiler/src/circuit_design/template.rs | 4 +- 10 files changed, 96 insertions(+), 61 deletions(-) diff --git a/circom/tests/arrays/unknown_index_load_store.circom b/circom/tests/arrays/unknown_index_load_store.circom index de890b36f..583868139 100644 --- a/circom/tests/arrays/unknown_index_load_store.circom +++ b/circom/tests/arrays/unknown_index_load_store.circom @@ -4,13 +4,20 @@ pragma circom 2.0.0; template UnknownIndexLoadStore() { signal input in; - signal output out[10]; + signal output out[8]; - var arr1[10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + var arr1[9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; var arr2[10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; - var arr3[10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + var arr3[11] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; out[in] <-- arr2[in]; } -component main = UnknownIndexLoadStore(); \ No newline at end of file +component main = UnknownIndexLoadStore(); + +// CHECK: define void @__array_store__0_to_8([0 x i256]* %0, i32 %1, i256 %2) +// CHECK: define i256 @__array_load__9_to_19([0 x i256]* %0, i32 %1) +// CHECK-NOT: @__array_load__0_to_8 +// CHECK-NOT: @__array_store__9_to_19 +// CHECK-NOT: @__array_load__20_to_31 +// CHECK-NOT: @__array_store__20_to_31 \ No newline at end of file diff --git a/circuit_passes/src/passes/conditional_flattening.rs b/circuit_passes/src/passes/conditional_flattening.rs index 56b9dce83..a2b469cae 100644 --- a/circuit_passes/src/passes/conditional_flattening.rs +++ b/circuit_passes/src/passes/conditional_flattening.rs @@ -112,6 +112,10 @@ impl CircuitTransformationPass for ConditionalFlatteningPass<'_> { "ConditionalFlattening" } + fn get_updated_field_constants(&self) -> Vec { + self.memory.get_field_constants_clone() + } + fn pre_hook_circuit(&self, circuit: &Circuit) { self.memory.fill_from_circuit(circuit); } @@ -121,10 +125,6 @@ impl CircuitTransformationPass for ConditionalFlatteningPass<'_> { self.memory.run_template(self.global_data, self, template); } - fn get_updated_field_constants(&self) -> Vec { - self.memory.get_field_constants_clone() - } - fn transform_branch_bucket(&self, bucket: &BranchBucket) -> InstructionPointer { if let Some(side) = self.replacements.borrow().get(&bucket) { let code = if *side { &bucket.if_branch } else { &bucket.else_branch }; diff --git a/circuit_passes/src/passes/deterministic_subcomponent_invocation.rs b/circuit_passes/src/passes/deterministic_subcomponent_invocation.rs index 94f3ab03c..1e9b9e5c6 100644 --- a/circuit_passes/src/passes/deterministic_subcomponent_invocation.rs +++ b/circuit_passes/src/passes/deterministic_subcomponent_invocation.rs @@ -130,6 +130,10 @@ impl CircuitTransformationPass for DeterministicSubCmpInvokePass<'_> { "DeterministicSubCmpInvokePass" } + fn get_updated_field_constants(&self) -> Vec { + self.memory.get_field_constants_clone() + } + fn pre_hook_circuit(&self, circuit: &Circuit) { self.memory.fill_from_circuit(circuit); } @@ -139,10 +143,6 @@ impl CircuitTransformationPass for DeterministicSubCmpInvokePass<'_> { self.memory.run_template(self.global_data, self, template); } - fn get_updated_field_constants(&self) -> Vec { - self.memory.get_field_constants_clone() - } - fn transform_address_type(&self, address: &AddressType) -> AddressType { let replacements = self.replacements.borrow(); match address { diff --git a/circuit_passes/src/passes/loop_unroll/mod.rs b/circuit_passes/src/passes/loop_unroll/mod.rs index 6947b6b52..1fd37131a 100644 --- a/circuit_passes/src/passes/loop_unroll/mod.rs +++ b/circuit_passes/src/passes/loop_unroll/mod.rs @@ -190,6 +190,10 @@ impl CircuitTransformationPass for LoopUnrollPass<'_> { "LoopUnrollPass" } + fn get_updated_field_constants(&self) -> Vec { + self.memory.get_field_constants_clone() + } + fn pre_hook_circuit(&self, circuit: &Circuit) { self.memory.fill_from_circuit(circuit); } @@ -206,10 +210,6 @@ impl CircuitTransformationPass for LoopUnrollPass<'_> { self.memory.run_template(self.global_data, self, template); } - fn get_updated_field_constants(&self) -> Vec { - self.memory.get_field_constants_clone() - } - fn transform_loop_bucket(&self, bucket: &LoopBucket) -> InstructionPointer { if let Some(unrolled_loop) = self.replacements.borrow().get(&bucket.id) { return self.transform_instruction(unrolled_loop); diff --git a/circuit_passes/src/passes/mod.rs b/circuit_passes/src/passes/mod.rs index b7eae09bb..5e105b757 100644 --- a/circuit_passes/src/passes/mod.rs +++ b/circuit_passes/src/passes/mod.rs @@ -1,5 +1,6 @@ use std::cell::RefCell; -use std::collections::{HashMap, BTreeMap}; +use std::collections::{BTreeMap, HashMap, HashSet}; +use std::ops::Range; use compiler::circuit_design::function::{FunctionCode, FunctionCodeInfo}; use compiler::circuit_design::template::{TemplateCode, TemplateCodeInfo}; use compiler::compiler_interface::Circuit; @@ -38,10 +39,12 @@ pub trait CircuitTransformationPass { self.pre_hook_circuit(&circuit); let templates = circuit.templates.iter().map(|t| self.transform_template(t)).collect(); let field_tracking = self.get_updated_field_constants(); + let bounded_loads = self.get_updated_bounded_array_loads(&circuit.llvm_data.bounded_array_loads); + let bounded_stores = self.get_updated_bounded_array_stores(&circuit.llvm_data.bounded_array_stores); let mut new_circuit = Circuit { wasm_producer: circuit.wasm_producer.clone(), c_producer: circuit.c_producer.clone(), - llvm_data: circuit.llvm_data.clone_with_new_field_tracking(field_tracking), + llvm_data: circuit.llvm_data.clone_with_updates(field_tracking, bounded_loads, bounded_stores), templates, functions: circuit.functions.iter().map(|f| self.transform_function(f)).collect(), }; @@ -51,6 +54,14 @@ pub trait CircuitTransformationPass { fn get_updated_field_constants(&self) -> Vec; + fn get_updated_bounded_array_loads(&self, old_array_loads: &HashSet>) -> HashSet> { + old_array_loads.clone() + } + + fn get_updated_bounded_array_stores(&self, old_array_stores: &HashSet>) -> HashSet> { + old_array_stores.clone() + } + fn transform_template(&self, template: &TemplateCode) -> TemplateCode { self.pre_hook_template(template); Box::new(TemplateCodeInfo { diff --git a/circuit_passes/src/passes/unknown_index_sanitization.rs b/circuit_passes/src/passes/unknown_index_sanitization.rs index c4f3ac18e..fa59e046b 100644 --- a/circuit_passes/src/passes/unknown_index_sanitization.rs +++ b/circuit_passes/src/passes/unknown_index_sanitization.rs @@ -1,12 +1,12 @@ use std::cell::RefCell; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, HashSet}; use std::ops::Range; use compiler::circuit_design::template::TemplateCode; use compiler::compiler_interface::Circuit; use compiler::intermediate_representation::{Instruction, InstructionPointer, new_id}; use compiler::intermediate_representation::ir_interface::*; use compiler::num_bigint::BigInt; -use code_producers::llvm_elements::array_switch::{get_array_load_symbol, get_array_store_symbol}; +use code_producers::llvm_elements::array_switch::{get_array_load_name, get_array_store_name}; use program_structure::constants::UsefulConstants; use crate::bucket_interpreter::env::Env; use crate::bucket_interpreter::memory::PassMemory; @@ -87,6 +87,8 @@ pub struct UnknownIndexSanitizationPass<'d> { memory: PassMemory, load_replacements: RefCell>>, store_replacements: RefCell>>, + scheduled_bounded_loads: RefCell>>, + scheduled_bounded_stores: RefCell>>, } /** @@ -99,6 +101,8 @@ impl<'d> UnknownIndexSanitizationPass<'d> { memory: PassMemory::new(prime, "".to_string(), Default::default()), load_replacements: Default::default(), store_replacements: Default::default(), + scheduled_bounded_loads: Default::default(), + scheduled_bounded_stores: Default::default(), } } @@ -176,7 +180,8 @@ impl InterpreterObserver for UnknownIndexSanitizationPass<'_> { let location = &bucket.src; if self.is_location_unknown(address, location, env) { let index_range = self.find_bounds(address, location, env); - self.load_replacements.borrow_mut().insert(bucket.clone(), index_range); + self.load_replacements.borrow_mut().insert(bucket.clone(), index_range.clone()); + self.scheduled_bounded_loads.borrow_mut().insert(index_range); } true } @@ -186,7 +191,8 @@ impl InterpreterObserver for UnknownIndexSanitizationPass<'_> { let location = &bucket.dest; if self.is_location_unknown(address, location, env) { let index_range = self.find_bounds(address, location, env); - self.store_replacements.borrow_mut().insert(bucket.clone(), index_range); + self.store_replacements.borrow_mut().insert(bucket.clone(), index_range.clone()); + self.scheduled_bounded_stores.borrow_mut().insert(index_range); } true } @@ -248,14 +254,30 @@ impl InterpreterObserver for UnknownIndexSanitizationPass<'_> { } } +fn do_array_union(a: &HashSet>, b: &HashSet>) -> HashSet> { + a.union(b).map(|e| e.clone()).collect() +} + impl CircuitTransformationPass for UnknownIndexSanitizationPass<'_> { fn name(&self) -> &str { "UnknownIndexSanitizationPass" } + fn get_updated_field_constants(&self) -> Vec { + self.memory.get_field_constants_clone() + } + + fn get_updated_bounded_array_loads(&self, old_array_loads: &HashSet>) -> HashSet> { + do_array_union(old_array_loads, &self.scheduled_bounded_loads.borrow()) + } + + fn get_updated_bounded_array_stores(&self, old_array_stores: &HashSet>) -> HashSet> { + do_array_union(old_array_stores, &self.scheduled_bounded_stores.borrow()) + } + fn transform_load_bucket(&self, bucket: &LoadBucket) -> InstructionPointer { let bounded_fn_symbol = match self.load_replacements.borrow().get(bucket) { - Some(index_range) => Some(get_array_load_symbol(index_range)), + Some(index_range) => Some(get_array_load_name(index_range)), None => bucket.bounded_fn.clone(), }; LoadBucket { @@ -272,7 +294,7 @@ impl CircuitTransformationPass for UnknownIndexSanitizationPass<'_> { fn transform_store_bucket(&self, bucket: &StoreBucket) -> InstructionPointer { let bounded_fn_symbol = match self.store_replacements.borrow().get(bucket) { - Some(index_range) => Some(get_array_store_symbol(index_range)), + Some(index_range) => Some(get_array_store_name(index_range)), None => bucket.bounded_fn.clone(), }; StoreBucket { @@ -290,10 +312,6 @@ impl CircuitTransformationPass for UnknownIndexSanitizationPass<'_> { .allocate() } - fn get_updated_field_constants(&self) -> Vec { - self.memory.get_field_constants_clone() - } - fn pre_hook_circuit(&self, circuit: &Circuit) { self.memory.fill_from_circuit(circuit); } diff --git a/code_producers/src/llvm_elements/array_switch.rs b/code_producers/src/llvm_elements/array_switch.rs index 7919b6734..946132476 100644 --- a/code_producers/src/llvm_elements/array_switch.rs +++ b/code_producers/src/llvm_elements/array_switch.rs @@ -1,4 +1,4 @@ -use std::ops::Range; +use std::{ops::Range, collections::HashSet}; use inkwell::types::PointerType; use crate::llvm_elements::LLVMIRProducer; use super::types::bigint_type; @@ -129,15 +129,22 @@ pub fn array_ptr_ty<'a>(producer: &dyn LLVMIRProducer<'a>) -> PointerType<'a> { bigint_ty.array_type(0).ptr_type(Default::default()) } -pub fn load_array_switch<'a>(producer: &dyn LLVMIRProducer<'a>, index_range: &Range) { - array_switch::create_array_load_fn(producer, index_range); - array_switch::create_array_store_fn(producer, index_range); +pub fn load_array_load_fns<'a>(producer: &dyn LLVMIRProducer<'a>, scheduled_array_loads: &HashSet>) { + for range in scheduled_array_loads { + array_switch::create_array_load_fn(producer, range); + } +} + +pub fn load_array_stores_fns<'a>(producer: &dyn LLVMIRProducer<'a>, scheduled_array_stores: &HashSet>) { + for range in scheduled_array_stores { + array_switch::create_array_store_fn(producer, range); + } } -pub fn get_array_load_symbol(index_range: &Range) -> String { +pub fn get_array_load_name(index_range: &Range) -> String { array_switch::get_load_symbol(index_range) } -pub fn get_array_store_symbol(index_range: &Range) -> String { +pub fn get_array_store_name(index_range: &Range) -> String { array_switch::get_store_symbol(index_range) } diff --git a/code_producers/src/llvm_elements/mod.rs b/code_producers/src/llvm_elements/mod.rs index f57e13f26..73a70c746 100644 --- a/code_producers/src/llvm_elements/mod.rs +++ b/code_producers/src/llvm_elements/mod.rs @@ -1,5 +1,5 @@ use std::cell::RefCell; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::convert::TryFrom; use std::ops::Range; use std::rc::Rc; @@ -100,16 +100,20 @@ pub struct LLVMCircuitData { pub signal_index_mapping: HashMap, pub variable_index_mapping: HashMap, pub component_index_mapping: HashMap, + pub bounded_array_loads: HashSet>, + pub bounded_array_stores: HashSet>, } impl LLVMCircuitData { - pub fn clone_with_new_field_tracking(&self, field_tracking: Vec) -> Self { + pub fn clone_with_updates(&self, field_tracking: Vec, array_loads: HashSet>, array_stores: HashSet>) -> Self { LLVMCircuitData { field_tracking, io_map: self.io_map.clone(), signal_index_mapping: self.signal_index_mapping.clone(), variable_index_mapping: self.variable_index_mapping.clone(), component_index_mapping: self.component_index_mapping.clone(), + bounded_array_loads: array_loads, + bounded_array_stores: array_stores, } } } diff --git a/compiler/src/circuit_design/circuit.rs b/compiler/src/circuit_design/circuit.rs index 658ca9e25..ec89db5d6 100644 --- a/compiler/src/circuit_design/circuit.rs +++ b/compiler/src/circuit_design/circuit.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use std::io::Write; use super::function::{FunctionCode, FunctionCodeInfo}; use super::template::{TemplateCode, TemplateCodeInfo}; @@ -7,8 +7,8 @@ use crate::hir::very_concrete_program::VCP; use crate::intermediate_representation::ir_interface::ObtainMeta; use crate::translating_traits::*; use code_producers::c_elements::*; +use code_producers::llvm_elements::array_switch::{load_array_stores_fns, load_array_load_fns}; use code_producers::llvm_elements::*; -use code_producers::llvm_elements::array_switch::load_array_switch; use code_producers::llvm_elements::fr::load_fr; use code_producers::llvm_elements::functions::{ create_function, FunctionLLVMIRProducer, ExtractedFunctionLLVMIRProducer, @@ -55,23 +55,9 @@ impl WriteLLVMIR for Circuit { load_fr(producer); load_stdlib(producer); - // Generate all the switch functions - let mut ranges = HashSet::new(); - let mappings = [ - &self.llvm_data.signal_index_mapping, - &self.llvm_data.variable_index_mapping, - &self.llvm_data.component_index_mapping, - ]; - for mapping in mappings { - for range_mapping in mapping.values() { - for range in range_mapping.values() { - ranges.insert(range); - } - } - } - for range in ranges { - load_array_switch(producer, range); - } + // Code for bounded array switch functions + load_array_load_fns(producer, &self.llvm_data.bounded_array_loads); + load_array_stores_fns(producer, &self.llvm_data.bounded_array_stores); // Declare all the functions let mut funcs = HashMap::new(); @@ -229,7 +215,7 @@ impl WriteWasm for Circuit { code.append(&mut code_aux); code_aux = get_input_size_generator(&producer); - code.append(&mut code_aux); + code.append(&mut code_aux); code_aux = get_witness_size_generator(&producer); code.append(&mut code_aux); @@ -369,7 +355,7 @@ impl WriteWasm for Circuit { code = merge_code(code_aux); writer.write_all(code.as_bytes()).map_err(|_| {})?; writer.flush().map_err(|_| {})?; - + code_aux = get_witness_size_generator(&producer); code = merge_code(code_aux); writer.write_all(code.as_bytes()).map_err(|_| {})?; @@ -460,7 +446,7 @@ impl WriteC for Circuit { std::mem::drop(function_headers); let (func_list_no_parallel, func_list_parallel) = generate_function_list( - producer, + producer, producer.get_template_instance_list() ); @@ -476,7 +462,7 @@ impl WriteC for Circuit { "uint get_main_input_signal_start() {{return {};}}\n", producer.get_number_of_main_outputs() )); - + code.push(format!( "uint get_main_input_signal_no() {{return {};}}\n", producer.get_number_of_main_inputs() @@ -503,7 +489,7 @@ impl WriteC for Circuit { producer.get_io_map().len() )); //code.append(&mut generate_message_list_def(producer, producer.get_message_list())); - + // Functions to release the memory let mut release_component_code = generate_function_release_memory_component(); code.append(&mut release_component_code); diff --git a/compiler/src/circuit_design/template.rs b/compiler/src/circuit_design/template.rs index c0605aed2..8feb335d1 100644 --- a/compiler/src/circuit_design/template.rs +++ b/compiler/src/circuit_design/template.rs @@ -59,7 +59,9 @@ impl ToString for TemplateCodeInfo { impl WriteLLVMIR for TemplateCodeInfo { fn produce_llvm_ir<'ctx, 'prod>(&self, producer: &'prod dyn LLVMIRProducer<'ctx>) -> Option> { - println!("Generating code for {}", self.header); + if cfg!(debug_assertions) { + println!("Generating code for {}", self.header); + } let void = void_type(producer); let n_signals = self.number_of_inputs + self.number_of_outputs + self.number_of_intermediates; let template_struct = create_template_struct(producer, n_signals); From fd83689e581c30e7a947a2a0e5df4f5a56ee0526 Mon Sep 17 00:00:00 2001 From: Timothy Hoffman <4001421+tim-hoffman@users.noreply.github.com> Date: Mon, 30 Oct 2023 11:22:51 -0500 Subject: [PATCH 4/9] skip body extraction when the loop has 0 iterations (#57) --- circom/tests/subcmps/conv_map2idx_C.circom | 55 ++++++++++++++++++++ circuit_passes/src/passes/loop_unroll/mod.rs | 2 +- 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 circom/tests/subcmps/conv_map2idx_C.circom diff --git a/circom/tests/subcmps/conv_map2idx_C.circom b/circom/tests/subcmps/conv_map2idx_C.circom new file mode 100644 index 000000000..bf78759b6 --- /dev/null +++ b/circom/tests/subcmps/conv_map2idx_C.circom @@ -0,0 +1,55 @@ +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 --enable-var-scope + +template SegmentMulFix(nWindows) { + signal input e[nWindows]; +} + +template EscalarMulFix() { + //Needs at least 2 subcomp to trigger the crash + component segments[2]; + for (var s = 0; s < 2; s++) { + + // s = 0, nseg = 9, nWindows = 9 + // s = 1, nseg = 4, nWindows = 6 + var nseg = (s == 0) ? 9 : 4; + var nWindows = (s == 0) ? 9 : 6; + + segments[s] = SegmentMulFix(nWindows); + + // Needs this split loop to trigger the crash + for (var i = 0; i < nseg; i++) { + //Runs 9 times for s=0 + //Runs 4 times for s=1 + segments[s].e[i] <-- 999; + } + for (var i = nseg; i < nWindows; i++) { + //Runs 0 times for s=0 //this is the case where the extracted body is generated but shouldn't be! + //Runs 2 times for s=1 + segments[s].e[i] <-- 888; + } + } +} + +component main = EscalarMulFix(); + +//CHECK-NOT: ..generated..loop.body. +// +//CHECK-LABEL: define void @EscalarMulFix_2_run([0 x i256]* %0) +//CHECK: store i256 999 +//CHECK: store i256 999 +//CHECK: store i256 999 +//CHECK: store i256 999 +//CHECK: store i256 999 +//CHECK: store i256 999 +//CHECK: store i256 999 +//CHECK: store i256 999 +//CHECK: store i256 999 +//CHECK: store i256 999 +//CHECK: store i256 999 +//CHECK: store i256 999 +//CHECK: store i256 999 +//CHECK: store i256 888 +//CHECK: store i256 888 diff --git a/circuit_passes/src/passes/loop_unroll/mod.rs b/circuit_passes/src/passes/loop_unroll/mod.rs index 1fd37131a..59f193a67 100644 --- a/circuit_passes/src/passes/loop_unroll/mod.rs +++ b/circuit_passes/src/passes/loop_unroll/mod.rs @@ -64,7 +64,7 @@ impl<'d> LoopUnrollPass<'d> { } let mut block_body = vec![]; - if EXTRACT_LOOP_BODY_TO_NEW_FUNC && recorder.is_safe_to_move() { + if EXTRACT_LOOP_BODY_TO_NEW_FUNC && recorder.is_safe_to_move() && recorder.get_iter() > 0 { // If the loop body contains more than one instruction, extract it into a new // function and generate 'recorder.get_iter()' number of calls to that function. // Otherwise, just duplicate the body 'recorder.get_iter()' number of times. From 4e99d42067882f961dff22229d61f8f122e04c69 Mon Sep 17 00:00:00 2001 From: Timothy Hoffman <4001421+tim-hoffman@users.noreply.github.com> Date: Mon, 30 Oct 2023 17:29:55 -0500 Subject: [PATCH 5/9] Various fixes for benchmarks (#62) * skip body extraction when the loop has 0 iterations * Modify interpreter to distinguish between circom functions and loop body functions * [VAN-676] duplicate extracted functions when flattening branch buckets * [VAN-670] generate and flatten subcmp counter/run * impl Debug for Env to be more friendly, expand on test case comment * remove debug println * fix: conditions not flattening in non-generated methods * [VAN-582] properly convert mapped to indexed when there are multiple versions of the subcomponent * fix XFAIL test outputs so they pass * add test cases * handle CallBucket return case in mapped_to_indexed * fix body_extractor assertion failure * fix segfault from improper GEP * use BucketId as key to speed up SimplificationPass * fix function name to reflect actual usage * Remove functions that cannot be reached from any template Co-authored-by: Daniel Dominguez --- circom/src/compilation_user.rs | 1 + circom/tests/loops/assign_in_loop_1.circom | 148 +++++ circom/tests/loops/assign_in_loop_2.circom | 46 ++ circom/tests/loops/assign_in_loop_3.circom | 46 ++ circom/tests/loops/call_inside_loop.circom | 35 +- .../tests/loops/fixed_idx_in_fixed_idx.circom | 119 ++++ circom/tests/loops/inner_conditional_1.circom | 98 ++-- .../tests/loops/inner_conditional_10.circom | 3 + .../tests/loops/inner_conditional_11.circom | 142 +++++ circom/tests/loops/inner_conditional_4.circom | 76 +-- circom/tests/loops/inner_conditional_7.circom | 169 ++---- circom/tests/loops/inner_conditional_9.circom | 138 +++-- circom/tests/subcmps/conv_map2idx_A.circom | 2 +- circom/tests/subcmps/mapped.circom | 406 ++++++++++++- circom/tests/subcmps/mapped2.circom | 554 +++++++++++++++++- circom/tests/subcmps/mapped3.circom | 146 ++++- circom/tests/subcmps/mapped4.circom | 222 ++++++- circom/tests/subcmps/subcmps0A.circom | 45 +- circom/tests/subcmps/subcmps0B.circom | 53 +- circom/tests/subcmps/subcmps0C.circom | 45 +- circom/tests/subcmps/subcmps0D.circom | 66 ++- circom/tests/subcmps/subcmps1.circom | 51 +- circom/tests/subcmps/subcmps2.circom | 469 ++++++++------- circom/tests/subcmps/subcmps3.circom | 231 ++++++++ .../tests/zzz/unreachable_code_crash.circom | 43 ++ .../env/extracted_func_env.rs | 204 ++++--- .../src/bucket_interpreter/env/mod.rs | 60 +- .../bucket_interpreter/env/standard_env.rs | 37 +- .../env/unrolled_block_env.rs | 16 + .../src/bucket_interpreter/memory.rs | 8 +- circuit_passes/src/bucket_interpreter/mod.rs | 50 +- .../bucket_interpreter/observed_visitor.rs | 145 +++++ .../src/bucket_interpreter/observer.rs | 79 +-- .../src/passes/conditional_flattening.rs | 183 +++++- .../deterministic_subcomponent_invocation.rs | 8 +- .../src/passes/loop_unroll/body_extractor.rs | 110 ++-- .../loop_unroll/extracted_location_updater.rs | 241 ++++++-- .../passes/loop_unroll/loop_env_recorder.rs | 48 +- circuit_passes/src/passes/loop_unroll/mod.rs | 30 +- .../src/passes/mapped_to_indexed.rs | 82 +-- circuit_passes/src/passes/mod.rs | 54 +- circuit_passes/src/passes/simplification.rs | 27 +- .../src/passes/unknown_index_sanitization.rs | 12 +- .../src/passes/unused_func_removal.rs | 169 ++++++ code_producers/src/llvm_elements/fr.rs | 15 + code_producers/src/llvm_elements/functions.rs | 37 +- code_producers/src/llvm_elements/mod.rs | 14 +- code_producers/src/llvm_elements/stdlib.rs | 16 +- code_producers/src/llvm_elements/template.rs | 10 + .../call_bucket.rs | 4 +- .../ir_interface.rs | 30 + .../load_bucket.rs | 12 +- .../location_rule.rs | 2 +- .../store_bucket.rs | 89 +-- 54 files changed, 4084 insertions(+), 1062 deletions(-) create mode 100644 circom/tests/loops/assign_in_loop_1.circom create mode 100644 circom/tests/loops/assign_in_loop_2.circom create mode 100644 circom/tests/loops/assign_in_loop_3.circom create mode 100644 circom/tests/loops/fixed_idx_in_fixed_idx.circom create mode 100644 circom/tests/loops/inner_conditional_11.circom create mode 100644 circom/tests/subcmps/subcmps3.circom create mode 100644 circom/tests/zzz/unreachable_code_crash.circom create mode 100644 circuit_passes/src/bucket_interpreter/observed_visitor.rs create mode 100644 circuit_passes/src/passes/unused_func_removal.rs diff --git a/circom/src/compilation_user.rs b/circom/src/compilation_user.rs index e802ebc0f..e27be8cda 100644 --- a/circom/src/compilation_user.rs +++ b/circom/src/compilation_user.rs @@ -65,6 +65,7 @@ pub fn compile(config: CompilerConfig, program_archive: ProgramArchive, prime: & .schedule_const_arg_deduplication_pass() .schedule_loop_unroll_pass() .schedule_conditional_flattening_pass() + .schedule_unused_function_removal_pass() //previous 2 passes create the dead functions .schedule_mapped_to_indexed_pass() .schedule_unknown_index_sanitization_pass() .schedule_simplification_pass() diff --git a/circom/tests/loops/assign_in_loop_1.circom b/circom/tests/loops/assign_in_loop_1.circom new file mode 100644 index 000000000..acac850d7 --- /dev/null +++ b/circom/tests/loops/assign_in_loop_1.circom @@ -0,0 +1,148 @@ +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 --enable-var-scope + +template Inner() { + signal input in; + signal output out; + + out <-- in & 1; +} + +template Num2Bits(n) { + signal input in; + signal output out[n]; + + component c[n]; + for (var i = 0; i < n; i++) { + c[i] = Inner(); + c[i].in <-- in; + out[i] <-- c[i].out; + } +} + +component main = Num2Bits(3); + +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %subfix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %subfix_[[X3:[0-9]+]], +//CHECK-SAME: [0 x i256]* %sub_[[X3]], i256* %subc_[[X3]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+\.T]]: +//CHECK-NEXT: br label %store1 +//CHECK-EMPTY: +//CHECK-NEXT: store1: +//CHECK-NEXT: %0 = getelementptr [0 x i256], [0 x i256]* %signals, i32 0, i32 3 +//CHECK-NEXT: %1 = load i256, i256* %0, align 4 +//CHECK-NEXT: %2 = getelementptr i256, i256* %subfix_[[X1]], i32 0 +//CHECK-NEXT: store i256 %1, i256* %2, align 4 +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %3 = load i256, i256* %subc_[[X3]], align 4 +//CHECK-NEXT: %call.fr_sub = call i256 @fr_sub(i256 %3, i256 1) +//CHECK-NEXT: %4 = getelementptr i256, i256* %subc_[[X3]], i32 0 +//CHECK-NEXT: store i256 %call.fr_sub, i256* %4, align 4 +//CHECK-NEXT: br label %fold_true3 +//CHECK-EMPTY: +//CHECK-NEXT: fold_true3: +//CHECK-NEXT: call void @llvm.donothing() +//CHECK-NEXT: call void @Inner_0_run([0 x i256]* %sub_[[X3]]) +//CHECK-NEXT: br label %store4 +//CHECK-EMPTY: +//CHECK-NEXT: store4: +//CHECK-NEXT: %5 = getelementptr i256, i256* %subfix_[[X3]], i32 0 +//CHECK-NEXT: %6 = load i256, i256* %5, align 4 +//CHECK-NEXT: %7 = getelementptr i256, i256* %fix_[[X2]], i32 0 +//CHECK-NEXT: store i256 %6, i256* %7, align 4 +//CHECK-NEXT: br label %store5 +//CHECK-EMPTY: +//CHECK-NEXT: store5: +//CHECK-NEXT: %8 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: %9 = load i256, i256* %8, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %9, i256 1) +//CHECK-NEXT: %10 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 %call.fr_add, i256* %10, align 4 +//CHECK-NEXT: br label %return6 +//CHECK-EMPTY: +//CHECK-NEXT: return6: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @Num2Bits_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-NEXT: prelude: +//CHECK-NEXT: %lvars = alloca [2 x i256], align 8 +//CHECK-NEXT: %subcmps = alloca [3 x { [0 x i256]*, i32 }], align 8 +//CHECK-NEXT: br label %store1 +//CHECK-EMPTY: +//CHECK-NEXT: store1: +//CHECK-NEXT: %1 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: store i256 3, i256* %1, align 4 +//CHECK-NEXT: br label %create_cmp2 +//CHECK-EMPTY: +//CHECK-NEXT: create_cmp2: +//CHECK-NEXT: %2 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0 +//CHECK-NEXT: call void @Inner_0_build({ [0 x i256]*, i32 }* %2) +//CHECK-NEXT: %3 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1 +//CHECK-NEXT: call void @Inner_0_build({ [0 x i256]*, i32 }* %3) +//CHECK-NEXT: %4 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2 +//CHECK-NEXT: call void @Inner_0_build({ [0 x i256]*, i32 }* %4) +//CHECK-NEXT: br label %store3 +//CHECK-EMPTY: +//CHECK-NEXT: store3: +//CHECK-NEXT: %5 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 0, i256* %5, align 4 +//CHECK-NEXT: br label %unrolled_loop4 +//CHECK-EMPTY: +//CHECK-NEXT: unrolled_loop4: +//CHECK-NEXT: %6 = bitcast [2 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %7 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %8 = load [0 x i256]*, [0 x i256]** %7, align 8 +//CHECK-NEXT: %9 = getelementptr [0 x i256], [0 x i256]* %8, i32 0 +//CHECK-NEXT: %10 = getelementptr [0 x i256], [0 x i256]* %9, i32 0, i256 1 +//CHECK-NEXT: %11 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 0 +//CHECK-NEXT: %12 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %13 = load [0 x i256]*, [0 x i256]** %12, align 8 +//CHECK-NEXT: %14 = getelementptr [0 x i256], [0 x i256]* %13, i32 0 +//CHECK-NEXT: %15 = getelementptr [0 x i256], [0 x i256]* %14, i32 0, i256 0 +//CHECK-NEXT: %16 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %17 = load [0 x i256]*, [0 x i256]** %16, align 8 +//CHECK-NEXT: %18 = getelementptr [0 x i256], [0 x i256]* %17, i32 0 +//CHECK-NEXT: %19 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 1 +//CHECK-NEXT: %20 = bitcast i32* %19 to i256* +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %6, [0 x i256]* %0, i256* %10, i256* %11, i256* %15, [0 x i256]* %18, i256* %20) +//CHECK-NEXT: %21 = bitcast [2 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %22 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 0 +//CHECK-NEXT: %23 = load [0 x i256]*, [0 x i256]** %22, align 8 +//CHECK-NEXT: %24 = getelementptr [0 x i256], [0 x i256]* %23, i32 0 +//CHECK-NEXT: %25 = getelementptr [0 x i256], [0 x i256]* %24, i32 0, i256 1 +//CHECK-NEXT: %26 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 1 +//CHECK-NEXT: %27 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 0 +//CHECK-NEXT: %28 = load [0 x i256]*, [0 x i256]** %27, align 8 +//CHECK-NEXT: %29 = getelementptr [0 x i256], [0 x i256]* %28, i32 0 +//CHECK-NEXT: %30 = getelementptr [0 x i256], [0 x i256]* %29, i32 0, i256 0 +//CHECK-NEXT: %31 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 0 +//CHECK-NEXT: %32 = load [0 x i256]*, [0 x i256]** %31, align 8 +//CHECK-NEXT: %33 = getelementptr [0 x i256], [0 x i256]* %32, i32 0 +//CHECK-NEXT: %34 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 1 +//CHECK-NEXT: %35 = bitcast i32* %34 to i256* +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %21, [0 x i256]* %0, i256* %25, i256* %26, i256* %30, [0 x i256]* %33, i256* %35) +//CHECK-NEXT: %36 = bitcast [2 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %37 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2, i32 0 +//CHECK-NEXT: %38 = load [0 x i256]*, [0 x i256]** %37, align 8 +//CHECK-NEXT: %39 = getelementptr [0 x i256], [0 x i256]* %38, i32 0 +//CHECK-NEXT: %40 = getelementptr [0 x i256], [0 x i256]* %39, i32 0, i256 1 +//CHECK-NEXT: %41 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 2 +//CHECK-NEXT: %42 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2, i32 0 +//CHECK-NEXT: %43 = load [0 x i256]*, [0 x i256]** %42, align 8 +//CHECK-NEXT: %44 = getelementptr [0 x i256], [0 x i256]* %43, i32 0 +//CHECK-NEXT: %45 = getelementptr [0 x i256], [0 x i256]* %44, i32 0, i256 0 +//CHECK-NEXT: %46 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2, i32 0 +//CHECK-NEXT: %47 = load [0 x i256]*, [0 x i256]** %46, align 8 +//CHECK-NEXT: %48 = getelementptr [0 x i256], [0 x i256]* %47, i32 0 +//CHECK-NEXT: %49 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2, i32 1 +//CHECK-NEXT: %50 = bitcast i32* %49 to i256* +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %36, [0 x i256]* %0, i256* %40, i256* %41, i256* %45, [0 x i256]* %48, i256* %50) +//CHECK-NEXT: br label %prologue +//CHECK-EMPTY: +//CHECK-NEXT: prologue: +//CHECK-NEXT: ret void +//CHECK-NEXT: } diff --git a/circom/tests/loops/assign_in_loop_2.circom b/circom/tests/loops/assign_in_loop_2.circom new file mode 100644 index 000000000..f6a7caa39 --- /dev/null +++ b/circom/tests/loops/assign_in_loop_2.circom @@ -0,0 +1,46 @@ +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 --enable-var-scope + +// References to the Inner subcmp use LocationRule::Mapped because of the 'i' parameter +template Inner(i) { + signal input in; + signal output out; + + out <-- in & i; +} + +template Num2Bits(n) { + signal input in; + signal output out[n]; + + component c[n]; + for (var i = 0; i < n; i++) { + c[i] = Inner(i); + c[i].in <-- in; + out[i] <-- c[i].out; + } +} + +component main = Num2Bits(3); + +//CHECK-LABEL: define void @Inner_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +// +//CHECK-LABEL: define void @Inner_ +//CHECK-SAME: [[$RUN_1:[0-9]+]]_run([0 x i256]* %0){{.*}} { +// +//CHECK-LABEL: define void @Inner_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +// +//CHECK-LABEL: define void @Inner_ +//CHECK-SAME: [[$RUN_2:[0-9]+]]_run([0 x i256]* %0){{.*}} { +// +//CHECK-LABEL: define void @Inner_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +// +//CHECK-LABEL: define void @Inner_ +//CHECK-SAME: [[$RUN_3:[0-9]+]]_run([0 x i256]* %0){{.*}} { +// +//CHECK-LABEL: define void @Num2Bits_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK: unrolled_loop{{[0-9]+}}: +//CHECK: call void @Inner_[[$RUN_1]]_run([0 x i256]* % +//CHECK: call void @Inner_[[$RUN_2]]_run([0 x i256]* % +//CHECK: call void @Inner_[[$RUN_3]]_run([0 x i256]* % diff --git a/circom/tests/loops/assign_in_loop_3.circom b/circom/tests/loops/assign_in_loop_3.circom new file mode 100644 index 000000000..cef469df3 --- /dev/null +++ b/circom/tests/loops/assign_in_loop_3.circom @@ -0,0 +1,46 @@ +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 --enable-var-scope + +// References to the Inner subcmp use LocationRule::Mapped because of the 'i' parameter +template Inner(i,j) { + signal input in; + signal output out; + + out <-- (in >> i) & j; +} + +template Num2Bits(n) { + signal input in; + signal output out[n]; + + component c[n]; + for (var i = 0; i < n; i++) { + c[i] = Inner(i, i+1); + c[i].in <-- in; + out[i] <-- c[i].out; + } +} + +component main = Num2Bits(3); + +//CHECK-LABEL: define void @Inner_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +// +//CHECK-LABEL: define void @Inner_ +//CHECK-SAME: [[$RUN_1:[0-9]+]]_run([0 x i256]* %0){{.*}} { +// +//CHECK-LABEL: define void @Inner_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +// +//CHECK-LABEL: define void @Inner_ +//CHECK-SAME: [[$RUN_2:[0-9]+]]_run([0 x i256]* %0){{.*}} { +// +//CHECK-LABEL: define void @Inner_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +// +//CHECK-LABEL: define void @Inner_ +//CHECK-SAME: [[$RUN_3:[0-9]+]]_run([0 x i256]* %0){{.*}} { +// +//CHECK-LABEL: define void @Num2Bits_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK: unrolled_loop{{[0-9]+}}: +//CHECK: call void @Inner_[[$RUN_1]]_run([0 x i256]* % +//CHECK: call void @Inner_[[$RUN_2]]_run([0 x i256]* % +//CHECK: call void @Inner_[[$RUN_3]]_run([0 x i256]* % diff --git a/circom/tests/loops/call_inside_loop.circom b/circom/tests/loops/call_inside_loop.circom index 912ce3287..3a4375cd7 100644 --- a/circom/tests/loops/call_inside_loop.circom +++ b/circom/tests/loops/call_inside_loop.circom @@ -70,7 +70,7 @@ component main = CallInLoop(2, 3); //CHECK-NEXT: } // //CHECK-LABEL: define void @..generated..loop.body. -//CHECK-SAME: [[$F_ID_2:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals){{.*}} { +//CHECK-SAME: [[$F_ID_2:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_2]]: //CHECK-NEXT: br label %call1 //CHECK-EMPTY: @@ -95,21 +95,16 @@ component main = CallInLoop(2, 3); //CHECK-NEXT: store i256 3, i256* %8, align 4 //CHECK-NEXT: %9 = bitcast [15 x i256]* %fun_0_arena to i256* //CHECK-NEXT: %call.fun_0 = call i256 @fun_0(i256* %9) -//CHECK-NEXT: %10 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 6 -//CHECK-NEXT: %11 = load i256, i256* %10, align 4 -//CHECK-NEXT: %call.fr_cast_to_addr = call i32 @fr_cast_to_addr(i256 %11) -//CHECK-NEXT: %mul_addr = mul i32 1, %call.fr_cast_to_addr -//CHECK-NEXT: %add_addr = add i32 %mul_addr, 4 -//CHECK-NEXT: %12 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 %add_addr -//CHECK-NEXT: store i256 %call.fun_0, i256* %12, align 4 +//CHECK-NEXT: %10 = getelementptr i256, i256* %fix_0, i32 0 +//CHECK-NEXT: store i256 %call.fun_0, i256* %10, align 4 //CHECK-NEXT: br label %store2 //CHECK-EMPTY: //CHECK-NEXT: store2: +//CHECK-NEXT: %11 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 6 +//CHECK-NEXT: %12 = load i256, i256* %11, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %12, i256 1) //CHECK-NEXT: %13 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 6 -//CHECK-NEXT: %14 = load i256, i256* %13, align 4 -//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %14, i256 1) -//CHECK-NEXT: %15 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 6 -//CHECK-NEXT: store i256 %call.fr_add, i256* %15, align 4 +//CHECK-NEXT: store i256 %call.fr_add, i256* %13, align 4 //CHECK-NEXT: br label %return3 //CHECK-EMPTY: //CHECK-NEXT: return3: @@ -175,16 +170,20 @@ component main = CallInLoop(2, 3); //CHECK-EMPTY: //CHECK-NEXT: unrolled_loop10: //CHECK-NEXT: %15 = bitcast [7 x i256]* %lvars to [0 x i256]* -//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %15, [0 x i256]* %0) //CHECK-NEXT: %16 = bitcast [7 x i256]* %lvars to [0 x i256]* -//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %16, [0 x i256]* %0) +//CHECK-NEXT: %17 = getelementptr [0 x i256], [0 x i256]* %16, i32 0, i256 4 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %15, [0 x i256]* %0, i256* %17) +//CHECK-NEXT: %18 = bitcast [7 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %19 = bitcast [7 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %20 = getelementptr [0 x i256], [0 x i256]* %19, i32 0, i256 5 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %18, [0 x i256]* %0, i256* %20) //CHECK-NEXT: br label %store11 //CHECK-EMPTY: //CHECK-NEXT: store11: -//CHECK-NEXT: %17 = getelementptr [7 x i256], [7 x i256]* %lvars, i32 0, i32 4 -//CHECK-NEXT: %18 = load i256, i256* %17, align 4 -//CHECK-NEXT: %19 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 0 -//CHECK-NEXT: store i256 %18, i256* %19, align 4 +//CHECK-NEXT: %21 = getelementptr [7 x i256], [7 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: %22 = load i256, i256* %21, align 4 +//CHECK-NEXT: %23 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 0 +//CHECK-NEXT: store i256 %22, i256* %23, align 4 //CHECK-NEXT: br label %prologue //CHECK-EMPTY: //CHECK-NEXT: prologue: diff --git a/circom/tests/loops/fixed_idx_in_fixed_idx.circom b/circom/tests/loops/fixed_idx_in_fixed_idx.circom new file mode 100644 index 000000000..6f34c84b3 --- /dev/null +++ b/circom/tests/loops/fixed_idx_in_fixed_idx.circom @@ -0,0 +1,119 @@ +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 --enable-var-scope + +// This case initially triggered the "assert!(bucket_to_args.is_empty());" line in body_extractor.rs +// because the entire expression 'in[byte_order[i]]'' is replaced but the 'byte_order[i]' expression +// is also listed in the "bucket_to_args" map as a safe replacement. +template EmulatedAesencRowShifting() { + signal input in[16]; + signal output out[16]; + + var byte_order[16] = [0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11]; + + for (var i = 0; i < 16; i++) { + out[i] <== in[byte_order[i]]; + } +} + +component main = EmulatedAesencRowShifting(); + +//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0, i256* %fix_1){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1]]: +//CHECK-NEXT: br label %store1 +//CHECK-EMPTY: +//CHECK-NEXT: store1: +//CHECK-NEXT: %0 = getelementptr i256, i256* %fix_1, i32 0 +//CHECK-NEXT: %1 = load i256, i256* %0, align 4 +//CHECK-NEXT: %2 = getelementptr i256, i256* %fix_0, i32 0 +//CHECK-NEXT: store i256 %1, i256* %2, align 4 +//CHECK-NEXT: %3 = load i256, i256* %2, align 4 +//CHECK-NEXT: %constraint = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %1, i256 %3, i1* %constraint) +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %4 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 16 +//CHECK-NEXT: %5 = load i256, i256* %4, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %5, i256 1) +//CHECK-NEXT: %6 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 16 +//CHECK-NEXT: store i256 %call.fr_add, i256* %6, align 4 +//CHECK-NEXT: br label %return3 +//CHECK-EMPTY: +//CHECK-NEXT: return3: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @EmulatedAesencRowShifting_0_run([0 x i256]* %0){{.*}} { +//CHECK-NEXT: prelude: +//CHECK-NEXT: %lvars = alloca [17 x i256], align 8 +//CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 +//CHECK-NEXT: br label %store1 +//CHECK-EMPTY: +//CHECK: unrolled_loop18: +//CHECK-NEXT: %18 = bitcast [17 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %19 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 0 +//CHECK-NEXT: %20 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 16 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %18, [0 x i256]* %0, i256* %19, i256* %20) +//CHECK-NEXT: %21 = bitcast [17 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %22 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 1 +//CHECK-NEXT: %23 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 21 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %21, [0 x i256]* %0, i256* %22, i256* %23) +//CHECK-NEXT: %24 = bitcast [17 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %25 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 2 +//CHECK-NEXT: %26 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 26 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %24, [0 x i256]* %0, i256* %25, i256* %26) +//CHECK-NEXT: %27 = bitcast [17 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %28 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 3 +//CHECK-NEXT: %29 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 31 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %27, [0 x i256]* %0, i256* %28, i256* %29) +//CHECK-NEXT: %30 = bitcast [17 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %31 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 4 +//CHECK-NEXT: %32 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 20 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %30, [0 x i256]* %0, i256* %31, i256* %32) +//CHECK-NEXT: %33 = bitcast [17 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %34 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 5 +//CHECK-NEXT: %35 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 25 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %33, [0 x i256]* %0, i256* %34, i256* %35) +//CHECK-NEXT: %36 = bitcast [17 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %37 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 6 +//CHECK-NEXT: %38 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 30 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %36, [0 x i256]* %0, i256* %37, i256* %38) +//CHECK-NEXT: %39 = bitcast [17 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %40 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 7 +//CHECK-NEXT: %41 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 19 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %39, [0 x i256]* %0, i256* %40, i256* %41) +//CHECK-NEXT: %42 = bitcast [17 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %43 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 8 +//CHECK-NEXT: %44 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 24 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %42, [0 x i256]* %0, i256* %43, i256* %44) +//CHECK-NEXT: %45 = bitcast [17 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %46 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 9 +//CHECK-NEXT: %47 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 29 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %45, [0 x i256]* %0, i256* %46, i256* %47) +//CHECK-NEXT: %48 = bitcast [17 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %49 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 10 +//CHECK-NEXT: %50 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 18 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %48, [0 x i256]* %0, i256* %49, i256* %50) +//CHECK-NEXT: %51 = bitcast [17 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %52 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 11 +//CHECK-NEXT: %53 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 23 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %51, [0 x i256]* %0, i256* %52, i256* %53) +//CHECK-NEXT: %54 = bitcast [17 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %55 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 12 +//CHECK-NEXT: %56 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 28 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %54, [0 x i256]* %0, i256* %55, i256* %56) +//CHECK-NEXT: %57 = bitcast [17 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %58 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 13 +//CHECK-NEXT: %59 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 17 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %57, [0 x i256]* %0, i256* %58, i256* %59) +//CHECK-NEXT: %60 = bitcast [17 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %61 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 14 +//CHECK-NEXT: %62 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 22 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %60, [0 x i256]* %0, i256* %61, i256* %62) +//CHECK-NEXT: %63 = bitcast [17 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %64 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 15 +//CHECK-NEXT: %65 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 27 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %63, [0 x i256]* %0, i256* %64, i256* %65) +//CHECK-NEXT: br label %prologue diff --git a/circom/tests/loops/inner_conditional_1.circom b/circom/tests/loops/inner_conditional_1.circom index 85c98fca5..f76f5f361 100644 --- a/circom/tests/loops/inner_conditional_1.circom +++ b/circom/tests/loops/inner_conditional_1.circom @@ -14,55 +14,73 @@ template InnerConditional1(N) { acc -= i; } } + //Values at loop header per iteration + // N, acc, i + // 10, 0, 1 + // 10, 1, 2 + // 10, 3, 3 + // 10, 6, 4 + // 10, 10, 5 + // 10, 5, 6 + // 10, -1, 7 + // 10, -8, 8 + // 10, -16, 9 + // 10, -25, 10 out <-- acc; } component main = InnerConditional1(10); -//CHECK-LABEL: define void @..generated..loop.body. -//CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1]]: -//CHECK-NEXT: br label %branch1 +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}.F([0 x i256]* %lvars, [0 x i256]* %signals){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+\.F]]: +//CHECK-NEXT: br label %fold_false1 //CHECK-EMPTY: -//CHECK-NEXT: branch1: -//CHECK-NEXT: %0 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 2 +//CHECK-NEXT: fold_false1: +//CHECK-NEXT: %0 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 //CHECK-NEXT: %1 = load i256, i256* %0, align 4 -//CHECK-NEXT: %call.fr_lt = call i1 @fr_lt(i256 %1, i256 5) -//CHECK-NEXT: br i1 %call.fr_lt, label %if.then, label %if.else -//CHECK-EMPTY: -//CHECK-NEXT: if.then: -//CHECK-NEXT: %2 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: %2 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 2 //CHECK-NEXT: %3 = load i256, i256* %2, align 4 -//CHECK-NEXT: %4 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 2 -//CHECK-NEXT: %5 = load i256, i256* %4, align 4 -//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %3, i256 %5) -//CHECK-NEXT: %6 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 -//CHECK-NEXT: store i256 %call.fr_add, i256* %6, align 4 -//CHECK-NEXT: br label %if.merge +//CHECK-NEXT: %call.fr_sub = call i256 @fr_sub(i256 %1, i256 %3) +//CHECK-NEXT: %4 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 %call.fr_sub, i256* %4, align 4 +//CHECK-NEXT: br label %store2 //CHECK-EMPTY: -//CHECK-NEXT: if.else: -//CHECK-NEXT: %7 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 -//CHECK-NEXT: %8 = load i256, i256* %7, align 4 -//CHECK-NEXT: %9 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 2 -//CHECK-NEXT: %10 = load i256, i256* %9, align 4 -//CHECK-NEXT: %call.fr_sub = call i256 @fr_sub(i256 %8, i256 %10) -//CHECK-NEXT: %11 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 -//CHECK-NEXT: store i256 %call.fr_sub, i256* %11, align 4 -//CHECK-NEXT: br label %if.merge +//CHECK-NEXT: store2: +//CHECK-NEXT: %5 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 2 +//CHECK-NEXT: %6 = load i256, i256* %5, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %6, i256 1) +//CHECK-NEXT: %7 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 2 +//CHECK-NEXT: store i256 %call.fr_add, i256* %7, align 4 +//CHECK-NEXT: br label %return3 //CHECK-EMPTY: -//CHECK-NEXT: if.merge: -//CHECK-NEXT: br label %store5 +//CHECK-NEXT: return3: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}.T([0 x i256]* %lvars, [0 x i256]* %signals){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_2:[0-9]+\.T]]: +//CHECK-NEXT: br label %fold_true1 //CHECK-EMPTY: -//CHECK-NEXT: store5: -//CHECK-NEXT: %12 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 2 -//CHECK-NEXT: %13 = load i256, i256* %12, align 4 -//CHECK-NEXT: %call.fr_add1 = call i256 @fr_add(i256 %13, i256 1) -//CHECK-NEXT: %14 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 2 -//CHECK-NEXT: store i256 %call.fr_add1, i256* %14, align 4 -//CHECK-NEXT: br label %return6 +//CHECK-NEXT: fold_true1: +//CHECK-NEXT: %0 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: %1 = load i256, i256* %0, align 4 +//CHECK-NEXT: %2 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 2 +//CHECK-NEXT: %3 = load i256, i256* %2, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %1, i256 %3) +//CHECK-NEXT: %4 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 %call.fr_add, i256* %4, align 4 +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %5 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 2 +//CHECK-NEXT: %6 = load i256, i256* %5, align 4 +//CHECK-NEXT: %call.fr_add1 = call i256 @fr_add(i256 %6, i256 1) +//CHECK-NEXT: %7 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 2 +//CHECK-NEXT: store i256 %call.fr_add1, i256* %7, align 4 +//CHECK-NEXT: br label %return3 //CHECK-EMPTY: -//CHECK-NEXT: return6: +//CHECK-NEXT: return3: //CHECK-NEXT: ret void //CHECK-NEXT: } // @@ -89,13 +107,13 @@ component main = InnerConditional1(10); //CHECK-EMPTY: //CHECK-NEXT: unrolled_loop4: //CHECK-NEXT: %4 = bitcast [3 x i256]* %lvars to [0 x i256]* -//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %4, [0 x i256]* %0) +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %4, [0 x i256]* %0) //CHECK-NEXT: %5 = bitcast [3 x i256]* %lvars to [0 x i256]* -//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %5, [0 x i256]* %0) +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %5, [0 x i256]* %0) //CHECK-NEXT: %6 = bitcast [3 x i256]* %lvars to [0 x i256]* -//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %6, [0 x i256]* %0) +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %6, [0 x i256]* %0) //CHECK-NEXT: %7 = bitcast [3 x i256]* %lvars to [0 x i256]* -//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %7, [0 x i256]* %0) +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %7, [0 x i256]* %0) //CHECK-NEXT: %8 = bitcast [3 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %8, [0 x i256]* %0) //CHECK-NEXT: %9 = bitcast [3 x i256]* %lvars to [0 x i256]* diff --git a/circom/tests/loops/inner_conditional_10.circom b/circom/tests/loops/inner_conditional_10.circom index 066ad245c..ddc93e38e 100644 --- a/circom/tests/loops/inner_conditional_10.circom +++ b/circom/tests/loops/inner_conditional_10.circom @@ -12,6 +12,9 @@ template Poseidon() { component sigmaF[2]; + // NOTE: When processing the loop, the statements indexed with 'k' are determined + // NOT safe to move into a new function since 'k' is unknown. That results in + // the loop unrolling in place. for (var i=0; i<4; i++) { if (i < 1 || i >= 3) { var k = i < 1 ? 0 : 1; diff --git a/circom/tests/loops/inner_conditional_11.circom b/circom/tests/loops/inner_conditional_11.circom new file mode 100644 index 000000000..a18a080ee --- /dev/null +++ b/circom/tests/loops/inner_conditional_11.circom @@ -0,0 +1,142 @@ +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 --enable-var-scope + +template Sigma() { + signal input inp; + signal output out; +} + +// Equivalent to inner_conditional_10 but refactored to allow the loop body to be extracted to a new function. +template Poseidon() { + signal input inp; + + component sigmaF[2]; + + for (var i=0; i<4; i++) { + if (i < 1) { + sigmaF[0] = Sigma(); + sigmaF[0].inp <== inp; + } else if (i >= 3) { + sigmaF[1] = Sigma(); + sigmaF[1].inp <== inp; + } + } +} + +component main = Poseidon(); + +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.F\.F}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+\.F\.F]]: +//CHECK-NEXT: br label %fold_false1 +//CHECK-EMPTY: +//CHECK-NEXT: fold_false1: +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %0 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: %1 = load i256, i256* %0, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %1, i256 1) +//CHECK-NEXT: %2 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: store i256 %call.fr_add, i256* %2, align 4 +//CHECK-NEXT: br label %return3 +//CHECK-EMPTY: +//CHECK-NEXT: return3: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.F\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_2:[0-9]+\.F\.T]]: +//CHECK-NEXT: br label %fold_false1 +//CHECK-EMPTY: +//CHECK-NEXT: fold_false1: +//CHECK-NEXT: %0 = getelementptr [0 x i256], [0 x i256]* %signals, i32 0, i32 0 +//CHECK-NEXT: %1 = load i256, i256* %0, align 4 +//CHECK-NEXT: %2 = getelementptr i256, i256* %fix_[[X2]], i32 0 +//CHECK-NEXT: store i256 %1, i256* %2, align 4 +//CHECK-NEXT: %3 = load i256, i256* %2, align 4 +//CHECK-NEXT: %constraint = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %1, i256 %3, i1* %constraint) +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %4 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: %5 = load i256, i256* %4, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %5, i256 1) +//CHECK-NEXT: %6 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: store i256 %call.fr_add, i256* %6, align 4 +//CHECK-NEXT: br label %return3 +//CHECK-EMPTY: +//CHECK-NEXT: return3: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_3:[0-9]+\.T]]: +//CHECK-NEXT: br label %fold_true1 +//CHECK-EMPTY: +//CHECK-NEXT: fold_true1: +//CHECK-NEXT: %0 = getelementptr [0 x i256], [0 x i256]* %signals, i32 0, i32 0 +//CHECK-NEXT: %1 = load i256, i256* %0, align 4 +//CHECK-NEXT: %2 = getelementptr i256, i256* %fix_[[X1]], i32 0 +//CHECK-NEXT: store i256 %1, i256* %2, align 4 +//CHECK-NEXT: %3 = load i256, i256* %2, align 4 +//CHECK-NEXT: %constraint = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %1, i256 %3, i1* %constraint) +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %4 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: %5 = load i256, i256* %4, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %5, i256 1) +//CHECK-NEXT: %6 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: store i256 %call.fr_add, i256* %6, align 4 +//CHECK-NEXT: br label %return3 +//CHECK-EMPTY: +//CHECK-NEXT: return3: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @Poseidon_1_run([0 x i256]* %0){{.*}} { +//CHECK-NEXT: prelude: +//CHECK-NEXT: %lvars = alloca [1 x i256], align 8 +//CHECK-NEXT: %subcmps = alloca [2 x { [0 x i256]*, i32 }], align 8 +//CHECK-NEXT: br label %create_cmp1 +//CHECK-EMPTY: +//CHECK-NEXT: create_cmp1: +//CHECK-NEXT: %1 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0 +//CHECK-NEXT: call void @Sigma_0_build({ [0 x i256]*, i32 }* %1) +//CHECK-NEXT: %2 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1 +//CHECK-NEXT: call void @Sigma_0_build({ [0 x i256]*, i32 }* %2) +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %3 = getelementptr [1 x i256], [1 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: store i256 0, i256* %3, align 4 +//CHECK-NEXT: br label %unrolled_loop3 +//CHECK-EMPTY: +//CHECK-NEXT: unrolled_loop3: +//CHECK-NEXT: %4 = bitcast [1 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %5 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %6 = load [0 x i256]*, [0 x i256]** %5, align 8 +//CHECK-NEXT: %7 = getelementptr [0 x i256], [0 x i256]* %6, i32 0 +//CHECK-NEXT: %8 = getelementptr [0 x i256], [0 x i256]* %7, i32 0, i256 1 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_3]]([0 x i256]* %4, [0 x i256]* %0, i256* %8, i256* null) +//CHECK-NEXT: %9 = bitcast [1 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %9, [0 x i256]* %0, i256* null, i256* null) +//CHECK-NEXT: %10 = bitcast [1 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %10, [0 x i256]* %0, i256* null, i256* null) +//CHECK-NEXT: %11 = bitcast [1 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %12 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 0 +//CHECK-NEXT: %13 = load [0 x i256]*, [0 x i256]** %12, align 8 +//CHECK-NEXT: %14 = getelementptr [0 x i256], [0 x i256]* %13, i32 0 +//CHECK-NEXT: %15 = getelementptr [0 x i256], [0 x i256]* %14, i32 0, i256 1 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %11, [0 x i256]* %0, i256* null, i256* %15) +//CHECK-NEXT: br label %prologue +//CHECK-EMPTY: +//CHECK-NEXT: prologue: +//CHECK-NEXT: ret void +//CHECK-NEXT: } diff --git a/circom/tests/loops/inner_conditional_4.circom b/circom/tests/loops/inner_conditional_4.circom index 54f13c096..7480fd5e1 100644 --- a/circom/tests/loops/inner_conditional_4.circom +++ b/circom/tests/loops/inner_conditional_4.circom @@ -18,44 +18,52 @@ template InnerConditional4(N) { component main = InnerConditional4(6); -//CHECK-LABEL: define void @..generated..loop.body. -//CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1]]: -//CHECK-NEXT: br label %branch1 +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}.F([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+\.F]]: +//CHECK-NEXT: br label %fold_false1 //CHECK-EMPTY: -//CHECK-NEXT: branch1: -//CHECK-NEXT: %0 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: fold_false1: +//CHECK-NEXT: %0 = getelementptr [0 x i256], [0 x i256]* %signals, i32 0, i32 6 //CHECK-NEXT: %1 = load i256, i256* %0, align 4 -//CHECK-NEXT: %call.fr_lt = call i1 @fr_lt(i256 %1, i256 3) -//CHECK-NEXT: br i1 %call.fr_lt, label %if.then, label %if.else +//CHECK-NEXT: %2 = getelementptr i256, i256* %fix_[[X2]], i32 0 +//CHECK-NEXT: store i256 %1, i256* %2, align 4 +//CHECK-NEXT: br label %store2 //CHECK-EMPTY: -//CHECK-NEXT: if.then: -//CHECK-NEXT: %2 = getelementptr [0 x i256], [0 x i256]* %signals, i32 0, i32 6 -//CHECK-NEXT: %3 = load i256, i256* %2, align 4 -//CHECK-NEXT: %call.fr_neg = call i256 @fr_neg(i256 %3) -//CHECK-NEXT: %4 = getelementptr i256, i256* %fix_[[X1]], i32 0 -//CHECK-NEXT: store i256 %call.fr_neg, i256* %4, align 4 -//CHECK-NEXT: br label %if.merge +//CHECK-NEXT: store2: +//CHECK-NEXT: %3 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: %4 = load i256, i256* %3, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %4, i256 1) +//CHECK-NEXT: %5 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 %call.fr_add, i256* %5, align 4 +//CHECK-NEXT: br label %return3 //CHECK-EMPTY: -//CHECK-NEXT: if.else: -//CHECK-NEXT: %5 = getelementptr [0 x i256], [0 x i256]* %signals, i32 0, i32 6 -//CHECK-NEXT: %6 = load i256, i256* %5, align 4 -//CHECK-NEXT: %7 = getelementptr i256, i256* %fix_[[X2]], i32 0 -//CHECK-NEXT: store i256 %6, i256* %7, align 4 -//CHECK-NEXT: br label %if.merge +//CHECK-NEXT: return3: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}.T([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_2:[0-9]+\.T]]: +//CHECK-NEXT: br label %fold_true1 //CHECK-EMPTY: -//CHECK-NEXT: if.merge: -//CHECK-NEXT: br label %store5 +//CHECK-NEXT: fold_true1: +//CHECK-NEXT: %0 = getelementptr [0 x i256], [0 x i256]* %signals, i32 0, i32 6 +//CHECK-NEXT: %1 = load i256, i256* %0, align 4 +//CHECK-NEXT: %call.fr_neg = call i256 @fr_neg(i256 %1) +//CHECK-NEXT: %2 = getelementptr i256, i256* %fix_[[X1]], i32 0 +//CHECK-NEXT: store i256 %call.fr_neg, i256* %2, align 4 +//CHECK-NEXT: br label %store2 //CHECK-EMPTY: -//CHECK-NEXT: store5: -//CHECK-NEXT: %8 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 -//CHECK-NEXT: %9 = load i256, i256* %8, align 4 -//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %9, i256 1) -//CHECK-NEXT: %10 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 -//CHECK-NEXT: store i256 %call.fr_add, i256* %10, align 4 -//CHECK-NEXT: br label %return6 +//CHECK-NEXT: store2: +//CHECK-NEXT: %3 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: %4 = load i256, i256* %3, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %4, i256 1) +//CHECK-NEXT: %5 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 %call.fr_add, i256* %5, align 4 +//CHECK-NEXT: br label %return3 //CHECK-EMPTY: -//CHECK-NEXT: return6: +//CHECK-NEXT: return3: //CHECK-NEXT: ret void //CHECK-NEXT: } // @@ -78,13 +86,13 @@ component main = InnerConditional4(6); //CHECK-NEXT: unrolled_loop3: //CHECK-NEXT: %3 = bitcast [2 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %4 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 0 -//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %3, [0 x i256]* %0, i256* %4, i256* null) +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %3, [0 x i256]* %0, i256* %4, i256* null) //CHECK-NEXT: %5 = bitcast [2 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %6 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 1 -//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %5, [0 x i256]* %0, i256* %6, i256* null) +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %5, [0 x i256]* %0, i256* %6, i256* null) //CHECK-NEXT: %7 = bitcast [2 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %8 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 2 -//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %7, [0 x i256]* %0, i256* %8, i256* null) +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %7, [0 x i256]* %0, i256* %8, i256* null) //CHECK-NEXT: %9 = bitcast [2 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %10 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 3 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %9, [0 x i256]* %0, i256* null, i256* %10) diff --git a/circom/tests/loops/inner_conditional_7.circom b/circom/tests/loops/inner_conditional_7.circom index 2ce359d33..43683a341 100644 --- a/circom/tests/loops/inner_conditional_7.circom +++ b/circom/tests/loops/inner_conditional_7.circom @@ -28,140 +28,75 @@ template InnerConditional7(N) { component main = InnerConditional7(3); -//CHECK-LABEL: define void @..generated..loop.body. -//CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1]]: -//CHECK-NEXT: br label %branch1 +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}.F([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+\.F]]: +//CHECK-NEXT: br label %fold_false1 //CHECK-EMPTY: -//CHECK-NEXT: branch1: -//CHECK-NEXT: %0 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: fold_false1: +//CHECK-NEXT: %0 = getelementptr i256, i256* %fix_[[X2]], i32 0 //CHECK-NEXT: %1 = load i256, i256* %0, align 4 -//CHECK-NEXT: %call.fr_gt = call i1 @fr_gt(i256 %1, i256 1) -//CHECK-NEXT: br i1 %call.fr_gt, label %if.then, label %if.else -//CHECK-EMPTY: -//CHECK-NEXT: if.then: -//CHECK-NEXT: %2 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 -//CHECK-NEXT: %3 = load i256, i256* %2, align 4 -//CHECK-NEXT: %call.fr_cast_to_addr = call i32 @fr_cast_to_addr(i256 %3) -//CHECK-NEXT: %mul_addr = mul i32 1, %call.fr_cast_to_addr -//CHECK-NEXT: %add_addr = add i32 %mul_addr, 1 -//CHECK-NEXT: %4 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 %add_addr -//CHECK-NEXT: store i256 777, i256* %4, align 4 -//CHECK-NEXT: br label %if.merge -//CHECK-EMPTY: -//CHECK-NEXT: if.else: -//CHECK-NEXT: %5 = getelementptr i256, i256* %fix_[[X2]], i32 0 -//CHECK-NEXT: %6 = load i256, i256* %5, align 4 -//CHECK-NEXT: %call.fr_sub = call i256 @fr_sub(i256 %6, i256 111) -//CHECK-NEXT: %7 = getelementptr i256, i256* %fix_[[X1]], i32 0 -//CHECK-NEXT: store i256 %call.fr_sub, i256* %7, align 4 -//CHECK-NEXT: br label %if.merge -//CHECK-EMPTY: -//CHECK-NEXT: if.merge: -//CHECK-NEXT: br label %store5 -//CHECK-EMPTY: -//CHECK-NEXT: store5: -//CHECK-NEXT: %8 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 -//CHECK-NEXT: %9 = load i256, i256* %8, align 4 -//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %9, i256 1) -//CHECK-NEXT: %10 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 -//CHECK-NEXT: store i256 %call.fr_add, i256* %10, align 4 -//CHECK-NEXT: br label %return6 -//CHECK-EMPTY: -//CHECK-NEXT: return6: -//CHECK-NEXT: ret void -//CHECK-NEXT: } -// -//CHECK-LABEL: define void @..generated..loop.body. -//CHECK-SAME: [[$F_ID_2:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_2]]: -//CHECK-NEXT: br label %branch1 -//CHECK-EMPTY: -//CHECK-NEXT: branch1: -//CHECK-NEXT: %0 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 4 -//CHECK-NEXT: %1 = load i256, i256* %0, align 4 -//CHECK-NEXT: %call.fr_gt = call i1 @fr_gt(i256 %1, i256 1) -//CHECK-NEXT: br i1 %call.fr_gt, label %if.then, label %if.else -//CHECK-EMPTY: -//CHECK-NEXT: if.then: -//CHECK-NEXT: %2 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 -//CHECK-NEXT: %3 = load i256, i256* %2, align 4 -//CHECK-NEXT: %call.fr_cast_to_addr = call i32 @fr_cast_to_addr(i256 %3) -//CHECK-NEXT: %mul_addr = mul i32 1, %call.fr_cast_to_addr -//CHECK-NEXT: %add_addr = add i32 %mul_addr, 1 -//CHECK-NEXT: %4 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 %add_addr -//CHECK-NEXT: store i256 777, i256* %4, align 4 -//CHECK-NEXT: br label %if.merge -//CHECK-EMPTY: -//CHECK-NEXT: if.else: -//CHECK-NEXT: %5 = getelementptr i256, i256* %fix_[[X2]], i32 0 -//CHECK-NEXT: %6 = load i256, i256* %5, align 4 -//CHECK-NEXT: %call.fr_sub = call i256 @fr_sub(i256 %6, i256 111) -//CHECK-NEXT: %7 = getelementptr i256, i256* %fix_[[X1]], i32 0 -//CHECK-NEXT: store i256 %call.fr_sub, i256* %7, align 4 -//CHECK-NEXT: br label %if.merge -//CHECK-EMPTY: -//CHECK-NEXT: if.merge: -//CHECK-NEXT: br label %store5 +//CHECK-NEXT: %call.fr_sub = call i256 @fr_sub(i256 %1, i256 111) +//CHECK-NEXT: %2 = getelementptr i256, i256* %fix_[[X1]], i32 0 +//CHECK-NEXT: store i256 %call.fr_sub, i256* %2, align 4 +//CHECK-NEXT: br label %store2 //CHECK-EMPTY: -//CHECK-NEXT: store5: -//CHECK-NEXT: %8 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 -//CHECK-NEXT: %9 = load i256, i256* %8, align 4 -//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %9, i256 1) -//CHECK-NEXT: %10 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 -//CHECK-NEXT: store i256 %call.fr_add, i256* %10, align 4 -//CHECK-NEXT: br label %return6 +//CHECK-NEXT: store2: +//CHECK-NEXT: %3 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 +//CHECK-NEXT: %4 = load i256, i256* %3, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %4, i256 1) +//CHECK-NEXT: %5 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 +//CHECK-NEXT: store i256 %call.fr_add, i256* %5, align 4 +//CHECK-NEXT: br label %return3 //CHECK-EMPTY: -//CHECK-NEXT: return6: +//CHECK-NEXT: return3: //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body. -//CHECK-SAME: [[$F_ID_3:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_[[X1:[0-9]+]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_3]]: -//CHECK-NEXT: br label %branch1 +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}.F([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_2:[0-9]+\.F]]: +//CHECK-NEXT: br label %fold_false1 //CHECK-EMPTY: -//CHECK-NEXT: branch1: -//CHECK-NEXT: %0 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: fold_false1: +//CHECK-NEXT: %0 = getelementptr i256, i256* %fix_[[X2]], i32 0 //CHECK-NEXT: %1 = load i256, i256* %0, align 4 -//CHECK-NEXT: %call.fr_gt = call i1 @fr_gt(i256 %1, i256 1) -//CHECK-NEXT: br i1 %call.fr_gt, label %if.then, label %if.else -//CHECK-EMPTY: -//CHECK-NEXT: if.then: +//CHECK-NEXT: %call.fr_sub = call i256 @fr_sub(i256 %1, i256 111) //CHECK-NEXT: %2 = getelementptr i256, i256* %fix_[[X1]], i32 0 -//CHECK-NEXT: store i256 777, i256* %2, align 4 -//CHECK-NEXT: br label %if.merge +//CHECK-NEXT: store i256 %call.fr_sub, i256* %2, align 4 +//CHECK-NEXT: br label %store2 //CHECK-EMPTY: -//CHECK-NEXT: if.else: +//CHECK-NEXT: store2: //CHECK-NEXT: %3 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 //CHECK-NEXT: %4 = load i256, i256* %3, align 4 -//CHECK-NEXT: %call.fr_cast_to_addr = call i32 @fr_cast_to_addr(i256 %4) -//CHECK-NEXT: %mul_addr = mul i32 1, %call.fr_cast_to_addr -//CHECK-NEXT: %add_addr = add i32 %mul_addr, 1 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %4, i256 1) //CHECK-NEXT: %5 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 -//CHECK-NEXT: %6 = load i256, i256* %5, align 4 -//CHECK-NEXT: %call.fr_cast_to_addr1 = call i32 @fr_cast_to_addr(i256 %6) -//CHECK-NEXT: %mul_addr2 = mul i32 1, %call.fr_cast_to_addr1 -//CHECK-NEXT: %add_addr3 = add i32 %mul_addr2, 1 -//CHECK-NEXT: %7 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 %add_addr3 -//CHECK-NEXT: %8 = load i256, i256* %7, align 4 -//CHECK-NEXT: %call.fr_sub = call i256 @fr_sub(i256 %8, i256 111) -//CHECK-NEXT: %9 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 %add_addr -//CHECK-NEXT: store i256 %call.fr_sub, i256* %9, align 4 -//CHECK-NEXT: br label %if.merge +//CHECK-NEXT: store i256 %call.fr_add, i256* %5, align 4 +//CHECK-NEXT: br label %return3 //CHECK-EMPTY: -//CHECK-NEXT: if.merge: -//CHECK-NEXT: br label %store5 +//CHECK-NEXT: return3: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}.T([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_3:[0-9]+\.T]]: +//CHECK-NEXT: br label %fold_true1 +//CHECK-EMPTY: +//CHECK-NEXT: fold_true1: +//CHECK-NEXT: %0 = getelementptr i256, i256* %fix_[[X1]], i32 0 +//CHECK-NEXT: store i256 777, i256* %0, align 4 +//CHECK-NEXT: br label %store2 //CHECK-EMPTY: -//CHECK-NEXT: store5: -//CHECK-NEXT: %10 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 -//CHECK-NEXT: %11 = load i256, i256* %10, align 4 -//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %11, i256 1) -//CHECK-NEXT: %12 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 -//CHECK-NEXT: store i256 %call.fr_add, i256* %12, align 4 -//CHECK-NEXT: br label %return6 +//CHECK-NEXT: store2: +//CHECK-NEXT: %1 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 +//CHECK-NEXT: %2 = load i256, i256* %1, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %2, i256 1) +//CHECK-NEXT: %3 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 +//CHECK-NEXT: store i256 %call.fr_add, i256* %3, align 4 +//CHECK-NEXT: br label %return3 //CHECK-EMPTY: -//CHECK-NEXT: return6: +//CHECK-NEXT: return3: //CHECK-NEXT: ret void //CHECK-NEXT: } // diff --git a/circom/tests/loops/inner_conditional_9.circom b/circom/tests/loops/inner_conditional_9.circom index 345e26d0c..0c630d167 100644 --- a/circom/tests/loops/inner_conditional_9.circom +++ b/circom/tests/loops/inner_conditional_9.circom @@ -25,83 +25,91 @@ template InnerConditional9(N) { component main = InnerConditional9(4); -//CHECK-LABEL: define void @..generated..loop.body. -//CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]], i256* %fix_[[X4:[0-9]+]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1]]: -//CHECK-NEXT: br label %branch1 -//CHECK-EMPTY: -//CHECK-NEXT: branch1: -//CHECK-NEXT: %0 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 -//CHECK-NEXT: %1 = load i256, i256* %0, align 4 -//CHECK-NEXT: %call.fr_gt = call i1 @fr_gt(i256 %1, i256 1) -//CHECK-NEXT: br i1 %call.fr_gt, label %if.then, label %if.else -//CHECK-EMPTY: -//CHECK-NEXT: if.then: -//CHECK-NEXT: %2 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 6 -//CHECK-NEXT: store i256 0, i256* %2, align 4 +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}.F([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]], i256* %fix_[[X4:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+\.F]]: +//CHECK-NEXT: br label %fold_false1 +//CHECK-EMPTY: +//CHECK-NEXT: fold_false1: +//CHECK-NEXT: %0 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 6 +//CHECK-NEXT: store i256 0, i256* %0, align 4 //CHECK-NEXT: br label %loop.cond //CHECK-EMPTY: -//CHECK-NEXT: if.else: -//CHECK-NEXT: %3 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 6 -//CHECK-NEXT: store i256 0, i256* %3, align 4 -//CHECK-NEXT: br label %loop.cond2 -//CHECK-EMPTY: -//CHECK-NEXT: if.merge: -//CHECK-NEXT: br label %store11 -//CHECK-EMPTY: //CHECK-NEXT: loop.cond: -//CHECK-NEXT: %4 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 6 -//CHECK-NEXT: %5 = load i256, i256* %4, align 4 -//CHECK-NEXT: %call.fr_lt = call i1 @fr_lt(i256 %5, i256 4) +//CHECK-NEXT: %1 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 6 +//CHECK-NEXT: %2 = load i256, i256* %1, align 4 +//CHECK-NEXT: %call.fr_lt = call i1 @fr_lt(i256 %2, i256 4) //CHECK-NEXT: br i1 %call.fr_lt, label %loop.body, label %loop.end //CHECK-EMPTY: //CHECK-NEXT: loop.body: -//CHECK-NEXT: %6 = getelementptr i256, i256* %fix_[[X4]], i32 0 +//CHECK-NEXT: %3 = getelementptr i256, i256* %fix_[[X2]], i32 0 +//CHECK-NEXT: %4 = load i256, i256* %3, align 4 +//CHECK-NEXT: %call.fr_sub = call i256 @fr_sub(i256 %4, i256 999) +//CHECK-NEXT: %5 = getelementptr i256, i256* %fix_[[X1]], i32 0 +//CHECK-NEXT: store i256 %call.fr_sub, i256* %5, align 4 +//CHECK-NEXT: %6 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 6 //CHECK-NEXT: %7 = load i256, i256* %6, align 4 -//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %7, i256 999) -//CHECK-NEXT: %8 = getelementptr i256, i256* %fix_[[X3]], i32 0 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %7, i256 1) +//CHECK-NEXT: %8 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 6 //CHECK-NEXT: store i256 %call.fr_add, i256* %8, align 4 -//CHECK-NEXT: %9 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 6 +//CHECK-NEXT: br label %loop.cond +//CHECK-EMPTY: +//CHECK-NEXT: loop.end: +//CHECK-NEXT: br label %store5 +//CHECK-EMPTY: +//CHECK-NEXT: store5: +//CHECK-NEXT: %9 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 //CHECK-NEXT: %10 = load i256, i256* %9, align 4 //CHECK-NEXT: %call.fr_add1 = call i256 @fr_add(i256 %10, i256 1) -//CHECK-NEXT: %11 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 6 +//CHECK-NEXT: %11 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 //CHECK-NEXT: store i256 %call.fr_add1, i256* %11, align 4 +//CHECK-NEXT: br label %return6 +//CHECK-EMPTY: +//CHECK-NEXT: return6: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}.T([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]], i256* %fix_[[X4:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_2:[0-9]+\.T]]: +//CHECK-NEXT: br label %fold_true1 +//CHECK-EMPTY: +//CHECK-NEXT: fold_true1: +//CHECK-NEXT: %0 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 6 +//CHECK-NEXT: store i256 0, i256* %0, align 4 +//CHECK-NEXT: br label %loop.cond +//CHECK-EMPTY: +//CHECK-NEXT: loop.cond: +//CHECK-NEXT: %1 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 6 +//CHECK-NEXT: %2 = load i256, i256* %1, align 4 +//CHECK-NEXT: %call.fr_lt = call i1 @fr_lt(i256 %2, i256 4) +//CHECK-NEXT: br i1 %call.fr_lt, label %loop.body, label %loop.end +//CHECK-EMPTY: +//CHECK-NEXT: loop.body: +//CHECK-NEXT: %3 = getelementptr i256, i256* %fix_[[X4]], i32 0 +//CHECK-NEXT: %4 = load i256, i256* %3, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %4, i256 999) +//CHECK-NEXT: %5 = getelementptr i256, i256* %fix_[[X3]], i32 0 +//CHECK-NEXT: store i256 %call.fr_add, i256* %5, align 4 +//CHECK-NEXT: %6 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 6 +//CHECK-NEXT: %7 = load i256, i256* %6, align 4 +//CHECK-NEXT: %call.fr_add1 = call i256 @fr_add(i256 %7, i256 1) +//CHECK-NEXT: %8 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 6 +//CHECK-NEXT: store i256 %call.fr_add1, i256* %8, align 4 //CHECK-NEXT: br label %loop.cond //CHECK-EMPTY: //CHECK-NEXT: loop.end: -//CHECK-NEXT: br label %if.merge -//CHECK-EMPTY: -//CHECK-NEXT: loop.cond2: -//CHECK-NEXT: %12 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 6 -//CHECK-NEXT: %13 = load i256, i256* %12, align 4 -//CHECK-NEXT: %call.fr_lt5 = call i1 @fr_lt(i256 %13, i256 4) -//CHECK-NEXT: br i1 %call.fr_lt5, label %loop.body3, label %loop.end4 -//CHECK-EMPTY: -//CHECK-NEXT: loop.body3: -//CHECK-NEXT: %14 = getelementptr i256, i256* %fix_[[X2]], i32 0 -//CHECK-NEXT: %15 = load i256, i256* %14, align 4 -//CHECK-NEXT: %call.fr_sub = call i256 @fr_sub(i256 %15, i256 999) -//CHECK-NEXT: %16 = getelementptr i256, i256* %fix_[[X1]], i32 0 -//CHECK-NEXT: store i256 %call.fr_sub, i256* %16, align 4 -//CHECK-NEXT: %17 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 6 -//CHECK-NEXT: %18 = load i256, i256* %17, align 4 -//CHECK-NEXT: %call.fr_add6 = call i256 @fr_add(i256 %18, i256 1) -//CHECK-NEXT: %19 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 6 -//CHECK-NEXT: store i256 %call.fr_add6, i256* %19, align 4 -//CHECK-NEXT: br label %loop.cond2 -//CHECK-EMPTY: -//CHECK-NEXT: loop.end4: -//CHECK-NEXT: br label %if.merge -//CHECK-EMPTY: -//CHECK-NEXT: store11: -//CHECK-NEXT: %20 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 -//CHECK-NEXT: %21 = load i256, i256* %20, align 4 -//CHECK-NEXT: %call.fr_add7 = call i256 @fr_add(i256 %21, i256 1) -//CHECK-NEXT: %22 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 -//CHECK-NEXT: store i256 %call.fr_add7, i256* %22, align 4 -//CHECK-NEXT: br label %return12 -//CHECK-EMPTY: -//CHECK-NEXT: return12: +//CHECK-NEXT: br label %store5 +//CHECK-EMPTY: +//CHECK-NEXT: store5: +//CHECK-NEXT: %9 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 +//CHECK-NEXT: %10 = load i256, i256* %9, align 4 +//CHECK-NEXT: %call.fr_add2 = call i256 @fr_add(i256 %10, i256 1) +//CHECK-NEXT: %11 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 +//CHECK-NEXT: store i256 %call.fr_add2, i256* %11, align 4 +//CHECK-NEXT: br label %return6 +//CHECK-EMPTY: +//CHECK-NEXT: return6: //CHECK-NEXT: ret void //CHECK-NEXT: } // @@ -159,13 +167,13 @@ component main = InnerConditional9(4); //CHECK-NEXT: %19 = getelementptr [0 x i256], [0 x i256]* %18, i32 0, i256 3 //CHECK-NEXT: %20 = bitcast [7 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %21 = getelementptr [0 x i256], [0 x i256]* %20, i32 0, i256 3 -//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %17, [0 x i256]* %0, i256* null, i256* null, i256* %19, i256* %21) +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %17, [0 x i256]* %0, i256* null, i256* null, i256* %19, i256* %21) //CHECK-NEXT: %22 = bitcast [7 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %23 = bitcast [7 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %24 = getelementptr [0 x i256], [0 x i256]* %23, i32 0, i256 4 //CHECK-NEXT: %25 = bitcast [7 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %26 = getelementptr [0 x i256], [0 x i256]* %25, i32 0, i256 4 -//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %22, [0 x i256]* %0, i256* null, i256* null, i256* %24, i256* %26) +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %22, [0 x i256]* %0, i256* null, i256* null, i256* %24, i256* %26) //CHECK-NEXT: br label %store8 //CHECK-EMPTY: //CHECK-NEXT: store8: diff --git a/circom/tests/subcmps/conv_map2idx_A.circom b/circom/tests/subcmps/conv_map2idx_A.circom index 4ae5fc574..a3c2e43d0 100644 --- a/circom/tests/subcmps/conv_map2idx_A.circom +++ b/circom/tests/subcmps/conv_map2idx_A.circom @@ -108,7 +108,7 @@ component main = ComputeValue(); //CHECK-NEXT: store i32 %decrement.counter, i32* %6, align 4 //CHECK-NEXT: %7 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 //CHECK-NEXT: %8 = load [0 x i256]*, [0 x i256]** %7, align 8 -//CHECK-NEXT: call void @GetWeight_1_run([0 x i256]* %8) +//CHECK-NEXT: call void @GetWeight_0_run([0 x i256]* %8) //CHECK-NEXT: br label %store4 //CHECK-EMPTY: //CHECK-NEXT: store4: diff --git a/circom/tests/subcmps/mapped.circom b/circom/tests/subcmps/mapped.circom index 69c44a397..8e16e7307 100644 --- a/circom/tests/subcmps/mapped.circom +++ b/circom/tests/subcmps/mapped.circom @@ -2,8 +2,6 @@ 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 --enable-var-scope -// XFAIL:.* -// TODO: I think it has problems related to both https://veridise.atlassian.net/browse/VAN-582 and https://veridise.atlassian.net/browse/VAN-670 template A(n) { signal input a[n]; @@ -41,3 +39,407 @@ template B(n) { } component main = B(2); + +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+]]: +//CHECK-NEXT: br label %store1 +//CHECK-EMPTY: +//CHECK-NEXT: store1: +//CHECK-NEXT: %0 = getelementptr i256, i256* %fix_[[X2]], i32 0 +//CHECK-NEXT: %1 = load i256, i256* %0, align 4 +//CHECK-NEXT: %2 = getelementptr i256, i256* %fix_[[X3]], i32 0 +//CHECK-NEXT: %3 = load i256, i256* %2, align 4 +//CHECK-NEXT: %call.fr_mul = call i256 @fr_mul(i256 %1, i256 %3) +//CHECK-NEXT: %4 = getelementptr i256, i256* %fix_[[X1]], i32 0 +//CHECK-NEXT: store i256 %call.fr_mul, i256* %4, align 4 +//CHECK-NEXT: %5 = load i256, i256* %4, align 4 +//CHECK-NEXT: %constraint = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %call.fr_mul, i256 %5, i1* %constraint) +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %6 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: %7 = load i256, i256* %6, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %7, i256 1) +//CHECK-NEXT: %8 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 %call.fr_add, i256* %8, align 4 +//CHECK-NEXT: br label %return3 +//CHECK-EMPTY: +//CHECK-NEXT: return3: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_2:[0-9]+]]: +//CHECK-NEXT: br label %store1 +//CHECK-EMPTY: +//CHECK-NEXT: store1: +//CHECK-NEXT: %0 = getelementptr i256, i256* %fix_[[X2]], i32 0 +//CHECK-NEXT: %1 = load i256, i256* %0, align 4 +//CHECK-NEXT: %2 = getelementptr i256, i256* %fix_[[X3]], i32 0 +//CHECK-NEXT: %3 = load i256, i256* %2, align 4 +//CHECK-NEXT: %call.fr_mul = call i256 @fr_mul(i256 %1, i256 %3) +//CHECK-NEXT: %4 = getelementptr i256, i256* %fix_[[X1]], i32 0 +//CHECK-NEXT: store i256 %call.fr_mul, i256* %4, align 4 +//CHECK-NEXT: %5 = load i256, i256* %4, align 4 +//CHECK-NEXT: %constraint = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %call.fr_mul, i256 %5, i1* %constraint) +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %6 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: %7 = load i256, i256* %6, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %7, i256 1) +//CHECK-NEXT: %8 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 %call.fr_add, i256* %8, align 4 +//CHECK-NEXT: br label %return3 +//CHECK-EMPTY: +//CHECK-NEXT: return3: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @A_0_run([0 x i256]* %0){{.*}} { +//CHECK-NEXT: prelude: +//CHECK-NEXT: %lvars = alloca [2 x i256], align 8 +//CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 +//CHECK-NEXT: br label %store1 +//CHECK-EMPTY: +//CHECK-NEXT: store1: +//CHECK-NEXT: %1 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: store i256 4, i256* %1, align 4 +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %2 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 0, i256* %2, align 4 +//CHECK-NEXT: br label %store3 +//CHECK-EMPTY: +//CHECK-NEXT: store3: +//CHECK-NEXT: %3 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 0, i256* %3, align 4 +//CHECK-NEXT: br label %unrolled_loop4 +//CHECK-EMPTY: +//CHECK-NEXT: unrolled_loop4: +//CHECK-NEXT: %4 = bitcast [2 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %5 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 0 +//CHECK-NEXT: %6 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 4 +//CHECK-NEXT: %7 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 8 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %4, [0 x i256]* %0, i256* %5, i256* %6, i256* %7) +//CHECK-NEXT: %8 = bitcast [2 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %9 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 1 +//CHECK-NEXT: %10 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 5 +//CHECK-NEXT: %11 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 9 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %8, [0 x i256]* %0, i256* %9, i256* %10, i256* %11) +//CHECK-NEXT: %12 = bitcast [2 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %13 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 2 +//CHECK-NEXT: %14 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 6 +//CHECK-NEXT: %15 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 10 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %12, [0 x i256]* %0, i256* %13, i256* %14, i256* %15) +//CHECK-NEXT: %16 = bitcast [2 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %17 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 3 +//CHECK-NEXT: %18 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 7 +//CHECK-NEXT: %19 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 11 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %16, [0 x i256]* %0, i256* %17, i256* %18, i256* %19) +//CHECK-NEXT: br label %prologue +//CHECK-EMPTY: +//CHECK-NEXT: prologue: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @A_1_run([0 x i256]* %0){{.*}} { +//CHECK-NEXT: prelude: +//CHECK-NEXT: %lvars = alloca [2 x i256], align 8 +//CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 +//CHECK-NEXT: br label %store1 +//CHECK-EMPTY: +//CHECK-NEXT: store1: +//CHECK-NEXT: %1 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: store i256 2, i256* %1, align 4 +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %2 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 0, i256* %2, align 4 +//CHECK-NEXT: br label %store3 +//CHECK-EMPTY: +//CHECK-NEXT: store3: +//CHECK-NEXT: %3 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 0, i256* %3, align 4 +//CHECK-NEXT: br label %unrolled_loop4 +//CHECK-EMPTY: +//CHECK-NEXT: unrolled_loop4: +//CHECK-NEXT: %4 = bitcast [2 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %5 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 0 +//CHECK-NEXT: %6 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 2 +//CHECK-NEXT: %7 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 4 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %4, [0 x i256]* %0, i256* %5, i256* %6, i256* %7) +//CHECK-NEXT: %8 = bitcast [2 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %9 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 1 +//CHECK-NEXT: %10 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 3 +//CHECK-NEXT: %11 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 5 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %8, [0 x i256]* %0, i256* %9, i256* %10, i256* %11) +//CHECK-NEXT: br label %prologue +//CHECK-EMPTY: +//CHECK-NEXT: prologue: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @B_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-NEXT: prelude: +//CHECK-NEXT: %lvars = alloca [2 x i256], align 8 +//CHECK-NEXT: %subcmps = alloca [2 x { [0 x i256]*, i32 }], align 8 +//CHECK-NEXT: br label %store1 +//CHECK-EMPTY: +//CHECK-NEXT: store1: +//CHECK-NEXT: %1 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: store i256 2, i256* %1, align 4 +//CHECK-NEXT: br label %create_cmp2 +//CHECK-EMPTY: +//CHECK-NEXT: create_cmp2: +//CHECK-NEXT: %2 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0 +//CHECK-NEXT: call void @A_0_build({ [0 x i256]*, i32 }* %2) +//CHECK-NEXT: br label %create_cmp3 +//CHECK-EMPTY: +//CHECK-NEXT: create_cmp3: +//CHECK-NEXT: %3 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1 +//CHECK-NEXT: call void @A_1_build({ [0 x i256]*, i32 }* %3) +//CHECK-NEXT: br label %store4 +//CHECK-EMPTY: +//CHECK-NEXT: store4: +//CHECK-NEXT: %4 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 0, i256* %4, align 4 +//CHECK-NEXT: br label %store5 +//CHECK-EMPTY: +//CHECK-NEXT: store5: +//CHECK-NEXT: %5 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 0, i256* %5, align 4 +//CHECK-NEXT: br label %unrolled_loop6 +//CHECK-EMPTY: +//CHECK-NEXT: unrolled_loop6: +//CHECK-NEXT: %6 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 2 +//CHECK-NEXT: %7 = load i256, i256* %6, align 4 +//CHECK-NEXT: %8 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %9 = load [0 x i256]*, [0 x i256]** %8, align 8 +//CHECK-NEXT: %10 = getelementptr [0 x i256], [0 x i256]* %9, i32 0, i32 4 +//CHECK-NEXT: store i256 %7, i256* %10, align 4 +//CHECK-NEXT: %11 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 1 +//CHECK-NEXT: %load.subcmp.counter = load i32, i32* %11, align 4 +//CHECK-NEXT: %decrement.counter = sub i32 %load.subcmp.counter, 1 +//CHECK-NEXT: store i32 %decrement.counter, i32* %11, align 4 +//CHECK-NEXT: %12 = load i256, i256* %10, align 4 +//CHECK-NEXT: %constraint = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %7, i256 %12, i1* %constraint) +//CHECK-NEXT: %13 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 6 +//CHECK-NEXT: %14 = load i256, i256* %13, align 4 +//CHECK-NEXT: %15 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %16 = load [0 x i256]*, [0 x i256]** %15, align 8 +//CHECK-NEXT: %17 = getelementptr [0 x i256], [0 x i256]* %16, i32 0, i32 8 +//CHECK-NEXT: store i256 %14, i256* %17, align 4 +//CHECK-NEXT: %18 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 1 +//CHECK-NEXT: %load.subcmp.counter1 = load i32, i32* %18, align 4 +//CHECK-NEXT: %decrement.counter2 = sub i32 %load.subcmp.counter1, 1 +//CHECK-NEXT: store i32 %decrement.counter2, i32* %18, align 4 +//CHECK-NEXT: %19 = load i256, i256* %17, align 4 +//CHECK-NEXT: %constraint3 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %14, i256 %19, i1* %constraint3) +//CHECK-NEXT: %20 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 1, i256* %20, align 4 +//CHECK-NEXT: %21 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 3 +//CHECK-NEXT: %22 = load i256, i256* %21, align 4 +//CHECK-NEXT: %23 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %24 = load [0 x i256]*, [0 x i256]** %23, align 8 +//CHECK-NEXT: %25 = getelementptr [0 x i256], [0 x i256]* %24, i32 0, i32 5 +//CHECK-NEXT: store i256 %22, i256* %25, align 4 +//CHECK-NEXT: %26 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 1 +//CHECK-NEXT: %load.subcmp.counter4 = load i32, i32* %26, align 4 +//CHECK-NEXT: %decrement.counter5 = sub i32 %load.subcmp.counter4, 1 +//CHECK-NEXT: store i32 %decrement.counter5, i32* %26, align 4 +//CHECK-NEXT: %27 = load i256, i256* %25, align 4 +//CHECK-NEXT: %constraint6 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %22, i256 %27, i1* %constraint6) +//CHECK-NEXT: %28 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 7 +//CHECK-NEXT: %29 = load i256, i256* %28, align 4 +//CHECK-NEXT: %30 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %31 = load [0 x i256]*, [0 x i256]** %30, align 8 +//CHECK-NEXT: %32 = getelementptr [0 x i256], [0 x i256]* %31, i32 0, i32 9 +//CHECK-NEXT: store i256 %29, i256* %32, align 4 +//CHECK-NEXT: %33 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 1 +//CHECK-NEXT: %load.subcmp.counter7 = load i32, i32* %33, align 4 +//CHECK-NEXT: %decrement.counter8 = sub i32 %load.subcmp.counter7, 1 +//CHECK-NEXT: store i32 %decrement.counter8, i32* %33, align 4 +//CHECK-NEXT: %34 = load i256, i256* %32, align 4 +//CHECK-NEXT: %constraint9 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %29, i256 %34, i1* %constraint9) +//CHECK-NEXT: %35 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 2, i256* %35, align 4 +//CHECK-NEXT: %36 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 4 +//CHECK-NEXT: %37 = load i256, i256* %36, align 4 +//CHECK-NEXT: %38 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %39 = load [0 x i256]*, [0 x i256]** %38, align 8 +//CHECK-NEXT: %40 = getelementptr [0 x i256], [0 x i256]* %39, i32 0, i32 6 +//CHECK-NEXT: store i256 %37, i256* %40, align 4 +//CHECK-NEXT: %41 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 1 +//CHECK-NEXT: %load.subcmp.counter10 = load i32, i32* %41, align 4 +//CHECK-NEXT: %decrement.counter11 = sub i32 %load.subcmp.counter10, 1 +//CHECK-NEXT: store i32 %decrement.counter11, i32* %41, align 4 +//CHECK-NEXT: %42 = load i256, i256* %40, align 4 +//CHECK-NEXT: %constraint12 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %37, i256 %42, i1* %constraint12) +//CHECK-NEXT: %43 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 8 +//CHECK-NEXT: %44 = load i256, i256* %43, align 4 +//CHECK-NEXT: %45 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %46 = load [0 x i256]*, [0 x i256]** %45, align 8 +//CHECK-NEXT: %47 = getelementptr [0 x i256], [0 x i256]* %46, i32 0, i32 10 +//CHECK-NEXT: store i256 %44, i256* %47, align 4 +//CHECK-NEXT: %48 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 1 +//CHECK-NEXT: %load.subcmp.counter13 = load i32, i32* %48, align 4 +//CHECK-NEXT: %decrement.counter14 = sub i32 %load.subcmp.counter13, 1 +//CHECK-NEXT: store i32 %decrement.counter14, i32* %48, align 4 +//CHECK-NEXT: %49 = load i256, i256* %47, align 4 +//CHECK-NEXT: %constraint15 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %44, i256 %49, i1* %constraint15) +//CHECK-NEXT: %50 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 3, i256* %50, align 4 +//CHECK-NEXT: %51 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 5 +//CHECK-NEXT: %52 = load i256, i256* %51, align 4 +//CHECK-NEXT: %53 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %54 = load [0 x i256]*, [0 x i256]** %53, align 8 +//CHECK-NEXT: %55 = getelementptr [0 x i256], [0 x i256]* %54, i32 0, i32 7 +//CHECK-NEXT: store i256 %52, i256* %55, align 4 +//CHECK-NEXT: %56 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 1 +//CHECK-NEXT: %load.subcmp.counter16 = load i32, i32* %56, align 4 +//CHECK-NEXT: %decrement.counter17 = sub i32 %load.subcmp.counter16, 1 +//CHECK-NEXT: store i32 %decrement.counter17, i32* %56, align 4 +//CHECK-NEXT: %57 = load i256, i256* %55, align 4 +//CHECK-NEXT: %constraint18 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %52, i256 %57, i1* %constraint18) +//CHECK-NEXT: %58 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 9 +//CHECK-NEXT: %59 = load i256, i256* %58, align 4 +//CHECK-NEXT: %60 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %61 = load [0 x i256]*, [0 x i256]** %60, align 8 +//CHECK-NEXT: %62 = getelementptr [0 x i256], [0 x i256]* %61, i32 0, i32 11 +//CHECK-NEXT: store i256 %59, i256* %62, align 4 +//CHECK-NEXT: %63 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 1 +//CHECK-NEXT: %load.subcmp.counter19 = load i32, i32* %63, align 4 +//CHECK-NEXT: %decrement.counter20 = sub i32 %load.subcmp.counter19, 1 +//CHECK-NEXT: store i32 %decrement.counter20, i32* %63, align 4 +//CHECK-NEXT: %64 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %65 = load [0 x i256]*, [0 x i256]** %64, align 8 +//CHECK-NEXT: call void @A_0_run([0 x i256]* %65) +//CHECK-NEXT: %66 = load i256, i256* %62, align 4 +//CHECK-NEXT: %constraint21 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %59, i256 %66, i1* %constraint21) +//CHECK-NEXT: %67 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 4, i256* %67, align 4 +//CHECK-NEXT: br label %store7 +//CHECK-EMPTY: +//CHECK-NEXT: store7: +//CHECK-NEXT: %68 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 0, i256* %68, align 4 +//CHECK-NEXT: br label %unrolled_loop8 +//CHECK-EMPTY: +//CHECK-NEXT: unrolled_loop8: +//CHECK-NEXT: %69 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %70 = load [0 x i256]*, [0 x i256]** %69, align 8 +//CHECK-NEXT: %71 = getelementptr [0 x i256], [0 x i256]* %70, i32 0, i32 0 +//CHECK-NEXT: %72 = load i256, i256* %71, align 4 +//CHECK-NEXT: %73 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 0 +//CHECK-NEXT: %74 = load [0 x i256]*, [0 x i256]** %73, align 8 +//CHECK-NEXT: %75 = getelementptr [0 x i256], [0 x i256]* %74, i32 0, i32 2 +//CHECK-NEXT: store i256 %72, i256* %75, align 4 +//CHECK-NEXT: %76 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 1 +//CHECK-NEXT: %load.subcmp.counter22 = load i32, i32* %76, align 4 +//CHECK-NEXT: %decrement.counter23 = sub i32 %load.subcmp.counter22, 1 +//CHECK-NEXT: store i32 %decrement.counter23, i32* %76, align 4 +//CHECK-NEXT: %77 = load i256, i256* %75, align 4 +//CHECK-NEXT: %constraint24 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %72, i256 %77, i1* %constraint24) +//CHECK-NEXT: %78 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %79 = load [0 x i256]*, [0 x i256]** %78, align 8 +//CHECK-NEXT: %80 = getelementptr [0 x i256], [0 x i256]* %79, i32 0, i32 2 +//CHECK-NEXT: %81 = load i256, i256* %80, align 4 +//CHECK-NEXT: %82 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 0 +//CHECK-NEXT: %83 = load [0 x i256]*, [0 x i256]** %82, align 8 +//CHECK-NEXT: %84 = getelementptr [0 x i256], [0 x i256]* %83, i32 0, i32 4 +//CHECK-NEXT: store i256 %81, i256* %84, align 4 +//CHECK-NEXT: %85 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 1 +//CHECK-NEXT: %load.subcmp.counter25 = load i32, i32* %85, align 4 +//CHECK-NEXT: %decrement.counter26 = sub i32 %load.subcmp.counter25, 1 +//CHECK-NEXT: store i32 %decrement.counter26, i32* %85, align 4 +//CHECK-NEXT: %86 = load i256, i256* %84, align 4 +//CHECK-NEXT: %constraint27 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %81, i256 %86, i1* %constraint27) +//CHECK-NEXT: %87 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 1, i256* %87, align 4 +//CHECK-NEXT: %88 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %89 = load [0 x i256]*, [0 x i256]** %88, align 8 +//CHECK-NEXT: %90 = getelementptr [0 x i256], [0 x i256]* %89, i32 0, i32 1 +//CHECK-NEXT: %91 = load i256, i256* %90, align 4 +//CHECK-NEXT: %92 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 0 +//CHECK-NEXT: %93 = load [0 x i256]*, [0 x i256]** %92, align 8 +//CHECK-NEXT: %94 = getelementptr [0 x i256], [0 x i256]* %93, i32 0, i32 3 +//CHECK-NEXT: store i256 %91, i256* %94, align 4 +//CHECK-NEXT: %95 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 1 +//CHECK-NEXT: %load.subcmp.counter28 = load i32, i32* %95, align 4 +//CHECK-NEXT: %decrement.counter29 = sub i32 %load.subcmp.counter28, 1 +//CHECK-NEXT: store i32 %decrement.counter29, i32* %95, align 4 +//CHECK-NEXT: %96 = load i256, i256* %94, align 4 +//CHECK-NEXT: %constraint30 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %91, i256 %96, i1* %constraint30) +//CHECK-NEXT: %97 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %98 = load [0 x i256]*, [0 x i256]** %97, align 8 +//CHECK-NEXT: %99 = getelementptr [0 x i256], [0 x i256]* %98, i32 0, i32 3 +//CHECK-NEXT: %100 = load i256, i256* %99, align 4 +//CHECK-NEXT: %101 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 0 +//CHECK-NEXT: %102 = load [0 x i256]*, [0 x i256]** %101, align 8 +//CHECK-NEXT: %103 = getelementptr [0 x i256], [0 x i256]* %102, i32 0, i32 5 +//CHECK-NEXT: store i256 %100, i256* %103, align 4 +//CHECK-NEXT: %104 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 1 +//CHECK-NEXT: %load.subcmp.counter31 = load i32, i32* %104, align 4 +//CHECK-NEXT: %decrement.counter32 = sub i32 %load.subcmp.counter31, 1 +//CHECK-NEXT: store i32 %decrement.counter32, i32* %104, align 4 +//CHECK-NEXT: %105 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 0 +//CHECK-NEXT: %106 = load [0 x i256]*, [0 x i256]** %105, align 8 +//CHECK-NEXT: call void @A_1_run([0 x i256]* %106) +//CHECK-NEXT: %107 = load i256, i256* %103, align 4 +//CHECK-NEXT: %constraint33 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %100, i256 %107, i1* %constraint33) +//CHECK-NEXT: %108 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 2, i256* %108, align 4 +//CHECK-NEXT: br label %store9 +//CHECK-EMPTY: +//CHECK-NEXT: store9: +//CHECK-NEXT: %109 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 0, i256* %109, align 4 +//CHECK-NEXT: br label %unrolled_loop10 +//CHECK-EMPTY: +//CHECK-NEXT: unrolled_loop10: +//CHECK-NEXT: %110 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 0 +//CHECK-NEXT: %111 = load [0 x i256]*, [0 x i256]** %110, align 8 +//CHECK-NEXT: %112 = getelementptr [0 x i256], [0 x i256]* %111, i32 0, i32 0 +//CHECK-NEXT: %113 = load i256, i256* %112, align 4 +//CHECK-NEXT: %114 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 0 +//CHECK-NEXT: store i256 %113, i256* %114, align 4 +//CHECK-NEXT: %115 = load i256, i256* %114, align 4 +//CHECK-NEXT: %constraint34 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %113, i256 %115, i1* %constraint34) +//CHECK-NEXT: %116 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 1, i256* %116, align 4 +//CHECK-NEXT: %117 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 0 +//CHECK-NEXT: %118 = load [0 x i256]*, [0 x i256]** %117, align 8 +//CHECK-NEXT: %119 = getelementptr [0 x i256], [0 x i256]* %118, i32 0, i32 1 +//CHECK-NEXT: %120 = load i256, i256* %119, align 4 +//CHECK-NEXT: %121 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 1 +//CHECK-NEXT: store i256 %120, i256* %121, align 4 +//CHECK-NEXT: %122 = load i256, i256* %121, align 4 +//CHECK-NEXT: %constraint35 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %120, i256 %122, i1* %constraint35) +//CHECK-NEXT: %123 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 2, i256* %123, align 4 +//CHECK-NEXT: br label %prologue +//CHECK-EMPTY: +//CHECK-NEXT: prologue: +//CHECK-NEXT: ret void +//CHECK-NEXT: } diff --git a/circom/tests/subcmps/mapped2.circom b/circom/tests/subcmps/mapped2.circom index 41b3d479c..0e1670a01 100644 --- a/circom/tests/subcmps/mapped2.circom +++ b/circom/tests/subcmps/mapped2.circom @@ -2,7 +2,6 @@ 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 --enable-var-scope -// XFAIL:.* // pending https://veridise.atlassian.net/browse/VAN-670 template A(n) { signal input a[n]; @@ -57,3 +56,556 @@ template B(n, m, j) { } component main = B(2, 3, 2); + +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0, i256* %fix_1){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+]]: +//CHECK-NEXT: br label %store1 +//CHECK-EMPTY: +//CHECK-NEXT: store1: +//CHECK-NEXT: %0 = getelementptr i256, i256* %fix_1, i32 0 +//CHECK-NEXT: %1 = load i256, i256* %0, align 4 +//CHECK-NEXT: %call.fr_mul = call i256 @fr_mul(i256 %1, i256 2) +//CHECK-NEXT: %2 = getelementptr i256, i256* %fix_0, i32 0 +//CHECK-NEXT: store i256 %call.fr_mul, i256* %2, align 4 +//CHECK-NEXT: %3 = load i256, i256* %2, align 4 +//CHECK-NEXT: %constraint = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %call.fr_mul, i256 %3, i1* %constraint) +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %4 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: %5 = load i256, i256* %4, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %5, i256 1) +//CHECK-NEXT: %6 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 %call.fr_add, i256* %6, align 4 +//CHECK-NEXT: br label %return3 +//CHECK-EMPTY: +//CHECK-NEXT: return3: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0, i256* %fix_1){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_2:[0-9]+]]: +//CHECK-NEXT: br label %store1 +//CHECK-EMPTY: +//CHECK-NEXT: store1: +//CHECK-NEXT: %0 = getelementptr i256, i256* %fix_1, i32 0 +//CHECK-NEXT: %1 = load i256, i256* %0, align 4 +//CHECK-NEXT: %call.fr_mul = call i256 @fr_mul(i256 %1, i256 2) +//CHECK-NEXT: %2 = getelementptr i256, i256* %fix_0, i32 0 +//CHECK-NEXT: store i256 %call.fr_mul, i256* %2, align 4 +//CHECK-NEXT: %3 = load i256, i256* %2, align 4 +//CHECK-NEXT: %constraint = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %call.fr_mul, i256 %3, i1* %constraint) +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %4 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: %5 = load i256, i256* %4, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %5, i256 1) +//CHECK-NEXT: %6 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 %call.fr_add, i256* %6, align 4 +//CHECK-NEXT: br label %return3 +//CHECK-EMPTY: +//CHECK-NEXT: return3: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @A_0_run([0 x i256]* %0){{.*}} { +//CHECK-NEXT: prelude: +//CHECK-NEXT: %lvars = alloca [2 x i256], align 8 +//CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 +//CHECK-NEXT: br label %store1 +//CHECK-EMPTY: +//CHECK-NEXT: store1: +//CHECK-NEXT: %1 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: store i256 2, i256* %1, align 4 +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %2 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 0, i256* %2, align 4 +//CHECK-NEXT: br label %store3 +//CHECK-EMPTY: +//CHECK-NEXT: store3: +//CHECK-NEXT: %3 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 0, i256* %3, align 4 +//CHECK-NEXT: br label %unrolled_loop4 +//CHECK-EMPTY: +//CHECK-NEXT: unrolled_loop4: +//CHECK-NEXT: %4 = bitcast [2 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %5 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 0 +//CHECK-NEXT: %6 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 2 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %4, [0 x i256]* %0, i256* %5, i256* %6) +//CHECK-NEXT: %7 = bitcast [2 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %8 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 1 +//CHECK-NEXT: %9 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 3 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %7, [0 x i256]* %0, i256* %8, i256* %9) +//CHECK-NEXT: br label %prologue +//CHECK-EMPTY: +//CHECK-NEXT: prologue: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @A_1_run([0 x i256]* %0){{.*}} { +//CHECK-NEXT: prelude: +//CHECK-NEXT: %lvars = alloca [2 x i256], align 8 +//CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 +//CHECK-NEXT: br label %store1 +//CHECK-EMPTY: +//CHECK-NEXT: store1: +//CHECK-NEXT: %1 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: store i256 3, i256* %1, align 4 +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %2 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 0, i256* %2, align 4 +//CHECK-NEXT: br label %store3 +//CHECK-EMPTY: +//CHECK-NEXT: store3: +//CHECK-NEXT: %3 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 0, i256* %3, align 4 +//CHECK-NEXT: br label %unrolled_loop4 +//CHECK-EMPTY: +//CHECK-NEXT: unrolled_loop4: +//CHECK-NEXT: %4 = bitcast [2 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %5 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 0 +//CHECK-NEXT: %6 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 3 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %4, [0 x i256]* %0, i256* %5, i256* %6) +//CHECK-NEXT: %7 = bitcast [2 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %8 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 1 +//CHECK-NEXT: %9 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 4 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %7, [0 x i256]* %0, i256* %8, i256* %9) +//CHECK-NEXT: %10 = bitcast [2 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %11 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 2 +//CHECK-NEXT: %12 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 5 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %10, [0 x i256]* %0, i256* %11, i256* %12) +//CHECK-NEXT: br label %prologue +//CHECK-EMPTY: +//CHECK-NEXT: prologue: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @B_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-NEXT: prelude: +//CHECK-NEXT: %lvars = alloca [5 x i256], align 8 +//CHECK-NEXT: %subcmps = alloca [4 x { [0 x i256]*, i32 }], align 8 +//CHECK-NEXT: br label %store1 +//CHECK-EMPTY: +//CHECK-NEXT: store1: +//CHECK-NEXT: %1 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: store i256 2, i256* %1, align 4 +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %2 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 3, i256* %2, align 4 +//CHECK-NEXT: br label %store3 +//CHECK-EMPTY: +//CHECK-NEXT: store3: +//CHECK-NEXT: %3 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 2 +//CHECK-NEXT: store i256 2, i256* %3, align 4 +//CHECK-NEXT: br label %create_cmp4 +//CHECK-EMPTY: +//CHECK-NEXT: create_cmp4: +//CHECK-NEXT: %4 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0 +//CHECK-NEXT: call void @A_0_build({ [0 x i256]*, i32 }* %4) +//CHECK-NEXT: br label %create_cmp5 +//CHECK-EMPTY: +//CHECK-NEXT: create_cmp5: +//CHECK-NEXT: %5 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1 +//CHECK-NEXT: call void @A_0_build({ [0 x i256]*, i32 }* %5) +//CHECK-NEXT: br label %create_cmp6 +//CHECK-EMPTY: +//CHECK-NEXT: create_cmp6: +//CHECK-NEXT: %6 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2 +//CHECK-NEXT: call void @A_1_build({ [0 x i256]*, i32 }* %6) +//CHECK-NEXT: br label %create_cmp7 +//CHECK-EMPTY: +//CHECK-NEXT: create_cmp7: +//CHECK-NEXT: %7 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 3 +//CHECK-NEXT: call void @A_1_build({ [0 x i256]*, i32 }* %7) +//CHECK-NEXT: br label %store8 +//CHECK-EMPTY: +//CHECK-NEXT: store8: +//CHECK-NEXT: %8 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 3 +//CHECK-NEXT: store i256 0, i256* %8, align 4 +//CHECK-NEXT: br label %store9 +//CHECK-EMPTY: +//CHECK-NEXT: store9: +//CHECK-NEXT: %9 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 0, i256* %9, align 4 +//CHECK-NEXT: br label %store10 +//CHECK-EMPTY: +//CHECK-NEXT: store10: +//CHECK-NEXT: %10 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 0, i256* %10, align 4 +//CHECK-NEXT: br label %unrolled_loop11 +//CHECK-EMPTY: +//CHECK-NEXT: unrolled_loop11: +//CHECK-NEXT: %11 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 1, i256* %11, align 4 +//CHECK-NEXT: %12 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 2, i256* %12, align 4 +//CHECK-NEXT: br label %store12 +//CHECK-EMPTY: +//CHECK-NEXT: store12: +//CHECK-NEXT: %13 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 3 +//CHECK-NEXT: store i256 0, i256* %13, align 4 +//CHECK-NEXT: br label %unrolled_loop13 +//CHECK-EMPTY: +//CHECK-NEXT: unrolled_loop13: +//CHECK-NEXT: %14 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 0, i256* %14, align 4 +//CHECK-NEXT: %15 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 10 +//CHECK-NEXT: %16 = load i256, i256* %15, align 4 +//CHECK-NEXT: %17 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %18 = load [0 x i256]*, [0 x i256]** %17, align 8 +//CHECK-NEXT: %19 = getelementptr [0 x i256], [0 x i256]* %18, i32 0, i32 2 +//CHECK-NEXT: store i256 %16, i256* %19, align 4 +//CHECK-NEXT: %20 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 1 +//CHECK-NEXT: %load.subcmp.counter = load i32, i32* %20, align 4 +//CHECK-NEXT: %decrement.counter = sub i32 %load.subcmp.counter, 1 +//CHECK-NEXT: store i32 %decrement.counter, i32* %20, align 4 +//CHECK-NEXT: %21 = load i256, i256* %19, align 4 +//CHECK-NEXT: %constraint = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %16, i256 %21, i1* %constraint) +//CHECK-NEXT: %22 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 1, i256* %22, align 4 +//CHECK-NEXT: %23 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 11 +//CHECK-NEXT: %24 = load i256, i256* %23, align 4 +//CHECK-NEXT: %25 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 0 +//CHECK-NEXT: %26 = load [0 x i256]*, [0 x i256]** %25, align 8 +//CHECK-NEXT: %27 = getelementptr [0 x i256], [0 x i256]* %26, i32 0, i32 2 +//CHECK-NEXT: store i256 %24, i256* %27, align 4 +//CHECK-NEXT: %28 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 1 +//CHECK-NEXT: %load.subcmp.counter1 = load i32, i32* %28, align 4 +//CHECK-NEXT: %decrement.counter2 = sub i32 %load.subcmp.counter1, 1 +//CHECK-NEXT: store i32 %decrement.counter2, i32* %28, align 4 +//CHECK-NEXT: %29 = load i256, i256* %27, align 4 +//CHECK-NEXT: %constraint3 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %24, i256 %29, i1* %constraint3) +//CHECK-NEXT: %30 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 2, i256* %30, align 4 +//CHECK-NEXT: %31 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 3 +//CHECK-NEXT: store i256 1, i256* %31, align 4 +//CHECK-NEXT: %32 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 0, i256* %32, align 4 +//CHECK-NEXT: %33 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 12 +//CHECK-NEXT: %34 = load i256, i256* %33, align 4 +//CHECK-NEXT: %35 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %36 = load [0 x i256]*, [0 x i256]** %35, align 8 +//CHECK-NEXT: %37 = getelementptr [0 x i256], [0 x i256]* %36, i32 0, i32 3 +//CHECK-NEXT: store i256 %34, i256* %37, align 4 +//CHECK-NEXT: %38 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 1 +//CHECK-NEXT: %load.subcmp.counter4 = load i32, i32* %38, align 4 +//CHECK-NEXT: %decrement.counter5 = sub i32 %load.subcmp.counter4, 1 +//CHECK-NEXT: store i32 %decrement.counter5, i32* %38, align 4 +//CHECK-NEXT: %39 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %40 = load [0 x i256]*, [0 x i256]** %39, align 8 +//CHECK-NEXT: call void @A_0_run([0 x i256]* %40) +//CHECK-NEXT: %41 = load i256, i256* %37, align 4 +//CHECK-NEXT: %constraint6 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %34, i256 %41, i1* %constraint6) +//CHECK-NEXT: %42 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 1, i256* %42, align 4 +//CHECK-NEXT: %43 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 13 +//CHECK-NEXT: %44 = load i256, i256* %43, align 4 +//CHECK-NEXT: %45 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 0 +//CHECK-NEXT: %46 = load [0 x i256]*, [0 x i256]** %45, align 8 +//CHECK-NEXT: %47 = getelementptr [0 x i256], [0 x i256]* %46, i32 0, i32 3 +//CHECK-NEXT: store i256 %44, i256* %47, align 4 +//CHECK-NEXT: %48 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 1 +//CHECK-NEXT: %load.subcmp.counter7 = load i32, i32* %48, align 4 +//CHECK-NEXT: %decrement.counter8 = sub i32 %load.subcmp.counter7, 1 +//CHECK-NEXT: store i32 %decrement.counter8, i32* %48, align 4 +//CHECK-NEXT: %49 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 0 +//CHECK-NEXT: %50 = load [0 x i256]*, [0 x i256]** %49, align 8 +//CHECK-NEXT: call void @A_0_run([0 x i256]* %50) +//CHECK-NEXT: %51 = load i256, i256* %47, align 4 +//CHECK-NEXT: %constraint9 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %44, i256 %51, i1* %constraint9) +//CHECK-NEXT: %52 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 2, i256* %52, align 4 +//CHECK-NEXT: %53 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 3 +//CHECK-NEXT: store i256 2, i256* %53, align 4 +//CHECK-NEXT: br label %store14 +//CHECK-EMPTY: +//CHECK-NEXT: store14: +//CHECK-NEXT: %54 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 0, i256* %54, align 4 +//CHECK-NEXT: br label %unrolled_loop15 +//CHECK-EMPTY: +//CHECK-NEXT: unrolled_loop15: +//CHECK-NEXT: %55 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 1, i256* %55, align 4 +//CHECK-NEXT: %56 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 2, i256* %56, align 4 +//CHECK-NEXT: br label %store16 +//CHECK-EMPTY: +//CHECK-NEXT: store16: +//CHECK-NEXT: %57 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 3 +//CHECK-NEXT: store i256 0, i256* %57, align 4 +//CHECK-NEXT: br label %unrolled_loop17 +//CHECK-EMPTY: +//CHECK-NEXT: unrolled_loop17: +//CHECK-NEXT: %58 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 0, i256* %58, align 4 +//CHECK-NEXT: %59 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 14 +//CHECK-NEXT: %60 = load i256, i256* %59, align 4 +//CHECK-NEXT: %61 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2, i32 0 +//CHECK-NEXT: %62 = load [0 x i256]*, [0 x i256]** %61, align 8 +//CHECK-NEXT: %63 = getelementptr [0 x i256], [0 x i256]* %62, i32 0, i32 3 +//CHECK-NEXT: store i256 %60, i256* %63, align 4 +//CHECK-NEXT: %64 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2, i32 1 +//CHECK-NEXT: %load.subcmp.counter10 = load i32, i32* %64, align 4 +//CHECK-NEXT: %decrement.counter11 = sub i32 %load.subcmp.counter10, 1 +//CHECK-NEXT: store i32 %decrement.counter11, i32* %64, align 4 +//CHECK-NEXT: %65 = load i256, i256* %63, align 4 +//CHECK-NEXT: %constraint12 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %60, i256 %65, i1* %constraint12) +//CHECK-NEXT: %66 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 1, i256* %66, align 4 +//CHECK-NEXT: %67 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 15 +//CHECK-NEXT: %68 = load i256, i256* %67, align 4 +//CHECK-NEXT: %69 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 3, i32 0 +//CHECK-NEXT: %70 = load [0 x i256]*, [0 x i256]** %69, align 8 +//CHECK-NEXT: %71 = getelementptr [0 x i256], [0 x i256]* %70, i32 0, i32 3 +//CHECK-NEXT: store i256 %68, i256* %71, align 4 +//CHECK-NEXT: %72 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 3, i32 1 +//CHECK-NEXT: %load.subcmp.counter13 = load i32, i32* %72, align 4 +//CHECK-NEXT: %decrement.counter14 = sub i32 %load.subcmp.counter13, 1 +//CHECK-NEXT: store i32 %decrement.counter14, i32* %72, align 4 +//CHECK-NEXT: %73 = load i256, i256* %71, align 4 +//CHECK-NEXT: %constraint15 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %68, i256 %73, i1* %constraint15) +//CHECK-NEXT: %74 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 2, i256* %74, align 4 +//CHECK-NEXT: %75 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 3 +//CHECK-NEXT: store i256 1, i256* %75, align 4 +//CHECK-NEXT: %76 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 0, i256* %76, align 4 +//CHECK-NEXT: %77 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 16 +//CHECK-NEXT: %78 = load i256, i256* %77, align 4 +//CHECK-NEXT: %79 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2, i32 0 +//CHECK-NEXT: %80 = load [0 x i256]*, [0 x i256]** %79, align 8 +//CHECK-NEXT: %81 = getelementptr [0 x i256], [0 x i256]* %80, i32 0, i32 4 +//CHECK-NEXT: store i256 %78, i256* %81, align 4 +//CHECK-NEXT: %82 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2, i32 1 +//CHECK-NEXT: %load.subcmp.counter16 = load i32, i32* %82, align 4 +//CHECK-NEXT: %decrement.counter17 = sub i32 %load.subcmp.counter16, 1 +//CHECK-NEXT: store i32 %decrement.counter17, i32* %82, align 4 +//CHECK-NEXT: %83 = load i256, i256* %81, align 4 +//CHECK-NEXT: %constraint18 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %78, i256 %83, i1* %constraint18) +//CHECK-NEXT: %84 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 1, i256* %84, align 4 +//CHECK-NEXT: %85 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 17 +//CHECK-NEXT: %86 = load i256, i256* %85, align 4 +//CHECK-NEXT: %87 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 3, i32 0 +//CHECK-NEXT: %88 = load [0 x i256]*, [0 x i256]** %87, align 8 +//CHECK-NEXT: %89 = getelementptr [0 x i256], [0 x i256]* %88, i32 0, i32 4 +//CHECK-NEXT: store i256 %86, i256* %89, align 4 +//CHECK-NEXT: %90 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 3, i32 1 +//CHECK-NEXT: %load.subcmp.counter19 = load i32, i32* %90, align 4 +//CHECK-NEXT: %decrement.counter20 = sub i32 %load.subcmp.counter19, 1 +//CHECK-NEXT: store i32 %decrement.counter20, i32* %90, align 4 +//CHECK-NEXT: %91 = load i256, i256* %89, align 4 +//CHECK-NEXT: %constraint21 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %86, i256 %91, i1* %constraint21) +//CHECK-NEXT: %92 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 2, i256* %92, align 4 +//CHECK-NEXT: %93 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 3 +//CHECK-NEXT: store i256 2, i256* %93, align 4 +//CHECK-NEXT: %94 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 0, i256* %94, align 4 +//CHECK-NEXT: %95 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 18 +//CHECK-NEXT: %96 = load i256, i256* %95, align 4 +//CHECK-NEXT: %97 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2, i32 0 +//CHECK-NEXT: %98 = load [0 x i256]*, [0 x i256]** %97, align 8 +//CHECK-NEXT: %99 = getelementptr [0 x i256], [0 x i256]* %98, i32 0, i32 5 +//CHECK-NEXT: store i256 %96, i256* %99, align 4 +//CHECK-NEXT: %100 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2, i32 1 +//CHECK-NEXT: %load.subcmp.counter22 = load i32, i32* %100, align 4 +//CHECK-NEXT: %decrement.counter23 = sub i32 %load.subcmp.counter22, 1 +//CHECK-NEXT: store i32 %decrement.counter23, i32* %100, align 4 +//CHECK-NEXT: %101 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2, i32 0 +//CHECK-NEXT: %102 = load [0 x i256]*, [0 x i256]** %101, align 8 +//CHECK-NEXT: call void @A_1_run([0 x i256]* %102) +//CHECK-NEXT: %103 = load i256, i256* %99, align 4 +//CHECK-NEXT: %constraint24 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %96, i256 %103, i1* %constraint24) +//CHECK-NEXT: %104 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 1, i256* %104, align 4 +//CHECK-NEXT: %105 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 19 +//CHECK-NEXT: %106 = load i256, i256* %105, align 4 +//CHECK-NEXT: %107 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 3, i32 0 +//CHECK-NEXT: %108 = load [0 x i256]*, [0 x i256]** %107, align 8 +//CHECK-NEXT: %109 = getelementptr [0 x i256], [0 x i256]* %108, i32 0, i32 5 +//CHECK-NEXT: store i256 %106, i256* %109, align 4 +//CHECK-NEXT: %110 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 3, i32 1 +//CHECK-NEXT: %load.subcmp.counter25 = load i32, i32* %110, align 4 +//CHECK-NEXT: %decrement.counter26 = sub i32 %load.subcmp.counter25, 1 +//CHECK-NEXT: store i32 %decrement.counter26, i32* %110, align 4 +//CHECK-NEXT: %111 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 3, i32 0 +//CHECK-NEXT: %112 = load [0 x i256]*, [0 x i256]** %111, align 8 +//CHECK-NEXT: call void @A_1_run([0 x i256]* %112) +//CHECK-NEXT: %113 = load i256, i256* %109, align 4 +//CHECK-NEXT: %constraint27 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %106, i256 %113, i1* %constraint27) +//CHECK-NEXT: %114 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 2, i256* %114, align 4 +//CHECK-NEXT: %115 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 3 +//CHECK-NEXT: store i256 3, i256* %115, align 4 +//CHECK-NEXT: br label %store18 +//CHECK-EMPTY: +//CHECK-NEXT: store18: +//CHECK-NEXT: %116 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 3 +//CHECK-NEXT: store i256 0, i256* %116, align 4 +//CHECK-NEXT: br label %unrolled_loop19 +//CHECK-EMPTY: +//CHECK-NEXT: unrolled_loop19: +//CHECK-NEXT: %117 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 0, i256* %117, align 4 +//CHECK-NEXT: %118 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %119 = load [0 x i256]*, [0 x i256]** %118, align 8 +//CHECK-NEXT: %120 = getelementptr [0 x i256], [0 x i256]* %119, i32 0, i32 0 +//CHECK-NEXT: %121 = load i256, i256* %120, align 4 +//CHECK-NEXT: %122 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 0 +//CHECK-NEXT: store i256 %121, i256* %122, align 4 +//CHECK-NEXT: %123 = load i256, i256* %122, align 4 +//CHECK-NEXT: %constraint28 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %121, i256 %123, i1* %constraint28) +//CHECK-NEXT: %124 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 1, i256* %124, align 4 +//CHECK-NEXT: %125 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 0 +//CHECK-NEXT: %126 = load [0 x i256]*, [0 x i256]** %125, align 8 +//CHECK-NEXT: %127 = getelementptr [0 x i256], [0 x i256]* %126, i32 0, i32 0 +//CHECK-NEXT: %128 = load i256, i256* %127, align 4 +//CHECK-NEXT: %129 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 1 +//CHECK-NEXT: store i256 %128, i256* %129, align 4 +//CHECK-NEXT: %130 = load i256, i256* %129, align 4 +//CHECK-NEXT: %constraint29 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %128, i256 %130, i1* %constraint29) +//CHECK-NEXT: %131 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 2, i256* %131, align 4 +//CHECK-NEXT: %132 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 3 +//CHECK-NEXT: store i256 1, i256* %132, align 4 +//CHECK-NEXT: %133 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 0, i256* %133, align 4 +//CHECK-NEXT: %134 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %135 = load [0 x i256]*, [0 x i256]** %134, align 8 +//CHECK-NEXT: %136 = getelementptr [0 x i256], [0 x i256]* %135, i32 0, i32 1 +//CHECK-NEXT: %137 = load i256, i256* %136, align 4 +//CHECK-NEXT: %138 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 2 +//CHECK-NEXT: store i256 %137, i256* %138, align 4 +//CHECK-NEXT: %139 = load i256, i256* %138, align 4 +//CHECK-NEXT: %constraint30 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %137, i256 %139, i1* %constraint30) +//CHECK-NEXT: %140 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 1, i256* %140, align 4 +//CHECK-NEXT: %141 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 0 +//CHECK-NEXT: %142 = load [0 x i256]*, [0 x i256]** %141, align 8 +//CHECK-NEXT: %143 = getelementptr [0 x i256], [0 x i256]* %142, i32 0, i32 1 +//CHECK-NEXT: %144 = load i256, i256* %143, align 4 +//CHECK-NEXT: %145 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 3 +//CHECK-NEXT: store i256 %144, i256* %145, align 4 +//CHECK-NEXT: %146 = load i256, i256* %145, align 4 +//CHECK-NEXT: %constraint31 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %144, i256 %146, i1* %constraint31) +//CHECK-NEXT: %147 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 2, i256* %147, align 4 +//CHECK-NEXT: %148 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 3 +//CHECK-NEXT: store i256 2, i256* %148, align 4 +//CHECK-NEXT: br label %store20 +//CHECK-EMPTY: +//CHECK-NEXT: store20: +//CHECK-NEXT: %149 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 3 +//CHECK-NEXT: store i256 0, i256* %149, align 4 +//CHECK-NEXT: br label %unrolled_loop21 +//CHECK-EMPTY: +//CHECK-NEXT: unrolled_loop21: +//CHECK-NEXT: %150 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 0, i256* %150, align 4 +//CHECK-NEXT: %151 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2, i32 0 +//CHECK-NEXT: %152 = load [0 x i256]*, [0 x i256]** %151, align 8 +//CHECK-NEXT: %153 = getelementptr [0 x i256], [0 x i256]* %152, i32 0, i32 0 +//CHECK-NEXT: %154 = load i256, i256* %153, align 4 +//CHECK-NEXT: %155 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 4 +//CHECK-NEXT: store i256 %154, i256* %155, align 4 +//CHECK-NEXT: %156 = load i256, i256* %155, align 4 +//CHECK-NEXT: %constraint32 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %154, i256 %156, i1* %constraint32) +//CHECK-NEXT: %157 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 1, i256* %157, align 4 +//CHECK-NEXT: %158 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 3, i32 0 +//CHECK-NEXT: %159 = load [0 x i256]*, [0 x i256]** %158, align 8 +//CHECK-NEXT: %160 = getelementptr [0 x i256], [0 x i256]* %159, i32 0, i32 0 +//CHECK-NEXT: %161 = load i256, i256* %160, align 4 +//CHECK-NEXT: %162 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 5 +//CHECK-NEXT: store i256 %161, i256* %162, align 4 +//CHECK-NEXT: %163 = load i256, i256* %162, align 4 +//CHECK-NEXT: %constraint33 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %161, i256 %163, i1* %constraint33) +//CHECK-NEXT: %164 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 2, i256* %164, align 4 +//CHECK-NEXT: %165 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 3 +//CHECK-NEXT: store i256 1, i256* %165, align 4 +//CHECK-NEXT: %166 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 0, i256* %166, align 4 +//CHECK-NEXT: %167 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2, i32 0 +//CHECK-NEXT: %168 = load [0 x i256]*, [0 x i256]** %167, align 8 +//CHECK-NEXT: %169 = getelementptr [0 x i256], [0 x i256]* %168, i32 0, i32 1 +//CHECK-NEXT: %170 = load i256, i256* %169, align 4 +//CHECK-NEXT: %171 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 6 +//CHECK-NEXT: store i256 %170, i256* %171, align 4 +//CHECK-NEXT: %172 = load i256, i256* %171, align 4 +//CHECK-NEXT: %constraint34 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %170, i256 %172, i1* %constraint34) +//CHECK-NEXT: %173 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 1, i256* %173, align 4 +//CHECK-NEXT: %174 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 3, i32 0 +//CHECK-NEXT: %175 = load [0 x i256]*, [0 x i256]** %174, align 8 +//CHECK-NEXT: %176 = getelementptr [0 x i256], [0 x i256]* %175, i32 0, i32 1 +//CHECK-NEXT: %177 = load i256, i256* %176, align 4 +//CHECK-NEXT: %178 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 7 +//CHECK-NEXT: store i256 %177, i256* %178, align 4 +//CHECK-NEXT: %179 = load i256, i256* %178, align 4 +//CHECK-NEXT: %constraint35 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %177, i256 %179, i1* %constraint35) +//CHECK-NEXT: %180 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 2, i256* %180, align 4 +//CHECK-NEXT: %181 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 3 +//CHECK-NEXT: store i256 2, i256* %181, align 4 +//CHECK-NEXT: %182 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 0, i256* %182, align 4 +//CHECK-NEXT: %183 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2, i32 0 +//CHECK-NEXT: %184 = load [0 x i256]*, [0 x i256]** %183, align 8 +//CHECK-NEXT: %185 = getelementptr [0 x i256], [0 x i256]* %184, i32 0, i32 2 +//CHECK-NEXT: %186 = load i256, i256* %185, align 4 +//CHECK-NEXT: %187 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 8 +//CHECK-NEXT: store i256 %186, i256* %187, align 4 +//CHECK-NEXT: %188 = load i256, i256* %187, align 4 +//CHECK-NEXT: %constraint36 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %186, i256 %188, i1* %constraint36) +//CHECK-NEXT: %189 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 1, i256* %189, align 4 +//CHECK-NEXT: %190 = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 3, i32 0 +//CHECK-NEXT: %191 = load [0 x i256]*, [0 x i256]** %190, align 8 +//CHECK-NEXT: %192 = getelementptr [0 x i256], [0 x i256]* %191, i32 0, i32 2 +//CHECK-NEXT: %193 = load i256, i256* %192, align 4 +//CHECK-NEXT: %194 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 9 +//CHECK-NEXT: store i256 %193, i256* %194, align 4 +//CHECK-NEXT: %195 = load i256, i256* %194, align 4 +//CHECK-NEXT: %constraint37 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %193, i256 %195, i1* %constraint37) +//CHECK-NEXT: %196 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 +//CHECK-NEXT: store i256 2, i256* %196, align 4 +//CHECK-NEXT: %197 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 3 +//CHECK-NEXT: store i256 3, i256* %197, align 4 +//CHECK-NEXT: br label %prologue +//CHECK-EMPTY: +//CHECK-NEXT: prologue: +//CHECK-NEXT: ret void +//CHECK-NEXT: } diff --git a/circom/tests/subcmps/mapped3.circom b/circom/tests/subcmps/mapped3.circom index 6393b7fdc..e2957eaff 100644 --- a/circom/tests/subcmps/mapped3.circom +++ b/circom/tests/subcmps/mapped3.circom @@ -11,12 +11,6 @@ template ArrayOp(q) { } } -//CHECK-LABEL: define void @ArrayOp_{{[0-9]+}}_build -//CHECK-SAME: ({ [0 x i256]*, i32 }* %{{.*}}) -//CHECK: alloca [30 x i256] -//CHECK: %[[DIM_REG:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 -//CHECK: store i32 15, i32* %{{.*}}[[DIM_REG]] - template Wrapper() { signal input inp[15]; signal output outp; @@ -37,14 +31,136 @@ template Wrapper() { component main = Wrapper(); -//CHECK-LABEL: define void @Wrapper_{{[0-9]+}}_run -//CHECK-SAME: ([0 x i256]* %{{.*}}) +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+]]: +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_2:[0-9]+]]: +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_3:[0-9]+]]: +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_4:[0-9]+]]: +// +//CHECK-LABEL: define void @ArrayOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-NEXT: main: +//CHECK-NEXT: %[[SIGNALS:.*]] = alloca [30 x i256] +//CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 +//CHECK-NEXT: store i32 15, i32* %[[COUNTER]] +// +//CHECK-LABEL: define void @ArrayOp_ +//CHECK-SAME: [[$RUN_1:[0-9]+]]_run([0 x i256]* %0){{.*}} { +//CHECK: call void @..generated..loop.body.[[$F_ID_1]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_1]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_1]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_1]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_1]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_1]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_1]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_1]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_1]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_1]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_1]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_1]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_1]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_1]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_1]]( +// +//CHECK-LABEL: define void @ArrayOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-NEXT: main: +//CHECK-NEXT: %[[SIGNALS:.*]] = alloca [30 x i256] +//CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 +//CHECK-NEXT: store i32 15, i32* %[[COUNTER]] + +//CHECK-LABEL: define void @ArrayOp_ +//CHECK-SAME: [[$RUN_2:[0-9]+]]_run([0 x i256]* %0){{.*}} { +//CHECK: call void @..generated..loop.body.[[$F_ID_2]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_2]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_2]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_2]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_2]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_2]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_2]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_2]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_2]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_2]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_2]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_2]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_2]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_2]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_2]]( +// +//CHECK-LABEL: define void @ArrayOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-NEXT: main: +//CHECK-NEXT: %[[SIGNALS:.*]] = alloca [30 x i256] +//CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 +//CHECK-NEXT: store i32 15, i32* %[[COUNTER]] +// +//CHECK-LABEL: define void @ArrayOp_ +//CHECK-SAME: [[$RUN_3:[0-9]+]]_run([0 x i256]* %0){{.*}} { +//CHECK: call void @..generated..loop.body.[[$F_ID_3]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_3]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_3]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_3]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_3]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_3]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_3]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_3]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_3]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_3]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_3]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_3]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_3]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_3]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_3]]( +// +//CHECK-LABEL: define void @ArrayOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-NEXT: main: +//CHECK-NEXT: %[[SIGNALS:.*]] = alloca [30 x i256] +//CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 +//CHECK-NEXT: store i32 15, i32* %[[COUNTER]] +// +//CHECK-LABEL: define void @ArrayOp_ +//CHECK-SAME: [[$RUN_4:[0-9]+]]_run([0 x i256]* %0){{.*}} { +//CHECK: call void @..generated..loop.body.[[$F_ID_4]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_4]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_4]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_4]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_4]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_4]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_4]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_4]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_4]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_4]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_4]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_4]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_4]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_4]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_4]]( +// +//CHECK-LABEL: define void @Wrapper_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-NEXT: main: +//CHECK-NEXT: %[[SIGNALS:.*]] = alloca [16 x i256] +//CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 +//CHECK-NEXT: store i32 15, i32* %{{.*}}[[COUNTER]] +// +//CHECK-LABEL: define void @Wrapper_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK: %lvars = alloca [2 x i256] +//CHECK: unrolled_loop{{[0-9]+}}: +//CHECK: call void @ArrayOp_[[$RUN_1]]_run([0 x i256]* % +//CHECK: call void @ArrayOp_[[$RUN_2]]_run([0 x i256]* % +//CHECK: call void @ArrayOp_[[$RUN_3]]_run([0 x i256]* % +//CHECK: call void @ArrayOp_[[$RUN_4]]_run([0 x i256]* % //COM: offset = (1 * (3 * 7)) + (2 * (7)) + (3) + 1 (since 0 is output) = 21 + 14 + 3 + 1 = 39 -//CHECK: store{{.*}}:{{.*}}; preds = %unrolled_loop{{.*}} -//CHECK: %[[SUB_PTR:.*]] = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2, i32 0 -//CHECK: %[[SUBCMP:.*]] = load [0 x i256]*, [0 x i256]** %[[SUB_PTR]] -//CHECK: %[[VAL_PTR:.*]] = getelementptr [0 x i256], [0 x i256]* %[[SUBCMP]], i32 0, i32 3 -//CHECK: %[[VAL:.*]] = load i256, i256* %[[VAL_PTR]] -//CHECK: %[[OUTP_PTR:.*]] = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 0 -//CHECK: store i256 %[[VAL]], i256* %[[OUTP_PTR]] +//CHECK: store{{[0-9]+}}:{{ +}}; preds = %unrolled_loop{{[0-9]+}} +//CHECK-NEXT: %[[SUB_PTR:.*]] = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2, i32 0 +//CHECK-NEXT: %[[SUBCMP:.*]] = load [0 x i256]*, [0 x i256]** %[[SUB_PTR]] +//CHECK-NEXT: %[[VAL_PTR:.*]] = getelementptr [0 x i256], [0 x i256]* %[[SUBCMP]], i32 0, i32 3 +//CHECK-NEXT: %[[VAL:.*]] = load i256, i256* %[[VAL_PTR]] +//CHECK-NEXT: %[[OUTP_PTR:.*]] = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 0 +//CHECK-NEXT: store i256 %[[VAL]], i256* %[[OUTP_PTR]] diff --git a/circom/tests/subcmps/mapped4.circom b/circom/tests/subcmps/mapped4.circom index 7312cbc80..a0a771958 100644 --- a/circom/tests/subcmps/mapped4.circom +++ b/circom/tests/subcmps/mapped4.circom @@ -13,12 +13,6 @@ template MatrixOp(q) { } } -//CHECK-LABEL: define void @MatrixOp_{{[0-9]+}}_build -//CHECK-SAME: ({ [0 x i256]*, i32 }* %{{.*}}) -//CHECK: alloca [16 x i256] -//CHECK: %[[DIM_REG:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 -//CHECK: store i32 15, i32* %{{.*}}[[DIM_REG]] - template Wrapper() { signal input inp[5][3]; signal output outp; @@ -41,13 +35,211 @@ template Wrapper() { component main = Wrapper(); -//CHECK-LABEL: define void @Wrapper_{{[0-9]+}}_run -//CHECK-SAME: ([0 x i256]* %{{.*}}) +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_01:[0-9]+]]: +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_02:[0-9]+]]: +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_03:[0-9]+]]: +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_04:[0-9]+]]: +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_05:[0-9]+]]: +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_06:[0-9]+]]: +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_07:[0-9]+]]: +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_08:[0-9]+]]: +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_09:[0-9]+]]: +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_10:[0-9]+]]: +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_11:[0-9]+]]: +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_12:[0-9]+]]: +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_13:[0-9]+]]: +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_14:[0-9]+]]: +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_15:[0-9]+]]: +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_16:[0-9]+]]: +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_17:[0-9]+]]: +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_18:[0-9]+]]: +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_19:[0-9]+]]: +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_20:[0-9]+]]: +// +//CHECK-LABEL: define void @MatrixOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-NEXT: main: +//CHECK-NEXT: %[[SIGNALS:.*]] = alloca [30 x i256] +//CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 +//CHECK-NEXT: store i32 15, i32* %[[COUNTER]] +// +//CHECK-LABEL: define void @MatrixOp_ +//CHECK-SAME: [[$RUN_1:[0-9]+]]_run([0 x i256]* %0){{.*}} { +//CHECK-NEXT: prelude: +//CHECK-NEXT: %lvars = alloca [3 x i256] +//CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }] +//CHECK: call void @..generated..loop.body.[[$F_ID_01]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_01]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_01]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_02]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_02]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_02]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_03]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_03]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_03]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_04]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_04]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_04]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_05]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_05]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_05]]( +// +//CHECK-LABEL: define void @MatrixOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-NEXT: main: +//CHECK-NEXT: %[[SIGNALS:.*]] = alloca [30 x i256] +//CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 +//CHECK-NEXT: store i32 15, i32* %[[COUNTER]] +// +//CHECK-LABEL: define void @MatrixOp_ +//CHECK-SAME: [[$RUN_2:[0-9]+]]_run([0 x i256]* %0){{.*}} { +//CHECK-NEXT: prelude: +//CHECK-NEXT: %lvars = alloca [3 x i256] +//CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }] +//CHECK: call void @..generated..loop.body.[[$F_ID_06]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_06]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_06]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_07]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_07]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_07]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_08]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_08]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_08]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_09]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_09]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_09]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_10]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_10]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_10]]( +// +//CHECK-LABEL: define void @MatrixOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-NEXT: main: +//CHECK-NEXT: %[[SIGNALS:.*]] = alloca [30 x i256] +//CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 +//CHECK-NEXT: store i32 15, i32* %[[COUNTER]] +// +//CHECK-LABEL: define void @MatrixOp_ +//CHECK-SAME: [[$RUN_3:[0-9]+]]_run([0 x i256]* %0){{.*}} { +//CHECK-NEXT: prelude: +//CHECK-NEXT: %lvars = alloca [3 x i256] +//CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }] +//CHECK: call void @..generated..loop.body.[[$F_ID_11]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_11]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_11]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_12]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_12]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_12]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_13]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_13]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_13]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_14]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_14]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_14]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_15]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_15]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_15]]( +// +//CHECK-LABEL: define void @MatrixOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-NEXT: main: +//CHECK-NEXT: %[[SIGNALS:.*]] = alloca [30 x i256] +//CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 +//CHECK-NEXT: store i32 15, i32* %[[COUNTER]] +// +//CHECK-LABEL: define void @MatrixOp_ +//CHECK-SAME: [[$RUN_4:[0-9]+]]_run([0 x i256]* %0){{.*}} { +//CHECK-NEXT: prelude: +//CHECK-NEXT: %lvars = alloca [3 x i256] +//CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }] +//CHECK: call void @..generated..loop.body.[[$F_ID_16]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_16]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_16]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_17]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_17]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_17]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_18]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_18]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_18]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_19]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_19]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_19]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_20]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_20]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_20]]( +// +//CHECK-LABEL: define void @Wrapper_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-NEXT: main: +//CHECK-NEXT: %[[SIGNALS:.*]] = alloca [16 x i256] +//CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 +//CHECK-NEXT: store i32 15, i32* %{{.*}}[[COUNTER]] +// +//CHECK-LABEL: define void @Wrapper_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK: %lvars = alloca [3 x i256] -//CHECK: store{{.*}}:{{.*}}; preds = %unrolled_loop{{.*}} -//CHECK: %[[SUB_PTR:.*]] = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2, i32 0 -//CHECK: %[[SUBCMP:.*]] = load [0 x i256]*, [0 x i256]** %[[SUB_PTR]] -//CHECK: %[[VAL_PTR:.*]] = getelementptr [0 x i256], [0 x i256]* %[[SUBCMP]], i32 0, i32 5 -//CHECK: %[[VAL:.*]] = load i256, i256* %[[VAL_PTR]] -//CHECK: %[[OUTP_PTR:.*]] = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 0 -//CHECK: store i256 %[[VAL]], i256* %[[OUTP_PTR]] +//CHECK: unrolled_loop{{[0-9]+}}: +//CHECK: call void @MatrixOp_[[$RUN_1]]_run([0 x i256]* % +//CHECK: call void @MatrixOp_[[$RUN_2]]_run([0 x i256]* % +//CHECK: call void @MatrixOp_[[$RUN_3]]_run([0 x i256]* % +//CHECK: call void @MatrixOp_[[$RUN_4]]_run([0 x i256]* % +//CHECK: store{{[0-9]+}}:{{ +}}; preds = %unrolled_loop{{[0-9]+}} +//CHECK-NEXT: %[[SUB_PTR:.*]] = getelementptr [4 x { [0 x i256]*, i32 }], [4 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2, i32 0 +//CHECK-NEXT: %[[SUBCMP:.*]] = load [0 x i256]*, [0 x i256]** %[[SUB_PTR]] +//CHECK-NEXT: %[[VAL_PTR:.*]] = getelementptr [0 x i256], [0 x i256]* %[[SUBCMP]], i32 0, i32 5 +//CHECK-NEXT: %[[VAL:.*]] = load i256, i256* %[[VAL_PTR]] +//CHECK-NEXT: %[[OUTP_PTR:.*]] = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 0 +//CHECK-NEXT: store i256 %[[VAL]], i256* %[[OUTP_PTR]] diff --git a/circom/tests/subcmps/subcmps0A.circom b/circom/tests/subcmps/subcmps0A.circom index 4f33801b3..80e497bc3 100644 --- a/circom/tests/subcmps/subcmps0A.circom +++ b/circom/tests/subcmps/subcmps0A.circom @@ -24,10 +24,10 @@ template SubCmps0A(n) { component main = SubCmps0A(2); -//CHECK-LABEL: define void @..generated..loop.body. -//CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %subfix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], -//CHECK-SAME: i256* %fix_[[X3:[0-9]+]], i256* %subfix_[[X4:[0-9]+]], [0 x i256]* %sub_[[X4]], i256* %subc_[[X4]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1]]: +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %subfix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]], +//CHECK-SAME: i256* %subfix_[[X4:[0-9]+]], [0 x i256]* %sub_[[X4]], i256* %subc_[[X4]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+\.T]]: //CHECK-NEXT: br label %store1 //CHECK-EMPTY: //CHECK-NEXT: store1: @@ -38,26 +38,33 @@ component main = SubCmps0A(2); //CHECK-NEXT: br label %store2 //CHECK-EMPTY: //CHECK-NEXT: store2: -//CHECK-NEXT: %3 = getelementptr [0 x i256], [0 x i256]* %sub_[[X4]], i32 0 -//CHECK-NEXT: call void @IsZero_0_run([0 x i256]* %sub_[[X4]]) -//CHECK-NEXT: br label %store3 +//CHECK-NEXT: %3 = load i256, i256* %subc_[[X4]], align 4 +//CHECK-NEXT: %call.fr_sub = call i256 @fr_sub(i256 %3, i256 1) +//CHECK-NEXT: %4 = getelementptr i256, i256* %subc_[[X4]], i32 0 +//CHECK-NEXT: store i256 %call.fr_sub, i256* %4, align 4 +//CHECK-NEXT: br label %fold_true3 //CHECK-EMPTY: -//CHECK-NEXT: store3: -//CHECK-NEXT: %4 = getelementptr i256, i256* %subfix_[[X4]], i32 0 -//CHECK-NEXT: %5 = load i256, i256* %4, align 4 -//CHECK-NEXT: %6 = getelementptr i256, i256* %fix_[[X3]], i32 0 -//CHECK-NEXT: store i256 %5, i256* %6, align 4 +//CHECK-NEXT: fold_true3: +//CHECK-NEXT: call void @llvm.donothing() +//CHECK-NEXT: call void @IsZero_0_run([0 x i256]* %sub_[[X4]]) //CHECK-NEXT: br label %store4 //CHECK-EMPTY: //CHECK-NEXT: store4: -//CHECK-NEXT: %7 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 -//CHECK-NEXT: %8 = load i256, i256* %7, align 4 -//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %8, i256 1) -//CHECK-NEXT: %9 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 -//CHECK-NEXT: store i256 %call.fr_add, i256* %9, align 4 -//CHECK-NEXT: br label %return5 +//CHECK-NEXT: %5 = getelementptr i256, i256* %subfix_[[X4]], i32 0 +//CHECK-NEXT: %6 = load i256, i256* %5, align 4 +//CHECK-NEXT: %7 = getelementptr i256, i256* %fix_[[X3]], i32 0 +//CHECK-NEXT: store i256 %6, i256* %7, align 4 +//CHECK-NEXT: br label %store5 +//CHECK-EMPTY: +//CHECK-NEXT: store5: +//CHECK-NEXT: %8 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: %9 = load i256, i256* %8, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %9, i256 1) +//CHECK-NEXT: %10 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 %call.fr_add, i256* %10, align 4 +//CHECK-NEXT: br label %return6 //CHECK-EMPTY: -//CHECK-NEXT: return5: +//CHECK-NEXT: return6: //CHECK-NEXT: ret void //CHECK-NEXT: } // diff --git a/circom/tests/subcmps/subcmps0B.circom b/circom/tests/subcmps/subcmps0B.circom index f858f60e8..c73f889ab 100644 --- a/circom/tests/subcmps/subcmps0B.circom +++ b/circom/tests/subcmps/subcmps0B.circom @@ -25,10 +25,10 @@ template SubCmps0B(n) { component main = SubCmps0B(2); -//CHECK-LABEL: define void @..generated..loop.body. -//CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %subfix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]], -//CHECK-SAME: i256* %subfix_[[X4:[0-9]+]], i256* %subfix_[[X5:[0-9]+]], [0 x i256]* %sub_[[X5]], i256* %subc_[[X5]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1]]: +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %subfix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]], i256* %subfix_[[X4:[0-9]+]], +//CHECK-SAME: i256* %subfix_[[X5:[0-9]+]], [0 x i256]* %sub_[[X5]], i256* %subc_[[X5]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+\.T]]: //CHECK-NEXT: br label %store1 //CHECK-EMPTY: //CHECK-NEXT: store1: @@ -39,33 +39,40 @@ component main = SubCmps0B(2); //CHECK-NEXT: br label %store2 //CHECK-EMPTY: //CHECK-NEXT: store2: -//CHECK-NEXT: %3 = getelementptr [0 x i256], [0 x i256]* %sub_[[X5]], i32 0 -//CHECK-NEXT: call void @IsZero_0_run([0 x i256]* %sub_[[X5]]) -//CHECK-NEXT: br label %store3 +//CHECK-NEXT: %3 = load i256, i256* %subc_[[X5]], align 4 +//CHECK-NEXT: %call.fr_sub = call i256 @fr_sub(i256 %3, i256 1) +//CHECK-NEXT: %4 = getelementptr i256, i256* %subc_[[X5]], i32 0 +//CHECK-NEXT: store i256 %call.fr_sub, i256* %4, align 4 +//CHECK-NEXT: br label %fold_true3 //CHECK-EMPTY: -//CHECK-NEXT: store3: -//CHECK-NEXT: %4 = getelementptr i256, i256* %subfix_[[X4]], i32 0 -//CHECK-NEXT: %5 = load i256, i256* %4, align 4 -//CHECK-NEXT: %6 = getelementptr i256, i256* %fix_[[X3]], i32 0 -//CHECK-NEXT: store i256 %5, i256* %6, align 4 +//CHECK-NEXT: fold_true3: +//CHECK-NEXT: call void @llvm.donothing() +//CHECK-NEXT: call void @IsZero_0_run([0 x i256]* %sub_[[X5]]) //CHECK-NEXT: br label %store4 //CHECK-EMPTY: //CHECK-NEXT: store4: -//CHECK-NEXT: %7 = getelementptr i256, i256* %subfix_[[X5]], i32 0 -//CHECK-NEXT: %8 = load i256, i256* %7, align 4 -//CHECK-NEXT: %9 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 -//CHECK-NEXT: store i256 %8, i256* %9, align 4 +//CHECK-NEXT: %5 = getelementptr i256, i256* %subfix_[[X4]], i32 0 +//CHECK-NEXT: %6 = load i256, i256* %5, align 4 +//CHECK-NEXT: %7 = getelementptr i256, i256* %fix_[[X3]], i32 0 +//CHECK-NEXT: store i256 %6, i256* %7, align 4 //CHECK-NEXT: br label %store5 //CHECK-EMPTY: //CHECK-NEXT: store5: -//CHECK-NEXT: %10 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 2 -//CHECK-NEXT: %11 = load i256, i256* %10, align 4 -//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %11, i256 1) -//CHECK-NEXT: %12 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 2 -//CHECK-NEXT: store i256 %call.fr_add, i256* %12, align 4 -//CHECK-NEXT: br label %return6 +//CHECK-NEXT: %8 = getelementptr i256, i256* %subfix_[[X5]], i32 0 +//CHECK-NEXT: %9 = load i256, i256* %8, align 4 +//CHECK-NEXT: %10 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 %9, i256* %10, align 4 +//CHECK-NEXT: br label %store6 +//CHECK-EMPTY: +//CHECK-NEXT: store6: +//CHECK-NEXT: %11 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 2 +//CHECK-NEXT: %12 = load i256, i256* %11, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %12, i256 1) +//CHECK-NEXT: %13 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 2 +//CHECK-NEXT: store i256 %call.fr_add, i256* %13, align 4 +//CHECK-NEXT: br label %return7 //CHECK-EMPTY: -//CHECK-NEXT: return6: +//CHECK-NEXT: return7: //CHECK-NEXT: ret void //CHECK-NEXT: } // diff --git a/circom/tests/subcmps/subcmps0C.circom b/circom/tests/subcmps/subcmps0C.circom index c62cdff92..ecf098e96 100644 --- a/circom/tests/subcmps/subcmps0C.circom +++ b/circom/tests/subcmps/subcmps0C.circom @@ -23,10 +23,10 @@ template SubCmps0C(n) { component main = SubCmps0C(2); -//CHECK-LABEL: define void @..generated..loop.body. -//CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %subfix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], -//CHECK-SAME: i256* %fix_[[X3:[0-9]+]], i256* %subfix_[[X4:[0-9]+]], [0 x i256]* %sub_[[X4]], i256* %subc_[[X4]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1]]: +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %subfix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]], +//CHECK-SAME: i256* %subfix_[[X4:[0-9]+]], [0 x i256]* %sub_[[X4]], i256* %subc_[[X4]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+\.T]]: //CHECK-NEXT: br label %store1 //CHECK-EMPTY: //CHECK-NEXT: store1: @@ -37,26 +37,33 @@ component main = SubCmps0C(2); //CHECK-NEXT: br label %store2 //CHECK-EMPTY: //CHECK-NEXT: store2: -//CHECK-NEXT: %3 = getelementptr [0 x i256], [0 x i256]* %sub_[[X4]], i32 0 -//CHECK-NEXT: call void @IsZero_0_run([0 x i256]* %sub_[[X4]]) -//CHECK-NEXT: br label %store3 +//CHECK-NEXT: %3 = load i256, i256* %subc_[[X4]], align 4 +//CHECK-NEXT: %call.fr_sub = call i256 @fr_sub(i256 %3, i256 1) +//CHECK-NEXT: %4 = getelementptr i256, i256* %subc_[[X4]], i32 0 +//CHECK-NEXT: store i256 %call.fr_sub, i256* %4, align 4 +//CHECK-NEXT: br label %fold_true3 //CHECK-EMPTY: -//CHECK-NEXT: store3: -//CHECK-NEXT: %4 = getelementptr i256, i256* %subfix_[[X4]], i32 0 -//CHECK-NEXT: %5 = load i256, i256* %4, align 4 -//CHECK-NEXT: %6 = getelementptr i256, i256* %fix_[[X3]], i32 0 -//CHECK-NEXT: store i256 %5, i256* %6, align 4 +//CHECK-NEXT: fold_true3: +//CHECK-NEXT: call void @llvm.donothing() +//CHECK-NEXT: call void @IsZero_0_run([0 x i256]* %sub_[[X4]]) //CHECK-NEXT: br label %store4 //CHECK-EMPTY: //CHECK-NEXT: store4: -//CHECK-NEXT: %7 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 -//CHECK-NEXT: %8 = load i256, i256* %7, align 4 -//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %8, i256 1) -//CHECK-NEXT: %9 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 -//CHECK-NEXT: store i256 %call.fr_add, i256* %9, align 4 -//CHECK-NEXT: br label %return5 +//CHECK-NEXT: %5 = getelementptr i256, i256* %subfix_[[X4]], i32 0 +//CHECK-NEXT: %6 = load i256, i256* %5, align 4 +//CHECK-NEXT: %7 = getelementptr i256, i256* %fix_[[X3]], i32 0 +//CHECK-NEXT: store i256 %6, i256* %7, align 4 +//CHECK-NEXT: br label %store5 +//CHECK-EMPTY: +//CHECK-NEXT: store5: +//CHECK-NEXT: %8 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: %9 = load i256, i256* %8, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %9, i256 1) +//CHECK-NEXT: %10 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 %call.fr_add, i256* %10, align 4 +//CHECK-NEXT: br label %return6 //CHECK-EMPTY: -//CHECK-NEXT: return5: +//CHECK-NEXT: return6: //CHECK-NEXT: ret void //CHECK-NEXT: } // diff --git a/circom/tests/subcmps/subcmps0D.circom b/circom/tests/subcmps/subcmps0D.circom index c2eeee5f5..c9dee689b 100644 --- a/circom/tests/subcmps/subcmps0D.circom +++ b/circom/tests/subcmps/subcmps0D.circom @@ -24,10 +24,10 @@ template SubCmps0D(n) { component main = SubCmps0D(3); -//CHECK-LABEL: define void @..generated..loop.body. -//CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %subfix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %subfix_[[X3:[0-9]+]], -//CHECK-SAME: i256* %fix_[[X4:[0-9]+]], i256* %fix_[[X5:[0-9]+]], i256* %subfix_[[X6:[0-9]+]], [0 x i256]* %sub_[[X6]], i256* %subc_[[X6]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1]]: +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.F\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %subfix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %subfix_[[X3:[0-9]+]], i256* %fix_[[X4:[0-9]+]], +//CHECK-SAME: i256* %fix_[[X5:[0-9]+]], i256* %subfix_[[X6:[0-9]+]], [0 x i256]* %sub_[[X6]], i256* %subc_[[X6]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+\.F\.T]]: //CHECK-NEXT: br label %store1 //CHECK-EMPTY: //CHECK-NEXT: store1: @@ -38,38 +38,50 @@ component main = SubCmps0D(3); //CHECK-NEXT: br label %store2 //CHECK-EMPTY: //CHECK-NEXT: store2: -//CHECK-NEXT: %3 = getelementptr [0 x i256], [0 x i256]* %sub_[[X6]], i32 0 -//CHECK-NEXT: call void @Add_0_run([0 x i256]* %sub_[[X6]]) -//CHECK-NEXT: br label %store3 +//CHECK-NEXT: %3 = load i256, i256* %subc_[[X6]], align 4 +//CHECK-NEXT: %call.fr_sub = call i256 @fr_sub(i256 %3, i256 1) +//CHECK-NEXT: %4 = getelementptr i256, i256* %subc_[[X6]], i32 0 +//CHECK-NEXT: store i256 %call.fr_sub, i256* %4, align 4 +//CHECK-NEXT: br label %fold_false3 //CHECK-EMPTY: -//CHECK-NEXT: store3: -//CHECK-NEXT: %4 = getelementptr i256, i256* %fix_[[X4]], i32 0 -//CHECK-NEXT: %5 = load i256, i256* %4, align 4 -//CHECK-NEXT: %6 = getelementptr i256, i256* %subfix_[[X3]], i32 0 -//CHECK-NEXT: store i256 %5, i256* %6, align 4 +//CHECK-NEXT: fold_false3: //CHECK-NEXT: br label %store4 //CHECK-EMPTY: //CHECK-NEXT: store4: -//CHECK-NEXT: %7 = getelementptr [0 x i256], [0 x i256]* %sub_[[X6]], i32 0 -//CHECK-NEXT: call void @Add_0_run([0 x i256]* %sub_[[X6]]) +//CHECK-NEXT: %5 = getelementptr i256, i256* %fix_[[X4]], i32 0 +//CHECK-NEXT: %6 = load i256, i256* %5, align 4 +//CHECK-NEXT: %7 = getelementptr i256, i256* %subfix_[[X3]], i32 0 +//CHECK-NEXT: store i256 %6, i256* %7, align 4 //CHECK-NEXT: br label %store5 //CHECK-EMPTY: //CHECK-NEXT: store5: -//CHECK-NEXT: %8 = getelementptr i256, i256* %subfix_[[X6]], i32 0 -//CHECK-NEXT: %9 = load i256, i256* %8, align 4 -//CHECK-NEXT: %10 = getelementptr i256, i256* %fix_[[X5]], i32 0 -//CHECK-NEXT: store i256 %9, i256* %10, align 4 -//CHECK-NEXT: br label %store6 -//CHECK-EMPTY: -//CHECK-NEXT: store6: -//CHECK-NEXT: %11 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 -//CHECK-NEXT: %12 = load i256, i256* %11, align 4 -//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %12, i256 1) +//CHECK-NEXT: %8 = load i256, i256* %subc_[[X6]], align 4 +//CHECK-NEXT: %call.fr_sub1 = call i256 @fr_sub(i256 %8, i256 1) +//CHECK-NEXT: %9 = getelementptr i256, i256* %subc_[[X6]], i32 0 +//CHECK-NEXT: store i256 %call.fr_sub1, i256* %9, align 4 +//CHECK-NEXT: br label %fold_true6 +//CHECK-EMPTY: +//CHECK-NEXT: fold_true6: +//CHECK-NEXT: call void @llvm.donothing() +//CHECK-NEXT: call void @Add_0_run([0 x i256]* %sub_[[X6]]) +//CHECK-NEXT: br label %store7 +//CHECK-EMPTY: +//CHECK-NEXT: store7: +//CHECK-NEXT: %10 = getelementptr i256, i256* %subfix_[[X6]], i32 0 +//CHECK-NEXT: %11 = load i256, i256* %10, align 4 +//CHECK-NEXT: %12 = getelementptr i256, i256* %fix_[[X5]], i32 0 +//CHECK-NEXT: store i256 %11, i256* %12, align 4 +//CHECK-NEXT: br label %store8 +//CHECK-EMPTY: +//CHECK-NEXT: store8: //CHECK-NEXT: %13 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 -//CHECK-NEXT: store i256 %call.fr_add, i256* %13, align 4 -//CHECK-NEXT: br label %return7 +//CHECK-NEXT: %14 = load i256, i256* %13, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %14, i256 1) +//CHECK-NEXT: %15 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 %call.fr_add, i256* %15, align 4 +//CHECK-NEXT: br label %return9 //CHECK-EMPTY: -//CHECK-NEXT: return7: +//CHECK-NEXT: return9: //CHECK-NEXT: ret void //CHECK-NEXT: } // diff --git a/circom/tests/subcmps/subcmps1.circom b/circom/tests/subcmps/subcmps1.circom index 883d3d290..a38ddc024 100644 --- a/circom/tests/subcmps/subcmps1.circom +++ b/circom/tests/subcmps/subcmps1.circom @@ -34,10 +34,10 @@ component main = SubCmps1(3); // %lvars = [ n, i ] // %subcmps = [ IsZero[0]{signals=[out,in,inv]}, IsZero[1]{SAME} ] // -//CHECK-LABEL: define void @..generated..loop.body. -//CHECK-SAME: [[$F_ID:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %subfix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], -//CHECK-SAME: i256* %fix_[[X3:[0-9]+]], i256* %subfix_[[X4:[0-9]+]], [0 x i256]* %sub_[[X4]], i256* %subc_[[X4]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID]]: +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %subfix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]], +//CHECK-SAME: i256* %subfix_[[X4:[0-9]+]], [0 x i256]* %sub_[[X4]], i256* %subc_[[X4]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID:[0-9]+\.T]]: //CHECK-NEXT: br label %store1 //CHECK-EMPTY: //CHECK-NEXT: store1: @@ -51,29 +51,36 @@ component main = SubCmps1(3); //CHECK-NEXT: br label %store2 //CHECK-EMPTY: //CHECK-NEXT: store2: -//CHECK-NEXT: %4 = getelementptr [0 x i256], [0 x i256]* %sub_[[X4]], i32 0 -//CHECK-NEXT: call void @IsZero_0_run([0 x i256]* %sub_[[X4]]) -//CHECK-NEXT: br label %store3 +//CHECK-NEXT: %4 = load i256, i256* %subc_[[X4]], align 4 +//CHECK-NEXT: %call.fr_sub = call i256 @fr_sub(i256 %4, i256 1) +//CHECK-NEXT: %5 = getelementptr i256, i256* %subc_[[X4]], i32 0 +//CHECK-NEXT: store i256 %call.fr_sub, i256* %5, align 4 +//CHECK-NEXT: br label %fold_true3 //CHECK-EMPTY: -//CHECK-NEXT: store3: -//CHECK-NEXT: %5 = getelementptr i256, i256* %subfix_[[X4]], i32 0 -//CHECK-NEXT: %6 = load i256, i256* %5, align 4 -//CHECK-NEXT: %7 = getelementptr i256, i256* %fix_[[X3]], i32 0 -//CHECK-NEXT: store i256 %6, i256* %7, align 4 -//CHECK-NEXT: %8 = load i256, i256* %7, align 4 -//CHECK-NEXT: %constraint1 = alloca i1, align 1 -//CHECK-NEXT: call void @__constraint_values(i256 %6, i256 %8, i1* %constraint1) +//CHECK-NEXT: fold_true3: +//CHECK-NEXT: call void @llvm.donothing() +//CHECK-NEXT: call void @IsZero_0_run([0 x i256]* %sub_[[X4]]) //CHECK-NEXT: br label %store4 //CHECK-EMPTY: //CHECK-NEXT: store4: -//CHECK-NEXT: %9 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 -//CHECK-NEXT: %10 = load i256, i256* %9, align 4 -//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %10, i256 1) -//CHECK-NEXT: %11 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 -//CHECK-NEXT: store i256 %call.fr_add, i256* %11, align 4 -//CHECK-NEXT: br label %return5 +//CHECK-NEXT: %6 = getelementptr i256, i256* %subfix_[[X4]], i32 0 +//CHECK-NEXT: %7 = load i256, i256* %6, align 4 +//CHECK-NEXT: %8 = getelementptr i256, i256* %fix_[[X3]], i32 0 +//CHECK-NEXT: store i256 %7, i256* %8, align 4 +//CHECK-NEXT: %9 = load i256, i256* %8, align 4 +//CHECK-NEXT: %constraint1 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %7, i256 %9, i1* %constraint1) +//CHECK-NEXT: br label %store5 +//CHECK-EMPTY: +//CHECK-NEXT: store5: +//CHECK-NEXT: %10 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: %11 = load i256, i256* %10, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %11, i256 1) +//CHECK-NEXT: %12 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 %call.fr_add, i256* %12, align 4 +//CHECK-NEXT: br label %return6 //CHECK-EMPTY: -//CHECK-NEXT: return5: +//CHECK-NEXT: return6: //CHECK-NEXT: ret void //CHECK-NEXT: } // diff --git a/circom/tests/subcmps/subcmps2.circom b/circom/tests/subcmps/subcmps2.circom index 23f932c8e..faf7d0dbf 100644 --- a/circom/tests/subcmps/subcmps2.circom +++ b/circom/tests/subcmps/subcmps2.circom @@ -1,7 +1,6 @@ pragma circom 2.0.6; // REQUIRES: circom // RUN: rm -rf %t && mkdir %t && %circom --llvm -o %t %s | sed -n 's/.*Written successfully:.* \(.*\)/\1/p' | xargs cat | FileCheck %s --enable-var-scope -// XFAIL:.* // pending https://veridise.atlassian.net/browse/VAN-670 template Sum(n) { signal input inp[n]; @@ -35,226 +34,248 @@ template Caller() { component main = Caller(); -//CHECK-LABEL: define void @Caller_{{[0-9]+}}_run -//CHECK-SAME: ([0 x i256]* %0) -//CHECK: %[[CALL_VAL:call\.nop_[0-3]]] = call i256 @nop_{{[0-3]}}(i256* %6) -//CHECK: %[[SUBCMP_PTR:.*]] = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 {{[0-3]}} -//CHECK: %[[SUBCMP:.*]] = load [0 x i256]*, [0 x i256]** %[[SUBCMP_PTR]] -//CHECK: %[[SUBCMP_INP:.*]] = getelementptr [0 x i256], [0 x i256]* %[[SUBCMP]], i32 0, i32 {{[1-4]}} -//CHECK: store i256 %[[CALL_VAL]], i256* %[[SUBCMP_INP]] - -/* -define void @Sum_0_build({ [0 x i256]*, i32 }* %0) !dbg !9 { -main: - %1 = alloca [5 x i256], align 8 - %2 = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 - store i32 4, i32* %2, align 4 - %3 = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 0 - %4 = bitcast [5 x i256]* %1 to [0 x i256]* - store [0 x i256]* %4, [0 x i256]** %3, align 8 - ret void -} - -define void @Sum_0_run([0 x i256]* %0) !dbg !11 { -prelude: - %lvars = alloca [3 x i256], align 8 - %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 - br label %store1 - -store1: - %1 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 0 - store i256 4, i256* %1, align 4 - br label %store2 - -store2: - %2 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 1 - store i256 0, i256* %2, align 4 - br label %store3 - -store3: - %3 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 2 - store i256 0, i256* %3, align 4 - br label %unrolled_loop4 - -unrolled_loop4: - %4 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 1 - %5 = load i256, i256* %4, align 4 - %6 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 1 - %7 = load i256, i256* %6, align 4 - %call.fr_add = call i256 @fr_add(i256 %5, i256 %7) - %8 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 1 - store i256 %call.fr_add, i256* %8, align 4 - %9 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 2 - store i256 1, i256* %9, align 4 - %10 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 1 - %11 = load i256, i256* %10, align 4 - %12 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 2 - %13 = load i256, i256* %12, align 4 - %call.fr_add1 = call i256 @fr_add(i256 %11, i256 %13) - %14 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 1 - store i256 %call.fr_add1, i256* %14, align 4 - %15 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 2 - store i256 2, i256* %15, align 4 - %16 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 1 - %17 = load i256, i256* %16, align 4 - %18 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 3 - %19 = load i256, i256* %18, align 4 - %call.fr_add2 = call i256 @fr_add(i256 %17, i256 %19) - %20 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 1 - store i256 %call.fr_add2, i256* %20, align 4 - %21 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 2 - store i256 3, i256* %21, align 4 - %22 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 1 - %23 = load i256, i256* %22, align 4 - %24 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 4 - %25 = load i256, i256* %24, align 4 - %call.fr_add3 = call i256 @fr_add(i256 %23, i256 %25) - %26 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 1 - store i256 %call.fr_add3, i256* %26, align 4 - %27 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 2 - store i256 4, i256* %27, align 4 - br label %store5 - -store5: - %28 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 1 - %29 = load i256, i256* %28, align 4 - %30 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 0 - store i256 %29, i256* %30, align 4 - %31 = load i256, i256* %30, align 4 - %constraint = alloca i1, align 1 - call void @__constraint_values(i256 %29, i256 %31, i1* %constraint) - br label %prologue - -prologue: - ret void -} - -define void @Caller_1_build({ [0 x i256]*, i32 }* %0) !dbg !18 { -main: - %1 = alloca [5 x i256], align 8 - %2 = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 - store i32 4, i32* %2, align 4 - %3 = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 0 - %4 = bitcast [5 x i256]* %1 to [0 x i256]* - store [0 x i256]* %4, [0 x i256]** %3, align 8 - ret void -} - -define void @Caller_1_run([0 x i256]* %0) !dbg !20 { -prelude: - %lvars = alloca [1 x i256], align 8 - %subcmps = alloca [1 x { [0 x i256]*, i32 }], align 8 - br label %create_cmp1 - -create_cmp1: - %1 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0 - call void @Sum_0_build({ [0 x i256]*, i32 }* %1) - br label %store2 - -store2: - %2 = getelementptr [1 x i256], [1 x i256]* %lvars, i32 0, i32 0 - store i256 0, i256* %2, align 4 - br label %unrolled_loop3 - -unrolled_loop3: - %nop_0_arena = alloca [1 x i256], align 8 - %3 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 1 - %4 = load i256, i256* %3, align 4 - %5 = getelementptr [1 x i256], [1 x i256]* %nop_0_arena, i32 0, i32 0 - store i256 %4, i256* %5, align 4 - %6 = bitcast [1 x i256]* %nop_0_arena to i256* - %call.nop_0 = call i256 @nop_0(i256* %6) - %7 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 - %8 = load [0 x i256]*, [0 x i256]** %7, align 8 - %9 = getelementptr [0 x i256], [0 x i256]* %8, i32 0, i32 1 - store i256 %call.nop_0, i256* %9, align 4 - %10 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 1 - %load.subcmp.counter = load i32, i32* %10, align 4 - %decrement.counter = sub i32 %load.subcmp.counter, 1 - store i32 %decrement.counter, i32* %10, align 4 - %11 = load i256, i256* %9, align 4 - %constraint = alloca i1, align 1 - call void @__constraint_values(i256 %call.nop_0, i256 %11, i1* %constraint) - %12 = getelementptr [1 x i256], [1 x i256]* %lvars, i32 0, i32 0 - store i256 1, i256* %12, align 4 - %nop_0_arena1 = alloca [1 x i256], align 8 - %13 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 2 - %14 = load i256, i256* %13, align 4 - %15 = getelementptr [1 x i256], [1 x i256]* %nop_0_arena1, i32 0, i32 0 - store i256 %14, i256* %15, align 4 - %16 = bitcast [1 x i256]* %nop_0_arena1 to i256* - %call.nop_02 = call i256 @nop_0(i256* %16) - %17 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 - %18 = load [0 x i256]*, [0 x i256]** %17, align 8 - %19 = getelementptr [0 x i256], [0 x i256]* %18, i32 0, i32 2 - store i256 %call.nop_02, i256* %19, align 4 - %20 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 1 - %load.subcmp.counter3 = load i32, i32* %20, align 4 - %decrement.counter4 = sub i32 %load.subcmp.counter3, 1 - store i32 %decrement.counter4, i32* %20, align 4 - %21 = load i256, i256* %19, align 4 - %constraint5 = alloca i1, align 1 - call void @__constraint_values(i256 %call.nop_02, i256 %21, i1* %constraint5) - %22 = getelementptr [1 x i256], [1 x i256]* %lvars, i32 0, i32 0 - store i256 2, i256* %22, align 4 - %nop_0_arena6 = alloca [1 x i256], align 8 - %23 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 3 - %24 = load i256, i256* %23, align 4 - %25 = getelementptr [1 x i256], [1 x i256]* %nop_0_arena6, i32 0, i32 0 - store i256 %24, i256* %25, align 4 - %26 = bitcast [1 x i256]* %nop_0_arena6 to i256* - %call.nop_07 = call i256 @nop_0(i256* %26) - %27 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 - %28 = load [0 x i256]*, [0 x i256]** %27, align 8 - %29 = getelementptr [0 x i256], [0 x i256]* %28, i32 0, i32 3 - store i256 %call.nop_07, i256* %29, align 4 - %30 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 1 - %load.subcmp.counter8 = load i32, i32* %30, align 4 - %decrement.counter9 = sub i32 %load.subcmp.counter8, 1 - store i32 %decrement.counter9, i32* %30, align 4 - %31 = load i256, i256* %29, align 4 - %constraint10 = alloca i1, align 1 - call void @__constraint_values(i256 %call.nop_07, i256 %31, i1* %constraint10) - %32 = getelementptr [1 x i256], [1 x i256]* %lvars, i32 0, i32 0 - store i256 3, i256* %32, align 4 - %nop_0_arena11 = alloca [1 x i256], align 8 - %33 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 4 - %34 = load i256, i256* %33, align 4 - %35 = getelementptr [1 x i256], [1 x i256]* %nop_0_arena11, i32 0, i32 0 - store i256 %34, i256* %35, align 4 - %36 = bitcast [1 x i256]* %nop_0_arena11 to i256* - %call.nop_012 = call i256 @nop_0(i256* %36) - %37 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 - %38 = load [0 x i256]*, [0 x i256]** %37, align 8 - %39 = getelementptr [0 x i256], [0 x i256]* %38, i32 0, i32 4 - store i256 %call.nop_012, i256* %39, align 4 - %40 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 1 - %load.subcmp.counter13 = load i32, i32* %40, align 4 - %decrement.counter14 = sub i32 %load.subcmp.counter13, 1 - store i32 %decrement.counter14, i32* %40, align 4 - %41 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 - %42 = load [0 x i256]*, [0 x i256]** %41, align 8 - call void @Sum_0_run([0 x i256]* %42) - %43 = load i256, i256* %39, align 4 - %constraint15 = alloca i1, align 1 - call void @__constraint_values(i256 %call.nop_012, i256 %43, i1* %constraint15) - %44 = getelementptr [1 x i256], [1 x i256]* %lvars, i32 0, i32 0 - store i256 4, i256* %44, align 4 - br label %store4 - -store4: - %45 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 - %46 = load [0 x i256]*, [0 x i256]** %45, align 8 - %47 = getelementptr [0 x i256], [0 x i256]* %46, i32 0, i32 0 - %48 = load i256, i256* %47, align 4 - %49 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 0 - store i256 %48, i256* %49, align 4 - %50 = load i256, i256* %49, align 4 - %constraint16 = alloca i1, align 1 - call void @__constraint_values(i256 %48, i256 %50, i1* %constraint16) - br label %prologue - -prologue: - ret void -} -*/ +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+]]: +//CHECK-NEXT: br label %store1 +//CHECK-EMPTY: +//CHECK-NEXT: store1: +//CHECK-NEXT: %0 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: %1 = load i256, i256* %0, align 4 +//CHECK-NEXT: %2 = getelementptr i256, i256* %fix_[[X1]], i32 0 +//CHECK-NEXT: %3 = load i256, i256* %2, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %1, i256 %3) +//CHECK-NEXT: %4 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 %call.fr_add, i256* %4, align 4 +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %5 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 2 +//CHECK-NEXT: %6 = load i256, i256* %5, align 4 +//CHECK-NEXT: %call.fr_add1 = call i256 @fr_add(i256 %6, i256 1) +//CHECK-NEXT: %7 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 2 +//CHECK-NEXT: store i256 %call.fr_add1, i256* %7, align 4 +//CHECK-NEXT: br label %return3 +//CHECK-EMPTY: +//CHECK-NEXT: return3: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.F}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %subfix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], [0 x i256]* %sub_[[X3:[0-9]+]], i256* %subc_[[X4:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_2:[0-9]+\.F]]: +//CHECK-NEXT: br label %call1 +//CHECK-EMPTY: +//CHECK-NEXT: call1: +//CHECK-NEXT: %nop_0_arena = alloca [1 x i256], align 8 +//CHECK-NEXT: %0 = getelementptr [1 x i256], [1 x i256]* %nop_0_arena, i32 0, i32 0 +//CHECK-NEXT: %1 = getelementptr i256, i256* %fix_[[X2]], i32 0 +//CHECK-NEXT: %2 = load i256, i256* %1, align 4 +//CHECK-NEXT: store i256 %2, i256* %0, align 4 +//CHECK-NEXT: %3 = bitcast [1 x i256]* %nop_0_arena to i256* +//CHECK-NEXT: %call.nop_0 = call i256 @nop_0(i256* %3) +//CHECK-NEXT: %4 = getelementptr i256, i256* %subfix_[[X1]], i32 0 +//CHECK-NEXT: store i256 %call.nop_0, i256* %4, align 4 +//CHECK-NEXT: %5 = load i256, i256* %4, align 4 +//CHECK-NEXT: %constraint = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %call.nop_0, i256 %5, i1* %constraint) +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %6 = load i256, i256* %subc_[[X4]], align 4 +//CHECK-NEXT: %call.fr_sub = call i256 @fr_sub(i256 %6, i256 1) +//CHECK-NEXT: %7 = getelementptr i256, i256* %subc_[[X4]], i32 0 +//CHECK-NEXT: store i256 %call.fr_sub, i256* %7, align 4 +//CHECK-NEXT: br label %fold_false3 +//CHECK-EMPTY: +//CHECK-NEXT: fold_false3: +//CHECK-NEXT: br label %store4 +//CHECK-EMPTY: +//CHECK-NEXT: store4: +//CHECK-NEXT: %8 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: %9 = load i256, i256* %8, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %9, i256 1) +//CHECK-NEXT: %10 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: store i256 %call.fr_add, i256* %10, align 4 +//CHECK-NEXT: br label %return5 +//CHECK-EMPTY: +//CHECK-NEXT: return5: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %subfix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], [0 x i256]* %sub_[[X3:[0-9]+]], i256* %subc_[[X4:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_3:[0-9]+\.T]]: +//CHECK-NEXT: br label %call1 +//CHECK-EMPTY: +//CHECK-NEXT: call1: +//CHECK-NEXT: %nop_0_arena = alloca [1 x i256], align 8 +//CHECK-NEXT: %0 = getelementptr [1 x i256], [1 x i256]* %nop_0_arena, i32 0, i32 0 +//CHECK-NEXT: %1 = getelementptr i256, i256* %fix_[[X2]], i32 0 +//CHECK-NEXT: %2 = load i256, i256* %1, align 4 +//CHECK-NEXT: store i256 %2, i256* %0, align 4 +//CHECK-NEXT: %3 = bitcast [1 x i256]* %nop_0_arena to i256* +//CHECK-NEXT: %call.nop_0 = call i256 @nop_0(i256* %3) +//CHECK-NEXT: %4 = getelementptr i256, i256* %subfix_[[X1]], i32 0 +//CHECK-NEXT: store i256 %call.nop_0, i256* %4, align 4 +//CHECK-NEXT: %5 = load i256, i256* %4, align 4 +//CHECK-NEXT: %constraint = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %call.nop_0, i256 %5, i1* %constraint) +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %6 = load i256, i256* %subc_[[X4]], align 4 +//CHECK-NEXT: %call.fr_sub = call i256 @fr_sub(i256 %6, i256 1) +//CHECK-NEXT: %7 = getelementptr i256, i256* %subc_[[X4]], i32 0 +//CHECK-NEXT: store i256 %call.fr_sub, i256* %7, align 4 +//CHECK-NEXT: br label %fold_true3 +//CHECK-EMPTY: +//CHECK-NEXT: fold_true3: +//CHECK-NEXT: call void @llvm.donothing() +//CHECK-NEXT: call void @Sum_0_run([0 x i256]* %sub_[[X3]]) +//CHECK-NEXT: br label %store4 +//CHECK-EMPTY: +//CHECK-NEXT: store4: +//CHECK-NEXT: %8 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: %9 = load i256, i256* %8, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %9, i256 1) +//CHECK-NEXT: %10 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: store i256 %call.fr_add, i256* %10, align 4 +//CHECK-NEXT: br label %return5 +//CHECK-EMPTY: +//CHECK-NEXT: return5: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @Sum_0_run([0 x i256]* %0){{.*}} { +//CHECK-NEXT: prelude: +//CHECK-NEXT: %lvars = alloca [3 x i256], align 8 +//CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 +//CHECK-NEXT: br label %store1 +//CHECK-EMPTY: +//CHECK-NEXT: store1: +//CHECK-NEXT: %1 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: store i256 4, i256* %1, align 4 +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %2 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 0, i256* %2, align 4 +//CHECK-NEXT: br label %store3 +//CHECK-EMPTY: +//CHECK-NEXT: store3: +//CHECK-NEXT: %3 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 2 +//CHECK-NEXT: store i256 0, i256* %3, align 4 +//CHECK-NEXT: br label %unrolled_loop4 +//CHECK-EMPTY: +//CHECK-NEXT: unrolled_loop4: +//CHECK-NEXT: %4 = bitcast [3 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %5 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 1 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %4, [0 x i256]* %0, i256* %5) +//CHECK-NEXT: %6 = bitcast [3 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %7 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 2 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %6, [0 x i256]* %0, i256* %7) +//CHECK-NEXT: %8 = bitcast [3 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %9 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 3 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %8, [0 x i256]* %0, i256* %9) +//CHECK-NEXT: %10 = bitcast [3 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %11 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 4 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %10, [0 x i256]* %0, i256* %11) +//CHECK-NEXT: br label %store5 +//CHECK-EMPTY: +//CHECK-NEXT: store5: +//CHECK-NEXT: %12 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: %13 = load i256, i256* %12, align 4 +//CHECK-NEXT: %14 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 0 +//CHECK-NEXT: store i256 %13, i256* %14, align 4 +//CHECK-NEXT: %15 = load i256, i256* %14, align 4 +//CHECK-NEXT: %constraint = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %13, i256 %15, i1* %constraint) +//CHECK-NEXT: br label %prologue +//CHECK-EMPTY: +//CHECK-NEXT: prologue: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @Caller_1_run([0 x i256]* %0){{.*}} { +//CHECK-NEXT: prelude: +//CHECK-NEXT: %lvars = alloca [1 x i256], align 8 +//CHECK-NEXT: %subcmps = alloca [1 x { [0 x i256]*, i32 }], align 8 +//CHECK-NEXT: br label %create_cmp1 +//CHECK-EMPTY: +//CHECK-NEXT: create_cmp1: +//CHECK-NEXT: %1 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0 +//CHECK-NEXT: call void @Sum_0_build({ [0 x i256]*, i32 }* %1) +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %2 = getelementptr [1 x i256], [1 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: store i256 0, i256* %2, align 4 +//CHECK-NEXT: br label %unrolled_loop3 +//CHECK-EMPTY: +//CHECK-NEXT: unrolled_loop3: +//CHECK-NEXT: %3 = bitcast [1 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %4 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %5 = load [0 x i256]*, [0 x i256]** %4, align 8 +//CHECK-NEXT: %6 = getelementptr [0 x i256], [0 x i256]* %5, i32 0 +//CHECK-NEXT: %7 = getelementptr [0 x i256], [0 x i256]* %6, i32 0, i256 1 +//CHECK-NEXT: %8 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 1 +//CHECK-NEXT: %9 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %10 = load [0 x i256]*, [0 x i256]** %9, align 8 +//CHECK-NEXT: %11 = getelementptr [0 x i256], [0 x i256]* %10, i32 0 +//CHECK-NEXT: %12 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 1 +//CHECK-NEXT: %13 = bitcast i32* %12 to i256* +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %3, [0 x i256]* %0, i256* %7, i256* %8, [0 x i256]* %11, i256* %13) +//CHECK-NEXT: %14 = bitcast [1 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %15 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %16 = load [0 x i256]*, [0 x i256]** %15, align 8 +//CHECK-NEXT: %17 = getelementptr [0 x i256], [0 x i256]* %16, i32 0 +//CHECK-NEXT: %18 = getelementptr [0 x i256], [0 x i256]* %17, i32 0, i256 2 +//CHECK-NEXT: %19 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 2 +//CHECK-NEXT: %20 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %21 = load [0 x i256]*, [0 x i256]** %20, align 8 +//CHECK-NEXT: %22 = getelementptr [0 x i256], [0 x i256]* %21, i32 0 +//CHECK-NEXT: %23 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 1 +//CHECK-NEXT: %24 = bitcast i32* %23 to i256* +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %14, [0 x i256]* %0, i256* %18, i256* %19, [0 x i256]* %22, i256* %24) +//CHECK-NEXT: %25 = bitcast [1 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %26 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %27 = load [0 x i256]*, [0 x i256]** %26, align 8 +//CHECK-NEXT: %28 = getelementptr [0 x i256], [0 x i256]* %27, i32 0 +//CHECK-NEXT: %29 = getelementptr [0 x i256], [0 x i256]* %28, i32 0, i256 3 +//CHECK-NEXT: %30 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 3 +//CHECK-NEXT: %31 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %32 = load [0 x i256]*, [0 x i256]** %31, align 8 +//CHECK-NEXT: %33 = getelementptr [0 x i256], [0 x i256]* %32, i32 0 +//CHECK-NEXT: %34 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 1 +//CHECK-NEXT: %35 = bitcast i32* %34 to i256* +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %25, [0 x i256]* %0, i256* %29, i256* %30, [0 x i256]* %33, i256* %35) +//CHECK-NEXT: %36 = bitcast [1 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %37 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %38 = load [0 x i256]*, [0 x i256]** %37, align 8 +//CHECK-NEXT: %39 = getelementptr [0 x i256], [0 x i256]* %38, i32 0 +//CHECK-NEXT: %40 = getelementptr [0 x i256], [0 x i256]* %39, i32 0, i256 4 +//CHECK-NEXT: %41 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 4 +//CHECK-NEXT: %42 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %43 = load [0 x i256]*, [0 x i256]** %42, align 8 +//CHECK-NEXT: %44 = getelementptr [0 x i256], [0 x i256]* %43, i32 0 +//CHECK-NEXT: %45 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 1 +//CHECK-NEXT: %46 = bitcast i32* %45 to i256* +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_3]]([0 x i256]* %36, [0 x i256]* %0, i256* %40, i256* %41, [0 x i256]* %44, i256* %46) +//CHECK-NEXT: br label %store4 +//CHECK-EMPTY: +//CHECK-NEXT: store4: +//CHECK-NEXT: %47 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %48 = load [0 x i256]*, [0 x i256]** %47, align 8 +//CHECK-NEXT: %49 = getelementptr [0 x i256], [0 x i256]* %48, i32 0, i32 0 +//CHECK-NEXT: %50 = load i256, i256* %49, align 4 +//CHECK-NEXT: %51 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 0 +//CHECK-NEXT: store i256 %50, i256* %51, align 4 +//CHECK-NEXT: %52 = load i256, i256* %51, align 4 +//CHECK-NEXT: %constraint = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %50, i256 %52, i1* %constraint) +//CHECK-NEXT: br label %prologue +//CHECK-EMPTY: +//CHECK-NEXT: prologue: +//CHECK-NEXT: ret void +//CHECK-NEXT: } diff --git a/circom/tests/subcmps/subcmps3.circom b/circom/tests/subcmps/subcmps3.circom new file mode 100644 index 000000000..63eac590b --- /dev/null +++ b/circom/tests/subcmps/subcmps3.circom @@ -0,0 +1,231 @@ +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 --enable-var-scope + +template Sum(n) { + signal input inp[n]; + signal output outp; + + var s = 0; + + for (var i = 0; i < n; i++) { + s += inp[i]; + } + + outp <== s; +} + +template SubCmps3() { + signal input inp[4]; + signal output outp; + + component s = Sum(4); + + for (var i = 0; i < 4; i++) { + s.inp[i] <== inp[i]; + if (i == 3) { + outp <== s.outp; + } + } +} + +component main = SubCmps3(); + +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+]]: +//CHECK-NEXT: br label %store1 +//CHECK-EMPTY: +//CHECK-NEXT: store1: +//CHECK-NEXT: %0 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: %1 = load i256, i256* %0, align 4 +//CHECK-NEXT: %2 = getelementptr i256, i256* %fix_[[X1]], i32 0 +//CHECK-NEXT: %3 = load i256, i256* %2, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %1, i256 %3) +//CHECK-NEXT: %4 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 %call.fr_add, i256* %4, align 4 +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %5 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 2 +//CHECK-NEXT: %6 = load i256, i256* %5, align 4 +//CHECK-NEXT: %call.fr_add1 = call i256 @fr_add(i256 %6, i256 1) +//CHECK-NEXT: %7 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 2 +//CHECK-NEXT: store i256 %call.fr_add1, i256* %7, align 4 +//CHECK-NEXT: br label %return3 +//CHECK-EMPTY: +//CHECK-NEXT: return3: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.F}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_2:[0-9]+\.F]]: +//CHECK-NEXT: br label %store1 +//CHECK-EMPTY: +//CHECK-NEXT: store1: +//CHECK-NEXT: %0 = getelementptr i256, i256* %fix_[[X2]], i32 0 +//CHECK-NEXT: %1 = load i256, i256* %0, align 4 +//CHECK-NEXT: %2 = getelementptr i256, i256* %fix_[[X1]], i32 0 +//CHECK-NEXT: store i256 %1, i256* %2, align 4 +//CHECK-NEXT: %3 = load i256, i256* %2, align 4 +//CHECK-NEXT: %constraint = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %1, i256 %3, i1* %constraint) +//CHECK-NEXT: br label %fold_false2 +//CHECK-EMPTY: +//CHECK-NEXT: fold_false2: +//CHECK-NEXT: br label %store3 +//CHECK-EMPTY: +//CHECK-NEXT: store3: +//CHECK-NEXT: %4 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: %5 = load i256, i256* %4, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %5, i256 1) +//CHECK-NEXT: %6 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: store i256 %call.fr_add, i256* %6, align 4 +//CHECK-NEXT: br label %return4 +//CHECK-EMPTY: +//CHECK-NEXT: return4: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_3:[0-9]+\.T]]: +//CHECK-NEXT: br label %store1 +//CHECK-EMPTY: +//CHECK-NEXT: store1: +//CHECK-NEXT: %0 = getelementptr i256, i256* %fix_[[X2]], i32 0 +//CHECK-NEXT: %1 = load i256, i256* %0, align 4 +//CHECK-NEXT: %2 = getelementptr i256, i256* %fix_[[X1]], i32 0 +//CHECK-NEXT: store i256 %1, i256* %2, align 4 +//CHECK-NEXT: %3 = load i256, i256* %2, align 4 +//CHECK-NEXT: %constraint = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %1, i256 %3, i1* %constraint) +//CHECK-NEXT: br label %fold_true2 +//CHECK-EMPTY: +//CHECK-NEXT: fold_true2: +//CHECK-NEXT: %4 = getelementptr i256, i256* %fix_[[X3]], i32 0 +//CHECK-NEXT: %5 = load i256, i256* %4, align 4 +//CHECK-NEXT: %6 = getelementptr [0 x i256], [0 x i256]* %signals, i32 0, i32 0 +//CHECK-NEXT: store i256 %5, i256* %6, align 4 +//CHECK-NEXT: %7 = load i256, i256* %6, align 4 +//CHECK-NEXT: %constraint1 = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %5, i256 %7, i1* %constraint1) +//CHECK-NEXT: br label %store3 +//CHECK-EMPTY: +//CHECK-NEXT: store3: +//CHECK-NEXT: %8 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: %9 = load i256, i256* %8, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %9, i256 1) +//CHECK-NEXT: %10 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: store i256 %call.fr_add, i256* %10, align 4 +//CHECK-NEXT: br label %return4 +//CHECK-EMPTY: +//CHECK-NEXT: return4: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @Sum_0_run([0 x i256]* %0){{.*}} { +//CHECK-NEXT: prelude: +//CHECK-NEXT: %lvars = alloca [3 x i256], align 8 +//CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 +//CHECK-NEXT: br label %store1 +//CHECK-EMPTY: +//CHECK-NEXT: store1: +//CHECK-NEXT: %1 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: store i256 4, i256* %1, align 4 +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %2 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 0, i256* %2, align 4 +//CHECK-NEXT: br label %store3 +//CHECK-EMPTY: +//CHECK-NEXT: store3: +//CHECK-NEXT: %3 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 2 +//CHECK-NEXT: store i256 0, i256* %3, align 4 +//CHECK-NEXT: br label %unrolled_loop4 +//CHECK-EMPTY: +//CHECK-NEXT: unrolled_loop4: +//CHECK-NEXT: %4 = bitcast [3 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %5 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 1 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %4, [0 x i256]* %0, i256* %5) +//CHECK-NEXT: %6 = bitcast [3 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %7 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 2 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %6, [0 x i256]* %0, i256* %7) +//CHECK-NEXT: %8 = bitcast [3 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %9 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 3 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %8, [0 x i256]* %0, i256* %9) +//CHECK-NEXT: %10 = bitcast [3 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %11 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 4 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %10, [0 x i256]* %0, i256* %11) +//CHECK-NEXT: br label %store5 +//CHECK-EMPTY: +//CHECK-NEXT: store5: +//CHECK-NEXT: %12 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: %13 = load i256, i256* %12, align 4 +//CHECK-NEXT: %14 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 0 +//CHECK-NEXT: store i256 %13, i256* %14, align 4 +//CHECK-NEXT: %15 = load i256, i256* %14, align 4 +//CHECK-NEXT: %constraint = alloca i1, align 1 +//CHECK-NEXT: call void @__constraint_values(i256 %13, i256 %15, i1* %constraint) +//CHECK-NEXT: br label %prologue +//CHECK-EMPTY: +//CHECK-NEXT: prologue: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @SubCmps3_1_run([0 x i256]* %0){{.*}} { +//CHECK-NEXT: prelude: +//CHECK-NEXT: %lvars = alloca [1 x i256], align 8 +//CHECK-NEXT: %subcmps = alloca [1 x { [0 x i256]*, i32 }], align 8 +//CHECK-NEXT: br label %create_cmp1 +//CHECK-EMPTY: +//CHECK-NEXT: create_cmp1: +//CHECK-NEXT: %1 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0 +//CHECK-NEXT: call void @Sum_0_build({ [0 x i256]*, i32 }* %1) +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %2 = getelementptr [1 x i256], [1 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: store i256 0, i256* %2, align 4 +//CHECK-NEXT: br label %unrolled_loop3 +//CHECK-EMPTY: +//CHECK-NEXT: unrolled_loop3: +//CHECK-NEXT: %3 = bitcast [1 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %4 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %5 = load [0 x i256]*, [0 x i256]** %4, align 8 +//CHECK-NEXT: %6 = getelementptr [0 x i256], [0 x i256]* %5, i32 0 +//CHECK-NEXT: %7 = getelementptr [0 x i256], [0 x i256]* %6, i32 0, i256 1 +//CHECK-NEXT: %8 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 1 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %3, [0 x i256]* %0, i256* %7, i256* %8, i256* null) +//CHECK-NEXT: %9 = bitcast [1 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %10 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %11 = load [0 x i256]*, [0 x i256]** %10, align 8 +//CHECK-NEXT: %12 = getelementptr [0 x i256], [0 x i256]* %11, i32 0 +//CHECK-NEXT: %13 = getelementptr [0 x i256], [0 x i256]* %12, i32 0, i256 2 +//CHECK-NEXT: %14 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 2 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %9, [0 x i256]* %0, i256* %13, i256* %14, i256* null) +//CHECK-NEXT: %15 = bitcast [1 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %16 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %17 = load [0 x i256]*, [0 x i256]** %16, align 8 +//CHECK-NEXT: %18 = getelementptr [0 x i256], [0 x i256]* %17, i32 0 +//CHECK-NEXT: %19 = getelementptr [0 x i256], [0 x i256]* %18, i32 0, i256 3 +//CHECK-NEXT: %20 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 3 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %15, [0 x i256]* %0, i256* %19, i256* %20, i256* null) +//CHECK-NEXT: %21 = bitcast [1 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %22 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %23 = load [0 x i256]*, [0 x i256]** %22, align 8 +//CHECK-NEXT: %24 = getelementptr [0 x i256], [0 x i256]* %23, i32 0 +//CHECK-NEXT: %25 = getelementptr [0 x i256], [0 x i256]* %24, i32 0, i256 4 +//CHECK-NEXT: %26 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 4 +//CHECK-NEXT: %27 = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %28 = load [0 x i256]*, [0 x i256]** %27, align 8 +//CHECK-NEXT: %29 = getelementptr [0 x i256], [0 x i256]* %28, i32 0 +//CHECK-NEXT: %30 = getelementptr [0 x i256], [0 x i256]* %29, i32 0, i256 0 +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_3]]([0 x i256]* %21, [0 x i256]* %0, i256* %25, i256* %26, i256* %30) +//CHECK-NEXT: br label %prologue +//CHECK-EMPTY: +//CHECK-NEXT: prologue: +//CHECK-NEXT: ret void +//CHECK-NEXT: } diff --git a/circom/tests/zzz/unreachable_code_crash.circom b/circom/tests/zzz/unreachable_code_crash.circom new file mode 100644 index 000000000..2bcc5f528 --- /dev/null +++ b/circom/tests/zzz/unreachable_code_crash.circom @@ -0,0 +1,43 @@ +pragma circom 2.0.2; +// 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 OR() { + signal input a; +} + +// This test demonstrates the need for the UnusedFuncRemovalPass. +// Here's what happens without that pass. The outer loop unrolls first, with 2 copies of its body +// because it has 2 iterations. In the second iteration (i.e. the second copy of the inner loop), +// the 'true' branch of the if-else will never execute so in the "loop.body" function generated +// for that second copy of the inner loop, this branch is dead code. Because it is dead code, no +// parameter was added to the generated function to reference the destination of the StoreBucket +// in that branch and therefore the location information in that StoreBucket was not updated thus +// leaving an invalid parameter reference that causes 'functions.rs::get_arg_ptr' to crash. +// +template InvalidArgIndex(n, k) { + component has_prev_non_zero[k * n]; + for (var i = k - 1; i >= 0; i--) { + for (var j = n - 1; j >= 0; j--) { + has_prev_non_zero[n * i + j] = OR(); + if (i == k - 1 && j == n - 1) { + has_prev_non_zero[n * i + j].a <-- 99; + } else { + has_prev_non_zero[n * i + j].a <-- 33; + } + } + } +} + +component main = InvalidArgIndex(3, 2); + +//// Check that only the proper versions of the generated functions remain +//// (i.e. the initial one was removed after conditional flattening). +// +//CHECK-NOT: define void @..generated..loop.body.{{[0-9]+}}( +//CHECK: define void @..generated..loop.body.[[NAME_1:[0-9]+]].F( +//CHECK-NOT: define void @..generated..loop.body.{{[0-9]+}}( +//CHECK: define void @..generated..loop.body.[[NAME_1]].T( +//CHECK-NOT: define void @..generated..loop.body.{{[0-9]+}}( +//CHECK: define void @..generated..loop.body.[[NAME_2:[0-9]+]].F.T( +//CHECK-NOT: define void @..generated..loop.body.{{[0-9]+}}( diff --git a/circuit_passes/src/bucket_interpreter/env/extracted_func_env.rs b/circuit_passes/src/bucket_interpreter/env/extracted_func_env.rs index 57685e7e4..7e5413be1 100644 --- a/circuit_passes/src/bucket_interpreter/env/extracted_func_env.rs +++ b/circuit_passes/src/bucket_interpreter/env/extracted_func_env.rs @@ -1,13 +1,13 @@ use std::cell::Ref; -use std::collections::{HashMap, BTreeMap}; +use std::collections::{HashMap, BTreeMap, HashSet}; use std::fmt::{Display, Formatter, Result}; use compiler::circuit_design::function::FunctionCode; use compiler::circuit_design::template::TemplateCode; -use compiler::intermediate_representation::Instruction; +use compiler::intermediate_representation::{Instruction, BucketId}; use compiler::intermediate_representation::ir_interface::{AddressType, ValueBucket, ValueType}; use crate::bucket_interpreter::BucketInterpreter; use crate::bucket_interpreter::value::Value; -use crate::passes::loop_unroll::body_extractor::ToOriginalLocation; +use crate::passes::loop_unroll::body_extractor::{ToOriginalLocation, FuncArgIdx}; use super::{Env, LibraryAccess}; /// This Env is used to process functions created by extracting loop bodies @@ -18,7 +18,15 @@ use super::{Env, LibraryAccess}; #[derive(Clone)] pub struct ExtractedFuncEnvData<'a> { base: Box>, + caller: BucketId, remap: ToOriginalLocation, + arenas: HashSet, +} + +macro_rules! update_inner { + ($self: expr, $inner: expr) => {{ + ExtractedFuncEnvData::new($inner, &$self.caller, $self.remap, $self.arenas) + }}; } impl Display for ExtractedFuncEnvData<'_> { @@ -43,8 +51,17 @@ impl LibraryAccess for ExtractedFuncEnvData<'_> { // AddressType::SubcmpSignal references created by ExtractedFunctionLocationUpdater // back into the proper reference to access the correct Env entry. impl<'a> ExtractedFuncEnvData<'a> { - pub fn new(inner: Env<'a>, remap: ToOriginalLocation) -> Self { - ExtractedFuncEnvData { base: Box::new(inner), remap } + pub fn new( + inner: Env<'a>, + caller: &BucketId, + remap: ToOriginalLocation, + arenas: HashSet, + ) -> Self { + ExtractedFuncEnvData { base: Box::new(inner), caller: caller.clone(), remap, arenas } + } + + pub fn extracted_func_caller(&self) -> Option<&BucketId> { + Some(&self.caller) } pub fn get_base(self) -> Env<'a> { @@ -63,7 +80,11 @@ impl<'a> ExtractedFuncEnvData<'a> { pub fn get_subcmp_signal(&self, subcmp_idx: usize, signal_idx: usize) -> Value { let res = match self.remap.get(&subcmp_idx) { - None => todo!(), // from ArgIndex::SubCmp 'arena' and 'counter' parameters + None => { + //ASSERT: ArgIndex::SubCmp 'arena' parameters are not in 'remap' but all others are. + assert!(self.arenas.contains(&subcmp_idx)); + unreachable!(); + } Some((loc, idx)) => { //ASSERT: ExtractedFunctionLocationUpdater will always assign 0 in // the LocationRule that 'signal_idx' is computed from. @@ -71,7 +92,7 @@ impl<'a> ExtractedFuncEnvData<'a> { match loc { AddressType::Variable => self.base.get_var(*idx), AddressType::Signal => self.base.get_signal(*idx), - AddressType::SubcmpSignal { cmp_address, .. } => { + AddressType::SubcmpSignal { counter_override, cmp_address, .. } => { let subcmp = match **cmp_address { Instruction::Value(ValueBucket { parse_as: ValueType::U32, @@ -80,7 +101,13 @@ impl<'a> ExtractedFuncEnvData<'a> { }) => value, _ => unreachable!(), //ASSERT: 'cmp_address' was formed by 'loop_unroll::new_u32_value' }; - self.base.get_subcmp_signal(subcmp, *idx) + if *counter_override { + // ASSERT: always 0 from 'get_reverse_passing_refs_for_itr' in 'body_extractor.rs' + assert_eq!(*idx, 0); + self.base.get_subcmp_counter(subcmp) + } else { + self.base.get_subcmp_signal(subcmp, *idx) + } } } } @@ -90,12 +117,16 @@ impl<'a> ExtractedFuncEnvData<'a> { pub fn get_subcmp_name(&self, subcmp_idx: usize) -> &String { match self.remap.get(&subcmp_idx) { - None => todo!(), // from ArgIndex::SubCmp 'arena' and 'counter' parameters + None => { + //ASSERT: ArgIndex::SubCmp 'arena' parameters are not in 'remap' but all others are. + assert!(self.arenas.contains(&subcmp_idx)); + unreachable!(); + } Some((loc, idx)) => { match loc { AddressType::Variable => self.base.get_subcmp_name(*idx), AddressType::Signal => self.base.get_subcmp_name(*idx), - AddressType::SubcmpSignal { cmp_address, .. } => { + AddressType::SubcmpSignal { counter_override, cmp_address, .. } => { let subcmp = match **cmp_address { Instruction::Value(ValueBucket { parse_as: ValueType::U32, @@ -104,10 +135,14 @@ impl<'a> ExtractedFuncEnvData<'a> { }) => value, _ => unreachable!(), //ASSERT: 'cmp_address' was formed by 'loop_unroll::new_u32_value' }; - //ASSERT: ExtractedFunctionLocationUpdater will always assign 0 in - // the LocationRule that 'signal_idx' is computed from. - assert_eq!(*idx, 0); - self.base.get_subcmp_name(subcmp) + if *counter_override { + unreachable!(); + } else { + //ASSERT: ExtractedFunctionLocationUpdater will always assign 0 in + // the LocationRule that 'idx' is computed from. + assert_eq!(*idx, 0); + self.base.get_subcmp_name(subcmp) + } } } } @@ -116,12 +151,16 @@ impl<'a> ExtractedFuncEnvData<'a> { pub fn get_subcmp_template_id(&self, subcmp_idx: usize) -> usize { match self.remap.get(&subcmp_idx) { - None => todo!(), // from ArgIndex::SubCmp 'arena' and 'counter' parameters + None => { + //ASSERT: ArgIndex::SubCmp 'arena' parameters are not in 'remap' but all others are. + assert!(self.arenas.contains(&subcmp_idx)); + unreachable!(); + } Some((loc, idx)) => { match loc { AddressType::Variable => self.base.get_subcmp_template_id(*idx), AddressType::Signal => self.base.get_subcmp_template_id(*idx), - AddressType::SubcmpSignal { cmp_address, .. } => { + AddressType::SubcmpSignal { counter_override, cmp_address, .. } => { let subcmp = match **cmp_address { Instruction::Value(ValueBucket { parse_as: ValueType::U32, @@ -130,27 +169,35 @@ impl<'a> ExtractedFuncEnvData<'a> { }) => value, _ => unreachable!(), //ASSERT: 'cmp_address' was formed by 'loop_unroll::new_u32_value' }; - //ASSERT: ExtractedFunctionLocationUpdater will always assign 0 in - // the LocationRule that 'signal_idx' is computed from. - assert_eq!(*idx, 0); - self.base.get_subcmp_template_id(subcmp) + if *counter_override { + unreachable!(); + } else { + //ASSERT: ExtractedFunctionLocationUpdater will always assign 0 in + // the LocationRule that 'signal_idx' is computed from. + assert_eq!(*idx, 0); + self.base.get_subcmp_template_id(subcmp) + } } } } } } + pub fn get_subcmp_counter(&self, _subcmp_idx: usize) -> Value { + todo!() + } + pub fn subcmp_counter_is_zero(&self, subcmp_idx: usize) -> bool { let res = match self.remap.get(&subcmp_idx).cloned() { - //TODO: Is this None case being hit by a pre-existing subcmp at index 0 reference? I think so. Can I verify? - // All subcmp refs in extracted body should have been replaced with refs to a subfix parameter... right? - //OBS: It happens because there will be Unknown counter when certain loop bodies are extracted to a function. - // That means I do need to add the code to decrement counters inside the loop and let StoreBucket generate - // the counter checks that will determine when to execute the "run" function at runtime. - None => todo!(), //false, // from ArgIndex::SubCmp 'arena' and 'counter' parameters + None => { + //ASSERT: ArgIndex::SubCmp 'arena' parameters are not in 'remap' but all others are. + assert!(self.arenas.contains(&subcmp_idx)); + // This will be reached for the StoreBucket that generates a call to the "_run" function. + return true; // True to execute the run_subcmp function + } Some((loc, _)) => { match loc { - AddressType::SubcmpSignal { cmp_address, .. } => { + AddressType::SubcmpSignal { counter_override, cmp_address, .. } => { let subcmp = match *cmp_address { Instruction::Value(ValueBucket { parse_as: ValueType::U32, @@ -159,7 +206,11 @@ impl<'a> ExtractedFuncEnvData<'a> { }) => value, _ => unreachable!(), //ASSERT: 'cmp_address' was formed by 'loop_unroll::new_u32_value' }; - self.base.subcmp_counter_is_zero(subcmp) + if counter_override { + unreachable!() // there is no counter for a counter reference + } else { + self.base.subcmp_counter_is_zero(subcmp) + } } _ => false, // no counter for Variable/Signal types } @@ -170,10 +221,14 @@ impl<'a> ExtractedFuncEnvData<'a> { pub fn subcmp_counter_equal_to(&self, subcmp_idx: usize, value: usize) -> bool { let res = match self.remap.get(&subcmp_idx).cloned() { - None => todo!(), //false, // from ArgIndex::SubCmp 'arena' and 'counter' parameters + None => { + //ASSERT: ArgIndex::SubCmp 'arena' parameters are not in 'remap' but all others are. + assert!(self.arenas.contains(&subcmp_idx)); + unreachable!(); + } Some((loc, _)) => { match loc { - AddressType::SubcmpSignal { cmp_address, .. } => { + AddressType::SubcmpSignal { counter_override, cmp_address, .. } => { let subcmp = match *cmp_address { Instruction::Value(ValueBucket { parse_as: ValueType::U32, @@ -182,7 +237,11 @@ impl<'a> ExtractedFuncEnvData<'a> { }) => value, _ => unreachable!(), //ASSERT: 'cmp_address' was formed by 'loop_unroll::new_u32_value' }; - self.base.subcmp_counter_equal_to(subcmp, value) + if counter_override { + unreachable!() // there is no counter for a counter reference + } else { + self.base.subcmp_counter_equal_to(subcmp, value) + } } _ => false, // no counter for Variable/Signal types } @@ -201,40 +260,44 @@ impl<'a> ExtractedFuncEnvData<'a> { pub fn set_var(self, idx: usize, value: Value) -> Self { // Local variables are referenced in the normal way - ExtractedFuncEnvData { base: Box::new(self.base.set_var(idx, value)), remap: self.remap } + update_inner!(self, self.base.set_var(idx, value)) } pub fn set_signal(self, idx: usize, value: Value) -> Self { // Signals are referenced in the normal way - ExtractedFuncEnvData { base: Box::new(self.base.set_signal(idx, value)), remap: self.remap } + update_inner!(self, self.base.set_signal(idx, value)) } pub fn set_all_to_unk(self) -> Self { - // Local variables are referenced in the normal way - ExtractedFuncEnvData { base: Box::new(self.base.set_all_to_unk()), remap: self.remap } + update_inner!(self, self.base.set_all_to_unk()) } - pub fn set_subcmp_to_unk(self, _subcmp_idx: usize) -> Self { - unreachable!() + pub fn set_subcmp_to_unk(self, subcmp_idx: usize) -> Self { + // The index here is already converted within BucketInterpreter::get_write_operations_in_store_bucket + // via interpreting the LocationRule and performing the PassMemory lookup on the unchanged scope + // (per comment in BucketInterpreter::run_function_loopbody). + update_inner!(self, self.base.set_subcmp_to_unk(subcmp_idx)) } - pub fn set_subcmp_signal(self, subcmp_idx: usize, signal_idx: usize, value: Value) -> Self { + pub fn set_subcmp_signal(self, subcmp_idx: usize, signal_idx: usize, new_value: Value) -> Self { //NOTE: This is only called by BucketInterpreter::store_value_in_address. //Use the map from loop unrolling to convert the SubcmpSignal reference back // into the proper reference (reversing ExtractedFunctionLocationUpdater). let new_env = match self.remap.get(&subcmp_idx).cloned() { - //NOTE: The ArgIndex::SubCmp 'arena' and 'counter' parameters were not added - // to the 'remap' (producing None result here) because those parameters are - // not actually used to access signals, just to call _run and update counter. - None => *self.base, + None => { + //ASSERT: ArgIndex::SubCmp 'arena' parameters are not in 'remap' but all others are. + assert!(self.arenas.contains(&subcmp_idx)); + // This will be reached for the StoreBucket that generates a call to the "_run" function. + return self; // Nothing needs to be done. + } Some((loc, idx)) => { //ASSERT: ExtractedFunctionLocationUpdater will always assign 0 in // the LocationRule that 'signal_idx' is computed from. assert_eq!(signal_idx, 0); match loc { - AddressType::Variable => self.base.set_var(idx, value), - AddressType::Signal => self.base.set_signal(idx, value), - AddressType::SubcmpSignal { cmp_address, .. } => { + AddressType::Variable => self.base.set_var(idx, new_value), + AddressType::Signal => self.base.set_signal(idx, new_value), + AddressType::SubcmpSignal { counter_override, cmp_address, .. } => { let subcmp = match *cmp_address { Instruction::Value(ValueBucket { parse_as: ValueType::U32, @@ -243,48 +306,31 @@ impl<'a> ExtractedFuncEnvData<'a> { }) => value, _ => unreachable!(), //ASSERT: 'cmp_address' was formed by 'loop_unroll::new_u32_value' }; - self.base.set_subcmp_signal(subcmp, idx, value) + if counter_override { + // ASSERT: always 0 from 'get_reverse_passing_refs_for_itr' in 'body_extractor.rs' + assert_eq!(idx, 0); + // NOTE: If unwrapping to u32 directly causes a panic, then need to allow Value as the parameter. + self.base.set_subcmp_counter(subcmp, new_value.get_u32()) + } else { + self.base.set_subcmp_signal(subcmp, idx, new_value) + } } } } }; - ExtractedFuncEnvData { base: Box::new(new_env), remap: self.remap } + update_inner!(self, new_env) } - pub fn decrease_subcmp_counter(self, subcmp_idx: usize) -> Self { - let new_env = match self.remap.get(&subcmp_idx).cloned() { - //NOTE: The ArgIndex::SubCmp 'arena' and 'counter' parameters were not added - // to the 'remap' (producing None result here) because those parameters are - // not actually used to access signals, just to call _run and update counter. - // No counter update needed when SubcmpSignal is used for these special cases. - None => *self.base, - Some((loc, _)) => { - match loc { - AddressType::SubcmpSignal { cmp_address, .. } => { - let subcmp = match *cmp_address { - Instruction::Value(ValueBucket { - parse_as: ValueType::U32, - value, - .. - }) => value, - _ => unreachable!(), //ASSERT: 'cmp_address' was formed by 'loop_unroll::new_u32_value' - }; - self.base.decrease_subcmp_counter(subcmp) - } - _ => *self.base, // no counter for Variable/Signal types - } - } - }; - ExtractedFuncEnvData { base: Box::new(new_env), remap: self.remap } + pub fn set_subcmp_counter(self, _subcmp_idx: usize, _new_val: usize) -> Self { + todo!() } - pub fn run_subcmp( - self, - _subcmp_idx: usize, - _name: &String, - _interpreter: &BucketInterpreter, - _observe: bool, - ) -> Self { + pub fn decrease_subcmp_counter(self, _subcmp_idx: usize) -> Self { + //Do nothing because subcmp counter is managed explicitly in extracted functions + self + } + + pub fn run_subcmp(self, _: usize, _: &String, _: &BucketInterpreter, _: bool) -> Self { //Return self just like the StandardEnvData self } diff --git a/circuit_passes/src/bucket_interpreter/env/mod.rs b/circuit_passes/src/bucket_interpreter/env/mod.rs index 30e729888..c9908c3fa 100644 --- a/circuit_passes/src/bucket_interpreter/env/mod.rs +++ b/circuit_passes/src/bucket_interpreter/env/mod.rs @@ -1,11 +1,12 @@ use std::cell::Ref; -use std::collections::{HashMap, BTreeMap}; +use std::collections::{HashMap, BTreeMap, HashSet}; use std::fmt::{Display, Formatter, Result}; use compiler::circuit_design::function::FunctionCode; use compiler::circuit_design::template::TemplateCode; +use compiler::intermediate_representation::BucketId; use crate::bucket_interpreter::BucketInterpreter; use crate::bucket_interpreter::value::Value; -use crate::passes::loop_unroll::body_extractor::{LoopBodyExtractor, ToOriginalLocation}; +use crate::passes::loop_unroll::body_extractor::{LoopBodyExtractor, ToOriginalLocation, FuncArgIdx}; use self::extracted_func_env::ExtractedFuncEnvData; use self::standard_env::StandardEnvData; use self::unrolled_block_env::UnrolledBlockEnvData; @@ -48,6 +49,16 @@ impl SubcmpEnv { copy } + pub fn get_counter(&self) -> usize { + self.counter + } + + pub fn set_counter(self, new_val: usize) -> SubcmpEnv { + let mut copy = self; + copy.counter = new_val; + copy + } + pub fn counter_is_zero(&self) -> bool { self.counter == 0 } @@ -81,6 +92,16 @@ impl Display for Env<'_> { } } +impl std::fmt::Debug for Env<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + match self { + Env::Standard(d) => d.fmt(f), + Env::UnrolledBlock(d) => d.fmt(f), + Env::ExtractedFunction(d) => d.fmt(f), + } + } +} + impl LibraryAccess for Env<'_> { fn get_function(&self, name: &String) -> Ref { match self { @@ -100,6 +121,14 @@ impl LibraryAccess for Env<'_> { } impl<'a> Env<'a> { + pub fn extracted_func_caller(&self) -> Option<&BucketId> { + match self { + Env::Standard(e) => e.extracted_func_caller(), + Env::UnrolledBlock(e) => e.extracted_func_caller(), + Env::ExtractedFunction(e) => e.extracted_func_caller(), + } + } + pub fn new_standard_env(libs: &'a dyn LibraryAccess) -> Self { Env::Standard(StandardEnvData::new(libs)) } @@ -108,8 +137,13 @@ impl<'a> Env<'a> { Env::UnrolledBlock(UnrolledBlockEnvData::new(inner, extractor)) } - pub fn new_extracted_func_env(inner: Env<'a>, remap: ToOriginalLocation) -> Self { - Env::ExtractedFunction(ExtractedFuncEnvData::new(inner, remap)) + pub fn new_extracted_func_env( + inner: Env<'a>, + caller: &BucketId, + remap: ToOriginalLocation, + arenas: HashSet, + ) -> Self { + Env::ExtractedFunction(ExtractedFuncEnvData::new(inner, caller, remap, arenas)) } pub fn peel_extracted_func(self) -> Self { @@ -160,6 +194,14 @@ impl<'a> Env<'a> { } } + pub fn get_subcmp_counter(&self, subcmp_idx: usize) -> Value { + match self { + Env::Standard(d) => d.get_subcmp_counter(subcmp_idx), + Env::UnrolledBlock(d) => d.get_subcmp_counter(subcmp_idx), + Env::ExtractedFunction(d) => d.get_subcmp_counter(subcmp_idx), + } + } + pub fn subcmp_counter_is_zero(&self, subcmp_idx: usize) -> bool { match self { Env::Standard(d) => d.subcmp_counter_is_zero(subcmp_idx), @@ -238,6 +280,16 @@ impl<'a> Env<'a> { } } + pub fn set_subcmp_counter(self, subcmp_idx: usize, new_val: usize) -> Self { + match self { + Env::Standard(d) => Env::Standard(d.set_subcmp_counter(subcmp_idx, new_val)), + Env::UnrolledBlock(d) => Env::UnrolledBlock(d.set_subcmp_counter(subcmp_idx, new_val)), + Env::ExtractedFunction(d) => { + Env::ExtractedFunction(d.set_subcmp_counter(subcmp_idx, new_val)) + } + } + } + pub fn decrease_subcmp_counter(self, subcmp_idx: usize) -> Self { match self { Env::Standard(d) => Env::Standard(d.decrease_subcmp_counter(subcmp_idx)), diff --git a/circuit_passes/src/bucket_interpreter/env/standard_env.rs b/circuit_passes/src/bucket_interpreter/env/standard_env.rs index ab211aa02..38e43a532 100644 --- a/circuit_passes/src/bucket_interpreter/env/standard_env.rs +++ b/circuit_passes/src/bucket_interpreter/env/standard_env.rs @@ -3,6 +3,7 @@ use std::collections::{HashMap, BTreeMap}; use std::fmt::{Display, Formatter, Result}; use compiler::circuit_design::function::FunctionCode; use compiler::circuit_design::template::TemplateCode; +use compiler::intermediate_representation::BucketId; use crate::bucket_interpreter::BucketInterpreter; use crate::bucket_interpreter::value::Value; use super::{SubcmpEnv, LibraryAccess}; @@ -46,6 +47,10 @@ impl<'a> StandardEnvData<'a> { } // READ OPERATIONS + pub fn extracted_func_caller(&self) -> Option<&BucketId> { + None + } + pub fn get_var(&self, idx: usize) -> Value { self.vars.get(&idx).unwrap_or_default().clone() } @@ -66,6 +71,10 @@ impl<'a> StandardEnvData<'a> { self.subcmps[&subcmp_idx].template_id } + pub fn get_subcmp_counter(&self, subcmp_idx: usize) -> Value { + Value::KnownU32(self.subcmps.get(&subcmp_idx).unwrap().get_counter()) + } + pub fn subcmp_counter_is_zero(&self, subcmp_idx: usize) -> bool { self.subcmps.get(&subcmp_idx).unwrap().counter_is_zero() } @@ -114,32 +123,28 @@ impl<'a> StandardEnvData<'a> { /// Sets all the signals of the subcmp to UNK pub fn set_subcmp_to_unk(self, subcmp_idx: usize) -> Self { - let mut copy = self; - let subcmp_env = copy - .subcmps - .remove(&subcmp_idx) - .expect(format!("Can't set a signal of subcomponent {}", subcmp_idx).as_str()); - copy.subcmps.insert(subcmp_idx, subcmp_env.reset()); - copy + self.update_subcmp(subcmp_idx, |subcmp_env| subcmp_env.reset()) } pub fn set_subcmp_signal(self, subcmp_idx: usize, signal_idx: usize, value: Value) -> Self { - let mut copy = self; - let subcmp_env = copy - .subcmps - .remove(&subcmp_idx) - .expect(format!("Can't set a signal of subcomponent {}", subcmp_idx).as_str()); - copy.subcmps.insert(subcmp_idx, subcmp_env.set_signal(signal_idx, value)); - copy + self.update_subcmp(subcmp_idx, |subcmp_env| subcmp_env.set_signal(signal_idx, value)) + } + + pub fn set_subcmp_counter(self, subcmp_idx: usize, new_val: usize) -> Self { + self.update_subcmp(subcmp_idx, |subcmp_env| subcmp_env.set_counter(new_val)) } pub fn decrease_subcmp_counter(self, subcmp_idx: usize) -> Self { + self.update_subcmp(subcmp_idx, |subcmp_env| subcmp_env.decrease_counter()) + } + + fn update_subcmp(self, subcmp_idx: usize, f: impl FnOnce(SubcmpEnv) -> SubcmpEnv) -> Self { let mut copy = self; let subcmp_env = copy .subcmps .remove(&subcmp_idx) - .expect(format!("Can't decrease counter of subcomponent {}", subcmp_idx).as_str()); - copy.subcmps.insert(subcmp_idx, subcmp_env.decrease_counter()); + .expect(format!("Can't find subcomponent {}", subcmp_idx).as_str()); + copy.subcmps.insert(subcmp_idx, f(subcmp_env)); copy } diff --git a/circuit_passes/src/bucket_interpreter/env/unrolled_block_env.rs b/circuit_passes/src/bucket_interpreter/env/unrolled_block_env.rs index 23a8f4e09..4bb4f8ba0 100644 --- a/circuit_passes/src/bucket_interpreter/env/unrolled_block_env.rs +++ b/circuit_passes/src/bucket_interpreter/env/unrolled_block_env.rs @@ -3,6 +3,7 @@ use std::collections::{HashMap, BTreeMap}; use std::fmt::{Display, Formatter, Result}; use compiler::circuit_design::function::FunctionCode; use compiler::circuit_design::template::TemplateCode; +use compiler::intermediate_representation::BucketId; use crate::bucket_interpreter::BucketInterpreter; use crate::bucket_interpreter::value::Value; use crate::passes::loop_unroll::LOOP_BODY_FN_PREFIX; @@ -50,6 +51,10 @@ impl<'a> UnrolledBlockEnvData<'a> { UnrolledBlockEnvData { base: Box::new(base), extractor } } + pub fn extracted_func_caller(&self) -> Option<&BucketId> { + None + } + pub fn get_var(&self, idx: usize) -> Value { self.base.get_var(idx) } @@ -70,6 +75,10 @@ impl<'a> UnrolledBlockEnvData<'a> { self.base.get_subcmp_template_id(subcmp_idx) } + pub fn get_subcmp_counter(&self, subcmp_idx: usize) -> Value { + self.base.get_subcmp_counter(subcmp_idx) + } + pub fn subcmp_counter_is_zero(&self, subcmp_idx: usize) -> bool { self.base.subcmp_counter_is_zero(subcmp_idx) } @@ -121,6 +130,13 @@ impl<'a> UnrolledBlockEnvData<'a> { } } + pub fn set_subcmp_counter(self, subcmp_idx: usize, new_val: usize) -> Self { + UnrolledBlockEnvData { + base: Box::new(self.base.set_subcmp_counter(subcmp_idx, new_val)), + extractor: self.extractor, + } + } + pub fn decrease_subcmp_counter(self, subcmp_idx: usize) -> Self { UnrolledBlockEnvData { base: Box::new(self.base.decrease_subcmp_counter(subcmp_idx)), diff --git a/circuit_passes/src/bucket_interpreter/memory.rs b/circuit_passes/src/bucket_interpreter/memory.rs index 368474491..f16fc904c 100644 --- a/circuit_passes/src/bucket_interpreter/memory.rs +++ b/circuit_passes/src/bucket_interpreter/memory.rs @@ -8,7 +8,7 @@ use compiler::circuit_design::template::TemplateCode; use compiler::compiler_interface::Circuit; use crate::bucket_interpreter::BucketInterpreter; use crate::bucket_interpreter::env::{Env, LibraryAccess}; -use crate::bucket_interpreter::observer::InterpreterObserver; +use crate::bucket_interpreter::observer::Observer; use crate::passes::GlobalPassData; pub struct PassMemory { @@ -44,7 +44,7 @@ impl PassMemory { pub fn build_interpreter<'a, 'd: 'a>( &'a self, global_data: &'d RefCell, - observer: &'a dyn InterpreterObserver, + observer: &'a dyn for<'e> Observer>, ) -> BucketInterpreter { self.build_interpreter_with_scope( global_data, @@ -56,7 +56,7 @@ impl PassMemory { pub fn build_interpreter_with_scope<'a, 'd: 'a>( &'a self, global_data: &'d RefCell, - observer: &'a dyn InterpreterObserver, + observer: &'a dyn for<'e> Observer>, scope: String, ) -> BucketInterpreter { BucketInterpreter::init(global_data, observer, self, scope) @@ -69,7 +69,7 @@ impl PassMemory { pub fn run_template<'d>( &self, global_data: &'d RefCell, - observer: &dyn InterpreterObserver, + observer: &dyn for<'e> Observer>, template: &TemplateCode, ) { assert!(!self.current_scope.borrow().is_empty()); diff --git a/circuit_passes/src/bucket_interpreter/mod.rs b/circuit_passes/src/bucket_interpreter/mod.rs index 18998bdcb..2f5966a4e 100644 --- a/circuit_passes/src/bucket_interpreter/mod.rs +++ b/circuit_passes/src/bucket_interpreter/mod.rs @@ -2,6 +2,7 @@ pub mod value; pub mod env; pub mod memory; pub mod observer; +pub mod observed_visitor; pub(crate) mod operations; use std::cell::RefCell; @@ -12,7 +13,7 @@ use code_producers::llvm_elements::stdlib::GENERATED_FN_PREFIX; use compiler::intermediate_representation::{Instruction, InstructionList, InstructionPointer}; use compiler::intermediate_representation::ir_interface::*; use compiler::num_bigint::BigInt; -use observer::InterpreterObserver; +use observer::Observer; use program_structure::constants::UsefulConstants; use crate::bucket_interpreter::env::Env; use crate::bucket_interpreter::memory::PassMemory; @@ -24,7 +25,7 @@ use self::env::LibraryAccess; pub struct BucketInterpreter<'a, 'd> { global_data: &'d RefCell, - observer: &'a dyn InterpreterObserver, + observer: &'a dyn for<'e> Observer>, mem: &'a PassMemory, scope: String, p: BigInt, @@ -35,7 +36,7 @@ pub type R<'a> = (Option, Env<'a>); impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { pub fn init( global_data: &'d RefCell, - observer: &'a dyn InterpreterObserver, + observer: &'a dyn for<'e> Observer>, mem: &'a PassMemory, scope: String, ) -> Self { @@ -66,21 +67,19 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { subcmps: &mut Vec, env: &Env, ) { + let idx = self.get_index_from_location(&bucket.dest, env); match bucket.dest_address_type { AddressType::Variable => { - let idx = self.get_index_from_location(&bucket.dest, env); for index in self.mem.get_variables_index_mapping(&self.scope, &idx) { vars.push(index); } } AddressType::Signal => { - let idx = self.get_index_from_location(&bucket.dest, env); for index in self.mem.get_signal_index_mapping(&self.scope, &idx) { signals.push(index); } } AddressType::SubcmpSignal { .. } => { - let idx = self.get_index_from_location(&bucket.dest, env); for index in self.mem.get_component_addr_index_mapping(&self.scope, &idx) { subcmps.push(index); } @@ -388,6 +387,7 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { env: Env<'env>, observe: bool, ) -> R<'env> { + // println!("Interpreter executing {:?}", bucket); let (src, env) = self.execute_instruction(&bucket.src, env, observe); let src = src.expect("src instruction in StoreBucket must produce a value!"); let env = @@ -417,26 +417,34 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { (computed_value, env) } - fn run_function_loopbody<'env>(&self, name: &String, env: Env<'env>, observe: bool) -> R<'env> { + fn run_function_extracted<'env>( + &self, + bucket: &'env CallBucket, + env: Env<'env>, + observe: bool, + ) -> R<'env> { + let name = &bucket.symbol; if cfg!(debug_assertions) { println!("Running function {}", name); }; - let mut res: R<'env> = ( - None, - Env::new_extracted_func_env( - env.clone(), - if name.starts_with(LOOP_BODY_FN_PREFIX) { - self.global_data.borrow().extract_func_orig_loc[name][&env.get_vars_sort()] - .clone() - } else { - Default::default() - }, - ), - ); + let mut res: R<'env> = (None, { + if name.starts_with(LOOP_BODY_FN_PREFIX) { + let gdat = self.global_data.borrow(); + let fdat = &gdat.get_data_for_func(name)[&env.get_vars_sort()]; + Env::new_extracted_func_env(env.clone(), &bucket.id, fdat.0.clone(), fdat.1.clone()) + } else { + Env::new_extracted_func_env( + env.clone(), + &bucket.id, + Default::default(), + Default::default(), + ) + } + }); //NOTE: Do not change scope for the new interpreter because the mem lookups within // `get_write_operations_in_store_bucket` need to use the original function context. let interp = self.mem.build_interpreter(self.global_data, self.observer); - let observe = observe && !interp.observer.ignore_function_calls(); + let observe = observe && !interp.observer.ignore_extracted_function_calls(); let instructions = &env.get_function(name).body; unsafe { let ptr = instructions.as_ptr(); @@ -480,7 +488,7 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { // The extracted loop body and array parameter functions can change any values in // the environment via the parameters passed to it. So interpret the function and // keep the resulting Env (as if the function had executed inline). - self.run_function_loopbody(&bucket.symbol, env, observe) + self.run_function_extracted(&bucket, env, observe) } else { let mut args = vec![]; for i in &bucket.arguments { diff --git a/circuit_passes/src/bucket_interpreter/observed_visitor.rs b/circuit_passes/src/bucket_interpreter/observed_visitor.rs new file mode 100644 index 000000000..57bae3a9a --- /dev/null +++ b/circuit_passes/src/bucket_interpreter/observed_visitor.rs @@ -0,0 +1,145 @@ +use code_producers::llvm_elements::fr::BUILT_IN_NAMES; +use compiler::intermediate_representation::InstructionPointer; +use compiler::intermediate_representation::ir_interface::*; +use super::env::LibraryAccess; +use super::observer::Observer; + +pub struct ObservedVisitor<'a, S> { + observer: &'a dyn Observer, + libs: Option<&'a dyn LibraryAccess>, +} + +impl<'a, S> ObservedVisitor<'a, S> { + pub fn new(observer: &'a dyn Observer, libs: Option<&'a dyn LibraryAccess>) -> Self { + ObservedVisitor { observer, libs } + } + + pub fn visit_address_type(&self, addr_type: &AddressType, state: &S, observe: bool) { + if let AddressType::SubcmpSignal { cmp_address, .. } = addr_type { + self.visit_instruction(cmp_address, state, observe); + } + } + + pub fn visit_location_rule(&self, location_rule: &LocationRule, state: &S, observe: bool) { + match location_rule { + LocationRule::Indexed { location, .. } => { + self.visit_instruction(location, state, observe); + } + LocationRule::Mapped { indexes, .. } => { + self.visit_instructions(indexes, state, observe) + } + } + } + + pub fn visit_load_bucket(&self, bucket: &LoadBucket, state: &S, observe: bool) { + self.visit_address_type(&bucket.address_type, state, observe); + self.visit_location_rule(&bucket.src, state, observe); + } + + pub fn visit_store_bucket(&self, bucket: &StoreBucket, state: &S, observe: bool) { + self.visit_instruction(&bucket.src, state, observe); + self.visit_address_type(&bucket.dest_address_type, state, observe); + self.visit_location_rule(&bucket.dest, state, observe); + } + + pub fn visit_call_bucket(&self, bucket: &CallBucket, state: &S, observe: bool) { + self.visit_instructions(&bucket.arguments, state, observe); + if let ReturnType::Final(fd) = &bucket.return_info { + self.visit_address_type(&fd.dest_address_type, state, observe); + self.visit_location_rule(&fd.dest, state, observe); + } + // Visit the callee function body if LibraryAccess was provided + if let Some(libs) = self.libs { + let name = &bucket.symbol; + // Skip those that cannot be visited (i.e. not yet in Circuit.functions) + if !BUILT_IN_NAMES.with(|f| f.contains(name.as_str())) { + self.visit_instructions( + &libs.get_function(name).body, + state, + observe && !self.observer.ignore_call(name), + ); + } + } + } + + pub fn visit_compute_bucket(&self, bucket: &ComputeBucket, state: &S, observe: bool) { + self.visit_instructions(&bucket.stack, state, observe); + } + + pub fn visit_assert_bucket(&self, bucket: &AssertBucket, state: &S, observe: bool) { + self.visit_instruction(&bucket.evaluate, state, observe); + } + + pub fn visit_loop_bucket(&self, bucket: &LoopBucket, state: &S, observe: bool) { + self.visit_instruction(&bucket.continue_condition, state, observe); + self.visit_instructions(&bucket.body, state, observe); + } + + pub fn visit_create_cmp_bucket(&self, bucket: &CreateCmpBucket, state: &S, observe: bool) { + self.visit_instruction(&bucket.sub_cmp_id, state, observe); + } + + pub fn visit_constraint_bucket(&self, bucket: &ConstraintBucket, state: &S, observe: bool) { + self.visit_instruction( + match bucket { + ConstraintBucket::Substitution(i) => i, + ConstraintBucket::Equality(i) => i, + }, + state, + observe, + ); + } + + pub fn visit_block_bucket(&self, bucket: &BlockBucket, state: &S, observe: bool) { + self.visit_instructions(&bucket.body, state, observe); + } + + pub fn visit_branch_bucket(&self, bucket: &BranchBucket, state: &S, observe: bool) { + self.visit_instruction(&bucket.cond, state, observe); + self.visit_instructions(&bucket.if_branch, state, observe); + self.visit_instructions(&bucket.else_branch, state, observe); + } + + pub fn visit_return_bucket(&self, bucket: &ReturnBucket, state: &S, observe: bool) { + self.visit_instruction(&bucket.value, state, observe); + } + + pub fn visit_log_bucket(&self, bucket: &LogBucket, state: &S, observe: bool) { + for arg in &bucket.argsprint { + if let LogBucketArg::LogExp(i) = arg { + self.visit_instruction(i, state, observe); + } + } + } + + pub fn visit_value_bucket(&self, _bucket: &ValueBucket, _state: &S, _observe: bool) {} + + pub fn visit_nop_bucket(&self, _bucket: &NopBucket, _state: &S, _observe: bool) {} + + pub fn visit_instructions(&self, insts: &Vec, state: &S, observe: bool) { + for i in insts { + self.visit_instruction(i, state, observe); + } + } + + pub fn visit_instruction(&self, inst: &InstructionPointer, state: &S, observe: bool) { + let keep_observing = + if observe { self.observer.on_instruction(inst, state) } else { observe }; + match inst.as_ref() { + Instruction::Value(b) => self.visit_value_bucket(b, state, keep_observing), + Instruction::Load(b) => self.visit_load_bucket(b, state, keep_observing), + Instruction::Store(b) => self.visit_store_bucket(b, state, keep_observing), + Instruction::Compute(b) => self.visit_compute_bucket(b, state, keep_observing), + Instruction::Call(b) => self.visit_call_bucket(b, state, keep_observing), + Instruction::Branch(b) => self.visit_branch_bucket(b, state, keep_observing), + Instruction::Return(b) => self.visit_return_bucket(b, state, keep_observing), + Instruction::Assert(b) => self.visit_assert_bucket(b, state, keep_observing), + Instruction::Log(b) => self.visit_log_bucket(b, state, keep_observing), + Instruction::Loop(b) => self.visit_loop_bucket(b, state, keep_observing), + Instruction::CreateCmp(b) => self.visit_create_cmp_bucket(b, state, keep_observing), + Instruction::Constraint(b) => self.visit_constraint_bucket(b, state, keep_observing), + Instruction::Block(b) => self.visit_block_bucket(b, state, keep_observing), + Instruction::Nop(b) => self.visit_nop_bucket(b, state, keep_observing), + } + } +} diff --git a/circuit_passes/src/bucket_interpreter/observer.rs b/circuit_passes/src/bucket_interpreter/observer.rs index b6cc713d1..cd8b41f38 100644 --- a/circuit_passes/src/bucket_interpreter/observer.rs +++ b/circuit_passes/src/bucket_interpreter/observer.rs @@ -1,49 +1,58 @@ +use code_producers::llvm_elements::stdlib::GENERATED_FN_PREFIX; use compiler::intermediate_representation::{Instruction, InstructionPointer}; use compiler::intermediate_representation::ir_interface::{ AssertBucket, BranchBucket, CallBucket, ComputeBucket, ConstraintBucket, CreateCmpBucket, LoadBucket, LocationRule, LogBucket, LoopBucket, NopBucket, ReturnBucket, StoreBucket, BlockBucket, ValueBucket, }; -use crate::bucket_interpreter::env::Env; -/// Will get called everytime we are about to execute a bucket, with access to the environment -/// prior to the execution of the bucket -pub trait InterpreterObserver { - fn on_value_bucket(&self, bucket: &ValueBucket, env: &Env) -> bool; - fn on_load_bucket(&self, bucket: &LoadBucket, env: &Env) -> bool; - fn on_store_bucket(&self, bucket: &StoreBucket, env: &Env) -> bool; - fn on_compute_bucket(&self, bucket: &ComputeBucket, env: &Env) -> bool; - fn on_assert_bucket(&self, bucket: &AssertBucket, env: &Env) -> bool; - fn on_loop_bucket(&self, bucket: &LoopBucket, env: &Env) -> bool; - fn on_create_cmp_bucket(&self, bucket: &CreateCmpBucket, env: &Env) -> bool; - fn on_constraint_bucket(&self, bucket: &ConstraintBucket, env: &Env) -> bool; - fn on_block_bucket(&self, bucket: &BlockBucket, env: &Env) -> bool; - fn on_nop_bucket(&self, bucket: &NopBucket, env: &Env) -> bool; - fn on_location_rule(&self, location_rule: &LocationRule, env: &Env) -> bool; - fn on_call_bucket(&self, bucket: &CallBucket, env: &Env) -> bool; - fn on_branch_bucket(&self, bucket: &BranchBucket, env: &Env) -> bool; - fn on_return_bucket(&self, bucket: &ReturnBucket, env: &Env) -> bool; - fn on_log_bucket(&self, bucket: &LogBucket, env: &Env) -> bool; +/// Will get called everytime some visitor is about to visit a bucket, +/// with access to the state data prior to the execution of the bucket. +pub trait Observer { + fn on_value_bucket(&self, bucket: &ValueBucket, state: &S) -> bool; + fn on_load_bucket(&self, bucket: &LoadBucket, state: &S) -> bool; + fn on_store_bucket(&self, bucket: &StoreBucket, state: &S) -> bool; + fn on_compute_bucket(&self, bucket: &ComputeBucket, state: &S) -> bool; + fn on_assert_bucket(&self, bucket: &AssertBucket, state: &S) -> bool; + fn on_loop_bucket(&self, bucket: &LoopBucket, state: &S) -> bool; + fn on_create_cmp_bucket(&self, bucket: &CreateCmpBucket, state: &S) -> bool; + fn on_constraint_bucket(&self, bucket: &ConstraintBucket, state: &S) -> bool; + fn on_block_bucket(&self, bucket: &BlockBucket, state: &S) -> bool; + fn on_nop_bucket(&self, bucket: &NopBucket, state: &S) -> bool; + fn on_location_rule(&self, location_rule: &LocationRule, state: &S) -> bool; + fn on_call_bucket(&self, bucket: &CallBucket, state: &S) -> bool; + fn on_branch_bucket(&self, bucket: &BranchBucket, state: &S) -> bool; + fn on_return_bucket(&self, bucket: &ReturnBucket, state: &S) -> bool; + fn on_log_bucket(&self, bucket: &LogBucket, state: &S) -> bool; - fn on_instruction(&self, inst: &InstructionPointer, env: &Env) -> bool { + fn on_instruction(&self, inst: &InstructionPointer, state: &S) -> bool { match inst.as_ref() { - Instruction::Value(bucket) => self.on_value_bucket(bucket, env), - Instruction::Load(bucket) => self.on_load_bucket(bucket, env), - Instruction::Store(bucket) => self.on_store_bucket(bucket, env), - Instruction::Compute(bucket) => self.on_compute_bucket(bucket, env), - Instruction::Call(bucket) => self.on_call_bucket(bucket, env), - Instruction::Branch(bucket) => self.on_branch_bucket(bucket, env), - Instruction::Return(bucket) => self.on_return_bucket(bucket, env), - Instruction::Assert(bucket) => self.on_assert_bucket(bucket, env), - Instruction::Log(bucket) => self.on_log_bucket(bucket, env), - Instruction::Loop(bucket) => self.on_loop_bucket(bucket, env), - Instruction::CreateCmp(bucket) => self.on_create_cmp_bucket(bucket, env), - Instruction::Constraint(bucket) => self.on_constraint_bucket(bucket, env), - Instruction::Block(bucket) => self.on_block_bucket(bucket, env), - Instruction::Nop(bucket) => self.on_nop_bucket(bucket, env), + Instruction::Value(bucket) => self.on_value_bucket(bucket, state), + Instruction::Load(bucket) => self.on_load_bucket(bucket, state), + Instruction::Store(bucket) => self.on_store_bucket(bucket, state), + Instruction::Compute(bucket) => self.on_compute_bucket(bucket, state), + Instruction::Call(bucket) => self.on_call_bucket(bucket, state), + Instruction::Branch(bucket) => self.on_branch_bucket(bucket, state), + Instruction::Return(bucket) => self.on_return_bucket(bucket, state), + Instruction::Assert(bucket) => self.on_assert_bucket(bucket, state), + Instruction::Log(bucket) => self.on_log_bucket(bucket, state), + Instruction::Loop(bucket) => self.on_loop_bucket(bucket, state), + Instruction::CreateCmp(bucket) => self.on_create_cmp_bucket(bucket, state), + Instruction::Constraint(bucket) => self.on_constraint_bucket(bucket, state), + Instruction::Block(bucket) => self.on_block_bucket(bucket, state), + Instruction::Nop(bucket) => self.on_nop_bucket(bucket, state), } } - fn ignore_function_calls(&self) -> bool; fn ignore_subcmp_calls(&self) -> bool; + fn ignore_function_calls(&self) -> bool; + fn ignore_extracted_function_calls(&self) -> bool; + + fn ignore_call(&self, callee: &String) -> bool { + if callee.starts_with(GENERATED_FN_PREFIX) { + self.ignore_extracted_function_calls() + } else { + self.ignore_function_calls() + } + } } diff --git a/circuit_passes/src/passes/conditional_flattening.rs b/circuit_passes/src/passes/conditional_flattening.rs index a2b469cae..80b2555a5 100644 --- a/circuit_passes/src/passes/conditional_flattening.rs +++ b/circuit_passes/src/passes/conditional_flattening.rs @@ -1,19 +1,36 @@ use std::cell::RefCell; -use std::collections::BTreeMap; +use std::collections::{HashMap, BTreeMap}; +use compiler::circuit_design::function::FunctionCode; use compiler::circuit_design::template::TemplateCode; use compiler::compiler_interface::Circuit; -use compiler::intermediate_representation::{InstructionPointer, new_id}; +use compiler::intermediate_representation::{InstructionPointer, new_id, BucketId}; use compiler::intermediate_representation::ir_interface::*; -use crate::bucket_interpreter::env::Env; +use indexmap::{IndexMap, IndexSet}; +use crate::bucket_interpreter::env::{Env, LibraryAccess}; use crate::bucket_interpreter::memory::PassMemory; -use crate::bucket_interpreter::observer::InterpreterObserver; +use crate::bucket_interpreter::observer::Observer; use super::{CircuitTransformationPass, GlobalPassData}; +type BranchValues = BTreeMap>; + pub struct ConditionalFlatteningPass<'d> { global_data: &'d RefCell, - // Wrapped in a RefCell because the reference to the static analysis is immutable but we need mutability memory: PassMemory, - replacements: RefCell>, + // Wrapped in a RefCell because the reference to the static analysis is immutable but we need mutability + // + /// Maps the ID of the CallBucket that is currently on the interpreter's stack (or None if the + /// interpreter is currently analyzing code that is not in one of the generated loopbody functions) + /// to a list of (ID, evaluated condition) pairs for the BranchBuckets in the current context. + evaluated_conditions: RefCell, BranchValues>>, + /// Track the order that the branches appear in the traversal to stabilize output for lit tests. + branch_bucket_order: RefCell>, + /// Maps CallBucket symbol (i.e. target function name) to BranchBucket value mapping to the + /// new function that has brances simplified according to that mapping. + /// NOTE: Uses IndexMap to preserve insertion order to stabilize lit test output. + new_functions: RefCell>>, + /// Within the CircuitTransformationPass impl below, this holds the BranchBucket + /// condition for when the function is called by the current CallBucket. + caller_context: RefCell>, } impl<'d> ConditionalFlatteningPass<'d> { @@ -21,12 +38,28 @@ impl<'d> ConditionalFlatteningPass<'d> { ConditionalFlatteningPass { global_data, memory: PassMemory::new(prime, "".to_string(), Default::default()), - replacements: Default::default(), + evaluated_conditions: Default::default(), + branch_bucket_order: Default::default(), + new_functions: Default::default(), + //The None key in this map is for the cases that are NOT inside the loopbody functions. When + // traversal enters a loopbody function, this will change to the BranchValues of that CallBucket. + caller_context: RefCell::new(None), + } + } + + fn get_known_condition(&self, bucket_id: &BucketId) -> Option { + // Get from the current 'caller_context' or lookup via None key in 'evaluated_conditions' + let ec = self.evaluated_conditions.borrow(); + if let Some(bv) = self.caller_context.borrow().as_ref().or_else(|| ec.get(&None)) { + if let Some(Some(side)) = bv.get(bucket_id) { + return Some(*side); + } } + None } } -impl InterpreterObserver for ConditionalFlatteningPass<'_> { +impl Observer> for ConditionalFlatteningPass<'_> { fn on_value_bucket(&self, _bucket: &ValueBucket, _env: &Env) -> bool { true } @@ -84,9 +117,28 @@ impl InterpreterObserver for ConditionalFlatteningPass<'_> { env.clone(), false, ); - if cond_result.is_some() { - self.replacements.borrow_mut().insert(bucket.clone(), cond_result.unwrap()); - } + // Store the result for the current bucket in the list for the current caller. + // NOTE: Store 'cond_result' even when it is None (meaning the BranchBucket + // condition could not be determined) so that it will fully differentiate the + // branching behavior of functions called at multiple sites. + let in_func = env.extracted_func_caller().map(|n| n.clone()); + // NOTE: 'in_func' is None when the current branch is NOT located within a function + // that was generated during loop unrolling to hold the body of a loop. + self.evaluated_conditions + .borrow_mut() + .entry(in_func) + .or_default() + .entry(bucket.id) + // If an existing entry is not equal to the new computed value, use None for unknown + .and_modify(|e| { + if *e != cond_result { + *e = None + } + }) + // If there was no entry, insert the computed value + .or_insert(cond_result); + // + self.branch_bucket_order.borrow_mut().insert(bucket.id); true } @@ -105,6 +157,10 @@ impl InterpreterObserver for ConditionalFlatteningPass<'_> { fn ignore_subcmp_calls(&self) -> bool { true } + + fn ignore_extracted_function_calls(&self) -> bool { + false + } } impl CircuitTransformationPass for ConditionalFlatteningPass<'_> { @@ -120,14 +176,91 @@ impl CircuitTransformationPass for ConditionalFlatteningPass<'_> { self.memory.fill_from_circuit(circuit); } + fn post_hook_circuit(&self, cir: &mut Circuit) { + // Add the new functions + for (_, ev) in self.new_functions.borrow_mut().drain(..) { + for f in ev.into_values() { + cir.functions.push(f); + } + } + } + fn pre_hook_template(&self, template: &TemplateCode) { self.memory.set_scope(template); self.memory.run_template(self.global_data, self, template); } + fn transform_call_bucket(&self, bucket: &CallBucket) -> InstructionPointer { + let call_bucket_id = Some(bucket.id); + // The Some keys in the 'evaluated_conditions' map are for the cases that are inside + // the loopbody functions when executed from the CallBucket.id used as the key. + // NOTE: This borrow is inside brackets to prevent runtime double borrow error. + let ec = { self.evaluated_conditions.borrow_mut().remove(&call_bucket_id) }; + if let Some(ev) = ec { + // If there are any conditions that evaluated to a known value, replace the + // CallBucket target function with a simplified version of that function. + if ev.values().any(|e| e.is_some()) { + let mut nf = self.new_functions.borrow_mut(); + // Check if the needed function exists, else create it. + let old_name = &bucket.symbol; + // Build the new function name according to the values in 'ev' but sorted by 'branch_bucket_order' + let new_name = + self.branch_bucket_order.borrow().iter().filter_map(|id| ev.get(id)).fold( + old_name.clone(), + |acc, e| match e { + Some(true) => format!("{}.T", acc), + Some(false) => format!("{}.F", acc), + None => format!("{}.N", acc), + }, + ); + let new_target = nf + .entry(bucket.symbol.clone()) + .or_default() + .entry(ev) + .or_insert_with_key(|k| { + //Set the 'within_call' context and then use self.transform_function(..) + // on the existing extracted loopbody function to create a new + // FunctionCode by running this transformer on the existing one. + let old = self.caller_context.replace(Some(k.clone())); + let mut res = self.transform_function(&self.memory.get_function(old_name)); + self.caller_context.replace(old); + res.header = new_name; + res + }) + .header + .clone(); + return CallBucket { + id: new_id(), + source_file_id: bucket.source_file_id, + line: bucket.line, + message_id: bucket.message_id, + symbol: new_target, + argument_types: bucket.argument_types.clone(), + arguments: self.transform_instructions(&bucket.arguments), + arena_size: bucket.arena_size, + return_info: self.transform_return_type(&bucket.id, &bucket.return_info), + } + .allocate(); + } + } + // Default case: no change + CallBucket { + id: new_id(), + source_file_id: bucket.source_file_id, + line: bucket.line, + message_id: bucket.message_id, + symbol: bucket.symbol.to_string(), + argument_types: bucket.argument_types.clone(), + arguments: self.transform_instructions(&bucket.arguments), + arena_size: bucket.arena_size, + return_info: self.transform_return_type(&bucket.id, &bucket.return_info), + } + .allocate() + } + fn transform_branch_bucket(&self, bucket: &BranchBucket) -> InstructionPointer { - if let Some(side) = self.replacements.borrow().get(&bucket) { - let code = if *side { &bucket.if_branch } else { &bucket.else_branch }; + if let Some(side) = self.get_known_condition(&bucket.id) { + let code = if side { &bucket.if_branch } else { &bucket.else_branch }; let block = BlockBucket { id: new_id(), source_file_id: bucket.source_file_id, @@ -137,18 +270,18 @@ impl CircuitTransformationPass for ConditionalFlatteningPass<'_> { n_iters: 1, label: format!("fold_{}", side), }; - self.transform_block_bucket(&block) - } else { - BranchBucket { - id: new_id(), - source_file_id: bucket.source_file_id, - line: bucket.line, - message_id: bucket.message_id, - cond: self.transform_instruction(&bucket.cond), - if_branch: self.transform_instructions(&bucket.if_branch), - else_branch: self.transform_instructions(&bucket.else_branch), - } - .allocate() + return self.transform_block_bucket(&block); + } + // Default case: no change + BranchBucket { + id: new_id(), + source_file_id: bucket.source_file_id, + line: bucket.line, + message_id: bucket.message_id, + cond: self.transform_instruction(&bucket.cond), + if_branch: self.transform_instructions(&bucket.if_branch), + else_branch: self.transform_instructions(&bucket.else_branch), } + .allocate() } } diff --git a/circuit_passes/src/passes/deterministic_subcomponent_invocation.rs b/circuit_passes/src/passes/deterministic_subcomponent_invocation.rs index 1e9b9e5c6..ecf09d591 100644 --- a/circuit_passes/src/passes/deterministic_subcomponent_invocation.rs +++ b/circuit_passes/src/passes/deterministic_subcomponent_invocation.rs @@ -6,7 +6,7 @@ use compiler::intermediate_representation::ir_interface::*; use compiler::intermediate_representation::ir_interface::StatusInput::{Last, NoLast}; use crate::bucket_interpreter::env::Env; use crate::bucket_interpreter::memory::PassMemory; -use crate::bucket_interpreter::observer::InterpreterObserver; +use crate::bucket_interpreter::observer::Observer; use super::{CircuitTransformationPass, GlobalPassData}; pub struct DeterministicSubCmpInvokePass<'d> { @@ -48,7 +48,7 @@ impl<'d> DeterministicSubCmpInvokePass<'d> { } } -impl InterpreterObserver for DeterministicSubCmpInvokePass<'_> { +impl Observer> for DeterministicSubCmpInvokePass<'_> { fn on_value_bucket(&self, _bucket: &ValueBucket, _env: &Env) -> bool { true } @@ -123,6 +123,10 @@ impl InterpreterObserver for DeterministicSubCmpInvokePass<'_> { fn ignore_subcmp_calls(&self) -> bool { true } + + fn ignore_extracted_function_calls(&self) -> bool { + false + } } impl CircuitTransformationPass for DeterministicSubCmpInvokePass<'_> { diff --git a/circuit_passes/src/passes/loop_unroll/body_extractor.rs b/circuit_passes/src/passes/loop_unroll/body_extractor.rs index 3bfef2689..86b08407f 100644 --- a/circuit_passes/src/passes/loop_unroll/body_extractor.rs +++ b/circuit_passes/src/passes/loop_unroll/body_extractor.rs @@ -1,5 +1,5 @@ use std::cell::{RefCell, Ref}; -use std::collections::{BTreeMap, HashMap}; +use std::collections::{BTreeMap, HashMap, HashSet}; use std::vec; use indexmap::{IndexMap, IndexSet}; use code_producers::llvm_elements::fr::*; @@ -10,7 +10,7 @@ use compiler::intermediate_representation::{ }; use compiler::intermediate_representation::ir_interface::*; use crate::bucket_interpreter::value::Value; -use crate::passes::loop_unroll::LOOP_BODY_FN_PREFIX; +use crate::passes::loop_unroll::{DEBUG_LOOP_UNROLL, LOOP_BODY_FN_PREFIX}; use crate::passes::loop_unroll::extracted_location_updater::ExtractedFunctionLocationUpdater; use crate::passes::loop_unroll::loop_env_recorder::EnvRecorder; use crate::passes::{builders, checks}; @@ -90,16 +90,42 @@ impl ExtraArgsResult { .collect() } - fn get_reverse_passing_refs_for_itr(&self, iter_num: usize) -> ToOriginalLocation { - self.bucket_to_itr_to_ref.iter().fold(ToOriginalLocation::new(), |mut acc, (k, v)| { - if let Some((addr_ty, addr_offset)) = v[iter_num].as_ref() { - acc.insert( - self.bucket_to_args[k].get_signal_idx(), - (addr_ty.clone(), *addr_offset), - ); - } - acc - }) + fn get_reverse_passing_refs_for_itr( + &self, + iter_num: usize, + ) -> (ToOriginalLocation, HashSet) { + self.bucket_to_itr_to_ref.iter().fold( + (ToOriginalLocation::new(), HashSet::new()), + |mut acc, (k, v)| { + if let Some((addr_ty, addr_offset)) = v[iter_num].as_ref() { + let ai = self.bucket_to_args[k]; + acc.0.insert(ai.get_signal_idx(), (addr_ty.clone(), *addr_offset)); + // If applicable, insert the subcmp counter reference as well + if let ArgIndex::SubCmp { counter, arena, .. } = ai { + match addr_ty { + AddressType::SubcmpSignal { counter_override, cmp_address, .. } => { + assert_eq!(*counter_override, false); //there's no counter for a counter + let counter_addr_ty = AddressType::SubcmpSignal { + cmp_address: cmp_address.clone(), + uniform_parallel_value: None, + is_output: false, + input_information: InputInformation::NoInput, + counter_override: true, + }; + // NOTE: when there's a true subcomponent (indicated by the ArgIndex::SubCmp check above), + // the 'addr_offset' indicates which signal inside the subcomponent is accessed. That + // value is not relevant here because subcomponents have a single counter variable. + acc.0.insert(counter, (counter_addr_ty, 0)); + // + acc.1.insert(arena); + } + _ => unreachable!(), // SubcmpSignal was created for all of these refs + } + } + } + acc + }, + ) } } @@ -275,6 +301,21 @@ impl LoopBodyExtractor { func_name } + /// Create an Iterator containing the results of applying the given + /// function to only the `Some` entries in the given vector. + fn filter_map<'a, A, B, C>( + column: &'a Vec>, + f: impl FnMut(&(A, B)) -> C + 'a, + ) -> impl Iterator + '_ { + column.iter().filter_map(|x| x.as_ref()).map(f) + } + + /// Create an Iterator containing the results of applying the given + /// function to only the `Some` entries in the given vector. + fn filter_map_any(column: &Vec>, f: impl FnMut(&(A, B)) -> bool) -> bool { + column.iter().filter_map(|x| x.as_ref()).any(f) + } + /// The ideal scenario for extracting the loop body into a new function is to only /// need 2 function arguments, lvars and signals. However, we want to avoid variable /// indexing within the extracted function so we include extra pointer arguments @@ -282,7 +323,7 @@ impl LoopBodyExtractor { /// unrolled and the indexing will become known constant values. This computes the /// extra arguments that will be needed. fn compute_extra_args<'a>(recorder: &'a EnvRecorder<'a, '_>) -> ExtraArgsResult { - // Table structure indexed first by load/store BucketId, then by iteration number. + // Table structure indexed first by load/store/call BucketId, then by iteration number. // View the first (BucketId) as columns and the second (iteration number) as rows. // The data reference is wrapped in Option to allow for some iterations that don't // execute a specific bucket due to conditional branches within the loop body. @@ -300,7 +341,7 @@ impl LoopBodyExtractor { // NOTE: starts at 2 because the current component's signal arena and lvars are first. let mut next_idx: FuncArgIdx = 2; // First step is to collect all location references into the 'bucket_to_itr_to_ref' table. - // NOTE: collect to IndexSet to preserve insertion order to stabilize test output. + // NOTE: Uses IndexSet to preserve insertion order to stabilize lit test output. let all_loadstore_bucket_ids: IndexSet<&BucketId> = vpi.values().flat_map(|x| x.loadstore_to_index.keys()).collect(); for id in all_loadstore_bucket_ids { @@ -311,17 +352,18 @@ impl LoopBodyExtractor { assert!(temp.is_none() || !temp.unwrap().1.is_unknown()); column.push(temp.map(|(a, v)| (a.clone(), v.get_u32()))); } + if DEBUG_LOOP_UNROLL { + println!("bucket {} refs by iteration: {:?}", id, column); + } // ASSERT: same AddressType kind for this bucket in every (available) iteration - assert!(checks::all_same( - column.iter().filter_map(|x| x.as_ref()).map(|x| std::mem::discriminant(&x.0)) - )); + assert!(checks::all_same(Self::filter_map(column, |(x, _)| std::mem::discriminant(x)))); - // Check if the computed index value for this bucket is the same across all iterations (where it is - // not None, see earlier comment). If it is not, then an extra function argument is needed for it. - // Actually, check not only the computed index Value but the AddressType as well to capture when - // it's a SubcmpSignal referencing a different subcomponent (the AddressType::cmp_address field - // was also interpreted within the EnvRecorder so this comparison will be accurate). - if !checks::all_same(column.iter().filter_map(|x| x.as_ref())) { + // If the computed index value for this bucket is NOT the same across all available + // iterations (i.e. where it is not None, see earlier comment) or if the AddressType + // is SubcmpSignal, then an extra function argument is needed for it. + if Self::filter_map_any(column, |(x, _)| matches!(x, AddressType::SubcmpSignal { .. })) + || !checks::all_same(Self::filter_map(column, |(_, y)| *y)) + { bucket_to_args.insert(*id, ArgIndex::Signal(next_idx)); next_idx += 1; } @@ -341,7 +383,7 @@ impl LoopBodyExtractor { .map(|(k, col)| (k, &col[iter_num])) .fold(BTreeMap::new(), |mut r, (b, a)| { if let Some((at, _)) = a { - if let AddressType::SubcmpSignal { .. } = at { + if matches!(at, AddressType::SubcmpSignal { .. }) { r.entry(SubcmpSignalHashFix::convert(&at)).or_default().insert(*b); } } @@ -368,18 +410,14 @@ impl LoopBodyExtractor { ArgIndex::SubCmp { signal: *sig, arena: arena_idx, counter: counter_idx }, ); } else { - //TODO: What to do when the signal index w/in the subcomp was not variant? - // Should I just add a parameter anyway? It doesn't hurt to do that so - // I guess that's the approach to take for now. - bucket_to_args.insert( - *b, - ArgIndex::SubCmp { - signal: next_idx, - arena: arena_idx, - counter: counter_idx, - }, - ); - next_idx += 1; + //Since SubcmpSignal is always added above, this should be unreachable. + unreachable!() + // bucket_to_args.insert( + // *b, + // ArgIndex::SubCmp { signal: next_idx, arena: arena_idx, counter: counter_idx, + // }, + // ); + // next_idx += 1; } } } diff --git a/circuit_passes/src/passes/loop_unroll/extracted_location_updater.rs b/circuit_passes/src/passes/loop_unroll/extracted_location_updater.rs index d20a83b9e..17bb42d12 100644 --- a/circuit_passes/src/passes/loop_unroll/extracted_location_updater.rs +++ b/circuit_passes/src/passes/loop_unroll/extracted_location_updater.rs @@ -1,5 +1,5 @@ use indexmap::IndexMap; -use code_producers::llvm_elements::fr::FR_IDENTITY_ARR_PTR; +use code_producers::llvm_elements::stdlib::LLVM_DONOTHING_FN_NAME; use compiler::intermediate_representation::{BucketId, InstructionPointer, new_id}; use compiler::intermediate_representation::ir_interface::*; use crate::passes::builders::build_u32_value; @@ -10,6 +10,13 @@ pub struct ExtractedFunctionLocationUpdater { pub insert_after: InstructionList, } +/// Used within extracted loopbody functions to replace all storage references +/// (i.e. AddressType + LocationRule) to instead reference the proper parameter +/// of the extracted function. These replacements cannot use AddressType::Variable +/// or AddressType::Signal because ExtractedFunctionLLVMIRProducer references the +/// first two parameters of the extracted function via those. Therefore, it must +/// use SubcmpSignal which will work seamlessly with existing subcmps because they +/// will also just be passed as additional parameters to the function. impl ExtractedFunctionLocationUpdater { pub fn new() -> ExtractedFunctionLocationUpdater { ExtractedFunctionLocationUpdater { insert_after: Default::default() } @@ -22,10 +29,6 @@ impl ExtractedFunctionLocationUpdater { ) { if let Some(ai) = bucket_arg_order.remove(&bucket.id) { // Update the location information to reference the argument - //NOTE: This can't use AddressType::Variable or AddressType::Signal - // because ExtractedFunctionLLVMIRProducer references the first two - // parameters with those. So this has to use SubcmpSignal (it should - // work fine because subcomps will also just be additional params). bucket.address_type = AddressType::SubcmpSignal { cmp_address: build_u32_value(bucket, ai.get_signal_idx()), uniform_parallel_value: None, @@ -44,73 +47,181 @@ impl ExtractedFunctionLocationUpdater { } } - fn check_store_bucket( + fn handle_any_store( &mut self, - bucket: &mut StoreBucket, - bucket_arg_order: &mut IndexMap, - ) { - // Check the source/RHS of the store in either case - self.check_instruction(&mut bucket.src, bucket_arg_order); - // - if let Some(ai) = bucket_arg_order.remove(&bucket.id) { - // If needed, add a StoreBucket to 'insert_after' that will call the template_run function. - // NOTE: This must happen before the modification step so it can use existing values from the bucket. - if let ArgIndex::SubCmp { arena, .. } = ai { - self.insert_after.push( - StoreBucket { + ai: &ArgIndex, + dest: &LocationRule, + bucket_meta: &dyn ObtainMeta, + ) -> (AddressType, LocationRule) { + // If the current argument involves an actual subcomponent, then generate additional code in the + // 'insert_after' list that will decrement the subcomponent counter and call the proper "_run" + // function for the template when the counter reaches 0. + // NOTE: This must happen before the modification step so it can use existing values from the bucket. + if let ArgIndex::SubCmp { counter, arena, .. } = ai { + let counter_address = AddressType::SubcmpSignal { + cmp_address: build_u32_value(bucket_meta, *counter), + uniform_parallel_value: None, + counter_override: true, + is_output: false, + input_information: InputInformation::NoInput, + }; + // Generate counter LoadBucket+ComputeBucket+StoreBucket in the "insert_after" list + // (based on what StoreBucket::produce_llvm_ir would normally generate for this). + self.insert_after.push( + StoreBucket { + id: new_id(), + source_file_id: bucket_meta.get_source_file_id().clone(), + line: bucket_meta.get_line(), + message_id: bucket_meta.get_message_id(), + context: InstrContext { size: 1 }, + dest_is_output: false, + dest_address_type: counter_address.clone(), + dest: LocationRule::Indexed { + location: build_u32_value(bucket_meta, 0), + template_header: None, + }, + bounded_fn: None, + src: ComputeBucket { id: new_id(), - source_file_id: bucket.source_file_id.clone(), - line: bucket.line, - message_id: bucket.message_id, - context: bucket.context.clone(), - dest_is_output: bucket.dest_is_output, + source_file_id: bucket_meta.get_source_file_id().clone(), + line: bucket_meta.get_line(), + message_id: bucket_meta.get_message_id(), + op: OperatorType::Sub, + op_aux_no: 0, + stack: vec![ + LoadBucket { + id: new_id(), + source_file_id: bucket_meta.get_source_file_id().clone(), + line: bucket_meta.get_line(), + message_id: bucket_meta.get_message_id(), + address_type: counter_address.clone(), + src: LocationRule::Indexed { + location: build_u32_value(bucket_meta, 0), + template_header: None, + }, + bounded_fn: None, + } + .allocate(), + ValueBucket { + id: new_id(), + source_file_id: bucket_meta.get_source_file_id().clone(), + line: bucket_meta.get_line(), + message_id: bucket_meta.get_message_id(), + parse_as: ValueType::U32, + op_aux_no: 0, + value: 1, + } + .allocate(), + ], + } + .allocate(), + } + .allocate(), + ); + + // Generate code to call the "run" function if the counter reaches 0 + self.insert_after.push( + BranchBucket { + id: new_id(), + source_file_id: bucket_meta.get_source_file_id().clone(), + line: bucket_meta.get_line(), + message_id: bucket_meta.get_message_id(), + cond: ComputeBucket { + id: new_id(), + source_file_id: bucket_meta.get_source_file_id().clone(), + line: bucket_meta.get_line(), + message_id: bucket_meta.get_message_id(), + op: OperatorType::Eq(1), + op_aux_no: 0, + stack: vec![ + LoadBucket { + id: new_id(), + source_file_id: bucket_meta.get_source_file_id().clone(), + line: bucket_meta.get_line(), + message_id: bucket_meta.get_message_id(), + address_type: counter_address, + src: LocationRule::Indexed { + location: build_u32_value(bucket_meta, 0), + template_header: None, + }, + bounded_fn: None, + } + .allocate(), + ValueBucket { + id: new_id(), + source_file_id: bucket_meta.get_source_file_id().clone(), + line: bucket_meta.get_line(), + message_id: bucket_meta.get_message_id(), + parse_as: ValueType::U32, + op_aux_no: 0, + value: 0, + } + .allocate(), + ], + } + .allocate(), + if_branch: vec![StoreBucket { + id: new_id(), + source_file_id: bucket_meta.get_source_file_id().clone(), + line: bucket_meta.get_line(), + message_id: bucket_meta.get_message_id(), + context: InstrContext { size: 1 }, + dest_is_output: false, dest_address_type: AddressType::SubcmpSignal { - cmp_address: build_u32_value(bucket, arena), + cmp_address: build_u32_value(bucket_meta, *arena), uniform_parallel_value: None, counter_override: false, is_output: false, - //TODO: Not sure what to put here. If I put Unknown (assuming the later pass - // would correct) it crashes somewhere. What I really need is Last in the - // proper place to make it generate the *_run function at the right time - // but NoLast in locations prior to that (I think). Why isn't Unknown handled - // by the later pass deterministic subcomp pass or something? Always using - // Last here could result in the run function being called too soon. - //SEE: circom/tests/subcmps/subcmps0C.circom input_information: InputInformation::Input { - status: StatusInput::Last, + status: StatusInput::Last, // This is the key to generating call to "run" function }, }, dest: LocationRule::Indexed { - location: build_u32_value(bucket, 0), //the value here is ignored by the 'bounded_fn' below - template_header: match &bucket.dest { + location: build_u32_value(bucket_meta, 0), //the value here is ignored by the 'bounded_fn' below + template_header: match dest { LocationRule::Indexed { template_header, .. } => { template_header.clone() } LocationRule::Mapped { .. } => todo!(), }, }, - src: build_u32_value(bucket, 0), //the value here is ignored at runtime - bounded_fn: Some(String::from(FR_IDENTITY_ARR_PTR)), //NOTE: doesn't have enough arguments but it works out + src: build_u32_value(bucket_meta, 0), //the value here is ignored at runtime + bounded_fn: Some(String::from(LLVM_DONOTHING_FN_NAME)), // actual result ignored, only need effect of 'StatusInput::Last' } - .allocate(), - ); - // NOTE: Not adding counter for now because it shouldn't be needed anyway and it's more work to add. - // The best approach would probably be to generate Load+Compute+Store (based on what StoreBucket - // would normally generate for it) in an "insert_before" list just like the "insert_after" list. - } - - //Transform this bucket into the normal fixed-index signal reference - bucket.dest_address_type = AddressType::SubcmpSignal { - cmp_address: build_u32_value(bucket, ai.get_signal_idx()), + .allocate()], + else_branch: vec![], + } + .allocate(), + ); + } + //Transform this bucket into the normal fixed-index signal reference + ( + AddressType::SubcmpSignal { + cmp_address: build_u32_value(bucket_meta, ai.get_signal_idx()), uniform_parallel_value: None, counter_override: false, is_output: false, input_information: InputInformation::NoInput, - }; - bucket.dest = LocationRule::Indexed { - location: build_u32_value(bucket, 0), //use index 0 to ref the entire storage array + }, + LocationRule::Indexed { + location: build_u32_value(bucket_meta, 0), //use index 0 to ref the entire storage array template_header: None, - }; + }, + ) + } + + fn check_store_bucket( + &mut self, + bucket: &mut StoreBucket, + bucket_arg_order: &mut IndexMap, + ) { + // Check the source/RHS of the store in either case + self.check_instruction(&mut bucket.src, bucket_arg_order); + // + if let Some(ai) = bucket_arg_order.remove(&bucket.id) { + let (at, lr) = self.handle_any_store(&ai, &bucket.dest, bucket); + bucket.dest_address_type = at; + bucket.dest = lr; } else { // If not replacing, check deeper in the AddressType and LocationRule self.check_address_type(&mut bucket.dest_address_type, bucket_arg_order); @@ -118,6 +229,28 @@ impl ExtractedFunctionLocationUpdater { } } + fn check_call_bucket( + &mut self, + bucket: &mut CallBucket, + bucket_arg_order: &mut IndexMap, + ) { + // Check the call parameters + self.check_instructions(&mut bucket.arguments, bucket_arg_order); + // A store can be implicit within a CallBucket 'return_info' + let bucket_meta = ObtainMetaImpl::from(bucket); //avoid borrow issues + if let ReturnType::Final(fd) = &mut bucket.return_info { + if let Some(ai) = bucket_arg_order.remove(&bucket.id) { + let (at, lr) = self.handle_any_store(&ai, &fd.dest, &bucket_meta); + fd.dest_address_type = at; + fd.dest = lr; + } else { + // If not replacing, check deeper in the AddressType and LocationRule + self.check_address_type(&mut fd.dest_address_type, bucket_arg_order); + self.check_location_rule(&mut fd.dest, bucket_arg_order); + } + } + } + fn check_location_rule( &mut self, location_rule: &mut LocationRule, @@ -196,14 +329,6 @@ impl ExtractedFunctionLocationUpdater { self.check_instructions(&mut bucket.body, bucket_arg_order); } - fn check_call_bucket( - &mut self, - bucket: &mut CallBucket, - bucket_arg_order: &mut IndexMap, - ) { - self.check_instructions(&mut bucket.arguments, bucket_arg_order); - } - fn check_branch_bucket( &mut self, bucket: &mut BranchBucket, diff --git a/circuit_passes/src/passes/loop_unroll/loop_env_recorder.rs b/circuit_passes/src/passes/loop_unroll/loop_env_recorder.rs index 8c1a3cc9b..cafb9bf1a 100644 --- a/circuit_passes/src/passes/loop_unroll/loop_env_recorder.rs +++ b/circuit_passes/src/passes/loop_unroll/loop_env_recorder.rs @@ -1,21 +1,22 @@ use std::cell::{RefCell, Ref}; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, HashSet}; use std::fmt::{Debug, Formatter}; use indexmap::IndexMap; use compiler::intermediate_representation::BucketId; use compiler::intermediate_representation::ir_interface::*; use crate::bucket_interpreter::env::Env; use crate::bucket_interpreter::memory::PassMemory; -use crate::bucket_interpreter::observer::InterpreterObserver; +use crate::bucket_interpreter::observer::Observer; use crate::bucket_interpreter::value::Value; use crate::passes::GlobalPassData; -use super::body_extractor::{UnrolledIterLvars, ToOriginalLocation}; +use super::DEBUG_LOOP_UNROLL; +use super::body_extractor::{UnrolledIterLvars, ToOriginalLocation, FuncArgIdx}; /// Holds values of index variables at array loads/stores within a loop pub struct VariableValues<'a> { pub env_at_header: Env<'a>, - /// The key is the ID of the load/store bucket where the reference is located. - /// NOTE: uses IndexMap to preserve insertion order to stabilize test output. + /// The key is the ID of the load/store/call bucket where the reference is located. + /// NOTE: Uses IndexMap to preserve insertion order to stabilize lit test output. pub loadstore_to_index: IndexMap, } @@ -106,7 +107,7 @@ impl<'a, 'd> EnvRecorder<'a, 'd> { &self, extract_func: String, iter_env: UnrolledIterLvars, - value: ToOriginalLocation, + value: (ToOriginalLocation, HashSet), ) { self.global_data .borrow_mut() @@ -171,6 +172,12 @@ impl<'a, 'd> EnvRecorder<'a, 'd> { fn visit(&self, bucket_id: &BucketId, addr_ty: &AddressType, loc: &LocationRule, env: &Env) { let loc_result = self.compute_index_from_rule(env, loc); if loc_result == Value::Unknown { + if DEBUG_LOOP_UNROLL { + println!( + "loop body is not safe to move because index is unknown from rule {:?}", + loc + ); + } self.safe_to_move.replace(false); } //NOTE: must record even when Unknown to ensure that Unknown value is not confused with @@ -189,6 +196,9 @@ impl<'a, 'd> EnvRecorder<'a, 'd> { AddressType::SubcmpSignal { cmp_address: { if addr_result == Value::Unknown { + if DEBUG_LOOP_UNROLL { + println!("loop body is not safe to move because index is unknown from addr {:?}", cmp_address); + } self.safe_to_move.replace(false); NopBucket { id: 0 }.allocate() } else { @@ -208,13 +218,18 @@ impl<'a, 'd> EnvRecorder<'a, 'd> { } } -impl InterpreterObserver for EnvRecorder<'_, '_> { +impl Observer> for EnvRecorder<'_, '_> { fn on_load_bucket(&self, bucket: &LoadBucket, env: &Env) -> bool { if let Some(_) = bucket.bounded_fn { todo!(); //not sure if/how to handle that } self.visit(&bucket.id, &bucket.address_type, &bucket.src, env); - true + // For a LoadBucket, there is no need to continue observing inside it and doing + // so can actually cause "assert!(bucket_to_args.is_empty())" to fail. See + // test "loops/fixed_idx_in_fixed_idx.circom" for an example and explanation. + // This is not applicable to other buckets because they have additional content + // inside of them that must be observed. + false } fn on_store_bucket(&self, bucket: &StoreBucket, env: &Env) -> bool { @@ -222,7 +237,14 @@ impl InterpreterObserver for EnvRecorder<'_, '_> { todo!(); //not sure if/how to handle that } self.visit(&bucket.id, &bucket.dest_address_type, &bucket.dest, env); - true + self.is_safe_to_move() //continue observing unless something unsafe has been found + } + + fn on_call_bucket(&self, bucket: &CallBucket, env: &Env) -> bool { + if let ReturnType::Final(fd) = &bucket.return_info { + self.visit(&bucket.id, &fd.dest_address_type, &fd.dest, env); + } + self.is_safe_to_move() //continue observing unless something unsafe has been found } fn on_value_bucket(&self, _bucket: &ValueBucket, _env: &Env) -> bool { @@ -261,10 +283,6 @@ impl InterpreterObserver for EnvRecorder<'_, '_> { self.is_safe_to_move() //continue observing unless something unsafe has been found } - fn on_call_bucket(&self, _bucket: &CallBucket, _env: &Env) -> bool { - self.is_safe_to_move() //continue observing unless something unsafe has been found - } - fn on_branch_bucket(&self, _bucket: &BranchBucket, _env: &Env) -> bool { self.is_safe_to_move() //continue observing unless something unsafe has been found } @@ -284,4 +302,8 @@ impl InterpreterObserver for EnvRecorder<'_, '_> { fn ignore_subcmp_calls(&self) -> bool { true } + + fn ignore_extracted_function_calls(&self) -> bool { + true + } } diff --git a/circuit_passes/src/passes/loop_unroll/mod.rs b/circuit_passes/src/passes/loop_unroll/mod.rs index 59f193a67..6121b6ba5 100644 --- a/circuit_passes/src/passes/loop_unroll/mod.rs +++ b/circuit_passes/src/passes/loop_unroll/mod.rs @@ -14,13 +14,15 @@ use compiler::intermediate_representation::{ use compiler::intermediate_representation::ir_interface::*; use crate::bucket_interpreter::env::Env; use crate::bucket_interpreter::memory::PassMemory; -use crate::bucket_interpreter::observer::InterpreterObserver; +use crate::bucket_interpreter::observer::Observer; use crate::passes::loop_unroll::loop_env_recorder::EnvRecorder; use super::{CircuitTransformationPass, GlobalPassData}; use self::body_extractor::LoopBodyExtractor; const EXTRACT_LOOP_BODY_TO_NEW_FUNC: bool = true; +const DEBUG_LOOP_UNROLL: bool = false; + pub const LOOP_BODY_FN_PREFIX: &str = const_format::concatcp!(GENERATED_FN_PREFIX, "loop.body."); pub struct LoopUnrollPass<'d> { @@ -42,6 +44,21 @@ impl<'d> LoopUnrollPass<'d> { } fn try_unroll_loop(&self, bucket: &LoopBucket, env: &Env) -> (Option, usize) { + if DEBUG_LOOP_UNROLL { + println!("\nTry unrolling loop {}:", bucket.id); //TODO: TEMP + for (i, s) in bucket.body.iter().enumerate() { + println!( + "[{}/{}]{}", + i + 1, + bucket.body.len(), + compiler::intermediate_representation::ToSExp::to_sexp(&**s).to_pretty(100) + ); + } + for (i, s) in bucket.body.iter().enumerate() { + println!("[{}/{}]{:?}", i + 1, bucket.body.len(), s); + } + println!("LOOP ENTRY env {}", env); //TODO: TEMP + } // Compute loop iteration count. If unknown, return immediately. let recorder = EnvRecorder::new(self.global_data, &self.memory); { @@ -62,6 +79,9 @@ impl<'d> LoopUnrollPass<'d> { inner_env = new_env; } } + if DEBUG_LOOP_UNROLL { + println!("recorder = {:?}", recorder); + } let mut block_body = vec![]; if EXTRACT_LOOP_BODY_TO_NEW_FUNC && recorder.is_safe_to_move() && recorder.get_iter() > 0 { @@ -81,7 +101,7 @@ impl<'d> LoopUnrollPass<'d> { } } } else { - //If the loop body is not safe to move into a new function, just unroll. + //If the loop body is not safe to move into a new function, just unroll in-place. for _ in 0..recorder.get_iter() { for s in &bucket.body { let mut copy = s.clone(); @@ -102,7 +122,7 @@ impl<'d> LoopUnrollPass<'d> { } } -impl InterpreterObserver for LoopUnrollPass<'_> { +impl Observer> for LoopUnrollPass<'_> { fn on_value_bucket(&self, _bucket: &ValueBucket, _env: &Env) -> bool { true } @@ -183,6 +203,10 @@ impl InterpreterObserver for LoopUnrollPass<'_> { fn ignore_subcmp_calls(&self) -> bool { true } + + fn ignore_extracted_function_calls(&self) -> bool { + true + } } impl CircuitTransformationPass for LoopUnrollPass<'_> { diff --git a/circuit_passes/src/passes/mapped_to_indexed.rs b/circuit_passes/src/passes/mapped_to_indexed.rs index 513fc9a1a..04739ad07 100644 --- a/circuit_passes/src/passes/mapped_to_indexed.rs +++ b/circuit_passes/src/passes/mapped_to_indexed.rs @@ -2,20 +2,24 @@ use std::cell::RefCell; use std::collections::BTreeMap; use compiler::circuit_design::template::TemplateCode; use compiler::compiler_interface::Circuit; -use compiler::intermediate_representation::ir_interface::*; +use compiler::intermediate_representation::{ir_interface::*, BucketId}; use compiler::intermediate_representation::{InstructionPointer, UpdateId}; use crate::bucket_interpreter::env::Env; use crate::bucket_interpreter::memory::PassMemory; -use crate::bucket_interpreter::observer::InterpreterObserver; +use crate::bucket_interpreter::observer::Observer; use crate::bucket_interpreter::operations::compute_offset; use crate::bucket_interpreter::value::Value::KnownU32; use super::{CircuitTransformationPass, GlobalPassData}; pub struct MappedToIndexedPass<'d> { global_data: &'d RefCell, - // Wrapped in a RefCell because the reference to the static analysis is immutable but we need mutability memory: PassMemory, - replacements: RefCell>, + /// Key is the BucketId of the bucket that holds the original LocationRule instance that needs to be + /// replaced and the mapped value is the new Indexed LocationRule. The BucketId must be used as key + /// instead of using the old LocationRule itself because the same Mapped LocationRule paired with a + /// different AddressType can result in a different Indexed LocationRule. + // Wrapped in a RefCell because the reference to the static analysis is immutable but we need mutability + replacements: RefCell>, } impl<'d> MappedToIndexedPass<'d> { @@ -43,70 +47,66 @@ impl<'d> MappedToIndexedPass<'d> { .expect("cmp_address instruction in SubcmpSignal must produce a value!") .get_u32(); - let mut acc_env = acc_env; let name = acc_env.get_subcmp_name(resolved_addr).clone(); let io_def = self.memory.get_iodef(&acc_env.get_subcmp_template_id(resolved_addr), &signal_code); - let map_access = io_def.offset; - if indexes.len() > 0 { + let offset = if indexes.len() > 0 { + let mut acc_env = acc_env; let mut indexes_values = vec![]; for i in indexes { let (val, new_env) = interpreter.execute_instruction(i, acc_env, false); indexes_values.push(val.expect("Mapped location must produce a value!").get_u32()); acc_env = new_env; } - let offset = compute_offset(&indexes_values, &io_def.lengths); - LocationRule::Indexed { - location: KnownU32(map_access + offset).to_value_bucket(&self.memory).allocate(), - template_header: Some(name), - } + io_def.offset + compute_offset(&indexes_values, &io_def.lengths) } else { - LocationRule::Indexed { - location: KnownU32(map_access).to_value_bucket(&self.memory).allocate(), - template_header: Some(name), - } + io_def.offset + }; + LocationRule::Indexed { + location: KnownU32(offset).to_value_bucket(&self.memory).allocate(), + template_header: Some(name), } } - fn maybe_transform_location_rule( + fn maybe_transform_location( &self, + bucket_id: &BucketId, address: &AddressType, location: &LocationRule, env: &Env, - ) -> bool { - match address { - AddressType::Variable | AddressType::Signal => match location { - LocationRule::Indexed { .. } => true, - LocationRule::Mapped { .. } => unreachable!(), - }, - AddressType::SubcmpSignal { cmp_address, .. } => match location { - LocationRule::Indexed { .. } => true, - LocationRule::Mapped { indexes, signal_code } => { + ) { + match location { + LocationRule::Mapped { indexes, signal_code } => match address { + AddressType::Variable | AddressType::Signal => unreachable!(), // cannot use mapped + AddressType::SubcmpSignal { cmp_address, .. } => { let indexed_rule = self.transform_mapped_loc_to_indexed_loc( cmp_address, indexes, *signal_code, env, ); - self.replacements.borrow_mut().insert(location.clone(), indexed_rule); - true + let old = self.replacements.borrow_mut().insert(*bucket_id, indexed_rule); + assert!(old.is_none()); // ensure nothing is unexpectedly overwritten } }, + LocationRule::Indexed { .. } => return, // do nothing for indexed } } } -impl InterpreterObserver for MappedToIndexedPass<'_> { +impl Observer> for MappedToIndexedPass<'_> { fn on_value_bucket(&self, _bucket: &ValueBucket, _env: &Env) -> bool { true } fn on_load_bucket(&self, bucket: &LoadBucket, env: &Env) -> bool { - self.maybe_transform_location_rule(&bucket.address_type, &bucket.src, env) + self.maybe_transform_location(&bucket.id, &bucket.address_type, &bucket.src, env); + true } fn on_store_bucket(&self, bucket: &StoreBucket, env: &Env) -> bool { - self.maybe_transform_location_rule(&bucket.dest_address_type, &bucket.dest, env) + self.maybe_transform_location(&bucket.id, &bucket.dest_address_type, &bucket.dest, env); + true } fn on_compute_bucket(&self, _bucket: &ComputeBucket, _env: &Env) -> bool { @@ -141,7 +141,10 @@ impl InterpreterObserver for MappedToIndexedPass<'_> { true } - fn on_call_bucket(&self, _bucket: &CallBucket, _env: &Env) -> bool { + fn on_call_bucket(&self, bucket: &CallBucket, env: &Env) -> bool { + if let ReturnType::Final(fd) = &bucket.return_info { + self.maybe_transform_location(&bucket.id, &fd.dest_address_type, &fd.dest, env); + } true } @@ -164,6 +167,10 @@ impl InterpreterObserver for MappedToIndexedPass<'_> { fn ignore_subcmp_calls(&self) -> bool { true } + + fn ignore_extracted_function_calls(&self) -> bool { + false + } } impl CircuitTransformationPass for MappedToIndexedPass<'_> { @@ -179,9 +186,12 @@ impl CircuitTransformationPass for MappedToIndexedPass<'_> { iangneal: Let the interpreter run to see if we can find any replacements. If so, yield the replacement. Else, just give the default transformation */ - fn transform_location_rule(&self, location_rule: &LocationRule) -> LocationRule { - // If the interpreter found a viable transformation, do that. - if let Some(indexed_rule) = self.replacements.borrow().get(&location_rule) { + fn transform_location_rule( + &self, + bucket_id: &BucketId, + location_rule: &LocationRule, + ) -> LocationRule { + if let Some(indexed_rule) = self.replacements.borrow().get(bucket_id) { let mut clone = indexed_rule.clone(); clone.update_id(); //generate a new unique ID for the clone to avoid assertion in checks.rs return clone; @@ -191,7 +201,7 @@ impl CircuitTransformationPass for MappedToIndexedPass<'_> { location: self.transform_instruction(location), template_header: template_header.clone(), }, - LocationRule::Mapped { .. } => unreachable!(), + LocationRule::Mapped { .. } => unreachable!(), // all Mapped locations were replaced above } } diff --git a/circuit_passes/src/passes/mod.rs b/circuit_passes/src/passes/mod.rs index 5e105b757..5d9adc1bf 100644 --- a/circuit_passes/src/passes/mod.rs +++ b/circuit_passes/src/passes/mod.rs @@ -4,7 +4,9 @@ use std::ops::Range; use compiler::circuit_design::function::{FunctionCode, FunctionCodeInfo}; use compiler::circuit_design::template::{TemplateCode, TemplateCodeInfo}; use compiler::compiler_interface::Circuit; -use compiler::intermediate_representation::{Instruction, InstructionList, InstructionPointer, new_id}; +use compiler::intermediate_representation::{ + Instruction, InstructionList, InstructionPointer, new_id, BucketId, +}; use compiler::intermediate_representation::ir_interface::*; use crate::passes::{ checks::assert_unique_ids_in_circuit, conditional_flattening::ConditionalFlatteningPass, @@ -12,14 +14,16 @@ use crate::passes::{ deterministic_subcomponent_invocation::DeterministicSubCmpInvokePass, loop_unroll::LoopUnrollPass, mapped_to_indexed::MappedToIndexedPass, simplification::SimplificationPass, unknown_index_sanitization::UnknownIndexSanitizationPass, + unused_func_removal::UnusedFuncRemovalPass, }; -use self::loop_unroll::body_extractor::{UnrolledIterLvars, ToOriginalLocation}; +use self::loop_unroll::body_extractor::{UnrolledIterLvars, ToOriginalLocation, FuncArgIdx}; mod const_arg_deduplication; mod conditional_flattening; mod simplification; mod deterministic_subcomponent_invocation; +mod unused_func_removal; mod mapped_to_indexed; mod unknown_index_sanitization; mod checks; @@ -183,7 +187,11 @@ pub trait CircuitTransformationPass { } } - fn transform_location_rule(&self, location_rule: &LocationRule) -> LocationRule { + fn transform_location_rule( + &self, + _bucket_id: &BucketId, + location_rule: &LocationRule, + ) -> LocationRule { match location_rule { LocationRule::Indexed { location, template_header } => LocationRule::Indexed { location: self.transform_instruction(location), @@ -203,7 +211,7 @@ pub trait CircuitTransformationPass { line: bucket.line, message_id: bucket.message_id, address_type: self.transform_address_type(&bucket.address_type), - src: self.transform_location_rule(&bucket.src), + src: self.transform_location_rule(&bucket.id, &bucket.src), bounded_fn: bucket.bounded_fn.clone(), } .allocate() @@ -218,7 +226,7 @@ pub trait CircuitTransformationPass { context: bucket.context.clone(), dest_is_output: bucket.dest_is_output, dest_address_type: self.transform_address_type(&bucket.dest_address_type), - dest: self.transform_location_rule(&bucket.dest), + dest: self.transform_location_rule(&bucket.id, &bucket.dest), src: self.transform_instruction(&bucket.src), bounded_fn: bucket.bounded_fn.clone(), } @@ -238,18 +246,18 @@ pub trait CircuitTransformationPass { .allocate() } - fn transform_final_data(&self, final_data: &FinalData) -> FinalData { + fn transform_final_data(&self, bucket_id: &BucketId, final_data: &FinalData) -> FinalData { FinalData { context: final_data.context, dest_is_output: final_data.dest_is_output, dest_address_type: self.transform_address_type(&final_data.dest_address_type), - dest: self.transform_location_rule(&final_data.dest), + dest: self.transform_location_rule(bucket_id, &final_data.dest), } } - fn transform_return_type(&self, return_type: &ReturnType) -> ReturnType { + fn transform_return_type(&self, bucket_id: &BucketId, return_type: &ReturnType) -> ReturnType { match return_type { - ReturnType::Final(f) => ReturnType::Final(self.transform_final_data(f)), + ReturnType::Final(f) => ReturnType::Final(self.transform_final_data(bucket_id, f)), x => x.clone(), } } @@ -264,7 +272,7 @@ pub trait CircuitTransformationPass { argument_types: bucket.argument_types.clone(), arguments: self.transform_instructions(&bucket.arguments), arena_size: bucket.arena_size, - return_info: self.transform_return_type(&bucket.return_info), + return_info: self.transform_return_type(&bucket.id, &bucket.return_info), } .allocate() } @@ -419,6 +427,7 @@ pub enum PassKind { LoopUnroll, Simplification, ConditionalFlattening, + UnusedFunctionRemoval, DeterministicSubCmpInvoke, MappedToIndexed, UnknownIndexSanitization, @@ -429,13 +438,28 @@ pub struct GlobalPassData { /// (from Env::get_vars_sort) to location reference in the original function. Used /// by ExtractedFuncEnvData to access the original function's Env via the extracted /// function's parameter references. - pub extract_func_orig_loc: HashMap>, + extract_func_orig_loc: + HashMap)>>, } impl GlobalPassData { pub fn new() -> GlobalPassData { GlobalPassData { extract_func_orig_loc: Default::default() } } + + pub fn get_data_for_func( + &self, + name: &String, + ) -> &BTreeMap)> { + match self.extract_func_orig_loc.get(name) { + Some(x) => x, + None => { + // Allow for the suffix(es) added by ConditionalFlatteningPass + let name = name.trim_end_matches(&['.', 'T', 'F', 'N']); + self.extract_func_orig_loc.get(name).unwrap() + } + } + } } pub struct PassManager { @@ -475,6 +499,11 @@ impl PassManager { self } + pub fn schedule_unused_function_removal_pass(&self) -> &Self { + self.passes.borrow_mut().push(PassKind::UnusedFunctionRemoval); + self + } + pub fn schedule_mapped_to_indexed_pass(&self) -> &Self { self.passes.borrow_mut().push(PassKind::MappedToIndexed); self @@ -504,6 +533,9 @@ impl PassManager { PassKind::DeterministicSubCmpInvoke => { Box::new(DeterministicSubCmpInvokePass::new(prime.clone(), global_data)) } + PassKind::UnusedFunctionRemoval => { + Box::new(UnusedFuncRemovalPass::new(prime.clone(), global_data)) + } PassKind::MappedToIndexed => { Box::new(MappedToIndexedPass::new(prime.clone(), global_data)) } diff --git a/circuit_passes/src/passes/simplification.rs b/circuit_passes/src/passes/simplification.rs index 81275e883..b866304ac 100644 --- a/circuit_passes/src/passes/simplification.rs +++ b/circuit_passes/src/passes/simplification.rs @@ -1,12 +1,12 @@ use std::cell::RefCell; -use std::collections::BTreeMap; +use std::collections::HashMap; use compiler::circuit_design::template::TemplateCode; use compiler::compiler_interface::Circuit; -use compiler::intermediate_representation::{InstructionPointer, new_id}; +use compiler::intermediate_representation::{InstructionPointer, new_id, BucketId}; use compiler::intermediate_representation::ir_interface::*; use crate::bucket_interpreter::env::Env; use crate::bucket_interpreter::memory::PassMemory; -use crate::bucket_interpreter::observer::InterpreterObserver; +use crate::bucket_interpreter::observer::Observer; use crate::bucket_interpreter::value::Value; use super::{CircuitTransformationPass, GlobalPassData}; @@ -14,9 +14,8 @@ pub struct SimplificationPass<'d> { global_data: &'d RefCell, // Wrapped in a RefCell because the reference to the static analysis is immutable but we need mutability memory: PassMemory, - compute_replacements: RefCell>, - call_replacements: RefCell>, - //TODO: could use BucketId instead of cloning buckets for keys + compute_replacements: RefCell>, + call_replacements: RefCell>, } impl<'d> SimplificationPass<'d> { @@ -30,7 +29,7 @@ impl<'d> SimplificationPass<'d> { } } -impl InterpreterObserver for SimplificationPass<'_> { +impl Observer> for SimplificationPass<'_> { fn on_value_bucket(&self, _bucket: &ValueBucket, _env: &Env) -> bool { true } @@ -49,7 +48,7 @@ impl InterpreterObserver for SimplificationPass<'_> { let (eval, _) = interpreter.execute_compute_bucket(bucket, env, false); let eval = eval.expect("Compute bucket must produce a value!"); if !eval.is_unknown() { - self.compute_replacements.borrow_mut().insert(bucket.clone(), eval); + self.compute_replacements.borrow_mut().insert(bucket.id, eval); return false; } true @@ -90,7 +89,7 @@ impl InterpreterObserver for SimplificationPass<'_> { if let Some(eval) = eval { // Call buckets may not return a value directly if !eval.is_unknown() { - self.call_replacements.borrow_mut().insert(bucket.clone(), eval); + self.call_replacements.borrow_mut().insert(bucket.id, eval); return false; } } @@ -116,6 +115,10 @@ impl InterpreterObserver for SimplificationPass<'_> { fn ignore_subcmp_calls(&self) -> bool { true } + + fn ignore_extracted_function_calls(&self) -> bool { + true + } } impl CircuitTransformationPass for SimplificationPass<'_> { @@ -128,7 +131,7 @@ impl CircuitTransformationPass for SimplificationPass<'_> { } fn transform_compute_bucket(&self, bucket: &ComputeBucket) -> InstructionPointer { - if let Some(value) = self.compute_replacements.borrow().get(&bucket) { + if let Some(value) = self.compute_replacements.borrow().get(&bucket.id) { return value.to_value_bucket(&self.memory).allocate(); } ComputeBucket { @@ -144,7 +147,7 @@ impl CircuitTransformationPass for SimplificationPass<'_> { } fn transform_call_bucket(&self, bucket: &CallBucket) -> InstructionPointer { - if let Some(value) = self.call_replacements.borrow().get(&bucket) { + if let Some(value) = self.call_replacements.borrow().get(&bucket.id) { return value.to_value_bucket(&self.memory).allocate(); } CallBucket { @@ -156,7 +159,7 @@ impl CircuitTransformationPass for SimplificationPass<'_> { argument_types: bucket.argument_types.clone(), arguments: self.transform_instructions(&bucket.arguments), arena_size: bucket.arena_size, - return_info: self.transform_return_type(&bucket.return_info), + return_info: self.transform_return_type(&bucket.id, &bucket.return_info), } .allocate() } diff --git a/circuit_passes/src/passes/unknown_index_sanitization.rs b/circuit_passes/src/passes/unknown_index_sanitization.rs index fa59e046b..d88e5d18e 100644 --- a/circuit_passes/src/passes/unknown_index_sanitization.rs +++ b/circuit_passes/src/passes/unknown_index_sanitization.rs @@ -10,7 +10,7 @@ use code_producers::llvm_elements::array_switch::{get_array_load_name, get_array use program_structure::constants::UsefulConstants; use crate::bucket_interpreter::env::Env; use crate::bucket_interpreter::memory::PassMemory; -use crate::bucket_interpreter::observer::InterpreterObserver; +use crate::bucket_interpreter::observer::Observer; use crate::bucket_interpreter::operations::compute_operation; use crate::bucket_interpreter::R; use crate::bucket_interpreter::value::Value::{KnownU32, KnownBigInt}; @@ -170,7 +170,7 @@ impl<'d> UnknownIndexSanitizationPass<'d> { * - loads with a function call that returns the loaded value * - stores with a function call that performs the store */ -impl InterpreterObserver for UnknownIndexSanitizationPass<'_> { +impl Observer> for UnknownIndexSanitizationPass<'_> { fn on_value_bucket(&self, _bucket: &ValueBucket, _env: &Env) -> bool { true } @@ -252,6 +252,10 @@ impl InterpreterObserver for UnknownIndexSanitizationPass<'_> { fn ignore_subcmp_calls(&self) -> bool { false } + + fn ignore_extracted_function_calls(&self) -> bool { + true + } } fn do_array_union(a: &HashSet>, b: &HashSet>) -> HashSet> { @@ -286,7 +290,7 @@ impl CircuitTransformationPass for UnknownIndexSanitizationPass<'_> { line: bucket.line, message_id: bucket.message_id, address_type: self.transform_address_type(&bucket.address_type), - src: self.transform_location_rule(&bucket.src), + src: self.transform_location_rule(&bucket.id, &bucket.src), bounded_fn: bounded_fn_symbol, } .allocate() @@ -305,7 +309,7 @@ impl CircuitTransformationPass for UnknownIndexSanitizationPass<'_> { context: bucket.context.clone(), dest_is_output: bucket.dest_is_output, dest_address_type: self.transform_address_type(&bucket.dest_address_type), - dest: self.transform_location_rule(&bucket.dest), + dest: self.transform_location_rule(&bucket.id, &bucket.dest), src: self.transform_instruction(&bucket.src), bounded_fn: bounded_fn_symbol, } diff --git a/circuit_passes/src/passes/unused_func_removal.rs b/circuit_passes/src/passes/unused_func_removal.rs new file mode 100644 index 000000000..856072c83 --- /dev/null +++ b/circuit_passes/src/passes/unused_func_removal.rs @@ -0,0 +1,169 @@ +use std::cell::{RefCell, Ref}; +use std::collections::{HashSet, HashMap}; +use compiler::circuit_design::function::FunctionCode; +use compiler::circuit_design::template::TemplateCode; +use compiler::compiler_interface::Circuit; +use compiler::intermediate_representation::ir_interface::*; +use crate::bucket_interpreter::{observer::Observer, env::LibraryAccess}; +use crate::bucket_interpreter::observed_visitor::ObservedVisitor; +use super::{CircuitTransformationPass, GlobalPassData}; + +/// The goal of this pass is to remove unreachable functions from the Circuit +pub struct UnusedFuncRemovalPass<'d> { + _global_data: &'d RefCell, + // Wrapped in a RefCell because the reference to the static analysis is immutable but we need mutability + used_functions: RefCell>, +} + +impl<'d> UnusedFuncRemovalPass<'d> { + pub fn new(_prime: String, _global_data: &'d RefCell) -> Self { + UnusedFuncRemovalPass { _global_data, used_functions: Default::default() } + } +} + +impl Observer<()> for UnusedFuncRemovalPass<'_> { + fn on_value_bucket(&self, _bucket: &ValueBucket, _: &()) -> bool { + true + } + + fn on_load_bucket(&self, _bucket: &LoadBucket, _: &()) -> bool { + true + } + + fn on_store_bucket(&self, _bucket: &StoreBucket, _: &()) -> bool { + true + } + + fn on_compute_bucket(&self, _bucket: &ComputeBucket, _: &()) -> bool { + true + } + + fn on_assert_bucket(&self, _bucket: &AssertBucket, _: &()) -> bool { + true + } + + fn on_loop_bucket(&self, _bucket: &LoopBucket, _: &()) -> bool { + true + } + + fn on_create_cmp_bucket(&self, _bucket: &CreateCmpBucket, _: &()) -> bool { + true + } + + fn on_constraint_bucket(&self, _bucket: &ConstraintBucket, _: &()) -> bool { + true + } + + fn on_block_bucket(&self, _bucket: &BlockBucket, _: &()) -> bool { + true + } + + fn on_nop_bucket(&self, _bucket: &NopBucket, _: &()) -> bool { + true + } + + fn on_location_rule(&self, _location_rule: &LocationRule, _: &()) -> bool { + true + } + + fn on_call_bucket(&self, bucket: &CallBucket, _: &()) -> bool { + self.used_functions.borrow_mut().insert(bucket.symbol.clone()); + true + } + + fn on_branch_bucket(&self, _bucket: &BranchBucket, _: &()) -> bool { + true + } + + fn on_return_bucket(&self, _bucket: &ReturnBucket, _: &()) -> bool { + true + } + + fn on_log_bucket(&self, _bucket: &LogBucket, _: &()) -> bool { + true + } + + fn ignore_function_calls(&self) -> bool { + false + } + + fn ignore_subcmp_calls(&self) -> bool { + false + } + + fn ignore_extracted_function_calls(&self) -> bool { + false + } +} + +impl CircuitTransformationPass for UnusedFuncRemovalPass<'_> { + fn name(&self) -> &str { + "UnusedFuncRemovalPass" + } + + fn get_updated_field_constants(&self) -> Vec { + unreachable!() + } + + fn transform_circuit(&self, circuit: &Circuit) -> Circuit { + //Build a structure to implement LibraryAccess + struct LibsImpl { + functions: HashMap>, + } + impl LibraryAccess for LibsImpl { + fn get_function(&self, name: &String) -> Ref { + self.functions[name].borrow() + } + + fn get_template(&self, _name: &String) -> Ref { + unreachable!() + } + } + let libs = LibsImpl { + functions: { + let mut functions = HashMap::new(); + for f in &circuit.functions { + functions.insert(f.header.clone(), RefCell::new((*f).clone())); + } + functions + }, + }; + + // Search each template for CallBucket and cache the names + let visitor = ObservedVisitor::new(self, Some(&libs)); + let templates = circuit + .templates + .iter() + .map(|t| { + visitor.visit_instructions(&t.body, &(), true); + t.clone() + }) + .collect(); + + // Filter out functions that are never used + let functions = circuit + .functions + .iter() + .filter_map(|f| { + if self.used_functions.borrow().contains(&f.header) { + Some(f.clone()) + } else { + None + } + }) + .collect(); + + // Return new circuit with reduced function list (and cloned templates) + Circuit { + wasm_producer: circuit.wasm_producer.clone(), + c_producer: circuit.c_producer.clone(), + llvm_data: circuit.llvm_data.clone_with_updates( + circuit.llvm_data.field_tracking.clone(), + self.get_updated_bounded_array_loads(&circuit.llvm_data.bounded_array_loads), + self.get_updated_bounded_array_stores(&circuit.llvm_data.bounded_array_stores), + ), + templates, + functions, + } + } +} diff --git a/code_producers/src/llvm_elements/fr.rs b/code_producers/src/llvm_elements/fr.rs index 581ea1180..847adfd64 100644 --- a/code_producers/src/llvm_elements/fr.rs +++ b/code_producers/src/llvm_elements/fr.rs @@ -47,6 +47,21 @@ pub const FR_PTR_CAST_I256_I32: &str = "cast_ptr_i256_i32"; pub const FR_NULL_I256_ARR_PTR: &str = "null_i256_arr_ptr"; pub const FR_NULL_I256_PTR: &str = "null_i256_ptr"; +thread_local!( + /// Contains all "built-in" functions that can be generated in + /// the Circom IR prior to the stage where LLVM IR is generated. + pub static BUILT_IN_NAMES: std::collections::HashSet<&'static str> = { + let mut result = std::collections::HashSet::default(); + result.insert(FR_INDEX_ARR_PTR); + result.insert(FR_IDENTITY_ARR_PTR); + result.insert(FR_PTR_CAST_I32_I256); + result.insert(FR_PTR_CAST_I256_I32); + result.insert(FR_NULL_I256_ARR_PTR); + result.insert(FR_NULL_I256_PTR); + result + } +); + macro_rules! fr_nullary_op { ($name: expr, $producer: expr, $retTy: expr) => {{ let func = create_function($producer, &None, 0, "", $name, $retTy.fn_type(&[], false)); diff --git a/code_producers/src/llvm_elements/functions.rs b/code_producers/src/llvm_elements/functions.rs index 2d0c1cec7..5ab27bd50 100644 --- a/code_producers/src/llvm_elements/functions.rs +++ b/code_producers/src/llvm_elements/functions.rs @@ -161,6 +161,14 @@ impl<'a> ExtractedFunctionCtx<'a> { format!("No signals argument for {:?}", self.current_function.get_name()).as_str(), ) } + + fn get_arg_ptr(&self, id: AnyValueEnum<'a>) -> PointerValue<'a> { + let num = id + .into_int_value() + .get_zero_extended_constant() + .expect("must reference a constant argument index"); + *self.args.get(num as usize).expect("must reference a valid argument index") + } } impl<'a> BodyCtx<'a> for ExtractedFunctionCtx<'a> { @@ -192,20 +200,33 @@ impl<'a> TemplateCtx<'a> for ExtractedFunctionCtx<'a> { _producer: &dyn LLVMIRProducer<'a>, id: AnyValueEnum<'a>, ) -> PointerValue<'a> { - let num = id - .into_int_value() - .get_zero_extended_constant() - .expect("must reference a constant argument index"); - *self.args.get(num as usize).expect("must reference a known argument index") + self.get_arg_ptr(id) } fn load_subcmp_counter( &self, _producer: &dyn LLVMIRProducer<'a>, - _id: AnyValueEnum<'a>, + id: AnyValueEnum<'a>, + implicit: bool, ) -> Option> { - // Use None to force StoreBucket::produce_llvm_ir to skip counter increment. - None + if implicit { + // Use None for the implicit case from StoreBucket::produce_llvm_ir so it will + // skip the counter decrement when using this ExtractedFunctionCtx because the + // counter decrement is generated explicitly inside the extracted functions. + None + } else { + Some(self.get_arg_ptr(id)) + } + } + + fn get_subcmp_signal( + &self, + producer: &dyn LLVMIRProducer<'a>, + subcmp_id: AnyValueEnum<'a>, + index: IntValue<'a>, + ) -> AnyValueEnum<'a> { + assert_eq!(zero(producer), index); + create_gep(producer, self.load_subcmp_addr(producer, subcmp_id), &[index]) } fn get_signal( diff --git a/code_producers/src/llvm_elements/mod.rs b/code_producers/src/llvm_elements/mod.rs index 73a70c746..ac5081851 100644 --- a/code_producers/src/llvm_elements/mod.rs +++ b/code_producers/src/llvm_elements/mod.rs @@ -66,8 +66,17 @@ pub trait TemplateCtx<'a> { &self, producer: &dyn LLVMIRProducer<'a>, id: AnyValueEnum<'a>, + implicit: bool, ) -> Option>; + /// Returns a pointer to the signal associated to given subcomponent id and index + fn get_subcmp_signal( + &self, + producer: &dyn LLVMIRProducer<'a>, + subcmp_id: AnyValueEnum<'a>, + index: IntValue<'a>, + ) -> AnyValueEnum<'a>; + /// Returns a pointer to the signal associated to the index fn get_signal( &self, @@ -192,7 +201,10 @@ impl<'a> TopLevelLLVMIRProducer<'a> { pub type LLVMAdapter<'a> = &'a Rc>>; pub type BigIntType<'a> = IntType<'a>; // i256 -pub fn new_constraint_with_name<'a>(producer: &dyn LLVMIRProducer<'a>, name: &str) -> AnyValueEnum<'a> { +pub fn new_constraint_with_name<'a>( + producer: &dyn LLVMIRProducer<'a>, + name: &str, +) -> AnyValueEnum<'a> { let alloca = create_alloca(producer, bool_type(producer).into(), name); let s = producer.context().metadata_string("constraint"); let kind = producer.context().get_kind_id("constraint"); diff --git a/code_producers/src/llvm_elements/stdlib.rs b/code_producers/src/llvm_elements/stdlib.rs index 27546f463..b6fba2a9d 100644 --- a/code_producers/src/llvm_elements/stdlib.rs +++ b/code_producers/src/llvm_elements/stdlib.rs @@ -7,8 +7,10 @@ pub const GENERATED_FN_PREFIX: &str = "..generated.."; pub const CONSTRAINT_VALUES_FN_NAME: &str = "__constraint_values"; pub const CONSTRAINT_VALUE_FN_NAME: &str = "__constraint_value"; pub const ASSERT_FN_NAME: &str = "__assert"; +pub const LLVM_DONOTHING_FN_NAME: &str = "llvm.donothing"; mod stdlib { + use inkwell::intrinsics::Intrinsic; use inkwell::values::AnyValue; use crate::llvm_elements::functions::{create_bb, create_function}; @@ -16,11 +18,18 @@ mod stdlib { create_br, create_call, create_conditional_branch, create_eq, create_return_void, create_store, }; - use crate::llvm_elements::stdlib::{ - ASSERT_FN_NAME, CONSTRAINT_VALUE_FN_NAME, CONSTRAINT_VALUES_FN_NAME, - }; use crate::llvm_elements::LLVMIRProducer; use crate::llvm_elements::types::{bigint_type, bool_type, void_type}; + use super::{ + ASSERT_FN_NAME, CONSTRAINT_VALUE_FN_NAME, CONSTRAINT_VALUES_FN_NAME, LLVM_DONOTHING_FN_NAME, + }; + + pub fn llvm_donothing_fn<'a>(producer: &dyn LLVMIRProducer<'a>) { + Intrinsic::find(LLVM_DONOTHING_FN_NAME) + .unwrap() + .get_declaration(&producer.llvm().module, &[]) + .unwrap(); + } pub fn constraint_values_fn<'a>(producer: &dyn LLVMIRProducer<'a>) { let bigint_ty = bigint_type(producer); @@ -100,6 +109,7 @@ mod stdlib { } pub fn load_stdlib<'a>(producer: &dyn LLVMIRProducer<'a>) { + stdlib::llvm_donothing_fn(producer); stdlib::constraint_values_fn(producer); stdlib::constraint_value_fn(producer); stdlib::abort_declared_fn(producer); diff --git a/code_producers/src/llvm_elements/template.rs b/code_producers/src/llvm_elements/template.rs index d23880676..66924c435 100644 --- a/code_producers/src/llvm_elements/template.rs +++ b/code_producers/src/llvm_elements/template.rs @@ -90,6 +90,7 @@ impl<'a> TemplateCtx<'a> for StdTemplateCtx<'a> { &self, producer: &dyn LLVMIRProducer<'a>, id: AnyValueEnum<'a>, + _implicit: bool, ) -> Option> { Some( create_gep( @@ -101,6 +102,15 @@ impl<'a> TemplateCtx<'a> for StdTemplateCtx<'a> { ) } + fn get_subcmp_signal( + &self, + producer: &dyn LLVMIRProducer<'a>, + subcmp_id: AnyValueEnum<'a>, + index: IntValue<'a>, + ) -> AnyValueEnum<'a> { + create_gep(producer, self.load_subcmp_addr(producer, subcmp_id), &[zero(producer), index]) + } + fn get_signal( &self, producer: &dyn LLVMIRProducer<'a>, diff --git a/compiler/src/intermediate_representation/call_bucket.rs b/compiler/src/intermediate_representation/call_bucket.rs index f59b8b3d0..62c8f88fd 100644 --- a/compiler/src/intermediate_representation/call_bucket.rs +++ b/compiler/src/intermediate_representation/call_bucket.rs @@ -163,9 +163,7 @@ impl WriteLLVMIR for CallBucket { let addr = cmp_address.produce_llvm_ir(producer).expect( "The address of a subcomponent must yield a value!", ); - let subcmp = - producer.template_ctx().load_subcmp_addr(producer, addr); - create_gep(producer, subcmp, &[zero(producer), index]) + producer.template_ctx().get_subcmp_signal(producer, addr, index) } } .into_pointer_value(); diff --git a/compiler/src/intermediate_representation/ir_interface.rs b/compiler/src/intermediate_representation/ir_interface.rs index 96c6e3a50..84d6e920a 100644 --- a/compiler/src/intermediate_representation/ir_interface.rs +++ b/compiler/src/intermediate_representation/ir_interface.rs @@ -37,6 +37,36 @@ pub trait ObtainMeta { fn get_message_id(&self) -> usize; } +pub struct ObtainMetaImpl { + source_file_id: Option, + line: usize, + message_id: usize, +} + +impl ObtainMeta for ObtainMetaImpl { + fn get_source_file_id(&self) -> &Option { + &self.source_file_id + } + + fn get_line(&self) -> usize { + self.line + } + + fn get_message_id(&self) -> usize { + self.message_id + } +} + +impl ObtainMetaImpl { + pub fn from(bucket: &dyn ObtainMeta) -> ObtainMetaImpl { + ObtainMetaImpl { + source_file_id: bucket.get_source_file_id().clone(), + line: bucket.get_line(), + message_id: bucket.get_message_id(), + } + } +} + pub trait CheckCompute { fn has_compute_in(&self) -> bool; } diff --git a/compiler/src/intermediate_representation/load_bucket.rs b/compiler/src/intermediate_representation/load_bucket.rs index a3a4d1cf0..e7c4cc664 100644 --- a/compiler/src/intermediate_representation/load_bucket.rs +++ b/compiler/src/intermediate_representation/load_bucket.rs @@ -95,7 +95,7 @@ impl WriteLLVMIR for LoadBucket { let addr = cmp_address.produce_llvm_ir(producer) .expect("The address of a subcomponent must yield a value!"); if *counter_override { - return producer.template_ctx().load_subcmp_counter(producer, addr).expect("could not find counter!") + return producer.template_ctx().load_subcmp_counter(producer, addr, false).expect("could not find counter!") } else { let subcmp = producer.template_ctx().load_subcmp_addr(producer, addr); create_gep(producer, subcmp, &[zero(producer)]) @@ -113,15 +113,9 @@ impl WriteLLVMIR for LoadBucket { AddressType::SubcmpSignal { cmp_address, counter_override, .. } => { let addr = cmp_address.produce_llvm_ir(producer).expect("The address of a subcomponent must yield a value!"); if *counter_override { - producer.template_ctx().load_subcmp_counter(producer, addr).expect("could not find counter!") + producer.template_ctx().load_subcmp_counter(producer, addr, false).expect("could not find counter!") } else { - let subcmp = producer.template_ctx().load_subcmp_addr(producer, addr); - if subcmp.get_type().get_element_type().is_array_type() { - create_gep(producer, subcmp, &[zero(producer), index]).into_pointer_value() - } else { - assert_eq!(zero(producer), index); - create_gep(producer, subcmp, &[index]).into_pointer_value() - } + producer.template_ctx().get_subcmp_signal(producer, addr, index).into_pointer_value() } } }; diff --git a/compiler/src/intermediate_representation/location_rule.rs b/compiler/src/intermediate_representation/location_rule.rs index 6bc7f2637..7a50a4266 100644 --- a/compiler/src/intermediate_representation/location_rule.rs +++ b/compiler/src/intermediate_representation/location_rule.rs @@ -65,7 +65,7 @@ impl WriteLLVMIR for LocationRule { fn produce_llvm_ir<'a, 'b>(&self, producer: &'b dyn LLVMIRProducer<'a>) -> Option> { match self { LocationRule::Indexed { location, .. } => location.produce_llvm_ir(producer), - LocationRule::Mapped { .. } => unreachable!() // We should not produce mapped location rules for Vanguard! + LocationRule::Mapped { .. } => unreachable!("LocationRule::Mapped should have been replaced"), } } } diff --git a/compiler/src/intermediate_representation/store_bucket.rs b/compiler/src/intermediate_representation/store_bucket.rs index 0787c9d38..2a66d44dd 100644 --- a/compiler/src/intermediate_representation/store_bucket.rs +++ b/compiler/src/intermediate_representation/store_bucket.rs @@ -8,6 +8,7 @@ use code_producers::llvm_elements::instructions::{ create_call, create_gep, create_load_with_name, create_store, create_sub_with_name, pointer_cast, }; +use code_producers::llvm_elements::stdlib::LLVM_DONOTHING_FN_NAME; use code_producers::llvm_elements::values::{create_literal_u32, zero}; use code_producers::wasm_elements::*; use crate::intermediate_representation::{BucketId, new_id, SExp, ToSExp, UpdateId}; @@ -86,7 +87,7 @@ impl UpdateId for StoreBucket { } } -impl StoreBucket{ +impl StoreBucket { /// The caller must manage the debug location information before calling this function. pub fn produce_llvm_ir<'a, 'b>( producer: &'b dyn LLVMIRProducer<'a>, @@ -96,7 +97,10 @@ impl StoreBucket{ context: InstrContext, bounded_fn: &Option, ) -> Option> { - let dest_index = dest.produce_llvm_ir(producer).expect("We need to produce some kind of instruction!").into_int_value(); + let dest_index = dest + .produce_llvm_ir(producer) + .expect("We need to produce some kind of instruction!") + .into_int_value(); let mut source = match src { Either::Left(s) => s, @@ -107,33 +111,42 @@ impl StoreBucket{ let store = match &bounded_fn { Some(name) => { assert_eq!(1, context.size, "unhandled array store"); - let arr_ptr = match &dest_address_type { - AddressType::Variable => producer.body_ctx().get_variable_array(producer), - AddressType::Signal => producer.template_ctx().get_signal_array(producer), - AddressType::SubcmpSignal { cmp_address, .. } => { - let addr = cmp_address.produce_llvm_ir(producer).expect("The address of a subcomponent must yield a value!"); - let subcmp = producer.template_ctx().load_subcmp_addr(producer, addr); - create_gep(producer, subcmp, &[zero(producer)]) + if name == LLVM_DONOTHING_FN_NAME { + //LLVM equivalent of a "nop" instruction + create_call(producer, LLVM_DONOTHING_FN_NAME, &[]) + } else { + let arr_ptr = match &dest_address_type { + AddressType::Variable => producer.body_ctx().get_variable_array(producer), + AddressType::Signal => producer.template_ctx().get_signal_array(producer), + AddressType::SubcmpSignal { cmp_address, .. } => { + let addr = cmp_address + .produce_llvm_ir(producer) + .expect("The address of a subcomponent must yield a value!"); + let subcmp = producer.template_ctx().load_subcmp_addr(producer, addr); + create_gep(producer, subcmp, &[zero(producer)]) + } } - }.into_pointer_value(); - let arr_ptr = pointer_cast(producer, arr_ptr, array_ptr_ty(producer)); - create_call(producer, name.as_str(), &[arr_ptr.into(), dest_index.into(), source.into_int_value().into()]) + .into_pointer_value(); + let arr_ptr = pointer_cast(producer, arr_ptr, array_ptr_ty(producer)); + create_call( + producer, + name.as_str(), + &[arr_ptr.into(), dest_index.into(), source.into_int_value().into()], + ) + } } None => { let dest_gep = match &dest_address_type { AddressType::Variable => producer.body_ctx().get_variable(producer, dest_index), AddressType::Signal => producer.template_ctx().get_signal(producer, dest_index), AddressType::SubcmpSignal { cmp_address, .. } => { - let addr = cmp_address.produce_llvm_ir(producer).expect("The address of a subcomponent must yield a value!"); - let subcmp = producer.template_ctx().load_subcmp_addr(producer, addr); - if subcmp.get_type().get_element_type().is_array_type() { - create_gep(producer, subcmp, &[zero(producer), dest_index]) - } else { - assert_eq!(zero(producer), dest_index); - create_gep(producer, subcmp, &[dest_index]) - } + let addr = cmp_address + .produce_llvm_ir(producer) + .expect("The address of a subcomponent must yield a value!"); + producer.template_ctx().get_subcmp_signal(producer, addr, dest_index) } - }.into_pointer_value(); + } + .into_pointer_value(); if context.size > 1 { // In the non-scalar case, produce an array copy. If the stored source // is a LoadBucket, first convert it into an address. @@ -152,9 +165,9 @@ impl StoreBucket{ producer.template_ctx().get_signal(producer, src_index) } AddressType::SubcmpSignal { cmp_address, .. } => { - let addr = cmp_address - .produce_llvm_ir(producer) - .expect("The address of a subcomponent must yield a value!"); + let addr = cmp_address.produce_llvm_ir(producer).expect( + "The address of a subcomponent must yield a value!", + ); let subcmp = producer.template_ctx().load_subcmp_addr(producer, addr); create_gep(producer, subcmp, &[zero(producer), src_index]) @@ -165,7 +178,11 @@ impl StoreBucket{ create_call( producer, FR_ARRAY_COPY_FN_NAME, - &[source.into_pointer_value().into(), dest_gep.into(), create_literal_u32(producer, context.size as u64).into()], + &[ + source.into_pointer_value().into(), + dest_gep.into(), + create_literal_u32(producer, context.size as u64).into(), + ], ) } else { // In the scalar case, just produce a store from the source value that was given @@ -177,7 +194,7 @@ impl StoreBucket{ // If we have a subcomponent storage decrement the counter by the size of the store (i.e., context.size) if let AddressType::SubcmpSignal { cmp_address, .. } = &dest_address_type { let addr = cmp_address.produce_llvm_ir(producer).expect("The address of a subcomponent must yield a value!"); - let counter = producer.template_ctx().load_subcmp_counter(producer, addr); + let counter = producer.template_ctx().load_subcmp_counter(producer, addr, true); if let Some(counter) = counter { let value = create_load_with_name(producer, counter, "load.subcmp.counter"); let new_value = create_sub_with_name(producer, value.into_int_value(), create_literal_u32(producer, context.size as u64), "decrement.counter"); @@ -187,31 +204,31 @@ impl StoreBucket{ // If the input information is unknown add a check that checks the counter and if its zero call the subcomponent // If its last just call run directly - if let AddressType::SubcmpSignal { input_information, cmp_address, .. } = &dest_address_type { + if let AddressType::SubcmpSignal { input_information, cmp_address, .. } = &dest_address_type + { if let InputInformation::Input { status } = input_information { let sub_cmp_name = match &dest { LocationRule::Indexed { template_header, .. } => template_header.clone(), - LocationRule::Mapped { .. } => None - }; + LocationRule::Mapped { .. } => unreachable!("LocationRule::Mapped should have been replaced"), + }.expect("Could not get the name of the subcomponent"); match status { StatusInput::Last => { - let run_fn = run_fn_name(sub_cmp_name.expect("Could not get the name of the subcomponent")); // If we reach this point gep is the address of the subcomponent so we can just reuse it - let addr = cmp_address.produce_llvm_ir(producer).expect("The address of a subcomponent must yield a value!"); + let addr = cmp_address + .produce_llvm_ir(producer) + .expect("The address of a subcomponent must yield a value!"); let subcmp = producer.template_ctx().load_subcmp_addr(producer, addr); - create_call(producer, run_fn.as_str(), &[subcmp.into()]); + create_call(producer, run_fn_name(sub_cmp_name).as_str(), &[subcmp.into()]); } StatusInput::Unknown => { panic!("There should not be Unknown input status"); - // let sub_cmp_name = sub_cmp_name.expect("Could not get the name of the subcomponent"); - // let run_fn = run_fn_name(sub_cmp_name.clone()); // let current_function = producer.current_function(); // let run_bb = create_bb(producer, current_function, format!("maybe_run.{}", sub_cmp_name).as_str()); // let continue_bb = create_bb(producer, current_function,"continue.store"); // // Here we need to get the counter and check if its 0 // // If its is then call the run function because it means that all signals have been assigned // let addr = cmp_address.produce_llvm_ir(producer).expect("The address of a subcomponent must yield a value!"); - // let counter = producer.template_ctx().load_subcmp_counter(producer, addr); + // let counter = producer.template_ctx().load_subcmp_counter(producer, addr, false); // let value = create_load_with_name(producer, counter, "load.subcmp.counter"); // let is_zero = create_eq_with_name(producer, zero(producer), value.into_int_value(), "subcmp.counter.isZero"); // create_conditional_branch(producer, is_zero.into_int_value(), run_bb, continue_bb); @@ -220,7 +237,7 @@ impl StoreBucket{ // let addr = cmp_address.produce_llvm_ir(producer).expect("The address of a subcomponent must yield a value!"); // let subcmp = producer.template_ctx().load_subcmp_addr(producer, addr); // - // create_call(producer, run_fn.as_str(), &[subcmp.into()]); + // create_call(producer, run_fn_name(sub_cmp_name).as_str(), &[subcmp.into()]); // create_br(producer,continue_bb); // producer.set_current_bb(continue_bb); } From a93f1a7b1b327febc821a4030baf987bacc1eb8f Mon Sep 17 00:00:00 2001 From: Timothy Hoffman <4001421+tim-hoffman@users.noreply.github.com> Date: Mon, 30 Oct 2023 18:43:28 -0500 Subject: [PATCH 6/9] [VAN-676][VAN-670] flatten branches in extracted function by duplicating the functions (#55) * Refactor StoreBucket to avoid generating call to "llvm.donothing" --- circom/tests/loops/assign_in_loop.circom | 186 ++++++++++++++++++ circom/tests/loops/assign_in_loop_1.circom | 1 - circom/tests/subcmps/subcmps0A.circom | 1 - circom/tests/subcmps/subcmps0B.circom | 1 - circom/tests/subcmps/subcmps0C.circom | 1 - circom/tests/subcmps/subcmps0D.circom | 1 - circom/tests/subcmps/subcmps1.circom | 1 - circom/tests/subcmps/subcmps2.circom | 1 - circuit_passes/src/bucket_interpreter/mod.rs | 1 - .../src/passes/loop_unroll/body_extractor.rs | 6 - .../store_bucket.rs | 15 +- 11 files changed, 193 insertions(+), 22 deletions(-) create mode 100644 circom/tests/loops/assign_in_loop.circom diff --git a/circom/tests/loops/assign_in_loop.circom b/circom/tests/loops/assign_in_loop.circom new file mode 100644 index 000000000..bcfa191a6 --- /dev/null +++ b/circom/tests/loops/assign_in_loop.circom @@ -0,0 +1,186 @@ +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 --enable-var-scope +// XFAIL:.* // panicked at 'not yet implemented', circuit_passes/src/passes/loop_unroll/loop_env_recorder.rs:149:44 (LocationRule::Mapped case) + +template Inner(i) { + signal input in; + signal output out; + + out <-- (in >> i) & 1; +} + +template Num2Bits(n) { + signal input in; + signal output out[n]; + + component c[n]; + for (var i = 0; i < n; i++) { + c[i] = Inner(i); + c[i].in <-- in; + out[i] <-- c[i].out; + } +} + +component main = Num2Bits(3); + +//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %subfix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %subfix_[[X3:[0-9]+]], +//CHECK-SAME: [0 x i256]* %sub_[[X1]], i256* %subc_[[X1]], [0 x i256]* %sub_[[X3]], i256* %subc_[[X3]]){{.*}} { +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1]]: +//CHECK-NEXT: br label %store1 +//CHECK-EMPTY: +//CHECK-NEXT: store1: +//CHECK-NEXT: %0 = getelementptr [0 x i256], [0 x i256]* %signals, i32 0, i32 3 +//CHECK-NEXT: %1 = load i256, i256* %0, align 4 +//CHECK-NEXT: %2 = getelementptr i256, i256* %subfix_[[X1]], i32 0 +//CHECK-NEXT: store i256 %1, i256* %2, align 4 +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %3 = getelementptr [0 x i256], [0 x i256]* %sub_[[X1]], i32 0 +//CHECK-NEXT: call void @Inner_?_run([0 x i256]* %sub_[[X1]]) //TODO: which function to call depends on which iteration of the loop +//CHECK-NEXT: br label %store3 +//CHECK-EMPTY: +//CHECK-NEXT: store3: +//CHECK-NEXT: %4 = getelementptr i256, i256* %subfix_[[X3]], i32 0 +//CHECK-NEXT: %5 = load i256, i256* %4, align 4 +//CHECK-NEXT: %6 = getelementptr i256, i256* %fix_[[X2]], i32 0 +//CHECK-NEXT: store i256 %5, i256* %6, align 4 +//CHECK-NEXT: br label %store4 +//CHECK-EMPTY: +//CHECK-NEXT: store4: +//CHECK-NEXT: %7 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: %8 = load i256, i256* %7, align 4 +//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %8, i256 1) +//CHECK-NEXT: %9 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 %call.fr_add, i256* %9, align 4 +//CHECK-NEXT: br label %return5 +//CHECK-EMPTY: +//CHECK-NEXT: return5: +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @Inner_0_build({ [0 x i256]*, i32 }* %0){{.*}} { +// +//CHECK-LABEL: define void @Inner_0_run([0 x i256]* %0){{.*}} { +// +//CHECK-LABEL: define void @Inner_1_build({ [0 x i256]*, i32 }* %0){{.*}} { +// +//CHECK-LABEL: define void @Inner_1_run([0 x i256]* %0){{.*}} { +// +//CHECK-LABEL: define void @Inner_2_build({ [0 x i256]*, i32 }* %0){{.*}} { +// +//CHECK-LABEL: define void @Inner_2_run([0 x i256]* %0){{.*}} { +// +//CHECK-LABEL: define void @Num2Bits_3_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-NEXT: main: +//CHECK-NEXT: %1 = alloca [4 x i256], align 8 +//CHECK-NEXT: %2 = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 +//CHECK-NEXT: store i32 1, i32* %2, align 4 +//CHECK-NEXT: %3 = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 0 +//CHECK-NEXT: %4 = bitcast [4 x i256]* %1 to [0 x i256]* +//CHECK-NEXT: store [0 x i256]* %4, [0 x i256]** %3, align 8 +//CHECK-NEXT: ret void +//CHECK-NEXT: } +// +//CHECK-LABEL: define void @Num2Bits_3_run([0 x i256]* %0){{.*}} { +//CHECK-NEXT: prelude: +//CHECK-NEXT: %lvars = alloca [2 x i256], align 8 +//CHECK-NEXT: %subcmps = alloca [3 x { [0 x i256]*, i32 }], align 8 +//CHECK-NEXT: br label %store1 +//CHECK-EMPTY: +//CHECK-NEXT: store1: +//CHECK-NEXT: %1 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: store i256 3, i256* %1, align 4 +//CHECK-NEXT: br label %create_cmp2 +//CHECK-EMPTY: +//CHECK-NEXT: create_cmp2: +//CHECK-NEXT: %2 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0 +//CHECK-NEXT: call void @Inner_0_build({ [0 x i256]*, i32 }* %2) +//CHECK-NEXT: br label %create_cmp3 +//CHECK-EMPTY: +//CHECK-NEXT: create_cmp3: +//CHECK-NEXT: %3 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1 +//CHECK-NEXT: call void @Inner_1_build({ [0 x i256]*, i32 }* %3) +//CHECK-NEXT: br label %create_cmp4 +//CHECK-EMPTY: +//CHECK-NEXT: create_cmp4: +//CHECK-NEXT: %4 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2 +//CHECK-NEXT: call void @Inner_2_build({ [0 x i256]*, i32 }* %4) +//CHECK-NEXT: br label %store5 +//CHECK-EMPTY: +//CHECK-NEXT: store5: +//CHECK-NEXT: %5 = getelementptr [2 x i256], [2 x i256]* %lvars, i32 0, i32 1 +//CHECK-NEXT: store i256 0, i256* %5, align 4 +//CHECK-NEXT: br label %unrolled_loop6 +//CHECK-EMPTY: +//CHECK-NEXT: unrolled_loop6: +//CHECK-NEXT: %6 = bitcast [2 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %7 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %8 = load [0 x i256]*, [0 x i256]** %7, align 8 +//CHECK-NEXT: %9 = getelementptr [0 x i256], [0 x i256]* %8, i32 0 +//CHECK-NEXT: %10 = getelementptr [0 x i256], [0 x i256]* %9, i32 0, i256 1 +//CHECK-NEXT: %11 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 0 +//CHECK-NEXT: %12 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %13 = load [0 x i256]*, [0 x i256]** %12, align 8 +//CHECK-NEXT: %14 = getelementptr [0 x i256], [0 x i256]* %13, i32 0 +//CHECK-NEXT: %15 = getelementptr [0 x i256], [0 x i256]* %14, i32 0, i256 0 +//CHECK-NEXT: %16 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %17 = load [0 x i256]*, [0 x i256]** %16, align 8 +//CHECK-NEXT: %18 = getelementptr [0 x i256], [0 x i256]* %17, i32 0 +//CHECK-NEXT: %19 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 1 +//CHECK-NEXT: %20 = bitcast i32* %19 to i256* +//CHECK-NEXT: %21 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 +//CHECK-NEXT: %22 = load [0 x i256]*, [0 x i256]** %21, align 8 +//CHECK-NEXT: %23 = getelementptr [0 x i256], [0 x i256]* %22, i32 0 +//CHECK-NEXT: %24 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 1 +//CHECK-NEXT: %25 = bitcast i32* %24 to i256* +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %6, [0 x i256]* %0, i256* %10, i256* %11, i256* %15, [0 x i256]* %18, i256* %20, [0 x i256]* %23, i256* %25) +//CHECK-NEXT: %26 = bitcast [2 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %27 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 0 +//CHECK-NEXT: %28 = load [0 x i256]*, [0 x i256]** %27, align 8 +//CHECK-NEXT: %29 = getelementptr [0 x i256], [0 x i256]* %28, i32 0 +//CHECK-NEXT: %30 = getelementptr [0 x i256], [0 x i256]* %29, i32 0, i256 1 +//CHECK-NEXT: %31 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 1 +//CHECK-NEXT: %32 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 0 +//CHECK-NEXT: %33 = load [0 x i256]*, [0 x i256]** %32, align 8 +//CHECK-NEXT: %34 = getelementptr [0 x i256], [0 x i256]* %33, i32 0 +//CHECK-NEXT: %35 = getelementptr [0 x i256], [0 x i256]* %34, i32 0, i256 0 +//CHECK-NEXT: %36 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 0 +//CHECK-NEXT: %37 = load [0 x i256]*, [0 x i256]** %36, align 8 +//CHECK-NEXT: %38 = getelementptr [0 x i256], [0 x i256]* %37, i32 0 +//CHECK-NEXT: %39 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 1 +//CHECK-NEXT: %40 = bitcast i32* %39 to i256* +//CHECK-NEXT: %41 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 0 +//CHECK-NEXT: %42 = load [0 x i256]*, [0 x i256]** %41, align 8 +//CHECK-NEXT: %43 = getelementptr [0 x i256], [0 x i256]* %42, i32 0 +//CHECK-NEXT: %44 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 1 +//CHECK-NEXT: %45 = bitcast i32* %44 to i256* +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %26, [0 x i256]* %0, i256* %30, i256* %31, i256* %35, [0 x i256]* %38, i256* %40, [0 x i256]* %43, i256* %45) +//CHECK-NEXT: %46 = bitcast [2 x i256]* %lvars to [0 x i256]* +//CHECK-NEXT: %47 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2, i32 0 +//CHECK-NEXT: %48 = load [0 x i256]*, [0 x i256]** %47, align 8 +//CHECK-NEXT: %49 = getelementptr [0 x i256], [0 x i256]* %48, i32 0 +//CHECK-NEXT: %50 = getelementptr [0 x i256], [0 x i256]* %49, i32 0, i256 1 +//CHECK-NEXT: %51 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 2 +//CHECK-NEXT: %52 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2, i32 0 +//CHECK-NEXT: %53 = load [0 x i256]*, [0 x i256]** %52, align 8 +//CHECK-NEXT: %54 = getelementptr [0 x i256], [0 x i256]* %53, i32 0 +//CHECK-NEXT: %55 = getelementptr [0 x i256], [0 x i256]* %54, i32 0, i256 0 +//CHECK-NEXT: %56 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2, i32 0 +//CHECK-NEXT: %57 = load [0 x i256]*, [0 x i256]** %56, align 8 +//CHECK-NEXT: %58 = getelementptr [0 x i256], [0 x i256]* %57, i32 0 +//CHECK-NEXT: %59 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2, i32 1 +//CHECK-NEXT: %60 = bitcast i32* %59 to i256* +//CHECK-NEXT: %61 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2, i32 0 +//CHECK-NEXT: %62 = load [0 x i256]*, [0 x i256]** %61, align 8 +//CHECK-NEXT: %63 = getelementptr [0 x i256], [0 x i256]* %62, i32 0 +//CHECK-NEXT: %64 = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 2, i32 1 +//CHECK-NEXT: %65 = bitcast i32* %64 to i256* +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %46, [0 x i256]* %0, i256* %50, i256* %51, i256* %55, [0 x i256]* %58, i256* %60, [0 x i256]* %63, i256* %65) +//CHECK-NEXT: br label %prologue +//CHECK-EMPTY: +//CHECK-NEXT: prologue: +//CHECK-NEXT: ret void +//CHECK-NEXT: } diff --git a/circom/tests/loops/assign_in_loop_1.circom b/circom/tests/loops/assign_in_loop_1.circom index acac850d7..7eac236e1 100644 --- a/circom/tests/loops/assign_in_loop_1.circom +++ b/circom/tests/loops/assign_in_loop_1.circom @@ -44,7 +44,6 @@ component main = Num2Bits(3); //CHECK-NEXT: br label %fold_true3 //CHECK-EMPTY: //CHECK-NEXT: fold_true3: -//CHECK-NEXT: call void @llvm.donothing() //CHECK-NEXT: call void @Inner_0_run([0 x i256]* %sub_[[X3]]) //CHECK-NEXT: br label %store4 //CHECK-EMPTY: diff --git a/circom/tests/subcmps/subcmps0A.circom b/circom/tests/subcmps/subcmps0A.circom index 80e497bc3..85b66d0e2 100644 --- a/circom/tests/subcmps/subcmps0A.circom +++ b/circom/tests/subcmps/subcmps0A.circom @@ -45,7 +45,6 @@ component main = SubCmps0A(2); //CHECK-NEXT: br label %fold_true3 //CHECK-EMPTY: //CHECK-NEXT: fold_true3: -//CHECK-NEXT: call void @llvm.donothing() //CHECK-NEXT: call void @IsZero_0_run([0 x i256]* %sub_[[X4]]) //CHECK-NEXT: br label %store4 //CHECK-EMPTY: diff --git a/circom/tests/subcmps/subcmps0B.circom b/circom/tests/subcmps/subcmps0B.circom index c73f889ab..dde20729a 100644 --- a/circom/tests/subcmps/subcmps0B.circom +++ b/circom/tests/subcmps/subcmps0B.circom @@ -46,7 +46,6 @@ component main = SubCmps0B(2); //CHECK-NEXT: br label %fold_true3 //CHECK-EMPTY: //CHECK-NEXT: fold_true3: -//CHECK-NEXT: call void @llvm.donothing() //CHECK-NEXT: call void @IsZero_0_run([0 x i256]* %sub_[[X5]]) //CHECK-NEXT: br label %store4 //CHECK-EMPTY: diff --git a/circom/tests/subcmps/subcmps0C.circom b/circom/tests/subcmps/subcmps0C.circom index ecf098e96..18fdacac1 100644 --- a/circom/tests/subcmps/subcmps0C.circom +++ b/circom/tests/subcmps/subcmps0C.circom @@ -44,7 +44,6 @@ component main = SubCmps0C(2); //CHECK-NEXT: br label %fold_true3 //CHECK-EMPTY: //CHECK-NEXT: fold_true3: -//CHECK-NEXT: call void @llvm.donothing() //CHECK-NEXT: call void @IsZero_0_run([0 x i256]* %sub_[[X4]]) //CHECK-NEXT: br label %store4 //CHECK-EMPTY: diff --git a/circom/tests/subcmps/subcmps0D.circom b/circom/tests/subcmps/subcmps0D.circom index c9dee689b..89d898aea 100644 --- a/circom/tests/subcmps/subcmps0D.circom +++ b/circom/tests/subcmps/subcmps0D.circom @@ -62,7 +62,6 @@ component main = SubCmps0D(3); //CHECK-NEXT: br label %fold_true6 //CHECK-EMPTY: //CHECK-NEXT: fold_true6: -//CHECK-NEXT: call void @llvm.donothing() //CHECK-NEXT: call void @Add_0_run([0 x i256]* %sub_[[X6]]) //CHECK-NEXT: br label %store7 //CHECK-EMPTY: diff --git a/circom/tests/subcmps/subcmps1.circom b/circom/tests/subcmps/subcmps1.circom index a38ddc024..7945748b8 100644 --- a/circom/tests/subcmps/subcmps1.circom +++ b/circom/tests/subcmps/subcmps1.circom @@ -58,7 +58,6 @@ component main = SubCmps1(3); //CHECK-NEXT: br label %fold_true3 //CHECK-EMPTY: //CHECK-NEXT: fold_true3: -//CHECK-NEXT: call void @llvm.donothing() //CHECK-NEXT: call void @IsZero_0_run([0 x i256]* %sub_[[X4]]) //CHECK-NEXT: br label %store4 //CHECK-EMPTY: diff --git a/circom/tests/subcmps/subcmps2.circom b/circom/tests/subcmps/subcmps2.circom index faf7d0dbf..22fa83ff8 100644 --- a/circom/tests/subcmps/subcmps2.circom +++ b/circom/tests/subcmps/subcmps2.circom @@ -131,7 +131,6 @@ component main = Caller(); //CHECK-NEXT: br label %fold_true3 //CHECK-EMPTY: //CHECK-NEXT: fold_true3: -//CHECK-NEXT: call void @llvm.donothing() //CHECK-NEXT: call void @Sum_0_run([0 x i256]* %sub_[[X3]]) //CHECK-NEXT: br label %store4 //CHECK-EMPTY: diff --git a/circuit_passes/src/bucket_interpreter/mod.rs b/circuit_passes/src/bucket_interpreter/mod.rs index 2f5966a4e..94c73bf08 100644 --- a/circuit_passes/src/bucket_interpreter/mod.rs +++ b/circuit_passes/src/bucket_interpreter/mod.rs @@ -387,7 +387,6 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { env: Env<'env>, observe: bool, ) -> R<'env> { - // println!("Interpreter executing {:?}", bucket); let (src, env) = self.execute_instruction(&bucket.src, env, observe); let src = src.expect("src instruction in StoreBucket must produce a value!"); let env = diff --git a/circuit_passes/src/passes/loop_unroll/body_extractor.rs b/circuit_passes/src/passes/loop_unroll/body_extractor.rs index 86b08407f..fc32776c3 100644 --- a/circuit_passes/src/passes/loop_unroll/body_extractor.rs +++ b/circuit_passes/src/passes/loop_unroll/body_extractor.rs @@ -412,12 +412,6 @@ impl LoopBodyExtractor { } else { //Since SubcmpSignal is always added above, this should be unreachable. unreachable!() - // bucket_to_args.insert( - // *b, - // ArgIndex::SubCmp { signal: next_idx, arena: arena_idx, counter: counter_idx, - // }, - // ); - // next_idx += 1; } } } diff --git a/compiler/src/intermediate_representation/store_bucket.rs b/compiler/src/intermediate_representation/store_bucket.rs index 2a66d44dd..f534fdf9a 100644 --- a/compiler/src/intermediate_representation/store_bucket.rs +++ b/compiler/src/intermediate_representation/store_bucket.rs @@ -112,8 +112,7 @@ impl StoreBucket { Some(name) => { assert_eq!(1, context.size, "unhandled array store"); if name == LLVM_DONOTHING_FN_NAME { - //LLVM equivalent of a "nop" instruction - create_call(producer, LLVM_DONOTHING_FN_NAME, &[]) + None } else { let arr_ptr = match &dest_address_type { AddressType::Variable => producer.body_ctx().get_variable_array(producer), @@ -128,11 +127,11 @@ impl StoreBucket { } .into_pointer_value(); let arr_ptr = pointer_cast(producer, arr_ptr, array_ptr_ty(producer)); - create_call( + Some(create_call( producer, name.as_str(), &[arr_ptr.into(), dest_index.into(), source.into_int_value().into()], - ) + )) } } None => { @@ -175,7 +174,7 @@ impl StoreBucket { }; } } - create_call( + Some(create_call( producer, FR_ARRAY_COPY_FN_NAME, &[ @@ -183,10 +182,10 @@ impl StoreBucket { dest_gep.into(), create_literal_u32(producer, context.size as u64).into(), ], - ) + )) } else { // In the scalar case, just produce a store from the source value that was given - create_store(producer, dest_gep, source) + Some(create_store(producer, dest_gep, source)) } } }; @@ -245,7 +244,7 @@ impl StoreBucket { } } } - Some(store) + store } } From 1b12aff70e2392f8e517613eff7b624879a4dd64 Mon Sep 17 00:00:00 2001 From: Timothy Hoffman <4001421+tim-hoffman@users.noreply.github.com> Date: Tue, 31 Oct 2023 14:23:13 -0500 Subject: [PATCH 7/9] [VAN-719] use LLVM pass to remove unused functions (#64) --- circom/tests/arrays/array8.circom | 6 +- circom/tests/arrays/array9.circom | 4 +- circom/tests/arrays/array_copy1.circom | 2 +- circom/tests/arrays/array_copy2.circom | 2 +- circom/tests/calls/call_with_array.circom | 4 +- .../calls/call_with_array_and_scalar.circom | 2 +- circom/tests/controlflow/van348F.circom | 4 +- circom/tests/controlflow/van544.circom | 2 +- circom/tests/loops/assign_in_loop_1.circom | 4 +- circom/tests/loops/assign_in_loop_2.circom | 14 ++--- circom/tests/loops/assign_in_loop_3.circom | 14 ++--- circom/tests/loops/call_inside_loop.circom | 6 +- circom/tests/loops/fib_input.circom | 2 +- circom/tests/loops/fib_template.circom | 2 +- .../tests/loops/fixed_idx_in_fixed_idx.circom | 4 +- circom/tests/loops/for_known.circom | 2 +- circom/tests/loops/for_unknown.circom | 2 +- circom/tests/loops/for_unknown_index.circom | 2 +- circom/tests/loops/init_nonzero.circom | 2 +- circom/tests/loops/inner_conditional_1.circom | 6 +- .../tests/loops/inner_conditional_10.circom | 2 +- .../tests/loops/inner_conditional_11.circom | 8 +-- circom/tests/loops/inner_conditional_2.circom | 10 ++-- circom/tests/loops/inner_conditional_3.circom | 4 +- circom/tests/loops/inner_conditional_4.circom | 6 +- circom/tests/loops/inner_conditional_5.circom | 10 ++-- circom/tests/loops/inner_conditional_6.circom | 4 +- circom/tests/loops/inner_conditional_7.circom | 8 +-- circom/tests/loops/inner_conditional_8.circom | 4 +- circom/tests/loops/inner_conditional_9.circom | 6 +- circom/tests/loops/inner_loop_simple.circom | 6 +- circom/tests/loops/inner_loops.circom | 6 +- circom/tests/loops/inner_loops2.circom | 12 ++-- circom/tests/loops/inner_loops3.circom | 12 ++-- circom/tests/loops/inner_loops4.circom | 6 +- circom/tests/loops/inner_loops5.circom | 4 +- circom/tests/loops/inner_loops6.circom | 6 +- circom/tests/loops/known_function.circom | 2 +- circom/tests/loops/known_signal_value.circom | 4 +- circom/tests/loops/simple_variant_idx.circom | 4 +- .../loops/unknown_index_from_array.circom | 2 +- .../loops/unknown_index_from_function.circom | 2 +- .../loops/unknown_local_array_index.circom | 2 +- .../tests/loops/unknown_loop_component.circom | 4 +- circom/tests/loops/unknown_loop_index.circom | 8 +-- circom/tests/loops/unknown_loop_oob.circom | 4 +- circom/tests/loops/vanguard-uc-comp.circom | 4 +- .../tests/loops/variant_idx_in_loop_A.circom | 4 +- .../tests/loops/variant_idx_in_loop_B.circom | 4 +- .../tests/loops/variant_idx_in_loop_C.circom | 2 +- .../subcmps/array_copy_constraints.circom | 2 +- circom/tests/subcmps/conv_map2idx_A.circom | 12 ++-- circom/tests/subcmps/conv_map2idx_B.circom | 12 ++-- circom/tests/subcmps/conv_map2idx_C.circom | 2 +- circom/tests/subcmps/large_array_param.circom | 8 +-- circom/tests/subcmps/mapped.circom | 10 ++-- circom/tests/subcmps/mapped2.circom | 10 ++-- circom/tests/subcmps/mapped3.circom | 28 ++++----- circom/tests/subcmps/mapped4.circom | 60 +++++++++---------- circom/tests/subcmps/subcmps0A.circom | 6 +- circom/tests/subcmps/subcmps0B.circom | 6 +- circom/tests/subcmps/subcmps0C.circom | 6 +- circom/tests/subcmps/subcmps0D.circom | 6 +- circom/tests/subcmps/subcmps1.circom | 4 +- circom/tests/subcmps/subcmps2.circom | 10 ++-- circom/tests/subcmps/subcmps3.circom | 11 ++-- circom/tests/type_conversions/bool_1.circom | 2 +- circom/tests/type_conversions/bool_2.circom | 2 +- circom/tests/type_conversions/bool_3.circom | 2 +- circom/tests/type_conversions/bool_4.circom | 2 +- .../tests/zzz/unreachable_code_crash.circom | 14 ++--- code_producers/src/llvm_elements/functions.rs | 9 +++ code_producers/src/llvm_elements/mod.rs | 12 ++++ code_producers/src/llvm_elements/stdlib.rs | 10 +++- code_producers/src/llvm_elements/template.rs | 4 ++ compiler/src/circuit_design/build.rs | 2 +- compiler/src/circuit_design/template.rs | 15 ++++- compiler/src/translating_traits/mod.rs | 1 + 78 files changed, 279 insertions(+), 235 deletions(-) diff --git a/circom/tests/arrays/array8.circom b/circom/tests/arrays/array8.circom index 2bfa1da79..f07688b8a 100644 --- a/circom/tests/arrays/array8.circom +++ b/circom/tests/arrays/array8.circom @@ -28,7 +28,7 @@ template ArrayReturnTemplate(n) { component main = ArrayReturnTemplate(4); -//CHECK-LABEL: define void @return_array_B_{{[0-9]+}} +//CHECK-LABEL: define{{.*}} void @return_array_B_{{[0-9]+}} //CHECK-SAME: (i256* %[[ARENA:.*]]) //CHECK: call void @return_array_A_{{[0-9]+}}(i256* %{{.*}}) //CHECK: %[[TEMP:.*]] = getelementptr i256, i256* %{{.*}}[[ARENA]], i32 2 @@ -36,12 +36,12 @@ component main = ArrayReturnTemplate(4); //CHECK: ret void //CHECK: } -//CHECK-LABEL: define void @return_array_A_{{[0-9]+}} +//CHECK-LABEL: define{{.*}} void @return_array_A_{{[0-9]+}} //CHECK-SAME: (i256* %[[ARENA:.*]]) //CHECK: ret void //CHECK: } -//CHECK-LABEL: define void @ArrayReturnTemplate_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @ArrayReturnTemplate_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %{{.*}}) //CHECK: %lvars = alloca [6 x i256] //CHECK: %[[TEMP:.*]] = getelementptr [6 x i256], [6 x i256]* %lvars, i32 0, i32 1 diff --git a/circom/tests/arrays/array9.circom b/circom/tests/arrays/array9.circom index 2e24db45d..5eb163686 100644 --- a/circom/tests/arrays/array9.circom +++ b/circom/tests/arrays/array9.circom @@ -14,7 +14,7 @@ template ArrayCopyTemplate() { component main = ArrayCopyTemplate(); -//CHECK-LABEL: define void @copy_{{[0-9]+}} +//CHECK-LABEL: define{{.*}} void @copy_{{[0-9]+}} //CHECK-SAME: (i256* %[[ARENA:.*]]) //CHECK: %[[TEMP1:.*]] = getelementptr i256, i256* %{{.*}}[[ARENA]], i32 3 //CHECK: %[[TEMP2:.*]] = getelementptr i256, i256* %{{.*}}[[ARENA]], i32 0 @@ -22,7 +22,7 @@ component main = ArrayCopyTemplate(); //CHECK: ret void //CHECK: } -//CHECK-LABEL: define void @ArrayCopyTemplate_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @ArrayCopyTemplate_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %{{.*}}) //CHECK: %lvars = alloca [6 x i256] //CHECK: %[[TEMP:.*]] = getelementptr [6 x i256], [6 x i256]* %lvars, i32 0, i32 3 diff --git a/circom/tests/arrays/array_copy1.circom b/circom/tests/arrays/array_copy1.circom index 3317229d2..7d88ffad6 100644 --- a/circom/tests/arrays/array_copy1.circom +++ b/circom/tests/arrays/array_copy1.circom @@ -11,7 +11,7 @@ template A(n) { component main = A(5); -//CHECK-LABEL: define void @A_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @A_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %0) //CHECK: %[[INP_PTR:[0-9]+]] = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 0 //CHECK: %[[INP_PTR_DST:[0-9]+]] = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 5 diff --git a/circom/tests/arrays/array_copy2.circom b/circom/tests/arrays/array_copy2.circom index 400ca754f..d4a099715 100644 --- a/circom/tests/arrays/array_copy2.circom +++ b/circom/tests/arrays/array_copy2.circom @@ -10,7 +10,7 @@ template A(n, S) { component main = A(5, [11,22,33,44,55]); -//CHECK-LABEL: define void @A_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @A_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %0) //CHECK: %[[INP_PTR:[0-9]+]] = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 0 //CHECK: %[[INP_PTR_DST:[0-9]+]] = getelementptr [6 x i256], [6 x i256]* %lvars, i32 0, i32 0 diff --git a/circom/tests/calls/call_with_array.circom b/circom/tests/calls/call_with_array.circom index 9f736893f..020ba32f3 100644 --- a/circom/tests/calls/call_with_array.circom +++ b/circom/tests/calls/call_with_array.circom @@ -15,7 +15,7 @@ template CallWithArray() { component main = CallWithArray(); -//CHECK-LABEL: define void @fr_copy_n +//CHECK-LABEL: define{{.*}} void @fr_copy_n //CHECK-SAME: (i256* %[[SRC:[0-9]+]], i256* %[[DST:[0-9]+]], i32 %[[LEN:[0-9]+]]) //CHECK: [[ENTRY_BB:.*]]: //CHECK: %[[I:.*]] = alloca i32 @@ -40,7 +40,7 @@ component main = CallWithArray(); //CHECK-SAME: preds = %[[COND_BB]] //CHECK: ret void -//CHECK-LABEL: define void @CallWithArray_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @CallWithArray_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]]) //CHECK: call1: //CHECK: %[[ARENA:sum_.*_arena]] = alloca [4 x i256] diff --git a/circom/tests/calls/call_with_array_and_scalar.circom b/circom/tests/calls/call_with_array_and_scalar.circom index 1c93efbf4..756575127 100644 --- a/circom/tests/calls/call_with_array_and_scalar.circom +++ b/circom/tests/calls/call_with_array_and_scalar.circom @@ -15,7 +15,7 @@ template CallWithArray() { component main = CallWithArray(); -//CHECK-LABEL: define void @CallWithArray_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @CallWithArray_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]]) //CHECK: call1: //CHECK: %[[ARENA:sum_.*_arena]] = alloca [6 x i256] diff --git a/circom/tests/controlflow/van348F.circom b/circom/tests/controlflow/van348F.circom index dcb16d3b8..2ab786b34 100644 --- a/circom/tests/controlflow/van348F.circom +++ b/circom/tests/controlflow/van348F.circom @@ -26,7 +26,7 @@ template BigModOld(n) { component main = BigModOld(2); -//CHECK-LABEL: define i256 @long_div_{{[0-9]+}} +//CHECK-LABEL: define{{.*}} i256 @long_div_{{[0-9]+}} //CHECK-SAME: (i256* %[[ARENA:.*]]) //CHECK: %[[TEMP1:.*]] = call i256 @short_div_{{.*}} //CHECK: %[[TEMP2:.*]] = getelementptr i256, i256* %{{.*}}[[ARENA]], i32 1 @@ -36,7 +36,7 @@ component main = BigModOld(2); //CHECK: ret i256 %{{.*}}[[TEMP4]] //CHECK: } -//CHECK-LABEL: define i256 @short_div_{{[0-9]+}} +//CHECK-LABEL: define{{.*}} i256 @short_div_{{[0-9]+}} //CHECK-SAME: (i256* %[[ARENA:.*]]) //CHECK: %[[TEMP1:.*]] = call i256 @identity_{{.*}} //CHECK: %[[TEMP2:.*]] = getelementptr i256, i256* %{{.*}}[[ARENA]], i32 1 diff --git a/circom/tests/controlflow/van544.circom b/circom/tests/controlflow/van544.circom index 40d4acc70..290bb808d 100644 --- a/circom/tests/controlflow/van544.circom +++ b/circom/tests/controlflow/van544.circom @@ -14,7 +14,7 @@ template Conditional() { component main = Conditional(); -//CHECK-LABEL: define void @Conditional_{{[0-9]+}}_run +//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 diff --git a/circom/tests/loops/assign_in_loop_1.circom b/circom/tests/loops/assign_in_loop_1.circom index 7eac236e1..2aee26196 100644 --- a/circom/tests/loops/assign_in_loop_1.circom +++ b/circom/tests/loops/assign_in_loop_1.circom @@ -23,7 +23,7 @@ template Num2Bits(n) { component main = Num2Bits(3); -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %subfix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %subfix_[[X3:[0-9]+]], //CHECK-SAME: [0 x i256]* %sub_[[X3]], i256* %subc_[[X3]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+\.T]]: @@ -66,7 +66,7 @@ component main = Num2Bits(3); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @Num2Bits_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @Num2Bits_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [2 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [3 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/loops/assign_in_loop_2.circom b/circom/tests/loops/assign_in_loop_2.circom index f6a7caa39..2a22110fe 100644 --- a/circom/tests/loops/assign_in_loop_2.circom +++ b/circom/tests/loops/assign_in_loop_2.circom @@ -24,22 +24,22 @@ template Num2Bits(n) { component main = Num2Bits(3); -//CHECK-LABEL: define void @Inner_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @Inner_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { // -//CHECK-LABEL: define void @Inner_ +//CHECK-LABEL: define{{.*}} void @Inner_ //CHECK-SAME: [[$RUN_1:[0-9]+]]_run([0 x i256]* %0){{.*}} { // -//CHECK-LABEL: define void @Inner_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @Inner_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { // -//CHECK-LABEL: define void @Inner_ +//CHECK-LABEL: define{{.*}} void @Inner_ //CHECK-SAME: [[$RUN_2:[0-9]+]]_run([0 x i256]* %0){{.*}} { // -//CHECK-LABEL: define void @Inner_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @Inner_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { // -//CHECK-LABEL: define void @Inner_ +//CHECK-LABEL: define{{.*}} void @Inner_ //CHECK-SAME: [[$RUN_3:[0-9]+]]_run([0 x i256]* %0){{.*}} { // -//CHECK-LABEL: define void @Num2Bits_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @Num2Bits_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK: unrolled_loop{{[0-9]+}}: //CHECK: call void @Inner_[[$RUN_1]]_run([0 x i256]* % //CHECK: call void @Inner_[[$RUN_2]]_run([0 x i256]* % diff --git a/circom/tests/loops/assign_in_loop_3.circom b/circom/tests/loops/assign_in_loop_3.circom index cef469df3..64f1aca39 100644 --- a/circom/tests/loops/assign_in_loop_3.circom +++ b/circom/tests/loops/assign_in_loop_3.circom @@ -24,22 +24,22 @@ template Num2Bits(n) { component main = Num2Bits(3); -//CHECK-LABEL: define void @Inner_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @Inner_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { // -//CHECK-LABEL: define void @Inner_ +//CHECK-LABEL: define{{.*}} void @Inner_ //CHECK-SAME: [[$RUN_1:[0-9]+]]_run([0 x i256]* %0){{.*}} { // -//CHECK-LABEL: define void @Inner_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @Inner_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { // -//CHECK-LABEL: define void @Inner_ +//CHECK-LABEL: define{{.*}} void @Inner_ //CHECK-SAME: [[$RUN_2:[0-9]+]]_run([0 x i256]* %0){{.*}} { // -//CHECK-LABEL: define void @Inner_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @Inner_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { // -//CHECK-LABEL: define void @Inner_ +//CHECK-LABEL: define{{.*}} void @Inner_ //CHECK-SAME: [[$RUN_3:[0-9]+]]_run([0 x i256]* %0){{.*}} { // -//CHECK-LABEL: define void @Num2Bits_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @Num2Bits_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK: unrolled_loop{{[0-9]+}}: //CHECK: call void @Inner_[[$RUN_1]]_run([0 x i256]* % //CHECK: call void @Inner_[[$RUN_2]]_run([0 x i256]* % diff --git a/circom/tests/loops/call_inside_loop.circom b/circom/tests/loops/call_inside_loop.circom index 3a4375cd7..dbc3f3c80 100644 --- a/circom/tests/loops/call_inside_loop.circom +++ b/circom/tests/loops/call_inside_loop.circom @@ -44,7 +44,7 @@ component main = CallInLoop(2, 3); // i = 2; // out <-- b[0]; // -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1]]: //CHECK-NEXT: br label %store1 @@ -69,7 +69,7 @@ component main = CallInLoop(2, 3); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_2:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_2]]: //CHECK-NEXT: br label %call1 @@ -111,7 +111,7 @@ component main = CallInLoop(2, 3); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @CallInLoop_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @CallInLoop_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [7 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/loops/fib_input.circom b/circom/tests/loops/fib_input.circom index e821b45bb..f1962d5f2 100644 --- a/circom/tests/loops/fib_input.circom +++ b/circom/tests/loops/fib_input.circom @@ -25,7 +25,7 @@ template 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-LABEL: define{{.*}} void @Fibonacci_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]]) //CHECK-NOT: unrolled_loop{{.*}}: //CHECK: loop.cond{{.*}}: diff --git a/circom/tests/loops/fib_template.circom b/circom/tests/loops/fib_template.circom index 003e1fcf1..3e6b8089e 100644 --- a/circom/tests/loops/fib_template.circom +++ b/circom/tests/loops/fib_template.circom @@ -29,7 +29,7 @@ template FibonacciTmpl(N) { component main = FibonacciTmpl(5); -//CHECK-LABEL: define void @FibonacciTmpl_{{[0-9]+}}_run +//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{{.*}}: diff --git a/circom/tests/loops/fixed_idx_in_fixed_idx.circom b/circom/tests/loops/fixed_idx_in_fixed_idx.circom index 6f34c84b3..fb4c2209e 100644 --- a/circom/tests/loops/fixed_idx_in_fixed_idx.circom +++ b/circom/tests/loops/fixed_idx_in_fixed_idx.circom @@ -18,7 +18,7 @@ template EmulatedAesencRowShifting() { component main = EmulatedAesencRowShifting(); -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0, i256* %fix_1){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1]]: //CHECK-NEXT: br label %store1 @@ -45,7 +45,7 @@ component main = EmulatedAesencRowShifting(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @EmulatedAesencRowShifting_0_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @EmulatedAesencRowShifting_0_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [17 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/loops/for_known.circom b/circom/tests/loops/for_known.circom index acbecf2ed..7635ae5c0 100644 --- a/circom/tests/loops/for_known.circom +++ b/circom/tests/loops/for_known.circom @@ -15,7 +15,7 @@ template ForKnown(N) { component main = ForKnown(10); -//CHECK-LABEL: define void @ForKnown_{{[0-9]+}}_run +//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{{.*}}: diff --git a/circom/tests/loops/for_unknown.circom b/circom/tests/loops/for_unknown.circom index b3d522043..7a5c81102 100644 --- a/circom/tests/loops/for_unknown.circom +++ b/circom/tests/loops/for_unknown.circom @@ -17,7 +17,7 @@ template 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-LABEL: define{{.*}} void @ForUnknown_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]]) //CHECK-NOT: unrolled_loop{{.*}}: //CHECK: loop.cond{{.*}}: diff --git a/circom/tests/loops/for_unknown_index.circom b/circom/tests/loops/for_unknown_index.circom index 091cbd8d7..9bf6356b4 100644 --- a/circom/tests/loops/for_unknown_index.circom +++ b/circom/tests/loops/for_unknown_index.circom @@ -20,7 +20,7 @@ template 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-LABEL: define{{.*}} void @ForUnknownIndex_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]]) //CHECK-NOT: unrolled_loop{{.*}}: //CHECK: loop.cond{{.*}}: diff --git a/circom/tests/loops/init_nonzero.circom b/circom/tests/loops/init_nonzero.circom index 9ac1520a6..542eb565b 100644 --- a/circom/tests/loops/init_nonzero.circom +++ b/circom/tests/loops/init_nonzero.circom @@ -20,7 +20,7 @@ template NonZeroInit() { component main = NonZeroInit(); -//CHECK-LABEL: define void @NonZeroInit_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @NonZeroInit_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { // //CHECK: store{{[0-9]+}}: //CHECK-NEXT: %[[VAR1:[0-9]+]] = getelementptr [1 x i256], [1 x i256]* %lvars, i32 0, i32 0 diff --git a/circom/tests/loops/inner_conditional_1.circom b/circom/tests/loops/inner_conditional_1.circom index f76f5f361..a7c6c8527 100644 --- a/circom/tests/loops/inner_conditional_1.circom +++ b/circom/tests/loops/inner_conditional_1.circom @@ -32,7 +32,7 @@ template InnerConditional1(N) { component main = InnerConditional1(10); -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}.F([0 x i256]* %lvars, [0 x i256]* %signals){{.*}} { +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}.F([0 x i256]* %lvars, [0 x i256]* %signals){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+\.F]]: //CHECK-NEXT: br label %fold_false1 //CHECK-EMPTY: @@ -58,7 +58,7 @@ component main = InnerConditional1(10); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}.T([0 x i256]* %lvars, [0 x i256]* %signals){{.*}} { +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}.T([0 x i256]* %lvars, [0 x i256]* %signals){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_2:[0-9]+\.T]]: //CHECK-NEXT: br label %fold_true1 //CHECK-EMPTY: @@ -84,7 +84,7 @@ component main = InnerConditional1(10); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @InnerConditional1_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @InnerConditional1_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [3 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/loops/inner_conditional_10.circom b/circom/tests/loops/inner_conditional_10.circom index ddc93e38e..4bac3ea42 100644 --- a/circom/tests/loops/inner_conditional_10.circom +++ b/circom/tests/loops/inner_conditional_10.circom @@ -26,7 +26,7 @@ template Poseidon() { component main = Poseidon(); -//CHECK-LABEL: define void @Poseidon_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @Poseidon_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [2 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [2 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/loops/inner_conditional_11.circom b/circom/tests/loops/inner_conditional_11.circom index a18a080ee..8d481e84e 100644 --- a/circom/tests/loops/inner_conditional_11.circom +++ b/circom/tests/loops/inner_conditional_11.circom @@ -26,7 +26,7 @@ template Poseidon() { component main = Poseidon(); -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.F\.F}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+\.F\.F}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+\.F\.F]]: //CHECK-NEXT: br label %fold_false1 @@ -46,7 +46,7 @@ component main = Poseidon(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.F\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+\.F\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_2:[0-9]+\.F\.T]]: //CHECK-NEXT: br label %fold_false1 @@ -73,7 +73,7 @@ component main = Poseidon(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_3:[0-9]+\.T]]: //CHECK-NEXT: br label %fold_true1 @@ -100,7 +100,7 @@ component main = Poseidon(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @Poseidon_1_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @Poseidon_1_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [1 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [2 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/loops/inner_conditional_2.circom b/circom/tests/loops/inner_conditional_2.circom index 5f0a7648f..b891ed045 100644 --- a/circom/tests/loops/inner_conditional_2.circom +++ b/circom/tests/loops/inner_conditional_2.circom @@ -29,7 +29,7 @@ template runner() { component main = runner(); -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1]]: //CHECK-NEXT: br label %store1 @@ -56,7 +56,7 @@ component main = runner(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_2:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_2]]: //CHECK-NEXT: br label %store1 @@ -83,7 +83,7 @@ component main = runner(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @InnerConditional2_0_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @InnerConditional2_0_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [4 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 @@ -129,7 +129,7 @@ component main = runner(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @InnerConditional2_1_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @InnerConditional2_1_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [4 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 @@ -177,7 +177,7 @@ component main = runner(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @runner_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @runner_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [0 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [2 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/loops/inner_conditional_3.circom b/circom/tests/loops/inner_conditional_3.circom index 554282a24..682e1bf12 100644 --- a/circom/tests/loops/inner_conditional_3.circom +++ b/circom/tests/loops/inner_conditional_3.circom @@ -21,7 +21,7 @@ template InnerConditional3(N) { component main = InnerConditional3(3); -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1]]: //CHECK-NEXT: br label %branch1 @@ -67,7 +67,7 @@ component main = InnerConditional3(3); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @InnerConditional3_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @InnerConditional3_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [3 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/loops/inner_conditional_4.circom b/circom/tests/loops/inner_conditional_4.circom index 7480fd5e1..bf5844705 100644 --- a/circom/tests/loops/inner_conditional_4.circom +++ b/circom/tests/loops/inner_conditional_4.circom @@ -18,7 +18,7 @@ template InnerConditional4(N) { component main = InnerConditional4(6); -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}.F([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}.F([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+\.F]]: //CHECK-NEXT: br label %fold_false1 @@ -42,7 +42,7 @@ component main = InnerConditional4(6); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}.T([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}.T([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_2:[0-9]+\.T]]: //CHECK-NEXT: br label %fold_true1 @@ -67,7 +67,7 @@ component main = InnerConditional4(6); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @InnerConditional4_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @InnerConditional4_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [2 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/loops/inner_conditional_5.circom b/circom/tests/loops/inner_conditional_5.circom index 37748c52d..1c2ebcf20 100644 --- a/circom/tests/loops/inner_conditional_5.circom +++ b/circom/tests/loops/inner_conditional_5.circom @@ -26,7 +26,7 @@ template runner() { component main = runner(); -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1]]: //CHECK-NEXT: br label %store1 @@ -48,7 +48,7 @@ component main = runner(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_2:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_2]]: //CHECK-NEXT: br label %store1 @@ -70,7 +70,7 @@ component main = runner(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @InnerConditional5_0_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @InnerConditional5_0_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [3 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 @@ -110,7 +110,7 @@ component main = runner(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @InnerConditional5_1_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @InnerConditional5_1_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [3 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 @@ -153,7 +153,7 @@ component main = runner(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @runner_2_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @runner_2_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [0 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [2 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/loops/inner_conditional_6.circom b/circom/tests/loops/inner_conditional_6.circom index 233e74b44..b667e44ba 100644 --- a/circom/tests/loops/inner_conditional_6.circom +++ b/circom/tests/loops/inner_conditional_6.circom @@ -26,7 +26,7 @@ template InnerConditional6(N) { component main = InnerConditional6(4); -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1]]: //CHECK-NEXT: br label %store1 @@ -74,7 +74,7 @@ component main = InnerConditional6(4); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @InnerConditional6_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @InnerConditional6_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [3 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/loops/inner_conditional_7.circom b/circom/tests/loops/inner_conditional_7.circom index 43683a341..cbd9a6773 100644 --- a/circom/tests/loops/inner_conditional_7.circom +++ b/circom/tests/loops/inner_conditional_7.circom @@ -28,7 +28,7 @@ template InnerConditional7(N) { component main = InnerConditional7(3); -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}.F([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}.F([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+\.F]]: //CHECK-NEXT: br label %fold_false1 @@ -53,7 +53,7 @@ component main = InnerConditional7(3); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}.F([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}.F([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_2:[0-9]+\.F]]: //CHECK-NEXT: br label %fold_false1 @@ -78,7 +78,7 @@ component main = InnerConditional7(3); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}.T([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}.T([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_3:[0-9]+\.T]]: //CHECK-NEXT: br label %fold_true1 @@ -100,7 +100,7 @@ component main = InnerConditional7(3); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @InnerConditional7_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @InnerConditional7_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [6 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/loops/inner_conditional_8.circom b/circom/tests/loops/inner_conditional_8.circom index 2f7c3f217..3ace667a7 100644 --- a/circom/tests/loops/inner_conditional_8.circom +++ b/circom/tests/loops/inner_conditional_8.circom @@ -22,7 +22,7 @@ template InnerConditional8(N) { component main = InnerConditional8(4); -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]], i256* %fix_[[X4:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1]]: //CHECK-NEXT: br label %store1 @@ -86,7 +86,7 @@ component main = InnerConditional8(4); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @InnerConditional8_0_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @InnerConditional8_0_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [7 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/loops/inner_conditional_9.circom b/circom/tests/loops/inner_conditional_9.circom index 0c630d167..314c8a649 100644 --- a/circom/tests/loops/inner_conditional_9.circom +++ b/circom/tests/loops/inner_conditional_9.circom @@ -25,7 +25,7 @@ template InnerConditional9(N) { component main = InnerConditional9(4); -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}.F([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}.F([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]], i256* %fix_[[X4:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+\.F]]: //CHECK-NEXT: br label %fold_false1 @@ -69,7 +69,7 @@ component main = InnerConditional9(4); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}.T([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}.T([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]], i256* %fix_[[X4:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_2:[0-9]+\.T]]: //CHECK-NEXT: br label %fold_true1 @@ -113,7 +113,7 @@ component main = InnerConditional9(4); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @InnerConditional9_0_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @InnerConditional9_0_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [7 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/loops/inner_loop_simple.circom b/circom/tests/loops/inner_loop_simple.circom index d1e0b00c8..ed2d9b238 100644 --- a/circom/tests/loops/inner_loop_simple.circom +++ b/circom/tests/loops/inner_loop_simple.circom @@ -20,7 +20,7 @@ component main = InnerLoops(2, 3); // %0 (i.e. signal arena) = { out, in[0], in[1], in[2] } // %lvars = { n, m, b[0], b[1], i, j } // -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1]]: //CHECK-NEXT: br label %store{{[0-9]+}} @@ -49,7 +49,7 @@ component main = InnerLoops(2, 3); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_2:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_2]]: //CHECK-NEXT: br label %store{{[0-9]+}} @@ -78,7 +78,7 @@ component main = InnerLoops(2, 3); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @InnerLoops_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @InnerLoops_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK: unrolled_loop{{[0-9]+}}: //CHECK-NEXT: %6 = getelementptr [6 x i256], [6 x i256]* %lvars, i32 0, i32 5 //CHECK-NEXT: store i256 0, i256* %6, align 4 diff --git a/circom/tests/loops/inner_loops.circom b/circom/tests/loops/inner_loops.circom index c2cef8c42..f02663513 100644 --- a/circom/tests/loops/inner_loops.circom +++ b/circom/tests/loops/inner_loops.circom @@ -30,7 +30,7 @@ component main = InnerLoops(2); // b[1] = b[1] + a[1 - 0 = 1]; //extracted function 2 // b[1] = b[1] + a[1 - 1 = 0]; //extracted function 2 // -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1]]: //CHECK-NEXT: br label %store1 @@ -75,7 +75,7 @@ component main = InnerLoops(2); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_2:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_2]]: //CHECK-NEXT: br label %store1 @@ -112,7 +112,7 @@ component main = InnerLoops(2); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @InnerLoops_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @InnerLoops_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK: unrolled_loop{{[0-9]+}}: //CHECK-NEXT: %5 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 4 //CHECK-NEXT: store i256 0, i256* %5, align 4 diff --git a/circom/tests/loops/inner_loops2.circom b/circom/tests/loops/inner_loops2.circom index df0775c1d..aef3fc0f8 100644 --- a/circom/tests/loops/inner_loops2.circom +++ b/circom/tests/loops/inner_loops2.circom @@ -34,7 +34,7 @@ template InnerLoops(n) { component main = InnerLoops(5); -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1]]: //CHECK-NEXT: br label %store{{[0-9]+}} @@ -55,7 +55,7 @@ component main = InnerLoops(5); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_2:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_2]]: //CHECK-NEXT: br label %store{{[0-9]+}} @@ -79,7 +79,7 @@ component main = InnerLoops(5); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_3:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_3]]: //CHECK-NEXT: br label %store{{[0-9]+}} @@ -103,7 +103,7 @@ component main = InnerLoops(5); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_4:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_4]]: //CHECK-NEXT: br label %store{{[0-9]+}} @@ -127,7 +127,7 @@ component main = InnerLoops(5); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_5:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_5]]: //CHECK-NEXT: br label %store{{[0-9]+}} @@ -151,7 +151,7 @@ component main = InnerLoops(5); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @InnerLoops_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @InnerLoops_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK: unrolled_loop{{[0-9]+}}: //CHECK-NEXT: %9 = bitcast [8 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %9, [0 x i256]* %0) diff --git a/circom/tests/loops/inner_loops3.circom b/circom/tests/loops/inner_loops3.circom index 558d94961..bb5284dc2 100644 --- a/circom/tests/loops/inner_loops3.circom +++ b/circom/tests/loops/inner_loops3.circom @@ -25,7 +25,7 @@ template InnerLoops(n) { component main = InnerLoops(5); -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1]]: //CHECK-NEXT: br label %store{{[0-9]+}} @@ -46,7 +46,7 @@ component main = InnerLoops(5); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_2:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_2]]: //CHECK-NEXT: br label %store{{[0-9]+}} @@ -70,7 +70,7 @@ component main = InnerLoops(5); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_3:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_3]]: //CHECK-NEXT: br label %store{{[0-9]+}} @@ -94,7 +94,7 @@ component main = InnerLoops(5); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_4:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_4]]: //CHECK-NEXT: br label %store{{[0-9]+}} @@ -118,7 +118,7 @@ component main = InnerLoops(5); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_5:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_5]]: //CHECK-NEXT: br label %store{{[0-9]+}} @@ -142,7 +142,7 @@ component main = InnerLoops(5); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @InnerLoops_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @InnerLoops_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK: unrolled_loop{{[0-9]+}}: //CHECK-NEXT: %8 = bitcast [7 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %8, [0 x i256]* %0) diff --git a/circom/tests/loops/inner_loops4.circom b/circom/tests/loops/inner_loops4.circom index 6c33e35a4..3100d7a40 100644 --- a/circom/tests/loops/inner_loops4.circom +++ b/circom/tests/loops/inner_loops4.circom @@ -31,7 +31,7 @@ component main = InnerLoops(2); // b[1] = a[1]; // b[1] = a[0]; // -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1]]: //CHECK-NEXT: br label %store{{[0-9]+}} @@ -68,7 +68,7 @@ component main = InnerLoops(2); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_2:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_2]]: //CHECK-NEXT: br label %store{{[0-9]+}} @@ -97,7 +97,7 @@ component main = InnerLoops(2); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @InnerLoops_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @InnerLoops_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK: unrolled_loop{{[0-9]+}}: //CHECK-NEXT: %6 = getelementptr [5 x i256], [5 x i256]* %lvars, i32 0, i32 3 //CHECK-NEXT: store i256 0, i256* %6, align 4 diff --git a/circom/tests/loops/inner_loops5.circom b/circom/tests/loops/inner_loops5.circom index 8cee6ce78..161344230 100644 --- a/circom/tests/loops/inner_loops5.circom +++ b/circom/tests/loops/inner_loops5.circom @@ -19,7 +19,7 @@ template Num2Bits(n) { component main = Num2Bits(4); -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1]]: //CHECK-NEXT: br label %store{{[0-9]+}} @@ -72,7 +72,7 @@ component main = Num2Bits(4); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @Num2Bits_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @Num2Bits_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK: unrolled_loop{{[0-9]+}}: //CHECK-NEXT: %4 = bitcast [4 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %4, [0 x i256]* %0) diff --git a/circom/tests/loops/inner_loops6.circom b/circom/tests/loops/inner_loops6.circom index ee885c37f..f9d015158 100644 --- a/circom/tests/loops/inner_loops6.circom +++ b/circom/tests/loops/inner_loops6.circom @@ -35,7 +35,7 @@ component main = Num2Bits(2); // out[2] = in; // out[3] = in; // -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1]]: //CHECK-NEXT: br label %store{{[0-9]+}} @@ -59,7 +59,7 @@ component main = Num2Bits(2); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID_2:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_2]]: //CHECK-NEXT: br label %store{{[0-9]+}} @@ -83,7 +83,7 @@ component main = Num2Bits(2); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @Num2Bits_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @Num2Bits_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK: unrolled_loop{{[0-9]+}}: //CHECK-NEXT: %3 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 2 //CHECK-NEXT: store i256 0, i256* %3, align 4 diff --git a/circom/tests/loops/known_function.circom b/circom/tests/loops/known_function.circom index d88d7b790..49aecce73 100644 --- a/circom/tests/loops/known_function.circom +++ b/circom/tests/loops/known_function.circom @@ -25,7 +25,7 @@ template KnownFunctionArgs() { component main = KnownFunctionArgs(); -//CHECK-LABEL: define void @KnownFunctionArgs_{{[0-9]+}}_run +//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]+}}: diff --git a/circom/tests/loops/known_signal_value.circom b/circom/tests/loops/known_signal_value.circom index 881e15fa8..42d7ef923 100644 --- a/circom/tests/loops/known_signal_value.circom +++ b/circom/tests/loops/known_signal_value.circom @@ -23,7 +23,7 @@ template KnownLoopViaSignal() { component main = KnownLoopViaSignal(); //// Use the block labels to check that the loop is NOT unrolled -//CHECK-LABEL: define void @accumulate_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @accumulate_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]]) //CHECK-NOT: unrolled_loop{{.*}}: //CHECK: loop.cond{{.*}}: @@ -33,7 +33,7 @@ component main = KnownLoopViaSignal(); //CHECK: } //// Use the block labels to check that no loop related blocks are present -//CHECK-LABEL: define void @KnownLoopViaSignal_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @KnownLoopViaSignal_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]]) //CHECK-NOT: {{.*}}loop{{.*}}: //CHECK: } diff --git a/circom/tests/loops/simple_variant_idx.circom b/circom/tests/loops/simple_variant_idx.circom index b72bbc2fe..407d2f271 100644 --- a/circom/tests/loops/simple_variant_idx.circom +++ b/circom/tests/loops/simple_variant_idx.circom @@ -23,7 +23,7 @@ component main = SimpleVariantIdx(3); // %lvars = [ n, lc, i ] // %subcmps = [] // -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK: store{{[0-9]+}}: //CHECK-NEXT: %0 = getelementptr [0 x i256], [0 x i256]* %signals, i32 0, i32 3 @@ -51,7 +51,7 @@ component main = SimpleVariantIdx(3); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @SimpleVariantIdx_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @SimpleVariantIdx_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]]) //CHECK: unrolled_loop{{[0-9]+}}: //CHECK-NEXT: %4 = bitcast [3 x i256]* %lvars to [0 x i256]* diff --git a/circom/tests/loops/unknown_index_from_array.circom b/circom/tests/loops/unknown_index_from_array.circom index a1f033191..0214e955a 100644 --- a/circom/tests/loops/unknown_index_from_array.circom +++ b/circom/tests/loops/unknown_index_from_array.circom @@ -17,7 +17,7 @@ component main = Example(3); // %0 (i.e. signal arena) = { c[0], c[1], c[2] , a[0], a[1], a[2], b[0], b[1], b[2] } // %lvars = { n, i } // -//CHECK-LABEL: define void @Example_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @Example_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]]) //CHECK: unrolled_loop{{[0-9]+}}: //CHECK-NOT: call void @..generated..loop.body.{{.*}} diff --git a/circom/tests/loops/unknown_index_from_function.circom b/circom/tests/loops/unknown_index_from_function.circom index 7f45c66ef..2ace9b198 100644 --- a/circom/tests/loops/unknown_index_from_function.circom +++ b/circom/tests/loops/unknown_index_from_function.circom @@ -26,7 +26,7 @@ component main = Example(3); // %0 (i.e. signal arena) { c[0], c[1], c[2] , a[0], a[1], a[2], b } // %lvars = { n, i, } // -//CHECK-LABEL: define void @Example_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @Example_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]]) //CHECK: unrolled_loop{{[0-9]+}}: //CHECK-NOT: call void @..generated..loop.body.{{.*}} diff --git a/circom/tests/loops/unknown_local_array_index.circom b/circom/tests/loops/unknown_local_array_index.circom index 2cdcf38be..5796cdd80 100644 --- a/circom/tests/loops/unknown_local_array_index.circom +++ b/circom/tests/loops/unknown_local_array_index.circom @@ -23,7 +23,7 @@ template 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-LABEL: define{{.*}} void @ForUnknownIndex_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]]) //CHECK-NOT: unrolled_loop{{.*}}: //CHECK: loop.cond{{.*}}: diff --git a/circom/tests/loops/unknown_loop_component.circom b/circom/tests/loops/unknown_loop_component.circom index 53ffd97af..671582d64 100644 --- a/circom/tests/loops/unknown_loop_component.circom +++ b/circom/tests/loops/unknown_loop_component.circom @@ -26,7 +26,7 @@ template UnknownLoopComponent() { component main = UnknownLoopComponent(); //// Use the block labels to check that the loop is NOT unrolled -//CHECK-LABEL: define void @nbits_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @nbits_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]]) //CHECK-NOT: unrolled_loop{{.*}}: //CHECK: loop.cond{{.*}}: @@ -36,7 +36,7 @@ component main = UnknownLoopComponent(); //CHECK: } //// Use the block labels to check that no loop related blocks are present -//CHECK-LABEL: define void @UnknownLoopComponent_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @UnknownLoopComponent_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]]) //CHECK-NOT: {{.*}}loop{{.*}}: //CHECK: } diff --git a/circom/tests/loops/unknown_loop_index.circom b/circom/tests/loops/unknown_loop_index.circom index 9b75d7e9d..2ed2e1ba3 100644 --- a/circom/tests/loops/unknown_loop_index.circom +++ b/circom/tests/loops/unknown_loop_index.circom @@ -67,7 +67,7 @@ template UnknownLoopIndex(n) { component main = UnknownLoopIndex(100); //// Use the block labels to check that the loop is unrolled -//CHECK-LABEL: define void @Num2Bits_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @Num2Bits_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]]) //CHECK-NOT: loop.cond{{.*}}: //CHECK-NOT: loop.body{{.*}}: @@ -79,13 +79,13 @@ component main = UnknownLoopIndex(100); //CHECK: } //// Use the block labels to check that no loop related blocks are present -//CHECK-LABEL: define void @LessThan_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @LessThan_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]]) //CHECK-NOT: {{.*}}loop{{.*}}: //CHECK: } //// Use the block labels to check that the loop is NOT unrolled -//CHECK-LABEL: define void @CountDown_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @CountDown_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]]) //CHECK-NOT: unrolled_loop{{.*}}: //CHECK: loop.cond{{.*}}: @@ -95,7 +95,7 @@ component main = UnknownLoopIndex(100); //CHECK: } //// Use the block labels to check that no loop related blocks are present -//CHECK-LABEL: define void @UnknownLoopIndex_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @UnknownLoopIndex_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]]) //CHECK-NOT: {{.*}}loop{{.*}}: //CHECK: } diff --git a/circom/tests/loops/unknown_loop_oob.circom b/circom/tests/loops/unknown_loop_oob.circom index 6b8c03676..4e9d7e832 100644 --- a/circom/tests/loops/unknown_loop_oob.circom +++ b/circom/tests/loops/unknown_loop_oob.circom @@ -25,7 +25,7 @@ template UnknownLoopOOB() { component main = UnknownLoopOOB(); //// Use the block labels to check that the loop is NOT unrolled -//CHECK-LABEL: define void @accumulate_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @accumulate_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]]) //CHECK-NOT: unrolled_loop{{.*}}: //CHECK: loop.cond{{.*}}: @@ -35,7 +35,7 @@ component main = UnknownLoopOOB(); //CHECK: } //// Use the block labels to check that no loop related blocks are present -//CHECK-LABEL: define void @UnknownLoopOOB_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @UnknownLoopOOB_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]]) //CHECK-NOT: {{.*}}loop{{.*}}: //CHECK: } diff --git a/circom/tests/loops/vanguard-uc-comp.circom b/circom/tests/loops/vanguard-uc-comp.circom index b67e6c122..4b973a2db 100644 --- a/circom/tests/loops/vanguard-uc-comp.circom +++ b/circom/tests/loops/vanguard-uc-comp.circom @@ -24,7 +24,7 @@ component main = Num2Bits(2); // %lvars = [ n, lc1, e2, i ] // %subcmps = [] // -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]], i256* %fix_[[X4:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID]]: //CHECK-NEXT: br label %store1 @@ -88,7 +88,7 @@ component main = Num2Bits(2); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @Num2Bits_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @Num2Bits_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]]) //CHECK: unrolled_loop{{[0-9]+}}: //CHECK-NEXT: %5 = bitcast [4 x i256]* %lvars to [0 x i256]* diff --git a/circom/tests/loops/variant_idx_in_loop_A.circom b/circom/tests/loops/variant_idx_in_loop_A.circom index b35250f72..28c849827 100644 --- a/circom/tests/loops/variant_idx_in_loop_A.circom +++ b/circom/tests/loops/variant_idx_in_loop_A.circom @@ -17,7 +17,7 @@ component main = VariantIndex(2); // %lvars = [ n, i ] // %subcmps = [] // -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0){{.*}} { //CHECK: store{{[0-9]+}}: //CHECK-NEXT: %0 = getelementptr [0 x i256], [0 x i256]* %signals, i32 0, i32 2 @@ -41,7 +41,7 @@ component main = VariantIndex(2); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @VariantIndex_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @VariantIndex_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]]) //CHECK: unrolled_loop{{[0-9]+}}: //CHECK-NEXT: %3 = bitcast [2 x i256]* %lvars to [0 x i256]* diff --git a/circom/tests/loops/variant_idx_in_loop_B.circom b/circom/tests/loops/variant_idx_in_loop_B.circom index b85223b1d..f6ebaea30 100644 --- a/circom/tests/loops/variant_idx_in_loop_B.circom +++ b/circom/tests/loops/variant_idx_in_loop_B.circom @@ -19,7 +19,7 @@ component main = VariantIndex(2); // %lvars = [ n, temp[0], temp[1], i ] // %subcmps = [] // -//CHECK-LABEL: define void @..generated..loop.body. +//CHECK-LABEL: define{{.*}} void @..generated..loop.body. //CHECK-SAME: [[$F_ID:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0){{.*}} { //CHECK: store{{[0-9]+}}: //CHECK-NEXT: %0 = getelementptr [0 x i256], [0 x i256]* %signals, i32 0, i32 1 @@ -43,7 +43,7 @@ component main = VariantIndex(2); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @VariantIndex_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @VariantIndex_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]]) //CHECK: unrolled_loop{{[0-9]+}}: //CHECK-NEXT: %5 = bitcast [4 x i256]* %lvars to [0 x i256]* diff --git a/circom/tests/loops/variant_idx_in_loop_C.circom b/circom/tests/loops/variant_idx_in_loop_C.circom index f3313bc95..29b9297cf 100644 --- a/circom/tests/loops/variant_idx_in_loop_C.circom +++ b/circom/tests/loops/variant_idx_in_loop_C.circom @@ -23,7 +23,7 @@ component main = VariantIndex(2); // %lvars = [ n, lc1, e2, i ] // %subcmps = [] // -//CHECK-LABEL: define void @VariantIndex_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @VariantIndex_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %[[ARG:[0-9]+]]) //CHECK: unrolled_loop{{[0-9]+}}: //CHECK-NOT: call void @..generated..loop.body.{{.*}} diff --git a/circom/tests/subcmps/array_copy_constraints.circom b/circom/tests/subcmps/array_copy_constraints.circom index c2e5b8e2e..0aa085801 100644 --- a/circom/tests/subcmps/array_copy_constraints.circom +++ b/circom/tests/subcmps/array_copy_constraints.circom @@ -26,7 +26,7 @@ template Caller(n) { component main = Caller(5); -//CHECK-LABEL: define void @Caller_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @Caller_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %0) //CHECK: store{{[0-9]+}}: ; preds = %create_cmp{{[0-9]+}} //CHECK: %[[SUBCMP_PTR:[0-9]+]] = getelementptr [1 x { [0 x i256]*, i32 }], [1 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 diff --git a/circom/tests/subcmps/conv_map2idx_A.circom b/circom/tests/subcmps/conv_map2idx_A.circom index a3c2e43d0..9d9b5230a 100644 --- a/circom/tests/subcmps/conv_map2idx_A.circom +++ b/circom/tests/subcmps/conv_map2idx_A.circom @@ -19,7 +19,7 @@ template ComputeValue() { component main = ComputeValue(); -//CHECK-LABEL: define void @GetWeight_0_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @GetWeight_0_build({ [0 x i256]*, i32 }* %0){{.*}} { //CHECK-NEXT: main: //CHECK-NEXT: %1 = alloca [1 x i256], align 8 //CHECK-NEXT: %2 = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 @@ -30,7 +30,7 @@ component main = ComputeValue(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @GetWeight_0_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @GetWeight_0_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [1 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 @@ -45,7 +45,7 @@ component main = ComputeValue(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @GetWeight_1_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @GetWeight_1_build({ [0 x i256]*, i32 }* %0){{.*}} { //CHECK-NEXT: main: //CHECK-NEXT: %1 = alloca [1 x i256], align 8 //CHECK-NEXT: %2 = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 @@ -56,7 +56,7 @@ component main = ComputeValue(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @GetWeight_1_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @GetWeight_1_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [1 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 @@ -71,7 +71,7 @@ component main = ComputeValue(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @ComputeValue_2_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @ComputeValue_2_build({ [0 x i256]*, i32 }* %0){{.*}} { //CHECK-NEXT: main: //CHECK-NEXT: %1 = alloca [0 x i256], align 8 //CHECK-NEXT: %2 = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 @@ -81,7 +81,7 @@ component main = ComputeValue(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @ComputeValue_2_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @ComputeValue_2_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [0 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [2 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/subcmps/conv_map2idx_B.circom b/circom/tests/subcmps/conv_map2idx_B.circom index 7fe243854..27e5bef79 100644 --- a/circom/tests/subcmps/conv_map2idx_B.circom +++ b/circom/tests/subcmps/conv_map2idx_B.circom @@ -22,7 +22,7 @@ template ComputeValue() { component main = ComputeValue(); -//CHECK-LABEL: define void @GetWeight_0_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @GetWeight_0_build({ [0 x i256]*, i32 }* %0){{.*}} { //CHECK-NEXT: main: //CHECK-NEXT: %1 = alloca [3 x i256], align 8 //CHECK-NEXT: %2 = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 @@ -33,7 +33,7 @@ component main = ComputeValue(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @GetWeight_0_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @GetWeight_0_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [2 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 @@ -58,7 +58,7 @@ component main = ComputeValue(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @GetWeight_1_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @GetWeight_1_build({ [0 x i256]*, i32 }* %0){{.*}} { //CHECK-NEXT: main: //CHECK-NEXT: %1 = alloca [3 x i256], align 8 //CHECK-NEXT: %2 = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 @@ -69,7 +69,7 @@ component main = ComputeValue(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @GetWeight_1_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @GetWeight_1_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [2 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 @@ -94,7 +94,7 @@ component main = ComputeValue(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @ComputeValue_2_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @ComputeValue_2_build({ [0 x i256]*, i32 }* %0){{.*}} { //CHECK-NEXT: main: //CHECK-NEXT: %1 = alloca [2 x i256], align 8 //CHECK-NEXT: %2 = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 @@ -105,7 +105,7 @@ component main = ComputeValue(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @ComputeValue_2_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @ComputeValue_2_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [0 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [2 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/subcmps/conv_map2idx_C.circom b/circom/tests/subcmps/conv_map2idx_C.circom index bf78759b6..fa1451848 100644 --- a/circom/tests/subcmps/conv_map2idx_C.circom +++ b/circom/tests/subcmps/conv_map2idx_C.circom @@ -37,7 +37,7 @@ component main = EscalarMulFix(); //CHECK-NOT: ..generated..loop.body. // -//CHECK-LABEL: define void @EscalarMulFix_2_run([0 x i256]* %0) +//CHECK-LABEL: define{{.*}} void @EscalarMulFix_2_run([0 x i256]* %0) //CHECK: store i256 999 //CHECK: store i256 999 //CHECK: store i256 999 diff --git a/circom/tests/subcmps/large_array_param.circom b/circom/tests/subcmps/large_array_param.circom index 7ae353a95..e9d71a059 100644 --- a/circom/tests/subcmps/large_array_param.circom +++ b/circom/tests/subcmps/large_array_param.circom @@ -58,7 +58,7 @@ template Main(t) { component main = Main(2); -//CHECK-LABEL: define void @..generated..array.param. +//CHECK-LABEL: define{{.*}} void @..generated..array.param. //CHECK-SAME: [[$F_ID_1:[0-9]+]]([0 x i256]* %lvars){{.*}} { //CHECK-NEXT: ..generated..array.param.[[$F_ID_1]]: //CHECK-NEXT: br label %store1 @@ -88,9 +88,9 @@ component main = Main(2); //CHECK-NEXT: } // //There is only 1 produced, no duplicates -//CHECK-NOT: define void @..generated..array.param. +//CHECK-NOT: define{{.*}} void @..generated..array.param. // -//CHECK-LABEL: define void @Mixer_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @Mixer_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [8 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 @@ -123,7 +123,7 @@ component main = Main(2); //CHECK-EMPTY: //CHECK-NEXT: unrolled_loop6: // -//CHECK-LABEL: define void @Mixer_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @Mixer_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [8 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/subcmps/mapped.circom b/circom/tests/subcmps/mapped.circom index 8e16e7307..3506e3fef 100644 --- a/circom/tests/subcmps/mapped.circom +++ b/circom/tests/subcmps/mapped.circom @@ -40,7 +40,7 @@ template B(n) { component main = B(2); -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+]]: //CHECK-NEXT: br label %store1 @@ -70,7 +70,7 @@ component main = B(2); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_2:[0-9]+]]: //CHECK-NEXT: br label %store1 @@ -100,7 +100,7 @@ component main = B(2); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @A_0_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @A_0_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [2 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 @@ -148,7 +148,7 @@ component main = B(2); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @A_1_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @A_1_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [2 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 @@ -186,7 +186,7 @@ component main = B(2); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @B_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @B_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [2 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [2 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/subcmps/mapped2.circom b/circom/tests/subcmps/mapped2.circom index 0e1670a01..bda9b2a12 100644 --- a/circom/tests/subcmps/mapped2.circom +++ b/circom/tests/subcmps/mapped2.circom @@ -57,7 +57,7 @@ template B(n, m, j) { component main = B(2, 3, 2); -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0, i256* %fix_1){{.*}} { +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0, i256* %fix_1){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+]]: //CHECK-NEXT: br label %store1 //CHECK-EMPTY: @@ -84,7 +84,7 @@ component main = B(2, 3, 2); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0, i256* %fix_1){{.*}} { +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0, i256* %fix_1){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_2:[0-9]+]]: //CHECK-NEXT: br label %store1 //CHECK-EMPTY: @@ -111,7 +111,7 @@ component main = B(2, 3, 2); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @A_0_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @A_0_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [2 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 @@ -147,7 +147,7 @@ component main = B(2, 3, 2); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @A_1_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @A_1_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [2 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 @@ -187,7 +187,7 @@ component main = B(2, 3, 2); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @B_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @B_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [5 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [4 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/subcmps/mapped3.circom b/circom/tests/subcmps/mapped3.circom index e2957eaff..a19d26857 100644 --- a/circom/tests/subcmps/mapped3.circom +++ b/circom/tests/subcmps/mapped3.circom @@ -31,29 +31,29 @@ template Wrapper() { component main = Wrapper(); -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+]]: // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_2:[0-9]+]]: // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_3:[0-9]+]]: // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_4:[0-9]+]]: // -//CHECK-LABEL: define void @ArrayOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @ArrayOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { //CHECK-NEXT: main: //CHECK-NEXT: %[[SIGNALS:.*]] = alloca [30 x i256] //CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 //CHECK-NEXT: store i32 15, i32* %[[COUNTER]] // -//CHECK-LABEL: define void @ArrayOp_ +//CHECK-LABEL: define{{.*}} void @ArrayOp_ //CHECK-SAME: [[$RUN_1:[0-9]+]]_run([0 x i256]* %0){{.*}} { //CHECK: call void @..generated..loop.body.[[$F_ID_1]]( //CHECK: call void @..generated..loop.body.[[$F_ID_1]]( @@ -71,13 +71,13 @@ component main = Wrapper(); //CHECK: call void @..generated..loop.body.[[$F_ID_1]]( //CHECK: call void @..generated..loop.body.[[$F_ID_1]]( // -//CHECK-LABEL: define void @ArrayOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @ArrayOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { //CHECK-NEXT: main: //CHECK-NEXT: %[[SIGNALS:.*]] = alloca [30 x i256] //CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 //CHECK-NEXT: store i32 15, i32* %[[COUNTER]] -//CHECK-LABEL: define void @ArrayOp_ +//CHECK-LABEL: define{{.*}} void @ArrayOp_ //CHECK-SAME: [[$RUN_2:[0-9]+]]_run([0 x i256]* %0){{.*}} { //CHECK: call void @..generated..loop.body.[[$F_ID_2]]( //CHECK: call void @..generated..loop.body.[[$F_ID_2]]( @@ -95,13 +95,13 @@ component main = Wrapper(); //CHECK: call void @..generated..loop.body.[[$F_ID_2]]( //CHECK: call void @..generated..loop.body.[[$F_ID_2]]( // -//CHECK-LABEL: define void @ArrayOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @ArrayOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { //CHECK-NEXT: main: //CHECK-NEXT: %[[SIGNALS:.*]] = alloca [30 x i256] //CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 //CHECK-NEXT: store i32 15, i32* %[[COUNTER]] // -//CHECK-LABEL: define void @ArrayOp_ +//CHECK-LABEL: define{{.*}} void @ArrayOp_ //CHECK-SAME: [[$RUN_3:[0-9]+]]_run([0 x i256]* %0){{.*}} { //CHECK: call void @..generated..loop.body.[[$F_ID_3]]( //CHECK: call void @..generated..loop.body.[[$F_ID_3]]( @@ -119,13 +119,13 @@ component main = Wrapper(); //CHECK: call void @..generated..loop.body.[[$F_ID_3]]( //CHECK: call void @..generated..loop.body.[[$F_ID_3]]( // -//CHECK-LABEL: define void @ArrayOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @ArrayOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { //CHECK-NEXT: main: //CHECK-NEXT: %[[SIGNALS:.*]] = alloca [30 x i256] //CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 //CHECK-NEXT: store i32 15, i32* %[[COUNTER]] // -//CHECK-LABEL: define void @ArrayOp_ +//CHECK-LABEL: define{{.*}} void @ArrayOp_ //CHECK-SAME: [[$RUN_4:[0-9]+]]_run([0 x i256]* %0){{.*}} { //CHECK: call void @..generated..loop.body.[[$F_ID_4]]( //CHECK: call void @..generated..loop.body.[[$F_ID_4]]( @@ -143,13 +143,13 @@ component main = Wrapper(); //CHECK: call void @..generated..loop.body.[[$F_ID_4]]( //CHECK: call void @..generated..loop.body.[[$F_ID_4]]( // -//CHECK-LABEL: define void @Wrapper_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @Wrapper_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { //CHECK-NEXT: main: //CHECK-NEXT: %[[SIGNALS:.*]] = alloca [16 x i256] //CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 //CHECK-NEXT: store i32 15, i32* %{{.*}}[[COUNTER]] // -//CHECK-LABEL: define void @Wrapper_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @Wrapper_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK: %lvars = alloca [2 x i256] //CHECK: unrolled_loop{{[0-9]+}}: //CHECK: call void @ArrayOp_[[$RUN_1]]_run([0 x i256]* % diff --git a/circom/tests/subcmps/mapped4.circom b/circom/tests/subcmps/mapped4.circom index a0a771958..701df9b4b 100644 --- a/circom/tests/subcmps/mapped4.circom +++ b/circom/tests/subcmps/mapped4.circom @@ -35,93 +35,93 @@ template Wrapper() { component main = Wrapper(); -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_01:[0-9]+]]: // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_02:[0-9]+]]: // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_03:[0-9]+]]: // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_04:[0-9]+]]: // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_05:[0-9]+]]: // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_06:[0-9]+]]: // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_07:[0-9]+]]: // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_08:[0-9]+]]: // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_09:[0-9]+]]: // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_10:[0-9]+]]: // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_11:[0-9]+]]: // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_12:[0-9]+]]: // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_13:[0-9]+]]: // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_14:[0-9]+]]: // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_15:[0-9]+]]: // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_16:[0-9]+]]: // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_17:[0-9]+]]: // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_18:[0-9]+]]: // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_19:[0-9]+]]: // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_20:[0-9]+]]: // -//CHECK-LABEL: define void @MatrixOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @MatrixOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { //CHECK-NEXT: main: //CHECK-NEXT: %[[SIGNALS:.*]] = alloca [30 x i256] //CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 //CHECK-NEXT: store i32 15, i32* %[[COUNTER]] // -//CHECK-LABEL: define void @MatrixOp_ +//CHECK-LABEL: define{{.*}} void @MatrixOp_ //CHECK-SAME: [[$RUN_1:[0-9]+]]_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [3 x i256] @@ -142,13 +142,13 @@ component main = Wrapper(); //CHECK: call void @..generated..loop.body.[[$F_ID_05]]( //CHECK: call void @..generated..loop.body.[[$F_ID_05]]( // -//CHECK-LABEL: define void @MatrixOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @MatrixOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { //CHECK-NEXT: main: //CHECK-NEXT: %[[SIGNALS:.*]] = alloca [30 x i256] //CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 //CHECK-NEXT: store i32 15, i32* %[[COUNTER]] // -//CHECK-LABEL: define void @MatrixOp_ +//CHECK-LABEL: define{{.*}} void @MatrixOp_ //CHECK-SAME: [[$RUN_2:[0-9]+]]_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [3 x i256] @@ -169,13 +169,13 @@ component main = Wrapper(); //CHECK: call void @..generated..loop.body.[[$F_ID_10]]( //CHECK: call void @..generated..loop.body.[[$F_ID_10]]( // -//CHECK-LABEL: define void @MatrixOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @MatrixOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { //CHECK-NEXT: main: //CHECK-NEXT: %[[SIGNALS:.*]] = alloca [30 x i256] //CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 //CHECK-NEXT: store i32 15, i32* %[[COUNTER]] // -//CHECK-LABEL: define void @MatrixOp_ +//CHECK-LABEL: define{{.*}} void @MatrixOp_ //CHECK-SAME: [[$RUN_3:[0-9]+]]_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [3 x i256] @@ -196,13 +196,13 @@ component main = Wrapper(); //CHECK: call void @..generated..loop.body.[[$F_ID_15]]( //CHECK: call void @..generated..loop.body.[[$F_ID_15]]( // -//CHECK-LABEL: define void @MatrixOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @MatrixOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { //CHECK-NEXT: main: //CHECK-NEXT: %[[SIGNALS:.*]] = alloca [30 x i256] //CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 //CHECK-NEXT: store i32 15, i32* %[[COUNTER]] // -//CHECK-LABEL: define void @MatrixOp_ +//CHECK-LABEL: define{{.*}} void @MatrixOp_ //CHECK-SAME: [[$RUN_4:[0-9]+]]_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [3 x i256] @@ -223,13 +223,13 @@ component main = Wrapper(); //CHECK: call void @..generated..loop.body.[[$F_ID_20]]( //CHECK: call void @..generated..loop.body.[[$F_ID_20]]( // -//CHECK-LABEL: define void @Wrapper_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @Wrapper_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { //CHECK-NEXT: main: //CHECK-NEXT: %[[SIGNALS:.*]] = alloca [16 x i256] //CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 //CHECK-NEXT: store i32 15, i32* %{{.*}}[[COUNTER]] // -//CHECK-LABEL: define void @Wrapper_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @Wrapper_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK: %lvars = alloca [3 x i256] //CHECK: unrolled_loop{{[0-9]+}}: //CHECK: call void @MatrixOp_[[$RUN_1]]_run([0 x i256]* % diff --git a/circom/tests/subcmps/subcmps0A.circom b/circom/tests/subcmps/subcmps0A.circom index 85b66d0e2..f36970423 100644 --- a/circom/tests/subcmps/subcmps0A.circom +++ b/circom/tests/subcmps/subcmps0A.circom @@ -24,7 +24,7 @@ template SubCmps0A(n) { component main = SubCmps0A(2); -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %subfix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]], //CHECK-SAME: i256* %subfix_[[X4:[0-9]+]], [0 x i256]* %sub_[[X4]], i256* %subc_[[X4]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+\.T]]: @@ -67,7 +67,7 @@ component main = SubCmps0A(2); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @IsZero_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @IsZero_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [0 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 @@ -85,7 +85,7 @@ component main = SubCmps0A(2); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @SubCmps0A_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @SubCmps0A_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [2 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [2 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/subcmps/subcmps0B.circom b/circom/tests/subcmps/subcmps0B.circom index dde20729a..1dbd4301e 100644 --- a/circom/tests/subcmps/subcmps0B.circom +++ b/circom/tests/subcmps/subcmps0B.circom @@ -25,7 +25,7 @@ template SubCmps0B(n) { component main = SubCmps0B(2); -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %subfix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]], i256* %subfix_[[X4:[0-9]+]], //CHECK-SAME: i256* %subfix_[[X5:[0-9]+]], [0 x i256]* %sub_[[X5]], i256* %subc_[[X5]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+\.T]]: @@ -75,7 +75,7 @@ component main = SubCmps0B(2); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @IsZero_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @IsZero_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [0 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 @@ -93,7 +93,7 @@ component main = SubCmps0B(2); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @SubCmps0B_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @SubCmps0B_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [3 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [2 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/subcmps/subcmps0C.circom b/circom/tests/subcmps/subcmps0C.circom index 18fdacac1..e15ae65e2 100644 --- a/circom/tests/subcmps/subcmps0C.circom +++ b/circom/tests/subcmps/subcmps0C.circom @@ -23,7 +23,7 @@ template SubCmps0C(n) { component main = SubCmps0C(2); -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %subfix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]], //CHECK-SAME: i256* %subfix_[[X4:[0-9]+]], [0 x i256]* %sub_[[X4]], i256* %subc_[[X4]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+\.T]]: @@ -66,7 +66,7 @@ component main = SubCmps0C(2); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @IsZero_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @IsZero_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [0 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 @@ -94,7 +94,7 @@ component main = SubCmps0C(2); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @SubCmps0C_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @SubCmps0C_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [2 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [2 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/subcmps/subcmps0D.circom b/circom/tests/subcmps/subcmps0D.circom index 89d898aea..60446eb70 100644 --- a/circom/tests/subcmps/subcmps0D.circom +++ b/circom/tests/subcmps/subcmps0D.circom @@ -24,7 +24,7 @@ template SubCmps0D(n) { component main = SubCmps0D(3); -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.F\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+\.F\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %subfix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %subfix_[[X3:[0-9]+]], i256* %fix_[[X4:[0-9]+]], //CHECK-SAME: i256* %fix_[[X5:[0-9]+]], i256* %subfix_[[X6:[0-9]+]], [0 x i256]* %sub_[[X6]], i256* %subc_[[X6]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+\.F\.T]]: @@ -84,7 +84,7 @@ component main = SubCmps0D(3); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @Add_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @Add_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [0 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 @@ -104,7 +104,7 @@ component main = SubCmps0D(3); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @SubCmps0D_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @SubCmps0D_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [2 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [3 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/subcmps/subcmps1.circom b/circom/tests/subcmps/subcmps1.circom index 7945748b8..b9e28e8bf 100644 --- a/circom/tests/subcmps/subcmps1.circom +++ b/circom/tests/subcmps/subcmps1.circom @@ -34,7 +34,7 @@ component main = SubCmps1(3); // %lvars = [ n, i ] // %subcmps = [ IsZero[0]{signals=[out,in,inv]}, IsZero[1]{SAME} ] // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %subfix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]], //CHECK-SAME: i256* %subfix_[[X4:[0-9]+]], [0 x i256]* %sub_[[X4]], i256* %subc_[[X4]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID:[0-9]+\.T]]: @@ -83,7 +83,7 @@ component main = SubCmps1(3); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @SubCmps1_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @SubCmps1_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK: unrolled_loop5: //CHECK-NEXT: %[[T07:[0-9]+]] = bitcast [2 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %[[T08:[0-9]+]] = getelementptr [3 x { [0 x i256]*, i32 }], [3 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 0, i32 0 diff --git a/circom/tests/subcmps/subcmps2.circom b/circom/tests/subcmps/subcmps2.circom index 22fa83ff8..b6c6fb800 100644 --- a/circom/tests/subcmps/subcmps2.circom +++ b/circom/tests/subcmps/subcmps2.circom @@ -34,7 +34,7 @@ template Caller() { component main = Caller(); -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+]]: //CHECK-NEXT: br label %store1 @@ -61,7 +61,7 @@ component main = Caller(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.F}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+\.F}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %subfix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], [0 x i256]* %sub_[[X3:[0-9]+]], i256* %subc_[[X4:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_2:[0-9]+\.F]]: //CHECK-NEXT: br label %call1 @@ -103,7 +103,7 @@ component main = Caller(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %subfix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], [0 x i256]* %sub_[[X3:[0-9]+]], i256* %subc_[[X4:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_3:[0-9]+\.T]]: //CHECK-NEXT: br label %call1 @@ -146,7 +146,7 @@ component main = Caller(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @Sum_0_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @Sum_0_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [3 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 @@ -196,7 +196,7 @@ component main = Caller(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @Caller_1_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @Caller_1_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [1 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [1 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/subcmps/subcmps3.circom b/circom/tests/subcmps/subcmps3.circom index 63eac590b..ef16fa6e9 100644 --- a/circom/tests/subcmps/subcmps3.circom +++ b/circom/tests/subcmps/subcmps3.circom @@ -1,6 +1,7 @@ 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 --enable-var-scope +// XFAIL: .* // pending https://veridise.atlassian.net/browse/VAN-798 template Sum(n) { signal input inp[n]; @@ -31,7 +32,7 @@ template SubCmps3() { component main = SubCmps3(); -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+]]: //CHECK-NEXT: br label %store1 @@ -58,7 +59,7 @@ component main = SubCmps3(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.F}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+\.F}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_2:[0-9]+\.F]]: //CHECK-NEXT: br label %store1 @@ -88,7 +89,7 @@ component main = SubCmps3(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @..generated..loop.body.{{[0-9]+\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+\.T}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_3:[0-9]+\.T]]: //CHECK-NEXT: br label %store1 @@ -125,7 +126,7 @@ component main = SubCmps3(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @Sum_0_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @Sum_0_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [3 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }], align 8 @@ -175,7 +176,7 @@ component main = SubCmps3(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define void @SubCmps3_1_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @SubCmps3_1_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [1 x i256], align 8 //CHECK-NEXT: %subcmps = alloca [1 x { [0 x i256]*, i32 }], align 8 diff --git a/circom/tests/type_conversions/bool_1.circom b/circom/tests/type_conversions/bool_1.circom index 9225add4a..9e9ad51c8 100644 --- a/circom/tests/type_conversions/bool_1.circom +++ b/circom/tests/type_conversions/bool_1.circom @@ -15,7 +15,7 @@ template A(x) { component main = A(5); -//CHECK-LABEL: define i256 @binop_comp_{{[0-9]+}} +//CHECK-LABEL: define{{.*}} i256 @binop_comp_{{[0-9]+}} //CHECK-SAME: (i256* %0) //CHECK: %call.fr_gt = call i1 @fr_gt(i256 %{{[0-9]+}}, i256 %{{[0-9]+}}) //CHECK: %[[RET:[0-9]+]] = zext i1 %call.fr_gt to i256 diff --git a/circom/tests/type_conversions/bool_2.circom b/circom/tests/type_conversions/bool_2.circom index 3836e98f0..79397cf23 100644 --- a/circom/tests/type_conversions/bool_2.circom +++ b/circom/tests/type_conversions/bool_2.circom @@ -24,7 +24,7 @@ template A(x) { component main = A(555); -//CHECK-LABEL: define i256 @binop_bool_{{[0-9]+}} +//CHECK-LABEL: define{{.*}} i256 @binop_bool_{{[0-9]+}} //CHECK-SAME: (i256* %0) //CHECK: %call.fr_logic_or = call i1 @fr_logic_or(i1 %{{[0-9]+}}, i1 %{{[0-9]+}}) //CHECK: %[[RET:[0-9]+]] = zext i1 %call.fr_logic_or to i256 diff --git a/circom/tests/type_conversions/bool_3.circom b/circom/tests/type_conversions/bool_3.circom index d3f2103e7..6a351867c 100644 --- a/circom/tests/type_conversions/bool_3.circom +++ b/circom/tests/type_conversions/bool_3.circom @@ -15,7 +15,7 @@ template A(x) { component main = A(99); -//CHECK-LABEL: define void @A_{{[0-9]+}}_run +//CHECK-LABEL: define{{.*}} void @A_{{[0-9]+}}_run //CHECK-SAME: ([0 x i256]* %0) //CHECK: branch{{[0-9]+}}: //CHECK: %[[VAL_PTR:[0-9]+]] = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 1 diff --git a/circom/tests/type_conversions/bool_4.circom b/circom/tests/type_conversions/bool_4.circom index aadcd3cf3..f0f62637b 100644 --- a/circom/tests/type_conversions/bool_4.circom +++ b/circom/tests/type_conversions/bool_4.circom @@ -20,7 +20,7 @@ template A() { component main = A(); -//CHECK-LABEL: define void @binop_bool_array_{{[0-9]+}} +//CHECK-LABEL: define{{.*}} void @binop_bool_array_{{[0-9]+}} //CHECK-SAME: (i256* %0) //CHECK: %call.fr_logic_or = call i1 @fr_logic_or(i1 %{{[0-9]+}}, i1 %{{[0-9]+}}) //CHECK: %[[VAL:[0-9]+]] = zext i1 %call.fr_logic_or to i256 diff --git a/circom/tests/zzz/unreachable_code_crash.circom b/circom/tests/zzz/unreachable_code_crash.circom index 2bcc5f528..e13b49161 100644 --- a/circom/tests/zzz/unreachable_code_crash.circom +++ b/circom/tests/zzz/unreachable_code_crash.circom @@ -34,10 +34,10 @@ component main = InvalidArgIndex(3, 2); //// Check that only the proper versions of the generated functions remain //// (i.e. the initial one was removed after conditional flattening). // -//CHECK-NOT: define void @..generated..loop.body.{{[0-9]+}}( -//CHECK: define void @..generated..loop.body.[[NAME_1:[0-9]+]].F( -//CHECK-NOT: define void @..generated..loop.body.{{[0-9]+}}( -//CHECK: define void @..generated..loop.body.[[NAME_1]].T( -//CHECK-NOT: define void @..generated..loop.body.{{[0-9]+}}( -//CHECK: define void @..generated..loop.body.[[NAME_2:[0-9]+]].F.T( -//CHECK-NOT: define void @..generated..loop.body.{{[0-9]+}}( +//CHECK-NOT: define{{.*}} void @..generated..loop.body.{{[0-9]+}}( +//CHECK: define{{.*}} void @..generated..loop.body.[[NAME_1:[0-9]+]].F( +//CHECK-NOT: define{{.*}} void @..generated..loop.body.{{[0-9]+}}( +//CHECK: define{{.*}} void @..generated..loop.body.[[NAME_1]].T( +//CHECK-NOT: define{{.*}} void @..generated..loop.body.{{[0-9]+}}( +//CHECK: define{{.*}} void @..generated..loop.body.[[NAME_2:[0-9]+]].F.T( +//CHECK-NOT: define{{.*}} void @..generated..loop.body.{{[0-9]+}}( diff --git a/code_producers/src/llvm_elements/functions.rs b/code_producers/src/llvm_elements/functions.rs index 5ab27bd50..cba13a9e1 100644 --- a/code_producers/src/llvm_elements/functions.rs +++ b/code_producers/src/llvm_elements/functions.rs @@ -19,6 +19,7 @@ pub fn create_function<'a>( ) -> FunctionValue<'a> { let llvm = producer.llvm(); let f = llvm.module.add_function(name, ty, None); + f.set_linkage(inkwell::module::Linkage::Internal); //default to Internal, allows removal if unused if let Some(file_id) = source_file_id { match llvm.get_debug_info(&file_id) { Err(msg) => panic!("{}", msg), @@ -131,6 +132,10 @@ impl<'ctx, 'prod> LLVMIRProducer<'ctx> for FunctionLLVMIRProducer<'ctx, 'prod> { fn get_template_mem_arg(&self, _run_fn: FunctionValue<'ctx>) -> ArrayValue<'ctx> { panic!("The function llvm producer can't extract the template argument of a run function!"); } + + fn get_main_template_header(&self) -> &String { + self.parent.get_main_template_header() + } } struct ExtractedFunctionCtx<'a> { @@ -296,4 +301,8 @@ impl<'ctx, 'prod> LLVMIRProducer<'ctx> for ExtractedFunctionLLVMIRProducer<'ctx, fn get_template_mem_arg(&self, _run_fn: FunctionValue<'ctx>) -> ArrayValue<'ctx> { panic!("The function llvm producer can't extract the template argument of a run function!"); } + + fn get_main_template_header(&self) -> &String { + self.parent.get_main_template_header() + } } diff --git a/code_producers/src/llvm_elements/mod.rs b/code_producers/src/llvm_elements/mod.rs index ac5081851..bdfce2367 100644 --- a/code_producers/src/llvm_elements/mod.rs +++ b/code_producers/src/llvm_elements/mod.rs @@ -17,6 +17,7 @@ use inkwell::values::{ArrayValue, BasicMetadataValueEnum, BasicValueEnum, IntVal pub use inkwell::types::AnyType; pub use inkwell::values::{AnyValue, AnyValueEnum, FunctionValue, InstructionOpcode}; pub use inkwell::debug_info::AsDIScope; +pub use inkwell::module::Linkage; use program_structure::program_archive::ProgramArchive; @@ -98,12 +99,14 @@ pub trait LLVMIRProducer<'a> { fn builder(&self) -> &Builder<'a>; fn constant_fields(&self) -> &Vec; fn get_template_mem_arg(&self, run_fn: FunctionValue<'a>) -> ArrayValue<'a>; + fn get_main_template_header(&self) -> &String; } pub type IndexMapping = HashMap>; #[derive(Default, Eq, PartialEq, Debug)] pub struct LLVMCircuitData { + pub main_header: String, pub field_tracking: Vec, pub io_map: TemplateInstanceIOMap, pub signal_index_mapping: HashMap, @@ -116,6 +119,7 @@ pub struct LLVMCircuitData { impl LLVMCircuitData { pub fn clone_with_updates(&self, field_tracking: Vec, array_loads: HashSet>, array_stores: HashSet>) -> Self { LLVMCircuitData { + main_header: self.main_header.clone(), field_tracking, io_map: self.io_map.clone(), signal_index_mapping: self.signal_index_mapping.clone(), @@ -131,6 +135,7 @@ pub struct TopLevelLLVMIRProducer<'a> { pub context: &'a Context, current_module: LLVM<'a>, pub field_tracking: Vec, + main_template_header: String, } impl<'a> LLVMIRProducer<'a> for TopLevelLLVMIRProducer<'a> { @@ -171,6 +176,10 @@ impl<'a> LLVMIRProducer<'a> for TopLevelLLVMIRProducer<'a> { "The top level llvm producer can't extract the template argument of a run function!" ); } + + fn get_main_template_header(&self) -> &String { + &self.main_template_header + } } impl<'a> TopLevelLLVMIRProducer<'a> { @@ -189,11 +198,13 @@ impl<'a> TopLevelLLVMIRProducer<'a> { program_archive: &ProgramArchive, llvm_path: &str, field_tracking: Vec, + main_template_header: String, ) -> Self { TopLevelLLVMIRProducer { context, current_module: LLVM::from_context(context, program_archive, llvm_path), field_tracking, + main_template_header, } } } @@ -340,6 +351,7 @@ impl<'a> LLVM<'a> { // Run LLVM IR inliner for the FR_IDENTITY_* and FR_INDEX_ARR_PTR functions let pm = PassManager::create(()); pm.add_always_inliner_pass(); + pm.add_global_dce_pass(); pm.run_on(&self.module); // Must finalize all debug info before running the verifier diff --git a/code_producers/src/llvm_elements/stdlib.rs b/code_producers/src/llvm_elements/stdlib.rs index b6fba2a9d..ab92d5233 100644 --- a/code_producers/src/llvm_elements/stdlib.rs +++ b/code_producers/src/llvm_elements/stdlib.rs @@ -104,7 +104,15 @@ mod stdlib { } pub fn abort_declared_fn<'a>(producer: &dyn LLVMIRProducer<'a>) { - create_function(producer, &None, 0, "", "__abort", void_type(producer).fn_type(&[], false)); + let f = create_function( + producer, + &None, + 0, + "", + "__abort", + void_type(producer).fn_type(&[], false), + ); + f.set_linkage(inkwell::module::Linkage::External); } } diff --git a/code_producers/src/llvm_elements/template.rs b/code_producers/src/llvm_elements/template.rs index 66924c435..c4482064d 100644 --- a/code_producers/src/llvm_elements/template.rs +++ b/code_producers/src/llvm_elements/template.rs @@ -182,6 +182,10 @@ impl<'a, 'b> LLVMIRProducer<'a> for TemplateLLVMIRProducer<'a, 'b> { fn get_template_mem_arg(&self, run_fn: FunctionValue<'a>) -> ArrayValue<'a> { run_fn.get_nth_param(self.ctx.signals_arg_offset as u32).unwrap().into_array_value() } + + fn get_main_template_header(&self) -> &String { + self.parent.get_main_template_header() + } } impl<'a, 'b> TemplateLLVMIRProducer<'a, 'b> { diff --git a/compiler/src/circuit_design/build.rs b/compiler/src/circuit_design/build.rs index 9175119c8..6db57b60e 100644 --- a/compiler/src/circuit_design/build.rs +++ b/compiler/src/circuit_design/build.rs @@ -273,7 +273,7 @@ fn initialize_c_producer(vcp: &VCP, database: &TemplateDB, version: &str) -> CPr fn initialize_llvm_data(vcp: &VCP, database: &TemplateDB) -> LLVMCircuitData { let mut producer = LLVMCircuitData::default(); - + producer.main_header = vcp.get_main_instance().unwrap().template_header.clone(); producer.io_map = build_io_map(vcp, database); producer } diff --git a/compiler/src/circuit_design/template.rs b/compiler/src/circuit_design/template.rs index 8feb335d1..0950742b3 100644 --- a/compiler/src/circuit_design/template.rs +++ b/compiler/src/circuit_design/template.rs @@ -3,9 +3,14 @@ use crate::intermediate_representation::ir_interface::ObtainMeta; use crate::translating_traits::*; use code_producers::c_elements::*; use std::default::Default; -use code_producers::llvm_elements::{AnyType, AnyValue, build_fn_name, LLVMInstruction, LLVMIRProducer, run_fn_name, to_basic_type_enum}; +use code_producers::llvm_elements::{ + AnyType, AnyValue, build_fn_name, LLVMInstruction, LLVMIRProducer, run_fn_name, + to_basic_type_enum, Linkage, +}; use code_producers::llvm_elements::functions::{create_bb, create_function}; -use code_producers::llvm_elements::instructions::{create_alloca, create_br, create_gep, create_return_void, create_store, pointer_cast}; +use code_producers::llvm_elements::instructions::{ + create_alloca, create_br, create_gep, create_return_void, create_store, pointer_cast, +}; use code_producers::llvm_elements::template::{create_template_struct, TemplateLLVMIRProducer}; use code_producers::llvm_elements::types::{bigint_type, i32_type, void_type}; use code_producers::llvm_elements::values::{create_literal_u32, zero}; @@ -138,8 +143,12 @@ impl WriteLLVMIR for TemplateCodeInfo { let prologue = create_bb(producer, run_function, "prologue"); create_br(producer, prologue); producer.set_current_bb(prologue); - let ret = create_return_void(producer); + + if self.header.eq(producer.get_main_template_header()) { + run_function.set_linkage(Linkage::External); + build_function.set_linkage(Linkage::External); + } Some(ret) } } diff --git a/compiler/src/translating_traits/mod.rs b/compiler/src/translating_traits/mod.rs index 3ced74a87..4986fa014 100644 --- a/compiler/src/translating_traits/mod.rs +++ b/compiler/src/translating_traits/mod.rs @@ -50,6 +50,7 @@ pub trait WriteLLVMIR { program_archive, out_path, data.field_tracking.clone(), + data.main_header.clone(), ); self.produce_llvm_ir(&top_level); top_level.write_to_file(out_path) From 890e7fc04c4adcf57717907da7668fcd47b5e3be Mon Sep 17 00:00:00 2001 From: Timothy Hoffman <4001421+tim-hoffman@users.noreply.github.com> Date: Tue, 31 Oct 2023 14:31:10 -0500 Subject: [PATCH 8/9] [VAN-717] use LLVM pass to merge identical functions (#66) prevent "build" and "run" functions from different templates from merging but all others are open to merging --- circom/tests/loops/assign_in_loop_2.circom | 4 - circom/tests/loops/assign_in_loop_3.circom | 4 - circom/tests/loops/inner_conditional_2.circom | 2 +- circom/tests/loops/inner_conditional_7.circom | 31 +- circom/tests/loops/inner_loop_simple.circom | 35 +- circom/tests/loops/inner_loops6.circom | 28 +- circom/tests/subcmps/conv_map2idx_A.circom | 13 +- circom/tests/subcmps/conv_map2idx_B.circom | 13 +- circom/tests/subcmps/mapped.circom | 38 +- circom/tests/subcmps/mapped2.circom | 37 +- circom/tests/subcmps/mapped3.circom | 18 - circom/tests/subcmps/mapped4.circom | 196 ++-- circom/tests/zzz/poseidon.circom | 958 ++++++++++++++++++ code_producers/src/llvm_elements/mod.rs | 8 +- compiler/src/circuit_design/template.rs | 6 + 15 files changed, 1052 insertions(+), 339 deletions(-) create mode 100644 circom/tests/zzz/poseidon.circom diff --git a/circom/tests/loops/assign_in_loop_2.circom b/circom/tests/loops/assign_in_loop_2.circom index 2a22110fe..f5a87d4da 100644 --- a/circom/tests/loops/assign_in_loop_2.circom +++ b/circom/tests/loops/assign_in_loop_2.circom @@ -29,13 +29,9 @@ component main = Num2Bits(3); //CHECK-LABEL: define{{.*}} void @Inner_ //CHECK-SAME: [[$RUN_1:[0-9]+]]_run([0 x i256]* %0){{.*}} { // -//CHECK-LABEL: define{{.*}} void @Inner_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { -// //CHECK-LABEL: define{{.*}} void @Inner_ //CHECK-SAME: [[$RUN_2:[0-9]+]]_run([0 x i256]* %0){{.*}} { // -//CHECK-LABEL: define{{.*}} void @Inner_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { -// //CHECK-LABEL: define{{.*}} void @Inner_ //CHECK-SAME: [[$RUN_3:[0-9]+]]_run([0 x i256]* %0){{.*}} { // diff --git a/circom/tests/loops/assign_in_loop_3.circom b/circom/tests/loops/assign_in_loop_3.circom index 64f1aca39..89c7e5563 100644 --- a/circom/tests/loops/assign_in_loop_3.circom +++ b/circom/tests/loops/assign_in_loop_3.circom @@ -29,13 +29,9 @@ component main = Num2Bits(3); //CHECK-LABEL: define{{.*}} void @Inner_ //CHECK-SAME: [[$RUN_1:[0-9]+]]_run([0 x i256]* %0){{.*}} { // -//CHECK-LABEL: define{{.*}} void @Inner_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { -// //CHECK-LABEL: define{{.*}} void @Inner_ //CHECK-SAME: [[$RUN_2:[0-9]+]]_run([0 x i256]* %0){{.*}} { // -//CHECK-LABEL: define{{.*}} void @Inner_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { -// //CHECK-LABEL: define{{.*}} void @Inner_ //CHECK-SAME: [[$RUN_3:[0-9]+]]_run([0 x i256]* %0){{.*}} { // diff --git a/circom/tests/loops/inner_conditional_2.circom b/circom/tests/loops/inner_conditional_2.circom index b891ed045..2a172831d 100644 --- a/circom/tests/loops/inner_conditional_2.circom +++ b/circom/tests/loops/inner_conditional_2.circom @@ -193,7 +193,7 @@ component main = runner(); //CHECK-EMPTY: //CHECK-NEXT: create_cmp2: //CHECK-NEXT: %4 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1 -//CHECK-NEXT: call void @InnerConditional2_1_build({ [0 x i256]*, i32 }* %4) +//CHECK-NEXT: call void @InnerConditional2_0_build({ [0 x i256]*, i32 }* %4) //CHECK-NEXT: %5 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 0 //CHECK-NEXT: %6 = load [0 x i256]*, [0 x i256]** %5, align 8 //CHECK-NEXT: call void @InnerConditional2_1_run([0 x i256]* %6) diff --git a/circom/tests/loops/inner_conditional_7.circom b/circom/tests/loops/inner_conditional_7.circom index cbd9a6773..537782852 100644 --- a/circom/tests/loops/inner_conditional_7.circom +++ b/circom/tests/loops/inner_conditional_7.circom @@ -53,31 +53,6 @@ component main = InnerConditional7(3); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}.F([0 x i256]* %lvars, [0 x i256]* %signals, -//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_2:[0-9]+\.F]]: -//CHECK-NEXT: br label %fold_false1 -//CHECK-EMPTY: -//CHECK-NEXT: fold_false1: -//CHECK-NEXT: %0 = getelementptr i256, i256* %fix_[[X2]], i32 0 -//CHECK-NEXT: %1 = load i256, i256* %0, align 4 -//CHECK-NEXT: %call.fr_sub = call i256 @fr_sub(i256 %1, i256 111) -//CHECK-NEXT: %2 = getelementptr i256, i256* %fix_[[X1]], i32 0 -//CHECK-NEXT: store i256 %call.fr_sub, i256* %2, align 4 -//CHECK-NEXT: br label %store2 -//CHECK-EMPTY: -//CHECK-NEXT: store2: -//CHECK-NEXT: %3 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 -//CHECK-NEXT: %4 = load i256, i256* %3, align 4 -//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %4, i256 1) -//CHECK-NEXT: %5 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 -//CHECK-NEXT: store i256 %call.fr_add, i256* %5, align 4 -//CHECK-NEXT: br label %return3 -//CHECK-EMPTY: -//CHECK-NEXT: return3: -//CHECK-NEXT: ret void -//CHECK-NEXT: } -// //CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}.T([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_3:[0-9]+\.T]]: @@ -161,19 +136,19 @@ component main = InnerConditional7(3); //CHECK-NEXT: %26 = getelementptr [0 x i256], [0 x i256]* %25, i32 0, i256 1 //CHECK-NEXT: %27 = bitcast [6 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %28 = getelementptr [0 x i256], [0 x i256]* %27, i32 0, i256 1 -//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %24, [0 x i256]* %0, i256* %26, i256* %28) +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %24, [0 x i256]* %0, i256* %26, i256* %28) //CHECK-NEXT: %29 = bitcast [6 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %30 = bitcast [6 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %31 = getelementptr [0 x i256], [0 x i256]* %30, i32 0, i256 2 //CHECK-NEXT: %32 = bitcast [6 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %33 = getelementptr [0 x i256], [0 x i256]* %32, i32 0, i256 2 -//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %29, [0 x i256]* %0, i256* %31, i256* %33) +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %29, [0 x i256]* %0, i256* %31, i256* %33) //CHECK-NEXT: %34 = bitcast [6 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %35 = bitcast [6 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %36 = getelementptr [0 x i256], [0 x i256]* %35, i32 0, i256 3 //CHECK-NEXT: %37 = bitcast [6 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %38 = getelementptr [0 x i256], [0 x i256]* %37, i32 0, i256 3 -//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %34, [0 x i256]* %0, i256* %36, i256* %38) +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %34, [0 x i256]* %0, i256* %36, i256* %38) //CHECK-NEXT: %39 = getelementptr [6 x i256], [6 x i256]* %lvars, i32 0, i32 4 //CHECK-NEXT: store i256 2, i256* %39, align 4 //CHECK-NEXT: %40 = getelementptr [6 x i256], [6 x i256]* %lvars, i32 0, i32 5 diff --git a/circom/tests/loops/inner_loop_simple.circom b/circom/tests/loops/inner_loop_simple.circom index ed2d9b238..f72c0f9fb 100644 --- a/circom/tests/loops/inner_loop_simple.circom +++ b/circom/tests/loops/inner_loop_simple.circom @@ -49,35 +49,6 @@ component main = InnerLoops(2, 3); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define{{.*}} void @..generated..loop.body. -//CHECK-SAME: [[$F_ID_2:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_2]]: -//CHECK-NEXT: br label %store{{[0-9]+}} -//CHECK-EMPTY: -//CHECK-NEXT: store{{[0-9]+}}: -//CHECK-NEXT: %0 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 4 -//CHECK-NEXT: %1 = load i256, i256* %0, align 4 -//CHECK-NEXT: %call.fr_cast_to_addr = call i32 @fr_cast_to_addr(i256 %1) -//CHECK-NEXT: %mul_addr = mul i32 1, %call.fr_cast_to_addr -//CHECK-NEXT: %add_addr = add i32 %mul_addr, 2 -//CHECK-NEXT: %2 = getelementptr i256, i256* %fix_0, i32 0 -//CHECK-NEXT: %3 = load i256, i256* %2, align 4 -//CHECK-NEXT: %4 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 %add_addr -//CHECK-NEXT: store i256 %3, i256* %4, align 4 -//CHECK-NEXT: br label %store{{[0-9]+}} -//CHECK-EMPTY: -//CHECK-NEXT: store{{[0-9]+}}: -//CHECK-NEXT: %5 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 -//CHECK-NEXT: %6 = load i256, i256* %5, align 4 -//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %6, i256 1) -//CHECK-NEXT: %7 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 5 -//CHECK-NEXT: store i256 %call.fr_add, i256* %7, align 4 -//CHECK-NEXT: br label %return{{[0-9]+}} -//CHECK-EMPTY: -//CHECK-NEXT: return{{[0-9]+}}: -//CHECK-NEXT: ret void -//CHECK-NEXT: } -// //CHECK-LABEL: define{{.*}} void @InnerLoops_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK: unrolled_loop{{[0-9]+}}: //CHECK-NEXT: %6 = getelementptr [6 x i256], [6 x i256]* %lvars, i32 0, i32 5 @@ -97,13 +68,13 @@ component main = InnerLoops(2, 3); //CHECK-NEXT: store i256 0, i256* %14, align 4 //CHECK-NEXT: %15 = bitcast [6 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %16 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 1 -//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %15, [0 x i256]* %0, i256* %16) +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %15, [0 x i256]* %0, i256* %16) //CHECK-NEXT: %17 = bitcast [6 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %18 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 2 -//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %17, [0 x i256]* %0, i256* %18) +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %17, [0 x i256]* %0, i256* %18) //CHECK-NEXT: %19 = bitcast [6 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %20 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 3 -//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %19, [0 x i256]* %0, i256* %20) +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %19, [0 x i256]* %0, i256* %20) //CHECK-NEXT: %21 = getelementptr [6 x i256], [6 x i256]* %lvars, i32 0, i32 4 //CHECK-NEXT: store i256 2, i256* %21, align 4 //CHECK-NEXT: br label %store{{[0-9]+}} diff --git a/circom/tests/loops/inner_loops6.circom b/circom/tests/loops/inner_loops6.circom index f9d015158..50ed8e333 100644 --- a/circom/tests/loops/inner_loops6.circom +++ b/circom/tests/loops/inner_loops6.circom @@ -58,30 +58,6 @@ component main = Num2Bits(2); //CHECK-NEXT: return{{[0-9]+}}: //CHECK-NEXT: ret void //CHECK-NEXT: } -// -//CHECK-LABEL: define{{.*}} void @..generated..loop.body. -//CHECK-SAME: [[$F_ID_2:[0-9]+]]([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_2]]: -//CHECK-NEXT: br label %store{{[0-9]+}} -//CHECK-EMPTY: -//CHECK-NEXT: store{{[0-9]+}}: -//CHECK-NEXT: %0 = getelementptr [0 x i256], [0 x i256]* %signals, i32 0, i32 4 -//CHECK-NEXT: %1 = load i256, i256* %0, align 4 -//CHECK-NEXT: %2 = getelementptr i256, i256* %fix_0, i32 0 -//CHECK-NEXT: store i256 %1, i256* %2, align 4 -//CHECK-NEXT: br label %store{{[0-9]+}} -//CHECK-EMPTY: -//CHECK-NEXT: store{{[0-9]+}}: -//CHECK-NEXT: %3 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 2 -//CHECK-NEXT: %4 = load i256, i256* %3, align 4 -//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %4, i256 1) -//CHECK-NEXT: %5 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 2 -//CHECK-NEXT: store i256 %call.fr_add, i256* %5, align 4 -//CHECK-NEXT: br label %return{{[0-9]+}} -//CHECK-EMPTY: -//CHECK-NEXT: return{{[0-9]+}}: -//CHECK-NEXT: ret void -//CHECK-NEXT: } // //CHECK-LABEL: define{{.*}} void @Num2Bits_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { //CHECK: unrolled_loop{{[0-9]+}}: @@ -99,10 +75,10 @@ component main = Num2Bits(2); //CHECK-NEXT: store i256 0, i256* %9, align 4 //CHECK-NEXT: %10 = bitcast [3 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %11 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 2 -//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %10, [0 x i256]* %0, i256* %11) +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %10, [0 x i256]* %0, i256* %11) //CHECK-NEXT: %12 = bitcast [3 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %13 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 3 -//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %12, [0 x i256]* %0, i256* %13) +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %12, [0 x i256]* %0, i256* %13) //CHECK-NEXT: %14 = getelementptr [3 x i256], [3 x i256]* %lvars, i32 0, i32 1 //CHECK-NEXT: store i256 2, i256* %14, align 4 //CHECK-NEXT: br label %prologue diff --git a/circom/tests/subcmps/conv_map2idx_A.circom b/circom/tests/subcmps/conv_map2idx_A.circom index 9d9b5230a..599094908 100644 --- a/circom/tests/subcmps/conv_map2idx_A.circom +++ b/circom/tests/subcmps/conv_map2idx_A.circom @@ -45,17 +45,6 @@ component main = ComputeValue(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define{{.*}} void @GetWeight_1_build({ [0 x i256]*, i32 }* %0){{.*}} { -//CHECK-NEXT: main: -//CHECK-NEXT: %1 = alloca [1 x i256], align 8 -//CHECK-NEXT: %2 = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 -//CHECK-NEXT: store i32 1, i32* %2, align 4 -//CHECK-NEXT: %3 = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 0 -//CHECK-NEXT: %4 = bitcast [1 x i256]* %1 to [0 x i256]* -//CHECK-NEXT: store [0 x i256]* %4, [0 x i256]** %3, align 8 -//CHECK-NEXT: ret void -//CHECK-NEXT: } -// //CHECK-LABEL: define{{.*}} void @GetWeight_1_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [1 x i256], align 8 @@ -94,7 +83,7 @@ component main = ComputeValue(); //CHECK-EMPTY: //CHECK-NEXT: create_cmp2: //CHECK-NEXT: %2 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1 -//CHECK-NEXT: call void @GetWeight_1_build({ [0 x i256]*, i32 }* %2) +//CHECK-NEXT: call void @GetWeight_0_build({ [0 x i256]*, i32 }* %2) //CHECK-NEXT: br label %store3 //CHECK-EMPTY: //CHECK-NEXT: store3: diff --git a/circom/tests/subcmps/conv_map2idx_B.circom b/circom/tests/subcmps/conv_map2idx_B.circom index 27e5bef79..0c9c1a288 100644 --- a/circom/tests/subcmps/conv_map2idx_B.circom +++ b/circom/tests/subcmps/conv_map2idx_B.circom @@ -58,17 +58,6 @@ component main = ComputeValue(); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define{{.*}} void @GetWeight_1_build({ [0 x i256]*, i32 }* %0){{.*}} { -//CHECK-NEXT: main: -//CHECK-NEXT: %1 = alloca [3 x i256], align 8 -//CHECK-NEXT: %2 = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 -//CHECK-NEXT: store i32 0, i32* %2, align 4 -//CHECK-NEXT: %3 = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 0 -//CHECK-NEXT: %4 = bitcast [3 x i256]* %1 to [0 x i256]* -//CHECK-NEXT: store [0 x i256]* %4, [0 x i256]** %3, align 8 -//CHECK-NEXT: ret void -//CHECK-NEXT: } -// //CHECK-LABEL: define{{.*}} void @GetWeight_1_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [2 x i256], align 8 @@ -121,7 +110,7 @@ component main = ComputeValue(); //CHECK-EMPTY: //CHECK-NEXT: create_cmp2: //CHECK-NEXT: %4 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1 -//CHECK-NEXT: call void @GetWeight_1_build({ [0 x i256]*, i32 }* %4) +//CHECK-NEXT: call void @GetWeight_0_build({ [0 x i256]*, i32 }* %4) //CHECK-NEXT: %5 = getelementptr [2 x { [0 x i256]*, i32 }], [2 x { [0 x i256]*, i32 }]* %subcmps, i32 0, i32 1, i32 0 //CHECK-NEXT: %6 = load [0 x i256]*, [0 x i256]** %5, align 8 //CHECK-NEXT: call void @GetWeight_1_run([0 x i256]* %6) diff --git a/circom/tests/subcmps/mapped.circom b/circom/tests/subcmps/mapped.circom index 3506e3fef..5ebe89a99 100644 --- a/circom/tests/subcmps/mapped.circom +++ b/circom/tests/subcmps/mapped.circom @@ -40,39 +40,13 @@ template B(n) { component main = B(2); -//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, -//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+]]: -//CHECK-NEXT: br label %store1 -//CHECK-EMPTY: -//CHECK-NEXT: store1: -//CHECK-NEXT: %0 = getelementptr i256, i256* %fix_[[X2]], i32 0 -//CHECK-NEXT: %1 = load i256, i256* %0, align 4 -//CHECK-NEXT: %2 = getelementptr i256, i256* %fix_[[X3]], i32 0 -//CHECK-NEXT: %3 = load i256, i256* %2, align 4 -//CHECK-NEXT: %call.fr_mul = call i256 @fr_mul(i256 %1, i256 %3) -//CHECK-NEXT: %4 = getelementptr i256, i256* %fix_[[X1]], i32 0 -//CHECK-NEXT: store i256 %call.fr_mul, i256* %4, align 4 -//CHECK-NEXT: %5 = load i256, i256* %4, align 4 -//CHECK-NEXT: %constraint = alloca i1, align 1 -//CHECK-NEXT: call void @__constraint_values(i256 %call.fr_mul, i256 %5, i1* %constraint) -//CHECK-NEXT: br label %store2 -//CHECK-EMPTY: -//CHECK-NEXT: store2: -//CHECK-NEXT: %6 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 -//CHECK-NEXT: %7 = load i256, i256* %6, align 4 -//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %7, i256 1) -//CHECK-NEXT: %8 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 -//CHECK-NEXT: store i256 %call.fr_add, i256* %8, align 4 -//CHECK-NEXT: br label %return3 -//CHECK-EMPTY: -//CHECK-NEXT: return3: -//CHECK-NEXT: ret void -//CHECK-NEXT: } +// NOTE: The loop in template A is the only that that is extracted for +// now becauseMapped locations currently block body extraction. +// // //CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]], i256* %fix_[[X3:[0-9]+]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_2:[0-9]+]]: +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+]]: //CHECK-NEXT: br label %store1 //CHECK-EMPTY: //CHECK-NEXT: store1: @@ -174,12 +148,12 @@ component main = B(2); //CHECK-NEXT: %5 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 0 //CHECK-NEXT: %6 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 2 //CHECK-NEXT: %7 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 4 -//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %4, [0 x i256]* %0, i256* %5, i256* %6, i256* %7) +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %4, [0 x i256]* %0, i256* %5, i256* %6, i256* %7) //CHECK-NEXT: %8 = bitcast [2 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %9 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 1 //CHECK-NEXT: %10 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 3 //CHECK-NEXT: %11 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 5 -//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %8, [0 x i256]* %0, i256* %9, i256* %10, i256* %11) +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %8, [0 x i256]* %0, i256* %9, i256* %10, i256* %11) //CHECK-NEXT: br label %prologue //CHECK-EMPTY: //CHECK-NEXT: prologue: diff --git a/circom/tests/subcmps/mapped2.circom b/circom/tests/subcmps/mapped2.circom index bda9b2a12..3ebed6705 100644 --- a/circom/tests/subcmps/mapped2.circom +++ b/circom/tests/subcmps/mapped2.circom @@ -57,35 +57,12 @@ template B(n, m, j) { component main = B(2, 3, 2); -//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0, i256* %fix_1){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+]]: -//CHECK-NEXT: br label %store1 -//CHECK-EMPTY: -//CHECK-NEXT: store1: -//CHECK-NEXT: %0 = getelementptr i256, i256* %fix_1, i32 0 -//CHECK-NEXT: %1 = load i256, i256* %0, align 4 -//CHECK-NEXT: %call.fr_mul = call i256 @fr_mul(i256 %1, i256 2) -//CHECK-NEXT: %2 = getelementptr i256, i256* %fix_0, i32 0 -//CHECK-NEXT: store i256 %call.fr_mul, i256* %2, align 4 -//CHECK-NEXT: %3 = load i256, i256* %2, align 4 -//CHECK-NEXT: %constraint = alloca i1, align 1 -//CHECK-NEXT: call void @__constraint_values(i256 %call.fr_mul, i256 %3, i1* %constraint) -//CHECK-NEXT: br label %store2 -//CHECK-EMPTY: -//CHECK-NEXT: store2: -//CHECK-NEXT: %4 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 -//CHECK-NEXT: %5 = load i256, i256* %4, align 4 -//CHECK-NEXT: %call.fr_add = call i256 @fr_add(i256 %5, i256 1) -//CHECK-NEXT: %6 = getelementptr [0 x i256], [0 x i256]* %lvars, i32 0, i32 1 -//CHECK-NEXT: store i256 %call.fr_add, i256* %6, align 4 -//CHECK-NEXT: br label %return3 -//CHECK-EMPTY: -//CHECK-NEXT: return3: -//CHECK-NEXT: ret void -//CHECK-NEXT: } +// NOTE: The loop in template A is the only that that is extracted for +// now becauseMapped locations currently block body extraction. +// // //CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_0, i256* %fix_1){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_2:[0-9]+]]: +//CHECK-NEXT: ..generated..loop.body.[[$F_ID_1:[0-9]+]]: //CHECK-NEXT: br label %store1 //CHECK-EMPTY: //CHECK-NEXT: store1: @@ -172,15 +149,15 @@ component main = B(2, 3, 2); //CHECK-NEXT: %4 = bitcast [2 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %5 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 0 //CHECK-NEXT: %6 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 3 -//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %4, [0 x i256]* %0, i256* %5, i256* %6) +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %4, [0 x i256]* %0, i256* %5, i256* %6) //CHECK-NEXT: %7 = bitcast [2 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %8 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 1 //CHECK-NEXT: %9 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 4 -//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %7, [0 x i256]* %0, i256* %8, i256* %9) +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %7, [0 x i256]* %0, i256* %8, i256* %9) //CHECK-NEXT: %10 = bitcast [2 x i256]* %lvars to [0 x i256]* //CHECK-NEXT: %11 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 2 //CHECK-NEXT: %12 = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i256 5 -//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_2]]([0 x i256]* %10, [0 x i256]* %0, i256* %11, i256* %12) +//CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %10, [0 x i256]* %0, i256* %11, i256* %12) //CHECK-NEXT: br label %prologue //CHECK-EMPTY: //CHECK-NEXT: prologue: diff --git a/circom/tests/subcmps/mapped3.circom b/circom/tests/subcmps/mapped3.circom index a19d26857..ebd87dbfd 100644 --- a/circom/tests/subcmps/mapped3.circom +++ b/circom/tests/subcmps/mapped3.circom @@ -71,12 +71,6 @@ component main = Wrapper(); //CHECK: call void @..generated..loop.body.[[$F_ID_1]]( //CHECK: call void @..generated..loop.body.[[$F_ID_1]]( // -//CHECK-LABEL: define{{.*}} void @ArrayOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { -//CHECK-NEXT: main: -//CHECK-NEXT: %[[SIGNALS:.*]] = alloca [30 x i256] -//CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 -//CHECK-NEXT: store i32 15, i32* %[[COUNTER]] - //CHECK-LABEL: define{{.*}} void @ArrayOp_ //CHECK-SAME: [[$RUN_2:[0-9]+]]_run([0 x i256]* %0){{.*}} { //CHECK: call void @..generated..loop.body.[[$F_ID_2]]( @@ -95,12 +89,6 @@ component main = Wrapper(); //CHECK: call void @..generated..loop.body.[[$F_ID_2]]( //CHECK: call void @..generated..loop.body.[[$F_ID_2]]( // -//CHECK-LABEL: define{{.*}} void @ArrayOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { -//CHECK-NEXT: main: -//CHECK-NEXT: %[[SIGNALS:.*]] = alloca [30 x i256] -//CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 -//CHECK-NEXT: store i32 15, i32* %[[COUNTER]] -// //CHECK-LABEL: define{{.*}} void @ArrayOp_ //CHECK-SAME: [[$RUN_3:[0-9]+]]_run([0 x i256]* %0){{.*}} { //CHECK: call void @..generated..loop.body.[[$F_ID_3]]( @@ -119,12 +107,6 @@ component main = Wrapper(); //CHECK: call void @..generated..loop.body.[[$F_ID_3]]( //CHECK: call void @..generated..loop.body.[[$F_ID_3]]( // -//CHECK-LABEL: define{{.*}} void @ArrayOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { -//CHECK-NEXT: main: -//CHECK-NEXT: %[[SIGNALS:.*]] = alloca [30 x i256] -//CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 -//CHECK-NEXT: store i32 15, i32* %[[COUNTER]] -// //CHECK-LABEL: define{{.*}} void @ArrayOp_ //CHECK-SAME: [[$RUN_4:[0-9]+]]_run([0 x i256]* %0){{.*}} { //CHECK: call void @..generated..loop.body.[[$F_ID_4]]( diff --git a/circom/tests/subcmps/mapped4.circom b/circom/tests/subcmps/mapped4.circom index 701df9b4b..a9f1bdd3f 100644 --- a/circom/tests/subcmps/mapped4.circom +++ b/circom/tests/subcmps/mapped4.circom @@ -51,70 +51,6 @@ component main = Wrapper(); //CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_04:[0-9]+]]: // -//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, -//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_05:[0-9]+]]: -// -//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, -//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_06:[0-9]+]]: -// -//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, -//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_07:[0-9]+]]: -// -//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, -//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_08:[0-9]+]]: -// -//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, -//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_09:[0-9]+]]: -// -//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, -//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_10:[0-9]+]]: -// -//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, -//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_11:[0-9]+]]: -// -//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, -//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_12:[0-9]+]]: -// -//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, -//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_13:[0-9]+]]: -// -//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, -//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_14:[0-9]+]]: -// -//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, -//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_15:[0-9]+]]: -// -//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, -//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_16:[0-9]+]]: -// -//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, -//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_17:[0-9]+]]: -// -//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, -//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_18:[0-9]+]]: -// -//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, -//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_19:[0-9]+]]: -// -//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, -//CHECK-SAME: i256* %fix_[[X1:[0-9]+]], i256* %fix_[[X2:[0-9]+]]){{.*}} { -//CHECK-NEXT: ..generated..loop.body.[[$F_ID_20:[0-9]+]]: -// //CHECK-LABEL: define{{.*}} void @MatrixOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { //CHECK-NEXT: main: //CHECK-NEXT: %[[SIGNALS:.*]] = alloca [30 x i256] @@ -129,99 +65,81 @@ component main = Wrapper(); //CHECK: call void @..generated..loop.body.[[$F_ID_01]]( //CHECK: call void @..generated..loop.body.[[$F_ID_01]]( //CHECK: call void @..generated..loop.body.[[$F_ID_01]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_02]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_02]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_02]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_03]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_03]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_03]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_04]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_04]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_04]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_05]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_05]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_05]]( -// -//CHECK-LABEL: define{{.*}} void @MatrixOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { -//CHECK-NEXT: main: -//CHECK-NEXT: %[[SIGNALS:.*]] = alloca [30 x i256] -//CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 -//CHECK-NEXT: store i32 15, i32* %[[COUNTER]] +//CHECK: call void @..generated..loop.body.[[$F_ID_01]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_01]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_01]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_01]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_01]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_01]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_01]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_01]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_01]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_01]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_01]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_01]]( // //CHECK-LABEL: define{{.*}} void @MatrixOp_ //CHECK-SAME: [[$RUN_2:[0-9]+]]_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [3 x i256] //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }] -//CHECK: call void @..generated..loop.body.[[$F_ID_06]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_06]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_06]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_07]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_07]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_07]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_08]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_08]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_08]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_09]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_09]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_09]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_10]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_10]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_10]]( -// -//CHECK-LABEL: define{{.*}} void @MatrixOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { -//CHECK-NEXT: main: -//CHECK-NEXT: %[[SIGNALS:.*]] = alloca [30 x i256] -//CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 -//CHECK-NEXT: store i32 15, i32* %[[COUNTER]] +//CHECK: call void @..generated..loop.body.[[$F_ID_02]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_02]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_02]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_02]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_02]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_02]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_02]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_02]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_02]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_02]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_02]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_02]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_02]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_02]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_02]]( // //CHECK-LABEL: define{{.*}} void @MatrixOp_ //CHECK-SAME: [[$RUN_3:[0-9]+]]_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [3 x i256] //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }] -//CHECK: call void @..generated..loop.body.[[$F_ID_11]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_11]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_11]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_12]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_12]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_12]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_13]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_13]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_13]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_14]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_14]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_14]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_15]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_15]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_15]]( -// -//CHECK-LABEL: define{{.*}} void @MatrixOp_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { -//CHECK-NEXT: main: -//CHECK-NEXT: %[[SIGNALS:.*]] = alloca [30 x i256] -//CHECK-NEXT: %[[COUNTER:.*]] = getelementptr { [0 x i256]*, i32 }, { [0 x i256]*, i32 }* %0, i32 0, i32 1 -//CHECK-NEXT: store i32 15, i32* %[[COUNTER]] +//CHECK: call void @..generated..loop.body.[[$F_ID_03]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_03]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_03]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_03]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_03]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_03]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_03]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_03]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_03]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_03]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_03]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_03]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_03]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_03]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_03]]( // //CHECK-LABEL: define{{.*}} void @MatrixOp_ //CHECK-SAME: [[$RUN_4:[0-9]+]]_run([0 x i256]* %0){{.*}} { //CHECK-NEXT: prelude: //CHECK-NEXT: %lvars = alloca [3 x i256] //CHECK-NEXT: %subcmps = alloca [0 x { [0 x i256]*, i32 }] -//CHECK: call void @..generated..loop.body.[[$F_ID_16]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_16]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_16]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_17]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_17]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_17]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_18]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_18]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_18]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_19]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_19]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_19]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_20]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_20]]( -//CHECK: call void @..generated..loop.body.[[$F_ID_20]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_04]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_04]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_04]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_04]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_04]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_04]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_04]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_04]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_04]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_04]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_04]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_04]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_04]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_04]]( +//CHECK: call void @..generated..loop.body.[[$F_ID_04]]( // //CHECK-LABEL: define{{.*}} void @Wrapper_{{[0-9]+}}_build({ [0 x i256]*, i32 }* %0){{.*}} { //CHECK-NEXT: main: diff --git a/circom/tests/zzz/poseidon.circom b/circom/tests/zzz/poseidon.circom new file mode 100644 index 000000000..f9a7d8852 --- /dev/null +++ b/circom/tests/zzz/poseidon.circom @@ -0,0 +1,958 @@ +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 --enable-var-scope + +function POSEIDON_C(t) { + if (t==5) { + return + [ + 0xeb544fee2815dda7f53e29ccac98ed7d889bb4ebd47c3864f3c2bd81a6da891, + 0x554d736315b8662f02fdba7dd737fbca197aeb12ea64713ba733f28475128cb, + 0x2f83b9df259b2b68bcd748056307c37754907df0c0fb0035f5087c58d5e8c2d4, + 0x2ca70e2e8d7f39a12447ac83052451b461f15f8b41a75ef31915208f5aba9683, + 0x1cb5f9319be6a45e91b04d7222271c94994196f12ed22c5d4ec719cb83ecfea9, + 0xa9c0b1916a8e41d360d02e6e2e5d1b98c34dfcec769429c851867e46e126fa3, + 0x1dd6ba3731e49d21e8d36e9d4d1edad245ebf9bdd9ebb60a252e4804a6390f6a, + 0x24ae2a67c3d521c11a11b7112abbdee30647107b808866a980837d0d7da4e3e0, + 0xd20c9310b5c14d9ef12866af5a45eae3ca9be16d200497066c8b2ee96781d70, + 0xe047c9821fe94d55d400d763a66c4c6169993abed543c7284b4a35430019445, + 0x29474ab799b1e13948eff41d2ce79bfad335d09110157076988ac207e10c81dd, + 0x3899f139d0dc4b281be3b74ab4c70789b7f41e7aca47ea2722a20d79afbca93, + 0x1866624f761ab8dd7a91c5f37af5e47639951d5acb6b1bbf3b96ca273f71029d, + 0x13c119f36718f7d5f09ad8541325a13acf6b34db6d9ee2af7ea06061240f3009, + 0xe4a1008158077402b11f13c08890b739643cc8e93fa44487b5a1575dd867fd7, + 0xef505fd44ac10a251b670dafe14cabd9ada9e3002210ac9c3876f37de4e7ad8, + 0x1d31e4e2a5978b7491c43d367470a5a5d1445b6b8129a5b9a6fd238405720de5, + 0xa979ad5428d481cb624d9d504524a9694ca5cb4421b5d1dc6af2c030fbeac39, + 0xf7fccd2ec8bc6ed9ce3682f38aa291deea9373f4995778bf762ade36d6ab2a0, + 0x2691b924dfa123005f7c078d9bf8706defe99c2ba99bd6ee53b153e9fec7bb80, + 0x2077df6510b4860e56b913bef3a80dbc464b0e4678add60dea7a9517463220b, + 0x29ee09d8af9d24ca49350ce2e0aa47d00a3dc21bafbfac1c9ba61c58e2993e8c, + 0x8b292c661d427506b9a01916624f3cde332aaced9f1a494a733cea6f25bfaad, + 0x2583699ce536a757b22e4713edfbb050092c84abc72c90ad87393a1da9a4cf90, + 0x1e3f1b660223d65ad88999475374f6e25fd4148eb8110a0b12cffa19657b0b66, + 0x20f3ecbb37c34aec79131455461259e59b222f0ee8e02f3194cf62a9ad4c3448, + 0xdf4f5088e4444fbf87d553ba62dbda95696d8b9cf6210b1c85513b1776fbc64, + 0x2b348effd4c9cef00a1cf4dd67dd664b2ffe361a807c589a252c63bcbfc6833, + 0x1ba1e522fcb153676cd8f20e82256f0327c000fa96b1b462fc84b556f26a86c7, + 0x294c44df8e68c96144e964c37bbc5766764ed3550aff80dbe9d3fa74419fe50, + 0x313716eec6dcd8a602ca040700498dc04c77dfe2194753c59bc818c1d2636a1, + 0x287dec74696d663e2359f68225de955384d960bbafb90967429a442e19e3ec61, + 0x25e42f72c6be0942311ba097cf365683db4962c8204fec9213f0f8f72c1946be, + 0x12b6881b96654fe1768c242acd5399b08639f081a94896f5ea6da70b6b475c91, + 0xdfc2b54546fd3267d7be55c716cb243ef18118ed9498c8270449bd9418afdb5, + 0x27dd55fe0d5c0ff56ad4890fa029c27c5f36d04cdc73899ab99b2872b28eedf0, + 0xc60962711aef16e7a2ce59f587443ec8b41ef8dcfccb38188adcbddd32f173f, + 0x2edc09feb267c6b586e62fffe32bf5f16c28b585986b81116684b7e8b40d42d2, + 0xaf8386859db252ff295a19466d8d100622c90502137aa1cd4c4bcc9656d11e2, + 0x121f218392f73d4c16abe382102a459e6c080b3ca4eda51a23e651a13a680550, + 0x1ea38273f5d59e65061f8c775c571ffc75ef67d29405b5e02913cb3019d56f8e, + 0x9bd2349005699bcc0ac35b627e2f8f08bfc3b0bf30b146f37742ac1556187fe, + 0x91c505b1e92448c11aea22aaac4d44f6a7f2132f89e91b7f55f9404696c1433, + 0xb316f1c29689d4f490f7fcdd5e9f2d256d443ba14cda4bb799b0573a931a99f, + 0x2049251919a8f3f4398188b81f99d2e2d0e3f5359cfa55bdf3aa75fdadf367e7, + 0x1fe7f9eb6788101908814168e3e4cf7a899a105bf9e584af0064188a4aac55bd, + 0x158e6579b0388153b0acd630ea94de8f6d966d529c2d01b9e9b1c67c1ec1d570, + 0x1994f82f27153afb9de2aa3f4be05c4b2c487e393dcedca2566aa6b7fbc3696b, + 0x1b6250553e8629a5a8a40b568432ce7dbd83c87603eeccc8dad572ccebef6e1d, + 0x20296940a7d1eded2ae79fd78fa2ac11abb2210bf24542feabee71f0d0d7c9e, + 0x2553943f9e0ffce9c297cd31c29f1fa5f01883cc9e504fded7a905032c170c89, + 0x1c56eb362896c2f00ad18faeaf04d577f5feb4db4e077965c38f2eaf5f7be08c, + 0xed8857205e0680055de7e822b6f7d62ac0f75fef67da1ff7b7735208885cf90, + 0x118f91185a09355f9d8c3f556367a2bebe79e7d9528a8d72a592681671aac75, + 0x2a71e6a67abdb25a78010fe6fe0a20d1d84e21cba75ad55937dc1834c13af0c5, + 0x2327dbc05997ce8575680e4b8929d4e9ed25fb9204277d603061986dbee57e0, + 0xe05235e01f21cc3f2971c382d18c14e41785a5ec8d447cd93d13281792e6d6e, + 0x98afa2ea7ff065b2adfc4ab00f3b04496c1e490eab264d2370b107e5a49204e, + 0x27bddb7bf06eaa63419adae44209dd25a4e35edcb863b009bd34ccc4905d204b, + 0x2704406bc806f4ccb19085cb9d3771b12ab5ce7aabf0601e9e06a2bc98837ade, + 0x21c75c54664b9fec86756aa9027261975244f42cf91c9cc0b33c2a62b756a3ef, + 0x2be84c1d84c16038ea5f933290699daaaa8164c5ea39a02bcbddc66cf69fe8ec, + 0x2c970e41d48649cf013c676c8c688ac165563720d1d5f32628ac5b239488a96e, + 0xe1ad2660a2e958daa1f2654b3a37fee60546ca0327150733070742edc806435, + 0x2060ee7fdf775fc7e389a55376374c9e35d5c8763d597f426304e236f577b829, + 0x1e0116818c843ed86f09daee0a581af10d52deeadad77656e736eac08e6f0f17, + 0xa89c1498ef25a383d886bb58424e6940ac399e3e557e9de951a697c54a7576c, + 0x303743d6f36d925e1097483350f5bd2cb297d4ec9239209f63c516b849a67e6, + 0x8cf44446d968430232df175d462b9c9b0e2e2c37e8406764cb96c7c3446018d, + 0x2419811cbaeb3f551b0a9232eee5d53e3769fbcf5239533074375f1b00777f16, + 0x4237c622626db376b774849dbbe876809082f1b13f5824f4c58369f27fe7b6, + 0x1e5b490c72eeb607e114a5cb87a8494b178937cdee34b9e8e947342c14454558, + 0x4265333e59e1a5ff749203cb4a5d1415a72862c61380b1c242d0f32ca15b97a, + 0x189deaf74258451ac4da682532be43d24a5c683293c1ff7486de26d35d982e86, + 0x4ec516b0fd42fa53a34905cfdedaad021b36399d03d8263ae08c46af3eca76f, + 0x2ce1c8a00845a82b3aa1b6642fc988578576cef86196525e6d595c7701ad700d, + 0x247816fd0d34f9d3b396917478605c94a1c052a6ed663bdc344e7aee9686b6b4, + 0xc676dbe6c494d5609c444de622bcf60cf555091a507fce86477019daea987d, + 0x1cb395ade530fc2407aa7b2148d2dfaee30f4ddf258fc149cce3c5cde80a85d5, + 0x190e1494e3cfdada3b9e65d8fe3c1ec769540da023f9ec2e56259f6a56890b0e, + 0x18f2941b2335138336c351a792343222a845ee0a2ea5a3b9160c1d6d9b229fe2, + 0x14ea23ce8b2312e07df57e0aece1da5d2c0e01f757e6a5c86ab5e403688544dc, + 0x2818ad1005f4efb5d554361a29f85ea10940d6e71f38e8369beff3563a660bbe, + 0x23ce3a9a522915a281793977b49054c37d65f90b841e0ca90817bab49d79db4a, + 0x6c2ed2be876309a9b3b44ece37b1c42382927dd04249658a3d41e3f38d5e022, + 0x18b6740f72d77ebcf642b945ca2ed6c8a9853a3749d7fab6051e4ca36f44fc42, + 0x1feacb9eb2a6878061374d069a9dae328369ee63e75a1b99cdb06a48b0d9976a, + 0x1a44ee4565a967647300c75ed2b2543d8d45d5477fd606a356d1073bd13831d2, + 0x41f3b3b5b1050c16bf3d62d87d5d273b067da484679103231ed65a18da9fe48, + 0x1fd958cc4fe0a290bd0fbfb8b8a513acb5898d63bc0d7e585b7d081c49eb5659, + 0x175daba07c5edbf84f09c87a8c34dd73325943a48fc12cb839dca47512561d2e, + 0x9cf0a4e6e31dc24dfd5a5a27a77833e477d5b2d92cff5fc5ccad9528c43ba78, + 0x12d49465bd4120cbf78e5a3414d44c6530bc963bd701c54d4c6418a6cebe80b1, + 0x101b2f2b675804d3b26b2bd1e07c7365af0bfc2edf010916eefb39e28215d44a, + 0x114fc65faba09a59749e0b5f111930783529a0638456216232cb7e5a339736aa, + 0x1dff99b52799afc802c2bbf9b67dd044d3cb51017dc4f88358ddd67366d3a9f5, + 0x290f4496a52dd4dda59edccd7325038bbdc0554ad3a9a0be7931c91062a67027, + 0x91e8704663c516c3b96721d2033d985089fb992dca48c8ddcb97d7d15c7e188, + 0x2dce22599de04196a0169fc211d0f9c8692643aa09728eadf6d50bb534c0e323, + 0x29a7ff0720e170c0e67efde72795328fecef66daada5f0e2ca858a8c6135fd48 + ]; + } else { + assert(0); + return [0]; + } +} + +function POSEIDON_M(t) { + if (t==5) { + return + [ + [ + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x2a70b9f1d4bbccdbc03e17c1d1dcdb02052903dc6609ea6969f661b2eb74c839, + 0x2f69a7198e1fbcc7dea43265306a37ed55b91bff652ad69aa4fa8478970d401d, + 0xc3f050a6bf5af151981e55e3e1a29a13c3ffa4550bd2514f1afd6c5f721f830, + 0x2a20e3a4a0e57d92f97c9d6186c6c3ea7c5e55c20146259be2f78c2ccc2e3595 + ], + [ + 0x25fb50b65acf4fb047cbd3b1c17d97c7fe26ea9ca238d6e348550486e91c7765, + 0x281154651c921e746315a9934f1b8a1bba9f92ad8ef4b979115b8e2e991ccd7a, + 0x1c1edd62645b73ad931ab80e37bbb267ba312b34140e716d6a3747594d3052, + 0xdec54e6dbf75205fa75ba7992bd34f08b2efe2ecd424a73eda7784320a1a36e, + 0x1049f8210566b51faafb1e9a5d63c0ee701673aed820d9c4403b01feb727a549 + ], + [ + 0x293d617d7da72102355f39ebf62f91b06deb5325f367a4556ea1e31ed5767833, + 0x28c2be2f8264f95f0b53c732134efa338ccd8fdb9ee2b45fb86a894f7db36c37, + 0x15b98ce93e47bc64ce2f2c96c69663c439c40c603049466fa7f9a4b228bfc32b, + 0x1c482a25a729f5df20225815034b196098364a11f4d988fb7cc75cf32d8136fa, + 0x2ecac687ef5b4b568002bd9d1b96b4bef357a69e3e86b5561b9299b82d69c8e + ], + [ + 0x104d0295ab00c85e960111ac25da474366599e575a9b7edf6145f14ba6d3c1c4, + 0x21888041e6febd546d427c890b1883bb9b626d8cb4dc18dcc4ec8fa75e530a13, + 0x12c7e2adfa524e5958f65be2fbac809fcba8458b28e44d9265051de33163cf9c, + 0x2625ce48a7b39a4252732624e4ab94360812ac2fc9a14a5fb8b607ae9fd8514a, + 0x2d3a1aea2e6d44466808f88c9ba903d3bdcb6b58ba40441ed4ebcf11bbe1e37b + ], + [ + 0xaaa35e2c84baf117dea3e336cd96a39792b3813954fe9bf3ed5b90f2f69c977, + 0x14ddb5fada0171db80195b9592d8cf2be810930e3ea4574a350d65e2cbff4941, + 0x2efc2b90d688134849018222e7b8922eaf67ce79816ef468531ec2de53bbd167, + 0x7f017a7ebd56dd086f7cd4fd710c509ed7ef8e300b9a8bb9fb9f28af710251f, + 0x14074bb14c982c81c9ad171e4f35fe49b39c4a7a72dbb6d9c98d803bfed65e64 + ] + ]; + } else { + assert(0); + return [[0]]; + } +} + +function POSEIDON_P(t) { + if (t==5) { + return + [ + [ + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x12873658ecf188d299b8ccd568eb14a4d4307c5caa95633dc296f05cfc966598, + 0x153cf8033d8e8a15cde2c5e6b93da4018c5954d00a9274ec5ec6d5101ea22761, + 0x9f15a882446823fdca6f6ab15dd8e250d90c84470516671afbdfb0de80fb00e, + 0x167c655bf6cf3e0fb64c9075773bc862b24b4ce2f69c8ec198add2758a2ce216 + ], + [ + 0x25fb50b65acf4fb047cbd3b1c17d97c7fe26ea9ca238d6e348550486e91c7765, + 0x27f9160806de9ef57ddb4243f839e4b7e8bb293ac176fdc5b5419ed73a07999f, + 0x16fceedd703bbbc2bc6f1d792e501939105b044b1b904d3b110110da983ccdc2, + 0x2eaa925d06b6f5a77c0d5cb20598742791495cec84593a57ee9fc4c9115ae7ca, + 0x279b324735fbc883e24f191ca7039f9986115b9e6fcf4946cf45f08ceda2dc8c + ], + [ + 0x293d617d7da72102355f39ebf62f91b06deb5325f367a4556ea1e31ed5767833, + 0x97d71f1fd579a0d0f436a6b36165cd23a9fcab03ad25e7872cdb09b4a0ea0dc, + 0x1a9fd26611128d592d594f51c251dbf4eff6dccecbcf2ebf310e34bed661337e, + 0x21eb30a57e5912ab06d18573fc546b2bf3be840d5f5ede01f91dd2bbb578dcc2, + 0x13abaf72889b31372b1e6f48759371ef65bc57d28ac2f60e6d227eb008b96ced + ], + [ + 0x104d0295ab00c85e960111ac25da474366599e575a9b7edf6145f14ba6d3c1c4, + 0x19bb8abf6a012cc7b8b974039c6be6df31446a51702b39a8d90ae4be7ec33ec9, + 0x11075889bc0dcc9d6f06af3012f04aadcf9049de04fc775f8fa091702e70b9bb, + 0x2e4cb25599a3dbf07de338827b28d16b9c8fcab8fffe8f2a16161be6a521a358, + 0xc7a700b33fb23fc642e0e8671deb84d05ded8ccbc968d15171182e158684e85 + ], + [ + 0xaaa35e2c84baf117dea3e336cd96a39792b3813954fe9bf3ed5b90f2f69c977, + 0x2b5d28e8d648bffe0fab59e3c7d983a4099fa0a4c548df0006e6d0f4e20206c1, + 0x1a96c37c461ab8a38ee15bc2784c5096d30d1482e57c2f861bab95584b90d84a, + 0xdbdd3171308bfcd3cb8b8a676592858b8652e902142beb8fe4145002fba8e0f, + 0x17ac4855f295a3b8fb8ceded7f4b39290647a0145af56b03b01e957808d66fa7 + ] + ]; + } else { + assert(0); + return [[0]]; + } +} + +function POSEIDON_S(t) { + if (t==5) { + return + [ + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x351d582486c39726623750495e297970b0e19787b49173a9388a0d5b08788ab, + 0x10e1a3beae297a472a31a3b51514c664abb12ec2d15860a29d2a9352d3ce8ba, + 0x12395fabf1c14664faf3ecc72a84623c1d5cb7b5e5744e602c886a5773e5f06d, + 0x9b91873151f00b299a173a5b736f73fbe2ce543f0b4d237565bd58758935cfd, + 0x1d53cf618f93c90852172c773264b8f49e938bf22791cff829e95ff6942299b, + 0x1a78e48450798918f254396fa7417bf2c5ff69259200c2a8d53af5f2c4d8ba1e, + 0xd3d4c1eb9828c87afeca8ea128d1d533750cf555c6b70d70a8520ccf16feb, + 0x3af062fcd1ca71ba6de0ca4436f1a5a0698a3f49abbe4ecf3daa0ea2e4dc84c, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1ad1ba4f26d401924b25657414256b59767284a692897ba5cd53a7f5322005fc, + 0x1133694747d2cb4890f4f5982564eac6019ca5a9091b302d2c10b87297041d5f, + 0x1b46c42ff1aa475972e26f559a88164024234f7b392039fb2a2171be631bd8de, + 0x1954aa0a79f14968c817000929e2e744262871011f238d986086e7d9574936b4, + 0x7aced898db99ae9796fc7191a103b9de4c77f0e08ecea6aa593974f652ac4ba, + 0x18a5a098d914f6221726d42ada7683a1605e20217a09489c9b2d84c3cdd2c39e, + 0x13e00cf4ab3b1e028165af8d41019ca20a21aeb40926592a180f9806083eb5a0, + 0x478f72938b528ec79defe09215b46320801fb752ddc88d638a48790561b4e2b, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x8ff43b0eda2134077b96d7e4cc37a6871254910ab4c58a4bcc78c1bc6ce3937, + 0x27d7fa3ab9c438b6ad1ec5a60e8ad91aad02e4d2908ff7192e5ac0cebd91f928, + 0x1e9ac8ae7cf2b40d629999251be50d9771391326a664dfc206f2abec8efbe56f, + 0x2d6b56b4849de82b636d81f2e98476bb6c35cbc8962137b615bff86f8f261971, + 0x21e70566d2f4bb8728fdb3749da99a2143a0d90bb6c1b0d6d02125aa1fe63092, + 0x1c01c050dd9b0b8ec8e5ee1eaecac1171bf69a8f3d477eb7ec3a605b010d4ea5, + 0x282e8dde73a0dc74ee10816aacc1dba10c142109c14ad7954eb7b56ca268a16e, + 0x767cf96b16035a96d19fcc57edcd92e746d226cfe84b733454c7ff9a16d25cc, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x18974b9f253b6bb681f82ed0f2d3e6b4f70ca858468b7f1bd3ded1a581ec21d9, + 0x18153fe8966abfc450a25222a6a27f6175fe851989776dcd2111a5a2de99c2da, + 0x2da1e2e775539490c2fe2c827e65c00e382a4a5d6c49a8374381d39c627f36c, + 0x2608589b9cd3f4c12b4e832e05fc5ebdcb403cd6560a8d7ece8d17ac94e79e06, + 0x5b4b074edb1366d35bf1c1ec1451a36cff351b407a8d30d563471bde491f146, + 0x856cc5a00bc37dd0217920da66c5765dea0644555e35822d7fd464d9eb38096, + 0x2021dde3ed193bdade457c9db5ab799e6b3fca640669d2f6295b4852f54d446e, + 0x12e3785f05f36bb797b2c9f03c5a55fab52e88b0550b7155d6013b706574d41b, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x118084c76d1340b3980add4df3878df4ffc6e9fe26f0b5c4e2f9579ee6fe2c1a, + 0xb9dacae8623c514c622c85753ef7b994d9102ab46620f956c26e9c62fe53050, + 0xdaea6d18a826bb2ba972ae16dc621cb8fdf9ecd531ee3c9f9d0b4012da6769f, + 0x8f2a5df6437e253b579921fc3208b3c176e5a18dde267a4f85b7afb7f79ceed, + 0x6a91d7c75e34fd43d9aa53b7d2793e4d5d70a5fecc5fd5653b162ba2631aa68, + 0x207579e33c36af2d20d759996c313f78dc339878c0a289d5db58b6b3d6069c56, + 0x25562540cd12084b3392c8cb8cda95ffc9c2dd6f8a75054ce16acf87ba871b9f, + 0xbbf47feca60b93dd0501ee0fc294c2a82b103817b4acf0af6979183afcdc87, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1e0814ce223453b24804a1ab4ce39815e35aed2fe9f7510e6288abb9d8b15711, + 0x18f9aa2721d95963399ae18d6d95a6f81b78b528e750554eb2613d6dabbd72a9, + 0x2ea329822ad302ab8831c559c64080e7ba6bf4c98ea0caf9cddd929bbb5875a6, + 0x29910d86bc27b38a93bca80677a3647c01cb5262ed19cd0c00872925a046a338, + 0x21c0a05ace45015ea895e01d630ce6b7423f3c211d26e8b6ef54d3dfc0660ab, + 0x25e7c463042f520ed2ff8c68be30bdddbd7ea5cdd7a91224bc6a32a3f5c0fcc, + 0xdf5b7e7663197f911e0dcd1ff4237ffdf080234e9b92201538ae7db6b6a7d21, + 0x94d0fcd9592b4771d2b9bfbc2bd78defef3b6ca923c68382650f9d63ce37c85, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x270361108967ed0391a49d4b7cd6af9bdd544e8bf048658c4fab36aa12407263, + 0x18bbf89e7cae93044c847bea654101914dbdd1656483e54e07ae332857821961, + 0x4aa47a0ede64ecdfa83507a2b8947b4b587758d75239071f6b4d3d66777bc1e, + 0x182d30ec988fca803ff7def1470c06aa6a596f56710184909fda17d354d3ce02, + 0x223c27171e456846dffc59cb1a53c761afddf85582e4c70ebafddf10eb1f8448, + 0x7d46dc97554a25edb78ea4d862c48bc5a08e9ea1eb369c5c8c2e0903114c915, + 0x1bf473a2e982e519523b486d264941d8e32cbbad362bdbf736d7ac04c4d2a964, + 0x12277b175bf54c3f2b0a57eb189e77714cf21630ace1fcf44d39397aae5b6da5, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x15c0a2cfffac7feab86a185031f489a9f83e89e3337a84b51dfe6fbb57feb15b, + 0x2b83199ec584185de52190f5a415c1fbb9efd4bb9eae4c4e2763abcf99359ccc, + 0x28601b9940a312c65b02adccb76937ef645d4e451c940ad4241b2b0f4925d7da, + 0x1a187b4875be24a2420729e016901b94ec0566c8a6936978c3f21e8d611996f7, + 0x10ed1fd44722d10bc7e44824e64978d36e68d56de2a465a0201b8e31065d5c57, + 0x2c4b6867179a949d377a9bfd3efe48456f7e70f02d859c78684a3573486dc227, + 0x15cb2c17aabecf7aa0f61655a8bb35a7afd87d0e20ac38fe21a07da7b388dfb1, + 0x4dff03c742111aab3e61f4166a733e87699c1ffa889fce179316e39f7d845ec, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x17baac874eaaa88de70cc92d5a72e00be4ec0e5e99ba7cbac2b0d98cead394a1, + 0x1dba338b4779919a2fb22ba949a050c85a73983d5ea4752cd73f664fe05f6247, + 0x1e33e7fcc41f32f90de5771d69e58f4486290c7b856becd5cd967d8e7739f719, + 0x10877ad7cf0652a2ff93977d3862e3ffb5d87d0c040f02a4f98612afafc9b604, + 0x115d3675856ff59ebcc9110defb9d6c70df6af533d4b0875d0e5eec430350595, + 0x3d74b961ba9013a874e7bcdc782f478da6097537549db7e6af4702ca749dae5, + 0x2563411e29867500a8fd18e4eba3c9a2b7992e44d263c29f7e06000f74887cdd, + 0x285501c4e0ee1b3c3e6b1b29160d6ec0f1af4dc2f36a4a1e654b7b47899738d7, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x209194489c86891b179e33103a81d969c5c75e941dc30e7228c04ed8ba68704f, + 0x2c7b2835cb79c29852926900cc168b2315aaf03a89532dd9fc162c2f7ddad845, + 0x1df181c420308c5b0bf00ee21c16f248edff686e9e835869d1022dcd4a8a635a, + 0x1ffabdffee2481d8cc1233506f708d9acabc1d758bb99c329142c866ef4c7474, + 0x8955ed55c2bec07027e4355a694a9b6ae1d9d50126563b29d8a074ea65540f5, + 0x1ab4b24a4db7c5758471846eb375163e7587791417cbc355b6ce93b64fd01da2, + 0x25a3439d2838ad459270bc633164f3a68215e11217eef1d605ecfa8b1805c609, + 0x65240d63179ae83013295a8251fbe17dd988ca5c84761ccb6a6ecb2bfbf02a6, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0xc1a91ddc1b24113bf876a2ef895c3315cd1b109cfa569b79f3155ee12b1c564, + 0x146fe8e28539ae36ae921069f4af83f675f1b68399efceb18989cab5fdd36ac9, + 0x1ba8c3cfa46425412e30790090980db139810efed7bdba7a38adf75e1a0d3641, + 0x83a58c9d889b74e66636bb8418db624726b0f1374f59eafb4d269ba1ed234d8, + 0x2b812a76ea526ce18df6032192ef033541aaf99d1c61839a0edf0336142a25f3, + 0x295f6d35fb9e57a50a5d913600538030ba8c09e021c16aa8634488cc8eeba645, + 0x1de69ba07e3b9f90c87eb67b1f64660c71befe5138061dbebb752296032542e6, + 0x24734fa363e52c64ee0162a86578ca899796e89caa1a3a3533b0965665208f59, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x2d5fb67efe93e8386fac071fe3522be1dade9dbf1d1030417a7b51e3122111f4, + 0x19522e9228feae7473e317fd7958a021a0b042a81b75da6dbf7568b857afab75, + 0x2bc3f6f0df0c7305afe83fd9ef0b708e129fbe889fce42cb695b33b290479342, + 0x783e5635eea0e623bb8c406909f0db77ad4f9302d4828b51015d6512818690e, + 0x2d61b243f02e21edaed6fd2e4969ddb95a6d0da8db17d115a9a3b0d8885bccaa, + 0x55e1a09f4bd4809a86e67f99279fc06ca89a4468df1ea25d76fe0ad36ccea12, + 0x17871eed22b0cdd2de61e55ba5c9f4e37da63ed0376420bb1ee7f077a0d7a85e, + 0x20fd0af1329bbdd70d4d835d18c915d98956c5f0a4252cfb81c1fe02fe130091, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x2e5b840ca8faeba6ec3613e22eb7b071d9633c83cef659ed96b2f6a8fcc6b262, + 0x5f5385703edf7c4a388ce585a81fe7cc92ff49e900b5601865a352c61d6b111, + 0x21e83ab5e95d369ccd30cc1c55cd5844cb1cc78ffcf0c8bc91c9c0d9937a3fab, + 0xa67b7ed9c37946306ac525597f1275b30a5d004ca50258c3d992284d90d724d, + 0x214f52f9f73a2c2d5425c9610461303d839dfe71891489c376c2ea3b5d868b27, + 0x241e0d267f7d1d899656929cdebd850f70ace216d9ac10253ab720bf40da0c7e, + 0x2229153475b7a6b282e110b10e8aed1fbc2a05a37352e954f40d85205fbd8bef, + 0xf30d0b7cd8ef10e895cdfab3faa4f4c1a61a5f4eba688634540619c84782d2d, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x265589a340c71d49e1660d3dd43d1869408176d8b9110ae8c369078de8ff7aef, + 0x1bcadf844bd1a2e7f4f464991dd651b9f15630c94977d35ebc3e85801252ac2e, + 0xc112b1c56ea288e8518cc039fe050649cf40b7ab98de8fdbc56eb7ef6bcfdde, + 0xf020b9ef75af8ddd505cd3947e11a04270be15daacbfa76fa04d9005283aa77, + 0xa426601ce9415e666acbbaf2a7cc8ef7ef7d07538d84b1a53da24c19c601688, + 0x10a1af65503614381fe2003123aee9008ab97d69739dc462e72a8be04594618e, + 0x2d792f9fe5f0ad658dddadfe3893d158012d84b3837b7415e188131595b060d2, + 0x2daa42d04e0b62fcb3869031bf382c3b9f8a98f7f5bf7421d0b63c2598f5f65e, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x144c0395157a1bfcfb5cc4187f271096784dbcdbfcb6a28c31ce8a06f908c0ac, + 0x1af8cdba0eccc83c16019622667527645e94c9ce64add4415df7f40446277a09, + 0x213c7a7ad6237e7211530c210a8d6f46a25bee433bade010591e6adf42fcd906, + 0x224f1ca24803c0119ad0e6c41a64968e064a83f5821972f2a5c9d5895da4ea42, + 0x10944d95ff5a3699efdde41ead13344937e3b1b93ba73a1531246ca4b99aad2b, + 0xcb2508b0a3395fabbeee5286ce5f1839c006ebbc09d94f475924923d8079ec2, + 0x284a14b1007ff6c5c0f8f7d8d0e4b19fe2d4a7094103912134b0f563a672acd1, + 0x2bc0bce43d55bfe1a27eed426980cf9055b0dbd42e8de516e77580b9d9a9060f, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x28e9b1884a4619b38b6f8a384368c358b7f210f3412c4481a26ae296f73c5c72, + 0x2123ca1f119a35e7d4e1b323fd2942d12ed020ccff3a7ad6b65af90457f00614, + 0x4aaffb0ba008fb9a82fc0700beaab2ce39efa895acdc280252f01e31035b8ad, + 0x1f1e16f8ec9261c82443b9b31cd908015e2c2d2314629a22639af1f37e1073d8, + 0x134928ff5ebe5e019214ef937b7f7a28248285d583613ea2bedfc66b5e2ae924, + 0x87fc99e11e63deec9d55047ac98030c57a4f09228cfa7749a3e1c7ab5f212e7, + 0x9429bcc52d6c43814df5b07fa116f8875299500a36ef791b592a64e27cca486, + 0x2267b1dfa5d26e6f0a80bc8b4c0026f0204bd4fd06c7725544d7760354e401f4, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x16fb3cdb76d21d3448c9988f428d198c8e5a640035ac2caff7aa7964b34ff1dd, + 0x80dd9d263a6698479df06bc98fc64594478028b61047ff93c425b29b092d37c, + 0x165f4f2d302a24eea5f46abeec4ab03d21e3d013865085e515bebcb2684af340, + 0xa8a3f3abf28f457c62045789fdcd302f0df1049b6ec521db2b7e72e8d9516cb, + 0x2342f103587a005c977578b12810378f9014bae831809cf7ad59ef3aed48aae9, + 0x1d1308e311e7ab846e158769c12213013eca377f396061aada6220f29eb1b7d8, + 0x2563949aeabfaa782be07dad903ebff5c913893761b75a3f8402a1e2bea5a998, + 0xcb371898d8d2e1f5bbc32dc21782704a73e415e0c9f6387157b48746bbf6ebe, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1231d40e7c6fe5bd47010ebe4f63d186369cdb6e8823aec194093a0b4cbc6845, + 0x18943696a4da551747068255f57a0437ba0ec36ad7e5c92cbed9c49a9775b97, + 0x1fa58f378160dd4af40e3b01bfe32dfd34f2cdca527973c194a53af30bc40670, + 0xc976561eeade533c5579041bcf5e8272e4af95efe3af9e5372250fdc5ad8966, + 0xcacfeeae1a8359ae9fcf831f315a4b8c576d579eae86b1b09823656231d3bff, + 0x109b0647298eaec354e4a155308192b5facfb586bc2fe63f073cd221a2106fb4, + 0x69d4744aca289d123baa0e6754c5232202dbcdfadd0ee8d14dd19a7bea39781, + 0x156195fe27df23b8184fc58a30e1a9bafcb9cc9fa9ce071163a26dccfb7c6ad0, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x20fed35942cbdc86df51a49ca26055bb25e232a42476ef06997af8911560fc12, + 0xcf20343957a55345423dd3450c2fd74039f1a82c6c02446dd64c4569d31471e, + 0x1e177139b05dbe38a56c40f919dc1f07126bad03049fc4025d77b4bc34c25ebf, + 0x144d1944a849fdc2aba8ab2a4368d57911e9614e3956d9326ca493c83050e932, + 0x162f08d305fe4f1b0a9bb1acf1223bde3405aecbf2356508841b85f1180cbc1d, + 0x21d68868502ab599c7c5f2a54d65be40ed5caec1613a98b2a98c5f8117415d97, + 0x984adb0c5263193be4027c68c6f3a6dbf7e22cf199dc4358b52968b0a248789, + 0x2883f3a940a8c10f7f347a8011b0f0d7f6e0a4a82eff568fffc7524235d1e4f3, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0xd89a340993be3d3ba07d2fa8432d412730e8ebf2bbfacbf9378c0c4d3d1e692, + 0x105e4a12836770bdbab24c85e7a63572c77556fffafc8f55a0e3f6e7383f7b02, + 0x4b09e851bb6dbbffd0780af3f99cbb707f5e8a073810b28b1b59794c8b117a8, + 0x2c8031907c10e1df2bfdd2589dd502a012a2292202e67954091ca57d21906d41, + 0x88a360cf4c5e26faddcba291dd2553906abd82fecb0ffaff4f3f544f672d703, + 0xe9e8d8ba62712e7f95840b5651f32912e84f146bbd57c566c178084cbb155f8, + 0x38fbaea7dd737c642ec414759bdeca4250d31d6011140e7e45e86c12c6f6fe2, + 0x96dea6e0d6411dd0c18e516511b03d8506c4901c52dbc2772c3d47bdbf461ab, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x2d60fb66fb133b0507b6b41ed7fbd5278c4ba9fa0679d2889da9672d21f07037, + 0x2567f444cfdbbf4d7799d5b50c8c582e1d2038a11969b3eb2b60aebafb1efc7b, + 0x2401d941b4fafe3311bc6cd9fb0bef62ad9b59e731c1ec4e6b0ca5e2c685bb2c, + 0x28747741579283853ed4e6525da70a4312769f7040db4f098eb7d9214fc8fae6, + 0x1104899fde3f530cf99500f20c4fb9d479e512cd70a15def442a4ea92bcb9743, + 0x4ddfde1b1aacb33977d4b3020db51b834f6197a18505e3ccfb37fa8a3a8764c, + 0x2bfa6913d62c8aea04ccc3e50229220efe3b9af6a568194ece56c065e3cac8aa, + 0x5cb914ec7b72436cf25adcbd0550c2db3c9c09aac565d46f96ac156fa72a90e, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x145dcc8a89ffd8fddf4e5bbe377a3b7649ab6faaddf5eb580ced3e0421b7077c, + 0x21f1b7c169a0744e49718346cbd390dbe3287f5de3897acdaaf2e4bbc1f3e80b, + 0xeeae34b5e8e48d2ba6bd062c803ced1dd1165cce5f8f0574ff7caf4e6eaf6b4, + 0x2827170c30a7f570a12f37aa0434e01a4aed9b5d37f1815029d5de89a8ff75e2, + 0xe328161a29c0376af526c8004597fbe018328d6d0c89503eaee36f59a4cee8a, + 0xd6617ff29ac941a779f907e749603cb36778fef6644b8684fa40055c8d978c6, + 0x169506e0877092fdef32109c064d251c4d6a50257ab9c032bd79801fa23094ba, + 0x8c516740479e1a852294e8cbbcbf83b4d7095b69758aaa9f1a368004dc1742a, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x281bcec4cbcefa9e18a1aca1dfeacd7f7ec527df5deb6c002f541ee4c0f2bcda, + 0x13ea58a6a82bf43f6d4c2619b87da0ce760410b68b77f694685e3f34ff47b86c, + 0x1ed604569bf581c71e4180d59a78dd48e2103006ac045566e44162656c36080b, + 0x15d25d19f8fb93c9272f10ea525e787c758f98c5bca884e6317ed21a292abf6f, + 0x1696701143abf5794f370a122fc60dafa4f0c241e8607983222bc72d1d8d1439, + 0x1471c9bea5d880676ffb53255487c1af57a0476b77eba56204a4a3780b109b50, + 0x1ec18e953909ee6e34dcbdde64fd6ae8b99817ffef4811551a27924b714cc00d, + 0x89ad915c65eb1cc1633229dd97f098a2f86e7ea44ee6d94f3fe5f08682c807f, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x7e3bb22a5d8f517b12b42d68ab707d809ce83671dd9a933313d251889a9d55, + 0x142b4285cb7ac7249975ddf59d177aeed1a94e0412002d83861ce061e3f38621, + 0x24839c6f8fade0c2ef1e248f64c4d81e324caa4ef4052916a31c5d1da484ec43, + 0xac0879ac864dc7bf40955a3f4a19cf37846fcfa9289ae59c8f8c7c174c5a57e, + 0x44832eb1eb4ac43192406deb4a37ea61e2d110468762d3a31f01f3c6c1f8208, + 0x2b3f948fb289860a26e995d14c6f8aba2089511c7ba58a310e6cbcb533f2dca2, + 0x118bfa7e2d1386301f187c1b1eda2f48c0a03de15e370b5be0f431a0b574681e, + 0x1399fb352bfce7874d22e0fcb24553b96ab59b85364c0c3c9b0135d4970c2349, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x2f25d0089300da1d286c5efcc9cf22d095af8f615b76cbee09b9ba651d737311, + 0x84eaaf7a0b07cf4992c7d05790c42cc742a7bed021c48f614b988d99f141e3d, + 0xcbb53527ad34cbd3c4d59504fa47c87eb5be078155e58ac3f1e4b3f45dd1cec, + 0x14e8e0d80d2af6efd3cc60741cbc21f6da3a42e2429322bc209097b1d22d26b4, + 0x149dc605f3ad39d4b470a132191d2739df2ad19fb71e067f6ede3f9da3172922, + 0x1533cdda4fe346f0a3e538172b8d5636d3b4b502047cb268015b2088f12b9897, + 0x1da21ab47505b1ed4358160f3cd24a01330718bb901beedde8cca37839805c62, + 0x130eee6229e6346096e121bda6bd3892aba85c363deda16ae8c8efc6ba721b18, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1d0669bb3cb83ad8702a76855510918ef300df2416cdf04a83061a915a6fbdeb, + 0x113f0f0db699267055417d499467b7502e23179a0c23787b7e8130967c95080d, + 0x28cd66f5e2046799405a9c14282070ef66fd409507971fcbac16032499bada61, + 0x230173d8146362d28c0cc9bc2c72a64afa7741b77653726017932821c1dc9502, + 0x4b23de911f3a1d3f32366c35a7f293837e1e7e8287b8abde423b2b3ab81c187, + 0xd4bcdd5ff441637f977dba6d523ef1f6178ba245cda76e429a91b0ca994db04, + 0x93bfbfaa8f3a8718603066321ce48219b55558f33e0f8645a93a41e6f4d3e2d, + 0x24e21e25f0b3d0e754bfd0e91e62b5fcd232e756ab34cbed6b4ab709dfca551a, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x146990fff0e10b8d70a4411f57f9e74a03d2ac0127b216400b82c8c644038303, + 0x1ddaefaba77bcd9c5ba0671b0a34a4cb37b7c689bdca187d90212f188ba4a87c, + 0xa7c37e8eab27e5edcfc3d6682b0267e3d9250fe470980956f5e3e5993ddaaaf, + 0x2d81f6984b67d7cc74b35aa9d673878f05d517085812190798dd24a510b8d6b5, + 0x7c46458e45e15ce1338bbe98ed3c0726664d8ae0c965bf0fc79ae31ad04a349, + 0x16dd83567c7289d8ea0e62df8620df74f3c987d5f162b6b0a24ab09837b5d2da, + 0x21819b9d78ef5e05c535a83e7d709f80f3ab5e8d733146139015ec4e34b29f1b, + 0x2340a29e4e4d4e920f39a6a32149b54307f918a2e179e6c7288cd02834c0e44c, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1ced784118aac9880c9fbbee28972453b36abc3d967b20e9b0a886af86d64305, + 0x237848c6b0c87f794b30cad5a3cebfe2c6c9173f7a258f4ea139252338a3ea5a, + 0x27c636aa956756d9ee04b355abe2fad8d703b1721fcf73b17a77751813c8abb4, + 0x1b40358386698e21d43bd3950c00f81d6ae340eff9ac0821a213f8fabd142d09, + 0x695487b95b15feda7188ab9bd8072f0edfcdaea2dfbe06596f8c037bf52145b, + 0x1df336831b6745c8f22a80c252ba12b24e2bb1e7fd3615cc96145d898dbf3220, + 0x264b7a66fcd41995c19f021b71fcb1abd59986c55377a82ad92e79a1165e58f5, + 0x208defb2122d53224aacda9868250ca3b39f78b13c9d150a14d75a886a1a42bc, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1627fe11fe92ca5b0841cd804a211151ca6c0d2706b2a17ec17a7fd224a48a13, + 0xd483b82a1ed0d6788ec73c257cacba9738eae7232e365df112b15a93459627e, + 0x24c490612a1636b43f902459851afb3cfc37d71db5e9ffd247116d5cbd34f9fc, + 0x2f2d08c8cab748b056307066141837d5cf195104459a91084768548346c8593f, + 0x42d3a4f87d782326b0c097a03de01ac1698954c8f300af708fa79a92e84790f, + 0x2b064fb3fabe9deb1593d253ecc7a12fcfae3193e8f7e16ec563876f92e4c62c, + 0x22b8060d8bd295c3a201655ef3891a481e21748554dcb7613ce6c0a532628e5a, + 0x1526148f85ce610667aa96af20059f0b02c8a9d4d463b27f0711db72a545503a, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x12d2a42d255875bd671d376e499cd79393db48c414f967d53388f60b4e180986, + 0x22d0f27c6767b64adf2eb09ed595e2f2c211a3504a8de66ac01991c81c0e2669, + 0x1fbcdf3ca6f2e0739b571248a9a994ea913375db065ed255b5eca3fde587dc91, + 0x402b7640d18feac0c700cbea0d8f527a7c3fb44a110c4d7cff21deae9a70e40, + 0x27f6c76f1b519e71c3888f1ece7cce4e0f99f231ddccc7798a31b0dee0c68206, + 0x2fe908cd208699c9d8e3b0c09f5c0fd58716d0eb50017aa7d12df08b53d963ff, + 0x1922a59ac83c1e2821afccf1610aa5fb0b3cf8eb3fe3f4957bac604c177fcffc, + 0x126fc5609db3cb254a05919034b8a7f9a0f85ec5abbde6f85068607250ea0ac0, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x28db35e17bb31e5be954d69f5bf8f6838651bb6f5c80f750b6b7017643b6c28c, + 0x26dd684288015065728c5e09454535a33e1537761d874102bd4ecd2baf40b384, + 0x1895d33a312becc17090e45df74981b4fc4b220d3aaa346c7e8485311cab159d, + 0x28bff25eb0f2a5c6d007a92a7c4d88bd9c12c5622d0ecc5a509c404048b7b5aa, + 0x130136f07c7e09acd49556f3a6bf0739c9efc0a1be738453af67b31e845c976e, + 0x259c455761e6b6420dadf3d6b64eb65493f989fb3e5698e7307a6d6075714ede, + 0x1c9ac464fb08828d02006c7529eb1e8f45eef54405ed2cfaa133bd697f618929, + 0x60abe65207efd0fda7b24719d35018f7607dd732e71c05077148f3d046dd180, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x2a41f347b5f6eebe8969667071926905a3e6e521b85a89006ec2f500ef42b000, + 0x17840fa3a180177731bce340ffeb5a3b6a68b94e3f870501e787edc5a94db63b, + 0x161ec94c3f624f928eadb0e2f2cf6b16430fba680a5a50590d89005a688d9b18, + 0x22d8be171b4571fb5b773c3a548fbb286b06e2701ce99b7630866e1bca6e2cc5, + 0x52464c9c7ad14525380aaea9b06e76f03db8edd220f90b03a9feef2fecfb978, + 0xbdee83b20d91ff9a0404d8b0593879c90f7be5a95a22c8e1b157d92c3cf4746, + 0x2d84235b4f4e04262d8f246123b8e631ad51a4e1051f41f1c89cc42b61717302, + 0x3d6b62f816bc4b464e2971cc6a7c1a585e519266c4627b1367ce7963cf93d86, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x16caff6fcc165168b3ed958d3aac8d09f98f670bdbb847ec0e9083a022d27692, + 0x2cd4beaac59c5306bf76ef7e06c81adff6de4bee730cd4676e966db45fc067d4, + 0x1b11abd8ee736830ffeda3782fc7a82623ecc5afa92c0ec9eeec58177ce8608b, + 0x2c80d3430e64bf850c9e10a22f6b781fd513af20d4705435bc870ec8cbe93cee, + 0x2d2f20d2ec0e52eec9fc2d0e49fef7a2454aa77a5055ebfc4d4449e8f83bd015, + 0x1e51c55a8d7a04be4edae4f7dfe6137e96370ee2a4ed459ec524b19de646e0b0, + 0x13d4327afa809e26c8f97e36ebb5be1d3992ec72d459760bbd25659790738f43, + 0x176222f47d8c0ff9e8a967920376793dbdb9dcc3a79b44fd25e1f43a755e6b81, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x5193cbcb59713c78012ede93db828e69336a197fdd30c6b7d03b1cfcdd6adfc, + 0x2bbe660fd34f6ac3f2545cba9f717d2eae9f8c60242851657f8661504a457c69, + 0x1fe59c3d2724f4158483406e6cd62aafa121c451f13e48ab3c857b2293333c3b, + 0x249c893f9de208601de45c9769ebad071eb864524003add0bde31fef7f4f91a7, + 0xc20c4a12bbd772e0dbb929b69b24751da26b0fa8639005ff786a25ac1a5fe96, + 0x1a0750fb1d27bcb326ceb3a3065a487cf7d513d8954f31dfb174fc5ed95ce55b, + 0x16d40c0ba7a7aa232eea997d45ec4f0567fb6814677b262aadfaefc91d409cad, + 0x25ccf860fc7237cc8721aaf1c717190db40ccd65bf65d108b16f851cebca736, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1a25b1a6b81926e968ffffa63979c900c1e82452c986ae599ef991ba214e6f67, + 0x2b344bbb50400ea76151bd0b68c3139955f101c701d32befddcfec1ca72df25e, + 0x1044e69af594eca5f9ca7ee28cc38d161d01037fe223412e2f10838bb9ffd1e5, + 0x1145f6f783af7d1e0ee3388f107ccc27609bb8314bce27b03dbf8d02843ab2c7, + 0x20ed7009a6093b160020318b0bbfbc9a9d14de64a3aa25936ddff0ffe3a3bc4b, + 0x24cc5ed4ff9d84fce95c1508e1c7852fe60a6def592f423bb79c229327be7627, + 0x1fc31b0e67cdf9efa9c0c312afe54b5158ada1511719c76953587b772f1c830c, + 0x1faf997032cbbadc0c6d30fc804d068faeccbdf7cc90155395b739e017081259, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1197c402e5f0a49c8f9b9a41af6fbcd013cf9adfe864613c1bdecb6201d9651e, + 0x3025d698462f4cf23c7d4d8a3eec4aa8e1a2184a43020122db653afc6d0deb4, + 0xecd1d402fafa3602052ab586f804ec15f1910542f35c608eb7a247d5a960cc9, + 0x30021619d0c0b402b429d4e962cc3c2a2d00c62c131144f7b3d7f8acae6975b8, + 0x2bcd05e889bf0fcd9dc4f5faf21c506cde15c316aaca47724e71bad0cf34b27d, + 0x1b890b4097a781900b40d9c1ffa06a5e8cd05ae8fe52e040db0e7085ca46b460, + 0x8081b53a974ee264310b279468093218cd5e5edec1b7da6b21ab35622242e48, + 0xe6632e8ec976cefca5b164e6c07ab40ac611fc723e8d8a14899a4cf4be3b2a, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x63a3f8dea9d024a6f6a851ecdb21bffbfe259ac17f6793c91e73823a82f4f76, + 0x23b2c6ec9af5d0188e75baab9990f663f8e929bcdac96cc09c4c0626274692a0, + 0x9a41c06730fe53d395c602113f1607fbe01425190d50d56e9f215658ad128cc, + 0x16571048fa92024a9345a0ffecc159e76602455a71bc7e9c9c01dc50d8aa1d6c, + 0x2a5a7e76dc76ad78878b3d3b4c74995e2ce77bc126e4d17db507161b049eadf6, + 0xa23738e129c11b285d81c1c01e3f87989c87600727e7593af45607f98fb18eb, + 0x2ce8d6eeaf4d6c7ca0922c4738e81dfba227e98fc3ed24e7696ebe9c2732a1ff, + 0x22e3bfb13d10368cee5175f5e2a2cc205d28021caf5fb2898de2389123178a5, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x66c43e71903c5b74ee8e90ec30a1d8cbff7d8c85d3c7b995a976036eef8c4b7, + 0x2fe5dfcdc9335f0c0dd3d08f4e783a5ff6c2e6fb7e2928840821e6da8d91570a, + 0x9accce03257f967a24c11ce718f21167d9d71a1cb60a4f50d0228418428300, + 0x224e2a85316b67bf2dc64549c505721a7858438a00e793fe76b961bfbfb67291, + 0x29f1447b45128f5c1cdb12a334509e0a991c0d2c9360a5cfc28af420c2ffffe0, + 0x1301ae5665bd3e87cb647f566ebcf2f2eb5bec4b257a77061a15dcc7b8b34abf, + 0xfc6599ea957e02f69b1ca585c7135425a6825867d0cdd2b06019f3c9398ba4f, + 0x22e91a30a945b960bd87d7b0d8290dcd5f5b1caa339c41aef323be1ba9c724e, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1c7c359c26eab655aa469e0f9a8cc3d8c7a8149ba9e9baeca9233b7edddd1d24, + 0x1ddf651a5d396b680828eaea1f252625db1988504765eb4aeae3274a19cef175, + 0xab486e3e737f40898d3fdd6bab09213c0056c2e090a90acc754574739159385, + 0xd0b817b8995913e3ddd08b576951bd47b45f536739fc9cc782e769fd17e0028, + 0x13471abd3a25160947928376fcd79dd5aa58672f8382745e3a040c2acb464974, + 0x7bff672e50ff1f20296b1838e5270229a7477110d9a7fb56580371ee4ba38c4, + 0x23f91ef1b8182e80c8a0f54c3a35ad51cb9a3bb61b07b3e34386f16f7f4b32bd, + 0x16c390b3fdf09c6c42e50b66557532cc5998cb5a8c15446d31813e7b70607ec5, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1976d21aee74f79c60d44e46029a5b04fc03ebfb9bdb09a0b5dbb89f677cd296, + 0x56e7cdc08bff8d8bc12dc72af3c84858dde68919cd991bdf513656eb0a0cfb2, + 0x22b7992d7c0ed349aab7531de2f12da4fdcf961215ba06f2b7577f5d42bfa85e, + 0x10f97fcc757a0d6d0d4e2d585ea5968b3faba9d6458d16bd366d081ab65ae95a, + 0x21bc046c3d727baf6e65b568653a398aeed8c95b73567feca3884a051ac001a2, + 0xe757fd0b77219a771723e071c9896062eedbb3da05cda25d39ead3cdf738491, + 0x1ed536c497ff36f612f326f3d03e97d30abf91605ba686af36ea04c19cce4f4a, + 0x2491340ecfed3f98ed6fd566034240e64a08e5a39a468c78b31e4734a679bd67, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x144b73c6f361a4c232674a08616b36c33f7bd667dcaeec35530a2e8fcb66103f, + 0xb244143540a248840ba5fa161cbfb2fb2dab97332073042cbf8a932144d27b, + 0xb5bedd8122560caf5a9dbd69f82f7439543bbad397d7cfb4ef7782f64ea4e12, + 0x1386c7e88c5c0bf880b28eb2735e221c2a88e7f871ca5d720c99b4287c528a67, + 0x277164cdc5187613b0a6d6450b56cabfc828f20dd7d07611edccbfc3d381c9ba, + 0x16bc97ee1ac4b1cea8f96e731dfa610212aec4a193015b94b0f2a1657d41f13, + 0xb341e4361f31734af9951c20a6aace08a3dc80f57379add9693b56b047b3480, + 0x263a060ba49fe4862df997994261e665c0406642c669c32dee4ae7a153fe1dbf, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0xdf811b70cab32c0ad0aacb576fd95b23424d3686d79e36feeff21d1aa047eb8, + 0xafae979e41c0cf7d662b4cf09e93dca70c0945c6759c4f8d2c935a6084eced, + 0x21ae12f1dbb152c33213efe9cdb6044574b3df8236be92341131435152115e5f, + 0x272fd8955a7524a09f77c28ce89d58caf7d883f9e4503ad6a37c0eab6bcbe468, + 0x3712cabfab0f6f3d23ac7beb815226883f409d60d798242c6d5e9dae8178fa6, + 0x15bc41d746b14885ba93dc7d00594ea2f174b3b3dbc1acd774335405c18b154f, + 0x9dded6d75c33754be1c1ebd2dbed077c1f1cb80938f0798bb2e25b054a52962, + 0x1d9fd7f273e141e48d7ae825a6d7758e351d80c4ed50139a659d52edff60d227, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0xca2cbfed626671d6e0f2e3d1b6b2ebb5e9048c2f1273223c34fe599429e1f2, + 0x1e9bb2efac004014858166710da5d764ab36b80e4e97500d784fe5cc2326fca1, + 0x23f8af81b77d2f06d566eb0d9096c4b267f498f92bac69d622dbed85bc8a8ada, + 0x11546811642965c71b3865d830809b7f402e02d1980c3219c4bbe48e8bd37811, + 0x2b872c434320ac521ac1e14867c05d88692de6ee063f402c28cba02adeaf9c51, + 0x1f80e8d09a04ffb20613cd83ea35fc1593f9a5d8db6c846d80dca53cd4ba5a94, + 0x117c4e17071565b51a2b97908f375ca0194dd595e9e873e8c0a158b59684ac70, + 0x14da94b9be3adb3c5f7cd04dd5c58f63e74245d5a1e6fce5de3d093d476f08a4, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x2ac96264771dd5b1762078d5132db23febb0d2edb19c7b24848d4b654e9ce670, + 0x5a23e8be5fe8e01b11d0c7a1dc85c909602604b15d620c7a51e2b017dd63830, + 0x172623676d3d38b2c68ba2b30c12c5818d874d83a98478cbec0b1d27f5dd7ece, + 0xb632ee1e8730d509691580805b890371ca2d51bce083faed1615a845481de7b, + 0x2a220ef566e4d54373e1a095231c10905a2f5e72edd2b6259b46ea45749203ce, + 0x2ebf4340ee05460d8298d52260b4ebae389357bd857cb638c41b2708cc333dc8, + 0x27e873b1750916366d2e7906ffe4f42e6dd7545bf534adc73a02b7410f7f8275, + 0x1ee70cb51ad6da4513ce42ff200e46dfa39992a90447f1004765711f3f5ad52e, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1021282efc84669e4a98956e30ad0043c6c19dfeb98d6d14bf027bcfa555f8af, + 0x1f1c2e424bdeadd277162d70faeb398d661225414a975a59be613e47274b73c3, + 0x1a71e415abc5ccd5bf268130070e89b1e61981cd54f6e5864b8cc4e1d50bb21b, + 0x29799820e28bb9c0a7bd0a2c6d6105e5c91f8f88b2823da7c57825067214dbb6, + 0x17377cb0195b95b473606c81a6bd5c807b22870afa6cb230a1048e9515e31db, + 0x2f73cf9f22e0431d5e7bbd907ebeb8553b4117ff1fc50d09fc7b75935ef41251, + 0x19cd57e77a99328260bd31fb993e7bb3fd27fdc21b2187fe3a4bac0ad664719c, + 0xd5ff1b6b5f33d6d568d9197d0df40d07abede20ae3a94a0292c01c304012713, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x26c7615e04be2355af0773fc0e025f86baab5f59d834ba005e099d95331d61b0, + 0x170ea6732c6d1b2ce3279f2d4990926fb8d279e4864d966ce6ee6c319739c2f5, + 0x2f870269a506f351fb0b9a9d677bad1bbc5e6ab40ff0afc1772f02ba395fdc8c, + 0x11986790a1cc239c92bd4b8d8a1b9baa76e1e49f847f16ede5f6398aa83e97c2, + 0x2510c2e5a39cd6c243ff590621941b221d2a2c5a79ed6e5bb90eb1008219239f, + 0x1ba5c05a828609b93a7e151338699af0b8b0aa96d3d5cc9e7d3785333fa03dcd, + 0x8648c03bd03b5f4dc3868ac1c47363d90010b9cb19933554fc7586b97b5fbda, + 0x69d0c72c5880618f66ad58d65f09e5fc488697c71d92135be291f55d496cb7, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x91acb34aa0d03afd0ea47c1d56965a9051b05eebff9af71e07c4554184f462a, + 0x2b3f75e8ca7118776d9676fe058565eb99b6e99bd23505a8fefc927e17cf5336, + 0x16d9ae82c0073fe1dcf35384c0dce87494b2400f9027ce1e64ee440a439fcbaa, + 0x2a11becd9333eb48f3027ad8f3c24fa1a0ea671a1020278ad84c863c322e8057, + 0xd569be295d5e44ccffd9d3ba84aaf6a0c178e8639689aa6c57214f00a6a9d90, + 0xa66025e45040fd45eb136eccc63e2d7fd237aae9b62e2330aaaa0bb44dbef48, + 0x2cda68234c7e22d8fd725d952d3c529b6997b68dc02065f6a047b6cabdd29e42, + 0x1f9ab3e8029afc72f56af02ced5a6b145ebc81444ed12e82c7ea547e9ad23650, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x18a2e32bb69277e0f5e82c2a60a008b3db5caf3c53a669215c0b3493b73c7138, + 0x224c4f2e98b4fa10d4ddc83f26ada461e5b4f412f94a1eb153be707470746fbf, + 0x1b2a8787e954d981add1b123a6f6c100a609e8135c0781ac9a1e7e326c4b0f4e, + 0x2da288c34f32d86d5dfc0b2dc9891091d396d36de9f70589b7beee769a058622, + 0x2e24d351b0d0e94f3e0f83eb60f2d476b8b64dcb47674290e87b27eda7f20180, + 0x14af016f9da2f982e82aec1ff6ee809445db2c6d85382f959508a31830dce9d7, + 0x91aeac9bde9ce64a54cbad523032180c2135b51ec4547ebcda08824bc9cdf9e, + 0xcaa07eac62d9f07c17f63f749b7047eaa1adda97f5716d76f23affd6d845dd3, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x554f06e31b164d9d7ada3e01c4bbf452fdccac121ca787b08ad50dd2928ed42, + 0xbf8f8d7702b1e8830bf126dc420158a624359067a0f6385068390b01d176601, + 0x1604d181baf488dce4f99bf63c065ed934ee29f0649af4dcc9ac2a2887e8690c, + 0xac951e2944f7532d4ddce72d31c8e91c0795cdfab82df338f172dd9bffdae43, + 0x24d53d9f665348c12bdc3425c2b83e24fbea3b66b0c9d119146ed5d5a1d1e9f3, + 0x1ee01a89a7ebc6b8e93f2ac2e60b9909e3e3d855852e0e113a72a118f56e2da3, + 0x2b78c3171a3c8ec6231bb7c208e5b7c2c90a85956a7f2a1f763cb6c883059938, + 0x7ca1e306d90787461696fc7e4a3938712312494329be76c8e2b402cc0d617e1, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1febc25f88aab92179ac3cefeea663f51562f6fc631bb236c04f5ef85b464784, + 0x1b1b065eb60dbd39a34da94414fdfa4415933a6bdba5c2de470ad8ccef1b28fd, + 0x60fcebd24cc08503ac4f80c0ffb87d0898f34bdce41420e84d941b5f7d352a, + 0x2a7b16d282447357a66d83fc5aafab7d3edbcb3f01105f193954c5ed496ae165, + 0xac39f59e76b9e296ef53921ae0436ab01217493f948bf6eca12b11ce46678b5, + 0x90b38aaae1df1873784a8966f1f62b68bbd93d34b0f4c637e208f9aeaedfc26, + 0x1ba601baf813cb2d40ed5674747b9e3d5760143501e0f21e31a7dd44b7135eb8, + 0x17695ec6204f10059ae5ca72c1332bc882cb7b4e161accd1ba9ef760b7365d5d, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0xab5930a06bb6b9a78e664dc5308da0b64d1e09e6c69fa583bc737245c5a469, + 0x16ab9a5de48bf089fba600dc70d2790ce0e8f79c1430566802f97fee43bc4e2b, + 0x75df7d5cdb7ccc175462dfad73927bf5a5f465e15ad267930c5ec846f42ae5e, + 0x23e4a7be74d0f0930279585aeaa432b5c28a4a2b21e3990aa45b5092f08d48ed, + 0x298795a8af97b8b3d378279e60b276b95227e66d74e2dc66cffa1c495af98c25, + 0x133d1455b6ea278f4acd91c65906bf75f2c90e41cdbefc2721b1e96adc5eeda7, + 0x24b722af1967cddac6a1745b71aca7bac72d436ed464e2b8ce55aa2ad5ff3502, + 0x276cb6e59cf4a06ff6775a537a4b04c6b42780c9c98a51ff634804b23acfac2b, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1044b0ed6b39096c0ff4d292c18632c909d1519149139b1cd192de01485dce3e, + 0x2dc918abffffceeb34cb17a8cb532f889d7dea98e9ad2686ef8e30936ecdb03a, + 0x2a5030937ec5690d090ad8b3d897541ecd187d2ee126fac5be6a280fbd4aa465, + 0x16961c105f85925010e0fdd445ee840dbd3370aab933ccfcb6e4b24a8826037, + 0x17262da0f8e41b6c42707dfbabec1d9f79ecdfdd25a32c2a640d3c5a4a3e8770, + 0x59935903a135cffc7c5e8cb06de7a0adbc6fe4f66b07a74172eb65951c6a345, + 0x1ea2228bc5f09dadfabf025e3d19db3cca4e448e60f2973605d2559a27b3bff8, + 0x1e35c4737f19de2debd3760ddc81e1f5857a01c42c86f4e264ba323f4165d5ed, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x5958875cfb17091058a7e29cbfe20d0d242ecdfbd3635279cd1e0c3a1144dd8, + 0x19fd165b2741329dc18d2a5b03d7b58eb3dcdf2c2b0870731a924387139033dd, + 0x11cea375386801203c61577504cdc68493716d023d116356def9ad9825be5887, + 0x2e911408231ad83ab40e44e28ee0b017a82f7e080a0d4bc1b42c52e9205ed13a, + 0x9d3f08c1d2cd4de393b703a7dd94df0540c91b59b288df6c1ad8ba0e51f179a, + 0xd8bac92c12807a3fb4b20ec11e083a88b953070c08c1ae9be28c80cddb29a50, + 0x22829b774491c0e3add8e7d2de8096cb55a1009ae9ce983b80c14972bc68b84e, + 0x2aec91a87a1731f6b2f534955aef3d09ca7e2ee2dbdb5e9a0d15db232557c621, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x281ec503552e6778fbafd7270951cfef153fcfeca0517410e495c62b81655f9e, + 0x98a3183f2ee18973943856c28e0dceb4392af147ca8b528ebee97577178bcf1, + 0x794a78e51b51af07808b643ed37bad31e6d6c68e5ef3171dcd06de598c6c29e, + 0x214a19348cd7cc8b1f985287e637e7987a3bedfa233f98dae9774daaea42fce9, + 0x130acc584954a9048597bda6395bd25ba02fce56102928cea7d5a6f520683ca4, + 0x1d09e1227434a4bcf72d8e91f5419ffd6da212a1d1ccb2a51b03e80aa258243, + 0x127397f2b156ba00d83847f03dd242007faf326271d0e2cd4f6dc84c961b19a6, + 0x971a3d373d35db8f181e0d7b26c33cff17e533e8f560d844694f853e7197e47, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x241c8bcc463ac96e3c1cc240ce83c44edcf9c781e258a2dad09d1976d9dc6dd6, + 0x1a0b489baf0a182599f458897aa340e57986dcde7bfd34738851092a75ae6e0e, + 0x102c886ce6381276fe52d15c51dbd571e94904a8ec4d4445d457d596442e443e, + 0x289f8a46d6792691caac00cd43dde74940f122c0e5ac202588349c2eee473f6b, + 0x2ed1721123242c33f23f809f6e431511594c10b0533afde3304ba62afc55f5ec, + 0xc730a9beb7b64f090a39929af4901900e772b0f817098adace287cc20dd9e84, + 0x480eb2f48521f46f5049f8d9d682d6f4060ff6c4190b2a22c40c27d0754b912, + 0x221d30bbccbb39bc23ffe2c8571a8cd1763cd48de6dfe21d7d8f2805db1e5066, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x22eff0bad54cf4f8fda9e07bfdae36713527756cff255aa481b730bd286cc90, + 0x220c6f4c23ec9272eafb522055494a1af4de6fe7456b39c5db851e1299b7a86e, + 0x18d66b43fd01a9cc88dd14b1b5d6c0d23b29ac28775ff60d3ccf36039de0963a, + 0x1f62901537c1c56f671fabbb4fc31fa743f3236c26f9f5c98ecbf332eda817df, + 0x130beece629451200a3de22eab4c45bb592aad667f9fc6729842971d4a802fcc, + 0x24411acb2c9c481c59adc41bc54fdb0fac658ed6e0b3636cdadfd12c386f8c98, + 0x2370059923938a3552819155a8b3816fb90cbde45871f6c122c190a27e7fdc43, + 0x217ccb823582bf7edbf4a6a64692e37928f2b02d79b43775abf304500dd2da46, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0xe2be5d3f9ee73557a1c421fe42cb29bdf8f4a58679a61496bf8a5a4f9bba3be, + 0x27639d7e461732f3baeb172103de2bc4a26708623919783fe54774153bdb59bf, + 0x159c005b660c7fb3551cbf624aadcec047ce72625673c866c5fb289f8c865fff, + 0x130d38734b549e833b50c550a90580c53248bb96731c0921ad6373316dfdaa8c, + 0x13ee4afd14334602b6791a7b8f49c4f4979d485b8d1b1119cb4a2a7c31a74f39, + 0x2d2647b74c63579e81a6270afc73e636e588996745ac0499dbeb6a7cf80a889e, + 0x1b884086fa3c4173be0fd5cb1c866c87e0f9ae4c3d9f1e3df630cb4c2fa59af5, + 0x2289328b5db5b2b2d00e76ff78815696e77eb19acdcb6c84279e65fcce29d15d, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0xbbd293300c70f612c8f5b7bcc6c4106246d2f713df02774a29742c31efeb4ae, + 0x278e2893fbb5d590fe623652e50086d58ab18d3015a59d6a61602b409252ec2b, + 0x2fcc41f73df0c835b0b514cbdd469af1e2b494f05269d15a6343af34668b18c9, + 0x378097f57525674b961d42a2f57a937c1fecaba4c673bdce345050d981b8fe0, + 0x15a6727e6f181a5da795ce173f1889e07f12892e13f889c4f8f6c71725ab9f62, + 0x1edc3a58673d364ba5906c3b39ff7f654c5d42f4ff94e6e75d2c500842846477, + 0x1aeddbe743c87ec10fe447a5d08ab5c73836eb214ef95a08ce91131b8e1a7f8, + 0x286e544456f114ce609d6b805b31064ab65482585699c91b9b3e83a75ca386b3, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x1477e88daf9348ea5f95cb08426f4285c654a897a2c4895333052fe2cdba34cb, + 0xc9918bbd089bc26c937ae2e0a92a1d8c87cf4480b055e43831a5e6a3acbe5b5, + 0x283c24f7bedf789f31465682347ff86b4c0fbb7f9aacbe5630021b41532f7931, + 0xb1e5f0ca68bafaf026438a4682a55c1df5d387c4c5f3e111ead3163eb5b2754, + 0x2d9da1df21f14ce401ff84b99fba07311a9da3cd7efc200695ab55b1233b9043, + 0xbb61e50ddc0821f0c03b3bed9476f580a02157b6a69a17f2afb0eff5f1e2a37, + 0x21dc1358f62ff3dc24cfc896fdfbae88b0074323dfc7b36d680edba89c470e4b, + 0xdc75868b6f7e6ec9c26221637eb789b9e4c2b892ce81b527c7da05627ec2dc8, + 0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, + 0x8606e28acd8b2ee4c23a757886d7e99e407d177a58fb31b410ead7fbe1ef272, + 0x2f70d379513ce458231a8ee6b3029bcbbb4860ef48c104ddcffe65603d81592d, + 0x15315ba38b9e4c7a64a0844985e7b45db39eaec4c63b490cecfb19f02e102669, + 0x2a1529e4b1ca0cee97cde58af1536c4823f7e558bdc13f774e4ef3ec8454675b, + 0x2a70b9f1d4bbccdbc03e17c1d1dcdb02052903dc6609ea6969f661b2eb74c839, + 0x2f69a7198e1fbcc7dea43265306a37ed55b91bff652ad69aa4fa8478970d401d, + 0xc3f050a6bf5af151981e55e3e1a29a13c3ffa4550bd2514f1afd6c5f721f830, + 0x2a20e3a4a0e57d92f97c9d6186c6c3ea7c5e55c20146259be2f78c2ccc2e3595 + ]; + } else { + assert(0); + return [0]; + } +} + +template Sigma() { + signal input in; + signal output out; + + signal in2; + signal in4; + + in2 <== in*in; + in4 <== in2*in2; + + out <== in4*in; +} + +template Ark(t, C, r) { + signal input in[t]; + signal output out[t]; + + for (var i=0; i0) { + ark[0].in[j] <== inputs[j-1]; + } else { + ark[0].in[j] <== initialState; + } + } + + for (var r = 0; r < nRoundsF\2-1; r++) { + for (var j=0; j, array_loads: HashSet>, array_stores: HashSet>) -> Self { + pub fn clone_with_updates( + &self, + field_tracking: Vec, + array_loads: HashSet>, + array_stores: HashSet>, + ) -> Self { LLVMCircuitData { main_header: self.main_header.clone(), field_tracking, @@ -351,6 +356,7 @@ impl<'a> LLVM<'a> { // Run LLVM IR inliner for the FR_IDENTITY_* and FR_INDEX_ARR_PTR functions let pm = PassManager::create(()); pm.add_always_inliner_pass(); + pm.add_merge_functions_pass(); pm.add_global_dce_pass(); pm.run_on(&self.module); diff --git a/compiler/src/circuit_design/template.rs b/compiler/src/circuit_design/template.rs index 0950742b3..a61f6149d 100644 --- a/compiler/src/circuit_design/template.rs +++ b/compiler/src/circuit_design/template.rs @@ -145,6 +145,12 @@ impl WriteLLVMIR for TemplateCodeInfo { producer.set_current_bb(prologue); let ret = create_return_void(producer); + // Use the template name as the Section identifier to prevent function merging + // pass from combining the build/run functions from different templates. + run_function.set_section(Some(&self.name)); + build_function.set_section(Some(&self.name)); + + // Set External linkage so main template functions are not removed by global DCE if self.header.eq(producer.get_main_template_header()) { run_function.set_linkage(Linkage::External); build_function.set_linkage(Linkage::External); From e5b719eb46a1f0aa5409259af8443d1fae300d8b Mon Sep 17 00:00:00 2001 From: Tim Hoffman Date: Tue, 31 Oct 2023 15:11:38 -0500 Subject: [PATCH 9/9] Update test cases from merged in changes --- circom/tests/debuginfo/assert.circom | 4 +- circom/tests/debuginfo/branch.circom | 4 +- circom/tests/debuginfo/call_and_return.circom | 6 +- circom/tests/debuginfo/compute.circom | 4 +- circom/tests/debuginfo/constraint.circom | 4 +- .../tests/debuginfo/create_component.circom | 8 +-- circom/tests/debuginfo/load.circom | 4 +- circom/tests/debuginfo/log.circom | 4 +- circom/tests/debuginfo/loop_and_block.circom | 57 ++++++++++++------- 9 files changed, 55 insertions(+), 40 deletions(-) diff --git a/circom/tests/debuginfo/assert.circom b/circom/tests/debuginfo/assert.circom index f2a79736c..41a3e51af 100644 --- a/circom/tests/debuginfo/assert.circom +++ b/circom/tests/debuginfo/assert.circom @@ -16,13 +16,13 @@ component main = A(5); // full lines or to remove the "--match-full-lines" option and surround each check with // {{^}} and {{$}} but it gets messy. -//CHECK-LABEL: define{{.*}} void @A_0_build({ [0 x i256]*, i32 }* %{{[[:alnum:]_]+}}) !dbg !4 { +//CHECK-LABEL: define{{.*}} void @A_0_build({ [0 x i256]*, i32 }* %{{[[:alnum:]_]+}}){{.*}} !dbg !4 { //CHECK-NEXT: [[L1:main]]: //CHECK-COUNT-06: {{.*}}, !dbg !7 //CHECK-NEXT: ret void, !dbg !7 //CHECK-NEXT: } -//CHECK-LABEL: define{{.*}} void @A_0_run([0 x i256]* %{{[[:alnum:]_]+}}) !dbg !8 { +//CHECK-LABEL: define{{.*}} void @A_0_run([0 x i256]* %{{[[:alnum:]_]+}}){{.*}} !dbg !8 { //CHECK-NEXT: [[L1:prelude]]: //CHECK-COUNT-03: {{.*}}, !dbg !9 //CHECK-EMPTY: diff --git a/circom/tests/debuginfo/branch.circom b/circom/tests/debuginfo/branch.circom index 5df9f2bf3..5508c9650 100644 --- a/circom/tests/debuginfo/branch.circom +++ b/circom/tests/debuginfo/branch.circom @@ -25,13 +25,13 @@ component main = B(); // full lines or to remove the "--match-full-lines" option and surround each check with // {{^}} and {{$}} but it gets messy. -//CHECK-LABEL: define{{.*}} void @B_0_build({ [0 x i256]*, i32 }* %{{[[:alnum:]_]+}}) !dbg !4 { +//CHECK-LABEL: define{{.*}} void @B_0_build({ [0 x i256]*, i32 }* %{{[[:alnum:]_]+}}){{.*}} !dbg !4 { //CHECK-NEXT: [[L1:main]]: //CHECK-COUNT-06: {{.*}}, !dbg !7 //CHECK-NEXT: ret void, !dbg !7 //CHECK-NEXT: } -//CHECK-LABEL: define{{.*}} void @B_0_run([0 x i256]* %{{[[:alnum:]_]+}}) !dbg !8 { +//CHECK-LABEL: define{{.*}} void @B_0_run([0 x i256]* %{{[[:alnum:]_]+}}){{.*}} !dbg !8 { //CHECK-NEXT: [[L1:prelude]]: //CHECK-COUNT-03: {{.*}}, !dbg !9 //CHECK-EMPTY: diff --git a/circom/tests/debuginfo/call_and_return.circom b/circom/tests/debuginfo/call_and_return.circom index f9d98f1d8..3d3dce231 100644 --- a/circom/tests/debuginfo/call_and_return.circom +++ b/circom/tests/debuginfo/call_and_return.circom @@ -25,7 +25,7 @@ component main = C(); // full lines or to remove the "--match-full-lines" option and surround each check with // {{^}} and {{$}} but it gets messy. -//CHECK-LABEL: define{{.*}} i256 @negative_0(i256* %{{[[:alnum:]_]+}}) !dbg !4 { +//CHECK-LABEL: define{{.*}} i256 @negative_0(i256* %{{[[:alnum:]_]+}}){{.*}} !dbg !4 { //CHECK-NEXT: [[L1:[[:alnum:]_]+]]: //CHECK-COUNT-01: {{.*}}, !dbg !7 //CHECK-EMPTY: @@ -42,13 +42,13 @@ component main = C(); //CHECK-NEXT: unreachable, !dbg !10 //CHECK-NEXT: } -//CHECK-LABEL: define{{.*}} void @C_0_build({ [0 x i256]*, i32 }* %{{[[:alnum:]_]+}}) !dbg !11 { +//CHECK-LABEL: define{{.*}} void @C_0_build({ [0 x i256]*, i32 }* %{{[[:alnum:]_]+}}){{.*}} !dbg !11 { //CHECK-NEXT: [[L1:main]]: //CHECK-COUNT-06: {{.*}}, !dbg !12 //CHECK-NEXT: ret void, !dbg !12 //CHECK-NEXT: } -//CHECK-LABEL: define{{.*}} void @C_0_run([0 x i256]* %{{[[:alnum:]_]+}}) !dbg !13 { +//CHECK-LABEL: define{{.*}} void @C_0_run([0 x i256]* %{{[[:alnum:]_]+}}){{.*}} !dbg !13 { //CHECK-NEXT: [[L1:prelude]]: //CHECK-COUNT-03: {{.*}}, !dbg !14 //CHECK-EMPTY: diff --git a/circom/tests/debuginfo/compute.circom b/circom/tests/debuginfo/compute.circom index b79c5512c..083a3d05c 100644 --- a/circom/tests/debuginfo/compute.circom +++ b/circom/tests/debuginfo/compute.circom @@ -29,13 +29,13 @@ component main = A(1); // full lines or to remove the "--match-full-lines" option and surround each check with // {{^}} and {{$}} but it gets messy. -//CHECK-LABEL: define{{.*}} void @A_0_build({ [0 x i256]*, i32 }* %{{[[:alnum:]_]+}}) !dbg !4 { +//CHECK-LABEL: define{{.*}} void @A_0_build({ [0 x i256]*, i32 }* %{{[[:alnum:]_]+}}){{.*}} !dbg !4 { //CHECK-NEXT: [[L1:main]]: //CHECK-COUNT-06: {{.*}}, !dbg !7 //CHECK-NEXT: ret void, !dbg !7 //CHECK-NEXT: } -//CHECK-LABEL: define{{.*}} void @A_0_run([0 x i256]* %{{[[:alnum:]_]+}}) !dbg !8 { +//CHECK-LABEL: define{{.*}} void @A_0_run([0 x i256]* %{{[[:alnum:]_]+}}){{.*}} !dbg !8 { //CHECK-NEXT: [[L01:prelude]]: //CHECK-COUNT-03: {{.*}}, !dbg !9 //CHECK-EMPTY: diff --git a/circom/tests/debuginfo/constraint.circom b/circom/tests/debuginfo/constraint.circom index d0088c823..33bf78d27 100644 --- a/circom/tests/debuginfo/constraint.circom +++ b/circom/tests/debuginfo/constraint.circom @@ -17,13 +17,13 @@ component main = A(); // full lines or to remove the "--match-full-lines" option and surround each check with // {{^}} and {{$}} but it gets messy. -//CHECK-LABEL: define{{.*}} void @A_0_build({ [0 x i256]*, i32 }* %{{[[:alnum:]_]+}}) !dbg !4 { +//CHECK-LABEL: define{{.*}} void @A_0_build({ [0 x i256]*, i32 }* %{{[[:alnum:]_]+}}){{.*}} !dbg !4 { //CHECK-NEXT: [[L1:main]]: //CHECK-COUNT-06: {{.*}}, !dbg !7 //CHECK-NEXT: ret void, !dbg !7 //CHECK-NEXT: } -//CHECK-LABEL: define{{.*}} void @A_0_run([0 x i256]* %{{[[:alnum:]_]+}}) !dbg !8 { +//CHECK-LABEL: define{{.*}} void @A_0_run([0 x i256]* %{{[[:alnum:]_]+}}){{.*}} !dbg !8 { //CHECK-NEXT: [[L1:prelude]]: //CHECK-COUNT-03: {{.*}}, !dbg !9 //CHECK-EMPTY: diff --git a/circom/tests/debuginfo/create_component.circom b/circom/tests/debuginfo/create_component.circom index a8e036903..87db122ff 100644 --- a/circom/tests/debuginfo/create_component.circom +++ b/circom/tests/debuginfo/create_component.circom @@ -21,13 +21,13 @@ component main = A(5); // full lines or to remove the "--match-full-lines" option and surround each check with // {{^}} and {{$}} but it gets messy. -//CHECK-LABEL: define{{.*}} void @B_0_build({ [0 x i256]*, i32 }* %{{[[:alnum:]_]+}}) !dbg !4 { +//CHECK-LABEL: define{{.*}} void @B_0_build({ [0 x i256]*, i32 }* %{{[[:alnum:]_]+}}){{.*}} !dbg !4 { //CHECK-NEXT: [[L1:main]]: //CHECK-COUNT-06: {{.*}}, !dbg !7 //CHECK-NEXT: ret void, !dbg !7 //CHECK-NEXT: } -//CHECK-LABEL: define{{.*}} void @B_0_run([0 x i256]* %{{[[:alnum:]_]+}}) !dbg !8 { +//CHECK-LABEL: define{{.*}} void @B_0_run([0 x i256]* %{{[[:alnum:]_]+}}){{.*}} !dbg !8 { //CHECK-NEXT: [[L1:prelude]]: //CHECK-COUNT-03: {{.*}}, !dbg !9 //CHECK-EMPTY: @@ -38,13 +38,13 @@ component main = A(5); //CHECK-NEXT: ret void, !dbg !9 //CHECK-NEXT: } -//CHECK-LABEL: define{{.*}} void @A_1_build({ [0 x i256]*, i32 }* %{{[[:alnum:]_]+}}) !dbg !10 { +//CHECK-LABEL: define{{.*}} void @A_1_build({ [0 x i256]*, i32 }* %{{[[:alnum:]_]+}}){{.*}} !dbg !10 { //CHECK-NEXT: [[L1:main]]: //CHECK-COUNT-06: {{.*}}, !dbg !11 //CHECK-NEXT: ret void, !dbg !11 //CHECK-NEXT: } -//CHECK-LABEL: define{{.*}} void @A_1_run([0 x i256]* %{{[[:alnum:]_]+}}) !dbg !12 { +//CHECK-LABEL: define{{.*}} void @A_1_run([0 x i256]* %{{[[:alnum:]_]+}}){{.*}} !dbg !12 { //CHECK-NEXT: [[L1:prelude]]: //CHECK-COUNT-03: {{.*}}, !dbg !13 //CHECK-EMPTY: diff --git a/circom/tests/debuginfo/load.circom b/circom/tests/debuginfo/load.circom index 9bfad5f34..33f74890a 100644 --- a/circom/tests/debuginfo/load.circom +++ b/circom/tests/debuginfo/load.circom @@ -26,13 +26,13 @@ component main = A(1); // full lines or to remove the "--match-full-lines" option and surround each check with // {{^}} and {{$}} but it gets messy. -//CHECK-LABEL: define{{.*}} void @A_0_build({ [0 x i256]*, i32 }* %{{[[:alnum:]_]+}}) !dbg !4 { +//CHECK-LABEL: define{{.*}} void @A_0_build({ [0 x i256]*, i32 }* %{{[[:alnum:]_]+}}){{.*}} !dbg !4 { //CHECK-NEXT: [[L1:main]]: //CHECK-COUNT-06: {{.*}}, !dbg !7 //CHECK-NEXT: ret void, !dbg !7 //CHECK-NEXT: } -//CHECK-LABEL: define{{.*}} void @A_0_run([0 x i256]* %{{[[:alnum:]_]+}}) !dbg !8 { +//CHECK-LABEL: define{{.*}} void @A_0_run([0 x i256]* %{{[[:alnum:]_]+}}){{.*}} !dbg !8 { //CHECK-NEXT: [[L1:prelude]]: //CHECK-COUNT-03: {{.*}}, !dbg !9 //CHECK-EMPTY: diff --git a/circom/tests/debuginfo/log.circom b/circom/tests/debuginfo/log.circom index cc94e9901..064281ad7 100644 --- a/circom/tests/debuginfo/log.circom +++ b/circom/tests/debuginfo/log.circom @@ -15,13 +15,13 @@ component main = A(); // full lines or to remove the "--match-full-lines" option and surround each check with // {{^}} and {{$}} but it gets messy. -//CHECK-LABEL: define{{.*}} void @A_0_build({ [0 x i256]*, i32 }* %{{[[:alnum:]_]+}}) !dbg !4 { +//CHECK-LABEL: define{{.*}} void @A_0_build({ [0 x i256]*, i32 }* %{{[[:alnum:]_]+}}){{.*}} !dbg !4 { //CHECK-NEXT: [[L1:main]]: //CHECK-COUNT-05: {{.*}}, !dbg !7 //CHECK-NEXT: ret void, !dbg !7 //CHECK-NEXT: } -//CHECK-LABEL: define{{.*}} void @A_0_run([0 x i256]* %{{[[:alnum:]_]+}}) !dbg !8 { +//CHECK-LABEL: define{{.*}} void @A_0_run([0 x i256]* %{{[[:alnum:]_]+}}){{.*}} !dbg !8 { //CHECK-NEXT: [[L1:prelude]]: //CHECK-COUNT-03: {{.*}}, !dbg !9 //CHECK-EMPTY: diff --git a/circom/tests/debuginfo/loop_and_block.circom b/circom/tests/debuginfo/loop_and_block.circom index 05b47e68b..85cad1b3c 100644 --- a/circom/tests/debuginfo/loop_and_block.circom +++ b/circom/tests/debuginfo/loop_and_block.circom @@ -20,42 +20,57 @@ component main = A(3); // full lines or to remove the "--match-full-lines" option and surround each check with // {{^}} and {{$}} but it gets messy. -//CHECK-LABEL: define{{.*}} void @A_0_build({ [0 x i256]*, i32 }* %{{[[:alnum:]_]+}}) !dbg !4 { -//CHECK-NEXT: [[L1:main]]: +//CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9]+}}([0 x i256]* %lvars, [0 x i256]* %signals, i256* %fix_{{[0-9]+}}, i256* %fix_{{[0-9]+}}){{.*}} !dbg !4 { +//CHECK-NEXT: [[$F_ID_1:..generated..loop.body.[0-9]+]]: +//CHECK-COUNT-01: {{.*}}, !dbg !7 +//CHECK-EMPTY: +//CHECK-NEXT: [[L01:store[0-9]*]]:{{[[:space:]]}}; preds = %[[$F_ID_1]] +//CHECK-COUNT-05: {{.*}}, !dbg !8 +//CHECK-EMPTY: +//CHECK-NEXT: [[L02:store[0-9]*]]:{{[[:space:]]}}; preds = %[[L01]] //CHECK-COUNT-06: {{.*}}, !dbg !7 +//CHECK-EMPTY: +//CHECK-NEXT: return{{[0-9]*}}:{{[[:space:]]}}; preds = %[[L02]] //CHECK-NEXT: ret void, !dbg !7 //CHECK-NEXT: } -//CHECK-LABEL: define{{.*}} void @A_0_run([0 x i256]* %{{[[:alnum:]_]+}}) !dbg !8 { +//CHECK-LABEL: define{{.*}} void @A_0_build({ [0 x i256]*, i32 }* %{{[[:alnum:]_]+}}){{.*}} !dbg !9 { +//CHECK-NEXT: [[L1:main]]: +//CHECK-COUNT-06: {{.*}}, !dbg !10 +//CHECK-NEXT: ret void, !dbg !10 +//CHECK-NEXT: } + +//CHECK-LABEL: define{{.*}} void @A_0_run([0 x i256]* %{{[[:alnum:]_]+}}){{.*}} !dbg !11 { //CHECK-NEXT: [[L01:prelude]]: -//CHECK-COUNT-03: {{.*}}, !dbg !9 +//CHECK-COUNT-03: {{.*}}, !dbg !12 //CHECK-EMPTY: //CHECK-NEXT: [[L02:store[0-9]*]]:{{[[:space:]]}}; preds = %[[L01]] -//CHECK-COUNT-03: {{.*}}, !dbg !9 +//CHECK-COUNT-03: {{.*}}, !dbg !12 //CHECK-EMPTY: //CHECK-NEXT: [[L03:store[0-9]*]]:{{[[:space:]]}}; preds = %[[L02]] -//CHECK-COUNT-03: {{.*}}, !dbg !10 +//CHECK-COUNT-03: {{.*}}, !dbg !13 //CHECK-EMPTY: //CHECK-NEXT: [[L04:unrolled_loop[0-9]*]]:{{[[:space:]]}}; preds = %[[L03]] -//CHECK-COUNT-04: {{.*}}, !dbg !11 -//CHECK-COUNT-02: {{.*}}, !dbg !10 -//CHECK-COUNT-04: {{.*}}, !dbg !11 -//CHECK-COUNT-02: {{.*}}, !dbg !10 -//CHECK-COUNT-04: {{.*}}, !dbg !11 -//CHECK-COUNT-02: {{.*}}, !dbg !10 -//CHECK-NEXT: br label %prologue, !dbg !10 +//CHECK-COUNT-03: {{.*}}, !dbg !13 +//CHECK-NEXT: call void @[[$F_ID_1]]([0 x i256]* %{{[[:alnum:]_]+}}, [0 x i256]* %{{[[:alnum:]_]+}}, i256* %{{[[:alnum:]_]+}}, i256* %{{[[:alnum:]_]+}}), !dbg !13 +//CHECK-COUNT-03: {{.*}}, !dbg !13 +//CHECK-NEXT: call void @[[$F_ID_1]]([0 x i256]* %{{[[:alnum:]_]+}}, [0 x i256]* %{{[[:alnum:]_]+}}, i256* %{{[[:alnum:]_]+}}, i256* %{{[[:alnum:]_]+}}), !dbg !13 +//CHECK-COUNT-03: {{.*}}, !dbg !13 +//CHECK-NEXT: call void @[[$F_ID_1]]([0 x i256]* %{{[[:alnum:]_]+}}, [0 x i256]* %{{[[:alnum:]_]+}}, i256* %{{[[:alnum:]_]+}}, i256* %{{[[:alnum:]_]+}}), !dbg !13 +//CHECK-NEXT: br label %prologue, !dbg !13 //CHECK-EMPTY: //CHECK-NEXT: [[L05:prologue]]:{{[[:space:]]}}; preds = %[[L04]] -//CHECK-NEXT: ret void, !dbg !10 +//CHECK-NEXT: ret void, !dbg !13 //CHECK-NEXT: } //CHECK-LABEL: !llvm.dbg.cu = !{!1} //CHECK: !1 = distinct !DICompileUnit({{.*}}file: !2{{.*}}) //CHECK: !2 = !DIFile(filename:{{.*}}loop_and_block.circom{{.*}}) -//CHECK: !4 = distinct !DISubprogram(name: "A", linkageName: "A_0_build", scope: null, file: !2, line: 5, {{.*}}unit: !1{{.*}}) -//CHECK: !7 = !DILocation(line: 5, scope: !4) -//CHECK: !8 = distinct !DISubprogram(name: "A", linkageName: "A_0_run", scope: null, file: !2, line: 5, {{.*}}unit: !1{{.*}}) -//CHECK: !9 = !DILocation(line: 5, scope: !8) -//CHECK: !10 = !DILocation(line: 9, scope: !8) -//CHECK: !11 = !DILocation(line: 10, scope: !8) - +//CHECK: !4 = distinct !DISubprogram(name: "[[$F_ID_1]]", linkageName: "[[$F_ID_1]]", scope: null, file: !2, line: 9, {{.*}}unit: !1{{.*}}) +//CHECK: !7 = !DILocation(line: 9, scope: !4) +//CHECK: !8 = !DILocation(line: 10, scope: !4) +//CHECK: !9 = distinct !DISubprogram(name: "A", linkageName: "A_0_build", scope: null, file: !2, line: 5, {{.*}}unit: !1{{.*}}) +//CHECK: !10 = !DILocation(line: 5, scope: !9) +//CHECK: !11 = distinct !DISubprogram(name: "A", linkageName: "A_0_run", scope: null, file: !2, line: 5, {{.*}}unit: !1{{.*}}) +//CHECK: !12 = !DILocation(line: 5, scope: !11) +//CHECK: !13 = !DILocation(line: 9, scope: !11)