diff --git a/cranelift/interpreter/src/step.rs b/cranelift/interpreter/src/step.rs index 802fea4645..2df9888e64 100644 --- a/cranelift/interpreter/src/step.rs +++ b/cranelift/interpreter/src/step.rs @@ -669,36 +669,25 @@ where Opcode::UshrImm => binary(Value::ushr, arg(0)?, imm_as_ctrl_ty()?)?, Opcode::SshrImm => binary(Value::ishr, arg(0)?, imm_as_ctrl_ty()?)?, Opcode::Bitrev => assign(Value::reverse_bits(arg(0)?)?), - // For `Clz`, `Cls`, `Ctz`, and `Popcnt`, the underlying Rust function - // always returns `u32` (and therefore a `Value` of type `U32`), so this - // is switched back to the correct type by recreating the `Value`. - Opcode::Clz => assign(Value::int( - Value::leading_zeros(arg(0)?)?.into_int()?, - ctrl_ty, - )?), + Opcode::Clz => assign(arg(0)?.leading_zeros()?), Opcode::Cls => { let count = if Value::lt(&arg(0)?, &Value::int(0, ctrl_ty)?)? { - Value::int(Value::leading_ones(arg(0)?)?.into_int()?, ctrl_ty)? + arg(0)?.leading_ones()? } else { - Value::int(Value::leading_zeros(arg(0)?)?.into_int()?, ctrl_ty)? + arg(0)?.leading_zeros()? }; assign(Value::sub(count, Value::int(1, ctrl_ty)?)?) } - Opcode::Ctz => assign(Value::int( - Value::trailing_zeros(arg(0)?)?.into_int()?, - ctrl_ty, - )?), + Opcode::Ctz => assign(arg(0)?.trailing_zeros()?), Opcode::Popcnt => { let count = if arg(0)?.ty().is_int() { - Value::int(Value::count_ones(arg(0)?)?.into_int()?, ctrl_ty)? + arg(0)?.count_ones()? } else { - let lanes = extractlanes(&arg(0)?, ctrl_ty.lane_type())?; - let mut new_vec = SimdVec::new(); - for i in lanes { - let c: V = Value::count_ones(i)?; - new_vec.push(c); - } - vectorizelanes(&new_vec, ctrl_ty)? + let lanes = extractlanes(&arg(0)?, ctrl_ty.lane_type())? + .into_iter() + .map(|lane| lane.count_ones().unwrap()) + .collect::>(); + vectorizelanes(&lanes, ctrl_ty)? }; assign(count) } diff --git a/cranelift/interpreter/src/value.rs b/cranelift/interpreter/src/value.rs index 2f8fe47056..6a09406b84 100644 --- a/cranelift/interpreter/src/value.rs +++ b/cranelift/interpreter/src/value.rs @@ -139,10 +139,10 @@ pub enum ValueConversionKind { /// Helper for creating match expressions over [DataValue]. macro_rules! unary_match { - ( $op:ident($arg1:expr); [ $( $data_value_ty:ident ),* ]; $return_value_ty:ident ) => { + ( $op:ident($arg1:expr); [ $( $data_value_ty:ident ),* ]; [ $( $return_value_ty:ident ),* ] ) => { match $arg1 { $( DataValue::$data_value_ty(a) => { - Ok(DataValue::$return_value_ty(a.$op())) + Ok(DataValue::$data_value_ty($return_value_ty::try_from(a.$op()).unwrap())) } )* _ => unimplemented!() } @@ -461,19 +461,19 @@ impl Value for DataValue { } fn count_ones(self) -> ValueResult { - unary_match!(count_ones(&self); [I8, I16, I32, I64, I128, U8, U16, U32, U64, U128]; U32) + unary_match!(count_ones(&self); [I8, I16, I32, I64, I128, U8, U16, U32, U64, U128]; [i8, i16, i32, i64, i128, u8, u16, u32, u64, u128]) } fn leading_ones(self) -> ValueResult { - unary_match!(leading_ones(&self); [I8, I16, I32, I64, I128, U8, U16, U32, U64, U128]; U32) + unary_match!(leading_ones(&self); [I8, I16, I32, I64, I128, U8, U16, U32, U64, U128]; [i8, i16, i32, i64, i128, u8, u16, u32, u64, u128]) } fn leading_zeros(self) -> ValueResult { - unary_match!(leading_zeros(&self); [I8, I16, I32, I64, I128, U8, U16, U32, U64, U128]; U32) + unary_match!(leading_zeros(&self); [I8, I16, I32, I64, I128, U8, U16, U32, U64, U128]; [i8, i16, i32, i64, i128, u8, u16, u32, u64, u128]) } fn trailing_zeros(self) -> ValueResult { - unary_match!(trailing_zeros(&self); [I8, I16, I32, I64, I128, U8, U16, U32, U64, U128]; U32) + unary_match!(trailing_zeros(&self); [I8, I16, I32, I64, I128, U8, U16, U32, U64, U128]; [i8, i16, i32, i64, i128, u8, u16, u32, u64, u128]) } fn reverse_bits(self) -> ValueResult {