Skip to content

Commit e623ee3

Browse files
Merge #1565
1565: Implement data prefetch intrinsics r=CohenArthur a=CohenArthur Addresses #658 Needs #1564 so only review the last commit This PR implements the two intrinsics related to data prefetching. I have to say, since these are hints for the backend, I am unsure if the current implementation is right. I believe it should be. Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
2 parents b409601 + 71397ab commit e623ee3

File tree

3 files changed

+111
-9
lines changed

3 files changed

+111
-9
lines changed

gcc/rust/backend/rust-builtins.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ BuiltinsContext::setup ()
9292
build_pointer_type (void_type_node),
9393
size_type_node, NULL_TREE),
9494
0);
95+
96+
define_builtin ("prefetch", BUILT_IN_PREFETCH, "__builtin_prefetch",
97+
"prefetch",
98+
build_varargs_function_type_list (
99+
build_pointer_type (const_ptr_type_node), NULL_TREE),
100+
builtin_const);
95101
}
96102

97103
static void

gcc/rust/backend/rust-compile-intrinsic.cc

Lines changed: 88 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "rust-compile-intrinsic.h"
1818
#include "rust-compile-context.h"
1919
#include "rust-compile-type.h"
20+
#include "rust-compile-expr.h"
2021
#include "rust-compile-fnparam.h"
2122
#include "rust-builtins.h"
2223
#include "rust-diagnostics.h"
@@ -28,6 +29,8 @@
2829
#include "fold-const.h"
2930
#include "langhooks.h"
3031

32+
#include "print-tree.h"
33+
3134
namespace Rust {
3235
namespace Compile {
3336

@@ -44,6 +47,15 @@ wrapping_op_handler (Context *ctx, TyTy::FnType *fntype, tree_code op);
4447
static tree
4548
copy_nonoverlapping_handler (Context *ctx, TyTy::FnType *fntype);
4649

50+
enum class Prefetch
51+
{
52+
Read,
53+
Write
54+
};
55+
56+
static tree
57+
prefetch_data_handler (Context *ctx, TyTy::FnType *fntype, Prefetch kind);
58+
4759
static inline tree
4860
rotate_left_handler (Context *ctx, TyTy::FnType *fntype)
4961
{
@@ -70,18 +82,32 @@ wrapping_mul_handler (Context *ctx, TyTy::FnType *fntype)
7082
{
7183
return wrapping_op_handler (ctx, fntype, MULT_EXPR);
7284
}
85+
static inline tree
86+
prefetch_read_data (Context *ctx, TyTy::FnType *fntype)
87+
{
88+
return prefetch_data_handler (ctx, fntype, Prefetch::Read);
89+
}
90+
static inline tree
91+
prefetch_write_data (Context *ctx, TyTy::FnType *fntype)
92+
{
93+
return prefetch_data_handler (ctx, fntype, Prefetch::Write);
94+
}
7395

7496
static const std::map<std::string,
7597
std::function<tree (Context *, TyTy::FnType *)>>
76-
generic_intrinsics = {{"offset", &offset_handler},
77-
{"size_of", &sizeof_handler},
78-
{"transmute", &transmute_handler},
79-
{"rotate_left", &rotate_left_handler},
80-
{"rotate_right", &rotate_right_handler},
81-
{"wrapping_add", &wrapping_add_handler},
82-
{"wrapping_sub", &wrapping_sub_handler},
83-
{"wrapping_mul", &wrapping_mul_handler},
84-
{"copy_nonoverlapping", &copy_nonoverlapping_handler}};
98+
generic_intrinsics = {
99+
{"offset", &offset_handler},
100+
{"size_of", &sizeof_handler},
101+
{"transmute", &transmute_handler},
102+
{"rotate_left", &rotate_left_handler},
103+
{"rotate_right", &rotate_right_handler},
104+
{"wrapping_add", &wrapping_add_handler},
105+
{"wrapping_sub", &wrapping_sub_handler},
106+
{"wrapping_mul", &wrapping_mul_handler},
107+
{"copy_nonoverlapping", &copy_nonoverlapping_handler},
108+
{"prefetch_read_data", &prefetch_read_data},
109+
{"prefetch_write_data", &prefetch_write_data},
110+
};
85111

86112
Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {}
87113

@@ -515,5 +541,58 @@ copy_nonoverlapping_handler (Context *ctx, TyTy::FnType *fntype)
515541
return fndecl;
516542
}
517543

544+
static tree
545+
prefetch_data_handler (Context *ctx, TyTy::FnType *fntype, Prefetch kind)
546+
{
547+
rust_assert (fntype->get_params ().size () == 2);
548+
549+
tree lookup = NULL_TREE;
550+
if (check_for_cached_intrinsic (ctx, fntype, &lookup))
551+
return lookup;
552+
553+
auto fndecl = compile_intrinsic_function (ctx, fntype);
554+
555+
// prefetching isn't pure and shouldn't be discarded after GIMPLE
556+
TREE_READONLY (fndecl) = 0;
557+
TREE_SIDE_EFFECTS (fndecl) = 1;
558+
559+
std::vector<Bvariable *> args;
560+
compile_fn_params (ctx, fntype, fndecl, &args);
561+
562+
if (!ctx->get_backend ()->function_set_parameters (fndecl, args))
563+
return error_mark_node;
564+
565+
enter_intrinsic_block (ctx, fndecl);
566+
567+
auto addr = ctx->get_backend ()->var_expression (args[0], Location ());
568+
auto locality = ctx->get_backend ()->var_expression (args[1], Location ());
569+
570+
mpz_t zero;
571+
mpz_t one;
572+
mpz_init_set_ui (zero, 0);
573+
mpz_init_set_ui (one, 1);
574+
575+
auto rw_flag_value = kind == Prefetch::Write ? one : zero;
576+
auto rw_flag
577+
= ctx->get_backend ()->integer_constant_expression (integer_type_node,
578+
rw_flag_value);
579+
auto prefetch_raw = NULL_TREE;
580+
auto ok
581+
= BuiltinsContext::get ().lookup_simple_builtin ("prefetch", &prefetch_raw);
582+
rust_assert (ok);
583+
auto prefetch
584+
= build_fold_addr_expr_loc (Location ().gcc_location (), prefetch_raw);
585+
586+
auto prefetch_call
587+
= ctx->get_backend ()->call_expression (prefetch, {addr, rw_flag, locality},
588+
nullptr, Location ());
589+
590+
ctx->add_statement (prefetch_call);
591+
592+
finalize_intrinsic_block (ctx, fndecl);
593+
594+
return fndecl;
595+
}
596+
518597
} // namespace Compile
519598
} // namespace Rust
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#![feature(intrinsics)]
2+
3+
extern "rust-intrinsic" {
4+
fn prefetch_read_data<T>(addr: *const T, locality: i32);
5+
fn prefetch_write_data<T>(addr: *const T, locality: i32);
6+
}
7+
8+
fn main() -> i32 {
9+
let a = [1, 2, 3, 4];
10+
11+
unsafe {
12+
prefetch_read_data(&a, 3);
13+
prefetch_write_data(&a[0], 3);
14+
}
15+
16+
0
17+
}

0 commit comments

Comments
 (0)