sp1_recursion_executor/
analyzed.rs1use serde::{Deserialize, Serialize};
2
3use crate::{
4 instruction::{HintBitsInstr, HintExt2FeltsInstr, HintInstr, Instruction},
5 program::RawProgram,
6 BasicBlock, RecursionAirEventCount, SeqBlock,
7};
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct AnalyzedInstruction<F> {
12 pub(crate) inner: Instruction<F>,
13 pub(crate) offset: usize,
14}
15
16impl<F> AnalyzedInstruction<F> {
17 pub const fn new(inner: Instruction<F>, offset: usize) -> Self {
18 Self { inner, offset }
19 }
20
21 pub const fn inner(&self) -> &Instruction<F> {
22 &self.inner
23 }
24}
25
26impl<F> RawProgram<Instruction<F>> {
27 pub fn analyze(self) -> (RawProgram<AnalyzedInstruction<F>>, RecursionAirEventCount) {
35 fn analyze_block<T>(
36 block: SeqBlock<Instruction<T>>,
37 counts: &mut RecursionAirEventCount,
38 ) -> SeqBlock<AnalyzedInstruction<T>> {
39 fn incr(num: &mut usize, amt: usize) -> usize {
41 let start = *num;
42 *num += amt;
43
44 start
45 }
46
47 match block {
48 SeqBlock::Basic(instrs) => {
49 let analyzed = instrs
50 .instrs
51 .into_iter()
52 .map(|instr| {
53 let start_offset = match &instr {
54 Instruction::BaseAlu(_) => incr(&mut counts.base_alu_events, 1),
55 Instruction::ExtAlu(_) => incr(&mut counts.ext_alu_events, 1),
56 Instruction::Mem(_) => incr(&mut counts.mem_const_events, 1),
57 Instruction::ExtFelt(_) => {
58 incr(&mut counts.ext_felt_conversion_events, 1)
59 }
60 Instruction::Poseidon2(_) => {
61 incr(&mut counts.poseidon2_wide_events, 1)
62 }
63 Instruction::Poseidon2LinearLayer(_) => {
64 incr(&mut counts.poseidon2_linear_layer_events, 1)
65 }
66 Instruction::Poseidon2SBox(_) => {
67 incr(&mut counts.poseidon2_sbox_events, 1)
68 }
69 Instruction::Select(_) => incr(&mut counts.select_events, 1),
70 Instruction::Hint(HintInstr { output_addrs_mults })
71 | Instruction::HintBits(HintBitsInstr {
72 output_addrs_mults,
73 input_addr: _, }) => incr(&mut counts.mem_var_events, output_addrs_mults.len()),
75 Instruction::HintExt2Felts(HintExt2FeltsInstr {
76 output_addrs_mults,
77 input_addr: _, }) => incr(&mut counts.mem_var_events, output_addrs_mults.len()),
79 Instruction::PrefixSumChecks(instr) => {
80 incr(&mut counts.prefix_sum_checks_events, instr.addrs.x1.len())
81 }
82 Instruction::HintAddCurve(instr) => incr(
83 &mut counts.mem_var_events,
84 instr.output_x_addrs_mults.len()
85 + instr.output_y_addrs_mults.len(),
86 ),
87 Instruction::CommitPublicValues(_) => {
88 incr(&mut counts.commit_pv_hash_events, 1)
89 }
90 Instruction::Print(_) | Instruction::DebugBacktrace(_) => 0,
93 };
94
95 AnalyzedInstruction::new(instr, start_offset)
96 })
97 .collect();
98
99 SeqBlock::Basic(BasicBlock { instrs: analyzed })
100 }
101 SeqBlock::Parallel(par_blocks) => {
102 let analyzed = par_blocks
103 .into_iter()
104 .map(|basic_blocks| {
105 let analyzed: Vec<_> = basic_blocks
106 .seq_blocks
107 .into_iter()
108 .map(|block| analyze_block(block, counts))
109 .collect();
110
111 RawProgram { seq_blocks: analyzed }
112 })
113 .collect();
114
115 SeqBlock::Parallel(analyzed)
116 }
117 }
118 }
119
120 let mut counts = RecursionAirEventCount::default();
121 let analyzed_blocks =
122 self.seq_blocks.into_iter().map(|block| analyze_block(block, &mut counts)).collect();
123
124 (RawProgram { seq_blocks: analyzed_blocks }, counts)
125 }
126}