simd: isa.funcMap to ensure only possible ISAs are analyzed

This commit is contained in:
Mitchell Hashimoto
2024-01-30 12:58:04 -08:00
parent 6523721846
commit 1e51cedd94
3 changed files with 42 additions and 12 deletions

View File

@ -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();

View File

@ -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 {

View File

@ -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 {