diff options
author | Arthur Cohen <arthur.cohen@embecosm.com> | 2022-10-05 17:49:44 +0200 |
---|---|---|
committer | Arthur Cohen <arthur.cohen@embecosm.com> | 2023-02-21 12:36:32 +0100 |
commit | ab6d8ad3f5957c88208cac2b397ac070d341db1a (patch) | |
tree | 54b27aac7123a5bbdf720adae76580ad497c8f58 | |
parent | 0a762d20498044794b29662a2e2b7927710c958b (diff) | |
download | gcc-ab6d8ad3f5957c88208cac2b397ac070d341db1a.zip gcc-ab6d8ad3f5957c88208cac2b397ac070d341db1a.tar.gz gcc-ab6d8ad3f5957c88208cac2b397ac070d341db1a.tar.bz2 |
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.
-rw-r--r-- | gcc/rust/backend/rust-builtins.cc | 6 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-intrinsic.cc | 97 | ||||
-rw-r--r-- | gcc/testsuite/rust/execute/torture/prefetch_data.rs | 17 |
3 files changed, 111 insertions, 9 deletions
diff --git a/gcc/rust/backend/rust-builtins.cc b/gcc/rust/backend/rust-builtins.cc index 14dc037..d6f8cb6 100644 --- a/gcc/rust/backend/rust-builtins.cc +++ b/gcc/rust/backend/rust-builtins.cc @@ -92,6 +92,12 @@ BuiltinsContext::setup () build_pointer_type (void_type_node), size_type_node, NULL_TREE), 0); + + define_builtin ("prefetch", BUILT_IN_PREFETCH, "__builtin_prefetch", + "prefetch", + build_varargs_function_type_list ( + build_pointer_type (const_ptr_type_node), NULL_TREE), + builtin_const); } static void 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<std::string, std::function<tree (Context *, TyTy::FnType *)>> - 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<Bvariable *> 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 diff --git a/gcc/testsuite/rust/execute/torture/prefetch_data.rs b/gcc/testsuite/rust/execute/torture/prefetch_data.rs new file mode 100644 index 0000000..dc049b1 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/prefetch_data.rs @@ -0,0 +1,17 @@ +#![feature(intrinsics)] + +extern "rust-intrinsic" { + fn prefetch_read_data<T>(addr: *const T, locality: i32); + fn prefetch_write_data<T>(addr: *const T, locality: i32); +} + +fn main() -> i32 { + let a = [1, 2, 3, 4]; + + unsafe { + prefetch_read_data(&a, 3); + prefetch_write_data(&a[0], 3); + } + + 0 +} |