diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 5ddc5956..b9254635 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -1635,7 +1635,10 @@ pub fn gen_getzf(ctx: &mut JitContext, negate: ConditionNegate) { } } }, - Instruction::Cmp { .. } | Instruction::Sub { .. } | Instruction::Add { .. } => { + Instruction::Cmp { .. } + | Instruction::Sub { .. } + | Instruction::Add { .. } + | Instruction::NonZeroShift { .. } => { gen_profiler_stat_increment(ctx.builder, profiler::stat::CONDITION_OPTIMISED); gen_get_last_result(ctx.builder, &ctx.previous_instruction); if negate == ConditionNegate::False { @@ -1752,6 +1755,15 @@ pub fn gen_getcf(ctx: &mut JitContext, negate: ConditionNegate) { ctx.builder .const_i32(if negate == ConditionNegate::True { 1 } else { 0 }); }, + Instruction::NonZeroShift { .. } => { + gen_profiler_stat_increment(ctx.builder, profiler::stat::CONDITION_OPTIMISED); + gen_get_flags(ctx.builder); + ctx.builder.const_i32(FLAG_CARRY); + ctx.builder.and_i32(); + if negate == ConditionNegate::True { + ctx.builder.eqz_i32(); + } + }, &Instruction::Other => { gen_profiler_stat_increment(ctx.builder, profiler::stat::CONDITION_UNOPTIMISED); @@ -1797,7 +1809,8 @@ pub fn gen_getsf(ctx: &mut JitContext, negate: ConditionNegate) { Instruction::Cmp { opsize, .. } | Instruction::Sub { opsize, .. } | Instruction::Add { opsize, .. } - | Instruction::Bitwise { opsize, .. } => { + | Instruction::Bitwise { opsize, .. } + | Instruction::NonZeroShift { opsize, .. } => { let &opsize = opsize; gen_profiler_stat_increment(ctx.builder, profiler::stat::CONDITION_OPTIMISED); gen_get_last_result(ctx.builder, &ctx.previous_instruction); @@ -1905,6 +1918,12 @@ pub fn gen_getof(ctx: &mut JitContext) { gen_profiler_stat_increment(ctx.builder, profiler::stat::CONDITION_OPTIMISED); ctx.builder.const_i32(0); }, + Instruction::NonZeroShift { .. } => { + gen_profiler_stat_increment(ctx.builder, profiler::stat::CONDITION_OPTIMISED); + gen_get_flags(ctx.builder); + ctx.builder.const_i32(FLAG_OVERFLOW); + ctx.builder.and_i32(); + }, &Instruction::Other => { gen_profiler_stat_increment(ctx.builder, profiler::stat::CONDITION_UNOPTIMISED); gen_get_flags_changed(ctx.builder); @@ -2051,7 +2070,7 @@ pub fn gen_test_be(ctx: &mut JitContext, negate: ConditionNegate) { ctx.builder.eqz_i32(); } }, - &Instruction::Other => { + Instruction::Other | Instruction::NonZeroShift { .. } => { gen_profiler_stat_increment(ctx.builder, profiler::stat::CONDITION_UNOPTIMISED); gen_getcf(ctx, ConditionNegate::False); gen_getzf(ctx, ConditionNegate::False); @@ -2167,7 +2186,7 @@ pub fn gen_test_l(ctx: &mut JitContext, negate: ConditionNegate) { gen_profiler_stat_increment(ctx.builder, profiler::stat::CONDITION_OPTIMISED); gen_getsf(ctx, negate); }, - &Instruction::Other | Instruction::Add { .. } => { + &Instruction::Other | Instruction::Add { .. } | Instruction::NonZeroShift { .. } => { gen_profiler_stat_increment(ctx.builder, profiler::stat::CONDITION_UNOPTIMISED); if let Instruction::Add { .. } = ctx.previous_instruction { gen_profiler_stat_increment( @@ -2297,7 +2316,7 @@ pub fn gen_test_le(ctx: &mut JitContext, negate: ConditionNegate) { ctx.builder.eqz_i32(); } }, - Instruction::Other | Instruction::Add { .. } => { + Instruction::Other | Instruction::Add { .. } | Instruction::NonZeroShift { .. } => { gen_profiler_stat_increment(ctx.builder, profiler::stat::CONDITION_UNOPTIMISED); if let Instruction::Add { .. } = ctx.previous_instruction { gen_profiler_stat_increment( diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 2b912e96..532c4d1e 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -274,6 +274,10 @@ pub enum Instruction { opsize: i32, is_inc: bool, }, + NonZeroShift { + dest: InstructionOperandDest, + opsize: i32, + }, Bitwise { dest: InstructionOperandDest, opsize: i32, diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 61f5a1de..a1f0a14a 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1555,6 +1555,12 @@ impl ShiftCount { } fn gen_shl32(ctx: &mut JitContext, dest_operand: &WasmLocal, source_operand: &LocalOrImmediate) { + if let &LocalOrImmediate::Immediate(1..=31) = source_operand { + ctx.current_instruction = Instruction::NonZeroShift { + dest: local_to_instruction_operand(ctx, dest_operand), + opsize: OPSIZE_32, + }; + } let builder = &mut ctx.builder; let count = match source_operand { LocalOrImmediate::WasmLocal(l) => { @@ -1622,6 +1628,12 @@ fn gen_shl32(ctx: &mut JitContext, dest_operand: &WasmLocal, source_operand: &Lo } } fn gen_shr32(ctx: &mut JitContext, dest_operand: &WasmLocal, source_operand: &LocalOrImmediate) { + if let &LocalOrImmediate::Immediate(1..=31) = source_operand { + ctx.current_instruction = Instruction::NonZeroShift { + dest: local_to_instruction_operand(ctx, dest_operand), + opsize: OPSIZE_32, + }; + } let builder = &mut ctx.builder; let count = match source_operand { LocalOrImmediate::WasmLocal(l) => { @@ -1682,6 +1694,12 @@ fn gen_shr32(ctx: &mut JitContext, dest_operand: &WasmLocal, source_operand: &Lo } } fn gen_sar32(ctx: &mut JitContext, dest_operand: &WasmLocal, source_operand: &LocalOrImmediate) { + if let &LocalOrImmediate::Immediate(1..=31) = source_operand { + ctx.current_instruction = Instruction::NonZeroShift { + dest: local_to_instruction_operand(ctx, dest_operand), + opsize: OPSIZE_32, + }; + } let builder = &mut ctx.builder; let count = match source_operand { LocalOrImmediate::WasmLocal(l) => {