neo_solidity/cli/ir_optimize/
neovm.rs1fn neovm_peephole_optimize(block: &mut ir::BasicBlock) {
3 let mut optimized = Vec::with_capacity(block.instructions.len());
4 let mut i = 0;
5
6 while i < block.instructions.len() {
7 if i + 1 < block.instructions.len() {
9 if matches!(&block.instructions[i], ir::Instruction::PushLiteral(_))
10 && matches!(&block.instructions[i + 1], ir::Instruction::Drop(_))
11 {
12 i += 2;
13 continue;
14 }
15
16 if matches!(&block.instructions[i], ir::Instruction::LoadLocal(_))
18 && matches!(&block.instructions[i + 1], ir::Instruction::Drop(_))
19 {
20 i += 2;
21 continue;
22 }
23
24 if matches!(&block.instructions[i], ir::Instruction::Dup)
26 && matches!(&block.instructions[i + 1], ir::Instruction::Drop(_))
27 {
28 i += 2;
29 continue;
30 }
31 }
32
33 if i + 1 < block.instructions.len() {
35 if let (
36 ir::Instruction::StoreLocal(store_idx),
37 ir::Instruction::LoadLocal(load_idx),
38 ) = (&block.instructions[i], &block.instructions[i + 1]) {
39 if store_idx == load_idx {
40 optimized.push(ir::Instruction::Dup);
41 optimized.push(ir::Instruction::StoreLocal(*store_idx));
42 i += 2;
43 continue;
44 }
45 }
46 }
47
48 if i + 1 < block.instructions.len()
50 && matches!(&block.instructions[i], ir::Instruction::Swap)
51 && matches!(&block.instructions[i + 1], ir::Instruction::Swap)
52 {
53 i += 2;
54 continue;
55 }
56
57 optimized.push(block.instructions[i].clone());
58 i += 1;
59 }
60
61 block.instructions = optimized;
62}
63
64fn neovm_simplify_identity_ops(block: &mut ir::BasicBlock) {
66 use num_bigint::BigInt;
67 use num_traits::Zero;
68
69 let mut optimized = Vec::with_capacity(block.instructions.len());
70 let mut i = 0;
71
72 while i < block.instructions.len() {
73 if i + 1 < block.instructions.len() {
75 if let ir::Instruction::PushLiteral(ir::LiteralValue::Integer(val)) =
76 &block.instructions[i]
77 {
78 if val.is_zero() {
79 if let ir::Instruction::BinaryOp(ir::BinaryOperator::Add) =
80 &block.instructions[i + 1]
81 {
82 i += 2;
84 continue;
85 }
86 if let ir::Instruction::BinaryOp(ir::BinaryOperator::Sub) =
87 &block.instructions[i + 1]
88 {
89 i += 2;
91 continue;
92 }
93 if let ir::Instruction::BinaryOp(ir::BinaryOperator::BitOr) =
94 &block.instructions[i + 1]
95 {
96 i += 2;
98 continue;
99 }
100 if let ir::Instruction::BinaryOp(ir::BinaryOperator::BitXor) =
101 &block.instructions[i + 1]
102 {
103 i += 2;
105 continue;
106 }
107 }
108 if *val == BigInt::from(1) {
110 if let ir::Instruction::BinaryOp(ir::BinaryOperator::Mul) =
111 &block.instructions[i + 1]
112 {
113 i += 2;
114 continue;
115 }
116 if let ir::Instruction::BinaryOp(ir::BinaryOperator::Div) =
117 &block.instructions[i + 1]
118 {
119 i += 2;
121 continue;
122 }
123 }
124 }
125 }
126
127 optimized.push(block.instructions[i].clone());
128 i += 1;
129 }
130
131 block.instructions = optimized;
132}
133
134fn neovm_bool_optimize(block: &mut ir::BasicBlock) {
136 let mut optimized = Vec::with_capacity(block.instructions.len());
137 let mut i = 0;
138
139 while i < block.instructions.len() {
140 if i + 1 < block.instructions.len() {
142 if let ir::Instruction::PushLiteral(ir::LiteralValue::Boolean(true)) =
143 &block.instructions[i]
144 {
145 if let ir::Instruction::BinaryOp(ir::BinaryOperator::Eq) =
146 &block.instructions[i + 1]
147 {
148 i += 2;
150 continue;
151 }
152 }
153
154 if let ir::Instruction::PushLiteral(ir::LiteralValue::Boolean(false)) =
156 &block.instructions[i]
157 {
158 if let ir::Instruction::BinaryOp(ir::BinaryOperator::Ne) =
159 &block.instructions[i + 1]
160 {
161 i += 2;
163 continue;
164 }
165 }
166
167 }
171
172 if i + 1 < block.instructions.len()
174 && matches!(&block.instructions[i], ir::Instruction::BitwiseNot)
175 && matches!(&block.instructions[i + 1], ir::Instruction::BitwiseNot)
176 {
177 i += 2;
178 continue;
179 }
180
181 optimized.push(block.instructions[i].clone());
182 i += 1;
183 }
184
185 block.instructions = optimized;
186}