From: Arthur Cohen <[email protected]>

Add an implementation for the aforementioned intrinsics. Note that this is a 
simple
implementation and does not actually implement fast mode for these operations, 
but
instead simply performs the operation. As far as I can tell, it is not possible 
to
turn on fast mode in GCC for just one operation instead of the whole program.

gcc/rust/ChangeLog:

        * backend/rust-compile-intrinsic.cc: Reformat the table and add entries 
for
        f<op>_fast intrinsics.
        * backend/rust-intrinsic-handlers.cc (fop_fast): New handler for 
f<op>_fast
        intrinsics.
        * backend/rust-intrinsic-handlers.h (fop_fast): New declaration.
        * typecheck/rust-hir-type-check-intrinsic.cc: Add typecheck info for 
f<op>_fast
        intrinsics.
        * util/rust-intrinsic-values.h: New intrinsics.

gcc/testsuite/ChangeLog:

        * rust/compile/fop_fast_intrinsics.rs: New test.
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.


Commit on github: 
https://github.com/Rust-GCC/gccrs/commit/7f128423f45f90bd44460ef9f7616b7a4b14138c

The commit has NOT been mentioned in any issue.

The commit has been mentioned in the following pull-request(s):
 - https://github.com/Rust-GCC/gccrs/pull/4944

 gcc/rust/backend/rust-compile-intrinsic.cc    | 120 ++++++++++--------
 gcc/rust/backend/rust-intrinsic-handlers.cc   |  56 ++++++++
 gcc/rust/backend/rust-intrinsic-handlers.h    |   5 +
 .../rust-hir-type-check-intrinsic.cc          |  14 ++
 gcc/rust/util/rust-intrinsic-values.h         |   6 +
 .../rust/compile/fop_fast_intrinsics.rs       |  27 ++++
 6 files changed, 173 insertions(+), 55 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/fop_fast_intrinsics.rs

diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc 
b/gcc/rust/backend/rust-compile-intrinsic.cc
index 872b53e70..c16db442f 100644
--- a/gcc/rust/backend/rust-compile-intrinsic.cc
+++ b/gcc/rust/backend/rust-compile-intrinsic.cc
@@ -28,61 +28,71 @@ namespace Compile {
 using IValue = Values::Intrinsics;
 
 static const std::map<std::string, handlers::HandlerBuilder> generic_intrinsics
-  = {{IValue::OFFSET, handlers::offset},
-     {IValue::ARITH_OFFSET, handlers::arith_offset_handler},
-     {IValue::WRITE_BYTES, handlers::write_bytes_handler},
-     {IValue::ASSERT_ZERO_VALID, handlers::assert_zero_valid_handler},
-     {IValue::SIZE_OF, handlers::sizeof_handler},
-     {IValue::SIZE_OF_VAL, handlers::size_of_val_handler},
-     {IValue::MIN_ALIGN_OF, handlers::min_align_of_handler},
-     {IValue::MIN_ALIGN_OF_VAL, handlers::min_align_of_val_handler},
-     {IValue::TRANSMUTE, handlers::transmute},
-     {IValue::ROTATE_LEFT, handlers::rotate_left},
-     {IValue::ROTATE_RIGHT, handlers::rotate_right},
-     {IValue::WRAPPING_ADD, handlers::wrapping_op (PLUS_EXPR)},
-     {IValue::WRAPPING_SUB, handlers::wrapping_op (MINUS_EXPR)},
-     {IValue::WRAPPING_MUL, handlers::wrapping_op (MULT_EXPR)},
-     {IValue::ADD_WITH_OVERFLOW, handlers::op_with_overflow (PLUS_EXPR)},
-     {IValue::SUB_WITH_OVERFLOW, handlers::op_with_overflow (MINUS_EXPR)},
-     {IValue::MUL_WITH_OVERFLOW, handlers::op_with_overflow (MULT_EXPR)},
-     {IValue::COPY, handlers::copy (true)},
-     {IValue::COPY_NONOVERLAPPING, handlers::copy (false)},
-     {IValue::PREFETCH_READ_DATA, handlers::prefetch_read_data},
-     {IValue::PREFETCH_WRITE_DATA, handlers::prefetch_write_data},
-     {IValue::ATOMIC_STORE, handlers::atomic_store (__ATOMIC_SEQ_CST)},
-     {IValue::ATOMIC_STORE_SEQCST, handlers::atomic_store (__ATOMIC_SEQ_CST)},
-     {IValue::ATOMIC_STORE_REL, handlers::atomic_store (__ATOMIC_RELEASE)},
-     {IValue::ATOMIC_STORE_RELEASE, handlers::atomic_store (__ATOMIC_RELEASE)},
-     {IValue::ATOMIC_STORE_RELAXED, handlers::atomic_store (__ATOMIC_RELAXED)},
-     {IValue::ATOMIC_STORE_UNORDERED,
-      handlers::atomic_store (__ATOMIC_RELAXED)},
-     {IValue::ATOMIC_LOAD, handlers::atomic_load (__ATOMIC_SEQ_CST)},
-     {IValue::ATOMIC_LOAD_SEQCST, handlers::atomic_load (__ATOMIC_SEQ_CST)},
-     {IValue::ATOMIC_LOAD_ACQ, handlers::atomic_load (__ATOMIC_ACQUIRE)},
-     {IValue::ATOMIC_LOAD_ACQUIRE, handlers::atomic_load (__ATOMIC_ACQUIRE)},
-     {IValue::ATOMIC_LOAD_RELAXED, handlers::atomic_load (__ATOMIC_RELAXED)},
-     {IValue::ATOMIC_LOAD_UNORDERED, handlers::atomic_load (__ATOMIC_RELAXED)},
-     {IValue::UNCHECKED_ADD, handlers::unchecked_op (PLUS_EXPR)},
-     {IValue::UNCHECKED_SUB, handlers::unchecked_op (MINUS_EXPR)},
-     {IValue::UNCHECKED_MUL, handlers::unchecked_op (MULT_EXPR)},
-     {IValue::UNCHECKED_DIV, handlers::unchecked_op (TRUNC_DIV_EXPR)},
-     {IValue::UNCHECKED_REM, handlers::unchecked_op (TRUNC_MOD_EXPR)},
-     {IValue::UNCHECKED_SHL, handlers::unchecked_op (LSHIFT_EXPR)},
-     {IValue::UNCHECKED_SHR, handlers::unchecked_op (RSHIFT_EXPR)},
-     {IValue::UNINIT, handlers::uninit},
-     {IValue::MOVE_VAL_INIT, handlers::move_val_init},
-     {IValue::LIKELY, handlers::expect (true)},
-     {IValue::UNLIKELY, handlers::expect (false)},
-     {IValue::ASSUME, handlers::assume},
-     {IValue::TRY, handlers::try_handler (false)},
-     {IValue::CATCH_UNWIND, handlers::try_handler (true)},
-     {IValue::DISCRIMINANT_VALUE, handlers::discriminant_value},
-     {IValue::VARIANT_COUNT, handlers::variant_count},
-     {IValue::BSWAP, handlers::bswap_handler},
-     {IValue::CTLZ, handlers::ctlz_handler},
-     {IValue::CTLZ_NONZERO, handlers::ctlz_nonzero_handler},
-     {IValue::CTTZ, handlers::cttz_handler},
-     {IValue::CTTZ_NONZERO, handlers::cttz_nonzero_handler}};
+  = {
+    {IValue::OFFSET, handlers::offset},
+    {IValue::ARITH_OFFSET, handlers::arith_offset_handler},
+    {IValue::WRITE_BYTES, handlers::write_bytes_handler},
+    {IValue::ASSERT_ZERO_VALID, handlers::assert_zero_valid_handler},
+    {IValue::SIZE_OF, handlers::sizeof_handler},
+    {IValue::SIZE_OF_VAL, handlers::size_of_val_handler},
+    {IValue::MIN_ALIGN_OF, handlers::min_align_of_handler},
+    {IValue::MIN_ALIGN_OF_VAL, handlers::min_align_of_val_handler},
+    {IValue::TRANSMUTE, handlers::transmute},
+    {IValue::ROTATE_LEFT, handlers::rotate_left},
+    {IValue::ROTATE_RIGHT, handlers::rotate_right},
+    {IValue::WRAPPING_ADD, handlers::wrapping_op (PLUS_EXPR)},
+    {IValue::WRAPPING_SUB, handlers::wrapping_op (MINUS_EXPR)},
+    {IValue::WRAPPING_MUL, handlers::wrapping_op (MULT_EXPR)},
+    {IValue::ADD_WITH_OVERFLOW, handlers::op_with_overflow (PLUS_EXPR)},
+    {IValue::SUB_WITH_OVERFLOW, handlers::op_with_overflow (MINUS_EXPR)},
+    {IValue::MUL_WITH_OVERFLOW, handlers::op_with_overflow (MULT_EXPR)},
+    {IValue::COPY, handlers::copy (true)},
+    {IValue::COPY_NONOVERLAPPING, handlers::copy (false)},
+    {IValue::PREFETCH_READ_DATA, handlers::prefetch_read_data},
+    {IValue::PREFETCH_WRITE_DATA, handlers::prefetch_write_data},
+    {IValue::ATOMIC_STORE, handlers::atomic_store (__ATOMIC_SEQ_CST)},
+    {IValue::ATOMIC_STORE_SEQCST, handlers::atomic_store (__ATOMIC_SEQ_CST)},
+    {IValue::ATOMIC_STORE_REL, handlers::atomic_store (__ATOMIC_RELEASE)},
+    {IValue::ATOMIC_STORE_RELEASE, handlers::atomic_store (__ATOMIC_RELEASE)},
+    {IValue::ATOMIC_STORE_RELAXED, handlers::atomic_store (__ATOMIC_RELAXED)},
+    {IValue::ATOMIC_STORE_UNORDERED, handlers::atomic_store 
(__ATOMIC_RELAXED)},
+    {IValue::ATOMIC_LOAD, handlers::atomic_load (__ATOMIC_SEQ_CST)},
+    {IValue::ATOMIC_LOAD_SEQCST, handlers::atomic_load (__ATOMIC_SEQ_CST)},
+    {IValue::ATOMIC_LOAD_ACQ, handlers::atomic_load (__ATOMIC_ACQUIRE)},
+    {IValue::ATOMIC_LOAD_ACQUIRE, handlers::atomic_load (__ATOMIC_ACQUIRE)},
+    {IValue::ATOMIC_LOAD_RELAXED, handlers::atomic_load (__ATOMIC_RELAXED)},
+    {IValue::ATOMIC_LOAD_UNORDERED, handlers::atomic_load (__ATOMIC_RELAXED)},
+    {IValue::UNCHECKED_ADD, handlers::unchecked_op (PLUS_EXPR)},
+    {IValue::UNCHECKED_SUB, handlers::unchecked_op (MINUS_EXPR)},
+    {IValue::UNCHECKED_MUL, handlers::unchecked_op (MULT_EXPR)},
+    {IValue::UNCHECKED_DIV, handlers::unchecked_op (TRUNC_DIV_EXPR)},
+    {IValue::UNCHECKED_REM, handlers::unchecked_op (TRUNC_MOD_EXPR)},
+    {IValue::UNCHECKED_SHL, handlers::unchecked_op (LSHIFT_EXPR)},
+    {IValue::UNCHECKED_SHR, handlers::unchecked_op (RSHIFT_EXPR)},
+    {IValue::UNINIT, handlers::uninit},
+    {IValue::MOVE_VAL_INIT, handlers::move_val_init},
+    {IValue::LIKELY, handlers::expect (true)},
+    {IValue::UNLIKELY, handlers::expect (false)},
+    {IValue::ASSUME, handlers::assume},
+    {IValue::TRY, handlers::try_handler (false)},
+    {IValue::CATCH_UNWIND, handlers::try_handler (true)},
+    {IValue::DISCRIMINANT_VALUE, handlers::discriminant_value},
+    {IValue::VARIANT_COUNT, handlers::variant_count},
+    {IValue::BSWAP, handlers::bswap_handler},
+    {IValue::CTLZ, handlers::ctlz_handler},
+    {IValue::CTLZ_NONZERO, handlers::ctlz_nonzero_handler},
+    {IValue::CTTZ, handlers::cttz_handler},
+    {IValue::CTTZ_NONZERO, handlers::cttz_nonzero_handler},
+    {IValue::FADD_FAST, handlers::fop_fast (ArithmeticOrLogicalOperator::ADD)},
+    {IValue::FSUB_FAST,
+     handlers::fop_fast (ArithmeticOrLogicalOperator::SUBTRACT)},
+    {IValue::FMUL_FAST,
+     handlers::fop_fast (ArithmeticOrLogicalOperator::MULTIPLY)},
+    {IValue::FDIV_FAST,
+     handlers::fop_fast (ArithmeticOrLogicalOperator::DIVIDE)},
+    {IValue::FREM_FAST,
+     handlers::fop_fast (ArithmeticOrLogicalOperator::MODULUS)},
+};
 
 Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {}
 
diff --git a/gcc/rust/backend/rust-intrinsic-handlers.cc 
b/gcc/rust/backend/rust-intrinsic-handlers.cc
index d68e872af..2d8dad763 100644
--- a/gcc/rust/backend/rust-intrinsic-handlers.cc
+++ b/gcc/rust/backend/rust-intrinsic-handlers.cc
@@ -26,6 +26,7 @@
 #include "rust-constexpr.h"
 #include "rust-session-manager.h"
 #include "rust-tree.h"
+#include "rust-tyty.h"
 #include "tree-core.h"
 #include "rust-gcc.h"
 #include "fold-const.h"
@@ -1036,6 +1037,53 @@ cttz_handler (Context *ctx, TyTy::FnType *fntype, bool 
nonzero)
   return fndecl;
 }
 
