Reverse lookup initialization for 1-byte Member-of

This commit is contained in:
Marshall Lochbaum 2023-04-24 16:29:30 -04:00
parent 0232f91582
commit e45231154c

View File

@ -97,12 +97,7 @@ def bittab_selector{loadtab} = {
tup{selector, reload} tup{selector, reload}
} }
fn avx2_member_u8(w0:*void, nw:u64, x0:*void, nx:u64, r0:*void, tab:*void) : void = { def readbytes{vtab}{} = {
assert{nw > 0}
vtab:= *VI~~tab; btab:= *i8~~tab
z:= VI**0
@unroll (vtab over 8) vtab = z
def readbytes{} = {
def side{i} = { def side{i} = {
def m = @collect (vtab over _ from i to i+4) homMask{vtab} def m = @collect (vtab over _ from i to i+4) homMask{vtab}
VI~~make{[8]u32, merge{m,m}} VI~~make{[8]u32, merge{m,m}}
@ -110,39 +105,60 @@ fn avx2_member_u8(w0:*void, nw:u64, x0:*void, nx:u64, r0:*void, tab:*void) : voi
each{side, 4*iota{2}} each{side, 4*iota{2}}
} }
# Fill table # Fill table with t (0 or -1) at all bytes in x0
u:u8 = 0 # Unseen unique bytes (goes to 255 on first step) # Stop early if the sum u reaches 0, indicating all bytes in the table
w:= *u8~~w0 # are equal: by the time it's checked at least one has been set to t,
iw:u64 = 32; if (nw<=48) iw=nw # so they're all t
@for (w over iw) { fn fill_bittab(x0:*void, n:u64, tab:*void, u:u8, t:i8) : u8 = {
u-= 1 + u8~~load{btab, w} # Subtract 1 if new btab:= *i8~~tab
store{btab, w, -1} def settab{x} = {
u+= u8~~(t - load{btab, x}) # u tracks the total of btab
store{btab, x, t}
} }
def {bitsel, reload_tab} = bittab_selector{readbytes} x:= *u8~~x0
wv:= *VI~~w0 i:u64 = 32; if (n<=48) i=n
while (iw < nw) { @for (x over i) settab{x}
ii:= iw+32 if (u == 0) return{u} # Won't ever trigger (m != 0)!
m:= bitsel{load{wv, iw/32}} def {bitsel, reload_tab} = bittab_selector{readbytes{*VI~~tab}}
if (ii > nw) { ii=nw; m|=(~u32~~0)<<(nw%32) } xv:= *VI~~x0
m = ~m while (i < n) {
ii:= i+32
m:= bitsel{load{xv, i/32}}
if (ii > n) { ii=n; m|=(~u32~~0)<<(n%32) }
m^= u32~~cast_i{i32, t}
if (m != 0) { # Need to add entries if (m != 0) { # Need to add entries
do { do {
wj:= load{w, iw+emit{u64, 'CTZ', m}} settab{load{x, i+emit{u64, 'CTZ', m}}}
u-= 1 + u8~~load{btab, wj} # Subtract 1 if new
store{btab, wj, -1}
m&= m-1 # Clear last bit m&= m-1 # Clear last bit
} while (m != 0) } while (m != 0)
if (u == 0) return{u} # Table is all one value
reload_tab{}
}
i = ii
}
u
}
fn avx2_member_u8(w0:*void, nw:u64, x0:*void, nx:u64, r0:*void, tab:*void) : void = {
assert{nw > 0}
vtab:= *VI~~tab
# Initialize
rev:u1 = nx < nw/4 # Reverse lookup
z:= VI**(-cast_i{i8,rev})
@unroll (vtab over 8) vtab = z
u:u8 = 0 # Sum of table, either 0 or 256
if (rev) u = fill_bittab(x0, nx, tab, u, 0)
# Fill table
u = fill_bittab(w0, nw, tab, u, -1)
if (u == 0) { # All found! if (u == 0) { # All found!
@for (r in *u64~~r0 over cdiv{nx,64}) r = maxvalue{u64} @for (r in *u64~~r0 over cdiv{nx,64}) r = maxvalue{u64}
return{} return{}
} }
reload_tab{}
}
iw = ii
}
# Read result # Read result
def {bitsel, _} = bittab_selector{readbytes{vtab}}
@for (x in *VI~~x0, r in *u32~~r0 over cdiv{nx,32}) r = bitsel{x} @for (x in *VI~~x0, r in *u32~~r0 over cdiv{nx,32}) r = bitsel{x}
} }