about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorlcnr/Bastian Kauschke <bastian_kauschke@hotmail.de>2019-06-03 12:59:48 +0200
committerlcnr/Bastian Kauschke <bastian_kauschke@hotmail.de>2019-06-03 12:59:48 +0200
commit4e7319cd3f3b0731416ee14666eb583caac75c97 (patch)
treefca41839aff20311e45c9a9dcdb4e3b6cc8d8305 /src
parentd6266a7666c22b4a64bbc9252e4ad080f5950d01 (diff)
downloadrust-4e7319cd3f3b0731416ee14666eb583caac75c97.tar.gz
rust-4e7319cd3f3b0731416ee14666eb583caac75c97.zip
add unchecked math intrinsics
Diffstat (limited to 'src')
-rw-r--r--src/libcore/intrinsics.rs15
-rw-r--r--src/librustc_codegen_llvm/intrinsic.rs24
-rw-r--r--src/librustc_typeck/check/intrinsic.rs3
3 files changed, 40 insertions, 2 deletions
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 782a7ba4559..31a4e380a3d 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -1240,6 +1240,21 @@ extern "rust-intrinsic" {
     /// y < 0 or y >= N, where N is the width of T in bits.
     pub fn unchecked_shr<T>(x: T, y: T) -> T;
 
+    /// Returns the result of an unchecked addition, resulting in
+    /// undefined behavior when `x + y > T::max_value()` or `x + y < T::min_value()`.
+    #[cfg(not(stage0))]
+    pub fn unchecked_add<T>(x: T, y: T) -> T;
+
+    /// Returns the result of an unchecked substraction, resulting in
+    /// undefined behavior when `x - y > T::max_value()` or `x - y < T::min_value()`.
+    #[cfg(not(stage0))]
+    pub fn unchecked_sub<T>(x: T, y: T) -> T;
+
+    /// Returns the result of an unchecked multiplication, resulting in
+    /// undefined behavior when `x * y > T::max_value()` or `x * y < T::min_value()`.
+    #[cfg(not(stage0))]
+    pub fn unchecked_mul<T>(x: T, y: T) -> T;
+
     /// Performs rotate left.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `rotate_left` method. For example,
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 060c295eb7a..ba93268cb43 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -334,7 +334,8 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
             "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "ctpop" | "bswap" |
             "bitreverse" | "add_with_overflow" | "sub_with_overflow" |
             "mul_with_overflow" | "overflowing_add" | "overflowing_sub" | "overflowing_mul" |
-            "unchecked_div" | "unchecked_rem" | "unchecked_shl" | "unchecked_shr" | "exact_div" |
+            "unchecked_div" | "unchecked_rem" | "unchecked_shl" | "unchecked_shr" |
+            "unchecked_add" | "unchecked_sub" | "unchecked_mul" | "exact_div" |
             "rotate_left" | "rotate_right" | "saturating_add" | "saturating_sub" => {
                 let ty = arg_tys[0];
                 match int_type_width_signed(ty, self) {
@@ -430,6 +431,27 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
                                 } else {
                                     self.lshr(args[0].immediate(), args[1].immediate())
                                 },
+                            "unchecked_add" => {
+                                if signed {
+                                    self.unchecked_sadd(args[0].immediate(), args[1].immediate())
+                                } else {
+                                    self.unchecked_uadd(args[0].immediate(), args[1].immediate())
+                                }
+                            },
+                            "unchecked_sub" => {
+                                if signed {
+                                    self.unchecked_ssub(args[0].immediate(), args[1].immediate())
+                                } else {
+                                    self.unchecked_usub(args[0].immediate(), args[1].immediate())
+                                }
+                            },
+                            "unchecked_mul" => {
+                                if signed {
+                                    self.unchecked_smul(args[0].immediate(), args[1].immediate())
+                                } else {
+                                    self.unchecked_umul(args[0].immediate(), args[1].immediate())
+                                }
+                            },
                             "rotate_left" | "rotate_right" => {
                                 let is_left = name == "rotate_left";
                                 let val = args[0].immediate();
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index c6191e6b579..0b14ff1db59 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -305,7 +305,8 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             "unchecked_shl" | "unchecked_shr" |
             "rotate_left" | "rotate_right" =>
                 (1, vec![param(0), param(0)], param(0)),
-
+            "unchecked_add" | "unchecked_sub" | "unchecked_mul" =>
+                (1, vec![param(0), param(0)], param(0)),
             "overflowing_add" | "overflowing_sub" | "overflowing_mul" =>
                 (1, vec![param(0), param(0)], param(0)),
             "saturating_add" | "saturating_sub" =>