11use crate :: ParserOptions ;
22use alloc:: vec:: Vec ;
3- use tinywasm_types:: { Instruction , WasmFunctionData } ;
3+ use tinywasm_types:: { CmpOp , Instruction , WasmFunctionData } ;
4+
5+ fn cmp_op ( instr : Instruction ) -> Option < CmpOp > {
6+ Some ( match instr {
7+ Instruction :: I32Eq => CmpOp :: Eq ,
8+ Instruction :: I32Ne => CmpOp :: Ne ,
9+ Instruction :: I32LtS => CmpOp :: LtS ,
10+ Instruction :: I32LtU => CmpOp :: LtU ,
11+ Instruction :: I32GtS => CmpOp :: GtS ,
12+ Instruction :: I32GtU => CmpOp :: GtU ,
13+ Instruction :: I32LeS => CmpOp :: LeS ,
14+ Instruction :: I32LeU => CmpOp :: LeU ,
15+ Instruction :: I32GeS => CmpOp :: GeS ,
16+ Instruction :: I32GeU => CmpOp :: GeU ,
17+ _ => return None ,
18+ } )
19+ }
20+
21+ fn inverse_cmp_op ( op : CmpOp ) -> CmpOp {
22+ match op {
23+ CmpOp :: Eq => CmpOp :: Ne ,
24+ CmpOp :: Ne => CmpOp :: Eq ,
25+ CmpOp :: LtS => CmpOp :: GeS ,
26+ CmpOp :: LtU => CmpOp :: GeU ,
27+ CmpOp :: GtS => CmpOp :: LeS ,
28+ CmpOp :: GtU => CmpOp :: LeU ,
29+ CmpOp :: LeS => CmpOp :: GtS ,
30+ CmpOp :: LeU => CmpOp :: GtU ,
31+ CmpOp :: GeS => CmpOp :: LtS ,
32+ CmpOp :: GeU => CmpOp :: LtU ,
33+ }
34+ }
435
536pub ( crate ) fn optimize_instructions (
637 mut instructions : Vec < Instruction > ,
@@ -30,7 +61,7 @@ fn rewrite(instructions: &mut [Instruction], self_func_addr: u32) {
3061 {
3162 instructions[ read - 2 ] = Instruction :: Nop ;
3263 instructions[ read - 1 ] = Instruction :: Nop ;
33- instructions[ read] = Instruction :: I32AddLocals ( a, b) ;
64+ instructions[ read] = Instruction :: AddLocalLocal32 ( a, b) ;
3465 }
3566
3667 if read > 0 {
@@ -39,15 +70,15 @@ fn rewrite(instructions: &mut [Instruction], self_func_addr: u32) {
3970 if let Instruction :: LocalGet32 ( local) = instructions[ read - 2 ] {
4071 instructions[ read - 2 ] = Instruction :: Nop ;
4172 instructions[ read - 1 ] = Instruction :: LocalGet32 ( local) ;
42- instructions[ read] = Instruction :: I32AddConst ( c) ;
73+ instructions[ read] = Instruction :: AddConst32 ( c) ;
4374 } else {
4475 instructions[ read - 1 ] = Instruction :: Nop ;
45- instructions[ read] = Instruction :: I32AddConst ( c) ;
76+ instructions[ read] = Instruction :: AddConst32 ( c) ;
4677 }
4778 }
4879 Instruction :: I32Const ( c) => {
4980 instructions[ read - 1 ] = Instruction :: Nop ;
50- instructions[ read] = Instruction :: I32AddConst ( c) ;
81+ instructions[ read] = Instruction :: AddConst32 ( c) ;
5182 }
5283 _ => { }
5384 }
@@ -60,7 +91,7 @@ fn rewrite(instructions: &mut [Instruction], self_func_addr: u32) {
6091 {
6192 instructions[ read - 2 ] = Instruction :: Nop ;
6293 instructions[ read - 1 ] = Instruction :: Nop ;
63- instructions[ read] = Instruction :: I64AddLocals ( a, b) ;
94+ instructions[ read] = Instruction :: AddLocalLocal64 ( a, b) ;
6495 }
6596
6697 if read > 0 {
@@ -69,15 +100,15 @@ fn rewrite(instructions: &mut [Instruction], self_func_addr: u32) {
69100 if let Instruction :: LocalGet64 ( local) = instructions[ read - 2 ] {
70101 instructions[ read - 2 ] = Instruction :: Nop ;
71102 instructions[ read - 1 ] = Instruction :: LocalGet64 ( local) ;
72- instructions[ read] = Instruction :: I64AddConst ( c) ;
103+ instructions[ read] = Instruction :: AddConst64 ( c) ;
73104 } else {
74105 instructions[ read - 1 ] = Instruction :: Nop ;
75- instructions[ read] = Instruction :: I64AddConst ( c) ;
106+ instructions[ read] = Instruction :: AddConst64 ( c) ;
76107 }
77108 }
78109 Instruction :: I64Const ( c) => {
79110 instructions[ read - 1 ] = Instruction :: Nop ;
80- instructions[ read] = Instruction :: I64AddConst ( c) ;
111+ instructions[ read] = Instruction :: AddConst64 ( c) ;
81112 }
82113 _ => { }
83114 }
@@ -90,7 +121,7 @@ fn rewrite(instructions: &mut [Instruction], self_func_addr: u32) {
90121 {
91122 instructions[ read - 2 ] = Instruction :: Nop ;
92123 instructions[ read - 1 ] = Instruction :: Nop ;
93- instructions[ read] = Instruction :: I64XorRotlConst ( c) ;
124+ instructions[ read] = Instruction :: XorRotlConst64 ( c) ;
94125 }
95126 }
96127 Instruction :: I32Store ( memarg) => {
@@ -101,7 +132,7 @@ fn rewrite(instructions: &mut [Instruction], self_func_addr: u32) {
101132 {
102133 instructions[ read - 2 ] = Instruction :: Nop ;
103134 instructions[ read - 1 ] = Instruction :: Nop ;
104- instructions[ read] = Instruction :: I32StoreLocalLocal ( memarg, addr_local, value_local) ;
135+ instructions[ read] = Instruction :: StoreLocalLocal32 ( memarg, addr_local, value_local) ;
105136 }
106137 }
107138 Instruction :: I64Store ( memarg) => {
@@ -112,7 +143,16 @@ fn rewrite(instructions: &mut [Instruction], self_func_addr: u32) {
112143 {
113144 instructions[ read - 2 ] = Instruction :: Nop ;
114145 instructions[ read - 1 ] = Instruction :: Nop ;
115- instructions[ read] = Instruction :: I64StoreLocalLocal ( memarg, addr_local, value_local) ;
146+ instructions[ read] = Instruction :: StoreLocalLocal64 ( memarg, addr_local, value_local) ;
147+ }
148+ }
149+ Instruction :: I32Load ( memarg) => {
150+ if read > 0
151+ && let Instruction :: LocalGet32 ( addr_local) = instructions[ read - 1 ]
152+ && let Ok ( addr_local) = u8:: try_from ( addr_local)
153+ {
154+ instructions[ read - 1 ] = Instruction :: Nop ;
155+ instructions[ read] = Instruction :: LoadLocal32 ( memarg, addr_local) ;
116156 }
117157 }
118158 Instruction :: MemoryFill ( mem) => {
@@ -163,34 +203,42 @@ fn rewrite(instructions: &mut [Instruction], self_func_addr: u32) {
163203 }
164204 Instruction :: I32Const ( c) => {
165205 instructions[ read - 1 ] = Instruction :: Nop ;
166- instructions[ read] = Instruction :: LocalSetConst32 ( dst, c) ;
206+ instructions[ read] = Instruction :: SetLocalConst32 ( dst, c) ;
167207 }
168208 Instruction :: F32Const ( c) => {
169209 instructions[ read - 1 ] = Instruction :: Nop ;
170210 instructions[ read] =
171- Instruction :: LocalSetConst32 ( dst, i32:: from_ne_bytes ( c. to_bits ( ) . to_ne_bytes ( ) ) ) ;
211+ Instruction :: SetLocalConst32 ( dst, i32:: from_ne_bytes ( c. to_bits ( ) . to_ne_bytes ( ) ) ) ;
172212 }
173213 _ => { }
174214 }
175215 }
176216
177217 if read > 1 {
178218 match ( instructions[ read - 2 ] , instructions[ read - 1 ] ) {
179- ( Instruction :: LocalGet32 ( src) , Instruction :: I32AddConst ( c) ) if src == dst => {
219+ ( Instruction :: LocalGet32 ( src) , Instruction :: AddConst32 ( c) ) if src == dst => {
180220 instructions[ read - 2 ] = Instruction :: Nop ;
181221 instructions[ read - 1 ] = Instruction :: Nop ;
182- instructions[ read] = Instruction :: LocalAddConst32 ( dst, c) ;
222+ instructions[ read] = Instruction :: AddLocalConst32 ( dst, c) ;
183223 }
184224 ( Instruction :: LocalGet32 ( addr) , Instruction :: I32Load ( memarg) ) => {
185225 if let ( Ok ( addr) , Ok ( dst) ) = ( u8:: try_from ( addr) , u8:: try_from ( dst) ) {
186226 instructions[ read - 2 ] = Instruction :: Nop ;
187227 instructions[ read - 1 ] = Instruction :: Nop ;
188- instructions[ read] = Instruction :: I32LoadLocalSet ( memarg, addr, dst) ;
228+ instructions[ read] = Instruction :: LoadLocalSet32 ( memarg, addr, dst) ;
189229 }
190230 }
191231 _ => { }
192232 }
193233 }
234+
235+ if read > 0
236+ && let Instruction :: LoadLocal32 ( memarg, addr) = instructions[ read - 1 ]
237+ && let Ok ( dst) = u8:: try_from ( dst)
238+ {
239+ instructions[ read - 1 ] = Instruction :: Nop ;
240+ instructions[ read] = Instruction :: LoadLocalSet32 ( memarg, addr, dst) ;
241+ }
194242 }
195243 Instruction :: LocalSet64 ( dst) => {
196244 if read > 0 {
@@ -202,25 +250,25 @@ fn rewrite(instructions: &mut [Instruction], self_func_addr: u32) {
202250 }
203251 Instruction :: I64Const ( c) => {
204252 instructions[ read - 1 ] = Instruction :: Nop ;
205- instructions[ read] = Instruction :: LocalSetConst64 ( dst, c) ;
253+ instructions[ read] = Instruction :: SetLocalConst64 ( dst, c) ;
206254 }
207255 Instruction :: F64Const ( c) => {
208256 instructions[ read - 1 ] = Instruction :: Nop ;
209257 instructions[ read] =
210- Instruction :: LocalSetConst64 ( dst, i64:: from_ne_bytes ( c. to_bits ( ) . to_ne_bytes ( ) ) ) ;
258+ Instruction :: SetLocalConst64 ( dst, i64:: from_ne_bytes ( c. to_bits ( ) . to_ne_bytes ( ) ) ) ;
211259 }
212260 _ => { }
213261 }
214262 }
215263
216264 if read > 1
217- && let ( Instruction :: LocalGet64 ( src) , Instruction :: I64AddConst ( c) ) =
265+ && let ( Instruction :: LocalGet64 ( src) , Instruction :: AddConst64 ( c) ) =
218266 ( instructions[ read - 2 ] , instructions[ read - 1 ] )
219267 && src == dst
220268 {
221269 instructions[ read - 2 ] = Instruction :: Nop ;
222270 instructions[ read - 1 ] = Instruction :: Nop ;
223- instructions[ read] = Instruction :: LocalAddConst64 ( dst, c) ;
271+ instructions[ read] = Instruction :: AddLocalConst64 ( dst, c) ;
224272 }
225273 }
226274 Instruction :: LocalSet128 ( dst) => {
@@ -247,16 +295,24 @@ fn rewrite(instructions: &mut [Instruction], self_func_addr: u32) {
247295 {
248296 instructions[ read - 2 ] = Instruction :: Nop ;
249297 instructions[ read - 1 ] = Instruction :: Nop ;
250- instructions[ read] = Instruction :: I32LoadLocalTee ( memarg, addr, dst) ;
298+ instructions[ read] = Instruction :: LoadLocalTee32 ( memarg, addr, dst) ;
299+ }
300+
301+ if read > 0
302+ && let Instruction :: LoadLocal32 ( memarg, addr) = instructions[ read - 1 ]
303+ && let Ok ( dst) = u8:: try_from ( dst)
304+ {
305+ instructions[ read - 1 ] = Instruction :: Nop ;
306+ instructions[ read] = Instruction :: LoadLocalTee32 ( memarg, addr, dst) ;
251307 }
252308 }
253309 Instruction :: LocalTee64 ( dst) if read > 0 => match instructions[ read - 1 ] {
254310 Instruction :: LocalGet64 ( src) if src == dst => {
255311 instructions[ read] = Instruction :: Nop ;
256312 }
257- Instruction :: I64XorRotlConst ( c) => {
313+ Instruction :: XorRotlConst64 ( c) => {
258314 instructions[ read - 1 ] = Instruction :: Nop ;
259- instructions[ read] = Instruction :: I64XorRotlConstTee ( c, dst) ;
315+ instructions[ read] = Instruction :: XorRotlConstTee64 ( c, dst) ;
260316 }
261317 _ => { }
262318 } ,
@@ -292,6 +348,87 @@ fn rewrite(instructions: &mut [Instruction], self_func_addr: u32) {
292348 instructions[ read] = Instruction :: Nop ;
293349 }
294350 }
351+ Instruction :: JumpIfZero ( ip) => {
352+ if read > 0 && instructions[ read - 1 ] == Instruction :: I32Eqz {
353+ instructions[ read - 1 ] = Instruction :: Nop ;
354+ instructions[ read] = Instruction :: JumpIfNonZero ( ip) ;
355+ continue ;
356+ }
357+
358+ if read > 2 {
359+ match ( instructions[ read - 2 ] , instructions[ read - 1 ] ) {
360+ ( Instruction :: I32Const ( imm) , cmp) => {
361+ if read > 3
362+ && let Instruction :: LocalGet32 ( local) = instructions[ read - 3 ]
363+ && let Some ( op) = cmp_op ( cmp)
364+ {
365+ instructions[ read - 3 ] = Instruction :: Nop ;
366+ instructions[ read - 2 ] = Instruction :: Nop ;
367+ instructions[ read - 1 ] = Instruction :: Nop ;
368+ instructions[ read] = Instruction :: JumpCmpLocalConst32 {
369+ target_ip : ip,
370+ local,
371+ imm,
372+ op : inverse_cmp_op ( op) ,
373+ } ;
374+ }
375+ }
376+ ( Instruction :: LocalGet32 ( right) , cmp) => {
377+ if read > 3
378+ && let Instruction :: LocalGet32 ( left) = instructions[ read - 3 ]
379+ && let Some ( op) = cmp_op ( cmp)
380+ {
381+ instructions[ read - 3 ] = Instruction :: Nop ;
382+ instructions[ read - 2 ] = Instruction :: Nop ;
383+ instructions[ read - 1 ] = Instruction :: Nop ;
384+ instructions[ read] = Instruction :: JumpCmpLocalLocal32 {
385+ target_ip : ip,
386+ left,
387+ right,
388+ op : inverse_cmp_op ( op) ,
389+ } ;
390+ }
391+ }
392+ _ => { }
393+ }
394+ }
395+ }
396+ Instruction :: JumpIfNonZero ( ip) => {
397+ if read > 0 && instructions[ read - 1 ] == Instruction :: I32Eqz {
398+ instructions[ read - 1 ] = Instruction :: Nop ;
399+ instructions[ read] = Instruction :: JumpIfZero ( ip) ;
400+ continue ;
401+ }
402+
403+ if read > 2 {
404+ match ( instructions[ read - 2 ] , instructions[ read - 1 ] ) {
405+ ( Instruction :: I32Const ( imm) , cmp) => {
406+ if read > 3
407+ && let Instruction :: LocalGet32 ( local) = instructions[ read - 3 ]
408+ && let Some ( op) = cmp_op ( cmp)
409+ {
410+ instructions[ read - 3 ] = Instruction :: Nop ;
411+ instructions[ read - 2 ] = Instruction :: Nop ;
412+ instructions[ read - 1 ] = Instruction :: Nop ;
413+ instructions[ read] = Instruction :: JumpCmpLocalConst32 { target_ip : ip, local, imm, op } ;
414+ }
415+ }
416+ ( Instruction :: LocalGet32 ( right) , cmp) => {
417+ if read > 3
418+ && let Instruction :: LocalGet32 ( left) = instructions[ read - 3 ]
419+ && let Some ( op) = cmp_op ( cmp)
420+ {
421+ instructions[ read - 3 ] = Instruction :: Nop ;
422+ instructions[ read - 2 ] = Instruction :: Nop ;
423+ instructions[ read - 1 ] = Instruction :: Nop ;
424+ instructions[ read] =
425+ Instruction :: JumpCmpLocalLocal32 { target_ip : ip, left, right, op } ;
426+ }
427+ }
428+ _ => { }
429+ }
430+ }
431+ }
295432 _ => { }
296433 }
297434 }
@@ -330,6 +467,8 @@ fn dce(instructions: &mut Vec<Instruction>, function_data: &mut WasmFunctionData
330467 Instruction :: Jump ( ip)
331468 | Instruction :: JumpIfZero ( ip)
332469 | Instruction :: JumpIfNonZero ( ip)
470+ | Instruction :: JumpCmpLocalConst32 { target_ip : ip, .. }
471+ | Instruction :: JumpCmpLocalLocal32 { target_ip : ip, .. }
333472 | Instruction :: BranchTable ( ip, _, _) => ip,
334473 _ => return !matches ! ( instr, Instruction :: Nop ) ,
335474 } ;
0 commit comments