]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: rust-builtins: add likely and unlikey intrinsics
authorliushuyu <liushuyu011@gmail.com>
Thu, 1 Jun 2023 04:08:02 +0000 (22:08 -0600)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 16 Jan 2024 18:04:36 +0000 (19:04 +0100)
gcc/rust/ChangeLog:
* backend/rust-builtins.cc: add `expect` builtin definition.
* backend/rust-compile-intrinsic.cc: add `likely` and `unlikely`
intrinsics handler.

Signed-off-by: Zixing Liu <liushuyu011@gmail.com>
gcc/rust/backend/rust-builtins.cc
gcc/rust/backend/rust-compile-intrinsic.cc

index c96553b8c5951f809cb0ddb8a9e174651eb3aae8..cd06379fcb00c1552eb81171f19376bd3ec393f1 100644 (file)
@@ -242,6 +242,12 @@ BuiltinsContext::setup ()
                  build_function_type (void_type_node, void_list_node),
                  builtin_const | builtin_noreturn);
 
+  define_builtin ("expect", BUILT_IN_EXPECT, "__builtin_expect", "expect",
+                 build_function_type_list (long_integer_type_node,
+                                           long_integer_type_node,
+                                           long_integer_type_node, NULL_TREE),
+                 builtin_const);
+
   define_builtin ("memcpy", BUILT_IN_MEMCPY, "__builtin_memcpy", "memcpy",
                  build_function_type_list (build_pointer_type (void_type_node),
                                            build_pointer_type (void_type_node),
index 243aab7dcb401802f659b329bbc375320fffb578..33ec9128cc93c3fcbafa40cfcdcea003c1b91462 100644 (file)
@@ -165,6 +165,17 @@ unchecked_op_handler (tree_code op)
   };
 }
 
+static inline tree
+expect_handler_inner (Context *ctx, TyTy::FnType *fntype, bool likely);
+
+const static std::function<tree (Context *, TyTy::FnType *)>
+expect_handler (bool likely)
+{
+  return [likely] (Context *ctx, TyTy::FnType *fntype) {
+    return expect_handler_inner (ctx, fntype, likely);
+  };
+}
+
 inline tree
 sorry_handler (Context *ctx, TyTy::FnType *fntype)
 {
@@ -208,6 +219,8 @@ static const std::map<std::string,
     {"unchecked_shr", unchecked_op_handler (RSHIFT_EXPR)},
     {"uninit", uninit_handler},
     {"move_val_init", move_val_init_handler},
+    {"likely", expect_handler (true)},
+    {"unlikely", expect_handler (false)},
 };
 
 Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {}
@@ -1104,5 +1117,49 @@ move_val_init_handler (Context *ctx, TyTy::FnType *fntype)
   return fndecl;
 }
 
+static inline tree
+expect_handler_inner (Context *ctx, TyTy::FnType *fntype, bool likely)
+{
+  rust_assert (fntype->get_params ().size () == 1);
+
+  tree lookup = NULL_TREE;
+  if (check_for_cached_intrinsic (ctx, fntype, &lookup))
+    return lookup;
+
+  auto fndecl = compile_intrinsic_function (ctx, fntype);
+
+  enter_intrinsic_block (ctx, fndecl);
+
+  // BUILTIN expect_handler_inner FN BODY BEGIN
+  // setup the params
+  std::vector<Bvariable *> param_vars;
+  compile_fn_params (ctx, fntype, fndecl, &param_vars);
+  tree expr = Backend::var_expression (param_vars[0], UNDEF_LOCATION);
+  tree expect_fn_raw = nullptr;
+  BuiltinsContext::get ().lookup_simple_builtin ("expect", &expect_fn_raw);
+  rust_assert (expect_fn_raw);
+  auto expect_fn = build_fold_addr_expr_loc (BUILTINS_LOCATION, expect_fn_raw);
+
+  // we need to convert the expression return type to long to match the expected
+  // parameter type of __builtin_expect
+  auto expect_src = build1 (CONVERT_EXPR, long_integer_type_node, expr);
+  auto expect_value
+    = make_unsigned_long_tree (static_cast<unsigned long> (likely));
+
+  auto expect_call
+    = Backend::call_expression (expect_fn, {expect_src, expect_value}, nullptr,
+                               BUILTINS_LOCATION);
+  // the return value also needs to be casted (to bool)
+  auto expect_call_bool = build1 (CONVERT_EXPR, boolean_type_node, expect_call);
+  auto return_statement
+    = Backend::return_statement (fndecl, expect_call_bool, BUILTINS_LOCATION);
+  ctx->add_statement (return_statement);
+  // BUILTIN expect_handler_inner FN BODY END
+
+  finalize_intrinsic_block (ctx, fndecl);
+
+  return fndecl;
+}
+
 } // namespace Compile
 } // namespace Rust