Skip to content

Commit 4edfbab

Browse files
feat: add JumpCmpLocalConst3/JumpCmpLocalLocal32 + rename superinstructions
Signed-off-by: Henry <mail@henrygressmann.de>
1 parent 5de0533 commit 4edfbab

3 files changed

Lines changed: 257 additions & 48 deletions

File tree

crates/parser/src/optimize.rs

Lines changed: 163 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,37 @@
11
use crate::ParserOptions;
22
use 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

536
pub(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

Comments
 (0)