authorgravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-07-02 02:35:49-07:00
committergravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-07-14 23:02:33-07:00
logf2301ba896bd522483e987ecebe72bdcd86705ba
tree2ef1e25a425ceeaf5b50830aab8e00db2c714fb8
parent3e73f37d0a371276c534240ee2d26cbf4b3a0033
signaturelock-open Commit is signed but in an unrecognized format.

simd: correct suggestVectorLength

* the file's doc-comment was misleading and did not focus on the correct aspect of SIMD * added cpu flag awareness to `suggestVectorLengthForCpu` in order to provide a more accurate vector length

1 files changed, 32 insertions(+), 4 deletions(-)

lib/std/simd.zig+32-4
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1//! SIMD (Single Instruction; Multiple Data) convenience functions.1//! SIMD (Single Instruction; Multiple Data) convenience functions.
2//!2//!
3//! May offer a potential boost in performance on some targets by performing3//! May offer a potential boost in performance on some targets by performing
4//! the same operations on multiple elements at once.4//! the same operation on multiple elements at once.
5//!5//!
6//! Some functions are known to not work on MIPS.6//! Some functions are known to not work on MIPS.
77
...@@ -10,7 +10,6 @@ const builtin = @import("builtin");...@@ -10,7 +10,6 @@ const builtin = @import("builtin");
1010
11pub fn suggestVectorLengthForCpu(comptime T: type, comptime cpu: std.Target.Cpu) ?comptime_int {11pub fn suggestVectorLengthForCpu(comptime T: type, comptime cpu: std.Target.Cpu) ?comptime_int {
12 // This is guesswork, if you have better suggestions can add it or edit the current here12 // This is guesswork, if you have better suggestions can add it or edit the current here
13 // This can run in comptime only, but stage 1 fails at it, stage 2 can understand it
14 const element_bit_size = @max(8, std.math.ceilPowerOfTwo(u16, @bitSizeOf(T)) catch unreachable);13 const element_bit_size = @max(8, std.math.ceilPowerOfTwo(u16, @bitSizeOf(T)) catch unreachable);
15 const vector_bit_size: u16 = blk: {14 const vector_bit_size: u16 = blk: {
16 if (cpu.arch.isX86()) {15 if (cpu.arch.isX86()) {
...@@ -37,8 +36,37 @@ pub fn suggestVectorLengthForCpu(comptime T: type, comptime cpu: std.Target.Cpu)...@@ -37,8 +36,37 @@ pub fn suggestVectorLengthForCpu(comptime T: type, comptime cpu: std.Target.Cpu)
37 // the 2048 bits or using just 64 per vector or something in between36 // the 2048 bits or using just 64 per vector or something in between
38 if (std.Target.mips.featureSetHas(cpu.features, std.Target.mips.Feature.mips3d)) break :blk 64;37 if (std.Target.mips.featureSetHas(cpu.features, std.Target.mips.Feature.mips3d)) break :blk 64;
39 } else if (cpu.arch.isRISCV()) {38 } else if (cpu.arch.isRISCV()) {
40 // in risc-v the Vector Extension allows configurable vector sizes, but a standard size of 128 is a safe estimate39 // In RISC-V Vector Registers are length agnostic so there's no good way to determine the best size.
41 if (std.Target.riscv.featureSetHas(cpu.features, .v)) break :blk 128;40 // The usual vector length in most RISC-V cpus is 256 bits, however it can get to multiple kB.
41 if (std.Target.riscv.featureSetHas(cpu.features, .v)) {
42 var vec_bit_length: u32 = 256;
43 if (std.Target.riscv.featureSetHas(cpu.features, .zvl32b)) {
44 vec_bit_length = 32;
45 } else if (std.Target.riscv.featureSetHas(cpu.features, .zvl64b)) {
46 vec_bit_length = 64;
47 } else if (std.Target.riscv.featureSetHas(cpu.features, .zvl128b)) {
48 vec_bit_length = 128;
49 } else if (std.Target.riscv.featureSetHas(cpu.features, .zvl256b)) {
50 vec_bit_length = 256;
51 } else if (std.Target.riscv.featureSetHas(cpu.features, .zvl512b)) {
52 vec_bit_length = 512;
53 } else if (std.Target.riscv.featureSetHas(cpu.features, .zvl1024b)) {
54 vec_bit_length = 1024;
55 } else if (std.Target.riscv.featureSetHas(cpu.features, .zvl2048b)) {
56 vec_bit_length = 2048;
57 } else if (std.Target.riscv.featureSetHas(cpu.features, .zvl4096b)) {
58 vec_bit_length = 4096;
59 } else if (std.Target.riscv.featureSetHas(cpu.features, .zvl8192b)) {
60 vec_bit_length = 8192;
61 } else if (std.Target.riscv.featureSetHas(cpu.features, .zvl16384b)) {
62 vec_bit_length = 16384;
63 } else if (std.Target.riscv.featureSetHas(cpu.features, .zvl32768b)) {
64 vec_bit_length = 32768;
65 } else if (std.Target.riscv.featureSetHas(cpu.features, .zvl65536b)) {
66 vec_bit_length = 65536;
67 }
68 break :blk vec_bit_length;
69 }
42 } else if (cpu.arch.isSPARC()) {70 } else if (cpu.arch.isSPARC()) {
43 // TODO: Test Sparc capability to handle bigger vectors71 // TODO: Test Sparc capability to handle bigger vectors
44 // In theory Sparc have 32 registers of 64 bits which can use in parallel72 // In theory Sparc have 32 registers of 64 bits which can use in parallel