Implement bit operations for Cranelift interpreter

Implemented for the Cranelift interpreter:
- `Bitrev` to reverse the order of the bits in an integer.
- `Cls` to count the leading bits which are the same as the sign bit in
an integer, yielding one less than the size of the integer for 0 and -1.
- `Clz` to count the number of leading zeros in the bitwise representation of the
integer.
- `Ctz` to count the number of trailing zeros in the bitwise representation of the
integer.
- `Popcnt` to count the number of ones in the bitwise representation of the
integer.

Copyright (c) 2021, Arm Limited
This commit is contained in:
dheaton-arm
2021-08-24 16:01:57 +01:00
parent 164835ecf5
commit 9f647301ff
11 changed files with 318 additions and 5 deletions

View File

@@ -668,11 +668,40 @@ where
Opcode::IshlImm => binary(Value::shl, arg(0)?, imm_as_ctrl_ty()?)?,
Opcode::UshrImm => binary(Value::ushr, arg(0)?, imm_as_ctrl_ty()?)?,
Opcode::SshrImm => binary(Value::ishr, arg(0)?, imm_as_ctrl_ty()?)?,
Opcode::Bitrev => unimplemented!("Bitrev"),
Opcode::Clz => unimplemented!("Clz"),
Opcode::Cls => unimplemented!("Cls"),
Opcode::Ctz => unimplemented!("Ctz"),
Opcode::Popcnt => unimplemented!("Popcnt"),
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::Cls => {
let count = if Value::lt(&arg(0)?, &Value::int(0, ctrl_ty)?)? {
Value::int(Value::leading_ones(arg(0)?)?.into_int()?, ctrl_ty)?
} else {
Value::int(Value::leading_zeros(arg(0)?)?.into_int()?, ctrl_ty)?
};
assign(Value::sub(count, Value::int(1, ctrl_ty)?)?)
}
Opcode::Ctz => assign(Value::int(
Value::trailing_zeros(arg(0)?)?.into_int()?,
ctrl_ty,
)?),
Opcode::Popcnt => {
let count = if arg(0)?.ty().is_int() {
Value::int(Value::count_ones(arg(0)?)?.into_int()?, ctrl_ty)?
} 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)?
};
assign(count)
}
Opcode::Fcmp => assign(Value::bool(
fcmp(inst.fp_cond_code().unwrap(), &arg(0)?, &arg(1)?)?,
ctrl_ty.as_bool(),