Merge pull request #3314 from dheaton-arm/implement-bitops
Implement bit operations for Cranelift interpreter
This commit is contained in:
@@ -668,11 +668,29 @@ 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)?)?),
|
||||
Opcode::Clz => assign(arg(0)?.leading_zeros()?),
|
||||
Opcode::Cls => {
|
||||
let count = if Value::lt(&arg(0)?, &Value::int(0, ctrl_ty)?)? {
|
||||
arg(0)?.leading_ones()?
|
||||
} else {
|
||||
arg(0)?.leading_zeros()?
|
||||
};
|
||||
assign(Value::sub(count, Value::int(1, ctrl_ty)?)?)
|
||||
}
|
||||
Opcode::Ctz => assign(arg(0)?.trailing_zeros()?),
|
||||
Opcode::Popcnt => {
|
||||
let count = if arg(0)?.ty().is_int() {
|
||||
arg(0)?.count_ones()?
|
||||
} else {
|
||||
let lanes = extractlanes(&arg(0)?, ctrl_ty.lane_type())?
|
||||
.into_iter()
|
||||
.map(|lane| lane.count_ones())
|
||||
.collect::<ValueResult<SimdVec<V>>>()?;
|
||||
vectorizelanes(&lanes, ctrl_ty)?
|
||||
};
|
||||
assign(count)
|
||||
}
|
||||
Opcode::Fcmp => assign(Value::bool(
|
||||
fcmp(inst.fp_cond_code().unwrap(), &arg(0)?, &arg(1)?)?,
|
||||
ctrl_ty.as_bool(),
|
||||
|
||||
@@ -62,6 +62,13 @@ pub trait Value: Clone + From<DataValue> {
|
||||
fn or(self, other: Self) -> ValueResult<Self>;
|
||||
fn xor(self, other: Self) -> ValueResult<Self>;
|
||||
fn not(self) -> ValueResult<Self>;
|
||||
|
||||
// Bit counting.
|
||||
fn count_ones(self) -> ValueResult<Self>;
|
||||
fn leading_ones(self) -> ValueResult<Self>;
|
||||
fn leading_zeros(self) -> ValueResult<Self>;
|
||||
fn trailing_zeros(self) -> ValueResult<Self>;
|
||||
fn reverse_bits(self) -> ValueResult<Self>;
|
||||
}
|
||||
|
||||
#[derive(Error, Debug, PartialEq)]
|
||||
@@ -132,6 +139,20 @@ 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 ),* ] ) => {
|
||||
match $arg1 {
|
||||
$( DataValue::$data_value_ty(a) => {
|
||||
Ok(DataValue::$data_value_ty($return_value_ty::try_from(a.$op()).unwrap()))
|
||||
} )*
|
||||
_ => unimplemented!()
|
||||
}
|
||||
};
|
||||
( $op:ident($arg1:expr); [ $( $data_value_ty:ident ),* ] ) => {
|
||||
match $arg1 {
|
||||
$( DataValue::$data_value_ty(a) => { Ok(DataValue::$data_value_ty(a.$op())) } )*
|
||||
_ => unimplemented!()
|
||||
}
|
||||
};
|
||||
( $op:tt($arg1:expr); [ $( $data_value_ty:ident ),* ] ) => {
|
||||
match $arg1 {
|
||||
$( DataValue::$data_value_ty(a) => { Ok(DataValue::$data_value_ty($op a)) } )*
|
||||
@@ -443,4 +464,24 @@ impl Value for DataValue {
|
||||
fn not(self) -> ValueResult<Self> {
|
||||
unary_match!(!(&self); [I8, I16, I32, I64])
|
||||
}
|
||||
|
||||
fn count_ones(self) -> ValueResult<Self> {
|
||||
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<Self> {
|
||||
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<Self> {
|
||||
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<Self> {
|
||||
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<Self> {
|
||||
unary_match!(reverse_bits(&self); [I8, I16, I32, I64, I128, U8, U16, U32, U64, U128])
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user