about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbjorn3 <17426603+bjorn3@users.noreply.github.com>2022-09-05 16:13:36 +0000
committerbjorn3 <17426603+bjorn3@users.noreply.github.com>2022-09-05 16:13:36 +0000
commit782b5fe7ac97554f7bf4b9121e985871e650ca41 (patch)
tree3cb76f3866073280704fa2b6fda5adcb36b190d4
parent0980596271fd99665921052c8f666f7fb718a3cc (diff)
downloadrust-782b5fe7ac97554f7bf4b9121e985871e650ca41.tar.gz
rust-782b5fe7ac97554f7bf4b9121e985871e650ca41.zip
Implement simd_saturating_{add,sub}
-rw-r--r--patches/0001-portable-simd-Disable-unsupported-tests.patch104
-rw-r--r--src/intrinsics/mod.rs24
-rw-r--r--src/intrinsics/simd.rs17
3 files changed, 39 insertions, 106 deletions
diff --git a/patches/0001-portable-simd-Disable-unsupported-tests.patch b/patches/0001-portable-simd-Disable-unsupported-tests.patch
index c75d5dda5ca..e23dea97694 100644
--- a/patches/0001-portable-simd-Disable-unsupported-tests.patch
+++ b/patches/0001-portable-simd-Disable-unsupported-tests.patch
@@ -11,110 +11,6 @@ Subject: [PATCH] Disable unsupported tests
  crates/core_simd/tests/masks.rs          | 3 ---
  5 files changed, 20 insertions(+), 3 deletions(-)
 