+static tree
+fop_fast (Context *ctx, TyTy::FnType *fntype, location_t locus,
+         ArithmeticOrLogicalOperator op)
+{
+  // fast float ops intrinsics have two parameters
+  rust_assert (fntype->get_params ().size () == 2);
+
+  // and one generic parameter
+  rust_assert (fntype->get_num_substitutions () == 1);
+
+  tree lookup = NULL_TREE;
+  if (check_for_cached_intrinsic (ctx, fntype, &lookup))
+    return lookup;
+
+  auto fndecl = compile_intrinsic_function (ctx, fntype);
+
+  // setup the params
+  std::vector<Bvariable *> param_vars;
+  compile_fn_params (ctx, fntype, fndecl, &param_vars);
+
+  auto &lhs_param = param_vars.at (0);
+  auto &rhs_param = param_vars.at (1);
+  rust_assert (param_vars.size () == 2);
+
+  if (!Backend::function_set_parameters (fndecl, param_vars))
+    return error_mark_node;
+
+  enter_intrinsic_block (ctx, fndecl);
+
+  // BUILTIN rotate FN BODY BEGIN
+  tree lhs = Backend::var_expression (lhs_param, UNDEF_LOCATION);
+  tree rhs = Backend::var_expression (rhs_param, UNDEF_LOCATION);
+
+  tree result_expr
+    = Backend::arithmetic_or_logical_expression (op, lhs, rhs, locus);
+
+  auto return_statement
+    = Backend::return_statement (fndecl, result_expr, UNDEF_LOCATION);
+
+  ctx->add_statement (return_statement);
+  // BUILTIN rotate FN BODY END
+
+  finalize_intrinsic_block (ctx, fndecl);
+
+  return fndecl;
+}
+
 } // namespace inner
 
 const HandlerBuilder
