diff options
| author | Mitchell Hashimoto <mitchell.hashimoto@gmail.com> | 2024-01-30 12:58:04 -0800 |
|---|---|---|
| committer | Mitchell Hashimoto <mitchell.hashimoto@gmail.com> | 2024-02-05 21:22:04 -0800 |
| commit | 1e51cedd949a15b221c27bc3697c77fb511f75c5 (patch) | |
| tree | 8a4c190596b91942692a56df3be587cb0a8584dd /src/simd | |
| parent | 6523721846a34f6fa73bb86569eec2078537f908 (diff) | |
simd: isa.funcMap to ensure only possible ISAs are analyzed
Diffstat (limited to 'src/simd')
| -rw-r--r-- | src/simd/isa.zig | 34 | ||||
| -rw-r--r-- | src/simd/utf8_count.zig | 10 | ||||
| -rw-r--r-- | src/simd/utf8_validate.zig | 10 |
3 files changed, 42 insertions, 12 deletions
diff --git a/src/simd/isa.zig b/src/simd/isa.zig index 8f42be53c..55a77162a 100644 --- a/src/simd/isa.zig +++ b/src/simd/isa.zig @@ -120,15 +120,45 @@ fn detectX86(set: *Set) void { } /// Check if a bit is set at the given offset -pub inline fn hasBit(input: u32, offset: u5) bool { +inline fn hasBit(input: u32, offset: u5) bool { return (input >> offset) & 1 != 0; } /// Checks if a mask exactly matches the input -pub inline fn hasMask(input: u32, mask: u32) bool { +inline fn hasMask(input: u32, mask: u32) bool { return (input & mask) == mask; } +/// This is a helper to provide a runtime lookup map for the ISA to +/// the proper function implementation. Func is the function type, +/// and map is an array of tuples of the form (ISA, Struct) where +/// Struct has a decl named `name` that is a Func. +/// +/// The slightly awkward parameters are to ensure that functions +/// are only analyzed for possible ISAs for the target. +/// +/// This will ensure that impossible ISAs for the build target are +/// not included so they're not analyzed. For example, a NEON implementation +/// will not be included on x86_64. +pub fn funcMap( + comptime Func: type, + comptime name: []const u8, + v: ISA, + comptime map: anytype, +) *const Func { + switch (v) { + inline else => |tag| { + // If this tag isn't possible, compile no code for this case. + if (comptime !possible(tag)) unreachable; + + // Find the entry for this tag and return the function. + inline for (map) |entry| { + if (entry[0] == tag) return @field(entry[1], name); + } else unreachable; + }, + } +} + test "detect" { const testing = std.testing; const set = detect(); diff --git a/src/simd/utf8_count.zig b/src/simd/utf8_count.zig index 98e4c77d1..a463654d2 100644 --- a/src/simd/utf8_count.zig +++ b/src/simd/utf8_count.zig @@ -9,11 +9,11 @@ pub const Count = fn ([]const u8) usize; /// Returns the count function for the given ISA. pub fn countFunc(v: isa.ISA) *const Count { - return switch (v) { - .avx2 => &Scalar.count, // todo - .neon => &Neon.count, - .scalar => &Scalar.count, - }; + return isa.funcMap(Count, "count", v, .{ + .{ .avx2, Scalar }, // todo + .{ .neon, Neon }, + .{ .scalar, Scalar }, + }); } pub const Scalar = struct { diff --git a/src/simd/utf8_validate.zig b/src/simd/utf8_validate.zig index af86b5230..c152d2086 100644 --- a/src/simd/utf8_validate.zig +++ b/src/simd/utf8_validate.zig @@ -12,11 +12,11 @@ const Validate = fn ([]const u8) bool; // - https://simdutf.github.io/simdutf/ (MIT License) pub fn validateFunc(v: isa.ISA) *const Validate { - return switch (v) { - .avx2 => &Scalar.validate, // todo - .neon => &Neon.validate, - .scalar => &Scalar.validate, - }; + return isa.funcMap(Validate, "validate", v, .{ + .{ .avx2, Scalar }, // todo + .{ .neon, Neon }, + .{ .scalar, Scalar }, + }); } pub const Scalar = struct { |
