Skip to content

Commit 2195f75

Browse files
committed
librustc: Speed up byte copy operations
1 parent c8e9d06 commit 2195f75

File tree

7 files changed

+96
-2
lines changed

7 files changed

+96
-2
lines changed

src/libcore/libc.rs

+13
Original file line numberDiff line numberDiff line change
@@ -1123,10 +1123,23 @@ pub mod funcs {
11231123
unsafe fn strerror(n: c_int) -> *c_char;
11241124
unsafe fn strtok(s: *c_char, t: *c_char) -> *c_char;
11251125
unsafe fn strxfrm(s: *c_char, ct: *c_char, n: size_t) -> size_t;
1126+
1127+
// These are fine to execute on the Rust stack. They must be, in
1128+
// fact, because LLVM generates calls to them!
1129+
#[rust_stack]
1130+
#[inline(always)]
11261131
unsafe fn memcpy(s: *c_void, ct: *c_void, n: size_t) -> *c_void;
1132+
#[rust_stack]
1133+
#[inline(always)]
11271134
unsafe fn memmove(s: *c_void, ct: *c_void, n: size_t) -> *c_void;
1135+
#[rust_stack]
1136+
#[inline(always)]
11281137
unsafe fn memcmp(cx: *c_void, ct: *c_void, n: size_t) -> c_int;
1138+
#[rust_stack]
1139+
#[inline(always)]
11291140
unsafe fn memchr(cx: *c_void, c: c_int, n: size_t) -> *c_void;
1141+
#[rust_stack]
1142+
#[inline(always)]
11301143
unsafe fn memset(s: *c_void, c: c_int, n: size_t) -> *c_void;
11311144
}
11321145
}

src/libcore/ptr.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,16 @@ pub pure fn is_not_null<T>(ptr: *const T) -> bool { !is_null(ptr) }
116116
* and destination may overlap.
117117
*/
118118
#[inline(always)]
119+
#[cfg(target_word_size = "32")]
119120
pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
120121
let n = count * sys::size_of::<T>();
121-
libc_::memmove(dst as *mut c_void, src as *c_void, n as size_t);
122+
memmove32(dst as *mut u8, src as *u8, n as u32);
123+
}
124+
#[inline(always)]
125+
#[cfg(target_word_size = "64")]
126+
pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
127+
let n = count * sys::size_of::<T>();
128+
memmove64(dst as *mut u8, src as *u8, n as u64);
122129
}
123130

124131
#[inline(always)]
@@ -183,6 +190,23 @@ pub trait Ptr<T> {
183190
pure fn offset(count: uint) -> self;
184191
}
185192