-diff --git a/crates/core_simd/src/elements/int.rs b/crates/core_simd/src/elements/int.rs
-index 9b8c37e..ea95f08 100644
---- a/crates/core_simd/src/elements/int.rs
-+++ b/crates/core_simd/src/elements/int.rs
-@@ -11,6 +11,7 @@ pub trait SimdInt: Copy + Sealed {
-     /// Scalar type contained by this SIMD vector type.
-     type Scalar;
- 
-+    /*
-     /// Lanewise saturating add.
-     ///
-     /// # Examples
-@@ -45,6 +46,7 @@ pub trait SimdInt: Copy + Sealed {
-     /// assert_eq!(unsat, Simd::from_array([1, MAX, MIN, 0]));
-     /// assert_eq!(sat, Simd::from_array([MIN, MIN, MIN, 0]));
-     fn saturating_sub(self, second: Self) -> Self;
-+    */
- 
-     /// Lanewise absolute value, implemented in Rust.
-     /// Every lane becomes its absolute value.
-@@ -61,6 +63,7 @@ pub trait SimdInt: Copy + Sealed {
-     /// ```
-     fn abs(self) -> Self;
- 
-+    /*
-     /// Lanewise saturating absolute value, implemented in Rust.
-     /// As abs(), except the MIN value becomes MAX instead of itself.
-     ///
-@@ -96,6 +99,7 @@ pub trait SimdInt: Copy + Sealed {
-     /// assert_eq!(sat, Simd::from_array([MAX, 2, -3, MIN + 1]));
-     /// ```
-     fn saturating_neg(self) -> Self;
-+    */
- 
-     /// Returns true for each positive lane and false if it is zero or negative.
-     fn is_positive(self) -> Self::Mask;
-@@ -199,6 +203,7 @@ macro_rules! impl_trait {
-             type Mask = Mask<<$ty as SimdElement>::Mask, LANES>;
-             type Scalar = $ty;
- 
-+            /*
-             #[inline]
-             fn saturating_add(self, second: Self) -> Self {
-                 // Safety: `self` is a vector
-@@ -210,6 +215,7 @@ macro_rules! impl_trait {
-                 // Safety: `self` is a vector
-                 unsafe { intrinsics::simd_saturating_sub(self, second) }
-             }
-+            */
- 
-             #[inline]
-             fn abs(self) -> Self {
-@@ -218,6 +224,7 @@ macro_rules! impl_trait {
-                 (self^m) - m
-             }
- 
-+            /*
-             #[inline]
-             fn saturating_abs(self) -> Self {
-                 // arith shift for -1 or 0 mask based on sign bit, giving 2s complement
-@@ -230,6 +237,7 @@ macro_rules! impl_trait {
-             fn saturating_neg(self) -> Self {
-                 Self::splat(0).saturating_sub(self)
-             }
-+            */
- 
-             #[inline]
-             fn is_positive(self) -> Self::Mask {
-diff --git a/crates/core_simd/src/elements/uint.rs b/crates/core_simd/src/elements/uint.rs
-index 21e7e76..0d6dee2 100644
---- a/crates/core_simd/src/elements/uint.rs
-+++ b/crates/core_simd/src/elements/uint.rs
-@@ -6,6 +6,7 @@ pub trait SimdUint: Copy + Sealed {
-     /// Scalar type contained by this SIMD vector type.
-     type Scalar;
- 
-+    /*
-     /// Lanewise saturating add.
-     ///
-     /// # Examples
-@@ -40,6 +41,7 @@ pub trait SimdUint: Copy + Sealed {
-     /// assert_eq!(unsat, Simd::from_array([3, 2, 1, 0]));
-     /// assert_eq!(sat, Simd::splat(0));
-     fn saturating_sub(self, second: Self) -> Self;
-+    */
- 
-     /// Returns the sum of the lanes of the vector, with wrapping addition.
-     fn reduce_sum(self) -> Self::Scalar;
-@@ -78,6 +80,7 @@ macro_rules! impl_trait {
-         {
-             type Scalar = $ty;
- 
-+            /*
-             #[inline]
-             fn saturating_add(self, second: Self) -> Self {
-                 // Safety: `self` is a vector
-@@ -89,6 +92,7 @@ macro_rules! impl_trait {
-                 // Safety: `self` is a vector
-                 unsafe { intrinsics::simd_saturating_sub(self, second) }
-             }
-+            */
- 
-             #[inline]
-             fn reduce_sum(self) -> Self::Scalar {
 diff --git a/crates/core_simd/src/masks/full_masks.rs b/crates/core_simd/src/masks/full_masks.rs
 index adf0fcb..e7e657e 100644
 --- a/crates/core_simd/src/masks/full_masks.rs
diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs
index e06166d0ab7..1e47ccbd49f 100644
--- a/src/intrinsics/mod.rs
+++ b/src/intrinsics/mod.rs
@@ -84,6 +84,30 @@ fn simd_for_each_lane<'tcx>(
     }
 }
 
+fn simd_pair_for_each_lane_typed<'tcx>(
+    fx: &mut FunctionCx<'_, '_, 'tcx>,
+    x: CValue<'tcx>,
+    y: CValue<'tcx>,
+    ret: CPlace<'tcx>,
+    f: &dyn Fn(&mut FunctionCx<'_, '_, 'tcx>, CValue<'tcx>, CValue<'tcx>) -> CValue<'tcx>,
+) {
+    assert_eq!(x.layout(), y.layout());
+    let layout = x.layout();
+
+    let (lane_count, _lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
+    let (ret_lane_count, _ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
+    assert_eq!(lane_count, ret_lane_count);
+
+    for lane_idx in 0..lane_count {
+        let x_lane = x.value_lane(fx, lane_idx);
+        let y_lane = y.value_lane(fx, lane_idx);
+
+        let res_lane = f(fx, x_lane, y_lane);
+
+        ret.place_lane(fx, lane_idx).write_cvalue(fx, res_lane);
+    }
+}
+
 fn simd_pair_for_each_lane<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     x: CValue<'tcx>,
diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs
index 4d77370dfc5..a70ced7472f 100644
--- a/src/intrinsics/simd.rs
+++ b/src/intrinsics/simd.rs
@@ -730,9 +730,22 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
             ret.write_cvalue(fx, res);
         }
 
+        sym::simd_saturating_add | sym::simd_saturating_sub => {
+            intrinsic_args!(fx, args => (x, y); intrinsic);
+
+            let bin_op = match intrinsic {
+                sym::simd_saturating_add => BinOp::Add,
+                sym::simd_saturating_sub => BinOp::Sub,
+                _ => unreachable!(),
+            };
+
+            // FIXME use vector instructions when possible
+            simd_pair_for_each_lane_typed(fx, x, y, ret, &|fx, x_lane, y_lane| {
+                crate::num::codegen_saturating_int_binop(fx, bin_op, x_lane, y_lane)
+            });
+        }
+
         // simd_arith_offset
-        // simd_saturating_add
-        // simd_saturating_sub
         // simd_scatter
         // simd_gather
         // simd_select_bitmask