@@ -17,12 +17,7 @@ pub(crate) fn optimize_instructions(
1717 track_local_memory_usage : bool ,
1818) -> OptimizeResult {
1919 let uses_local_memory = if options. optimize_rewrite ( ) {
20- rewrite (
21- & mut instructions,
22- self_func_addr,
23- imported_memory_count,
24- track_local_memory_usage,
25- )
20+ rewrite ( & mut instructions, self_func_addr, imported_memory_count, track_local_memory_usage)
2621 } else {
2722 track_local_memory_usage
2823 && instructions. iter ( ) . any ( |instr| instr. memory_addr ( ) . is_some_and ( |mem| mem >= imported_memory_count) )
@@ -55,28 +50,43 @@ fn rewrite(
5550 rewrite ! ( instrs, i, [ LocalGet32 ( a) , LocalGet32 ( b) ] => BinOpLocalLocal32 ( op, a, b) ) ;
5651 rewrite ! ( instrs, i, [ LocalGet32 ( local) , Const32 ( c) ] => BinOpLocalConst32 ( op, local, c) ) ;
5752 rewrite ! ( instrs, i, [ Const32 ( c) , LocalGet32 ( local) ] => BinOpLocalConst32 ( op, local, c) ) ;
53+ rewrite ! ( instrs, i, [ GlobalGet ( global) ] => [ Nop , BinOpStackGlobal32 ( op, global) ] ) ;
5854 if matches ! ( op, BinOp :: IAdd ) {
5955 rewrite ! ( instrs, i, [ Const32 ( c) ] => AddConst32 ( c) ) ;
56+ rewrite ! ( instrs, i, [ I32Add ] => [ Nop , I32Add3 ] ) ;
6057 }
6158 }
6259 instr @ ( I32Sub | I32Shl | I32ShrS | I32ShrU | I32Rotl | I32Rotr ) => {
6360 let Some ( op) = int_bin_op_32 ( instr) else { unreachable ! ( ) } ;
6461 rewrite ! ( instrs, i, [ LocalGet32 ( a) , LocalGet32 ( b) ] => BinOpLocalLocal32 ( op, a, b) ) ;
6562 rewrite ! ( instrs, i, [ LocalGet32 ( local) , Const32 ( c) ] => BinOpLocalConst32 ( op, local, c) ) ;
63+ rewrite ! ( instrs, i, [ GlobalGet ( global) ] => [ Nop , BinOpStackGlobal32 ( op, global) ] ) ;
64+ if matches ! ( op, BinOp :: IShrS ) {
65+ rewrite ! ( instrs, i, [ BinOpLocalConst32 ( BinOp :: IShl , local, 8 ) , Const32 ( 8 ) ] => [ Nop , LocalGet32 ( local) , I32Extend8S ] ) ;
66+ rewrite ! ( instrs, i, [ BinOpLocalConst32 ( BinOp :: IShl , local, 16 ) , Const32 ( 16 ) ] => [ Nop , LocalGet32 ( local) , I32Extend16S ] ) ;
67+ }
6668 }
6769 instr @ ( I64Add | I64Mul | I64And | I64Or | I64Xor ) => {
6870 let Some ( op) = int_bin_op_64 ( instr) else { unreachable ! ( ) } ;
6971 rewrite ! ( instrs, i, [ LocalGet64 ( a) , LocalGet64 ( b) ] => BinOpLocalLocal64 ( op, a, b) ) ;
7072 rewrite ! ( instrs, i, [ LocalGet64 ( local) , Const64 ( c) ] => BinOpLocalConst64 ( op, local, c) ) ;
7173 rewrite ! ( instrs, i, [ Const64 ( c) , LocalGet64 ( local) ] => BinOpLocalConst64 ( op, local, c) ) ;
74+ rewrite ! ( instrs, i, [ GlobalGet ( global) ] => [ Nop , BinOpStackGlobal64 ( op, global) ] ) ;
7275 if matches ! ( op, BinOp :: IAdd ) {
7376 rewrite ! ( instrs, i, [ Const64 ( c) ] => AddConst64 ( c) ) ;
77+ rewrite ! ( instrs, i, [ I64Add ] => [ Nop , I64Add3 ] ) ;
7478 }
7579 }
7680 instr @ ( I64Sub | I64Shl | I64ShrS | I64ShrU | I64Rotl | I64Rotr ) => {
7781 let Some ( op) = int_bin_op_64 ( instr) else { unreachable ! ( ) } ;
7882 rewrite ! ( instrs, i, [ LocalGet64 ( a) , LocalGet64 ( b) ] => BinOpLocalLocal64 ( op, a, b) ) ;
7983 rewrite ! ( instrs, i, [ LocalGet64 ( local) , Const64 ( c) ] => BinOpLocalConst64 ( op, local, c) ) ;
84+ rewrite ! ( instrs, i, [ GlobalGet ( global) ] => [ Nop , BinOpStackGlobal64 ( op, global) ] ) ;
85+ if matches ! ( op, BinOp :: IShrS ) {
86+ rewrite ! ( instrs, i, [ BinOpLocalConst64 ( BinOp :: IShl , local, 8 ) , Const64 ( 8 ) ] => [ Nop , LocalGet64 ( local) , I64Extend8S ] ) ;
87+ rewrite ! ( instrs, i, [ BinOpLocalConst64 ( BinOp :: IShl , local, 16 ) , Const64 ( 16 ) ] => [ Nop , LocalGet64 ( local) , I64Extend16S ] ) ;
88+ rewrite ! ( instrs, i, [ BinOpLocalConst64 ( BinOp :: IShl , local, 32 ) , Const64 ( 32 ) ] => [ Nop , LocalGet64 ( local) , I64Extend32S ] ) ;
89+ }
8090 }
8191 instr @ ( F32Add | F32Mul | F32Min | F32Max ) => {
8292 let Some ( op) = float_bin_op_32 ( instr) else { unreachable ! ( ) } ;
@@ -111,13 +121,15 @@ fn rewrite(
111121 rewrite ! ( instrs, i, [ LocalGet128 ( local) , Const128 ( c) ] => BinOpLocalConst128 ( BinOp128 :: AndNot , local, c) ) ;
112122 }
113123 I32Store ( memarg) | F32Store ( memarg) => {
124+ rewrite ! ( instrs, i, [ F32Mul , F32Add ] => [ Nop , Nop , FMaStoreF32 ( memarg) ] ) ;
114125 rewrite ! ( instrs, i,
115126 [ LocalGet32 ( addr_local) , LocalGet32 ( value_local) ] if
116127 ( let ( Ok ( addr_local) , Ok ( value_local) ) = ( u8 :: try_from( addr_local) , u8 :: try_from( value_local) ) ) =>
117128 StoreLocalLocal32 ( memarg, addr_local, value_local)
118129 ) ;
119130 }
120131 I64Store ( memarg) | F64Store ( memarg) => {
132+ rewrite ! ( instrs, i, [ F64Mul , F64Add ] => [ Nop , Nop , FMaStoreF64 ( memarg) ] ) ;
121133 rewrite ! ( instrs, i,
122134 [ LocalGet32 ( addr_local) , LocalGet64 ( value_local) ] if
123135 ( let ( Ok ( addr_local) , Ok ( value_local) ) = ( u8 :: try_from( addr_local) , u8 :: try_from( value_local) ) ) =>
@@ -156,6 +168,8 @@ fn rewrite(
156168 _ => Instruction :: BinOpLocalConstSet32 ( op, lhs, imm, dst) ,
157169 }
158170 ) ;
171+ rewrite ! ( instrs, i, [ I32Mul , LocalGet32 ( acc) , I32Add ] if ( acc == dst) => [ Nop , Nop , Nop , MulAccLocal32 ( dst) ] ) ;
172+ rewrite ! ( instrs, i, [ F32Mul , LocalGet32 ( acc) , F32Add ] if ( acc == dst) => [ Nop , Nop , Nop , FMulAccLocal32 ( dst) ] ) ;
159173 rewrite_local_set_direct ! (
160174 instrs,
161175 i,
@@ -193,6 +207,8 @@ fn rewrite(
193207 _ => Instruction :: BinOpLocalConstSet64 ( op, lhs, imm, dst) ,
194208 }
195209 ) ;
210+ rewrite ! ( instrs, i, [ I64Mul , LocalGet64 ( acc) , I64Add ] if ( acc == dst) => [ Nop , Nop , Nop , MulAccLocal64 ( dst) ] ) ;
211+ rewrite ! ( instrs, i, [ F64Mul , LocalGet64 ( acc) , F64Add ] if ( acc == dst) => [ Nop , Nop , Nop , FMulAccLocal64 ( dst) ] ) ;
196212 rewrite_local_set_direct ! (
197213 instrs,
198214 i,
0 commit comments