| ... | ... | @@ -40,9 +40,7 @@ fn memmoveSmall(opt_dest: ?[*]u8, opt_src: ?[*]const u8, len: usize) callconv(.C |
| 40 | 40 | |
| 41 | 41 | fn memmoveFast(dest: ?[*]u8, src: ?[*]u8, len: usize) callconv(.C) ?[*]u8 { |
| 42 | 42 | @setRuntimeSafety(builtin.is_test); |
| 43 | | const unroll_count = 1; |
| 44 | | comptime assert(std.math.isPowerOfTwo(unroll_count)); |
| 45 | | const small_limit = @max(2 * @sizeOf(Element), unroll_count * @sizeOf(Element)); |
| 43 | const small_limit = @max(2 * @sizeOf(Element), @sizeOf(Element)); |
| 46 | 44 | |
| 47 | 45 | if (copySmallLength(small_limit, dest.?, src.?, len)) return dest; |
| 48 | 46 | |
| ... | ... | @@ -50,9 +48,9 @@ fn memmoveFast(dest: ?[*]u8, src: ?[*]u8, len: usize) callconv(.C) ?[*]u8 { |
| 50 | 48 | const src_address = @intFromPtr(src); |
| 51 | 49 | |
| 52 | 50 | if (src_address < dest_address and src_address + len > dest_address) { |
| 53 | | copyBackwards(unroll_count, dest.?, src.?, len); |
| 51 | copyBackwards(dest.?, src.?, len); |
| 54 | 52 | } else { |
| 55 | | copyForwards(unroll_count, dest.?, src.?, len); |
| 53 | copyForwards(dest.?, src.?, len); |
| 56 | 54 | } |
| 57 | 55 | |
| 58 | 56 | return dest; |
| ... | ... | @@ -145,14 +143,12 @@ inline fn copyRange4( |
| 145 | 143 | } |
| 146 | 144 | |
| 147 | 145 | inline fn copyForwards( |
| 148 | | comptime unroll_count: comptime_int, |
| 149 | 146 | dest: [*]u8, |
| 150 | 147 | src: [*]const u8, |
| 151 | 148 | len: usize, |
| 152 | 149 | ) void { |
| 153 | 150 | @setRuntimeSafety(builtin.is_test); |
| 154 | 151 | assert(len >= 2 * @sizeOf(Element)); |
| 155 | | assert(len >= unroll_count * @sizeOf(Element)); |
| 156 | 152 | |
| 157 | 153 | const head = src[0..@sizeOf(Element)].*; |
| 158 | 154 | const tail = src[len - @sizeOf(Element) ..][0..@sizeOf(Element)].*; |
| ... | ... | @@ -161,7 +157,7 @@ inline fn copyForwards( |
| 161 | 157 | const d = dest + alignment_offset; |
| 162 | 158 | const s = src + alignment_offset; |
| 163 | 159 | |
| 164 | | copyBlocksAlignedSource(@ptrCast(d), @alignCast(@ptrCast(s)), n, unroll_count); |
| 160 | copyBlocksAlignedSource(@ptrCast(d), @alignCast(@ptrCast(s)), n); |
| 165 | 161 | |
| 166 | 162 | // copy last `copy_size` bytes unconditionally, since block copy |
| 167 | 163 | // methods only copy a multiple of `copy_size` bytes. |
| ... | ... | @@ -173,53 +169,31 @@ inline fn copyBlocksAlignedSource( |
| 173 | 169 | dest: [*]align(1) Element, |
| 174 | 170 | src: [*]const Element, |
| 175 | 171 | max_bytes: usize, |
| 176 | | comptime unroll_count: comptime_int, |
| 177 | 172 | ) void { |
| 178 | | copyBlocks(dest, src, max_bytes, unroll_count); |
| 173 | copyBlocks(dest, src, max_bytes); |
| 179 | 174 | } |
| 180 | 175 | |
| 181 | 176 | /// Copies the largest multiple of `@sizeOf(T)` bytes from `src` to `dest`, |
| 182 | 177 | /// that is less than `max_bytes` where `T` is the child type of `src` and |
| 183 | | /// `dest`; `max_bytes` must be at least `@sizeOf(T)`. The primary copy loop |
| 184 | | /// will be unrolled to perform `unroll_count` copies per iteration. |
| 178 | /// `dest`; `max_bytes` must be at least `@sizeOf(T)`. |
| 185 | 179 | inline fn copyBlocks( |
| 186 | 180 | dest: anytype, |
| 187 | 181 | src: anytype, |
| 188 | 182 | max_bytes: usize, |
| 189 | | comptime unroll_count: comptime_int, |
| 190 | 183 | ) void { |
| 191 | 184 | @setRuntimeSafety(builtin.is_test); |
| 192 | | comptime assert(unroll_count > 0); |
| 193 | 185 | |
| 194 | 186 | const T = @typeInfo(@TypeOf(dest)).pointer.child; |
| 195 | 187 | comptime assert(T == @typeInfo(@TypeOf(src)).pointer.child); |
| 196 | 188 | |
| 197 | | const loop_count = max_bytes / (@sizeOf(T) * unroll_count); |
| 189 | const loop_count = max_bytes / @sizeOf(T); |
| 198 | 190 | |
| 199 | | // save tail since it can overlap with `dest `in main copy loop |
| 200 | | const tail_start = (max_bytes / @sizeOf(T)) - (unroll_count - 1); |
| 201 | | const st = src[tail_start..][0 .. unroll_count - 1]; |
| 202 | | var tail_data: [unroll_count - 1]Element = undefined; |
| 203 | | inline for (&tail_data, st) |*d, s| { |
| 204 | | d.* = s; |
| 205 | | } |
| 206 | | |
| 207 | | for (0..loop_count) |i| { |
| 208 | | const du = dest[i * unroll_count ..][0..unroll_count]; |
| 209 | | const su = src[i * unroll_count ..][0..unroll_count]; |
| 210 | | inline for (du, su) |*d, s| { |
| 211 | | d.* = s; |
| 212 | | } |
| 213 | | } |
| 214 | | |
| 215 | | const dt = dest[tail_start..][0 .. unroll_count - 1]; |
| 216 | | inline for (dt, tail_data) |*d, s| { |
| 191 | for (dest[0..loop_count], src[0..loop_count]) |*d, s| { |
| 217 | 192 | d.* = s; |
| 218 | 193 | } |
| 219 | 194 | } |
| 220 | 195 | |
| 221 | 196 | inline fn copyBackwards( |
| 222 | | comptime unroll_count: comptime_int, |
| 223 | 197 | dest: [*]u8, |
| 224 | 198 | src: [*]const u8, |
| 225 | 199 | len: usize, |
| ... | ... | @@ -227,30 +201,18 @@ inline fn copyBackwards( |
| 227 | 201 | const end_bytes = src[len - @sizeOf(Element) ..][0..@sizeOf(Element)].*; |
| 228 | 202 | const start_bytes = src[0..@sizeOf(Element)].*; |
| 229 | 203 | |
| 230 | | const tail_dest: [*]Element = @ptrFromInt(std.mem.alignForward(usize, @intFromPtr(dest), @alignOf(Element))); |
| 231 | | const tail_src: [*]align(1) const Element = @ptrCast(src + (@intFromPtr(tail_dest) - @intFromPtr(dest))); |
| 232 | | const tail_bytes: [unroll_count - 1]Element = tail_src[0 .. unroll_count - 1].*; |
| 233 | | |
| 234 | 204 | const d_addr: usize = std.mem.alignBackward(usize, @intFromPtr(dest) + len, @alignOf(Element)); |
| 235 | 205 | const d: [*]Element = @ptrFromInt(d_addr); |
| 236 | 206 | const n = d_addr - @intFromPtr(dest); |
| 237 | 207 | const s: [*]align(1) const Element = @ptrCast(src + n); |
| 238 | 208 | |
| 239 | | const loop_count = n / (unroll_count * @sizeOf(Element)); |
| 209 | const loop_count = n / @sizeOf(Element); |
| 240 | 210 | var i: usize = 1; |
| 241 | 211 | while (i < loop_count + 1) : (i += 1) { |
| 242 | | const du = d - (i * unroll_count); |
| 243 | | const su = s - (i * unroll_count); |
| 244 | | inline for (0..unroll_count) |j| { |
| 245 | | du[unroll_count - 1 - j] = su[unroll_count - 1 - j]; |
| 246 | | } |
| 212 | (d - i)[0] = (s - i)[0]; |
| 247 | 213 | } |
| 248 | 214 | |
| 249 | | inline for (tail_dest[0 .. unroll_count - 1], tail_bytes) |*dt, st| { |
| 250 | | dt.* = st; |
| 251 | | } |
| 252 | 215 | dest[0..@sizeOf(Element)].* = start_bytes; |
| 253 | | |
| 254 | 216 | dest[len - @sizeOf(Element) ..][0..@sizeOf(Element)].* = end_bytes; |
| 255 | 217 | } |
| 256 | 218 | |