singeli bit_sel

This commit is contained in:
dzaima 2022-09-08 21:39:51 +03:00
parent d60713225b
commit d3a1fee437
6 changed files with 62 additions and 14 deletions

View File

@ -224,7 +224,7 @@ preSingeliBin:
@${MAKE} i_singeli=0 singeli=0 force_build_dir=obj/presingeli f= lf= postmsg="singeli sources:" i_t=presingeli i_f='-O1 -DPRE_SINGELI' FFI=0 OUTPUT=obj/presingeli/BQN c
build_singeli: ${addprefix src/singeli/gen/, cmp.c dyarith.c copy.c equal.c squeeze.c scan.c slash.c}
build_singeli: ${addprefix src/singeli/gen/, cmp.c dyarith.c copy.c equal.c squeeze.c scan.c slash.c bits.c}
@echo $(postmsg)
src/singeli/gen/%.c: src/singeli/src/%.singeli preSingeliBin
@echo $< | cut -c 17- | sed 's/^/ /'

View File

@ -60,3 +60,7 @@ def spreadBits{T, a & vcount{T} <= width{eltype{T}} & w256u{T}} = {
b:= make{T, 1<<iota{vcount{T}}}
b == (b & broadcast{T, a})
}
def loadBatchBit{T, x:*u64, n:(Size)} = { # vector with type T with each element being either all 0s or 1s
spreadBits{T, b_getBatch{vcount{T}, x, n}}
}

View File

@ -0,0 +1,30 @@
include './base'
include './f64'
include './cbqnDefs'
include './sse3'
include './avx'
include './avx2'
include './bitops'
include './mask'
def bitsel{VL, T, r, bits, e0, e1, len} = {
def bulk = VL/width{T}
def VT = [bulk]T
e0v:= broadcast{VT, e0}
e1v:= broadcast{VT, e1}
maskedLoop{bulk, len, {i, M} => {
cb:= loadBatchBit{VT, bits, i}
storeBatch{r, i, blendF{e0v, e1v, cb}, M}
}}
}
bitsel_i{VL,T}(r:*u8, bits:*u64, e0:u64, e1:u64, len:u64) : void = {
bitsel{VL, T, *T~~r, bits, trunc{T,e0}, trunc{T,e1}, len}
}
'avx2_bitsel_8' =bitsel_i{256, u8}
'avx2_bitsel_16'=bitsel_i{256, u16}
'avx2_bitsel_32'=bitsel_i{256, u32}
'avx2_bitsel_64'=bitsel_i{256, u64}

View File

@ -11,9 +11,8 @@ def copyFromBits{T, xp: *u64, rp: *eltype{T}, l:u64} = {
def TU = ty_u{T}
maskedLoop{bulk, l, {i, M} => {
x:= b_getBatch{bulk, xp, i} # TODO unroll f64 by two to make b_getBatch not sad
y:= spreadBits{TU, x}
r:= y & TU~~broadcast{T, 1}
x:= loadBatchBit{TU, xp, i}
r:= x & TU~~broadcast{T, 1}
storeBatch{rp, i, T~~r, M}
}}
}

View File

@ -25,10 +25,6 @@ def rootty{T & isvec{T}} = eltype{T}
def is_s{X} = issigned{rootty{X}}
def is_u{X} = isunsigned{rootty{X}}
def loadBatchBit{T, x:*u64, n:(Size)} = {
spreadBits{T, b_getBatch{vcount{T}, x, n}}
}
def ty_sc{O, R} = R # keep floats as-is
def ty_sc{O, R & is_s{O} & is_u{R}} = ty_s{R}
def ty_sc{O, R & is_u{O} & is_s{R}} = ty_u{R}

View File

@ -1,5 +1,20 @@
#include "../core.h"
#if SINGELI
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
#include "../singeli/gen/bits.c"
#pragma GCC diagnostic pop
typedef void (*BitselFn)(u8*, u64*, u64, u64, u64);
static BitselFn bitselFns[] = {
[0]=avx2_bitsel_8,
[1]=avx2_bitsel_16,
[2]=avx2_bitsel_32,
[3]=avx2_bitsel_64,
};
#endif
NOINLINE Arr* allZeroes(usz ia) { u64* rp; Arr* r = m_bitarrp(&rp, ia); for (usz i = 0; i < BIT_N(ia); i++) rp[i] = 0; return r; }
NOINLINE Arr* allOnes (usz ia) { u64* rp; Arr* r = m_bitarrp(&rp, ia); for (usz i = 0; i < BIT_N(ia); i++) rp[i] = ~0ULL; return r; }
@ -45,12 +60,16 @@ NOINLINE B bit_sel(B b, B e0, B e1) {
sel:
void* rp = m_tyarrlc(&r, width, b, type);
switch(width) {
case 0: for (usz i=0; i<ia; i++) (( u8*)rp)[i] = bitp_get(bp,i)? e1i : e0i; break;
case 1: for (usz i=0; i<ia; i++) ((u16*)rp)[i] = bitp_get(bp,i)? e1i : e0i; break;
case 2: for (usz i=0; i<ia; i++) ((u32*)rp)[i] = bitp_get(bp,i)? e1i : e0i; break;
case 3: for (usz i=0; i<ia; i++) ((u64*)rp)[i] = bitp_get(bp,i)? e1i : e0i; break;
}
#if SINGELI
bitselFns[width](rp, bp, e0i, e1i, ia);
#else
switch(width) {
case 0: for (usz i=0; i<ia; i++) (( u8*)rp)[i] = bitp_get(bp,i)? e1i : e0i; break;
case 1: for (usz i=0; i<ia; i++) ((u16*)rp)[i] = bitp_get(bp,i)? e1i : e0i; break;
case 2: for (usz i=0; i<ia; i++) ((u32*)rp)[i] = bitp_get(bp,i)? e1i : e0i; break;
case 3: for (usz i=0; i<ia; i++) ((u64*)rp)[i] = bitp_get(bp,i)? e1i : e0i; break;
}
#endif
goto dec_ret;
}