diff options
| author | bors <bors@rust-lang.org> | 2013-05-27 15:56:08 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2013-05-27 15:56:08 -0700 |
| commit | dbc57584bd4e87f0bd3eed6bced8bbd04d99edcf (patch) | |
| tree | 834f7712e7345b319c0662b0488bc25ee53b8654 /src/libstd/cast.rs | |
| parent | 5d04ee805b96d34e7c5b316270a730fd9a0c537f (diff) | |
| parent | e6c04dea0325af808198306e283c17f90d31fc26 (diff) | |
| download | rust-dbc57584bd4e87f0bd3eed6bced8bbd04d99edcf.tar.gz rust-dbc57584bd4e87f0bd3eed6bced8bbd04d99edcf.zip | |
auto merge of #6724 : thestinger/rust/swap_fast, r=thestinger
Passing higher alignment values gives the optimization passes more freedom since it can copy in larger chunks. This change results in rustc outputting the same post-optimization IR as clang for swaps and most copies excluding the lack of information about padding.
Code snippet:
```rust
#[inline(never)]
fn swap<T>(x: &mut T, y: &mut T) {
util::swap(x, y);
}
```
Original IR (for `int`):
```llvm
define internal fastcc void @_ZN9swap_283417_a71830ca3ed2d65d3_00E(i64*, i64*) #1 {
static_allocas:
%2 = icmp eq i64* %0, %1
br i1 %2, label %_ZN4util9swap_283717_a71830ca3ed2d65d3_00E.exit, label %3
; <label>:3 ; preds = %static_allocas
%4 = load i64* %0, align 1
%5 = load i64* %1, align 1
store i64 %5, i64* %0, align 1
store i64 %4, i64* %1, align 1
br label %_ZN4util9swap_283717_a71830ca3ed2d65d3_00E.exit
_ZN4util9swap_283717_a71830ca3ed2d65d3_00E.exit: ; preds = %3, %static_allocas
ret void
}
```
After #6710:
```llvm
define internal fastcc void @_ZN9swap_283017_a71830ca3ed2d65d3_00E(i64* nocapture, i64* nocapture) #1 {
static_allocas:
%2 = load i64* %0, align 1
%3 = load i64* %1, align 1
store i64 %3, i64* %0, align 1
store i64 %2, i64* %1, align 1
ret void
}
```
After this change:
```llvm
define internal fastcc void @_ZN9swap_283017_a71830ca3ed2d65d3_00E(i64* nocapture, i64* nocapture) #1 {
static_allocas:
%2 = load i64* %0, align 8
%3 = load i64* %1, align 8
store i64 %3, i64* %0, align 8
store i64 %2, i64* %1, align 8
ret void
}
```
Another example:
```rust
#[inline(never)]
fn set<T>(x: &mut T, y: T) {
*x = y;
}
```
Before, with `(int, int)` (align 1):
```llvm
define internal fastcc void @_ZN8set_282517_8fa972e3f9e451983_00E({ i64, i64 }* nocapture, { i64, i64 }* nocapture) #1 {
static_allocas:
%2 = bitcast { i64, i64 }* %1 to i8*
%3 = bitcast { i64, i64 }* %0 to i8*
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %3, i8* %2, i64 16, i32 1, i1 false)
ret void
}
```
After, with `(int, int)` (align 8):
```llvm
define internal fastcc void @_ZN8set_282617_8fa972e3f9e451983_00E({ i64, i64 }* nocapture, { i64, i64 }* nocapture) #1 {
static_allocas:
%2 = bitcast { i64, i64 }* %1 to i8*
%3 = bitcast { i64, i64 }* %0 to i8*
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %3, i8* %2, i64 16, i32 8, i1 false)
ret void
}
```
Diffstat (limited to 'src/libstd/cast.rs')
| -rw-r--r-- | src/libstd/cast.rs | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/src/libstd/cast.rs b/src/libstd/cast.rs index cde22afd34a..30ad41f0ca2 100644 --- a/src/libstd/cast.rs +++ b/src/libstd/cast.rs @@ -14,8 +14,9 @@ use sys; use unstable::intrinsics; /// Casts the value at `src` to U. The two types must have the same length. +#[cfg(stage0)] pub unsafe fn transmute_copy<T, U>(src: &T) -> U { - let mut dest: U = intrinsics::init(); + let mut dest: U = intrinsics::uninit(); { let dest_ptr: *mut u8 = transmute(&mut dest); let src_ptr: *u8 = transmute(src); @@ -26,6 +27,26 @@ pub unsafe fn transmute_copy<T, U>(src: &T) -> U { dest } +#[cfg(target_word_size = "32", not(stage0))] +#[inline(always)] +pub unsafe fn transmute_copy<T, U>(src: &T) -> U { + let mut dest: U = intrinsics::uninit(); + let dest_ptr: *mut u8 = transmute(&mut dest); + let src_ptr: *u8 = transmute(src); + intrinsics::memcpy32(dest_ptr, src_ptr, sys::size_of::<U>() as u32); + dest +} + +#[cfg(target_word_size = "64", not(stage0))] +#[inline(always)] +pub unsafe fn transmute_copy<T, U>(src: &T) -> U { + let mut dest: U = intrinsics::uninit(); + let dest_ptr: *mut u8 = transmute(&mut dest); + let src_ptr: *u8 = transmute(src); + intrinsics::memcpy64(dest_ptr, src_ptr, sys::size_of::<U>() as u64); + dest +} + /** * Move a thing into the void * @@ -43,6 +64,7 @@ pub unsafe fn forget<T>(thing: T) { intrinsics::forget(thing); } * and/or reinterpret_cast when such calls would otherwise scramble a box's * reference count */ +#[inline(always)] pub unsafe fn bump_box_refcount<T>(t: @T) { forget(t); } /** |
