neo_solidity/cli/ir_optimize/
optimize.rs

1/// IR optimization hook. Currently performs simple control-flow cleanup to drop
2/// instructions that appear after a terminal return in a basic block.
3pub(crate) fn optimize_ir(mut module: ir::Module, optimizer_level: u8) -> ir::Module {
4    if optimizer_level == 0 {
5        return module;
6    }
7
8    let enable_neovm_specific = optimizer_level >= 3;
9    let enable_constant_folding = optimizer_level >= 2;
10
11    for function in &mut module.functions {
12        let mut label_remap = std::collections::HashMap::new();
13
14        for block in &mut function.basic_blocks {
15            let mut trimmed = Vec::with_capacity(block.instructions.len());
16            let mut terminated = false;
17
18            for instr in block.instructions.drain(..) {
19                if terminated {
20                    // Preserve labels so jump targets remain addressable, drop other ops.
21                    if matches!(instr, ir::Instruction::Label(_)) {
22                        trimmed.push(instr);
23                        terminated = false; // New label can be targeted, resume collection
24                    }
25                    continue;
26                }
27
28                match instr {
29                    ir::Instruction::Return
30                    | ir::Instruction::ReturnVoid
31                    | ir::Instruction::ReturnDefault(_) => {
32                        trimmed.push(instr);
33                        terminated = true;
34                    }
35                    ir::Instruction::Jump { .. } => {
36                        trimmed.push(instr);
37                        terminated = true;
38                    }
39                    ir::Instruction::Abort
40                    | ir::Instruction::AbortMsg
41                    | ir::Instruction::Throw => {
42                        trimmed.push(instr);
43                        terminated = true;
44                    }
45                    ir::Instruction::EndTry { .. } => {
46                        trimmed.push(instr);
47                        terminated = true;
48                    }
49                    other => trimmed.push(other),
50                }
51            }
52
53            block.instructions = trimmed;
54
55            if enable_constant_folding {
56                fold_constant_binary_ops(block);
57            }
58
59            if enable_neovm_specific {
60                dedupe_labels(block, &mut label_remap);
61                remove_trivial_jumps(block);
62
63                // NeoVM-specific optimizations at O3
64                neovm_peephole_optimize(block);
65                neovm_simplify_identity_ops(block);
66                neovm_bool_optimize(block);
67
68                // Run peephole again to catch newly exposed patterns
69                neovm_peephole_optimize(block);
70            }
71        }
72
73        if enable_neovm_specific && !label_remap.is_empty() {
74            retarget_jumps(&mut function.basic_blocks, &label_remap);
75        }
76    }
77
78    module
79}