From dd23a21b9b51a8370c7cdd5df98dfb5dc75cc943 Mon Sep 17 00:00:00 2001 From: Damian Heaton <87125748+dheaton-arm@users.noreply.github.com> Date: Tue, 7 Sep 2021 17:53:49 +0100 Subject: [PATCH] Implement `Swizzle` and `Splat` for interpreter (#3268) * Implement `Swizzle` and `Splat` for interpreter Implemented for the Cranelift interpreter: - `Swizzle` to shuffle an `i8x16` SIMD vector based on the indices specified in another vector of the same size. - `Splat` to create a SIMD vector with all lanes having the same value. Copyright (c) 2021, Arm Limited * Fix old x86 backend failing test Copyright (c) 2021, Arm Limited * Represent i16x8 and above as hex Copyright (c) 2021, Arm Limited --- .../filetests/runtests/simd-splat.clif | 33 +++++++++++++++++++ .../filetests/runtests/simd-swizzle.clif | 33 +++++++++++++++++++ cranelift/interpreter/src/step.rs | 20 +++++++++-- 3 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 cranelift/filetests/filetests/runtests/simd-splat.clif create mode 100644 cranelift/filetests/filetests/runtests/simd-swizzle.clif diff --git a/cranelift/filetests/filetests/runtests/simd-splat.clif b/cranelift/filetests/filetests/runtests/simd-splat.clif new file mode 100644 index 0000000000..0da9d65c20 --- /dev/null +++ b/cranelift/filetests/filetests/runtests/simd-splat.clif @@ -0,0 +1,33 @@ +test interpret +test run +target aarch64 +set enable_simd +target x86_64 + +function %splat_i8x16(i8) -> i8x16 { +block0(v0: i8): + v1 = splat.i8x16 v0 + return v1 +} +; run: %splat_i8x16(1) == [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1] + +function %splat_i16x8(i16) -> i16x8 { +block0(v0: i16): + v1 = splat.i16x8 v0 + return v1 +} +; run: %splat_i16x8(512) == [512 512 512 512 512 512 512 512] + +function %splat_i32x4(i32) -> i32x4 { +block0(v0: i32): + v1 = splat.i32x4 v0 + return v1 +} +; run: %splat_i32x4(2000000) == [2000000 2000000 2000000 2000000] + +function %splat_i64x2(i64) -> i64x2 { +block0(v0: i64): + v1 = splat.i64x2 v0 + return v1 +} +; run: %splat_i64x2(5000000000) == [5000000000 5000000000] diff --git a/cranelift/filetests/filetests/runtests/simd-swizzle.clif b/cranelift/filetests/filetests/runtests/simd-swizzle.clif new file mode 100644 index 0000000000..6cad36f033 --- /dev/null +++ b/cranelift/filetests/filetests/runtests/simd-swizzle.clif @@ -0,0 +1,33 @@ +test interpret +test run +target aarch64 +set enable_simd +target x86_64 machinst + +function %swizzle_i8x16(i8x16, i8x16) -> i8x16 { +block0(v0: i8x16, v1: i8x16): + v2 = swizzle.i8x16 v0, v1 + return v2 +} +; run: %swizzle_i8x16([1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16], [0 9 15 1 6 13 7 11 10 8 100 12 4 2 3 5]) == [1 10 16 2 7 14 8 12 11 9 0 13 5 3 4 6] + +function %swizzle_i16x8(i8x16, i8x16) -> i16x8 { +block0(v0: i8x16, v1: i8x16): + v2 = swizzle.i16x8 v0, v1 + return v2 +} +; run: %swizzle_i16x8([1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16], [0 9 15 1 6 13 7 11 10 8 100 12 4 2 3 5]) == 0x060403050d00090b0c080e0702100a01 + +function %swizzle_i32x4(i8x16, i8x16) -> i32x4 { +block0(v0: i8x16, v1: i8x16): + v2 = swizzle.i32x4 v0, v1 + return v2 +} +; run: %swizzle_i32x4([1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16], [0 9 15 1 6 13 7 11 10 8 100 12 4 2 3 5]) == 0x060403050d00090b0c080e0702100a01 + +function %swizzle_i64x2(i8x16, i8x16) -> i64x2 { +block0(v0: i8x16, v1: i8x16): + v2 = swizzle.i64x2 v0, v1 + return v2 +} +; run: %swizzle_i64x2([1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16], [0 9 15 1 6 13 7 11 10 8 100 12 4 2 3 5]) == 0x060403050d00090b0c080e0702100a01 diff --git a/cranelift/interpreter/src/step.rs b/cranelift/interpreter/src/step.rs index a485401776..309b9305d1 100644 --- a/cranelift/interpreter/src/step.rs +++ b/cranelift/interpreter/src/step.rs @@ -777,8 +777,24 @@ where ValueConversionKind::RoundNearestEven(ctrl_ty), )?), Opcode::Shuffle => unimplemented!("Shuffle"), - Opcode::Swizzle => unimplemented!("Swizzle"), - Opcode::Splat => unimplemented!("Splat"), + Opcode::Swizzle => { + let x = Value::into_array(&arg(0)?)?; + let s = Value::into_array(&arg(1)?)?; + let mut new = [0u8; 16]; + for i in 0..new.len() { + if (s[i] as usize) < new.len() { + new[i] = x[s[i] as usize]; + } // else leave as 0 + } + assign(Value::vector(new, ctrl_ty)?) + } + Opcode::Splat => { + let mut new_vector = SimdVec::new(); + for _ in 0..ctrl_ty.lane_count() { + new_vector.push(arg(0)?.into_int()?); + } + assign(vectorizelanes(&new_vector, ctrl_ty)?) + } Opcode::Insertlane => { let idx = imm().into_int()? as usize; let mut vector = extractlanes(&arg(0)?, ctrl_ty.lane_type())?;