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:
26
cranelift/filetests/filetests/runtests/simd-swidenhigh.clif
Normal file
26
cranelift/filetests/filetests/runtests/simd-swidenhigh.clif
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
test interpret
|
||||||
|
test run
|
||||||
|
target aarch64
|
||||||
|
set enable_simd
|
||||||
|
target x86_64
|
||||||
|
|
||||||
|
function %swidenhigh_i8x16(i8x16) -> i16x8 {
|
||||||
|
block0(v0: i8x16):
|
||||||
|
v1 = swiden_high v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %swidenhigh_i8x16([1 -2 3 -4 5 -6 7 -8 9 -10 11 -12 13 -14 15 -16]) == [9 -10 11 -12 13 -14 15 -16]
|
||||||
|
|
||||||
|
function %swidenhigh_i16x8(i16x8) -> i32x4 {
|
||||||
|
block0(v0: i16x8):
|
||||||
|
v1 = swiden_high v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %swidenhigh_i16x8([1 -2 3 -4 5 -6 7 -8]) == [5 -6 7 -8]
|
||||||
|
|
||||||
|
function %swidenhigh_i32x4(i32x4) -> i64x2 {
|
||||||
|
block0(v0: i32x4):
|
||||||
|
v1 = swiden_high v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %swidenhigh_i32x4([1 -2 3 -4]) == [3 -4]
|
||||||
26
cranelift/filetests/filetests/runtests/simd-swidenlow.clif
Normal file
26
cranelift/filetests/filetests/runtests/simd-swidenlow.clif
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
test interpret
|
||||||
|
test run
|
||||||
|
target aarch64
|
||||||
|
set enable_simd
|
||||||
|
target x86_64
|
||||||
|
|
||||||
|
function %swidenlow_i8x16(i8x16) -> i16x8 {
|
||||||
|
block0(v0: i8x16):
|
||||||
|
v1 = swiden_low v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %swidenlow_i8x16([1 -2 3 -4 5 -6 7 -8 9 -10 11 -12 13 -14 15 -16]) == [1 -2 3 -4 5 -6 7 -8]
|
||||||
|
|
||||||
|
function %swidenlow_i16x8(i16x8) -> i32x4 {
|
||||||
|
block0(v0: i16x8):
|
||||||
|
v1 = swiden_low v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %swidenlow_i16x8([1 -2 3 -4 5 -6 7 -8]) == [1 -2 3 -4]
|
||||||
|
|
||||||
|
function %swidenlow_i32x4(i32x4) -> i64x2 {
|
||||||
|
block0(v0: i32x4):
|
||||||
|
v1 = swiden_low v0
|
||||||
|
return v1
|
||||||
|
}
|
||||||
|
; run: %swidenlow_i32x4([1 -2 3 -4]) == [1 -2]
|
||||||
@@ -840,8 +840,28 @@ where
|
|||||||
V::bool(true, types::B1)?,
|
V::bool(true, types::B1)?,
|
||||||
|acc, lane| acc.and(lane),
|
|acc, lane| acc.and(lane),
|
||||||
)?),
|
)?),
|
||||||
Opcode::SwidenLow => unimplemented!("SwidenLow"),
|
Opcode::SwidenLow => {
|
||||||
Opcode::SwidenHigh => unimplemented!("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.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 => {
|
Opcode::UwidenLow => {
|
||||||
let new_type = ctrl_ty.merge_lanes().unwrap();
|
let new_type = ctrl_ty.merge_lanes().unwrap();
|
||||||
let new_vec = extractlanes(&arg(0)?, ctrl_ty.lane_type())?
|
let new_vec = extractlanes(&arg(0)?, ctrl_ty.lane_type())?
|
||||||
|
|||||||
@@ -301,14 +301,14 @@ impl Value for DataValue {
|
|||||||
let extracted = (self.into_int()? & shifted_mask) >> shift_amt;
|
let extracted = (self.into_int()? & shifted_mask) >> shift_amt;
|
||||||
Self::from_integer(extracted, ty)?
|
Self::from_integer(extracted, ty)?
|
||||||
}
|
}
|
||||||
ValueConversionKind::SignExtend(ty) => match (self.ty(), ty) {
|
ValueConversionKind::SignExtend(ty) => match (self, ty) {
|
||||||
(types::I8, types::I16) => unimplemented!(),
|
(DataValue::I8(n), types::I16) => DataValue::I16(n as i16),
|
||||||
(types::I8, types::I32) => unimplemented!(),
|
(DataValue::I8(n), types::I32) => DataValue::I32(n as i32),
|
||||||
(types::I8, types::I64) => unimplemented!(),
|
(DataValue::I8(n), types::I64) => DataValue::I64(n as i64),
|
||||||
(types::I16, types::I32) => unimplemented!(),
|
(DataValue::I16(n), types::I32) => DataValue::I32(n as i32),
|
||||||
(types::I16, types::I64) => unimplemented!(),
|
(DataValue::I16(n), types::I64) => DataValue::I64(n as i64),
|
||||||
(types::I32, types::I64) => unimplemented!(),
|
(DataValue::I32(n), types::I64) => DataValue::I64(n as i64),
|
||||||
_ => unimplemented!("conversion: {} -> {:?}", self.ty(), kind),
|
(dv, _) => unimplemented!("conversion: {} -> {:?}", dv.ty(), kind),
|
||||||
},
|
},
|
||||||
ValueConversionKind::ZeroExtend(ty) => match (self, ty) {
|
ValueConversionKind::ZeroExtend(ty) => match (self, ty) {
|
||||||
(DataValue::U8(n), types::I16) => DataValue::U16(n as u16),
|
(DataValue::U8(n), types::I16) => DataValue::U16(n as u16),
|
||||||
|
|||||||
Reference in New Issue
Block a user