about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2021-04-07 11:05:34 -0500
committerGitHub <noreply@github.com>2021-04-07 17:05:34 +0100
commitc6356546c0503ad66dcb0c6722be3d9ed2788af4 (patch)
treee8ad27103aa875e26e9ee8e01bc6ed98b246c538
parent7bab2c06958fc21081e6a4e1a4e1a9d4bc35f701 (diff)
downloadrust-c6356546c0503ad66dcb0c6722be3d9ed2788af4.tar.gz
rust-c6356546c0503ad66dcb0c6722be3d9ed2788af4.zip
Updates for wasm simd support (#1110)
* Uncomment some i64-related instruction assertions now that LLVM
  supports the opcodes.
* Fix the codegen for `{i,u}32x4_trunc_sat_f32x4`. This was originally
  introduced using `simd_cast` but that inherits LLVM's UB related to
  float-to-integer casts out of bounds. Since the original inception of
  these intrinsics in LLVM dedicated intrinsics for the wasm
  instructions have been added, so this swithces the implementation to
  using those.
* Uncomment `f64x2_convert_low_i32x4` instruction assertion and add a
  test now that this is implemented in Wasmtime.
-rw-r--r--library/stdarch/ci/docker/wasm32-wasi/Dockerfile16
-rw-r--r--library/stdarch/crates/core_arch/src/wasm32/simd128.rs30
2 files changed, 24 insertions, 22 deletions
diff --git a/library/stdarch/ci/docker/wasm32-wasi/Dockerfile b/library/stdarch/ci/docker/wasm32-wasi/Dockerfile
index f8e090f1c81..eceebb9ee13 100644
--- a/library/stdarch/ci/docker/wasm32-wasi/Dockerfile
+++ b/library/stdarch/ci/docker/wasm32-wasi/Dockerfile
@@ -1,22 +1,14 @@
-FROM rust:1.50.0
-
-# Install wasmtime from source for now while the `experimental_x64` feature is
-# not yet the default. (it's not actually that experimental at the time of this
-# writing, wasmtime should switch defaults soon and the backend this enables has
-# better support for simd instructions)
-RUN \
-  CARGO_INCREMENTAL=0 \
-  CARGO_PROFILE_DEV_DEBUGINFO=0 \
-  cargo install wasmtime-cli --features experimental_x64 --debug --vers 0.25.0 --locked
-
 FROM ubuntu:20.04
 
 ENV DEBIAN_FRONTEND=noninteractive
 RUN apt-get update -y && apt-get install -y --no-install-recommends \
   ca-certificates \
+  curl \
+  xz-utils \
   clang
 
-COPY --from=0 /usr/local/cargo/bin/wasmtime /usr/local/bin/wasmtime
+RUN curl -L https://github.com/bytecodealliance/wasmtime/releases/download/v0.26.0/wasmtime-v0.26.0-x86_64-linux.tar.xz | tar xJf -
+ENV PATH=$PATH:/wasmtime-v0.26.0-x86_64-linux
 
 ENV CARGO_TARGET_WASM32_WASI_RUNNER="wasmtime \
   --enable-simd \
diff --git a/library/stdarch/crates/core_arch/src/wasm32/simd128.rs b/library/stdarch/crates/core_arch/src/wasm32/simd128.rs
index 2507c28a799..13812fb4fca 100644
--- a/library/stdarch/crates/core_arch/src/wasm32/simd128.rs
+++ b/library/stdarch/crates/core_arch/src/wasm32/simd128.rs
@@ -271,6 +271,10 @@ extern "C" {
     #[link_name = "llvm.wasm.pmax.v2f64"]
     fn llvm_f64x2_pmax(x: simd::f64x2, y: simd::f64x2) -> simd::f64x2;
 
+    #[link_name = "llvm.wasm.trunc.saturate.signed.v4i32.v4f32"]
+    fn llvm_i32x4_trunc_sat_f32x4_s(x: simd::f32x4) -> simd::i32x4;
+    #[link_name = "llvm.wasm.trunc.saturate.unsigned.v4i32.v4f32"]
+    fn llvm_i32x4_trunc_sat_f32x4_u(x: simd::f32x4) -> simd::i32x4;
     #[link_name = "llvm.wasm.convert.low.signed"]
     fn llvm_f64x2_convert_low_i32x4_s(x: simd::i32x4) -> simd::f64x2;
     #[link_name = "llvm.wasm.convert.low.unsigned"]
@@ -1564,7 +1568,7 @@ pub unsafe fn u32x4_ge(a: v128, b: v128) -> v128 {
 /// Returns a new vector where each lane is all ones if the pairwise elements
 /// were equal, or all zeros if the elements were not equal.
 #[inline]
-// #[cfg_attr(test, assert_instr(i64x2.eq))] // FIXME llvm
+#[cfg_attr(test, assert_instr(i64x2.eq))]
 #[target_feature(enable = "simd128")]
 pub unsafe fn i64x2_eq(a: v128, b: v128) -> v128 {
     transmute(simd_eq::<_, simd::i64x2>(a.as_i64x2(), b.as_i64x2()))
@@ -1576,7 +1580,7 @@ pub unsafe fn i64x2_eq(a: v128, b: v128) -> v128 {
 /// Returns a new vector where each lane is all ones if the pairwise elements
 /// were not equal, or all zeros if the elements were equal.
 #[inline]
-// #[cfg_attr(test, assert_instr(i64x2.ne))] // FIXME llvm
+#[cfg_attr(test, assert_instr(i64x2.ne))]
 #[target_feature(enable = "simd128")]
 pub unsafe fn i64x2_ne(a: v128, b: v128) -> v128 {
     transmute(simd_ne::<_, simd::i64x2>(a.as_i64x2(), b.as_i64x2()))
@@ -1588,7 +1592,7 @@ pub unsafe fn i64x2_ne(a: v128, b: v128) -> v128 {
 /// Returns a new vector where each lane is all ones if the pairwise left
 /// element is less than the pairwise right element, or all zeros otherwise.
 #[inline]
-// #[cfg_attr(test, assert_instr(i64x2.lt_s))] // FIXME llvm
+#[cfg_attr(test, assert_instr(i64x2.lt_s))]
 #[target_feature(enable = "simd128")]
 pub unsafe fn i64x2_lt(a: v128, b: v128) -> v128 {
     transmute(simd_lt::<_, simd::i64x2>(a.as_i64x2(), b.as_i64x2()))
@@ -1600,7 +1604,7 @@ pub unsafe fn i64x2_lt(a: v128, b: v128) -> v128 {
 /// Returns a new vector where each lane is all ones if the pairwise left
 /// element is greater than the pairwise right element, or all zeros otherwise.
 #[inline]
-// #[cfg_attr(test, assert_instr(i64x2.gt_s))] // FIXME llvm
+#[cfg_attr(test, assert_instr(i64x2.gt_s))]
 #[target_feature(enable = "simd128")]
 pub unsafe fn i64x2_gt(a: v128, b: v128) -> v128 {
     transmute(simd_gt::<_, simd::i64x2>(a.as_i64x2(), b.as_i64x2()))
@@ -1612,7 +1616,7 @@ pub unsafe fn i64x2_gt(a: v128, b: v128) -> v128 {
 /// Returns a new vector where each lane is all ones if the pairwise left
 /// element is less than the pairwise right element, or all zeros otherwise.
 #[inline]
-// #[cfg_attr(test, assert_instr(i64x2.le_s))] // FIXME llvm
+#[cfg_attr(test, assert_instr(i64x2.le_s))]
 #[target_feature(enable = "simd128")]
 pub unsafe fn i64x2_le(a: v128, b: v128) -> v128 {
     transmute(simd_le::<_, simd::i64x2>(a.as_i64x2(), b.as_i64x2()))
@@ -1624,7 +1628,7 @@ pub unsafe fn i64x2_le(a: v128, b: v128) -> v128 {
 /// Returns a new vector where each lane is all ones if the pairwise left
 /// element is greater than the pairwise right element, or all zeros otherwise.
 #[inline]
-// #[cfg_attr(test, assert_instr(i64x2.ge_s))] // FIXME llvm
+#[cfg_attr(test, assert_instr(i64x2.ge_s))]
 #[target_feature(enable = "simd128")]
 pub unsafe fn i64x2_ge(a: v128, b: v128) -> v128 {
     transmute(simd_ge::<_, simd::i64x2>(a.as_i64x2(), b.as_i64x2()))
@@ -1862,7 +1866,7 @@ pub unsafe fn i8x16_neg(a: v128) -> v128 {
 
 /// Count the number of bits set to one within each lane.
 #[inline]
-// #[cfg_attr(test, assert_instr(i8x16.popcnt))] // FIXME llvm & wasmtime
+// #[cfg_attr(test, assert_instr(i8x16.popcnt))] // FIXME wasmtime
 #[target_feature(enable = "simd128")]
 pub unsafe fn i8x16_popcnt(v: v128) -> v128 {
     transmute(llvm_popcnt(v.as_i8x16()))
@@ -3088,7 +3092,7 @@ pub unsafe fn f64x2_pmax(a: v128, b: v128) -> v128 {
 #[cfg_attr(test, assert_instr(i32x4.trunc_sat_f32x4_s))]
 #[target_feature(enable = "simd128")]
 pub unsafe fn i32x4_trunc_sat_f32x4(a: v128) -> v128 {
-    transmute(simd_cast::<_, simd::i32x4>(a.as_f32x4()))
+    transmute(llvm_i32x4_trunc_sat_f32x4_s(a.as_f32x4()))
 }
 
 /// Converts a 128-bit vector interpreted as four 32-bit floating point numbers
@@ -3100,7 +3104,7 @@ pub unsafe fn i32x4_trunc_sat_f32x4(a: v128) -> v128 {
 #[cfg_attr(test, assert_instr(i32x4.trunc_sat_f32x4_u))]
 #[target_feature(enable = "simd128")]
 pub unsafe fn u32x4_trunc_sat_f32x4(a: v128) -> v128 {
-    transmute(simd_cast::<_, simd::u32x4>(a.as_f32x4()))
+    transmute(llvm_i32x4_trunc_sat_f32x4_u(a.as_f32x4()))
 }
 
 /// Converts a 128-bit vector interpreted as four 32-bit signed integers into a
@@ -3153,7 +3157,7 @@ pub unsafe fn u32x4_trunc_sat_f64x2_zero(a: v128) -> v128 {
 
 /// Lane-wise conversion from integer to floating point.
 #[inline]
-// #[cfg_attr(test, assert_instr(f64x2.convert_low_i32x4_s))] // FIXME wasmtime
+#[cfg_attr(test, assert_instr(f64x2.convert_low_i32x4_s))]
 #[target_feature(enable = "simd128")]
 pub unsafe fn f64x2_convert_low_i32x4(a: v128) -> v128 {
     transmute(llvm_f64x2_convert_low_i32x4_s(a.as_i32x4()))
@@ -3193,6 +3197,7 @@ pub mod tests {
     use super::*;
     use core::ops::{Add, Div, Mul, Neg, Sub};
     use std;
+    use std::fmt::Debug;
     use std::mem;
     use std::num::Wrapping;
     use std::prelude::v1::*;
@@ -4722,6 +4727,11 @@ pub mod tests {
                 u32x4_trunc_sat_f32x4(f32x4(1., f32::NEG_INFINITY, f32::INFINITY, f32::NAN)),
                 u32x4(1, 0, u32::MAX, 0),
             );
+            compare_bytes(f64x2_convert_low_i32x4(i32x4(1, 2, 3, 4)), f64x2(1., 2.));
+            compare_bytes(
+                f64x2_convert_low_i32x4(i32x4(i32::MIN, i32::MAX, 3, 4)),
+                f64x2(f64::from(i32::MIN), f64::from(i32::MAX)),
+            );
         }
     }
 }