diff --git a/cranelift/filetests/filetests/runtests/simd-swidenhigh.clif b/cranelift/filetests/filetests/runtests/simd-swidenhigh.clif new file mode 100644 index 0000000000..6242859e8d --- /dev/null +++ b/cranelift/filetests/filetests/runtests/simd-swidenhigh.clif @@ -0,0 +1,26 @@ +test interpret +test run +target aarch64 +set enable_simd +target x86_64 machinst + +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] diff --git a/cranelift/filetests/filetests/runtests/simd-swidenlow.clif b/cranelift/filetests/filetests/runtests/simd-swidenlow.clif new file mode 100644 index 0000000000..38f100ef29 --- /dev/null +++ b/cranelift/filetests/filetests/runtests/simd-swidenlow.clif @@ -0,0 +1,26 @@ +test interpret +test run +target aarch64 +set enable_simd +target x86_64 machinst + +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] diff --git a/cranelift/interpreter/src/step.rs b/cranelift/interpreter/src/step.rs index 0b6ecd2f05..25ec8b2878 100644 --- a/cranelift/interpreter/src/step.rs +++ b/cranelift/interpreter/src/step.rs @@ -863,24 +863,29 @@ where V::bool(true, types::B1)?, |acc, lane| acc.and(lane), )?), - Opcode::SwidenLow => unimplemented!("SwidenLow"), - Opcode::SwidenHigh => unimplemented!("SwidenHigh"), - Opcode::UwidenLow => { + Opcode::SwidenLow | Opcode::SwidenHigh | Opcode::UwidenLow | Opcode::UwidenHigh => { let new_type = ctrl_ty.merge_lanes().unwrap(); - let new_vec = extractlanes(&arg(0)?, ctrl_ty.lane_type())? - .into_iter() - .take(new_type.lane_count() as usize) - .map(|lane| lane.convert(ValueConversionKind::ZeroExtend(new_type.lane_type()))) - .collect::>>()?; - assign(vectorizelanes(&new_vec, new_type)?) - } - Opcode::UwidenHigh => { - let new_type = ctrl_ty.merge_lanes().unwrap(); - let new_vec = extractlanes(&arg(0)?, ctrl_ty.lane_type())? - .into_iter() - .skip(new_type.lane_count() as usize) - .map(|lane| lane.convert(ValueConversionKind::ZeroExtend(new_type.lane_type()))) - .collect::>>()?; + let conv_type = match inst.opcode() { + Opcode::SwidenLow | Opcode::SwidenHigh => { + ValueConversionKind::SignExtend(new_type.lane_type()) + } + Opcode::UwidenLow | Opcode::UwidenHigh => { + ValueConversionKind::ZeroExtend(new_type.lane_type()) + } + _ => unreachable!(), + }; + let vec_iter = extractlanes(&arg(0)?, ctrl_ty.lane_type())?.into_iter(); + let new_vec = match inst.opcode() { + Opcode::SwidenLow | Opcode::UwidenLow => vec_iter + .take(new_type.lane_count() as usize) + .map(|lane| lane.convert(conv_type.clone())) + .collect::>>()?, + Opcode::SwidenHigh | Opcode::UwidenHigh => vec_iter + .skip(new_type.lane_count() as usize) + .map(|lane| lane.convert(conv_type.clone())) + .collect::>>()?, + _ => unreachable!(), + }; assign(vectorizelanes(&new_vec, new_type)?) } Opcode::FcvtToUint => unimplemented!("FcvtToUint"), diff --git a/cranelift/interpreter/src/value.rs b/cranelift/interpreter/src/value.rs index bd4cd93445..768ccfe8e2 100644 --- a/cranelift/interpreter/src/value.rs +++ b/cranelift/interpreter/src/value.rs @@ -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),