about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbendn <bend.n@outlook.com>2024-05-11 08:41:04 +0700
committerbendn <bend.n@outlook.com>2024-05-11 17:13:20 +0700
commite928185f6e4912891748da963b5d5fdfd44dfdf0 (patch)
tree3a6373c443f35d0f452def165117047429b23933 /src
parent6f4c7d997e55d9b7786c59823653d03464f8148d (diff)
downloadrust-e928185f6e4912891748da963b5d5fdfd44dfdf0.tar.gz
rust-e928185f6e4912891748da963b5d5fdfd44dfdf0.zip
support `f*_algebraic`
Diffstat (limited to 'src')
-rw-r--r--src/tools/miri/src/intrinsics/mod.rs22
-rw-r--r--src/tools/miri/tests/pass/intrinsics/float_algebraic_math.rs32
2 files changed, 54 insertions, 0 deletions
diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs
index effd7f6d543..e38a9e4d5e0 100644
--- a/src/tools/miri/src/intrinsics/mod.rs
+++ b/src/tools/miri/src/intrinsics/mod.rs
@@ -256,6 +256,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let res = this.adjust_nan(res, &[f]);
                 this.write_scalar(res, dest)?;
             }
+            #[rustfmt::skip]
+            | "fadd_algebraic"
+            | "fsub_algebraic"
+            | "fmul_algebraic"
+            | "fdiv_algebraic"
+            | "frem_algebraic"
+            => {
+                let [a, b] = check_arg_count(args)?;
+                let a = this.read_immediate(a)?;
+                let b = this.read_immediate(b)?;
+                let op = match intrinsic_name {
+                    "fadd_algebraic" => mir::BinOp::Add,
+                    "fsub_algebraic" => mir::BinOp::Sub,
+                    "fmul_algebraic" => mir::BinOp::Mul,
+                    "fdiv_algebraic" => mir::BinOp::Div,
+                    "frem_algebraic" => mir::BinOp::Rem,
+                    _ => bug!(),
+                };
+                let res = this.wrapping_binary_op(op, &a, &b)?;
+                // `wrapping_binary_op` already called `generate_nan` if necessary.
+                this.write_immediate(*res, dest)?;
+            }
 
             #[rustfmt::skip]
             | "fadd_fast"
diff --git a/src/tools/miri/tests/pass/intrinsics/float_algebraic_math.rs b/src/tools/miri/tests/pass/intrinsics/float_algebraic_math.rs
new file mode 100644
index 00000000000..f6f083f7b5f
--- /dev/null
+++ b/src/tools/miri/tests/pass/intrinsics/float_algebraic_math.rs
@@ -0,0 +1,32 @@
+#![feature(core_intrinsics)]
+
+use std::intrinsics::{
+    fadd_algebraic, fdiv_algebraic, fmul_algebraic, frem_algebraic, fsub_algebraic,
+};
+
+#[inline(never)]
+pub fn test_operations_f64(a: f64, b: f64) {
+    // make sure they all map to the correct operation
+    assert_eq!(fadd_algebraic(a, b), a + b);
+    assert_eq!(fsub_algebraic(a, b), a - b);
+    assert_eq!(fmul_algebraic(a, b), a * b);
+    assert_eq!(fdiv_algebraic(a, b), a / b);
+    assert_eq!(frem_algebraic(a, b), a % b);
+}
+
+#[inline(never)]
+pub fn test_operations_f32(a: f32, b: f32) {
+    // make sure they all map to the correct operation
+    assert_eq!(fadd_algebraic(a, b), a + b);
+    assert_eq!(fsub_algebraic(a, b), a - b);
+    assert_eq!(fmul_algebraic(a, b), a * b);
+    assert_eq!(fdiv_algebraic(a, b), a / b);
+    assert_eq!(frem_algebraic(a, b), a % b);
+}
+
+fn main() {
+    test_operations_f64(1., 2.);
+    test_operations_f64(10., 5.);
+    test_operations_f32(11., 2.);
+    test_operations_f32(10., 15.);
+}