@@ -1046,6 +1094,14 @@ op_with_overflow (tree_code op)
   };
 }
 
+HandlerBuilder
+fop_fast (ArithmeticOrLogicalOperator op)
+{
+  return [op] (Context *ctx, TyTy::FnType *fntype, location_t locus) {
+    return inner::fop_fast (ctx, fntype, locus, op);
+  };
+}
+
 tree
 rotate_left (Context *ctx, TyTy::FnType *fntype, location_t)
 {
diff --git a/gcc/rust/backend/rust-intrinsic-handlers.h 
b/gcc/rust/backend/rust-intrinsic-handlers.h
index 712d422e5..6161b7fa2 100644
--- a/gcc/rust/backend/rust-intrinsic-handlers.h
+++ b/gcc/rust/backend/rust-intrinsic-handlers.h
@@ -107,6 +107,11 @@ tree arith_offset_handler (Context *ctx, TyTy::FnType 
*fntype,
 tree assert_zero_valid_handler (Context *ctx, TyTy::FnType *fntype,
                                location_t expr_locus);
 
+/**
+ * For fadd_fast, fsub_fast, fmul_fast, fdiv_fast and frem_fast
+ */
+HandlerBuilder fop_fast (ArithmeticOrLogicalOperator op);
+
 } // namespace handlers
 
 } // namespace Compile
