From 75ef00f1fddcde4f609fa1e8ff99a24c1ad34f28 Mon Sep 17 00:00:00 2001 From: dheaton-arm Date: Mon, 6 Sep 2021 14:34:52 +0100 Subject: [PATCH] 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 --- .../filetests/runtests/simd-swidenhigh.clif | 26 +++++++++++++++++++ .../filetests/runtests/simd-swidenlow.clif | 26 +++++++++++++++++++ cranelift/interpreter/src/step.rs | 24 +++++++++++++++-- cranelift/interpreter/src/value.rs | 16 ++++++------ 4 files changed, 82 insertions(+), 10 deletions(-) create mode 100644 cranelift/filetests/filetests/runtests/simd-swidenhigh.clif create mode 100644 cranelift/filetests/filetests/runtests/simd-swidenlow.clif diff --git a/cranelift/filetests/filetests/runtests/simd-swidenhigh.clif b/cranelift/filetests/filetests/runtests/simd-swidenhigh.clif new file mode 100644 index 0000000000..47d4229c61 --- /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 + +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..997734702b --- /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 + +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 6b3eb59ff8..4a013868e9 100644 --- a/cranelift/interpreter/src/step.rs +++ b/cranelift/interpreter/src/step.rs @@ -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())? 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),