Implement SwidenLow and SwidenHigh for the interpreter

Implemented `SwidenLow` and `SwidenHigh` for the Cranelift interpreter,
doubling the width and halving the number of lanes preserving the low
and high halves respectively.

Conversions are performed using signed extension.

Copyright (c) 2021, Arm Limited
This commit is contained in:
dheaton-arm
2021-09-06 14:34:52 +01:00
parent 9323762d71
commit 75ef00f1fd
4 changed files with 82 additions and 10 deletions

View File

@@ -840,8 +840,28 @@ where
V::bool(true, types::B1)?,
|acc, lane| acc.and(lane),
)?),
Opcode::SwidenLow => unimplemented!("SwidenLow"),
Opcode::SwidenHigh => unimplemented!("SwidenHigh"),
Opcode::SwidenLow => {
let new_type = ctrl_ty.merge_lanes().unwrap();
let mut new_vec = SimdVec::new();
let mut arg0 = extractlanes(&arg(0)?, ctrl_ty.lane_type())?;
arg0.truncate(new_type.lane_count() as usize);
for lane in arg0 {
let lane = lane.convert(ValueConversionKind::SignExtend(new_type.lane_type()))?;
new_vec.push(lane);
}
assign(vectorizelanes(&new_vec, new_type)?)
}
Opcode::SwidenHigh => {
let new_type = ctrl_ty.merge_lanes().unwrap();
let mut new_vec = SimdVec::new();
let mut arg0 = extractlanes(&arg(0)?, ctrl_ty.lane_type())?;
arg0.drain(0..new_type.lane_count() as usize);
for lane in arg0 {
let lane = lane.convert(ValueConversionKind::SignExtend(new_type.lane_type()))?;
new_vec.push(lane);
}
assign(vectorizelanes(&new_vec, new_type)?)
}
Opcode::UwidenLow => {
let new_type = ctrl_ty.merge_lanes().unwrap();
let new_vec = extractlanes(&arg(0)?, ctrl_ty.lane_type())?

View File

@@ -301,14 +301,14 @@ impl Value for DataValue {
let extracted = (self.into_int()? & shifted_mask) >> shift_amt;
Self::from_integer(extracted, ty)?
}
ValueConversionKind::SignExtend(ty) => match (self.ty(), ty) {
(types::I8, types::I16) => unimplemented!(),
(types::I8, types::I32) => unimplemented!(),
(types::I8, types::I64) => unimplemented!(),
(types::I16, types::I32) => unimplemented!(),
(types::I16, types::I64) => unimplemented!(),
(types::I32, types::I64) => unimplemented!(),
_ => unimplemented!("conversion: {} -> {:?}", self.ty(), kind),
ValueConversionKind::SignExtend(ty) => match (self, ty) {
(DataValue::I8(n), types::I16) => DataValue::I16(n as i16),
(DataValue::I8(n), types::I32) => DataValue::I32(n as i32),
(DataValue::I8(n), types::I64) => DataValue::I64(n as i64),
(DataValue::I16(n), types::I32) => DataValue::I32(n as i32),
(DataValue::I16(n), types::I64) => DataValue::I64(n as i64),
(DataValue::I32(n), types::I64) => DataValue::I64(n as i64),
(dv, _) => unimplemented!("conversion: {} -> {:?}", dv.ty(), kind),
},
ValueConversionKind::ZeroExtend(ty) => match (self, ty) {
(DataValue::U8(n), types::I16) => DataValue::U16(n as u16),