@@ -107,6 +107,8 @@ fn rewrite(
107107 output. extend ( [ LocalGet32 ( local) , I32Add3 ] ) ;
108108 read = output. len ( ) - 1 ;
109109 }
110+ } else {
111+ rewrite ! ( output, read, [ Const32 ( value) ] => stack_const32( op, value) ) ;
110112 }
111113 }
112114 raw @ ( I32Sub | I32Shl | I32ShrS | I32ShrU | I32Rotl | I32Rotr ) => {
@@ -117,7 +119,10 @@ fn rewrite(
117119 if rewrite_scalar_const32 ( & mut output, & mut read, data, op, false ) ? {
118120 continue ;
119121 }
120- rewrite_sign_extend32 ( & mut output, & mut read, data, op) ;
122+ if rewrite_sign_extend32 ( & mut output, & mut read, data, op) {
123+ continue ;
124+ }
125+ rewrite ! ( output, read, [ Const32 ( value) ] => stack_const32( op, value) ) ;
121126 }
122127 raw @ ( I64Add | I64Mul | I64And | I64Or | I64Xor ) => {
123128 let op = int_bin_op ( raw) . unwrap ( ) ;
@@ -129,6 +134,8 @@ fn rewrite(
129134 if op == BinOp :: IAdd {
130135 rewrite ! ( output, read, [ Const64 ( index) ] => AddConst64 ( index) ) ;
131136 rewrite ! ( output, read, [ I64Add ] => I64Add3 ) ;
137+ } else {
138+ rewrite ! ( output, read, [ Const64 ( index) ] => BinOpStackConst64 ( PackedOp :: new( op, index) ) ) ;
132139 }
133140 }
134141 raw @ ( I64Sub | I64Shl | I64ShrS | I64ShrU | I64Rotl | I64Rotr ) => {
@@ -138,7 +145,10 @@ fn rewrite(
138145 if rewrite_scalar_const64 ( & mut output, & mut read, data, op, false ) ? {
139146 continue ;
140147 }
141- rewrite_sign_extend64 ( & mut output, & mut read, data, op) ;
148+ if rewrite_sign_extend64 ( & mut output, & mut read, data, op) {
149+ continue ;
150+ }
151+ rewrite ! ( output, read, [ Const64 ( index) ] => BinOpStackConst64 ( PackedOp :: new( op, index) ) ) ;
142152 }
143153 raw if cmp_op ( raw) . is_some ( ) => {
144154 let op = cmp_op ( raw) . unwrap ( ) ;
@@ -149,23 +159,31 @@ fn rewrite(
149159 let op = float_bin_op ( raw) . unwrap ( ) ;
150160 rewrite ! ( output, read, [ LocalGet32 ( a) , LocalGet32 ( b) ] => BinOpLocalLocal32 ( op, a, b) ) ;
151161 rewrite ! ( output, read, [ LocalGet32 ( local) ] => BinOpStackLocal32 ( op, local) ) ;
152- rewrite_scalar_const32 ( & mut output, & mut read, data, op, true ) ?;
162+ if !rewrite_scalar_const32 ( & mut output, & mut read, data, op, true ) ? {
163+ rewrite ! ( output, read, [ Const32 ( value) ] => stack_const32( op, value) ) ;
164+ }
153165 }
154166 raw @ ( F32Sub | F32Div | F32Copysign ) => {
155167 let op = float_bin_op ( raw) . unwrap ( ) ;
156168 rewrite ! ( output, read, [ LocalGet32 ( a) , LocalGet32 ( b) ] => BinOpLocalLocal32 ( op, a, b) ) ;
157169 rewrite ! ( output, read, [ LocalGet32 ( local) ] => BinOpStackLocal32 ( op, local) ) ;
158- rewrite_scalar_const32 ( & mut output, & mut read, data, op, false ) ?;
170+ if !rewrite_scalar_const32 ( & mut output, & mut read, data, op, false ) ? {
171+ rewrite ! ( output, read, [ Const32 ( value) ] => stack_const32( op, value) ) ;
172+ }
159173 }
160174 raw @ ( F64Add | F64Mul | F64Min | F64Max ) => {
161175 let op = float_bin_op ( raw) . unwrap ( ) ;
162176 rewrite ! ( output, read, [ LocalGet64 ( a) , LocalGet64 ( b) ] => BinOpLocalLocal64 ( op, a, b) ) ;
163- rewrite_scalar_const64 ( & mut output, & mut read, data, op, true ) ?;
177+ if !rewrite_scalar_const64 ( & mut output, & mut read, data, op, true ) ? {
178+ rewrite ! ( output, read, [ Const64 ( index) ] => BinOpStackConst64 ( PackedOp :: new( op, index) ) ) ;
179+ }
164180 }
165181 raw @ ( F64Sub | F64Div | F64Copysign ) => {
166182 let op = float_bin_op ( raw) . unwrap ( ) ;
167183 rewrite ! ( output, read, [ LocalGet64 ( a) , LocalGet64 ( b) ] => BinOpLocalLocal64 ( op, a, b) ) ;
168- rewrite_scalar_const64 ( & mut output, & mut read, data, op, false ) ?;
184+ if !rewrite_scalar_const64 ( & mut output, & mut read, data, op, false ) ? {
185+ rewrite ! ( output, read, [ Const64 ( index) ] => BinOpStackConst64 ( PackedOp :: new( op, index) ) ) ;
186+ }
169187 }
170188 raw @ ( V128And | V128Or | V128Xor | I64x2Add | I64x2Mul | V128AndNot ) => {
171189 let op = bin_op_128 ( raw) . unwrap ( ) ;
@@ -299,6 +317,8 @@ fn local_const32(data: &WasmFunctionData, instruction: Instruction) -> Option<(B
299317 Instruction :: AddLocalConst32 ( arg) => Some ( ( BinOp :: IAdd , arg. local , arg. value ) ) ,
300318 Instruction :: SubLocalConst32 ( arg) => Some ( ( BinOp :: ISub , arg. local , arg. value ) ) ,
301319 Instruction :: MulLocalConst32 ( arg) => Some ( ( BinOp :: IMul , arg. local , arg. value ) ) ,
320+ Instruction :: AndLocalConst32 ( arg) => Some ( ( BinOp :: IAnd , arg. local , arg. value ) ) ,
321+ Instruction :: ShrULocalConst32 ( arg) => Some ( ( BinOp :: IShrU , arg. local , arg. value ) ) ,
302322 Instruction :: BinOpLocalConst32 ( packed) => {
303323 let value = data. operand64 ( packed. index ) ;
304324 Some ( ( packed. op , value. a ( ) , value. b ( ) as i32 ) )
@@ -348,6 +368,8 @@ fn rewrite_scalar_const32(
348368 BinOp :: IAdd => Instruction :: AddLocalConst32 ( arg) ,
349369 BinOp :: ISub => Instruction :: SubLocalConst32 ( arg) ,
350370 BinOp :: IMul => Instruction :: MulLocalConst32 ( arg) ,
371+ BinOp :: IAnd => Instruction :: AndLocalConst32 ( arg) ,
372+ BinOp :: IShrU => Instruction :: ShrULocalConst32 ( arg) ,
351373 _ => Instruction :: BinOpLocalConst32 ( PackedOp :: new (
352374 op,
353375 data. push_operand64 ( Operand64 :: < ( u16 , u32 ) > :: new ( * local, * value as u32 ) ) ?,
@@ -362,6 +384,7 @@ fn rewrite_scalar_const32(
362384 match op {
363385 BinOp :: IAdd => Instruction :: AddLocalConst32 ( arg) ,
364386 BinOp :: IMul => Instruction :: MulLocalConst32 ( arg) ,
387+ BinOp :: IAnd => Instruction :: AndLocalConst32 ( arg) ,
365388 _ => Instruction :: BinOpLocalConst32 ( PackedOp :: new (
366389 op,
367390 data. push_operand64 ( Operand64 :: < ( u16 , u32 ) > :: new ( * local, * value as u32 ) ) ?,
@@ -380,6 +403,15 @@ fn rewrite_scalar_const32(
380403 Ok ( true )
381404}
382405
406+ fn stack_const32 ( op : BinOp , value : i32 ) -> Instruction {
407+ match op {
408+ BinOp :: IAnd => Instruction :: AndConst32 ( value) ,
409+ BinOp :: IXor => Instruction :: XorConst32 ( value) ,
410+ BinOp :: IShrU => Instruction :: ShrUConst32 ( value) ,
411+ _ => Instruction :: BinOpStackConst32 ( op, value) ,
412+ }
413+ }
414+
383415fn rewrite_scalar_const64 (
384416 output : & mut CompactOutput ,
385417 read : & mut usize ,
@@ -568,7 +600,7 @@ fn rewrite_store64(
568600 if let [
569601 Instruction :: LocalGet32 ( addr) | Instruction :: LocalGet64 ( addr) ,
570602 Instruction :: LoadLocal64 ( arg) ,
571- Instruction :: Const64 ( one) ,
603+ Instruction :: AddConst64 ( one) ,
572604 ] = previous
573605 && { compact_arg. map ( Operand64 :: from) == Some ( data. operand64 ( arg. memory_arg_idx ) ) }
574606 && addr == u16:: from ( arg. local1 )
@@ -820,6 +852,12 @@ fn rewrite_local_tee32(
820852 }
821853 if * read > output. block_start {
822854 match output[ * read - 1 ] {
855+ Instruction :: AndConst32 ( value) => {
856+ replace ! ( output, * read, 1 => Instruction :: AndConstTee32 ( I32LocalArg { value, local: dst } ) ) ;
857+ }
858+ Instruction :: BinOpStackConst32 ( BinOp :: ISub , value) => {
859+ replace ! ( output, * read, 1 => Instruction :: SubConstTee32 ( I32LocalArg { value, local: dst } ) ) ;
860+ }
823861 Instruction :: LocalGet32 ( src) if src == dst => replace ! ( output, * read, 1 => Instruction :: LocalGet32 ( src) ) ,
824862 Instruction :: BinOpLocalLocal32 ( op, left, right) => {
825863 let replacement = if op == BinOp :: IAdd {
@@ -886,6 +924,12 @@ fn rewrite_local_tee64(
886924 }
887925 if * read > output. block_start {
888926 match output[ * read - 1 ] {
927+ Instruction :: BinOpStackConst64 ( packed) if packed. op == BinOp :: IAnd => {
928+ replace ! ( output, * read, 1 => Instruction :: AndConstTee64 ( PackedOp :: new( dst, packed. index) ) ) ;
929+ }
930+ Instruction :: BinOpStackConst64 ( packed) if packed. op == BinOp :: ISub => {
931+ replace ! ( output, * read, 1 => Instruction :: SubConstTee64 ( PackedOp :: new( dst, packed. index) ) ) ;
932+ }
889933 Instruction :: LocalGet64 ( src) if src == dst => replace ! ( output, * read, 1 => Instruction :: LocalGet64 ( src) ) ,
890934 Instruction :: BinOpLocalLocal64 ( op, left, right) => {
891935 let index = data. push_operand64 ( Operand64 :: < ( u16 , u16 , u16 ) > :: new ( left, right, dst) ) ?;
@@ -1222,6 +1266,34 @@ fn rewrite_conditional(
12221266 replace ! ( output, * read, 3 => replacement) ;
12231267 return Ok ( ( ) ) ;
12241268 }
1269+ if * read >= output. block_start + 3 {
1270+ let update = match [ output[ * read - 3 ] , output[ * read - 2 ] , output[ * read - 1 ] ] {
1271+ [ Instruction :: XorConst32 ( value) , Instruction :: LocalTee32 ( local) , Instruction :: LocalGet32 ( cond) ]
1272+ if local == cond =>
1273+ {
1274+ Some ( ( BinOp :: IXor , value, local) )
1275+ }
1276+ [ Instruction :: ShrUConst32 ( value) , Instruction :: LocalTee32 ( local) , Instruction :: LocalGet32 ( cond) ]
1277+ if local == cond =>
1278+ {
1279+ Some ( ( BinOp :: IShrU , value, local) )
1280+ }
1281+ [
1282+ Instruction :: BinOpStackConst32 ( op, value) ,
1283+ Instruction :: LocalTee32 ( local) ,
1284+ Instruction :: LocalGet32 ( cond) ,
1285+ ] if local == cond => Some ( ( op, value, local) ) ,
1286+ _ => None ,
1287+ } ;
1288+ if let Some ( ( op, value, local) ) = update {
1289+ let replacement = Instruction :: BinOpStackConstTeeLocalJump32 ( PackedOp :: new (
1290+ op,
1291+ data. push_target_operand128 ( Operand128 :: < LocalUpdateOperand > :: new ( target, value, local, on_zero) ) ?,
1292+ ) ) ;
1293+ replace ! ( output, * read, 3 => replacement) ;
1294+ return Ok ( ( ) ) ;
1295+ }
1296+ }
12251297 if * read >= output. block_start + 2 {
12261298 let update = match [ output[ * read - 2 ] , output[ * read - 1 ] ] {
12271299 [ Instruction :: AndConstTee32 ( arg) , Instruction :: LocalGet32 ( cond) ] if arg. local == cond => {
0 commit comments