diff --git a/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc 
b/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
index a0a047963..716df7880 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
@@ -313,6 +313,20 @@ const std::unordered_map<std::string, IntrinsicRules>
      {1, {IRT::MutPtrFirstGeneric, IRT::U8, IRT::Usize}, IRT::Unit}},
     // pub fn assert_zero_valid<T>();
     {IValue::ASSERT_ZERO_VALID, {1, {}, IRT::Unit}},
+
+    // pub fn fadd_fast<T>(a: T, b: T) -> T
+    // same for fsub_fast, fmul_fast, fdiv_fast and frem_fast
+    {IValue::FADD_FAST,
+     {1, {IRT::FirstGeneric, IRT::FirstGeneric}, IRT::FirstGeneric}},
+    {IValue::FSUB_FAST,
+     {1, {IRT::FirstGeneric, IRT::FirstGeneric}, IRT::FirstGeneric}},
+    {IValue::FMUL_FAST,
+     {1, {IRT::FirstGeneric, IRT::FirstGeneric}, IRT::FirstGeneric}},
+    {IValue::FDIV_FAST,
+     {1, {IRT::FirstGeneric, IRT::FirstGeneric}, IRT::FirstGeneric}},
+    {IValue::FREM_FAST,
+     {1, {IRT::FirstGeneric, IRT::FirstGeneric}, IRT::FirstGeneric}},
+
 };
 
 IntrinsicCheckResult
diff --git a/gcc/rust/util/rust-intrinsic-values.h 
b/gcc/rust/util/rust-intrinsic-values.h
index 43df60fd5..9223e20ab 100644
--- a/gcc/rust/util/rust-intrinsic-values.h
+++ b/gcc/rust/util/rust-intrinsic-values.h
@@ -175,6 +175,12 @@ public:
   static constexpr auto &ARITH_OFFSET = "arith_offset";
   static constexpr auto &WRITE_BYTES = "write_bytes";
   static constexpr auto &ASSERT_ZERO_VALID = "assert_zero_valid";
+
+  static constexpr auto &FADD_FAST = "fadd_fast";
+  static constexpr auto &FSUB_FAST = "fsub_fast";
+  static constexpr auto &FMUL_FAST = "fmul_fast";
+  static constexpr auto &FDIV_FAST = "fdiv_fast";
+  static constexpr auto &FREM_FAST = "frem_fast";
 };
 } // namespace Values
 } // namespace Rust
diff --git a/gcc/testsuite/rust/compile/fop_fast_intrinsics.rs 
b/gcc/testsuite/rust/compile/fop_fast_intrinsics.rs
new file mode 100644
index 000000000..4d798a6da
--- /dev/null
+++ b/gcc/testsuite/rust/compile/fop_fast_intrinsics.rs
@@ -0,0 +1,27 @@
+#![feature(no_core)]
+#![feature(intrinsics)]
+#![feature(lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+extern "rust-intrinsic" {
+    fn fadd_fast<T>(a: T, b: T) -> T;
+    fn fsub_fast<T>(a: T, b: T) -> T;
+    fn fmul_fast<T>(a: T, b: T) -> T;
+    fn fdiv_fast<T>(a: T, b: T) -> T;
+    fn frem_fast<T>(a: T, b: T) -> T;
+}
+
+fn main() {
+    unsafe {
+        fadd_fast(4.07, 2.9);
+        fsub_fast(4.07, 2.9);
+        fmul_fast(4.07, 2.9);
+        fdiv_fast(4.07, 2.9);
+
+        frem_fast(4.07f32, 2.9f32);
+        frem_fast(4.07f64, 2.9f64);
+    }
+}

base-commit: 47fe33b0af2cfb5dea2a4d173e0c72752d6211bc
-- 
2.55.0

Reply via email to