summaryrefslogtreecommitdiff
path: root/src/simd
diff options
context:
space:
mode:
authorMitchell Hashimoto <mitchell.hashimoto@gmail.com>2024-01-30 12:58:04 -0800
committerMitchell Hashimoto <mitchell.hashimoto@gmail.com>2024-02-05 21:22:04 -0800
commit1e51cedd949a15b221c27bc3697c77fb511f75c5 (patch)
tree8a4c190596b91942692a56df3be587cb0a8584dd /src/simd
parent6523721846a34f6fa73bb86569eec2078537f908 (diff)
simd: isa.funcMap to ensure only possible ISAs are analyzed
Diffstat (limited to 'src/simd')
-rw-r--r--src/simd/isa.zig34
-rw-r--r--src/simd/utf8_count.zig10
-rw-r--r--src/simd/utf8_validate.zig10
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 {