From c75fdbc27795f6654a75e6dcdbecefd6fe6bfa9a Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Tue, 7 Nov 2023 22:06:34 -0500 Subject: [PATCH] Reverse Member-of hash lookup --- src/builtins/search.c | 2 +- src/singeli/src/search.singeli | 52 +++++++++++++++++++++------------- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/src/builtins/search.c b/src/builtins/search.c index bd910283..191f2b0c 100644 --- a/src/builtins/search.c +++ b/src/builtins/search.c @@ -370,7 +370,7 @@ B memberOf_c2(B t, B w, B x) { } CHECK_CHRS_ELSE { tyEls: // Both numbers - if (xia>32 && wia<=(xe<=el_i8?1:6)) { + if (xia>32 && wia<=(xe<=el_i8?1:xe==el_i32?4:6)) { SGetU(w); i8* rp; r = m_i8arrc(&rp, w); for (usz i=0; i{t:=a; a=b; b=t}, tup{ip,m}, tup{fp,n}} swap:u1 = 0 - if (prim=='⊒' and (swap = n < m)) { - each{{a,b}=>{t:=a; a=b; b=t}, tup{ip,m}, tup{fp,n}} - } + if ((prim=='⊒' or prim=='∊') and (swap = n < m)) swap_sides{} def stop = m log := clzc{m} @@ -372,11 +371,24 @@ fn hashtab{T, name}(rp:*rty{name}, iv:*void, m:usz, fv:*void, n:usz, links:ity{n def setm{found, i} = has_maxh |= found end := maxh>>sh # Clip trailing maxh if it shouldn't be in the table def usem{} = { - try_vec_memb{T, hash, sz+ext, sh, maxh, has_maxh, rp, fp, n, abort} + if (swap) { + swap_sides{}; i=m # i==m return value is kind of dumb + @for (ip over m) { # Remove values in ip from hash + h := hash_val{ip}; j := h>>sh + if (h == maxh) { has_maxh = 0 } else { + k := load{hash,j} + if (k <= h) { + while (k < h) { ++j; k = load{hash,j} } + if (k==h) hash_remove{j,h} + } + } + } + } + try_vec_memb{T, hash, sz+ext, sh, maxh, has_maxh, swap, rp, fp, n, abort} if (has_maxh) { while (load{hash,end}!=maxh) ++end } else end += promote{T,ext} # Unreachable } - def get{found, j} = promote{i8, found & (j { @@ -454,6 +466,16 @@ fn hashtab{T, name}(rp:*rty{name}, iv:*void, m:usz, fv:*void, n:usz, links:ity{n } } + def hash_remove{j,h} = { + do { + jp:=j; ++j + h=load{hash,j} + if (h>>sh == j) h = maxh + store{hash, jp, h} + each{{t} => store{t, jp, load{t,j}}, vals} + } while (h!=maxh) + } + setlabel{lookup} fixup{} def prog_lookup{swap} = { # Progressive Index-of lookup @@ -471,17 +493,8 @@ fn hashtab{T, name}(rp:*rty{name}, iv:*void, m:usz, fv:*void, n:usz, links:ity{n store{rp, ...rev{i, m-ti}} c -= promote{usz,ti>0}; if (c==0) goto{shortcut} ti = load{link, ti} - if (ti > 0) { - store{inds, j, ti} - } else { - do { - jp:=j; ++j - h=load{hash,j} - if (h>>sh == j) h = maxh - store{hash, jp, h} - store{inds, jp, load{inds,j}} - } while (h!=maxh) - } + if (ti > 0) store{inds, j, ti} + else hash_remove{j,h} } } } @@ -503,7 +516,7 @@ fn hashtab{T, name}(rp:*rty{name}, iv:*void, m:usz, fv:*void, n:usz, links:ity{n } def try_vec_memb{..._} = {} -def try_vec_memb{T, hash, hashlen, sh, maxh, has_maxh, rp, fp, n, done +def try_vec_memb{T, hash, hashlen, sh, maxh, has_maxh, swap, rp, fp, n, done & hasarch{'SSE4.2'} & T==u32} = { # Hash h wants bin h>>sh, so the offset for h in slot i is (in infite-precision ints) # i-h>>sh = i+((1<>sh = (((i+1)<>sh @@ -515,6 +528,7 @@ def try_vec_memb{T, hash, hashlen, sh, maxh, has_maxh, rp, fp, n, done mv := V**0 @for (h in *V~~(hash+o) over nh) { mv=max{mv, io-min{h,io}}; io+=id } max_off := vfold{max, mv} >> sh + vswap := base{256,vl**1} * promote{T,swap} def memb{test} = { def R = i8; def rw = width{R}; def u = width{T}/rw @@ -522,9 +536,9 @@ def try_vec_memb{T, hash, hashlen, sh, maxh, has_maxh, rp, fp, n, done @for (r in *T~~rp over i to l) { c := V**0 # Will combine u results to avoid folding too much @unroll (f in fp+u*i over a to u) c |= V**(1<<(rw*a)) & test{f} - r = vfold{|, c} + r = vswap ^ vfold{|, c} } - @for (rp, fp over _ from u*l to n) rp = promote{R, homAny{test{fp}}} + @for (rp, fp over _ from u*l to n) rp = promote{R, swap ^ homAny{test{fp}}} goto{done} } def try{nv} = {