From ab6d8ad3f5957c88208cac2b397ac070d341db1a Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 5 Oct 2022 17:49:44 +0200 Subject: gccrs: intrinsics: Add data prefetching intrinsics gcc/rust/ChangeLog: * backend/rust-builtins.cc (BuiltinsContext::setup): Declare prefetch intrinsics. * backend/rust-compile-intrinsic.cc (enum class Prefetch): Add kinds of prefetch intrinsics. (prefetch_data_handler): New function. (prefetch_read_data): Likewise. (prefetch_write_data): Likewise. gcc/testsuite/ChangeLog: * rust/execute/torture/prefetch_data.rs: New test. --- gcc/rust/backend/rust-compile-intrinsic.cc | 97 +++++++++++++++++++++++++++--- 1 file changed, 88 insertions(+), 9 deletions(-) (limited to 'gcc/rust/backend/rust-compile-intrinsic.cc') diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc index 6169196..a418b86 100644 --- a/gcc/rust/backend/rust-compile-intrinsic.cc +++ b/gcc/rust/backend/rust-compile-intrinsic.cc @@ -17,6 +17,7 @@ #include "rust-compile-intrinsic.h" #include "rust-compile-context.h" #include "rust-compile-type.h" +#include "rust-compile-expr.h" #include "rust-compile-fnparam.h" #include "rust-builtins.h" #include "rust-diagnostics.h" @@ -28,6 +29,8 @@ #include "fold-const.h" #include "langhooks.h" +#include "print-tree.h" + namespace Rust { namespace Compile { @@ -44,6 +47,15 @@ wrapping_op_handler (Context *ctx, TyTy::FnType *fntype, tree_code op); static tree copy_nonoverlapping_handler (Context *ctx, TyTy::FnType *fntype); +enum class Prefetch +{ + Read, + Write +}; + +static tree +prefetch_data_handler (Context *ctx, TyTy::FnType *fntype, Prefetch kind); + static inline tree rotate_left_handler (Context *ctx, TyTy::FnType *fntype) { @@ -70,18 +82,32 @@ wrapping_mul_handler (Context *ctx, TyTy::FnType *fntype) { return wrapping_op_handler (ctx, fntype, MULT_EXPR); } +static inline tree +prefetch_read_data (Context *ctx, TyTy::FnType *fntype) +{ + return prefetch_data_handler (ctx, fntype, Prefetch::Read); +} +static inline tree +prefetch_write_data (Context *ctx, TyTy::FnType *fntype) +{ + return prefetch_data_handler (ctx, fntype, Prefetch::Write); +} static const std::map> - generic_intrinsics = {{"offset", &offset_handler}, - {"size_of", &sizeof_handler}, - {"transmute", &transmute_handler}, - {"rotate_left", &rotate_left_handler}, - {"rotate_right", &rotate_right_handler}, - {"wrapping_add", &wrapping_add_handler}, - {"wrapping_sub", &wrapping_sub_handler}, - {"wrapping_mul", &wrapping_mul_handler}, - {"copy_nonoverlapping", ©_nonoverlapping_handler}}; + generic_intrinsics = { + {"offset", &offset_handler}, + {"size_of", &sizeof_handler}, + {"transmute", &transmute_handler}, + {"rotate_left", &rotate_left_handler}, + {"rotate_right", &rotate_right_handler}, + {"wrapping_add", &wrapping_add_handler}, + {"wrapping_sub", &wrapping_sub_handler}, + {"wrapping_mul", &wrapping_mul_handler}, + {"copy_nonoverlapping", ©_nonoverlapping_handler}, + {"prefetch_read_data", &prefetch_read_data}, + {"prefetch_write_data", &prefetch_write_data}, +}; Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {} @@ -515,5 +541,58 @@ copy_nonoverlapping_handler (Context *ctx, TyTy::FnType *fntype) return fndecl; } +static tree +prefetch_data_handler (Context *ctx, TyTy::FnType *fntype, Prefetch kind) +{ + rust_assert (fntype->get_params ().size () == 2); + + tree lookup = NULL_TREE; + if (check_for_cached_intrinsic (ctx, fntype, &lookup)) + return lookup; + + auto fndecl = compile_intrinsic_function (ctx, fntype); + + // prefetching isn't pure and shouldn't be discarded after GIMPLE + TREE_READONLY (fndecl) = 0; + TREE_SIDE_EFFECTS (fndecl) = 1; + + std::vector args; + compile_fn_params (ctx, fntype, fndecl, &args); + + if (!ctx->get_backend ()->function_set_parameters (fndecl, args)) + return error_mark_node; + + enter_intrinsic_block (ctx, fndecl); + + auto addr = ctx->get_backend ()->var_expression (args[0], Location ()); + auto locality = ctx->get_backend ()->var_expression (args[1], Location ()); + + mpz_t zero; + mpz_t one; + mpz_init_set_ui (zero, 0); + mpz_init_set_ui (one, 1); + + auto rw_flag_value = kind == Prefetch::Write ? one : zero; + auto rw_flag + = ctx->get_backend ()->integer_constant_expression (integer_type_node, + rw_flag_value); + auto prefetch_raw = NULL_TREE; + auto ok + = BuiltinsContext::get ().lookup_simple_builtin ("prefetch", &prefetch_raw); + rust_assert (ok); + auto prefetch + = build_fold_addr_expr_loc (Location ().gcc_location (), prefetch_raw); + + auto prefetch_call + = ctx->get_backend ()->call_expression (prefetch, {addr, rw_flag, locality}, + nullptr, Location ()); + + ctx->add_statement (prefetch_call); + + finalize_intrinsic_block (ctx, fndecl); + + return fndecl; +} + } // namespace Compile } // namespace Rust -- cgit v1.1