Specialize Index-of tables on result type

This commit is contained in:
Marshall Lochbaum 2023-11-10 15:41:57 -05:00
parent b782693d15
commit 3a50cda5d3
3 changed files with 25 additions and 14 deletions

View File

@ -17,10 +17,12 @@
// p⊐n & n∊p with boolean p: based on ⊑p and p⊐¬⊑p
// p⊐n & n∊p with short p:
// AVX2 binary search when applicable
// SHOULD apply vector binary search to characters (sort as ints)
// n⊸=¨p otherwise
// ≤16-bit elements: lookup tables
// 8-bit ∊ and ⊐: SSSE3 table
// SHOULD make 8-bit NEON table
// SHOULD have branchy reverse 16-bit table search
// 32- or 64-bit elements: hash tables
// Store hash in table and not element; Robin Hood ordering; resizing
// Reverse hash if searched-for is shorter
@ -35,9 +37,12 @@
#include "../utils/talloc.h"
#include "../utils/calls.h"
// From selfsearch.c
extern NOINLINE void memset32(u32* p, u32 v, usz l);
extern NOINLINE void memset64(u64* p, u64 v, usz l);
extern NOINLINE void memset16(u16* p, u16 v, usz l) { for (usz i=0; i<l; i++) p[i]=v; }
extern NOINLINE void memset32(u32* p, u32 v, usz l) { for (usz i=0; i<l; i++) p[i]=v; }
extern NOINLINE void memset64(u64* p, u64 v, usz l) { for (usz i=0; i<l; i++) p[i]=v; }
#define memset_i8 memset
#define memset_i16(P,V,L) memset16((u16*)(P), V, L)
#define memset_i32(P,V,L) memset32((u32*)(P), V, L)
RangeFn getRange_fns[el_f64+1];
#if SINGELI
@ -97,7 +102,7 @@ static u64 elRange(u8 eltype) { return 1ull<<(1<<elwBitLog(eltype)); }
if (IN.u != FOR.u) { \
if (FOR##e==el_i16 && n<ft/(64/sizeof(TY))) \
{ for (usz i=0; i<n; i++) tab[((i16*)fp)[i]]=INIT; } \
else { TY* to=tab-(ft/2-(ft==2)); for (i64 i=0; i<ft; i++) to[i]=INIT; } \
else { memset_##TY(tab-(ft/2-(ft==2)), INIT, ft); } \
} \
/* Set */ \
if (IN##e==el_i8) { for (usz i=m; i--; ) tab[((i8 *)ip)[i]]=SET; } \
@ -284,7 +289,7 @@ B indexOf_c2(B t, B w, B x) {
}
#if SINGELI_AVX2
if (xia>=32 && wia>1 && el_i8<=xe && xe<=el_i32 && wia<64>>(xe-el_i8) && we<=xe && !elChr(TI(x,elType))) {
if (xia>=32 && wia>1 && el_i8<=xe && xe<=el_i32 && wia<(xe==el_i8?64:16) && we<=xe && !elChr(TI(x,elType))) {
B g = C1(reverse, C1(gradeDown, incG(w)));
w = C2(select, incG(g), w);
switch (xe) { default:UD; case el_i8:w=toI8Any(w);break; case el_i16:w=toI16Any(w);break; case el_i32:w=toI32Any(w);break; }
@ -304,21 +309,26 @@ B indexOf_c2(B t, B w, B x) {
}
if (xia+wia>20 && we<=el_i16 && xe<=el_i16) {
B r;
#if SINGELI
if (wia>256 && we==el_i8 && xe==el_i8) {
TALLOC(u8, tab, 256*(1+sizeof(usz))); usz* ind = (usz*)(tab+256);
void* fp = tyany_ptr(x);
simd_index_tab_u8(tyany_ptr(w), wia, fp, xia, tab, ind);
decG(w);
i32* rp; B r = m_i32arrc(&rp, x);
for (usz i=0; i<xia; i++) rp[i]=ind[((u8*)fp)[i]];
#define LOOKUP(TY) \
TY* rp; r = m_##TY##arrc(&rp, x); \
for (usz i=0; i<xia; i++) rp[i]=ind[((u8*)fp)[i]];
if (wia<=INT16_MAX) { LOOKUP(i16) } else { LOOKUP(i32) }
#undef LOOKUP
TFREE(tab); decG(x);
return reduceI32Width(r, wia);
return r;
}
#endif
B r;
TABLE(w, x, i32, wia, i)
return reduceI32Width(r, wia);
if (wia<= INT8_MAX) { TABLE(w, x, i8, wia, i) }
else if (wia<=INT16_MAX) { TABLE(w, x, i16, wia, i) }
else { TABLE(w, x, i32, wia, i) }
return r;
}
#if SINGELI
if (we==xe && (we==el_i32 || (we==el_f64 && (split || canCompare64_norm(&w,wia,&x,xia))))) {

View File

@ -43,8 +43,9 @@ extern B mul_c2(B, B, B);
extern B scan_add_bool(B x, u64 ia);
extern B scan_max_num(B x, u8 xe, u64 ia);
extern NOINLINE void memset32(u32* p, u32 v, usz l) { for (usz i=0; i<l; i++) p[i]=v; }
extern NOINLINE void memset64(u64* p, u64 v, usz l) { for (usz i=0; i<l; i++) p[i]=v; }
// From search.c
extern NOINLINE void memset32(u32* p, u32 v, usz l);
extern NOINLINE void memset64(u64* p, u64 v, usz l);
#if SINGELI
#define SINGELI_FILE selfsearch

View File

@ -305,7 +305,7 @@ if (hasarch{'AVX2'}) {
}
exportT{
'avx2_indexOf_sort',
each{avx2_search_bin{'⊐',.,.}, tup{i8,i16,i32}, tup{64,32,16}}
each{avx2_search_bin{'⊐',.,.}, tup{i8,i16,i32}, tup{64,16,16}}
}
}