diff --git a/circom/tests/calls/arena_missing_val.circom b/circom/tests/calls/arena_missing_val.circom index 58ed3acc1..12cc313e9 100644 --- a/circom/tests/calls/arena_missing_val.circom +++ b/circom/tests/calls/arena_missing_val.circom @@ -15,13 +15,14 @@ function long_sub(k, a, b) { return d; } -// %0 (i.e. arena) = [ k, out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7], out[8], -// i, sub[0], sub[1], sub[2], sub[3], sub[4], sub[5], sub[6], sub[7], sub[8], -// mul[0], mul[1], mul[2], mul[3], mul[4], mul[5], mul[6], mul[7], mul[8], j ] -function long_div(k) { +// %0 (i.e. arena) = [ k, in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7], in[8], +// out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7], out[8], i, +// sub[0], sub[1], sub[2], sub[3], sub[4], sub[5], sub[6], sub[7], sub[8], mul[0], +// mul[1], mul[2], mul[3], mul[4], mul[5], mul[6], mul[7], mul[8], j ] +function long_div(k, in) { var out[9]; for (var i = k; i >= 0; i--) { // 5 iterations b/c k=4 - var sub[9]; + var sub[9] = in; var mul[9] = out; for (var j = 0; j <= k; j++) { // 5 iterations b/c k=4 sub[i + j] = mul[j]; @@ -32,28 +33,40 @@ function long_div(k) { } template BigMod() { + signal input in[9]; signal output out[9]; - out <-- long_div(4); + out <-- long_div(4, in); } component main = BigMod(); //NOTE: There is some instability in where [[$F_ID_1]] will be generated, possibly due to // the LLVM "add_merge_functions_pass" in which case there's no obvious way to address it. -// Instead, the definition of [[$F_ID_1]] is elided and the name is first defined within -// the 'long_div_' function. Also, the entire header of this first generated function must -// be matched on one line. +// Sometimes it appears as the very first function and sometimes between the definitions +// of long_sub() and long_div(). Instead, the definition of [[$F_ID_1]] is elided and the +// name is first defined within the 'long_div_' function. Also, the entire header of this +// first generated function must be matched on one line. // //CHECK-LABEL: define{{.*}} void @..generated..loop.body.{{[0-9a-zA-Z_\.]+}}([0 x i256]* %lvars, [0 x i256]* %signals, i256* %var_0, i256* %var_1, i256* %var_2, i256* %var_3, i256* %var_4){{.*}} { //CHECK-NEXT: ..generated..loop.body.[[$F_ID_2:[0-9a-zA-Z_\.]+]]: //CHECK-NEXT: br label %branch1 //CHECK-EMPTY: //CHECK-NEXT: branch1: -//CHECK-NEXT: br i1 true, label %if.then, label %if.else +//CHECK-NEXT: %[[T000:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %var_0, i32 0 +//CHECK-NEXT: %[[T001:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[T000]], align 4 +//CHECK-NEXT: %[[T002:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %var_1, i32 0 +//CHECK-NEXT: %[[T003:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[T002]], align 4 +//CHECK-NEXT: %[[T999:[0-9a-zA-Z_\.]+]] = call i1 @fr_ge(i256 %[[T001]], i256 %[[T003]]) +//CHECK-NEXT: br i1 %[[T999]], label %if.then, label %if.else //CHECK-EMPTY: //CHECK-NEXT: if.then: //CHECK-NEXT: %[[T004:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %var_2, i32 0 -//CHECK-NEXT: store i256 0, i256* %[[T004]], align 4 +//CHECK-NEXT: %[[T005:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %var_3, i32 0 +//CHECK-NEXT: %[[T006:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[T005]], align 4 +//CHECK-NEXT: %[[T007:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %var_4, i32 0 +//CHECK-NEXT: %[[T008:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[T007]], align 4 +//CHECK-NEXT: %[[T998:[0-9a-zA-Z_\.]+]] = call i256 @fr_sub(i256 %[[T006]], i256 %[[T008]]) +//CHECK-NEXT: store i256 %[[T998]], i256* %[[T004]], align 4 //CHECK-NEXT: br label %if.merge //CHECK-EMPTY: //CHECK-NEXT: if.else: @@ -179,78 +192,98 @@ component main = BigMod(); //CHECK-NEXT: br label %store1 //CHECK-EMPTY: //CHECK-NEXT: store1: -//CHECK-NEXT: %[[T001:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 1 +//CHECK-NEXT: %[[T001:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 10 //CHECK-NEXT: store i256 0, i256* %[[T001]], align 4 //CHECK-NEXT: br label %store2 //CHECK-EMPTY: //CHECK-NEXT: store2: -//CHECK-NEXT: %[[T002:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 2 +//CHECK-NEXT: %[[T002:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 11 //CHECK-NEXT: store i256 0, i256* %[[T002]], align 4 //CHECK-NEXT: br label %store3 //CHECK-EMPTY: //CHECK-NEXT: store3: -//CHECK-NEXT: %[[T003:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 3 +//CHECK-NEXT: %[[T003:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 12 //CHECK-NEXT: store i256 0, i256* %[[T003]], align 4 //CHECK-NEXT: br label %store4 //CHECK-EMPTY: //CHECK-NEXT: store4: -//CHECK-NEXT: %[[T004:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 4 +//CHECK-NEXT: %[[T004:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 13 //CHECK-NEXT: store i256 0, i256* %[[T004]], align 4 //CHECK-NEXT: br label %store5 //CHECK-EMPTY: //CHECK-NEXT: store5: -//CHECK-NEXT: %[[T005:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 5 +//CHECK-NEXT: %[[T005:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 14 //CHECK-NEXT: store i256 0, i256* %[[T005]], align 4 //CHECK-NEXT: br label %store6 //CHECK-EMPTY: //CHECK-NEXT: store6: -//CHECK-NEXT: %[[T006:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 6 +//CHECK-NEXT: %[[T006:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 15 //CHECK-NEXT: store i256 0, i256* %[[T006]], align 4 //CHECK-NEXT: br label %store7 //CHECK-EMPTY: //CHECK-NEXT: store7: -//CHECK-NEXT: %[[T007:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 7 +//CHECK-NEXT: %[[T007:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 16 //CHECK-NEXT: store i256 0, i256* %[[T007]], align 4 //CHECK-NEXT: br label %store8 //CHECK-EMPTY: //CHECK-NEXT: store8: -//CHECK-NEXT: %[[T008:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 8 +//CHECK-NEXT: %[[T008:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 17 //CHECK-NEXT: store i256 0, i256* %[[T008]], align 4 //CHECK-NEXT: br label %store9 //CHECK-EMPTY: //CHECK-NEXT: store9: -//CHECK-NEXT: %[[T009:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 9 +//CHECK-NEXT: %[[T009:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 18 //CHECK-NEXT: store i256 0, i256* %[[T009]], align 4 //CHECK-NEXT: br label %store10 //CHECK-EMPTY: //CHECK-NEXT: store10: -//CHECK-NEXT: %[[T010:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 10 +//CHECK-NEXT: %[[T010:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 19 //CHECK-NEXT: %[[T011:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 0 //CHECK-NEXT: %[[T012:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[T011]], align 4 //CHECK-NEXT: store i256 %[[T012]], i256* %[[T010]], align 4 //CHECK-NEXT: br label %unrolled_loop11 //CHECK-EMPTY: //CHECK-NEXT: unrolled_loop11: -//CHECK-NEXT: %[[T013:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 11 -//CHECK-NEXT: store i256 0, i256* %[[T013]], align 4 -//CHECK-NEXT: %[[T014:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 12 -//CHECK-NEXT: store i256 0, i256* %[[T014]], align 4 -//CHECK-NEXT: %[[T015:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 13 -//CHECK-NEXT: store i256 0, i256* %[[T015]], align 4 -//CHECK-NEXT: %[[T016:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 14 -//CHECK-NEXT: store i256 0, i256* %[[T016]], align 4 -//CHECK-NEXT: %[[T017:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 15 -//CHECK-NEXT: store i256 0, i256* %[[T017]], align 4 -//CHECK-NEXT: %[[T018:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 16 -//CHECK-NEXT: store i256 0, i256* %[[T018]], align 4 -//CHECK-NEXT: %[[T019:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 17 -//CHECK-NEXT: store i256 0, i256* %[[T019]], align 4 -//CHECK-NEXT: %[[T020:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 18 -//CHECK-NEXT: store i256 0, i256* %[[T020]], align 4 -//CHECK-NEXT: %[[T021:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 19 -//CHECK-NEXT: store i256 0, i256* %[[T021]], align 4 -//CHECK-NEXT: %[[T022:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 20 -//CHECK-NEXT: %[[T023:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 1 +//CHECK-NEXT: %[[T13:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 20 +//CHECK-NEXT: %[[T14:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 1 +//CHECK-NEXT: %[[CPY_SRC_100:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T14]], i32 0 +//CHECK-NEXT: %[[CPY_DST_100:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T13]], i32 0 +//CHECK-NEXT: %[[CPY_VAL_100:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_100]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_100]], i256* %[[CPY_DST_100]], align 4 +//CHECK-NEXT: %[[CPY_SRC_101:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T14]], i32 1 +//CHECK-NEXT: %[[CPY_DST_101:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T13]], i32 1 +//CHECK-NEXT: %[[CPY_VAL_101:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_101]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_101]], i256* %[[CPY_DST_101]], align 4 +//CHECK-NEXT: %[[CPY_SRC_102:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T14]], i32 2 +//CHECK-NEXT: %[[CPY_DST_102:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T13]], i32 2 +//CHECK-NEXT: %[[CPY_VAL_102:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_102]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_102]], i256* %[[CPY_DST_102]], align 4 +//CHECK-NEXT: %[[CPY_SRC_103:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T14]], i32 3 +//CHECK-NEXT: %[[CPY_DST_103:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T13]], i32 3 +//CHECK-NEXT: %[[CPY_VAL_103:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_103]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_103]], i256* %[[CPY_DST_103]], align 4 +//CHECK-NEXT: %[[CPY_SRC_104:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T14]], i32 4 +//CHECK-NEXT: %[[CPY_DST_104:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T13]], i32 4 +//CHECK-NEXT: %[[CPY_VAL_104:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_104]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_104]], i256* %[[CPY_DST_104]], align 4 +//CHECK-NEXT: %[[CPY_SRC_105:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T14]], i32 5 +//CHECK-NEXT: %[[CPY_DST_105:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T13]], i32 5 +//CHECK-NEXT: %[[CPY_VAL_105:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_105]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_105]], i256* %[[CPY_DST_105]], align 4 +//CHECK-NEXT: %[[CPY_SRC_106:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T14]], i32 6 +//CHECK-NEXT: %[[CPY_DST_106:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T13]], i32 6 +//CHECK-NEXT: %[[CPY_VAL_106:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_106]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_106]], i256* %[[CPY_DST_106]], align 4 +//CHECK-NEXT: %[[CPY_SRC_107:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T14]], i32 7 +//CHECK-NEXT: %[[CPY_DST_107:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T13]], i32 7 +//CHECK-NEXT: %[[CPY_VAL_107:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_107]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_107]], i256* %[[CPY_DST_107]], align 4 +//CHECK-NEXT: %[[CPY_SRC_108:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T14]], i32 8 +//CHECK-NEXT: %[[CPY_DST_108:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T13]], i32 8 +//CHECK-NEXT: %[[CPY_VAL_108:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_108]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_108]], i256* %[[CPY_DST_108]], align 4 +//CHECK-NEXT: %[[T022:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 29 +//CHECK-NEXT: %[[T023:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 10 //CHECK-NEXT: %[[CPY_SRC_0:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T023]], i32 0 //CHECK-NEXT: %[[CPY_DST_0:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T022]], i32 0 //CHECK-NEXT: %[[CPY_VAL_0:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_0]], align 4 @@ -287,37 +320,37 @@ component main = BigMod(); //CHECK-NEXT: %[[CPY_DST_8:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T022]], i32 8 //CHECK-NEXT: %[[CPY_VAL_8:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_8]], align 4 //CHECK-NEXT: store i256 %[[CPY_VAL_8]], i256* %[[CPY_DST_8]], align 4 -//CHECK-NEXT: %[[T024:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 29 +//CHECK-NEXT: %[[T024:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 38 //CHECK-NEXT: store i256 0, i256* %[[T024]], align 4 //CHECK-NEXT: %[[T025:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T026:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T027:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T026]], i32 0, i256 15 +//CHECK-NEXT: %[[T027:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T026]], i32 0, i256 24 //CHECK-NEXT: %[[T028:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T029:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T028]], i32 0, i256 20 +//CHECK-NEXT: %[[T029:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T028]], i32 0, i256 29 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1:[0-9a-zA-Z_\.]+]]([0 x i256]* %[[T025]], [0 x i256]* null, i256* %[[T027]], i256* %[[T029]]) //CHECK-NEXT: %[[T030:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T031:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T032:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T031]], i32 0, i256 16 +//CHECK-NEXT: %[[T032:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T031]], i32 0, i256 25 //CHECK-NEXT: %[[T033:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T034:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T033]], i32 0, i256 21 +//CHECK-NEXT: %[[T034:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T033]], i32 0, i256 30 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %[[T030]], [0 x i256]* null, i256* %[[T032]], i256* %[[T034]]) //CHECK-NEXT: %[[T035:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T036:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T037:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T036]], i32 0, i256 17 +//CHECK-NEXT: %[[T037:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T036]], i32 0, i256 26 //CHECK-NEXT: %[[T038:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T039:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T038]], i32 0, i256 22 +//CHECK-NEXT: %[[T039:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T038]], i32 0, i256 31 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %[[T035]], [0 x i256]* null, i256* %[[T037]], i256* %[[T039]]) //CHECK-NEXT: %[[T040:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T041:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T042:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T041]], i32 0, i256 18 +//CHECK-NEXT: %[[T042:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T041]], i32 0, i256 27 //CHECK-NEXT: %[[T043:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T044:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T043]], i32 0, i256 23 +//CHECK-NEXT: %[[T044:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T043]], i32 0, i256 32 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %[[T040]], [0 x i256]* null, i256* %[[T042]], i256* %[[T044]]) //CHECK-NEXT: %[[T045:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T046:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T047:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T046]], i32 0, i256 19 +//CHECK-NEXT: %[[T047:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T046]], i32 0, i256 28 //CHECK-NEXT: %[[T048:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T049:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T048]], i32 0, i256 24 +//CHECK-NEXT: %[[T049:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T048]], i32 0, i256 33 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %[[T045]], [0 x i256]* null, i256* %[[T047]], i256* %[[T049]]) //CHECK-NEXT: %[[CALL_ARENA:[0-9a-zA-Z_\.]+]] = alloca [29 x i256], align 8 //CHECK-NEXT: %[[T050:[0-9a-zA-Z_\.]+]] = getelementptr [29 x i256], [29 x i256]* %[[CALL_ARENA]], i32 0, i32 0 @@ -325,7 +358,7 @@ component main = BigMod(); //CHECK-NEXT: %[[T052:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[T051]], align 4 //CHECK-NEXT: store i256 %[[T052]], i256* %[[T050]], align 4 //CHECK-NEXT: %[[T053:[0-9a-zA-Z_\.]+]] = getelementptr [29 x i256], [29 x i256]* %[[CALL_ARENA]], i32 0, i32 1 -//CHECK-NEXT: %[[T054:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 1 +//CHECK-NEXT: %[[T054:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 10 //CHECK-NEXT: %[[CPY_SRC_018:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T054]], i32 0 //CHECK-NEXT: %[[CPY_DST_019:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T053]], i32 0 //CHECK-NEXT: %[[CPY_VAL_020:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_018]], align 4 @@ -363,7 +396,7 @@ component main = BigMod(); //CHECK-NEXT: %[[CPY_VAL_844:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_842]], align 4 //CHECK-NEXT: store i256 %[[CPY_VAL_844]], i256* %[[CPY_DST_843]], align 4 //CHECK-NEXT: %[[T055:[0-9a-zA-Z_\.]+]] = getelementptr [29 x i256], [29 x i256]* %[[CALL_ARENA]], i32 0, i32 10 -//CHECK-NEXT: %[[T056:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 11 +//CHECK-NEXT: %[[T056:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 20 //CHECK-NEXT: %[[CPY_SRC_045:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T056]], i32 0 //CHECK-NEXT: %[[CPY_DST_046:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T055]], i32 0 //CHECK-NEXT: %[[CPY_VAL_047:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_045]], align 4 @@ -402,7 +435,7 @@ component main = BigMod(); //CHECK-NEXT: store i256 %[[CPY_VAL_871]], i256* %[[CPY_DST_870]], align 4 //CHECK-NEXT: %[[T057:[0-9a-zA-Z_\.]+]] = bitcast [29 x i256]* %[[CALL_ARENA]] to i256* //CHECK-NEXT: %[[T994:[0-9a-zA-Z_\.]+]] = call i256* @long_sub_[[$F_ID_3]](i256* %[[T057]]) -//CHECK-NEXT: %[[T058:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 1 +//CHECK-NEXT: %[[T058:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 10 //CHECK-NEXT: %[[CPY_SRC_072:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T994]], i32 0 //CHECK-NEXT: %[[CPY_DST_073:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T058]], i32 0 //CHECK-NEXT: %[[CPY_VAL_074:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_072]], align 4 @@ -439,28 +472,48 @@ component main = BigMod(); //CHECK-NEXT: %[[CPY_DST_897:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T058]], i32 8 //CHECK-NEXT: %[[CPY_VAL_898:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_896]], align 4 //CHECK-NEXT: store i256 %[[CPY_VAL_898]], i256* %[[CPY_DST_897]], align 4 -//CHECK-NEXT: %[[T059:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 10 +//CHECK-NEXT: %[[T059:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 19 //CHECK-NEXT: store i256 3, i256* %[[T059]], align 4 -//CHECK-NEXT: %[[T060:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 11 -//CHECK-NEXT: store i256 0, i256* %[[T060]], align 4 -//CHECK-NEXT: %[[T061:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 12 -//CHECK-NEXT: store i256 0, i256* %[[T061]], align 4 -//CHECK-NEXT: %[[T062:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 13 -//CHECK-NEXT: store i256 0, i256* %[[T062]], align 4 -//CHECK-NEXT: %[[T063:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 14 -//CHECK-NEXT: store i256 0, i256* %[[T063]], align 4 -//CHECK-NEXT: %[[T064:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 15 -//CHECK-NEXT: store i256 0, i256* %[[T064]], align 4 -//CHECK-NEXT: %[[T065:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 16 -//CHECK-NEXT: store i256 0, i256* %[[T065]], align 4 -//CHECK-NEXT: %[[T066:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 17 -//CHECK-NEXT: store i256 0, i256* %[[T066]], align 4 -//CHECK-NEXT: %[[T067:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 18 -//CHECK-NEXT: store i256 0, i256* %[[T067]], align 4 -//CHECK-NEXT: %[[T068:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 19 -//CHECK-NEXT: store i256 0, i256* %[[T068]], align 4 -//CHECK-NEXT: %[[T069:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 20 -//CHECK-NEXT: %[[T070:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 1 +//CHECK-NEXT: %[[T253:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 20 +//CHECK-NEXT: %[[T254:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 1 +//CHECK-NEXT: %[[CPY_SRC_0126:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T254]], i32 0 +//CHECK-NEXT: %[[CPY_DST_0127:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T253]], i32 0 +//CHECK-NEXT: %[[CPY_VAL_0128:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_0126]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_0128]], i256* %[[CPY_DST_0127]], align 4 +//CHECK-NEXT: %[[CPY_SRC_1129:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T254]], i32 1 +//CHECK-NEXT: %[[CPY_DST_1130:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T253]], i32 1 +//CHECK-NEXT: %[[CPY_VAL_1131:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_1129]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_1131]], i256* %[[CPY_DST_1130]], align 4 +//CHECK-NEXT: %[[CPY_SRC_2132:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T254]], i32 2 +//CHECK-NEXT: %[[CPY_DST_2133:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T253]], i32 2 +//CHECK-NEXT: %[[CPY_VAL_2134:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_2132]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_2134]], i256* %[[CPY_DST_2133]], align 4 +//CHECK-NEXT: %[[CPY_SRC_3135:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T254]], i32 3 +//CHECK-NEXT: %[[CPY_DST_3136:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T253]], i32 3 +//CHECK-NEXT: %[[CPY_VAL_3137:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_3135]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_3137]], i256* %[[CPY_DST_3136]], align 4 +//CHECK-NEXT: %[[CPY_SRC_4138:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T254]], i32 4 +//CHECK-NEXT: %[[CPY_DST_4139:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T253]], i32 4 +//CHECK-NEXT: %[[CPY_VAL_4140:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_4138]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_4140]], i256* %[[CPY_DST_4139]], align 4 +//CHECK-NEXT: %[[CPY_SRC_5141:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T254]], i32 5 +//CHECK-NEXT: %[[CPY_DST_5142:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T253]], i32 5 +//CHECK-NEXT: %[[CPY_VAL_5143:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_5141]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_5143]], i256* %[[CPY_DST_5142]], align 4 +//CHECK-NEXT: %[[CPY_SRC_6144:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T254]], i32 6 +//CHECK-NEXT: %[[CPY_DST_6145:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T253]], i32 6 +//CHECK-NEXT: %[[CPY_VAL_6146:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_6144]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_6146]], i256* %[[CPY_DST_6145]], align 4 +//CHECK-NEXT: %[[CPY_SRC_7147:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T254]], i32 7 +//CHECK-NEXT: %[[CPY_DST_7148:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T253]], i32 7 +//CHECK-NEXT: %[[CPY_VAL_7149:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_7147]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_7149]], i256* %[[CPY_DST_7148]], align 4 +//CHECK-NEXT: %[[CPY_SRC_8150:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T254]], i32 8 +//CHECK-NEXT: %[[CPY_DST_8151:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T253]], i32 8 +//CHECK-NEXT: %[[CPY_VAL_8152:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_8150]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_8152]], i256* %[[CPY_DST_8151]], align 4 +//CHECK-NEXT: %[[T069:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 29 +//CHECK-NEXT: %[[T070:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 10 //CHECK-NEXT: %[[CPY_SRC_099:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T070]], i32 0 //CHECK-NEXT: %[[CPY_DST_0100:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T069]], i32 0 //CHECK-NEXT: %[[CPY_VAL_0101:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_099]], align 4 @@ -497,37 +550,37 @@ component main = BigMod(); //CHECK-NEXT: %[[CPY_DST_8124:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T069]], i32 8 //CHECK-NEXT: %[[CPY_VAL_8125:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_8123]], align 4 //CHECK-NEXT: store i256 %[[CPY_VAL_8125]], i256* %[[CPY_DST_8124]], align 4 -//CHECK-NEXT: %[[T071:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 29 +//CHECK-NEXT: %[[T071:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 38 //CHECK-NEXT: store i256 0, i256* %[[T071]], align 4 //CHECK-NEXT: %[[T072:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T073:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T074:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T073]], i32 0, i256 14 +//CHECK-NEXT: %[[T074:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T073]], i32 0, i256 23 //CHECK-NEXT: %[[T075:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T076:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T075]], i32 0, i256 20 +//CHECK-NEXT: %[[T076:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T075]], i32 0, i256 29 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %[[T072]], [0 x i256]* null, i256* %[[T074]], i256* %[[T076]]) //CHECK-NEXT: %[[T077:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T078:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T079:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T078]], i32 0, i256 15 +//CHECK-NEXT: %[[T079:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T078]], i32 0, i256 24 //CHECK-NEXT: %[[T080:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T081:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T080]], i32 0, i256 21 +//CHECK-NEXT: %[[T081:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T080]], i32 0, i256 30 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %[[T077]], [0 x i256]* null, i256* %[[T079]], i256* %[[T081]]) //CHECK-NEXT: %[[T082:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T083:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T084:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T083]], i32 0, i256 16 +//CHECK-NEXT: %[[T084:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T083]], i32 0, i256 25 //CHECK-NEXT: %[[T085:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T086:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T085]], i32 0, i256 22 +//CHECK-NEXT: %[[T086:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T085]], i32 0, i256 31 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %[[T082]], [0 x i256]* null, i256* %[[T084]], i256* %[[T086]]) //CHECK-NEXT: %[[T087:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T088:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T089:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T088]], i32 0, i256 17 +//CHECK-NEXT: %[[T089:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T088]], i32 0, i256 26 //CHECK-NEXT: %[[T090:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T091:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T090]], i32 0, i256 23 +//CHECK-NEXT: %[[T091:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T090]], i32 0, i256 32 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %[[T087]], [0 x i256]* null, i256* %[[T089]], i256* %[[T091]]) //CHECK-NEXT: %[[T092:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T093:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T094:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T093]], i32 0, i256 18 +//CHECK-NEXT: %[[T094:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T093]], i32 0, i256 27 //CHECK-NEXT: %[[T095:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T096:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T095]], i32 0, i256 24 +//CHECK-NEXT: %[[T096:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T095]], i32 0, i256 33 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %[[T092]], [0 x i256]* null, i256* %[[T094]], i256* %[[T096]]) //CHECK-NEXT: %[[CALL_ARENA146:[0-9a-zA-Z_\.]+]] = alloca [29 x i256], align 8 //CHECK-NEXT: %[[T097:[0-9a-zA-Z_\.]+]] = getelementptr [29 x i256], [29 x i256]* %[[CALL_ARENA146]], i32 0, i32 0 @@ -535,7 +588,7 @@ component main = BigMod(); //CHECK-NEXT: %[[T099:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[T098]], align 4 //CHECK-NEXT: store i256 %[[T099]], i256* %[[T097]], align 4 //CHECK-NEXT: %[[T100:[0-9a-zA-Z_\.]+]] = getelementptr [29 x i256], [29 x i256]* %[[CALL_ARENA146]], i32 0, i32 1 -//CHECK-NEXT: %[[T101:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 1 +//CHECK-NEXT: %[[T101:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 10 //CHECK-NEXT: %[[CPY_SRC_0147:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T101]], i32 0 //CHECK-NEXT: %[[CPY_DST_0148:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T100]], i32 0 //CHECK-NEXT: %[[CPY_VAL_0149:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_0147]], align 4 @@ -573,7 +626,7 @@ component main = BigMod(); //CHECK-NEXT: %[[CPY_VAL_8173:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_8171]], align 4 //CHECK-NEXT: store i256 %[[CPY_VAL_8173]], i256* %[[CPY_DST_8172]], align 4 //CHECK-NEXT: %[[T102:[0-9a-zA-Z_\.]+]] = getelementptr [29 x i256], [29 x i256]* %[[CALL_ARENA146]], i32 0, i32 10 -//CHECK-NEXT: %[[T103:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 11 +//CHECK-NEXT: %[[T103:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 20 //CHECK-NEXT: %[[CPY_SRC_0174:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T103]], i32 0 //CHECK-NEXT: %[[CPY_DST_0175:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T102]], i32 0 //CHECK-NEXT: %[[CPY_VAL_0176:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_0174]], align 4 @@ -612,7 +665,7 @@ component main = BigMod(); //CHECK-NEXT: store i256 %[[CPY_VAL_8200]], i256* %[[CPY_DST_8199]], align 4 //CHECK-NEXT: %[[T104:[0-9a-zA-Z_\.]+]] = bitcast [29 x i256]* %[[CALL_ARENA146]] to i256* //CHECK-NEXT: %[[T995:[0-9a-zA-Z_\.]+]] = call i256* @long_sub_[[$F_ID_3]](i256* %[[T104]]) -//CHECK-NEXT: %[[T105:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 1 +//CHECK-NEXT: %[[T105:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 10 //CHECK-NEXT: %[[CPY_SRC_0202:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T995]], i32 0 //CHECK-NEXT: %[[CPY_DST_0203:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T105]], i32 0 //CHECK-NEXT: %[[CPY_VAL_0204:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_0202]], align 4 @@ -649,28 +702,48 @@ component main = BigMod(); //CHECK-NEXT: %[[CPY_DST_8227:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T105]], i32 8 //CHECK-NEXT: %[[CPY_VAL_8228:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_8226]], align 4 //CHECK-NEXT: store i256 %[[CPY_VAL_8228]], i256* %[[CPY_DST_8227]], align 4 -//CHECK-NEXT: %[[T106:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 10 +//CHECK-NEXT: %[[T106:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 19 //CHECK-NEXT: store i256 2, i256* %[[T106]], align 4 -//CHECK-NEXT: %[[T107:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 11 -//CHECK-NEXT: store i256 0, i256* %[[T107]], align 4 -//CHECK-NEXT: %[[T108:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 12 -//CHECK-NEXT: store i256 0, i256* %[[T108]], align 4 -//CHECK-NEXT: %[[T109:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 13 -//CHECK-NEXT: store i256 0, i256* %[[T109]], align 4 -//CHECK-NEXT: %[[T110:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 14 -//CHECK-NEXT: store i256 0, i256* %[[T110]], align 4 -//CHECK-NEXT: %[[T111:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 15 -//CHECK-NEXT: store i256 0, i256* %[[T111]], align 4 -//CHECK-NEXT: %[[T112:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 16 -//CHECK-NEXT: store i256 0, i256* %[[T112]], align 4 -//CHECK-NEXT: %[[T113:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 17 -//CHECK-NEXT: store i256 0, i256* %[[T113]], align 4 -//CHECK-NEXT: %[[T114:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 18 -//CHECK-NEXT: store i256 0, i256* %[[T114]], align 4 -//CHECK-NEXT: %[[T115:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 19 -//CHECK-NEXT: store i256 0, i256* %[[T115]], align 4 -//CHECK-NEXT: %[[T116:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 20 -//CHECK-NEXT: %[[T117:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 1 +//CHECK-NEXT: %[[T293:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 20 +//CHECK-NEXT: %[[T294:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 1 +//CHECK-NEXT: %[[CPY_SRC_0283:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T294]], i32 0 +//CHECK-NEXT: %[[CPY_DST_0284:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T293]], i32 0 +//CHECK-NEXT: %[[CPY_VAL_0285:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_0283]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_0285]], i256* %[[CPY_DST_0284]], align 4 +//CHECK-NEXT: %[[CPY_SRC_1286:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T294]], i32 1 +//CHECK-NEXT: %[[CPY_DST_1287:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T293]], i32 1 +//CHECK-NEXT: %[[CPY_VAL_1288:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_1286]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_1288]], i256* %[[CPY_DST_1287]], align 4 +//CHECK-NEXT: %[[CPY_SRC_2289:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T294]], i32 2 +//CHECK-NEXT: %[[CPY_DST_2290:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T293]], i32 2 +//CHECK-NEXT: %[[CPY_VAL_2291:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_2289]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_2291]], i256* %[[CPY_DST_2290]], align 4 +//CHECK-NEXT: %[[CPY_SRC_3292:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T294]], i32 3 +//CHECK-NEXT: %[[CPY_DST_3293:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T293]], i32 3 +//CHECK-NEXT: %[[CPY_VAL_3294:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_3292]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_3294]], i256* %[[CPY_DST_3293]], align 4 +//CHECK-NEXT: %[[CPY_SRC_4295:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T294]], i32 4 +//CHECK-NEXT: %[[CPY_DST_4296:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T293]], i32 4 +//CHECK-NEXT: %[[CPY_VAL_4297:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_4295]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_4297]], i256* %[[CPY_DST_4296]], align 4 +//CHECK-NEXT: %[[CPY_SRC_5298:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T294]], i32 5 +//CHECK-NEXT: %[[CPY_DST_5299:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T293]], i32 5 +//CHECK-NEXT: %[[CPY_VAL_5300:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_5298]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_5300]], i256* %[[CPY_DST_5299]], align 4 +//CHECK-NEXT: %[[CPY_SRC_6301:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T294]], i32 6 +//CHECK-NEXT: %[[CPY_DST_6302:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T293]], i32 6 +//CHECK-NEXT: %[[CPY_VAL_6303:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_6301]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_6303]], i256* %[[CPY_DST_6302]], align 4 +//CHECK-NEXT: %[[CPY_SRC_7304:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T294]], i32 7 +//CHECK-NEXT: %[[CPY_DST_7305:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T293]], i32 7 +//CHECK-NEXT: %[[CPY_VAL_7306:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_7304]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_7306]], i256* %[[CPY_DST_7305]], align 4 +//CHECK-NEXT: %[[CPY_SRC_8307:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T294]], i32 8 +//CHECK-NEXT: %[[CPY_DST_8308:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T293]], i32 8 +//CHECK-NEXT: %[[CPY_VAL_8309:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_8307]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_8309]], i256* %[[CPY_DST_8308]], align 4 +//CHECK-NEXT: %[[T116:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 29 +//CHECK-NEXT: %[[T117:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 10 //CHECK-NEXT: %[[CPY_SRC_0229:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T117]], i32 0 //CHECK-NEXT: %[[CPY_DST_0230:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T116]], i32 0 //CHECK-NEXT: %[[CPY_VAL_0231:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_0229]], align 4 @@ -707,37 +780,37 @@ component main = BigMod(); //CHECK-NEXT: %[[CPY_DST_8254:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T116]], i32 8 //CHECK-NEXT: %[[CPY_VAL_8255:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_8253]], align 4 //CHECK-NEXT: store i256 %[[CPY_VAL_8255]], i256* %[[CPY_DST_8254]], align 4 -//CHECK-NEXT: %[[T118:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 29 +//CHECK-NEXT: %[[T118:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 38 //CHECK-NEXT: store i256 0, i256* %[[T118]], align 4 //CHECK-NEXT: %[[T119:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T120:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T121:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T120]], i32 0, i256 13 +//CHECK-NEXT: %[[T121:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T120]], i32 0, i256 22 //CHECK-NEXT: %[[T122:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T123:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T122]], i32 0, i256 20 +//CHECK-NEXT: %[[T123:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T122]], i32 0, i256 29 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %[[T119]], [0 x i256]* null, i256* %[[T121]], i256* %[[T123]]) //CHECK-NEXT: %[[T124:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T125:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T126:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T125]], i32 0, i256 14 +//CHECK-NEXT: %[[T126:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T125]], i32 0, i256 23 //CHECK-NEXT: %[[T127:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T128:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T127]], i32 0, i256 21 +//CHECK-NEXT: %[[T128:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T127]], i32 0, i256 30 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %[[T124]], [0 x i256]* null, i256* %[[T126]], i256* %[[T128]]) //CHECK-NEXT: %[[T129:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T130:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T131:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T130]], i32 0, i256 15 +//CHECK-NEXT: %[[T131:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T130]], i32 0, i256 24 //CHECK-NEXT: %[[T132:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T133:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T132]], i32 0, i256 22 +//CHECK-NEXT: %[[T133:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T132]], i32 0, i256 31 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %[[T129]], [0 x i256]* null, i256* %[[T131]], i256* %[[T133]]) //CHECK-NEXT: %[[T134:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T135:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T136:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T135]], i32 0, i256 16 +//CHECK-NEXT: %[[T136:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T135]], i32 0, i256 25 //CHECK-NEXT: %[[T137:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T138:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T137]], i32 0, i256 23 +//CHECK-NEXT: %[[T138:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T137]], i32 0, i256 32 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %[[T134]], [0 x i256]* null, i256* %[[T136]], i256* %[[T138]]) //CHECK-NEXT: %[[T139:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T140:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T141:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T140]], i32 0, i256 17 +//CHECK-NEXT: %[[T141:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T140]], i32 0, i256 26 //CHECK-NEXT: %[[T142:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T143:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T142]], i32 0, i256 24 +//CHECK-NEXT: %[[T143:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T142]], i32 0, i256 33 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %[[T139]], [0 x i256]* null, i256* %[[T141]], i256* %[[T143]]) //CHECK-NEXT: %[[CALL_ARENA276:[0-9a-zA-Z_\.]+]] = alloca [29 x i256], align 8 //CHECK-NEXT: %[[T144:[0-9a-zA-Z_\.]+]] = getelementptr [29 x i256], [29 x i256]* %[[CALL_ARENA276]], i32 0, i32 0 @@ -745,7 +818,7 @@ component main = BigMod(); //CHECK-NEXT: %[[T146:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[T145]], align 4 //CHECK-NEXT: store i256 %[[T146]], i256* %[[T144]], align 4 //CHECK-NEXT: %[[T147:[0-9a-zA-Z_\.]+]] = getelementptr [29 x i256], [29 x i256]* %[[CALL_ARENA276]], i32 0, i32 1 -//CHECK-NEXT: %[[T148:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 1 +//CHECK-NEXT: %[[T148:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 10 //CHECK-NEXT: %[[CPY_SRC_0277:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T148]], i32 0 //CHECK-NEXT: %[[CPY_DST_0278:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T147]], i32 0 //CHECK-NEXT: %[[CPY_VAL_0279:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_0277]], align 4 @@ -783,7 +856,7 @@ component main = BigMod(); //CHECK-NEXT: %[[CPY_VAL_8303:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_8301]], align 4 //CHECK-NEXT: store i256 %[[CPY_VAL_8303]], i256* %[[CPY_DST_8302]], align 4 //CHECK-NEXT: %[[T149:[0-9a-zA-Z_\.]+]] = getelementptr [29 x i256], [29 x i256]* %[[CALL_ARENA276]], i32 0, i32 10 -//CHECK-NEXT: %[[T150:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 11 +//CHECK-NEXT: %[[T150:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 20 //CHECK-NEXT: %[[CPY_SRC_0304:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T150]], i32 0 //CHECK-NEXT: %[[CPY_DST_0305:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T149]], i32 0 //CHECK-NEXT: %[[CPY_VAL_0306:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_0304]], align 4 @@ -822,7 +895,7 @@ component main = BigMod(); //CHECK-NEXT: store i256 %[[CPY_VAL_8330]], i256* %[[CPY_DST_8329]], align 4 //CHECK-NEXT: %[[T151:[0-9a-zA-Z_\.]+]] = bitcast [29 x i256]* %[[CALL_ARENA276]] to i256* //CHECK-NEXT: %[[T996:[0-9a-zA-Z_\.]+]] = call i256* @long_sub_[[$F_ID_3]](i256* %[[T151]]) -//CHECK-NEXT: %[[T152:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 1 +//CHECK-NEXT: %[[T152:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 10 //CHECK-NEXT: %[[CPY_SRC_0332:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T996]], i32 0 //CHECK-NEXT: %[[CPY_DST_0333:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T152]], i32 0 //CHECK-NEXT: %[[CPY_VAL_0334:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_0332]], align 4 @@ -859,28 +932,48 @@ component main = BigMod(); //CHECK-NEXT: %[[CPY_DST_8357:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T152]], i32 8 //CHECK-NEXT: %[[CPY_VAL_8358:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_8356]], align 4 //CHECK-NEXT: store i256 %[[CPY_VAL_8358]], i256* %[[CPY_DST_8357]], align 4 -//CHECK-NEXT: %[[T153:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 10 +//CHECK-NEXT: %[[T153:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 19 //CHECK-NEXT: store i256 1, i256* %[[T153]], align 4 -//CHECK-NEXT: %[[T154:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 11 -//CHECK-NEXT: store i256 0, i256* %[[T154]], align 4 -//CHECK-NEXT: %[[T155:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 12 -//CHECK-NEXT: store i256 0, i256* %[[T155]], align 4 -//CHECK-NEXT: %[[T156:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 13 -//CHECK-NEXT: store i256 0, i256* %[[T156]], align 4 -//CHECK-NEXT: %[[T157:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 14 -//CHECK-NEXT: store i256 0, i256* %[[T157]], align 4 -//CHECK-NEXT: %[[T158:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 15 -//CHECK-NEXT: store i256 0, i256* %[[T158]], align 4 -//CHECK-NEXT: %[[T159:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 16 -//CHECK-NEXT: store i256 0, i256* %[[T159]], align 4 -//CHECK-NEXT: %[[T160:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 17 -//CHECK-NEXT: store i256 0, i256* %[[T160]], align 4 -//CHECK-NEXT: %[[T161:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 18 -//CHECK-NEXT: store i256 0, i256* %[[T161]], align 4 -//CHECK-NEXT: %[[T162:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 19 -//CHECK-NEXT: store i256 0, i256* %[[T162]], align 4 -//CHECK-NEXT: %[[T163:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 20 -//CHECK-NEXT: %[[T164:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 1 +//CHECK-NEXT: %[[T333:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 20 +//CHECK-NEXT: %[[T334:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 1 +//CHECK-NEXT: %[[CPY_SRC_0440:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T334]], i32 0 +//CHECK-NEXT: %[[CPY_DST_0441:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T333]], i32 0 +//CHECK-NEXT: %[[CPY_VAL_0442:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_0440]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_0442]], i256* %[[CPY_DST_0441]], align 4 +//CHECK-NEXT: %[[CPY_SRC_1443:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T334]], i32 1 +//CHECK-NEXT: %[[CPY_DST_1444:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T333]], i32 1 +//CHECK-NEXT: %[[CPY_VAL_1445:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_1443]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_1445]], i256* %[[CPY_DST_1444]], align 4 +//CHECK-NEXT: %[[CPY_SRC_2446:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T334]], i32 2 +//CHECK-NEXT: %[[CPY_DST_2447:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T333]], i32 2 +//CHECK-NEXT: %[[CPY_VAL_2448:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_2446]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_2448]], i256* %[[CPY_DST_2447]], align 4 +//CHECK-NEXT: %[[CPY_SRC_3449:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T334]], i32 3 +//CHECK-NEXT: %[[CPY_DST_3450:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T333]], i32 3 +//CHECK-NEXT: %[[CPY_VAL_3451:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_3449]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_3451]], i256* %[[CPY_DST_3450]], align 4 +//CHECK-NEXT: %[[CPY_SRC_4452:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T334]], i32 4 +//CHECK-NEXT: %[[CPY_DST_4453:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T333]], i32 4 +//CHECK-NEXT: %[[CPY_VAL_4454:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_4452]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_4454]], i256* %[[CPY_DST_4453]], align 4 +//CHECK-NEXT: %[[CPY_SRC_5455:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T334]], i32 5 +//CHECK-NEXT: %[[CPY_DST_5456:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T333]], i32 5 +//CHECK-NEXT: %[[CPY_VAL_5457:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_5455]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_5457]], i256* %[[CPY_DST_5456]], align 4 +//CHECK-NEXT: %[[CPY_SRC_6458:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T334]], i32 6 +//CHECK-NEXT: %[[CPY_DST_6459:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T333]], i32 6 +//CHECK-NEXT: %[[CPY_VAL_6460:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_6458]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_6460]], i256* %[[CPY_DST_6459]], align 4 +//CHECK-NEXT: %[[CPY_SRC_7461:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T334]], i32 7 +//CHECK-NEXT: %[[CPY_DST_7462:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T333]], i32 7 +//CHECK-NEXT: %[[CPY_VAL_7463:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_7461]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_7463]], i256* %[[CPY_DST_7462]], align 4 +//CHECK-NEXT: %[[CPY_SRC_8464:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T334]], i32 8 +//CHECK-NEXT: %[[CPY_DST_8465:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T333]], i32 8 +//CHECK-NEXT: %[[CPY_VAL_8466:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_8464]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_8466]], i256* %[[CPY_DST_8465]], align 4 +//CHECK-NEXT: %[[T163:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 29 +//CHECK-NEXT: %[[T164:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 10 //CHECK-NEXT: %[[CPY_SRC_0359:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T164]], i32 0 //CHECK-NEXT: %[[CPY_DST_0360:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T163]], i32 0 //CHECK-NEXT: %[[CPY_VAL_0361:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_0359]], align 4 @@ -917,37 +1010,37 @@ component main = BigMod(); //CHECK-NEXT: %[[CPY_DST_8384:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T163]], i32 8 //CHECK-NEXT: %[[CPY_VAL_8385:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_8383]], align 4 //CHECK-NEXT: store i256 %[[CPY_VAL_8385]], i256* %[[CPY_DST_8384]], align 4 -//CHECK-NEXT: %[[T165:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 29 +//CHECK-NEXT: %[[T165:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 38 //CHECK-NEXT: store i256 0, i256* %[[T165]], align 4 //CHECK-NEXT: %[[T166:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T167:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T168:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T167]], i32 0, i256 12 +//CHECK-NEXT: %[[T168:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T167]], i32 0, i256 21 //CHECK-NEXT: %[[T169:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T170:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T169]], i32 0, i256 20 +//CHECK-NEXT: %[[T170:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T169]], i32 0, i256 29 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %[[T166]], [0 x i256]* null, i256* %[[T168]], i256* %[[T170]]) //CHECK-NEXT: %[[T171:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T172:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T173:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T172]], i32 0, i256 13 +//CHECK-NEXT: %[[T173:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T172]], i32 0, i256 22 //CHECK-NEXT: %[[T174:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T175:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T174]], i32 0, i256 21 +//CHECK-NEXT: %[[T175:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T174]], i32 0, i256 30 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %[[T171]], [0 x i256]* null, i256* %[[T173]], i256* %[[T175]]) //CHECK-NEXT: %[[T176:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T177:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T178:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T177]], i32 0, i256 14 +//CHECK-NEXT: %[[T178:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T177]], i32 0, i256 23 //CHECK-NEXT: %[[T179:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T180:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T179]], i32 0, i256 22 +//CHECK-NEXT: %[[T180:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T179]], i32 0, i256 31 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %[[T176]], [0 x i256]* null, i256* %[[T178]], i256* %[[T180]]) //CHECK-NEXT: %[[T181:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T182:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T183:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T182]], i32 0, i256 15 +//CHECK-NEXT: %[[T183:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T182]], i32 0, i256 24 //CHECK-NEXT: %[[T184:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T185:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T184]], i32 0, i256 23 +//CHECK-NEXT: %[[T185:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T184]], i32 0, i256 32 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %[[T181]], [0 x i256]* null, i256* %[[T183]], i256* %[[T185]]) //CHECK-NEXT: %[[T186:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T187:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T188:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T187]], i32 0, i256 16 +//CHECK-NEXT: %[[T188:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T187]], i32 0, i256 25 //CHECK-NEXT: %[[T189:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T190:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T189]], i32 0, i256 24 +//CHECK-NEXT: %[[T190:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T189]], i32 0, i256 33 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %[[T186]], [0 x i256]* null, i256* %[[T188]], i256* %[[T190]]) //CHECK-NEXT: %[[CALL_ARENA406:[0-9a-zA-Z_\.]+]] = alloca [29 x i256], align 8 //CHECK-NEXT: %[[T191:[0-9a-zA-Z_\.]+]] = getelementptr [29 x i256], [29 x i256]* %[[CALL_ARENA406]], i32 0, i32 0 @@ -955,7 +1048,7 @@ component main = BigMod(); //CHECK-NEXT: %[[T193:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[T192]], align 4 //CHECK-NEXT: store i256 %[[T193]], i256* %[[T191]], align 4 //CHECK-NEXT: %[[T194:[0-9a-zA-Z_\.]+]] = getelementptr [29 x i256], [29 x i256]* %[[CALL_ARENA406]], i32 0, i32 1 -//CHECK-NEXT: %[[T195:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 1 +//CHECK-NEXT: %[[T195:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 10 //CHECK-NEXT: %[[CPY_SRC_0407:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T195]], i32 0 //CHECK-NEXT: %[[CPY_DST_0408:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T194]], i32 0 //CHECK-NEXT: %[[CPY_VAL_0409:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_0407]], align 4 @@ -993,7 +1086,7 @@ component main = BigMod(); //CHECK-NEXT: %[[CPY_VAL_8433:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_8431]], align 4 //CHECK-NEXT: store i256 %[[CPY_VAL_8433]], i256* %[[CPY_DST_8432]], align 4 //CHECK-NEXT: %[[T196:[0-9a-zA-Z_\.]+]] = getelementptr [29 x i256], [29 x i256]* %[[CALL_ARENA406]], i32 0, i32 10 -//CHECK-NEXT: %[[T197:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 11 +//CHECK-NEXT: %[[T197:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 20 //CHECK-NEXT: %[[CPY_SRC_0434:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T197]], i32 0 //CHECK-NEXT: %[[CPY_DST_0435:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T196]], i32 0 //CHECK-NEXT: %[[CPY_VAL_0436:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_0434]], align 4 @@ -1032,7 +1125,7 @@ component main = BigMod(); //CHECK-NEXT: store i256 %[[CPY_VAL_8460]], i256* %[[CPY_DST_8459]], align 4 //CHECK-NEXT: %[[T198:[0-9a-zA-Z_\.]+]] = bitcast [29 x i256]* %[[CALL_ARENA406]] to i256* //CHECK-NEXT: %[[T997:[0-9a-zA-Z_\.]+]] = call i256* @long_sub_[[$F_ID_3]](i256* %[[T198]]) -//CHECK-NEXT: %[[T199:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 1 +//CHECK-NEXT: %[[T199:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 10 //CHECK-NEXT: %[[CPY_SRC_0462:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T997]], i32 0 //CHECK-NEXT: %[[CPY_DST_0463:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T199]], i32 0 //CHECK-NEXT: %[[CPY_VAL_0464:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_0462]], align 4 @@ -1069,28 +1162,48 @@ component main = BigMod(); //CHECK-NEXT: %[[CPY_DST_8487:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T199]], i32 8 //CHECK-NEXT: %[[CPY_VAL_8488:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_8486]], align 4 //CHECK-NEXT: store i256 %[[CPY_VAL_8488]], i256* %[[CPY_DST_8487]], align 4 -//CHECK-NEXT: %[[T200:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 10 +//CHECK-NEXT: %[[T200:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 19 //CHECK-NEXT: store i256 0, i256* %[[T200]], align 4 -//CHECK-NEXT: %[[T201:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 11 -//CHECK-NEXT: store i256 0, i256* %[[T201]], align 4 -//CHECK-NEXT: %[[T202:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 12 -//CHECK-NEXT: store i256 0, i256* %[[T202]], align 4 -//CHECK-NEXT: %[[T203:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 13 -//CHECK-NEXT: store i256 0, i256* %[[T203]], align 4 -//CHECK-NEXT: %[[T204:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 14 -//CHECK-NEXT: store i256 0, i256* %[[T204]], align 4 -//CHECK-NEXT: %[[T205:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 15 -//CHECK-NEXT: store i256 0, i256* %[[T205]], align 4 -//CHECK-NEXT: %[[T206:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 16 -//CHECK-NEXT: store i256 0, i256* %[[T206]], align 4 -//CHECK-NEXT: %[[T207:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 17 -//CHECK-NEXT: store i256 0, i256* %[[T207]], align 4 -//CHECK-NEXT: %[[T208:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 18 -//CHECK-NEXT: store i256 0, i256* %[[T208]], align 4 -//CHECK-NEXT: %[[T209:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 19 -//CHECK-NEXT: store i256 0, i256* %[[T209]], align 4 -//CHECK-NEXT: %[[T210:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 20 -//CHECK-NEXT: %[[T211:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 1 +//CHECK-NEXT: %[[T373:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 20 +//CHECK-NEXT: %[[T374:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 1 +//CHECK-NEXT: %[[CPY_SRC_0597:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T374]], i32 0 +//CHECK-NEXT: %[[CPY_DST_0598:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T373]], i32 0 +//CHECK-NEXT: %[[CPY_VAL_0599:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_0597]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_0599]], i256* %[[CPY_DST_0598]], align 4 +//CHECK-NEXT: %[[CPY_SRC_1600:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T374]], i32 1 +//CHECK-NEXT: %[[CPY_DST_1601:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T373]], i32 1 +//CHECK-NEXT: %[[CPY_VAL_1602:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_1600]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_1602]], i256* %[[CPY_DST_1601]], align 4 +//CHECK-NEXT: %[[CPY_SRC_2603:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T374]], i32 2 +//CHECK-NEXT: %[[CPY_DST_2604:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T373]], i32 2 +//CHECK-NEXT: %[[CPY_VAL_2605:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_2603]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_2605]], i256* %[[CPY_DST_2604]], align 4 +//CHECK-NEXT: %[[CPY_SRC_3606:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T374]], i32 3 +//CHECK-NEXT: %[[CPY_DST_3607:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T373]], i32 3 +//CHECK-NEXT: %[[CPY_VAL_3608:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_3606]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_3608]], i256* %[[CPY_DST_3607]], align 4 +//CHECK-NEXT: %[[CPY_SRC_4609:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T374]], i32 4 +//CHECK-NEXT: %[[CPY_DST_4610:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T373]], i32 4 +//CHECK-NEXT: %[[CPY_VAL_4611:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_4609]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_4611]], i256* %[[CPY_DST_4610]], align 4 +//CHECK-NEXT: %[[CPY_SRC_5612:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T374]], i32 5 +//CHECK-NEXT: %[[CPY_DST_5613:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T373]], i32 5 +//CHECK-NEXT: %[[CPY_VAL_5614:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_5612]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_5614]], i256* %[[CPY_DST_5613]], align 4 +//CHECK-NEXT: %[[CPY_SRC_6615:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T374]], i32 6 +//CHECK-NEXT: %[[CPY_DST_6616:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T373]], i32 6 +//CHECK-NEXT: %[[CPY_VAL_6617:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_6615]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_6617]], i256* %[[CPY_DST_6616]], align 4 +//CHECK-NEXT: %[[CPY_SRC_7618:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T374]], i32 7 +//CHECK-NEXT: %[[CPY_DST_7619:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T373]], i32 7 +//CHECK-NEXT: %[[CPY_VAL_7620:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_7618]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_7620]], i256* %[[CPY_DST_7619]], align 4 +//CHECK-NEXT: %[[CPY_SRC_8621:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T374]], i32 8 +//CHECK-NEXT: %[[CPY_DST_8622:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T373]], i32 8 +//CHECK-NEXT: %[[CPY_VAL_8623:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_8621]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_8623]], i256* %[[CPY_DST_8622]], align 4 +//CHECK-NEXT: %[[T210:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 29 +//CHECK-NEXT: %[[T211:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 10 //CHECK-NEXT: %[[CPY_SRC_0489:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T211]], i32 0 //CHECK-NEXT: %[[CPY_DST_0490:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T210]], i32 0 //CHECK-NEXT: %[[CPY_VAL_0491:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_0489]], align 4 @@ -1127,37 +1240,37 @@ component main = BigMod(); //CHECK-NEXT: %[[CPY_DST_8514:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T210]], i32 8 //CHECK-NEXT: %[[CPY_VAL_8515:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_8513]], align 4 //CHECK-NEXT: store i256 %[[CPY_VAL_8515]], i256* %[[CPY_DST_8514]], align 4 -//CHECK-NEXT: %[[T212:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 29 +//CHECK-NEXT: %[[T212:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 38 //CHECK-NEXT: store i256 0, i256* %[[T212]], align 4 //CHECK-NEXT: %[[T213:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T214:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T215:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T214]], i32 0, i256 11 +//CHECK-NEXT: %[[T215:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T214]], i32 0, i256 20 //CHECK-NEXT: %[[T216:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T217:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T216]], i32 0, i256 20 +//CHECK-NEXT: %[[T217:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T216]], i32 0, i256 29 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %[[T213]], [0 x i256]* null, i256* %[[T215]], i256* %[[T217]]) //CHECK-NEXT: %[[T218:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T219:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T220:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T219]], i32 0, i256 12 +//CHECK-NEXT: %[[T220:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T219]], i32 0, i256 21 //CHECK-NEXT: %[[T221:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T222:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T221]], i32 0, i256 21 +//CHECK-NEXT: %[[T222:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T221]], i32 0, i256 30 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %[[T218]], [0 x i256]* null, i256* %[[T220]], i256* %[[T222]]) //CHECK-NEXT: %[[T223:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T224:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T225:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T224]], i32 0, i256 13 +//CHECK-NEXT: %[[T225:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T224]], i32 0, i256 22 //CHECK-NEXT: %[[T226:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T227:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T226]], i32 0, i256 22 +//CHECK-NEXT: %[[T227:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T226]], i32 0, i256 31 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %[[T223]], [0 x i256]* null, i256* %[[T225]], i256* %[[T227]]) //CHECK-NEXT: %[[T228:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T229:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T230:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T229]], i32 0, i256 14 +//CHECK-NEXT: %[[T230:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T229]], i32 0, i256 23 //CHECK-NEXT: %[[T231:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T232:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T231]], i32 0, i256 23 +//CHECK-NEXT: %[[T232:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T231]], i32 0, i256 32 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %[[T228]], [0 x i256]* null, i256* %[[T230]], i256* %[[T232]]) //CHECK-NEXT: %[[T233:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* //CHECK-NEXT: %[[T234:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T235:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T234]], i32 0, i256 15 +//CHECK-NEXT: %[[T235:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T234]], i32 0, i256 24 //CHECK-NEXT: %[[T236:[0-9a-zA-Z_\.]+]] = bitcast i256* %0 to [0 x i256]* -//CHECK-NEXT: %[[T237:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T236]], i32 0, i256 24 +//CHECK-NEXT: %[[T237:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %[[T236]], i32 0, i256 33 //CHECK-NEXT: call void @..generated..loop.body.[[$F_ID_1]]([0 x i256]* %[[T233]], [0 x i256]* null, i256* %[[T235]], i256* %[[T237]]) //CHECK-NEXT: %[[CALL_ARENA536:[0-9a-zA-Z_\.]+]] = alloca [29 x i256], align 8 //CHECK-NEXT: %[[T238:[0-9a-zA-Z_\.]+]] = getelementptr [29 x i256], [29 x i256]* %[[CALL_ARENA536]], i32 0, i32 0 @@ -1165,7 +1278,7 @@ component main = BigMod(); //CHECK-NEXT: %[[T240:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[T239]], align 4 //CHECK-NEXT: store i256 %[[T240]], i256* %[[T238]], align 4 //CHECK-NEXT: %[[T241:[0-9a-zA-Z_\.]+]] = getelementptr [29 x i256], [29 x i256]* %[[CALL_ARENA536]], i32 0, i32 1 -//CHECK-NEXT: %[[T242:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 1 +//CHECK-NEXT: %[[T242:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 10 //CHECK-NEXT: %[[CPY_SRC_0537:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T242]], i32 0 //CHECK-NEXT: %[[CPY_DST_0538:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T241]], i32 0 //CHECK-NEXT: %[[CPY_VAL_0539:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_0537]], align 4 @@ -1203,7 +1316,7 @@ component main = BigMod(); //CHECK-NEXT: %[[CPY_VAL_8563:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_8561]], align 4 //CHECK-NEXT: store i256 %[[CPY_VAL_8563]], i256* %[[CPY_DST_8562]], align 4 //CHECK-NEXT: %[[T243:[0-9a-zA-Z_\.]+]] = getelementptr [29 x i256], [29 x i256]* %[[CALL_ARENA536]], i32 0, i32 10 -//CHECK-NEXT: %[[T244:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 11 +//CHECK-NEXT: %[[T244:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 20 //CHECK-NEXT: %[[CPY_SRC_0564:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T244]], i32 0 //CHECK-NEXT: %[[CPY_DST_0565:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T243]], i32 0 //CHECK-NEXT: %[[CPY_VAL_0566:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_0564]], align 4 @@ -1242,7 +1355,7 @@ component main = BigMod(); //CHECK-NEXT: store i256 %[[CPY_VAL_8590]], i256* %[[CPY_DST_8589]], align 4 //CHECK-NEXT: %[[T245:[0-9a-zA-Z_\.]+]] = bitcast [29 x i256]* %[[CALL_ARENA536]] to i256* //CHECK-NEXT: %[[T998:[0-9a-zA-Z_\.]+]] = call i256* @long_sub_[[$F_ID_3]](i256* %[[T245]]) -//CHECK-NEXT: %[[T246:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 1 +//CHECK-NEXT: %[[T246:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 10 //CHECK-NEXT: %[[CPY_SRC_0592:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T998]], i32 0 //CHECK-NEXT: %[[CPY_DST_0593:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T246]], i32 0 //CHECK-NEXT: %[[CPY_VAL_0594:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_0592]], align 4 @@ -1279,26 +1392,64 @@ component main = BigMod(); //CHECK-NEXT: %[[CPY_DST_8617:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T246]], i32 8 //CHECK-NEXT: %[[CPY_VAL_8618:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_8616]], align 4 //CHECK-NEXT: store i256 %[[CPY_VAL_8618]], i256* %[[CPY_DST_8617]], align 4 -//CHECK-NEXT: %[[T247:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 10 +//CHECK-NEXT: %[[T247:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 19 //CHECK-NEXT: store i256 21888242871839275222246405745257275088548364400416034343698204186575808495616, i256* %[[T247]], align 4 //CHECK-NEXT: br label %return12 //CHECK-EMPTY: //CHECK-NEXT: return12: -//CHECK-NEXT: %[[T248:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 1 +//CHECK-NEXT: %[[T248:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 10 //CHECK-NEXT: ret i256* %[[T248]] //CHECK-NEXT: } // -//CHECK-LABEL: define dso_local void @BigMod_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @BigMod_{{[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 //CHECK-NEXT: br label %call1 //CHECK-EMPTY: //CHECK-NEXT: call1: -//CHECK-NEXT: %[[CALL_ARENA:[0-9a-zA-Z_\.]+]] = alloca [30 x i256], align 8 -//CHECK-NEXT: %[[T001:[0-9a-zA-Z_\.]+]] = getelementptr [30 x i256], [30 x i256]* %[[CALL_ARENA]], i32 0, i32 0 +//CHECK-NEXT: %[[CALL_ARENA:[0-9a-zA-Z_\.]+]] = alloca [39 x i256], align 8 +//CHECK-NEXT: %[[T001:[0-9a-zA-Z_\.]+]] = getelementptr [39 x i256], [39 x i256]* %[[CALL_ARENA]], i32 0, i32 0 //CHECK-NEXT: store i256 4, i256* %[[T001]], align 4 -//CHECK-NEXT: %[[T002:[0-9a-zA-Z_\.]+]] = bitcast [30 x i256]* %[[CALL_ARENA]] to i256* +//CHECK-NEXT: %[[T102:[0-9a-zA-Z_\.]+]] = getelementptr [39 x i256], [39 x i256]* %[[CALL_ARENA]], i32 0, i32 1 +//CHECK-NEXT: %[[T103:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 9 +//CHECK-NEXT: %[[CPY_SRC_10:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T103]], i32 0 +//CHECK-NEXT: %[[CPY_DST_10:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T102]], i32 0 +//CHECK-NEXT: %[[CPY_VAL_10:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_10]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_10]], i256* %[[CPY_DST_10]], align 4 +//CHECK-NEXT: %[[CPY_SRC_11:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T103]], i32 1 +//CHECK-NEXT: %[[CPY_DST_11:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T102]], i32 1 +//CHECK-NEXT: %[[CPY_VAL_11:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_11]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_11]], i256* %[[CPY_DST_11]], align 4 +//CHECK-NEXT: %[[CPY_SRC_12:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T103]], i32 2 +//CHECK-NEXT: %[[CPY_DST_12:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T102]], i32 2 +//CHECK-NEXT: %[[CPY_VAL_12:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_12]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_12]], i256* %[[CPY_DST_12]], align 4 +//CHECK-NEXT: %[[CPY_SRC_13:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T103]], i32 3 +//CHECK-NEXT: %[[CPY_DST_13:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T102]], i32 3 +//CHECK-NEXT: %[[CPY_VAL_13:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_13]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_13]], i256* %[[CPY_DST_13]], align 4 +//CHECK-NEXT: %[[CPY_SRC_14:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T103]], i32 4 +//CHECK-NEXT: %[[CPY_DST_14:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T102]], i32 4 +//CHECK-NEXT: %[[CPY_VAL_14:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_14]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_14]], i256* %[[CPY_DST_14]], align 4 +//CHECK-NEXT: %[[CPY_SRC_15:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T103]], i32 5 +//CHECK-NEXT: %[[CPY_DST_15:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T102]], i32 5 +//CHECK-NEXT: %[[CPY_VAL_15:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_15]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_15]], i256* %[[CPY_DST_15]], align 4 +//CHECK-NEXT: %[[CPY_SRC_16:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T103]], i32 6 +//CHECK-NEXT: %[[CPY_DST_16:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T102]], i32 6 +//CHECK-NEXT: %[[CPY_VAL_16:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_16]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_16]], i256* %[[CPY_DST_16]], align 4 +//CHECK-NEXT: %[[CPY_SRC_17:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T103]], i32 7 +//CHECK-NEXT: %[[CPY_DST_17:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T102]], i32 7 +//CHECK-NEXT: %[[CPY_VAL_17:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_17]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_17]], i256* %[[CPY_DST_17]], align 4 +//CHECK-NEXT: %[[CPY_SRC_18:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T103]], i32 8 +//CHECK-NEXT: %[[CPY_DST_18:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T102]], i32 8 +//CHECK-NEXT: %[[CPY_VAL_18:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_18]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_18]], i256* %[[CPY_DST_18]], align 4 +//CHECK-NEXT: %[[T002:[0-9a-zA-Z_\.]+]] = bitcast [39 x i256]* %[[CALL_ARENA]] to i256* //CHECK-NEXT: %[[T999:[0-9a-zA-Z_\.]+]] = call i256* @long_div_[[$F_ID_4]](i256* %[[T002]]) //CHECK-NEXT: %[[T003:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 0 //CHECK-NEXT: %[[CPY_SRC_0:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T999]], i32 0 diff --git a/circom/tests/calls/call_ret_arraymulti_nonzero.circom b/circom/tests/calls/call_ret_arraymulti_nonzero.circom new file mode 100644 index 000000000..fde7b6844 --- /dev/null +++ b/circom/tests/calls/call_ret_arraymulti_nonzero.circom @@ -0,0 +1,75 @@ +pragma circom 2.0.3; +// 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 long_gt(a, b) { + for (var i = 1; i >= 0; i--) { + if (a[i] > b[i]) { + return 1; + } + if (a[i] < b[i]) { + return 2; + } + } + return 0; +} + +function long_scalar_mult() { + return [[99, 88, 77], [66, 55, 44]]; +} + +template Test() { + var norm[2][3] = long_scalar_mult(); + var out[1] = [long_gt(norm[0], norm[1])]; +} + +component main = Test(); + +// NOTE: With the constant arrays propagated through return and call, +// the long_gt() function is totally optimized away to the value '1'. + +//CHECK-LABEL: define{{.*}} void @Test_{{[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 +//CHECK-NEXT: br label %call1 +//CHECK-EMPTY: +//CHECK-NEXT: call1: +//CHECK-NEXT: %[[ARENA:[0-9a-zA-Z_\.]+]] = alloca [12 x i256], align 8 +//CHECK-NEXT: %[[T01:[0-9a-zA-Z_\.]+]] = bitcast [12 x i256]* %[[ARENA]] to i256* +//CHECK-NEXT: %[[T99:[0-9a-zA-Z_\.]+]] = call i256* @long_scalar_mult_{{[0-9a-zA-Z_\.]+}}(i256* %[[T01]]) +//CHECK-NEXT: %[[T02:[0-9a-zA-Z_\.]+]] = getelementptr [7 x i256], [7 x i256]* %lvars, i32 0, i32 0 +//CHECK-NEXT: %[[CPY_SRC_0:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T99]], i32 0 +//CHECK-NEXT: %[[CPY_DST_0:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T02]], i32 0 +//CHECK-NEXT: %[[CPY_VAL_0:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_0]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_0]], i256* %[[CPY_DST_0]], align 4 +//CHECK-NEXT: %[[CPY_SRC_1:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T99]], i32 1 +//CHECK-NEXT: %[[CPY_DST_1:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T02]], i32 1 +//CHECK-NEXT: %[[CPY_VAL_1:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_1]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_1]], i256* %[[CPY_DST_1]], align 4 +//CHECK-NEXT: %[[CPY_SRC_2:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T99]], i32 2 +//CHECK-NEXT: %[[CPY_DST_2:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T02]], i32 2 +//CHECK-NEXT: %[[CPY_VAL_2:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_2]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_2]], i256* %[[CPY_DST_2]], align 4 +//CHECK-NEXT: %[[CPY_SRC_3:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T99]], i32 3 +//CHECK-NEXT: %[[CPY_DST_3:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T02]], i32 3 +//CHECK-NEXT: %[[CPY_VAL_3:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_3]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_3]], i256* %[[CPY_DST_3]], align 4 +//CHECK-NEXT: %[[CPY_SRC_4:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T99]], i32 4 +//CHECK-NEXT: %[[CPY_DST_4:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T02]], i32 4 +//CHECK-NEXT: %[[CPY_VAL_4:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_4]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_4]], i256* %[[CPY_DST_4]], align 4 +//CHECK-NEXT: %[[CPY_SRC_5:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T99]], i32 5 +//CHECK-NEXT: %[[CPY_DST_5:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T02]], i32 5 +//CHECK-NEXT: %[[CPY_VAL_5:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_5]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_5]], i256* %[[CPY_DST_5]], align 4 +//CHECK-NEXT: br label %store2 +//CHECK-EMPTY: +//CHECK-NEXT: store2: +//CHECK-NEXT: %[[T03:[0-9a-zA-Z_\.]+]] = getelementptr [7 x i256], [7 x i256]* %lvars, i32 0, i32 6 +//CHECK-NEXT: store i256 1, i256* %[[T03]], align 4 +//CHECK-NEXT: br label %prologue +//CHECK-EMPTY: +//CHECK-NEXT: prologue: +//CHECK-NEXT: ret void +//CHECK-NEXT: } diff --git a/circom/tests/controlflow/early_return_loop_with_unknown_if.circom b/circom/tests/controlflow/early_return_loop_with_unknown_if.circom index 9e50c6dab..2e8ed48e4 100644 --- a/circom/tests/controlflow/early_return_loop_with_unknown_if.circom +++ b/circom/tests/controlflow/early_return_loop_with_unknown_if.circom @@ -7,26 +7,27 @@ function long_gt(a, b) { if (a[i] > b[i]) { return 1; } - if (a[i] < b[i]) { + if (a[i] <= b[i]) { return 0; } } return 0; } -function long_scalar_mult() { - var out[2]; +function long_scalar_mult(in) { + var out[2] = in; return out; } -function long_div2(){ - var norm[2] = long_scalar_mult(); +function long_div2(in){ + var norm[2] = long_scalar_mult(in); var out[1] = [long_gt(norm, norm)]; return out; } template Test() { - var out[1] = long_div2(); + signal input in[2]; + var out[1] = long_div2(in); } component main = Test(); @@ -37,17 +38,20 @@ component main = Test(); //CHECK-NEXT: br label %store1 //CHECK-EMPTY: //CHECK-NEXT: store1: -//CHECK-NEXT: %[[T01:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 0 -//CHECK-NEXT: store i256 0, i256* %[[T01]], align 4 -//CHECK-NEXT: br label %store2 -//CHECK-EMPTY: -//CHECK-NEXT: store2: -//CHECK-NEXT: %[[T02:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 1 -//CHECK-NEXT: store i256 0, i256* %[[T02]], align 4 -//CHECK-NEXT: br label %return3 +//CHECK-NEXT: %[[T01:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 2 +//CHECK-NEXT: %[[T02:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 0 +//CHECK-NEXT: %[[CPY_SRC_0:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T02]], i32 0 +//CHECK-NEXT: %[[CPY_DST_0:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T01]], i32 0 +//CHECK-NEXT: %[[CPY_VAL_0:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_0]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_0]], i256* %[[CPY_DST_0]], align 4 +//CHECK-NEXT: %[[CPY_SRC_1:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T02]], i32 1 +//CHECK-NEXT: %[[CPY_DST_1:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T01]], i32 1 +//CHECK-NEXT: %[[CPY_VAL_1:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_1]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_1]], i256* %[[CPY_DST_1]], align 4 +//CHECK-NEXT: br label %return2 //CHECK-EMPTY: -//CHECK-NEXT: return3: -//CHECK-NEXT: %[[T03:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 0 +//CHECK-NEXT: return2: +//CHECK-NEXT: %[[T03:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 2 //CHECK-NEXT: ret i256* %[[T03]] //CHECK-NEXT: } // @@ -71,7 +75,22 @@ component main = Test(); //CHECK-NEXT: br i1 %[[T99]], label %loop.body, label %loop.end //CHECK-EMPTY: //CHECK-NEXT: loop.body: -//CHECK-NEXT: br i1 false, label %if.then, label %if.else +//CHECK-NEXT: %[[T74:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 4 +//CHECK-NEXT: %[[T75:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[T74]], align 4 +//CHECK-NEXT: %[[T91:[0-9a-zA-Z_\.]+]] = call i32 @fr_cast_to_addr(i256 %[[T75]]) +//CHECK-NEXT: %[[T92:[0-9a-zA-Z_\.]+]] = mul i32 1, %[[T91]] +//CHECK-NEXT: %[[T93:[0-9a-zA-Z_\.]+]] = add i32 %[[T92]], 0 +//CHECK-NEXT: %[[T76:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 %[[T93]] +//CHECK-NEXT: %[[T77:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[T76]], align 4 +//CHECK-NEXT: %[[T78:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 4 +//CHECK-NEXT: %[[T79:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[T78]], align 4 +//CHECK-NEXT: %[[T97:[0-9a-zA-Z_\.]+]] = call i32 @fr_cast_to_addr(i256 %[[T79]]) +//CHECK-NEXT: %[[T96:[0-9a-zA-Z_\.]+]] = mul i32 1, %[[T97]] +//CHECK-NEXT: %[[T95:[0-9a-zA-Z_\.]+]] = add i32 %[[T96]], 2 +//CHECK-NEXT: %[[T80:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 %[[T95]] +//CHECK-NEXT: %[[T81:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[T80]], align 4 +//CHECK-NEXT: %[[T94:[0-9a-zA-Z_\.]+]] = call i1 @fr_gt(i256 %[[T77]], i256 %[[T81]]) +//CHECK-NEXT: br i1 %[[T94]], label %if.then, label %if.else //CHECK-EMPTY: //CHECK-NEXT: loop.end: //CHECK-NEXT: br label %return12 @@ -83,15 +102,30 @@ component main = Test(); //CHECK-NEXT: br label %if.merge //CHECK-EMPTY: //CHECK-NEXT: if.merge: -//CHECK-NEXT: br i1 false, label %if.then1, label %if.else2 -//CHECK-EMPTY: -//CHECK-NEXT: if.then1: +//CHECK-NEXT: %[[T12:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 4 +//CHECK-NEXT: %[[T13:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[T12]], align 4 +//CHECK-NEXT: %[[T27:[0-9a-zA-Z_\.]+]] = call i32 @fr_cast_to_addr(i256 %[[T13]]) +//CHECK-NEXT: %[[T26:[0-9a-zA-Z_\.]+]] = mul i32 1, %[[T27]] +//CHECK-NEXT: %[[T25:[0-9a-zA-Z_\.]+]] = add i32 %[[T26]], 0 +//CHECK-NEXT: %[[T14:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 %[[T25]] +//CHECK-NEXT: %[[T15:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[T14]], align 4 +//CHECK-NEXT: %[[T16:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 4 +//CHECK-NEXT: %[[T17:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[T16]], align 4 +//CHECK-NEXT: %[[T24:[0-9a-zA-Z_\.]+]] = call i32 @fr_cast_to_addr(i256 %[[T17]]) +//CHECK-NEXT: %[[T23:[0-9a-zA-Z_\.]+]] = mul i32 1, %[[T24]] +//CHECK-NEXT: %[[T22:[0-9a-zA-Z_\.]+]] = add i32 %[[T23]], 2 +//CHECK-NEXT: %[[T18:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 %[[T22]] +//CHECK-NEXT: %[[T19:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[T18]], align 4 +//CHECK-NEXT: %[[T21:[0-9a-zA-Z_\.]+]] = call i1 @fr_le(i256 %[[T15]], i256 %[[T19]]) +//CHECK-NEXT: br i1 %[[T21]], label %if.then4, label %if.else5 +//CHECK-EMPTY: +//CHECK-NEXT: if.then4: //CHECK-NEXT: ret i256 0 //CHECK-EMPTY: -//CHECK-NEXT: if.else2: -//CHECK-NEXT: br label %if.merge3 +//CHECK-NEXT: if.else5: +//CHECK-NEXT: br label %if.merge6 //CHECK-EMPTY: -//CHECK-NEXT: if.merge3: +//CHECK-NEXT: if.merge6: //CHECK-NEXT: %[[T04:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 4 //CHECK-NEXT: %[[T05:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 4 //CHECK-NEXT: %[[T06:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[T05]], align 4 @@ -109,10 +143,20 @@ component main = Test(); //CHECK-NEXT: br label %call1 //CHECK-EMPTY: //CHECK-NEXT: call1: -//CHECK-NEXT: %[[ARENA_1:[0-9a-zA-Z_\.]+]] = alloca [2 x i256], align 8 -//CHECK-NEXT: %[[T01:[0-9a-zA-Z_\.]+]] = bitcast [2 x i256]* %[[ARENA_1]] to i256* -//CHECK-NEXT: %call.long_scalar_mult_[[$F_ID_1]] = call i256* @long_scalar_mult_[[$F_ID_1]](i256* %[[T01]]) -//CHECK-NEXT: %[[T02:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 0 +//CHECK-NEXT: %[[ARENA_1:[0-9a-zA-Z_\.]+]] = alloca [4 x i256], align 8 +//CHECK-NEXT: %[[T50:[0-9a-zA-Z_\.]+]] = getelementptr [4 x i256], [4 x i256]* %[[ARENA_1]], i32 0, i32 0 +//CHECK-NEXT: %[[T52:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 0 +//CHECK-NEXT: %[[CPY_SRC_90:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T52]], i32 0 +//CHECK-NEXT: %[[CPY_DST_90:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T50]], i32 0 +//CHECK-NEXT: %[[CPY_VAL_90:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_90]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_90]], i256* %[[CPY_DST_90]], align 4 +//CHECK-NEXT: %[[CPY_SRC_91:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T52]], i32 1 +//CHECK-NEXT: %[[CPY_DST_91:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T50]], i32 1 +//CHECK-NEXT: %[[CPY_VAL_91:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_91]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_91]], i256* %[[CPY_DST_91]], align 4 +//CHECK-NEXT: %[[T01:[0-9a-zA-Z_\.]+]] = bitcast [4 x i256]* %[[ARENA_1]] to i256* +//CHECK-NEXT: %call.long_scalar_mult_[[$F_ID_1:[0-9a-zA-Z_\.]+]] = call i256* @long_scalar_mult_[[$F_ID_1]](i256* %[[T01]]) +//CHECK-NEXT: %[[T02:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 2 //CHECK-NEXT: %[[CPY_SRC_0:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %call.long_scalar_mult_[[$F_ID_1]], i32 0 //CHECK-NEXT: %[[CPY_DST_0:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T02]], i32 0 //CHECK-NEXT: %[[CPY_VAL_0:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_0]], align 4 @@ -126,7 +170,7 @@ component main = Test(); //CHECK-NEXT: call2: //CHECK-NEXT: %[[ARENA_2:[0-9a-zA-Z_\.]+]] = alloca [5 x i256], align 8 //CHECK-NEXT: %[[T03:[0-9a-zA-Z_\.]+]] = getelementptr [5 x i256], [5 x i256]* %[[ARENA_2]], i32 0, i32 0 -//CHECK-NEXT: %[[T04:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 0 +//CHECK-NEXT: %[[T04:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 2 //CHECK-NEXT: %[[CPY_SRC_01:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T04]], i32 0 //CHECK-NEXT: %[[CPY_DST_02:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T03]], i32 0 //CHECK-NEXT: %[[CPY_VAL_03:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_01]], align 4 @@ -136,7 +180,7 @@ component main = Test(); //CHECK-NEXT: %[[CPY_VAL_16:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_14]], align 4 //CHECK-NEXT: store i256 %[[CPY_VAL_16]], i256* %[[CPY_DST_15]], align 4 //CHECK-NEXT: %[[T05:[0-9a-zA-Z_\.]+]] = getelementptr [5 x i256], [5 x i256]* %[[ARENA_2]], i32 0, i32 2 -//CHECK-NEXT: %[[T06:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 0 +//CHECK-NEXT: %[[T06:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 2 //CHECK-NEXT: %[[CPY_SRC_07:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T06]], i32 0 //CHECK-NEXT: %[[CPY_DST_08:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T05]], i32 0 //CHECK-NEXT: %[[CPY_VAL_09:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_07]], align 4 @@ -147,19 +191,19 @@ component main = Test(); //CHECK-NEXT: store i256 %[[CPY_VAL_112]], i256* %[[CPY_DST_111]], align 4 //CHECK-NEXT: %[[T07:[0-9a-zA-Z_\.]+]] = bitcast [5 x i256]* %[[ARENA_2]] to i256* //CHECK-NEXT: %[[T97:[0-9a-zA-Z_\.]+]] = call i256 @long_gt_[[$F_ID_2]](i256* %[[T07]]) -//CHECK-NEXT: %[[T08:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 3 +//CHECK-NEXT: %[[T08:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 5 //CHECK-NEXT: store i256 %[[T97]], i256* %[[T08]], align 4 //CHECK-NEXT: br label %store3 //CHECK-EMPTY: //CHECK-NEXT: store3: -//CHECK-NEXT: %[[T09:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 2 -//CHECK-NEXT: %[[T10:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 3 +//CHECK-NEXT: %[[T09:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 4 +//CHECK-NEXT: %[[T10:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 5 //CHECK-NEXT: %[[T11:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[T10]], align 4 //CHECK-NEXT: store i256 %[[T11]], i256* %[[T09]], align 4 //CHECK-NEXT: br label %return4 //CHECK-EMPTY: //CHECK-NEXT: return4: -//CHECK-NEXT: %[[T12:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 2 +//CHECK-NEXT: %[[T12:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %0, i32 4 //CHECK-NEXT: %[[T13:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[T12]], align 4 //CHECK-NEXT: ret i256 %[[T13]] //CHECK-NEXT: } @@ -171,8 +215,18 @@ component main = Test(); //CHECK-NEXT: br label %call1 //CHECK-EMPTY: //CHECK-NEXT: call1: -//CHECK-NEXT: %[[ARENA_3:[0-9a-zA-Z_\.]+]] = alloca [4 x i256], align 8 -//CHECK-NEXT: %[[T01:[0-9a-zA-Z_\.]+]] = bitcast [4 x i256]* %[[ARENA_3]] to i256* +//CHECK-NEXT: %[[ARENA_3:[0-9a-zA-Z_\.]+]] = alloca [6 x i256], align 8 +//CHECK-NEXT: %[[T11:[0-9a-zA-Z_\.]+]] = getelementptr [6 x i256], [6 x i256]* %[[ARENA_3]], i32 0, i32 0 +//CHECK-NEXT: %[[T12:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 0 +//CHECK-NEXT: %[[CPY_SRC_0:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T12]], i32 0 +//CHECK-NEXT: %[[CPY_DST_0:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T11]], i32 0 +//CHECK-NEXT: %[[CPY_VAL_0:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_0]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_0]], i256* %[[CPY_DST_0]], align 4 +//CHECK-NEXT: %[[CPY_SRC_1:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T12]], i32 1 +//CHECK-NEXT: %[[CPY_DST_1:[0-9a-zA-Z_\.]+]] = getelementptr i256, i256* %[[T11]], i32 1 +//CHECK-NEXT: %[[CPY_VAL_1:[0-9a-zA-Z_\.]+]] = load i256, i256* %[[CPY_SRC_1]], align 4 +//CHECK-NEXT: store i256 %[[CPY_VAL_1]], i256* %[[CPY_DST_1]], align 4 +//CHECK-NEXT: %[[T01:[0-9a-zA-Z_\.]+]] = bitcast [6 x i256]* %[[ARENA_3]] to i256* //CHECK-NEXT: %[[T96:[0-9a-zA-Z_\.]+]] = call i256 @long_div2_[[$F_ID_3]](i256* %[[T01]]) //CHECK-NEXT: %[[T02:[0-9a-zA-Z_\.]+]] = getelementptr [1 x i256], [1 x i256]* %lvars, i32 0, i32 0 //CHECK-NEXT: store i256 %[[T96]], i256* %[[T02]], align 4 diff --git a/circom/tests/subcmps/subcmps4.circom b/circom/tests/subcmps/subcmps4.circom index 76177b7a5..b4ea3edc9 100644 --- a/circom/tests/subcmps/subcmps4.circom +++ b/circom/tests/subcmps/subcmps4.circom @@ -229,7 +229,7 @@ component main = SubCmps4(3); //CHECK-NEXT: ret void //CHECK-NEXT: } // -//CHECK-LABEL: define dso_local void @SubCmps4_1_run([0 x i256]* %0){{.*}} { +//CHECK-LABEL: define{{.*}} void @SubCmps4_1_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/zzz/array_size_mismatch_return.circom b/circom/tests/zzz/array_size_mismatch_return.circom new file mode 100644 index 000000000..ed865bd63 --- /dev/null +++ b/circom/tests/zzz/array_size_mismatch_return.circom @@ -0,0 +1,29 @@ +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 + +// The circom compiler only gives a warning for this: +// warning[T3001]: Typing warning: Mismatched dimensions, assigning to an array an expression of smaller length, the remaining positions are assigned to 0. + +function smaller() { + return [99, 98, 97, 96, 95]; +} + +template ImplicitExtension() { + signal output out[10]; + var temp[10] = smaller(); + out[0] <-- temp[0]; + out[4] <-- temp[4]; + out[5] <-- temp[5]; + out[9] <-- temp[9]; +} + +component main = ImplicitExtension(); + +//CHECK-LABEL: define{{.*}} void @ImplicitExtension_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK: store2: +//CHECK-NEXT: %[[T03:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 0 +//CHECK-NEXT: store i256 99, i256* %[[T03]], align 4 +//CHECK: store3: +//CHECK-NEXT: %[[T04:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 4 +//CHECK-NEXT: store i256 95, i256* %[[T04]], align 4 diff --git a/circom/tests/zzz/array_size_mismatch_store.circom b/circom/tests/zzz/array_size_mismatch_store.circom new file mode 100644 index 000000000..ca7ee470b --- /dev/null +++ b/circom/tests/zzz/array_size_mismatch_store.circom @@ -0,0 +1,25 @@ +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 + +// The circom compiler only gives a warning for this: +// warning[T3001]: Typing warning: Mismatched dimensions, assigning to an array an expression of smaller length, the remaining positions are assigned to 0. + +template ImplicitExtension() { + signal output out[10]; + var temp[10] = [99, 98, 97, 96, 95]; + out[0] <-- temp[0]; + out[4] <-- temp[4]; + out[5] <-- temp[5]; + out[9] <-- temp[9]; +} + +component main = ImplicitExtension(); + +//CHECK-LABEL: define{{.*}} void @ImplicitExtension_{{[0-9]+}}_run([0 x i256]* %0){{.*}} { +//CHECK: store6: +//CHECK-NEXT: %[[T06:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 0 +//CHECK-NEXT: store i256 99, i256* %[[T06]], align 4 +//CHECK: store7: +//CHECK-NEXT: %[[T07:[0-9a-zA-Z_\.]+]] = getelementptr [0 x i256], [0 x i256]* %0, i32 0, i32 4 +//CHECK-NEXT: store i256 95, i256* %[[T07]], align 4 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 0020e0e7f..9e73bf5ed 100644 --- a/circuit_passes/src/bucket_interpreter/env/extracted_func_env.rs +++ b/circuit_passes/src/bucket_interpreter/env/extracted_func_env.rs @@ -140,20 +140,18 @@ impl<'a> ExtractedFuncEnvData<'a> { unreachable!(); } Some((loc, idx)) => { - //ASSERT: ExtractedFunctionLocationUpdater will always assign 0 in - // the LocationRule that 'signal_idx' is computed from. - assert_eq!(signal_idx, 0); + let idx = signal_idx + idx; match loc { - AddressType::Variable => self.base.get_var(*idx), - AddressType::Signal => self.base.get_signal(*idx), + AddressType::Variable => self.base.get_var(idx), + AddressType::Signal => self.base.get_signal(idx), AddressType::SubcmpSignal { counter_override, cmp_address, .. } => { let subcmp_idx = Self::unwrap_subcmp_idx(cmp_address); if *counter_override { // ASSERT: always 0 from 'get_reverse_passing_refs_for_itr' in 'body_extractor.rs' - assert_eq!(*idx, 0); + assert_eq!(idx, 0); self.base.get_subcmp_counter(subcmp_idx) } else { - self.base.get_subcmp_signal(subcmp_idx, *idx) + self.base.get_subcmp_signal(subcmp_idx, idx) } } } @@ -343,7 +341,7 @@ impl<'a> ExtractedFuncEnvData<'a> { signal_idx: usize, new_value: Value, ) -> Result { - //NOTE: This is only called by BucketInterpreter::store_value_in_address. + //NOTE: This is only called by BucketInterpreter::store_value_at_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) { @@ -358,21 +356,19 @@ impl<'a> ExtractedFuncEnvData<'a> { return Ok(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); + let idx = signal_idx + idx; match loc { - AddressType::Variable => self.base.set_var(*idx, new_value), - AddressType::Signal => self.base.set_signal(*idx, new_value), + 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 = Self::unwrap_subcmp_idx(cmp_address); if *counter_override { // ASSERT: always 0 from 'get_reverse_passing_refs_for_itr' in 'body_extractor.rs' - assert_eq!(*idx, 0); + 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.as_u32()?)? } else { - self.base.set_subcmp_signal(subcmp, *idx, new_value)? + self.base.set_subcmp_signal(subcmp, idx, new_value)? } } } diff --git a/circuit_passes/src/bucket_interpreter/mod.rs b/circuit_passes/src/bucket_interpreter/mod.rs index 8c0628c2e..420bbbcf4 100644 --- a/circuit_passes/src/bucket_interpreter/mod.rs +++ b/circuit_passes/src/bucket_interpreter/mod.rs @@ -12,6 +12,7 @@ pub mod write_collector; use std::cell::RefCell; use std::ops::Range; +use compiler::num_traits::Zero; use paste::paste; use code_producers::llvm_elements::{array_switch, fr}; use code_producers::llvm_elements::stdlib::{GENERATED_FN_PREFIX, LLVM_DONOTHING_FN_NAME}; @@ -72,11 +73,11 @@ pub struct BucketInterpreter<'a, 'd> { // buckets do not return a value, only expression-like buckets do. // /// Result of the interpreter "execute" functions -type RE<'e> = Result<(Option, Env<'e>), BadInterp>; +type RE<'e> = Result<(Vec, Env<'e>), BadInterp>; /// Result of the interpreter "compute" functions -type RC = Result, BadInterp>; +type RC = Result, BadInterp>; /// Like 'RE' but with a fully generic environment type -type RG = Result<(Option, E), BadInterp>; +type RG = Result<(Vec, E), BadInterp>; /// Result of the interpreter 'execute_loop_bucket_once()' function type REB<'e> = Result<(Option, Env<'e>), BadInterp>; /// Result of the interpreter 'compute_condition()' function @@ -195,7 +196,9 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { ) -> Self { BucketInterpreter { global_data, observer, flags, mem, scope } } +} +impl BucketInterpreter<'_, '_> { gen_execute_wrapers!(ValueBucket); gen_execute_wrapers!(LoadBucket); gen_execute_wrapers!(StoreBucket); @@ -295,7 +298,10 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { ); //Since this is a public function, make sure all BadInterp cases add location // information and also peel off the Option, converting None into Err. - res.map(|v| opt_as_result(v, label)).flatten().add_loc_if_err(&**location).into() + res.map(|v| into_single_result(v, label)) + .flatten() + .add_loc_if_err(location.as_ref()) + .into() } LocationRule::Mapped { .. } => unreachable!(), } @@ -320,12 +326,34 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { move |s, i, e, o| process(s, i, e, o).map(|v| (v, e)) } + #[inline] + fn new_vec_from(count: usize, f: impl Fn(usize) -> T) -> Vec { + (0..count).map(f).collect() + } + + fn build_indexed_with_offset( + meta: &dyn ObtainMeta, + location: InstructionPointer, + template_header: Option, + i: usize, + ) -> LocationRule { + LocationRule::Indexed { + location: build_compute( + meta, + OperatorType::Add, + 0, + vec![location.clone(), build_u32_value(meta, i)], + ), + template_header: template_header.clone(), + } + } + fn _compute_value_bucket(&self, bucket: &ValueBucket, _: &Env, _: bool) -> RCI { match bucket.parse_as { - ValueType::U32 => InterpRes::Continue(Some(KnownU32(bucket.value))), + ValueType::U32 => InterpRes::Continue(vec![KnownU32(bucket.value)]), ValueType::BigInt => { let constant = &self.mem.get_ff_constant(bucket.value); - to_bigint(constant).add_loc_if_err(bucket).map(|x| Some(KnownBigInt(x))) + to_bigint(constant).add_loc_if_err(bucket).map(|x| vec![KnownBigInt(x)]) } } } @@ -345,7 +373,7 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { // LoadBucket with 'bounded_fn' cannot be interpreted in the normal way. It // must be specific to the function. Currently, there are none that give // a known value so take the conservative approach to always return Unknown. - return InterpRes::Continue(Some(Unknown)); + return InterpRes::Continue(vec![Unknown]); } assert!(bucket.context.size > 0); match &bucket.address_type { @@ -357,12 +385,13 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { observe, "load source variable", )); - if idx.is_unknown() { - return InterpRes::Continue(Some(Unknown)); + return InterpRes::Continue(vec![Unknown; bucket.context.size]); } else { - let val = env.get_var(check_std_res!(idx.as_u32())); - return InterpRes::Continue(Some(val)); + let idx = check_std_res!(idx.as_u32()); + return InterpRes::Continue(Self::new_vec_from(bucket.context.size, |i| { + env.get_var(idx + i) + })); } } AddressType::Signal => { @@ -376,15 +405,17 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { // NOTE: The 'all_signals_unknown' flag must be checked at the very // end so that the remainder of the expression is still visited. if self.flags.all_signals_unknown || idx.is_unknown() { - return InterpRes::Continue(Some(Unknown)); + return InterpRes::Continue(vec![Unknown; bucket.context.size]); } else { - let val = env.get_signal(check_std_res!(idx.as_u32())); - return InterpRes::Continue(Some(val)); + let idx = check_std_res!(idx.as_u32()); + return InterpRes::Continue(Self::new_vec_from(bucket.context.size, |i| { + env.get_signal(idx + i) + })); } } AddressType::SubcmpSignal { cmp_address, .. } => { let addr = check_res!(self._compute_instruction(cmp_address, env, observe)); - let addr = check_std_res!(opt_as_result_u32(addr, "load source subcomponent")); + let addr = check_std_res!(into_single_result_u32(addr, "load source subcomponent")); //NOTE: The 'continue_observing' flag only applies to what is inside the LocationRule. let continue_observing = check_std_res!(observe!( self, @@ -401,7 +432,7 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { env, continue_observing )); - check_std_res!(opt_as_result_u32( + check_std_res!(into_single_result_u32( i, "load source subcomponent indexed signal" )) @@ -417,7 +448,7 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { env, continue_observing )); - let val = check_std_res!(opt_as_result_u32( + let val = check_std_res!(into_single_result_u32( val, "load source subcomponent mapped signal", )); @@ -434,10 +465,11 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { // NOTE: The 'all_signals_unknown' flag must be checked at the very // end so that the remainder of the expression is still visited. if self.flags.all_signals_unknown { - return InterpRes::Continue(Some(Unknown)); + return InterpRes::Continue(vec![Unknown; bucket.context.size]); } else { - let val = env.get_subcmp_signal(addr, idx); - return InterpRes::Continue(Some(val)); + return InterpRes::Continue(Self::new_vec_from(bucket.context.size, |i| { + env.get_subcmp_signal(addr, idx + i) + })); } } }; @@ -453,20 +485,21 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { self._compute_load_bucket(bucket, &env, observe).map(|r| (r, env)) } - fn _store_value_in_address<'env>( + fn _store_value_at_address<'env>( &self, + env: Env<'env>, + observe: bool, address: &AddressType, - location: &LocationRule, + location_base: &LocationRule, + location_offset: usize, location_owner: &BucketId, possible_range: Option>, // use None if no bounds are known value: Value, - env: Env<'env>, - observe: bool, ) -> InterpRes> { match address { AddressType::Variable => { let idx = check_std_res!(self.compute_location_index( - location, + location_base, location_owner, &env, observe, @@ -476,14 +509,14 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { // All variables in the range must be marked as unknown if the index is unknown return InterpRes::Continue(env.set_vars_to_unknown(possible_range)); } else { - let idx = check_std_res!(idx.as_u32()); + let idx = location_offset + check_std_res!(idx.as_u32()); assert!(possible_range.is_none() || possible_range.unwrap().contains(&idx)); return InterpRes::Continue(env.set_var(idx, value)); } } AddressType::Signal => { let idx = check_std_res!(self.compute_location_index( - location, + location_base, location_owner, &env, observe, @@ -493,7 +526,7 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { // All signals in the range must be marked as unknown if the index is unknown return InterpRes::Continue(env.set_signals_to_unknown(possible_range)); } else { - let idx = check_std_res!(idx.as_u32()); + let idx = location_offset + check_std_res!(idx.as_u32()); assert!(possible_range.is_none() || possible_range.unwrap().contains(&idx)); return InterpRes::Continue(env.set_signal(idx, value)); } @@ -502,23 +535,23 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { let (addr, env) = check_res!(self._execute_instruction(cmp_address, env, observe), |(_, e)| e); let addr = - check_std_res!(opt_as_result_u32(addr, "store destination subcomponent")); + check_std_res!(into_single_result_u32(addr, "store destination subcomponent")); //NOTE: The 'continue_observing' flag only applies to what is inside the LocationRule. let continue_observing = check_std_res!(observe!( self, on_location_rule, - location, + location_base, env, observe, location_owner )); - let (idx, env, sub_cmp_name) = match location { + let (idx, env, sub_cmp_name) = match location_base { LocationRule::Indexed { location, template_header } => { let (i, e) = check_res!( self._execute_instruction(location, env, continue_observing), |(_, e)| e ); - let i = check_std_res!(opt_as_result_u32( + let i = check_std_res!(into_single_result_u32( i, "store destination subcomponent indexed signal", )); @@ -537,7 +570,7 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { self._execute_instruction(i, acc_env, continue_observing), |(_, e)| e ); - let val = check_std_res!(opt_as_result_u32( + let val = check_std_res!(into_single_result_u32( val, "store destination subcomponent mapped signal", )); @@ -552,7 +585,7 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { } } }; - + let idx = location_offset + idx; let env = check_std_res!(env.set_subcmp_signal(addr, idx, value)); let env = check_std_res!(env.decrease_subcmp_counter(addr)); if let InputInformation::Input { status } = input_information { @@ -571,12 +604,40 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { }; } + fn _store_values_at_address<'env>( + &self, + address: &AddressType, + base_location: &LocationRule, + location_owner: &BucketId, + values: Vec, + env: Env<'env>, + observe: bool, + ) -> REI<'env> { + let mut new_env = env; + for (i, r) in values.into_iter().enumerate() { + new_env = check_res!( + self._store_value_at_address( + new_env, + observe, + address, + base_location, + i, + location_owner, + None, + r, + ), + |e| (vec![], e) + ) + } + InterpRes::Continue((vec![], new_env)) + } + fn _compute_store_bucket(&self, bucket: &StoreBucket, _: &Env, _: bool) -> RCI { // A StoreBucket that uses the "llvm.donothing" function to // represent a no-op instruction will not update the Env. if let Some(f) = &bucket.bounded_fn { if f.eq(LLVM_DONOTHING_FN_NAME) { - return InterpRes::Continue(None); + return InterpRes::Continue(vec![]); } } // Other StoreBucket will update the Env so "compute" is NOT sufficient. @@ -593,37 +654,37 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { if f.eq(LLVM_DONOTHING_FN_NAME) { // A StoreBucket that uses the "llvm.donothing" function to // represent a no-op instruction will not update the Env. - return InterpRes::Continue((None, env)); + return InterpRes::Continue((vec![], env)); } else if let Some(r) = array_switch::get_array_switch_range(f) { // Here the index is unknown so, regardless of the value, // all values in the range must be set to Unknown. return self - ._store_value_in_address( + ._store_value_at_address( + env, + observe, &bucket.dest_address_type, &bucket.dest, + 0, &bucket.id, Some(r), Unknown, - env, - observe, ) - .map(|e| (None, e)); + .map(|e| (vec![], e)); } else { todo!("Unexpected bounded_fn: {}", f); } } else { let (src, env) = check_res!(self._execute_instruction(&bucket.src, env, observe)); - let src = check_std_res!(opt_as_result(src, "store source value")); - self._store_value_in_address( + // Assert expected number of results was produced + assert_eq!(bucket.context.size, src.len()); + self._store_values_at_address( &bucket.dest_address_type, &bucket.dest, &bucket.id, - None, src, env, observe, ) - .map(|e| (None, e)) } } @@ -638,16 +699,17 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { let mut env = env; for i in &bucket.stack { let (val, new_env) = check_res!(process(&self, i, env, observe)); - let val = check_std_res!(opt_as_result(val, format!("{:?} operand", bucket.op))); + let val = check_std_res!(into_single_result(val, format!("{:?} operand", bucket.op))); stack.push(val); env = new_env; } // If any value of the stack is unknown we just return Unknown if stack.iter().any(Value::is_unknown) { - InterpRes::Continue((Some(Unknown), env)) + InterpRes::Continue((vec![Unknown], env)) } else { InterpRes::try_continue( operations::compute_operation(bucket, &stack, self.mem.get_prime()) + .map(into_singleton_vec) .map(|v| (v, env)), ) } @@ -683,7 +745,7 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { // calls below (that give ownership of the 'env' object into the new Env instance) // to avoid copying the entire 'env' instance (which is likely more expensive). let instructions = env.get_function(name).body.clone(); - let mut res = (None, { + let mut res = (vec![], { 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()]; @@ -707,7 +769,9 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { res = Result::from(interp._execute_instruction(inst, res.1, observe))?; } } - //Remove the Env::ExtractedFunction wrapper + // ASSERT: All generated functions have void return type, thus produce no value(s) + assert!(res.0.is_empty()); + // Remove the Env::ExtractedFunction wrapper Result::Ok((res.0, res.1.peel_extracted_func())) } @@ -751,18 +815,30 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { // Restore the parent scope self.mem.set_scope(parent_scope); - // CHECK: All Circom source functions must return a value, unless - // self.flags.allow_nondetermined_return() == false because that - // case could result in no return statements being observed. - let func_val = if body_val.is_none() && !self.flags.allow_nondetermined_return() { - Some(Value::Unknown) + // CHECK: All Circom source functions must return the correct number + // of values, equal to the product of the return type dimensions, + // unless self.flags.allow_nondetermined_return() == false because + // that case could result in no return statements being observed. + let func_val = if body_val.is_empty() && !self.flags.allow_nondetermined_return() { + // Some(Value::Unknown) // TODO: return the correct number of Unknowns + Result::Ok(vec![Value::Unknown; callee.returns.iter().product::()]) } else { - body_val + let vals = into_result(body_val, "value returned from function"); + assert!( + vals.is_err() + || vals + .as_ref() + .is_ok_and(|v| v.len() == callee.returns.iter().product::()) + ); + vals }; // Return the original Env, not the new one that is internal to the function. - opt_as_result(func_val, "value returned from function").map(|v| (Some(v), env)) + func_val.map(|v| (v, env)) } else { - Ok((Some(Value::Unknown), env)) + // Produce the correct number of return values + let callee = self.mem.get_function(&bucket.symbol); + let return_size = callee.returns.iter().product::(); + Ok((vec![Value::Unknown; return_size], env)) } } @@ -815,15 +891,12 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { line: load.line, message_id: load.message_id, address_type: load.address_type.clone(), - src: LocationRule::Indexed { - location: build_compute( - load, - OperatorType::Add, - 0, - vec![location.clone(), build_u32_value(load, i)], - ), - template_header: template_header.clone(), - }, + src: Self::build_indexed_with_offset( + load, + location.clone(), + template_header.clone(), + i, + ), context: InstrContext { size: 1 }, bounded_fn: None, } @@ -832,7 +905,7 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { self._compute_instruction(&scalar_load, &env, observe), |v| (v, env) ); - args.push(check_std_res!(opt_as_result( + args.push(check_std_res!(into_single_result( val, "function argument" ))); @@ -844,7 +917,7 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { } // Case: anything else let val = check_res!(self._compute_instruction(a, &env, observe), |v| (v, env)); - args.push(check_std_res!(opt_as_result(val, "function argument"))); + args.push(check_std_res!(into_single_result(val, "function argument"))); } check_res!(InterpRes::try_continue( self._execute_function_basic(&bucket, env, args, observe) @@ -854,17 +927,38 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { // Write the result in the destination according to the ReturnType match &bucket.return_info { ReturnType::Intermediate { .. } => InterpRes::Continue(res), - ReturnType::Final(final_data) => self - ._store_value_in_address( + ReturnType::Final(final_data) => { + // If a vector is returned that is smaller than the return type, the circom frontend + // gives the warning "Mismatched dimensions, assigning to an array an expression of + // smaller length, the remaining positions are assigned to 0." + assert!(res.0.len() <= final_data.context.size); + let mut new_env = res.1; + if res.0.len() < final_data.context.size { + for i in res.0.len()..final_data.context.size { + new_env = check_res!( + self._store_value_at_address( + new_env, + observe, + &final_data.dest_address_type, + &final_data.dest, + i, + &bucket.id, + None, + Value::KnownBigInt(BigInt::zero()), + ), + |e| (vec![], e) + ) + } + } + self._store_values_at_address( &final_data.dest_address_type, &final_data.dest, &bucket.id, - None, - check_std_res!(opt_as_result(res.0, "function return value")), - res.1, + res.0, + new_env, observe, ) - .map(|x| (None, x)), + } } } @@ -948,7 +1042,7 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { process: impl Fn(&'s Self, &'i InstructionPointer, E, bool) -> RGI, ) -> RGI { let (cond, env) = check_res!(process(&self, &bucket.evaluate, env, observe)); - let cond = check_std_res!(opt_as_result(cond, "assert condition")); + let cond = check_std_res!(into_single_result(cond, "assert condition")); if !cond.is_unknown() && !check_std_res!(cond.to_bool(self.mem.get_prime())) { // Based on 'constraint_generation::execute::treat_result_with_execution_error' InterpRes::Err(BadInterp::error( @@ -956,7 +1050,7 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { ReportCode::RuntimeError, )) } else { - InterpRes::Continue((None, env)) + InterpRes::Continue((vec![], env)) } } @@ -980,7 +1074,7 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { check_res!(self._compute_instruction(i, env, observe)); } } - InterpRes::Continue(None) + InterpRes::Continue(vec![]) } fn _execute_log_bucket<'env>( @@ -1000,10 +1094,10 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { observe: bool, ) -> InterpRes> { self._compute_instruction(cond, env, observe) - .expect_some("branch condition") + .expect_single("branch condition") //NOTE: `to_bool` returns an Err if the condition is Unknown. // Here we must instead treat that error case as Option::None. - .map(|v| v.unwrap().to_bool(self.mem.get_prime()).ok()) + .map(|v| v.to_bool(self.mem.get_prime()).ok()) } fn _execute_condition<'env>( @@ -1037,27 +1131,46 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { } None => { // Must visit both branch bodies, ignore the result but if either - // had an early return the result must reflect that if requested. + // had an early return the result must reflect that, if requested. let observe_inside = observe & self.flags.visit_unknown_condition_branches; let tb_res = process_body(&self, &true_branch, env.clone(), observe_inside); let fb_res = process_body(&self, &false_branch, env.clone(), observe_inside); // Circom semantics do NOT allow a conditional statement to produce a value like this: // var x = if (a < 7) { 0 } else { 1 } - // Thus, only an `InterpRes::Return` result can contain `Some(Value)` and that case can - // occur when there is a return statement within the body of the branch. + // Thus, only an `InterpRes::Return` result can contain non-empty Vec and that + // case can occur when there is a return statement within the body of the branch. // - // ASSERT: `InterpRes::Continue`` must have `None`` for the value! - assert!(!matches!(tb_res, InterpRes::Continue((Some(_), _))), "{:?}", tb_res); - assert!(!matches!(fb_res, InterpRes::Continue((Some(_), _))), "{:?}", fb_res); - if self.flags.allow_nondetermined_return() - && (tb_res.is_return() || fb_res.is_return()) - { - // When the condition is Unknown, the actual value returned is Unknown - InterpRes::Return((Some(Value::Unknown), None, env)) - } else { - // As stated above, Continue must return None for the value - InterpRes::Continue((None, None, env)) + // ASSERT: `InterpRes::Continue` must have an empty value vector + assert_eq!( + false, + matches!(&tb_res, InterpRes::Continue((x, _)) if !x.is_empty()), + "Unexpected: value(s) produced without a RETURN: {:?}", + tb_res + ); + assert_eq!( + false, + matches!(&fb_res, InterpRes::Continue((x, _)) if !x.is_empty()), + "Unexpected: value(s) produced without a RETURN: {:?}", + fb_res + ); + // ASSERT: If both branches return, they must produce the same number of values + assert!(match (&tb_res, &fb_res) { + (InterpRes::Return((a, _)), InterpRes::Return((b, _))) => a.len() == b.len(), + _ => true, + }); + + if self.flags.allow_nondetermined_return() { + // When the condition is Unknown, the proper number of + // Unknown values must be returned with the original Env. + if let InterpRes::Return((a, _)) = tb_res { + return InterpRes::Return((vec![Value::Unknown; a.len()], None, env)); + } + if let InterpRes::Return((a, _)) = fb_res { + return InterpRes::Return((vec![Value::Unknown; a.len()], None, env)); + } } + // As stated above, Continue must not return any values. + InterpRes::Continue((vec![], None, env)) } } } @@ -1069,7 +1182,7 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { false_branch: &[InstructionPointer], env: &Env, observe: bool, - ) -> InterpRes<(Option, Option)> { + ) -> InterpRes<(Vec, Option)> { self._impl_conditional_bucket( cond, true_branch, @@ -1114,9 +1227,9 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { E, bool, ) -> RBI, - handle_unknown: impl Fn(&Self, &InstructionList, E, Option) -> RG, + handle_unknown: impl Fn(&Self, &InstructionList, E, Vec) -> RG, ) -> RGI { - let mut last_value = Some(Unknown); + let mut last_value = vec![Unknown]; let mut loop_env = env; let mut n_iters = 0; loop { @@ -1191,7 +1304,7 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { observe: bool, ) -> REI<'env> { let (cmp_id, env) = check_res!(self._execute_instruction(&bucket.sub_cmp_id, env, observe)); - let cmp_id = check_std_res!(opt_as_result_u32(cmp_id, "ID of subcomponent!")); + let cmp_id = check_std_res!(into_single_result_u32(cmp_id, "ID of subcomponent!")); let mut env = env.create_subcmp(&bucket.symbol, cmp_id, bucket.number_of_cmp, bucket.template_id); // Run the subcomponents with 0 inputs directly @@ -1200,7 +1313,7 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { env = env.run_subcmp(i, &bucket.symbol, self); } } - InterpRes::Continue((None, env)) + InterpRes::Continue((vec![], env)) } fn _compute_constraint_bucket( @@ -1235,7 +1348,7 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { } fn _compute_nop_bucket(&self, _bucket: &NopBucket, _env: &Env, _observe: bool) -> RCI { - InterpRes::Continue(None) + InterpRes::Continue(vec![]) } fn _execute_nop_bucket<'env>( @@ -1278,7 +1391,7 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { env: &Env, observe: bool, ) -> RCI { - let mut last = None; + let mut last = vec![]; for i in instructions { // Append location if Err to give more specific line information // Use "check" so any Err or Return case returns without processing the rest. @@ -1322,7 +1435,7 @@ impl<'a: 'd, 'd> BucketInterpreter<'a, 'd> { env: Env<'env>, observe: bool, ) -> REI<'env> { - let mut last = (None, env); + let mut last = (vec![], env); for i in instructions { // Append location if Err to give more specific line information. // Use "check" so any Err or Return case returns without processing the rest. diff --git a/circuit_passes/src/bucket_interpreter/result_types.rs b/circuit_passes/src/bucket_interpreter/result_types.rs index 05dc9ef7d..68873e11b 100644 --- a/circuit_passes/src/bucket_interpreter/result_types.rs +++ b/circuit_passes/src/bucket_interpreter/result_types.rs @@ -11,13 +11,13 @@ pub(crate) enum InterpRes { } /// Like 'super::RE' but internally uses InterpRes instead of Result -pub(crate) type REI<'e> = InterpRes<(Option, Env<'e>)>; +pub(crate) type REI<'e> = InterpRes<(Vec, Env<'e>)>; /// Like 'super::RC' but internally uses InterpRes instead of Result -pub(crate) type RCI = InterpRes>; +pub(crate) type RCI = InterpRes>; /// Like 'super::RG' but internally uses InterpRes instead of Result -pub(crate) type RGI = InterpRes<(Option, E)>; +pub(crate) type RGI = InterpRes<(Vec, E)>; /// Like 'RGI' but the value of a condition is also needed -pub(crate) type RBI = InterpRes<(Option, Option, E)>; +pub(crate) type RBI = InterpRes<(Vec, Option, E)>; impl InterpRes { #[inline] @@ -38,12 +38,6 @@ impl InterpRes { } } - #[must_use] - #[inline] - pub fn is_return(&self) -> bool { - matches!(self, InterpRes::Return(_)) - } - #[must_use] #[inline] pub fn map U>(self, op: F) -> InterpRes { @@ -78,17 +72,12 @@ impl InterpRes> { } } -impl InterpRes> { - /// NOTE: It is safe to use [Option::unwrap] on the Continue/Return variants of the return value +impl InterpRes> { #[must_use] - pub fn expect_some(self, label: S) -> Self { + pub fn expect_single(self, label: S) -> InterpRes { match self { - InterpRes::Continue(v) => { - InterpRes::try_continue(opt_as_result(v, label).map(Option::Some)) - } - InterpRes::Return(v) => { - InterpRes::try_return(opt_as_result(v, label).map(Option::Some)) - } + InterpRes::Continue(v) => InterpRes::try_continue(into_single_result(v, label)), + InterpRes::Return(v) => InterpRes::try_return(into_single_result(v, label)), InterpRes::Err(e) => InterpRes::Err(e), } } @@ -138,18 +127,54 @@ macro_rules! check_std_res { }}; } +#[inline] #[must_use] -pub fn opt_as_result(value: Option, label: S) -> Result { +pub fn into_singleton_vec(value: Option) -> Vec { match value { - Some(v) => Result::Ok(v), - None => Result::Err(new_compute_err(format!("Could not compute {}!", label))), + Some(v) => vec![v], + None => vec![], } } +#[inline] #[must_use] -pub fn opt_as_result_u32( - value: Option, +pub fn into_single_option(values: Vec) -> Option { + let mut values = values; + match values.len() { + 1 => values.pop(), + _ => None, + } +} + +#[inline] +#[must_use] +pub fn into_single_result_u32( + values: Vec, label: S, ) -> Result { - opt_as_result(value, label).and_then(Value::as_u32) + into_single_result(values, label).and_then(Value::as_u32) +} + +#[must_use] +pub fn into_single_result( + values: Vec, + label: S, +) -> Result { + let mut values = values; + match &values[..] { + [] => Result::Err(new_compute_err(format!("Could not compute {}!", label))), + [_] => Result::Ok(values.remove(0)), + [head, tail @ ..] => { + let s = tail.iter().fold(format!("{}", head), |acc, nxt| format!("{},{}", acc, nxt)); + Result::Err(new_compute_err(format!("Non-scalar value for {}: [{}]", label, s))) + } + } +} + +#[must_use] +pub fn into_result(values: Vec, label: S) -> Result, BadInterp> { + match &values[..] { + [] => Result::Err(new_compute_err(format!("Could not compute {}!", label))), + _ => Result::Ok(values), + } } diff --git a/circuit_passes/src/passes/deterministic_subcomponent_invocation.rs b/circuit_passes/src/passes/deterministic_subcomponent_invocation.rs index e95d65120..79b9a232d 100644 --- a/circuit_passes/src/passes/deterministic_subcomponent_invocation.rs +++ b/circuit_passes/src/passes/deterministic_subcomponent_invocation.rs @@ -7,6 +7,7 @@ use crate::bucket_interpreter::env::Env; use crate::bucket_interpreter::error::BadInterp; use crate::bucket_interpreter::memory::PassMemory; use crate::bucket_interpreter::observer::Observer; +use crate::bucket_interpreter::result_types; use crate::{checked_insert, default__get_mem, default__name, default__run_template}; use super::{CircuitTransformationPass, GlobalPassData}; @@ -42,9 +43,7 @@ impl<'d> DeterministicSubCmpInvokePass<'d> { { let interpreter = self.memory.build_interpreter(self.global_data, self); let addr = interpreter.compute_instruction(cmp_address, env, false)?; - let addr = addr - .expect("cmp_address instruction in SubcmpSignal must produce a value!") - .as_u32()?; + let addr = result_types::into_single_result_u32(addr, "address of subcomponent")?; let new_status = if env.subcmp_counter_equal_to(addr, 1) { Last } else { NoLast }; checked_insert!(self.replacements.borrow_mut(), address_type.clone(), new_status); } 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 29ebcbcc5..b4f5670d1 100644 --- a/circuit_passes/src/passes/loop_unroll/loop_env_recorder.rs +++ b/circuit_passes/src/passes/loop_unroll/loop_env_recorder.rs @@ -8,6 +8,7 @@ use crate::bucket_interpreter::env::{Env, EnvContextKind}; use crate::bucket_interpreter::error::BadInterp; use crate::bucket_interpreter::memory::PassMemory; use crate::bucket_interpreter::observer::Observer; +use crate::bucket_interpreter::result_types; use crate::bucket_interpreter::value::Value; use crate::passes::GlobalPassData; use super::DEBUG_LOOP_UNROLL; @@ -144,14 +145,15 @@ impl<'a, 'd> EnvRecorder<'a, 'd> { // not safe to move the loop body to another function because the index computation may // not give the same result when done at the call site, outside of the new function. let interp = self.mem.build_interpreter(self.global_data, self); - if let Some(idx_loc) = interp.compute_instruction(location, env, false)? { + let computed_idx = interp.compute_instruction(location, env, false)?; + if let Some(idx_loc) = result_types::into_single_option(computed_idx) { // NOTE: It's possible for the interpreter to run into problems evaluating the location // using the header Env. For example, a value may not have been defined yet so address // computations on that value could give out of range results for the 'usize' type. // Thus, these errors should be ignored and fall through into the Ok(Unknown) case. let env_ref = self.env_at_header.borrow(); let header_res = interp.compute_instruction(location, env_ref.as_ref().unwrap(), false); - if let Ok(Some(idx_header)) = header_res { + if let Ok(Some(idx_header)) = header_res.map(result_types::into_single_option) { if Value::eq(&idx_header, &idx_loc) { return Ok(idx_loc); } diff --git a/circuit_passes/src/passes/mapped_to_indexed.rs b/circuit_passes/src/passes/mapped_to_indexed.rs index 2f344b9c1..5e86de1e5 100644 --- a/circuit_passes/src/passes/mapped_to_indexed.rs +++ b/circuit_passes/src/passes/mapped_to_indexed.rs @@ -8,7 +8,7 @@ use crate::bucket_interpreter::error::BadInterp; use crate::bucket_interpreter::memory::PassMemory; use crate::bucket_interpreter::observer::Observer; use crate::bucket_interpreter::operations::compute_offset; -use crate::bucket_interpreter::result_types::opt_as_result_u32; +use crate::bucket_interpreter::result_types::into_single_result_u32; use crate::bucket_interpreter::value::Value::KnownU32; use crate::{checked_insert, default__get_mem, default__name, default__run_template}; use super::{CircuitTransformationPass, GlobalPassData}; @@ -43,7 +43,7 @@ impl<'d> MappedToIndexedPass<'d> { let interpreter = self.memory.build_interpreter(self.global_data, self); let resolved_addr = interpreter .compute_instruction(cmp_address, env, false) - .and_then(|v| opt_as_result_u32(v, "subcomponent address"))?; + .and_then(|v| into_single_result_u32(v, "subcomponent address"))?; let name = env.get_subcmp_name(resolved_addr).clone(); let io_def = self.memory.get_iodef(&env.get_subcmp_template_id(resolved_addr), &signal_code); @@ -52,7 +52,7 @@ impl<'d> MappedToIndexedPass<'d> { for i in indexes { let val = interpreter .compute_instruction(i, env, false) - .and_then(|v| opt_as_result_u32(v, "subcomponent mapped signal"))?; + .and_then(|v| into_single_result_u32(v, "subcomponent mapped signal"))?; indexes_values.push(val); } io_def.offset + compute_offset(&indexes_values, &io_def.lengths)? diff --git a/circuit_passes/src/passes/simplification.rs b/circuit_passes/src/passes/simplification.rs index 9b6c99eb5..fd1bd5ab7 100644 --- a/circuit_passes/src/passes/simplification.rs +++ b/circuit_passes/src/passes/simplification.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use compiler::circuit_design::template::TemplateCode; use compiler::intermediate_representation::{new_id, BucketId, InstructionPointer}; use compiler::intermediate_representation::ir_interface::*; -use crate::bucket_interpreter::{InterpreterFlags, BucketInterpreter, operations}; +use crate::bucket_interpreter::{operations, result_types, BucketInterpreter, InterpreterFlags}; use crate::bucket_interpreter::env::Env; use crate::bucket_interpreter::error::BadInterp; use crate::bucket_interpreter::memory::PassMemory; @@ -83,7 +83,7 @@ impl Observer> for SimplificationPass<'_> { fn on_compute_bucket(&self, bucket: &ComputeBucket, env: &Env) -> Result { let interp = self.build_interpreter(); let v = interp.compute_compute_bucket(bucket, env, false)?; - let v = v.expect("Compute bucket must produce a value!"); + let v = result_types::into_single_result(v, "ComputeBucket")?; if !v.is_unknown() { Self::insert(&self.compute_replacements, bucket.id, v); Ok(false) @@ -94,8 +94,11 @@ impl Observer> for SimplificationPass<'_> { fn on_call_bucket(&self, bucket: &CallBucket, env: &Env) -> Result { let interp = self.build_interpreter(); - if let Some(v) = interp.compute_call_bucket(bucket, env, false)? { - // Call buckets may not return a value directly + let v = interp.compute_call_bucket(bucket, env, false)?; + // CallBucket may not return a value directly so use 'into_single_option()' + // rather than 'into_single_result()' and return 'true' in the None case + // so buckets nested within this bucket will be observed. + if let Some(v) = result_types::into_single_option(v) { if !v.is_unknown() { Self::insert(&self.call_replacements, bucket.id, v); return Ok(false); @@ -122,7 +125,7 @@ impl Observer> for SimplificationPass<'_> { // Leave this Observer enabled so that ComputeBucket w/in the RHS expression // could be simplified even if the entire expression will not be simplified. let v = interp.compute_instruction(inst, env, true)?; - let v = v.expect("Compute bucket operand must produce a value!"); + let v = result_types::into_single_result(v, "operand of compute")?; values.push(v); } // If at least one is a known value, then we can (likely) simplify @@ -142,7 +145,7 @@ impl Observer> for SimplificationPass<'_> { // Leave this Observer enabled so that ComputeBucket w/in the RHS expression // could be simplified even if the entire expression will not be simplified. let v = interp.compute_instruction(&bucket.src, env, true)?; - v.expect("Store bucket source must produce a value!") + result_types::into_single_result(v, "source of store")? }; // Interpret the LHS memory reference @@ -159,7 +162,7 @@ impl Observer> for SimplificationPass<'_> { &bucket.dest_address_type { let v = interp.compute_instruction(cmp_address, env, false)?; - v.expect("Store bucket source must produce a value!") + result_types::into_single_result(v, "source of store")? } else { Value::Unknown }; diff --git a/circuit_passes/src/passes/unknown_index_sanitization.rs b/circuit_passes/src/passes/unknown_index_sanitization.rs index 1ba12722c..18fd19426 100644 --- a/circuit_passes/src/passes/unknown_index_sanitization.rs +++ b/circuit_passes/src/passes/unknown_index_sanitization.rs @@ -11,7 +11,7 @@ use crate::bucket_interpreter::env::Env; use crate::bucket_interpreter::error::BadInterp; use crate::bucket_interpreter::memory::PassMemory; use crate::bucket_interpreter::observer::Observer; -use crate::bucket_interpreter::result_types::{InterpRes, RCI}; +use crate::bucket_interpreter::result_types::{self, InterpRes, RCI}; use crate::bucket_interpreter::value::Value::{self, KnownBigInt, KnownU32}; use crate::{check_res, checked_insert, default__get_mem, default__name, default__run_template}; use super::{CircuitTransformationPass, GlobalPassData}; @@ -27,33 +27,34 @@ impl<'a> ZeroingInterpreter<'a> { pub fn compute_value_bucket(&self, bucket: &ValueBucket, _env: &Env) -> RCI { match bucket.parse_as { - ValueType::U32 => InterpRes::Continue(Some(KnownU32(bucket.value))), + ValueType::U32 => InterpRes::Continue(vec![KnownU32(bucket.value)]), ValueType::BigInt => { let constant = &self.mem.get_ff_constant(bucket.value); - to_bigint(constant).add_loc_if_err(bucket).map(|r| Some(KnownBigInt(r))) + to_bigint(constant).add_loc_if_err(bucket).map(|r| vec![KnownBigInt(r)]) } } } pub fn compute_load_bucket(&self, _bucket: &LoadBucket, _env: &Env) -> RCI { - InterpRes::Continue(Some(KnownU32(0))) + InterpRes::Continue(vec![KnownU32(0)]) } pub fn compute_compute_bucket(&self, bucket: &ComputeBucket, env: &Env) -> RCI { let mut stack: Vec = Vec::with_capacity(bucket.stack.len()); for i in &bucket.stack { - let value = check_res!(self.compute_instruction(i, env).expect_some("operand")); - stack.push(value.unwrap()); + stack.push(check_res!( + self.compute_instruction(i, env).expect_single("operand"), + |e| vec![e] + )); } // If any value of the stack is unknown we just return 0 if stack.iter().any(|v| v.is_unknown()) { - InterpRes::Continue(Some(KnownU32(0))) + InterpRes::Continue(vec![KnownU32(0)]) } else { - InterpRes::try_continue(operations::compute_operation( - bucket, - &stack, - self.mem.get_prime(), - )) + InterpRes::try_continue( + operations::compute_operation(bucket, &stack, self.mem.get_prime()) + .map(result_types::into_singleton_vec), + ) } } @@ -111,7 +112,7 @@ impl<'d> UnknownIndexSanitizationPass<'d> { let mem = &self.memory; let interpreter = ZeroingInterpreter::init(mem); let res = Result::from(interpreter.compute_instruction(location, env))?; - let offset = match res { + let offset = match result_types::into_single_option(res) { Some(KnownU32(base)) => base, _ => unreachable!(), };