Skip to content

Commit de6be01

Browse files
committed
test wasm32 simd128 instructions
1 parent 1ab5af1 commit de6be01

File tree

8 files changed

+676
-81
lines changed

8 files changed

+676
-81
lines changed

.travis.yml

+2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ matrix:
4242
- cat wasm.wat
4343
- grep current_memory wasm.wat
4444
- grep grow_memory wasm.wat
45+
- cargo test --manifest-path=crates/wasm-test
46+
- cargo test --release --manifest-path=crates/wasm-test
4547
- env: TARGET=thumbv6m-none-eabi NOSTD=1
4648
- env: TARGET=thumbv7m-none-eabi NOSTD=1
4749
- env: TARGET=thumbv7em-none-eabi NOSTD=1

Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ members = [
33
"crates/stdsimd-verify",
44
"crates/stdsimd",
55
]
6+
exclude = [
7+
"crates/wasm-test"
8+
]
69

710
[profile.release]
811
debug = true

coresimd/wasm32/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! WASM32 intrinsics
22
3+
#[macro_use]
34
mod simd128;
5+
pub use self::simd128::*;
46

57
extern "C" {
68
#[link_name = "llvm.wasm.grow.memory.i32"]

coresimd/wasm32/simd128.rs

+71-81
Original file line numberDiff line numberDiff line change
@@ -6,48 +6,17 @@
66
#![allow(non_camel_case_types)]
77

88
/// A single unconstrained byte (0-255).
9-
#[derive(Copy, Clone, Debug)]
10-
pub struct ImmByte(u8);
11-
impl ImmByte {
12-
/// Constructor
13-
#[inline]
14-
#[rustc_args_required_const(0)]
15-
pub const fn new(value: u8) -> Self {
16-
ImmByte(value)
17-
}
18-
}
19-
20-
macro_rules! impl_laneidx {
21-
($id:ident($ty:ty): [$_from:expr, $_to:expr] | $(#[$doc:meta])*) => {
22-
#[derive(Copy, Clone, Debug)]
23-
pub struct $id($ty);
24-
impl $id {
25-
#[inline]
26-
#[rustc_args_required_const(0)]
27-
pub const fn new(x: $ty) -> Self {
28-
// FIXME: not allowed in const fn:
29-
// * if statements
30-
// * unreachable_unchecked / panic / abort
31-
//
32-
// if x < $from || x > $to {
33-
// unsafe { ::_core::hint::unreachable_unchecked() };
34-
// debug_assert!(...)
35-
// }
36-
$id(x)
37-
}
38-
}
39-
};
40-
}
41-
impl_laneidx!(LaneIdx2(u8): [0, 1] | /// A byte with values in the range 0–1 identifying a lane.
42-
);
43-
impl_laneidx!(LaneIdx4(u8): [0, 3] | /// A byte with values in the range 0–3 identifying a lane.
44-
);
45-
impl_laneidx!(LaneIdx8(u8): [0, 7] | /// A byte with values in the range 0–7 identifying a lane.
46-
);
47-
impl_laneidx!(LaneIdx16(u8): [0, 15] | /// A byte with values in the range 0–15 identifying a lane.
48-
);
49-
impl_laneidx!(LaneIdx32(u8): [0, 31] | /// A byte with values in the range 0–31 identifying a lane.
50-
);
9+
pub type ImmByte = u8;
10+
/// A byte with values in the range 0–1 identifying a lane.
11+
pub type LaneIdx2 = u8;
12+
/// A byte with values in the range 0–3 identifying a lane.
13+
pub type LaneIdx4 = u8;
14+
/// A byte with values in the range 0–7 identifying a lane.
15+
pub type LaneIdx8 = u8;
16+
/// A byte with values in the range 0–15 identifying a lane.
17+
pub type LaneIdx16 = u8;
18+
/// A byte with values in the range 0–31 identifying a lane.
19+
pub type LaneIdx32 = u8;
5120

5221
types! {
5322
/// WASM-specific 128-bit wide SIMD vector type
@@ -102,6 +71,9 @@ mod sealed {
10271
fn sqrt_v4f32(x: f32x4) -> f32x4;
10372
#[link_name = "llvm.sqrt.v2f64"]
10473
fn sqrt_v2f64(x: f64x2) -> f64x2;
74+
#[link_name = "shufflevector"]
75+
pub fn shufflevector_v16i8(x: v8x16, y: v8x16, i: v8x16) -> v8x16;
76+
10577
}
10678
impl f32x4 {
10779
#[inline(always)]
@@ -214,7 +186,7 @@ macro_rules! impl_extract_lane {
214186
a: v128
215187
}
216188
// the vectors store a signed integer => extract into it
217-
let v: $selem_ty = simd_extract(U { a }.vec, imm.0 as u32 /* zero-extends index */);
189+
let v: $selem_ty = simd_extract(U { a }.vec, imm as u32 /* zero-extends index */);
218190
v as $x_ty
219191
}
220192

@@ -233,7 +205,7 @@ macro_rules! impl_extract_lane {
233205
a: v128
234206
}
235207
// the vectors store a signed integer => extract into it
236-
let v: $selem_ty = simd_extract(U { a }.vec, imm.0 as u32 /* zero-extends index */);
208+
let v: $selem_ty = simd_extract(U { a }.vec, imm as u32 /* zero-extends index */);
237209
// re-interpret the signed integer as an unsigned one of the same size (no-op)
238210
let v: $uelem_ty= ::mem::transmute(v);
239211
// cast the internal unsigned integer to a larger signed integer (zero-extends)
@@ -258,7 +230,7 @@ macro_rules! impl_extract_lane {
258230
a: v128
259231
}
260232
// the vectors store a signed integer => extract into it
261-
simd_extract(U { a }.vec, imm.0 as u32 /* zero-extends index */)
233+
simd_extract(U { a }.vec, imm as u32 /* zero-extends index */)
262234
}
263235
}
264236
};
@@ -291,7 +263,7 @@ macro_rules! impl_replace_lane {
291263
// the vectors store a signed integer => extract into it
292264
::mem::transmute(
293265
simd_insert(U { a }.vec,
294-
imm.0 as u32 /* zero-extends index */,
266+
imm as u32 /* zero-extends index */,
295267
x as $ielem_ty)
296268
)
297269
}
@@ -306,23 +278,44 @@ impl_replace_lane!(i64x2[v64x2:i64](LaneIdx2) <= i64);
306278
impl_replace_lane!(f32x4[f32x4:f32](LaneIdx4) <= f32);
307279
impl_replace_lane!(f64x2[f64x2:f64](LaneIdx2) <= f64);
308280