193+
#[cfg(stage0)]
194+
unsafe fn memmove32(dst: *mut u8, src: *const u8, count: u32) {
195+
libc::memmove(dst as *c_void, src as *c_void, count as size_t);
196+
}
197+
#[cfg(stage0)]
198+
unsafe fn memmove64(dst: *mut u8, src: *const u8, count: u64) {
199+
libc::memmove(dst as *c_void, src as *c_void, count as size_t);
200+
}
201+
202+
#[abi="rust-intrinsic"]
203+
#[cfg(stage1)]
204+
#[cfg(stage2)]
205+
pub extern {
206+
fn memmove32(dst: *mut u8, src: *u8, size: u32);
207+
fn memmove64(dst: *mut u8, src: *u8, size: u64);
208+
}
209+
186210
/// Extension methods for immutable pointers
187211
impl<T> *T: Ptr<T> {
188212
/// Returns true if the pointer is equal to the null pointer.

src/libcore/vec.rs

+7
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ pub pure fn slice<T: Copy>(v: &[const T], start: uint, end: uint) -> ~[T] {
266266
}
267267

268268
/// Return a slice that points into another slice.
269+
#[inline(always)]
269270
pub pure fn view<T>(v: &r/[T], start: uint, end: uint) -> &r/[T] {
270271
assert (start <= end);
271272
assert (end <= len(v));
@@ -279,6 +280,7 @@ pub pure fn view<T>(v: &r/[T], start: uint, end: uint) -> &r/[T] {
279280
}
280281

281282
/// Return a slice that points into another slice.
283+
#[inline(always)]
282284
pub pure fn mut_view<T>(v: &r/[mut T], start: uint, end: uint) -> &r/[mut T] {
283285
assert (start <= end);
284286
assert (end <= len(v));
@@ -292,6 +294,7 @@ pub pure fn mut_view<T>(v: &r/[mut T], start: uint, end: uint) -> &r/[mut T] {
292294
}
293295

294296
/// Return a slice that points into another slice.
297+
#[inline(always)]
295298
pub pure fn const_view<T>(v: &r/[const T], start: uint,
296299
end: uint) -> &r/[const T] {
297300
assert (start <= end);
@@ -305,6 +308,8 @@ pub pure fn const_view<T>(v: &r/[const T], start: uint,
305308
}
306309
}
307310

311+
/// Copies
312+
308313
/// Split the vector `v` by applying each element against the predicate `f`.
309314
pub fn split<T: Copy>(v: &[T], f: fn(t: &T) -> bool) -> ~[~[T]] {
310315
let ln = len(v);
@@ -2127,6 +2132,7 @@ pub mod raw {
21272132
* Copies `count` bytes from `src` to `dst`. The source and destination
21282133
* may overlap.
21292134
*/
2135+
#[inline(always)]
21302136
pub unsafe fn copy_memory<T>(dst: &[mut T], src: &[const T],
21312137
count: uint) {
21322138
assert dst.len() >= count;
@@ -2193,6 +2199,7 @@ pub mod bytes {
21932199
* Copies `count` bytes from `src` to `dst`. The source and destination
21942200
* may overlap.
21952201
*/
2202+
#[inline(always)]
21962203
pub fn copy_memory(dst: &[mut u8], src: &[const u8], count: uint) {
21972204
// Bound checks are done at vec::raw::copy_memory.
21982205
unsafe { vec::raw::copy_memory(dst, src, count) }

src/librustc/middle/trans/base.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -2593,9 +2593,15 @@ fn declare_intrinsics(llmod: ModuleRef) -> HashMap<~str, ValueRef> {
25932593
T_void()));
25942594
let memcpy32 =
25952595
decl_cdecl_fn(llmod, ~"llvm.memcpy.p0i8.p0i8.i32",
2596-
T_fn(T_memcpy32_args, T_void()));
2596+
T_fn(copy T_memcpy32_args, T_void()));
25972597
let memcpy64 =
25982598
decl_cdecl_fn(llmod, ~"llvm.memcpy.p0i8.p0i8.i64",
2599+
T_fn(copy T_memcpy64_args, T_void()));
2600+
let memmove32 =
2601+
decl_cdecl_fn(llmod, ~"llvm.memmove.p0i8.p0i8.i32",
2602+
T_fn(T_memcpy32_args, T_void()));
2603+
let memmove64 =
2604+
decl_cdecl_fn(llmod, ~"llvm.memmove.p0i8.p0i8.i64",
25992605
T_fn(T_memcpy64_args, T_void()));
26002606
let memset32 =
26012607
decl_cdecl_fn(llmod, ~"llvm.memset.p0i8.i32",
@@ -2704,6 +2710,8 @@ fn declare_intrinsics(llmod: ModuleRef) -> HashMap<~str, ValueRef> {
27042710
intrinsics.insert(~"llvm.gcread", gcread);
27052711
intrinsics.insert(~"llvm.memcpy.p0i8.p0i8.i32", memcpy32);
27062712
intrinsics.insert(~"llvm.memcpy.p0i8.p0i8.i64", memcpy64);
2713+
intrinsics.insert(~"llvm.memmove.p0i8.p0i8.i32", memmove32);
2714+
intrinsics.insert(~"llvm.memmove.p0i8.p0i8.i64", memmove64);
27072715
intrinsics.insert(~"llvm.memset.p0i8.i32", memset32);
27082716
intrinsics.insert(~"llvm.memset.p0i8.i64", memset64);
27092717
intrinsics.insert(~"llvm.trap", trap);

src/librustc/middle/trans/foreign.rs

+18
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,24 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item,
568568
T_ptr(T_nil()));
569569
Store(bcx, morestack_addr, fcx.llretptr);
570570
}
571+
~"memmove32" => {
572+
let dst_ptr = get_param(decl, first_real_arg);
573+
let src_ptr = get_param(decl, first_real_arg + 1);
574+
let size = get_param(decl, first_real_arg + 2);
575+
let align = C_i32(1);
576+
let volatile = C_bool(false);
577+
let llfn = bcx.ccx().intrinsics.get(~"llvm.memmove.p0i8.p0i8.i32");
578+
Call(bcx, llfn, ~[dst_ptr, src_ptr, size, align, volatile]);
579+
}
580+
~"memmove64" => {
581+
let dst_ptr = get_param(decl, first_real_arg);
582+
let src_ptr = get_param(decl, first_real_arg + 1);
583+
let size = get_param(decl, first_real_arg + 2);
584+
let align = C_i32(1);
585+
let volatile = C_bool(false);
586+
let llfn = bcx.ccx().intrinsics.get(~"llvm.memmove.p0i8.p0i8.i64");
587+
Call(bcx, llfn, ~[dst_ptr, src_ptr, size, align, volatile]);
588+
}
571589
~"sqrtf32" => {
572590
let x = get_param(decl, first_real_arg);
573591
let sqrtf = ccx.intrinsics.get(~"llvm.sqrt.f32");

src/librustc/middle/trans/type_use.rs

+2
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
129129
~"visit_tydesc" | ~"forget" | ~"addr_of" |
130130
~"frame_address" | ~"morestack_addr" => 0,
131131

132+
~"memmove32" | ~"memmove64" => 0,
133+
132134
~"sqrtf32" | ~"sqrtf64" | ~"powif32" | ~"powif64" |
133135
~"sinf32" | ~"sinf64" | ~"cosf32" | ~"cosf64" |
134136
~"powf32" | ~"powf64" | ~"expf32" | ~"expf64" |

src/librustc/middle/typeck/check/mod.rs

+22
Original file line numberDiff line numberDiff line change
@@ -3152,6 +3152,28 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) {
31523152
~"morestack_addr" => {
31533153
(0u, ~[], ty::mk_nil_ptr(tcx))
31543154
}
3155+
~"memmove32" => {
3156+
(0, ~[arg(ast::by_copy,
3157+
ty::mk_ptr(tcx,
3158+
ty::mt { ty: ty::mk_u8(tcx), mutbl: ast::m_mutbl })),
3159+
arg(ast::by_copy,
3160+
ty::mk_ptr(tcx,
3161+
ty::mt { ty: ty::mk_u8(tcx), mutbl: ast::m_imm })),
3162+
arg(ast::by_copy,
3163+
ty::mk_u32(tcx))],
3164+
ty::mk_nil(tcx))
3165+
}
3166+
~"memmove64" => {
3167+
(0, ~[arg(ast::by_copy,
3168+
ty::mk_ptr(tcx,
3169+
ty::mt { ty: ty::mk_u8(tcx), mutbl: ast::m_mutbl })),
3170+
arg(ast::by_copy,
3171+
ty::mk_ptr(tcx,
3172+
ty::mt { ty: ty::mk_u8(tcx), mutbl: ast::m_imm })),
3173+
arg(ast::by_copy,
3174+
ty::mk_u64(tcx))],
3175+
ty::mk_nil(tcx))
3176+
}
31553177
~"sqrtf32" => {
31563178
(0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))],
31573179
ty::mk_f32(tcx))

0 commit comments

Comments
 (0)