diff --git a/cranelift/filetests/filetests/runtests/simd-shuffle.clif b/cranelift/filetests/filetests/runtests/simd-shuffle.clif new file mode 100644 index 0000000000..d4151953e6 --- /dev/null +++ b/cranelift/filetests/filetests/runtests/simd-shuffle.clif @@ -0,0 +1,12 @@ +test interpret +test run +target aarch64 +set enable_simd +target x86_64 + +function %shuffle_i8x16(i8x16, i8x16) -> i8x16 { +block0(v0: i8x16, v1: i8x16): + v2 = shuffle v0, v1, [3 0 31 26 100 6 12 11 23 13 24 4 2 15 17 5] + return v2 +} +; run: %shuffle_i8x16([1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16], [17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32]) == [4 1 32 27 0 7 13 12 24 14 25 5 3 16 18 6] diff --git a/cranelift/interpreter/src/step.rs b/cranelift/interpreter/src/step.rs index 6b3eb59ff8..0b6ecd2f05 100644 --- a/cranelift/interpreter/src/step.rs +++ b/cranelift/interpreter/src/step.rs @@ -76,6 +76,16 @@ where .as_slice(); DataValue::V128(buffer.try_into().expect("a 16-byte data buffer")) } + InstructionData::Shuffle { mask, .. } => { + let mask = state + .get_current_function() + .dfg + .immediates + .get(mask) + .unwrap() + .as_slice(); + DataValue::V128(mask.try_into().expect("a 16-byte vector mask")) + } _ => inst.imm_value().unwrap(), }) }; @@ -794,7 +804,20 @@ where arg(0)?, ValueConversionKind::RoundNearestEven(ctrl_ty), )?), - Opcode::Shuffle => unimplemented!("Shuffle"), + Opcode::Shuffle => { + let mask = imm().into_array()?; + let a = Value::into_array(&arg(0)?)?; + let b = Value::into_array(&arg(1)?)?; + let mut new = [0u8; 16]; + for i in 0..mask.len() { + if (mask[i] as usize) < a.len() { + new[i] = a[mask[i] as usize]; + } else if (mask[i] as usize - a.len()) < b.len() { + new[i] = b[mask[i] as usize - a.len()]; + } // else leave as 0. + } + assign(Value::vector(new, ctrl_ty)?) + } Opcode::Swizzle => { let x = Value::into_array(&arg(0)?)?; let s = Value::into_array(&arg(1)?)?;