diff --git a/evm/src/cpu/kernel/optimizer.rs b/evm/src/cpu/kernel/optimizer.rs index 66307aec..cc595191 100644 --- a/evm/src/cpu/kernel/optimizer.rs +++ b/evm/src/cpu/kernel/optimizer.rs @@ -23,6 +23,7 @@ fn optimize_asm_once(code: &mut Vec) { constant_propagation(code); no_op_jumps(code); remove_swaps(code); + remove_ignored_values(code); } /// Constant propagation. @@ -62,7 +63,7 @@ fn constant_propagation(code: &mut Vec) { }); } -/// Remove no-op jumps: `[PUSH label, JUMP, label:] -> [label:]` +/// Remove no-op jumps: `[PUSH label, JUMP, label:] -> [label:]`. fn no_op_jumps(code: &mut Vec) { replace_windows(code, |window| { if let [Push(Label(l)), StandardOp(jump), decl] = window @@ -76,7 +77,7 @@ fn no_op_jumps(code: &mut Vec) { }); } -/// Remove swaps: `[PUSH x, PUSH y, SWAP1] -> [PUSH y, PUSH x]` +/// Remove swaps: `[PUSH x, PUSH y, SWAP1] -> [PUSH y, PUSH x]`. fn remove_swaps(code: &mut Vec) { replace_windows(code, |window| { if let [Push(x), Push(y), StandardOp(swap1)] = window @@ -88,6 +89,21 @@ fn remove_swaps(code: &mut Vec) { }); } +/// Remove push-pop type patterns, such as: `[DUP1, POP]`. +fn remove_ignored_values(code: &mut Vec) { + replace_windows(code, |[a, b]| { + if let StandardOp(pop) = b && &pop == "POP" { + match a { + Push(_) => Some(vec![]), + StandardOp(dup) if dup.starts_with("DUP") => Some(vec![]), + _ => None, + } + } else { + None + } + }); +} + #[cfg(test)] mod tests { use super::*; @@ -178,4 +194,18 @@ mod tests { vec![Push(Label("mylabel".into())), Push(Literal("42".into()))] ); } + + #[test] + fn test_remove_push_pop() { + let mut code = vec![Push(Literal("42".into())), StandardOp("POP".into())]; + remove_ignored_values(&mut code); + assert_eq!(code, vec![]); + } + + #[test] + fn test_remove_dup_pop() { + let mut code = vec![StandardOp("DUP5".into()), StandardOp("POP".into())]; + remove_ignored_values(&mut code); + assert_eq!(code, vec![]); + } }