authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-04-26 13:48:38-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-04-28 13:24:43-07:00
log57ea6207d3cb2db706bdc06c14605e4b901736dd
treee40302ce7199f5614d8b9c3cc9a3d70c782620ce
parent82fc360613e7070ffe7124fb070b151a382bd31b

std.ArrayList: mark the appendNTimes methods inline

The previous commit introduced an optimization to the LLVM backend that makes `@memset` lower more optimally when the element is comptime-known and has a repeating byte pattern. By making these functions inline, if the element parameter is comptime-known at the callsite, it will be comptime-known in the `@memset` call, causing more use of the LLVM `memset` intrinsic rather than an inline for loop when using the LLVM backend. This affects, for example, std.crypto.argon2, which calls appendNTimesAssumeCapacity with a `[128]u64` as the element. This is now lowered with a single `memset` call.

1 files changed, 16 insertions(+), 8 deletions(-)

lib/std/array_list.zig+16-8
...@@ -306,18 +306,22 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {...@@ -306,18 +306,22 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
306 /// Append a value to the list `n` times.306 /// Append a value to the list `n` times.
307 /// Allocates more memory as necessary.307 /// Allocates more memory as necessary.
308 /// Invalidates pointers if additional memory is needed.308 /// Invalidates pointers if additional memory is needed.
309 pub fn appendNTimes(self: *Self, value: T, n: usize) Allocator.Error!void {309 /// The function is inline so that a comptime-known `value` parameter will
310 /// have a more optimal memset codegen in case it has a repeated byte pattern.
311 pub inline fn appendNTimes(self: *Self, value: T, n: usize) Allocator.Error!void {
310 const old_len = self.items.len;312 const old_len = self.items.len;
311 try self.resize(self.items.len + n);313 try self.resize(self.items.len + n);
312 mem.set(T, self.items[old_len..self.items.len], value);314 @memset(self.items[old_len..self.items.len], value);
313 }315 }
314316
315 /// Append a value to the list `n` times.317 /// Append a value to the list `n` times.
316 /// Asserts the capacity is enough. **Does not** invalidate pointers.318 /// Asserts the capacity is enough. **Does not** invalidate pointers.
317 pub fn appendNTimesAssumeCapacity(self: *Self, value: T, n: usize) void {319 /// The function is inline so that a comptime-known `value` parameter will
320 /// have a more optimal memset codegen in case it has a repeated byte pattern.
321 pub inline fn appendNTimesAssumeCapacity(self: *Self, value: T, n: usize) void {
318 const new_len = self.items.len + n;322 const new_len = self.items.len + n;
319 assert(new_len <= self.capacity);323 assert(new_len <= self.capacity);
320 mem.set(T, self.items.ptr[self.items.len..new_len], value);324 @memset(self.items.ptr[self.items.len..new_len], value);
321 self.items.len = new_len;325 self.items.len = new_len;
322 }326 }
323327
...@@ -766,19 +770,23 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -766,19 +770,23 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
766 /// Append a value to the list `n` times.770 /// Append a value to the list `n` times.
767 /// Allocates more memory as necessary.771 /// Allocates more memory as necessary.
768 /// Invalidates pointers if additional memory is needed.772 /// Invalidates pointers if additional memory is needed.
769 pub fn appendNTimes(self: *Self, allocator: Allocator, value: T, n: usize) Allocator.Error!void {773 /// The function is inline so that a comptime-known `value` parameter will
774 /// have a more optimal memset codegen in case it has a repeated byte pattern.
775 pub inline fn appendNTimes(self: *Self, allocator: Allocator, value: T, n: usize) Allocator.Error!void {
770 const old_len = self.items.len;776 const old_len = self.items.len;
771 try self.resize(allocator, self.items.len + n);777 try self.resize(allocator, self.items.len + n);
772 mem.set(T, self.items[old_len..self.items.len], value);778 @memset(self.items[old_len..self.items.len], value);
773 }779 }
774780
775 /// Append a value to the list `n` times.781 /// Append a value to the list `n` times.
776 /// **Does not** invalidate pointers.782 /// **Does not** invalidate pointers.
777 /// Asserts the capacity is enough.783 /// Asserts the capacity is enough.
778 pub fn appendNTimesAssumeCapacity(self: *Self, value: T, n: usize) void {784 /// The function is inline so that a comptime-known `value` parameter will
785 /// have a more optimal memset codegen in case it has a repeated byte pattern.
786 pub inline fn appendNTimesAssumeCapacity(self: *Self, value: T, n: usize) void {
779 const new_len = self.items.len + n;787 const new_len = self.items.len + n;
780 assert(new_len <= self.capacity);788 assert(new_len <= self.capacity);
781 mem.set(T, self.items.ptr[self.items.len..new_len], value);789 @memset(self.items.ptr[self.items.len..new_len], value);
782 self.items.len = new_len;790 self.items.len = new_len;
783 }791 }
784792