diff --git a/circom/tests/subcmps/conv_map2idx_C.circom b/circom/tests/subcmps/conv_map2idx_C.circom new file mode 100644 index 000000000..e598c3981 --- /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 589e46cc4..dac33497a 100644 --- a/circuit_passes/src/passes/loop_unroll/mod.rs +++ b/circuit_passes/src/passes/loop_unroll/mod.rs @@ -84,7 +84,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.