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