Skip to content

Commit 40674f5

Browse files
committed
Add different misaligned path for archs with unaligned support
1 parent 3ad5fa9 commit 40674f5

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

build.rs

+5
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ fn main() {
3333
println!("cargo:rustc-cfg=feature=\"mem\"");
3434
}
3535

36+
// These targets have hardware unaligned access support.
37+
if target.contains("x86_64") || target.contains("i686") || target.contains("aarch64") {
38+
println!("cargo:rustc-cfg=feature=\"mem-unaligned\"");
39+
}
40+
3641
// NOTE we are going to assume that llvm-target, what determines our codegen option, matches the
3742
// target triple. This is usually correct for our built-in targets but can break in presence of
3843
// custom targets, which can have arbitrary names.

src/mem/impls.rs

+38
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ const WORD_COPY_THRESHOLD: usize = if 2 * WORD_SIZE > 16 {
1616
16
1717
};
1818

19+
#[cfg(feature = "mem-unaligned")]
20+
unsafe fn read_usize_unaligned(x: *const usize) -> usize {
21+
// Do not use `core::ptr::read_unaligned` here, since it calls `copy_nonoverlapping` which
22+
// is translated to memcpy in LLVM.
23+
let x_read = (x as *const [u8; core::mem::size_of::<usize>()]).read();
24+
core::mem::transmute(x_read)
25+
}
26+
1927
#[inline(always)]
2028
pub unsafe fn copy_forward(mut dest: *mut u8, mut src: *const u8, mut n: usize) {
2129
#[inline(always)]
@@ -41,6 +49,7 @@ pub unsafe fn copy_forward(mut dest: *mut u8, mut src: *const u8, mut n: usize)
4149
}
4250
}
4351

52+
#[cfg(not(feature = "mem-unaligned"))]
4453
#[inline(always)]
4554
unsafe fn copy_forward_misaligned_words(dest: *mut u8, src: *const u8, n: usize) {
4655
let mut dest_usize = dest as *mut usize;
@@ -69,6 +78,20 @@ pub unsafe fn copy_forward(mut dest: *mut u8, mut src: *const u8, mut n: usize)
6978
}
7079
}
7180

81+
#[cfg(feature = "mem-unaligned")]
82+
#[inline(always)]
83+
unsafe fn copy_forward_misaligned_words(dest: *mut u8, src: *const u8, n: usize) {
84+
let mut dest_usize = dest as *mut usize;
85+
let mut src_usize = src as *mut usize;
86+
let dest_end = dest.add(n) as *mut usize;
87+
88+
while dest_usize < dest_end {
89+
*dest_usize = read_usize_unaligned(src_usize);
90+
dest_usize = dest_usize.add(1);
91+
src_usize = src_usize.add(1);
92+
}
93+
}
94+
7295
if n >= WORD_COPY_THRESHOLD {
7396
// Align dest
7497
// Because of n >= 2 * WORD_SIZE, dst_misalignment < n
@@ -119,6 +142,7 @@ pub unsafe fn copy_backward(dest: *mut u8, src: *const u8, mut n: usize) {
119142
}
120143
}
121144

145+
#[cfg(not(feature = "mem-unaligned"))]
122146
#[inline(always)]
123147
unsafe fn copy_backward_misaligned_words(dest: *mut u8, src: *const u8, n: usize) {
124148
let mut dest_usize = dest as *mut usize;
@@ -147,6 +171,20 @@ pub unsafe fn copy_backward(dest: *mut u8, src: *const u8, mut n: usize) {
147171
}
148172
}
149173

174+
#[cfg(feature = "mem-unaligned")]
175+
#[inline(always)]
176+
unsafe fn copy_backward_misaligned_words(dest: *mut u8, src: *const u8, n: usize) {
177+
let mut dest_usize = dest as *mut usize;
178+
let mut src_usize = src as *mut usize;
179+
let dest_start = dest.sub(n) as *mut usize;
180+
181+
while dest_start < dest_usize {
182+
dest_usize = dest_usize.sub(1);
183+
src_usize = src_usize.sub(1);
184+
*dest_usize = read_usize_unaligned(src_usize as *const u8);
185+
}
186+
}
187+
150188
let mut dest = dest.add(n);
151189
let mut src = src.add(n);
152190

0 commit comments

Comments
 (0)