309-
impl v8x16 {
310-
/// Shuffle lanes
311-
///
312-
/// Create vector with lanes selected from the lanes of two input vectors
313-
/// `a` and `b` by the indices specified in the immediate mode operand
314-
/// `imm`. Each index selects an element of the result vector, where the
315-
/// indices `i` in range `[0, 15]` select the `i`-th elements of `a`, and
316-
/// the indices in range `[16, 31]` select the `i - 16`-th element of `b`.
317-
#[inline]
318-
// #[target_feature(enable = "simd128")]
319-
// FIXME: #[cfg_attr(test, assert_instr(v8x16.shuffle))]
320-
#[rustc_args_required_const(2)]
321-
pub unsafe fn shuffle(a: v128, b: v128, imm: [LaneIdx32; 16]) -> v128 {
322-
// FIXME: LLVM does not support v8x16.shuffle (use inline assembly?)
323-
let result: v128;
324-
asm!("v8x16.shuffle $0, $1, $2" : "=r"(result) : "r"(a), "r"(b), "r"(imm) : : );
325-
result
281+
pub use ::coresimd::simd_llvm::simd_shuffle16 as __internal_v8x16_shuffle;
282+
pub use self::sealed::v8x16 as __internal_v8x16;
283+
284+
/// Shuffle lanes
285+
///
286+
/// Create vector with lanes selected from the lanes of two input vectors
287+
/// `a` and `b` by the indices specified in the immediate mode operand
288+
/// `imm`. Each index selects an element of the result vector, where the
289+
/// indices `i` in range `[0, 15]` select the `i`-th elements of `a`, and
290+
/// the indices in range `[16, 31]` select the `i - 16`-th element of `b`.
291+
#[macro_export]
292+
macro_rules! v8x16_shuffle {
293+
($a:expr, $b:expr, [
294+
$imm0:expr, $imm1:expr, $imm2:expr, $imm3:expr,
295+
$imm4:expr, $imm5:expr, $imm6:expr, $imm7:expr,
296+
$imm8:expr, $imm9:expr, $imm10:expr, $imm11:expr,
297+
$imm12:expr, $imm13:expr, $imm14:expr, $imm15:expr
298+
]) => {
299+
#[allow(unused_unsafe)]
300+
unsafe {
301+
let a: $crate::arch::wasm32::v128 = $a;
302+
let b: $crate::arch::wasm32::v128 = $b;
303+
union U {
304+
e: v128,
305+
i: $crate::arch::wasm32::__internal_v8x16,
306+
}
307+
let a = U { e: a }.i;
308+
let b = U { e: b }.i;
309+
310+
let r: $crate::arch::wasm32::__internal_v8x16 =
311+
$crate::arch::wasm32::__internal_v8x16_shuffle(a, b, [
312+
$imm0 as u32, $imm1, $imm2, $imm3,
313+
$imm4, $imm5, $imm6, $imm7,
314+
$imm8, $imm9, $imm10, $imm11,
315+
$imm12, $imm13, $imm14, $imm15
316+
]);
317+
U { i: r }.e
318+
}
326319
}
327320
}
328321

@@ -557,6 +550,9 @@ impl_boolean_reduction!(i64x2[v64x2]);
557550

558551
macro_rules! impl_comparisons {
559552
($id:ident[$ivec_ty:ident]) => {
553+
impl_comparisons!($id[$ivec_ty=>$ivec_ty]);
554+
};
555+
($id:ident[$ivec_ty:ident=>$rvec_ty:ident]) => {
560556
impl $id {
561557
/// Equality
562558
#[inline]
@@ -566,7 +562,7 @@ macro_rules! impl_comparisons {
566562
use coresimd::simd_llvm::simd_eq;
567563
let a: sealed::$ivec_ty = ::mem::transmute(a);
568564
let b: sealed::$ivec_ty = ::mem::transmute(b);
569-
let c: sealed::$ivec_ty = simd_eq(a, b);
565+
let c: sealed::$rvec_ty = simd_eq(a, b);
570566
::mem::transmute(c)
571567
}
572568
/// Non-Equality
@@ -577,7 +573,7 @@ macro_rules! impl_comparisons {
577573
use coresimd::simd_llvm::simd_ne;
578574
let a: sealed::$ivec_ty = ::mem::transmute(a);
579575
let b: sealed::$ivec_ty = ::mem::transmute(b);
580-
let c: sealed::$ivec_ty = simd_ne(a, b);
576+
let c: sealed::$rvec_ty = simd_ne(a, b);
581577
::mem::transmute(c)
582578
}
583579
/// Less-than
@@ -588,7 +584,7 @@ macro_rules! impl_comparisons {
588584
use coresimd::simd_llvm::simd_lt;
589585
let a: sealed::$ivec_ty = ::mem::transmute(a);
590586
let b: sealed::$ivec_ty = ::mem::transmute(b);
591-
let c: sealed::$ivec_ty = simd_lt(a, b);
587+
let c: sealed::$rvec_ty = simd_lt(a, b);
592588
::mem::transmute(c)
593589
}
594590

@@ -600,7 +596,7 @@ macro_rules! impl_comparisons {
600596
use coresimd::simd_llvm::simd_le;
601597
let a: sealed::$ivec_ty = ::mem::transmute(a);
602598
let b: sealed::$ivec_ty = ::mem::transmute(b);
603-
let c: sealed::$ivec_ty = simd_le(a, b);
599+
let c: sealed::$rvec_ty = simd_le(a, b);
604600
::mem::transmute(c)
605601
}
606602

@@ -612,7 +608,7 @@ macro_rules! impl_comparisons {
612608
use coresimd::simd_llvm::simd_gt;
613609
let a: sealed::$ivec_ty = ::mem::transmute(a);
614610
let b: sealed::$ivec_ty = ::mem::transmute(b);
615-
let c: sealed::$ivec_ty = simd_gt(a, b);
611+
let c: sealed::$rvec_ty = simd_gt(a, b);
616612
::mem::transmute(c)
617613
}
618614

@@ -624,7 +620,7 @@ macro_rules! impl_comparisons {
624620
use coresimd::simd_llvm::simd_ge;
625621
let a: sealed::$ivec_ty = ::mem::transmute(a);
626622
let b: sealed::$ivec_ty = ::mem::transmute(b);
627-
let c: sealed::$ivec_ty = simd_ge(a, b);
623+
let c: sealed::$rvec_ty = simd_ge(a, b);
628624
::mem::transmute(c)
629625
}
630626
}
@@ -635,8 +631,8 @@ impl_comparisons!(i8x16[v8x16]);
635631
impl_comparisons!(i16x8[v16x8]);
636632
impl_comparisons!(i32x4[v32x4]);
637633
impl_comparisons!(i64x2[v64x2]);
638-
impl_comparisons!(f32x4[f32x4]);
639-
impl_comparisons!(f64x2[f64x2]);
634+
impl_comparisons!(f32x4[f32x4=>v32x4]);
635+
impl_comparisons!(f64x2[f64x2=>v64x2]);
640636

641637
// Load and store
642638
impl v128 {
@@ -696,10 +692,7 @@ macro_rules! impl_floating_point_ops {
696692
// #[target_feature(enable = "simd128")]
697693
// FIXME: #[cfg_attr(test, assert_instr($id.min))]
698694
pub unsafe fn min(a: v128, b: v128) -> v128 {
699-
use coresimd::simd_llvm::simd_fmin;
700-
let a: sealed::$id = ::mem::transmute(a);
701-
let b: sealed::$id = ::mem::transmute(b);
702-
::mem::transmute(simd_fmin(a, b))
695+
v128::bitselect(a, b, $id::lt(a, b))
703696
}
704697

705698
/// NaN-propagating maximum
@@ -709,10 +702,7 @@ macro_rules! impl_floating_point_ops {
709702
// #[target_feature(enable = "simd128")]
710703
// FIXME: #[cfg_attr(test, assert_instr($id.max))]
711704
pub unsafe fn max(a: v128, b: v128) -> v128 {
712-
use coresimd::simd_llvm::simd_fmax;
713-
let a: sealed::$id = ::mem::transmute(a);
714-
let b: sealed::$id = ::mem::transmute(b);
715-
::mem::transmute(simd_fmax(a, b))
705+
v128::bitselect(a, b, $id::gt(a, b))
716706
}
717707

718708
/// Square-root
@@ -794,9 +784,9 @@ macro_rules! impl_conversion {
794784

795785
// Integer to floating point
796786
impl_conversion!(convert_s_i32x4["f32x4.convert_s/i32x4"]: v32x4 => f32x4 | f32x4);
797-
impl_conversion!(convert_u_i32x4["f32x4.convert_u/i32x4"]: v32x4 => f32x4 | f32x4);
787+
impl_conversion!(convert_u_i32x4["f32x4.convert_u/i32x4"]: u32x4 => f32x4 | f32x4);
798788
impl_conversion!(convert_s_i64x2["f64x2.convert_s/i64x2"]: v64x2 => f64x2 | f64x2);
799-
impl_conversion!(convert_u_i64x2["f64x2.convert_u/i64x2"]: v64x2 => f64x2 | f64x2);
789+
impl_conversion!(convert_u_i64x2["f64x2.convert_u/i64x2"]: u64x2 => f64x2 | f64x2);
800790

801791
// Floating point to integer with saturation
802792
impl_conversion!(trunc_s_f32x4_sat["i32x4.trunc_s/f32x4:sat"]: f32x4 => v32x4 | i32x4);

crates/wasm-test/.cargo/config

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[target.wasm32-unknown-unknown]
2+
runner = 'wasm-bindgen-test-runner'

crates/wasm-test/Cargo.toml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "wasm-test"
3+
version = "0.1.0"
4+
authors = ["gnzlbg <[email protected]>"]
5+
6+
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
7+
wasm-bindgen-test = { git = 'https://github.com/rustwasm/wasm-bindgen' }
8+
coresimd = { path = "../coresimd" }
9+
10+
[patch.crates-io]
11+
wasm-bindgen = { git = 'https://github.com/rustwasm/wasm-bindgen' }

crates/wasm-test/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#![no_std]

0 commit comments

Comments
 (0)