authorgravatar for rpkak@noreply.codeberg.orgrpkak <rpkak@noreply.codeberg.org> 2025-09-23 12:58:08+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-09-24 12:29:43-07:00
log4fb08986cba65623c6dbabcbb83f0aa570e06a65
treeba68a077311282fd9f35bd961cd25a6a068bde9e
parent5bf52a6f50a9fa0380499dd38a9826fc39c43f11

optimize std.mem.swap


1 files changed, 28 insertions(+), 4 deletions(-)

lib/std/mem.zig+28-4
...@@ -3633,10 +3633,34 @@ test indexOfMinMax {...@@ -3633,10 +3633,34 @@ test indexOfMinMax {
3633}3633}
36343634
3635/// Exchanges contents of two memory locations.3635/// Exchanges contents of two memory locations.
3636pub fn swap(comptime T: type, a: *T, b: *T) void {3636pub fn swap(comptime T: type, noalias a: *T, noalias b: *T) void {
3637 const tmp = a.*;3637 if (@inComptime()) {
3638 a.* = b.*;3638 // In comptime, accessing bytes of values with no defined layout is a compile error.
3639 b.* = tmp;3639 const tmp = a.*;
3640 a.* = b.*;
3641 b.* = tmp;
3642 } else {
3643 // Swapping in streaming nature from start to end instead of swapping
3644 // everything in one step allows easier optimizations and less stack usage.
3645 const a_bytes: []align(@alignOf(T)) u8 = @ptrCast(a);
3646 const b_bytes: []align(@alignOf(T)) u8 = @ptrCast(b);
3647 for (a_bytes, b_bytes) |*ab, *bb| {
3648 const tmp = ab.*;
3649 ab.* = bb.*;
3650 bb.* = tmp;
3651 }
3652 }
3653}
3654
3655test "swap works at comptime with types with no defined layout" {
3656 comptime {
3657 const T = struct { val: u64 };
3658 var a: T = .{ .val = 0 };
3659 var b: T = .{ .val = 1 };
3660 swap(T, &a, &b);
3661 try testing.expectEqual(T{ .val = 1 }, a);
3662 try testing.expectEqual(T{ .val = 0 }, b);
3663 }
3640}3664}
36413665
3642inline fn reverseVector(comptime N: usize, comptime T: type, a: []T) [N]T {3666inline fn reverseVector(comptime N: usize, comptime T: type, a: []T) [N]T {