| author | |
| committer | |
| log | 6a32d58876995f18b35ffd89b8875a99417c29cf |
| tree | 7d446c1ecf0721a189d7784ec621aae9cab12cc8 |
| parent | aaf1e0b25bbeedc18869073e1a51719e2e86cc93 |
| parent | 564b1da2144a94fd3cf4c66614968d8b669bc26f |
| signature |
Rename `simd.suggestVectorSize` to clarify intent and fix related segfault5 files changed, 31 insertions(+), 30 deletions(-)
lib/std/crypto/ghash_polyval.zig+1-5| ... | ... | @@ -158,11 +158,7 @@ fn Hash(comptime endian: std.builtin.Endian, comptime shift_key: bool) type { |
| 158 | 158 | /// clmulSoft128_64 is faster on platforms with no native 128-bit registers. |
| 159 | 159 | const clmulSoft = switch (builtin.cpu.arch) { |
| 160 | 160 | .wasm32, .wasm64 => clmulSoft128_64, |
| 161 | else => impl: { | |
| 162 | const vector_size = std.simd.suggestVectorSize(u128) orelse 0; | |
| 163 | if (vector_size < 128) break :impl clmulSoft128_64; | |
| 164 | break :impl clmulSoft128; | |
| 165 | }, | |
| 161 | else => if (std.simd.suggestVectorLength(u128) != null) clmulSoft128 else clmulSoft128_64, | |
| 166 | 162 | }; |
| 167 | 163 | |
| 168 | 164 | // Software carryless multiplication of two 64-bit integers using native 128-bit registers. |
lib/std/http/protocol.zig+1-1| ... | ... | @@ -84,7 +84,7 @@ pub const HeadersParser = struct { |
| 84 | 84 | /// If the amount returned is less than `bytes.len`, you may assume that the parser is in a content state and the |
| 85 | 85 | /// first byte of content is located at `bytes[result]`. |
| 86 | 86 | pub fn findHeadersEnd(r: *HeadersParser, bytes: []const u8) u32 { |
| 87 | const vector_len: comptime_int = @max(std.simd.suggestVectorSize(u8) orelse 1, 8); | |
| 87 | const vector_len: comptime_int = @max(std.simd.suggestVectorLength(u8) orelse 1, 8); | |
| 88 | 88 | const len: u32 = @intCast(bytes.len); |
| 89 | 89 | var index: u32 = 0; |
| 90 | 90 |
lib/std/mem.zig+7-6| ... | ... | @@ -1032,15 +1032,16 @@ pub fn indexOfSentinel(comptime T: type, comptime sentinel: T, p: [*:sentinel]co |
| 1032 | 1032 | // The below branch assumes that reading past the end of the buffer is valid, as long |
| 1033 | 1033 | // as we don't read into a new page. This should be the case for most architectures |
| 1034 | 1034 | // which use paged memory, however should be confirmed before adding a new arch below. |
| 1035 | .aarch64, .x86, .x86_64 => if (std.simd.suggestVectorSize(T)) |block_len| { | |
| 1036 | comptime std.debug.assert(std.mem.page_size % block_len == 0); | |
| 1035 | .aarch64, .x86, .x86_64 => if (std.simd.suggestVectorLength(T)) |block_len| { | |
| 1037 | 1036 | const Block = @Vector(block_len, T); |
| 1038 | 1037 | const mask: Block = @splat(sentinel); |
| 1039 | 1038 | |
| 1039 | comptime std.debug.assert(std.mem.page_size % @sizeOf(Block) == 0); | |
| 1040 | ||
| 1040 | 1041 | // First block may be unaligned |
| 1041 | 1042 | const start_addr = @intFromPtr(&p[i]); |
| 1042 | 1043 | const offset_in_page = start_addr & (std.mem.page_size - 1); |
| 1043 | if (offset_in_page < std.mem.page_size - block_len) { | |
| 1044 | if (offset_in_page <= std.mem.page_size - @sizeOf(Block)) { | |
| 1044 | 1045 | // Will not read past the end of a page, full block. |
| 1045 | 1046 | const block: Block = p[i..][0..block_len].*; |
| 1046 | 1047 | const matches = block == mask; |
| ... | ... | @@ -1085,7 +1086,7 @@ test "indexOfSentinel vector paths" { |
| 1085 | 1086 | const allocator = std.testing.allocator; |
| 1086 | 1087 | |
| 1087 | 1088 | inline for (Types) |T| { |
| 1088 | const block_len = std.simd.suggestVectorSize(T) orelse continue; | |
| 1089 | const block_len = std.simd.suggestVectorLength(T) orelse continue; | |
| 1089 | 1090 | |
| 1090 | 1091 | // Allocate three pages so we guarantee a page-crossing address with a full page after |
| 1091 | 1092 | const memory = try allocator.alloc(T, 3 * std.mem.page_size / @sizeOf(T)); |
| ... | ... | @@ -1176,11 +1177,11 @@ pub fn indexOfScalarPos(comptime T: type, slice: []const T, start_index: usize, |
| 1176 | 1177 | !@inComptime() and |
| 1177 | 1178 | (@typeInfo(T) == .Int or @typeInfo(T) == .Float) and std.math.isPowerOfTwo(@bitSizeOf(T))) |
| 1178 | 1179 | { |
| 1179 | if (std.simd.suggestVectorSize(T)) |block_len| { | |
| 1180 | if (std.simd.suggestVectorLength(T)) |block_len| { | |
| 1180 | 1181 | // For Intel Nehalem (2009) and AMD Bulldozer (2012) or later, unaligned loads on aligned data result |
| 1181 | 1182 | // in the same execution as aligned loads. We ignore older arch's here and don't bother pre-aligning. |
| 1182 | 1183 | // |
| 1183 | // Use `std.simd.suggestVectorSize(T)` to get the same alignment as used in this function | |
| 1184 | // Use `std.simd.suggestVectorLength(T)` to get the same alignment as used in this function | |
| 1184 | 1185 | // however this usually isn't necessary unless your arch has a performance penalty due to this. |
| 1185 | 1186 | // |
| 1186 | 1187 | // This may differ for other arch's. Arm for example costs a cycle when loading across a cache |
lib/std/simd.zig+16-12| ... | ... | @@ -6,7 +6,9 @@ |
| 6 | 6 | const std = @import("std"); |
| 7 | 7 | const builtin = @import("builtin"); |
| 8 | 8 | |
| 9 | pub fn suggestVectorSizeForCpu(comptime T: type, comptime cpu: std.Target.Cpu) ?comptime_int { | |
| 9 | pub const suggestVectorSizeForCpu = @compileError("deprecated; use 'suggestVectorLengthForCpu'"); | |
| 10 | ||
| 11 | pub fn suggestVectorLengthForCpu(comptime T: type, comptime cpu: std.Target.Cpu) ?comptime_int { | |
| 10 | 12 | // This is guesswork, if you have better suggestions can add it or edit the current here |
| 11 | 13 | // This can run in comptime only, but stage 1 fails at it, stage 2 can understand it |
| 12 | 14 | const element_bit_size = @max(8, std.math.ceilPowerOfTwo(u16, @bitSizeOf(T)) catch unreachable); |
| ... | ... | @@ -53,24 +55,26 @@ pub fn suggestVectorSizeForCpu(comptime T: type, comptime cpu: std.Target.Cpu) ? |
| 53 | 55 | return @divExact(vector_bit_size, element_bit_size); |
| 54 | 56 | } |
| 55 | 57 | |
| 56 | /// Suggests a target-dependant vector size for a given type, or null if scalars are recommended. | |
| 58 | pub const suggestVectorSize = @compileError("deprecated; use 'suggestVectorLength'"); | |
| 59 | ||
| 60 | /// Suggests a target-dependant vector length for a given type, or null if scalars are recommended. | |
| 57 | 61 | /// Not yet implemented for every CPU architecture. |
| 58 | pub fn suggestVectorSize(comptime T: type) ?comptime_int { | |
| 59 | return suggestVectorSizeForCpu(T, builtin.cpu); | |
| 62 | pub fn suggestVectorLength(comptime T: type) ?comptime_int { | |
| 63 | return suggestVectorLengthForCpu(T, builtin.cpu); | |
| 60 | 64 | } |
| 61 | 65 | |
| 62 | test "suggestVectorSizeForCpu works with signed and unsigned values" { | |
| 66 | test "suggestVectorLengthForCpu works with signed and unsigned values" { | |
| 63 | 67 | comptime var cpu = std.Target.Cpu.baseline(std.Target.Cpu.Arch.x86_64); |
| 64 | 68 | comptime cpu.features.addFeature(@intFromEnum(std.Target.x86.Feature.avx512f)); |
| 65 | 69 | comptime cpu.features.populateDependencies(&std.Target.x86.all_features); |
| 66 | const expected_size: usize = switch (builtin.zig_backend) { | |
| 70 | const expected_len: usize = switch (builtin.zig_backend) { | |
| 67 | 71 | .stage2_x86_64 => 8, |
| 68 | 72 | else => 16, |
| 69 | 73 | }; |
| 70 | const signed_integer_size = suggestVectorSizeForCpu(i32, cpu).?; | |
| 71 | const unsigned_integer_size = suggestVectorSizeForCpu(u32, cpu).?; | |
| 72 | try std.testing.expectEqual(expected_size, unsigned_integer_size); | |
| 73 | try std.testing.expectEqual(expected_size, signed_integer_size); | |
| 74 | const signed_integer_len = suggestVectorLengthForCpu(i32, cpu).?; | |
| 75 | const unsigned_integer_len = suggestVectorLengthForCpu(u32, cpu).?; | |
| 76 | try std.testing.expectEqual(expected_len, unsigned_integer_len); | |
| 77 | try std.testing.expectEqual(expected_len, signed_integer_len); | |
| 74 | 78 | } |
| 75 | 79 | |
| 76 | 80 | fn vectorLength(comptime VectorType: type) comptime_int { |
| ... | ... | @@ -232,7 +236,7 @@ test "vector patterns" { |
| 232 | 236 | } |
| 233 | 237 | } |
| 234 | 238 | |
| 235 | /// Joins two vectors, shifts them leftwards (towards lower indices) and extracts the leftmost elements into a vector the size of a and b. | |
| 239 | /// Joins two vectors, shifts them leftwards (towards lower indices) and extracts the leftmost elements into a vector the length of a and b. | |
| 236 | 240 | pub fn mergeShift(a: anytype, b: anytype, comptime shift: VectorCount(@TypeOf(a, b))) @TypeOf(a, b) { |
| 237 | 241 | const len = vectorLength(@TypeOf(a, b)); |
| 238 | 242 | |
| ... | ... | @@ -240,7 +244,7 @@ pub fn mergeShift(a: anytype, b: anytype, comptime shift: VectorCount(@TypeOf(a, |
| 240 | 244 | } |
| 241 | 245 | |
| 242 | 246 | /// Elements are shifted rightwards (towards higher indices). New elements are added to the left, and the rightmost elements are cut off |
| 243 | /// so that the size of the vector stays the same. | |
| 247 | /// so that the length of the vector stays the same. | |
| 244 | 248 | pub fn shiftElementsRight(vec: anytype, comptime amount: VectorCount(@TypeOf(vec)), shift_in: std.meta.Child(@TypeOf(vec))) @TypeOf(vec) { |
| 245 | 249 | // It may be possible to implement shifts and rotates with a runtime-friendly slice of two joined vectors, as the length of the |
| 246 | 250 | // slice would be comptime-known. This would permit vector shifts and rotates by a non-comptime-known amount. |
lib/std/unicode.zig+6-6| ... | ... | @@ -202,7 +202,7 @@ pub fn utf8CountCodepoints(s: []const u8) !usize { |
| 202 | 202 | pub fn utf8ValidateSlice(input: []const u8) bool { |
| 203 | 203 | var remaining = input; |
| 204 | 204 | |
| 205 | const chunk_len = std.simd.suggestVectorSize(u8) orelse 1; | |
| 205 | const chunk_len = std.simd.suggestVectorLength(u8) orelse 1; | |
| 206 | 206 | const Chunk = @Vector(chunk_len, u8); |
| 207 | 207 | |
| 208 | 208 | // Fast path. Check for and skip ASCII characters at the start of the input. |
| ... | ... | @@ -758,7 +758,7 @@ pub fn utf16leToUtf8Alloc(allocator: mem.Allocator, utf16le: []const u16) ![]u8 |
| 758 | 758 | |
| 759 | 759 | var remaining = utf16le; |
| 760 | 760 | if (builtin.zig_backend != .stage2_x86_64) { |
| 761 | const chunk_len = std.simd.suggestVectorSize(u16) orelse 1; | |
| 761 | const chunk_len = std.simd.suggestVectorLength(u16) orelse 1; | |
| 762 | 762 | const Chunk = @Vector(chunk_len, u16); |
| 763 | 763 | |
| 764 | 764 | // Fast path. Check for and encode ASCII characters at the start of the input. |
| ... | ... | @@ -801,7 +801,7 @@ pub fn utf16leToUtf8AllocZ(allocator: mem.Allocator, utf16le: []const u16) ![:0] |
| 801 | 801 | |
| 802 | 802 | var remaining = utf16le; |
| 803 | 803 | if (builtin.zig_backend != .stage2_x86_64) { |
| 804 | const chunk_len = std.simd.suggestVectorSize(u16) orelse 1; | |
| 804 | const chunk_len = std.simd.suggestVectorLength(u16) orelse 1; | |
| 805 | 805 | const Chunk = @Vector(chunk_len, u16); |
| 806 | 806 | |
| 807 | 807 | // Fast path. Check for and encode ASCII characters at the start of the input. |
| ... | ... | @@ -842,7 +842,7 @@ pub fn utf16leToUtf8(utf8: []u8, utf16le: []const u16) !usize { |
| 842 | 842 | |
| 843 | 843 | var remaining = utf16le; |
| 844 | 844 | if (builtin.zig_backend != .stage2_x86_64) { |
| 845 | const chunk_len = std.simd.suggestVectorSize(u16) orelse 1; | |
| 845 | const chunk_len = std.simd.suggestVectorLength(u16) orelse 1; | |
| 846 | 846 | const Chunk = @Vector(chunk_len, u16); |
| 847 | 847 | |
| 848 | 848 | // Fast path. Check for and encode ASCII characters at the start of the input. |
| ... | ... | @@ -941,7 +941,7 @@ pub fn utf8ToUtf16LeWithNull(allocator: mem.Allocator, utf8: []const u8) ![:0]u1 |
| 941 | 941 | var remaining = utf8; |
| 942 | 942 | // Need support for std.simd.interlace |
| 943 | 943 | if (builtin.zig_backend != .stage2_x86_64 and comptime !builtin.cpu.arch.isMIPS()) { |
| 944 | const chunk_len = std.simd.suggestVectorSize(u8) orelse 1; | |
| 944 | const chunk_len = std.simd.suggestVectorLength(u8) orelse 1; | |
| 945 | 945 | const Chunk = @Vector(chunk_len, u8); |
| 946 | 946 | |
| 947 | 947 | // Fast path. Check for and encode ASCII characters at the start of the input. |
| ... | ... | @@ -986,7 +986,7 @@ pub fn utf8ToUtf16Le(utf16le: []u16, utf8: []const u8) !usize { |
| 986 | 986 | var remaining = utf8; |
| 987 | 987 | // Need support for std.simd.interlace |
| 988 | 988 | if (builtin.zig_backend != .stage2_x86_64 and comptime !builtin.cpu.arch.isMIPS()) { |
| 989 | const chunk_len = std.simd.suggestVectorSize(u8) orelse 1; | |
| 989 | const chunk_len = std.simd.suggestVectorLength(u8) orelse 1; | |
| 990 | 990 | const Chunk = @Vector(chunk_len, u8); |
| 991 | 991 | |
| 992 | 992 | // Fast path. Check for and encode ASCII characters at the start of the input. |