Skip to content

Commit

Permalink
Remove unnecessary extend instructions (#1147)
Browse files Browse the repository at this point in the history
* remove unnecessary extend instructions

The Wasm i64_extend_i32_u and i64_extend_i32_s instructions are unnecessary in Wasmi bytecode since they can be replaced entirely by the sign-extension instructions. This is possible since Wasmi bytecode is untyped during execution and the only different between those instructions is their effect on the type system.

* add debug_assert
  • Loading branch information
Robbepop authored Aug 1, 2024
1 parent 0a6a083 commit 8d0f733
Show file tree
Hide file tree
Showing 11 changed files with 24 additions and 24 deletions.
5 changes: 0 additions & 5 deletions crates/core/src/untyped.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1135,11 +1135,6 @@ impl UntypedVal {
self.execute_unary(<i32 as ExtendInto<i64>>::extend_into)
}

/// Execute `i64.extend_i32_u` Wasm operation.
pub fn i64_extend_i32_u(self) -> Self {
self.execute_unary(<u32 as ExtendInto<i64>>::extend_into)
}

/// Execute `i64.trunc_f32_s` Wasm operation.
///
/// # Errors
Expand Down
2 changes: 0 additions & 2 deletions crates/wasmi/src/engine/bytecode/construct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1386,8 +1386,6 @@ constructor_for_unary_instrs! {
fn i64_extend32_s() -> Self::I64Extend32S;

fn i32_wrap_i64() -> Self::I32WrapI64;
fn i64_extend_i32_s() -> Self::I64ExtendI32S;
fn i64_extend_i32_u() -> Self::I64ExtendI32U;

fn f32_demote_f64() -> Self::F32DemoteF64;
fn f64_promote_f32() -> Self::F64PromoteF32;
Expand Down
4 changes: 0 additions & 4 deletions crates/wasmi/src/engine/bytecode/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2119,10 +2119,6 @@ pub enum Instruction {

/// Wasm `i32.wrap_i64` instruction.
I32WrapI64(UnaryInstr),
/// Wasm `i64.extend_i32_s` instruction.
I64ExtendI32S(UnaryInstr),
/// Wasm `i64.extend_i32_u` instruction.
I64ExtendI32U(UnaryInstr),

/// Wasm `i32.extend8_s` instruction.
///
Expand Down
2 changes: 0 additions & 2 deletions crates/wasmi/src/engine/executor/instrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -613,8 +613,6 @@ impl<'engine> Executor<'engine> {
Instr::I64RotrImm(instr) => self.execute_i64_rotr_imm(instr),
Instr::I64RotrImm16Rev(instr) => self.execute_i64_rotr_imm16_rev(instr),
Instr::I32WrapI64(instr) => self.execute_i32_wrap_i64(instr),
Instr::I64ExtendI32S(instr) => self.execute_i64_extend_i32_s(instr),
Instr::I64ExtendI32U(instr) => self.execute_i64_extend_i32_u(instr),
Instr::I32Extend8S(instr) => self.execute_i32_extend8_s(instr),
Instr::I32Extend16S(instr) => self.execute_i32_extend16_s(instr),
Instr::I64Extend8S(instr) => self.execute_i64_extend8_s(instr),
Expand Down
2 changes: 0 additions & 2 deletions crates/wasmi/src/engine/executor/instrs/conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ macro_rules! impl_fallible_conversion_impls {
impl<'engine> Executor<'engine> {
impl_conversion_impls! {
(Instruction::I32WrapI64, execute_i32_wrap_i64, UntypedVal::i32_wrap_i64),
(Instruction::I64ExtendI32S, execute_i64_extend_i32_s, UntypedVal::i64_extend_i32_s),
(Instruction::I64ExtendI32U, execute_i64_extend_i32_u, UntypedVal::i64_extend_i32_u),

(Instruction::I32TruncSatF32S, execute_i32_trunc_sat_f32_s, UntypedVal::i32_trunc_sat_f32_s),
(Instruction::I32TruncSatF32U, execute_i32_trunc_sat_f32_u, UntypedVal::i32_trunc_sat_f32_u),
Expand Down
19 changes: 19 additions & 0 deletions crates/wasmi/src/engine/translator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2520,6 +2520,25 @@ impl FuncTranslator {
Ok(())
}

/// Translates a Wasm `i64.extend_i32_u` instruction.
fn translate_i64_extend_i32_u(&mut self) -> Result<(), Error> {
bail_unreachable!(self);
if let TypedProvider::Register(_) = self.alloc.stack.peek() {
// Nothing to do.
//
// We try to not manipulate the emulation stack if not needed.
return Ok(());
}
// Case: At this point we know that the top-most stack item is a constant value.
// We pop it, change its type and push it back onto the stack.
let TypedProvider::Const(value) = self.alloc.stack.pop() else {
panic!("the top-most stack item was asserted to be a constant value but a register was found")
};
debug_assert_eq!(value.ty(), ValType::I32);
self.alloc.stack.push_const(u64::from(u32::from(value)));
Ok(())
}

/// Translates an unconditional `return` instruction.
fn translate_return(&mut self) -> Result<(), Error> {
let fuel_info = self.fuel_info();
Expand Down
2 changes: 0 additions & 2 deletions crates/wasmi/src/engine/translator/relink_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,8 +497,6 @@ impl Instruction {
I::I64RemUImm16Rev(instr) => relink_simple(instr, new_result, old_result),

I::I32WrapI64(instr) |
I::I64ExtendI32S(instr) |
I::I64ExtendI32U(instr) |
I::I32TruncF32S(instr) |
I::I32TruncF32U(instr) |
I::I32TruncF64S(instr) |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ mod i64_extend_i32_s {
#[test]
#[cfg_attr(miri, ignore)]
fn reg() {
conversion_reg::<i32, i64>(OP, Instruction::i64_extend_i32_s);
conversion_reg::<i32, i64>(OP, Instruction::i64_extend32_s);
}

#[test]
Expand All @@ -57,7 +57,8 @@ mod i64_extend_i32_u {
#[test]
#[cfg_attr(miri, ignore)]
fn reg() {
conversion_reg::<i32, i64>(OP, Instruction::i64_extend_i32_u);
let expected = [Instruction::return_reg(0)];
conversion_reg_with::<i32, i64, _>(OP, expected)
}

#[test]
Expand Down
1 change: 0 additions & 1 deletion crates/wasmi/src/engine/translator/typed_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,6 @@ impl TypedVal {

fn i32_wrap_i64(i64) -> i32;
fn i64_extend_i32_s(i32) -> i64;
fn i64_extend_i32_u(i32) -> i64;

fn f32_demote_f64(f64) -> f32;
fn f64_promote_f32(f32) -> f64;
Expand Down
4 changes: 2 additions & 2 deletions crates/wasmi/src/engine/translator/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3049,11 +3049,11 @@ impl<'a> VisitOperator<'a> for FuncTranslator {
}

fn visit_i64_extend_i32_s(&mut self) -> Self::Output {
self.translate_unary(Instruction::i64_extend_i32_s, TypedVal::i64_extend_i32_s)
self.translate_unary(Instruction::i64_extend32_s, TypedVal::i64_extend_i32_s)
}

fn visit_i64_extend_i32_u(&mut self) -> Self::Output {
self.translate_unary(Instruction::i64_extend_i32_u, TypedVal::i64_extend_i32_u)
self.translate_i64_extend_i32_u()
}

fn visit_i64_trunc_f32_s(&mut self) -> Self::Output {
Expand Down
2 changes: 0 additions & 2 deletions crates/wasmi/src/engine/translator/visit_register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -523,8 +523,6 @@ impl VisitInputRegisters for Instruction {
Instruction::F32CopysignImm(instr) => instr.visit_input_registers(f),
Instruction::F64CopysignImm(instr) => instr.visit_input_registers(f),
Instruction::I32WrapI64(instr) => instr.visit_input_registers(f),
Instruction::I64ExtendI32S(instr) => instr.visit_input_registers(f),
Instruction::I64ExtendI32U(instr) => instr.visit_input_registers(f),
Instruction::I32TruncF32S(instr) => instr.visit_input_registers(f),
Instruction::I32TruncF32U(instr) => instr.visit_input_registers(f),
Instruction::I32TruncF64S(instr) => instr.visit_input_registers(f),
Expand Down

0 comments on commit 8d0f733

Please sign in to comment.