From 75ef00f1fddcde4f609fa1e8ff99a24c1ad34f28 Mon Sep 17 00:00:00 2001 From: dheaton-arm Date: Mon, 6 Sep 2021 14:34:52 +0100 Subject: [PATCH 1/4] 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), From d2cbe4fc305e2314009380e01a8ef4f7d2f5cab6 Mon Sep 17 00:00:00 2001 From: dheaton-arm Date: Wed, 8 Sep 2021 15:44:20 +0100 Subject: [PATCH 2/4] Fix failing test from old x86 backend Copyright (c) 2021, Arm Limited --- cranelift/filetests/filetests/runtests/simd-swidenhigh.clif | 2 +- cranelift/filetests/filetests/runtests/simd-swidenlow.clif | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cranelift/filetests/filetests/runtests/simd-swidenhigh.clif b/cranelift/filetests/filetests/runtests/simd-swidenhigh.clif index 47d4229c61..6242859e8d 100644 --- a/cranelift/filetests/filetests/runtests/simd-swidenhigh.clif +++ b/cranelift/filetests/filetests/runtests/simd-swidenhigh.clif @@ -2,7 +2,7 @@ test interpret test run target aarch64 set enable_simd -target x86_64 +target x86_64 machinst function %swidenhigh_i8x16(i8x16) -> i16x8 { block0(v0: i8x16): diff --git a/cranelift/filetests/filetests/runtests/simd-swidenlow.clif b/cranelift/filetests/filetests/runtests/simd-swidenlow.clif index 997734702b..38f100ef29 100644 --- a/cranelift/filetests/filetests/runtests/simd-swidenlow.clif +++ b/cranelift/filetests/filetests/runtests/simd-swidenlow.clif @@ -2,7 +2,7 @@ test interpret test run target aarch64 set enable_simd -target x86_64 +target x86_64 machinst function %swidenlow_i8x16(i8x16) -> i16x8 { block0(v0: i8x16): From a595bd22e37c509f00a20c313d536fa1b14fc2a5 Mon Sep 17 00:00:00 2001 From: dheaton-arm Date: Thu, 9 Sep 2021 10:34:29 +0100 Subject: [PATCH 3/4] Replace loops with iterator methods. Copyright (c) 2021, Arm Limited --- cranelift/interpreter/src/step.rs | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/cranelift/interpreter/src/step.rs b/cranelift/interpreter/src/step.rs index 4a013868e9..78b56dba9f 100644 --- a/cranelift/interpreter/src/step.rs +++ b/cranelift/interpreter/src/step.rs @@ -842,24 +842,20 @@ where )?), 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); - } + let new_vec = extractlanes(&arg(0)?, ctrl_ty.lane_type())? + .into_iter() + .take(new_type.lane_count() as usize) + .map(|lane| lane.convert(ValueConversionKind::SignExtend(new_type.lane_type()))) + .collect::>>()?; 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); - } + let new_vec = extractlanes(&arg(0)?, ctrl_ty.lane_type())? + .into_iter() + .skip(new_type.lane_count() as usize) + .map(|lane| lane.convert(ValueConversionKind::SignExtend(new_type.lane_type()))) + .collect::>>()?; assign(vectorizelanes(&new_vec, new_type)?) } Opcode::UwidenLow => { From 99cc95d6302b7069c4cc76150e80035cb6fb5e8e Mon Sep 17 00:00:00 2001 From: dheaton-arm Date: Tue, 14 Sep 2021 13:08:35 +0100 Subject: [PATCH 4/4] Factor out shared logic for widening ops. Copyright (c) 2021, Arm Limited --- cranelift/interpreter/src/step.rs | 55 +++++++++++++------------------ 1 file changed, 22 insertions(+), 33 deletions(-) diff --git a/cranelift/interpreter/src/step.rs b/cranelift/interpreter/src/step.rs index 78b56dba9f..d01d625b5c 100644 --- a/cranelift/interpreter/src/step.rs +++ b/cranelift/interpreter/src/step.rs @@ -840,40 +840,29 @@ where V::bool(true, types::B1)?, |acc, lane| acc.and(lane), )?), - Opcode::SwidenLow => { + 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::SignExtend(new_type.lane_type()))) - .collect::>>()?; - assign(vectorizelanes(&new_vec, new_type)?) - } - Opcode::SwidenHigh => { - 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::SignExtend(new_type.lane_type()))) - .collect::>>()?; - 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())? - .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"),