Replace tuplen{} and tupsel{} with length{} and select{}

This commit is contained in:
Marshall Lochbaum 2024-05-10 09:49:58 -04:00
parent 12d7629f9c
commit 4d6612cb16
17 changed files with 60 additions and 60 deletions

View File

@ -148,10 +148,10 @@ Some may also support one scalar argument or arguments with different widths.
<!-- -->
- `zip{a:T,b:T} : tup{T, T}` - `zip{[0,1,2,3], [4,5,6,7]} → tup{[0,4,1,5], [2,6,3,7]}`
- `mzip{a:T,b:T} : tup{el_dbl{T}, el_dbl{T}}` - reinterpreted `zip{a, b}`
- `zipLo{a:T,b:T} : T` - `tupsel{0, zip{a, b}}`
- `zipHi{a:T,b:T} : T` - `tupsel{1, zip{a, b}}`
- `mzipLo{a:T,b:T} : T` - `tupsel{0, mzip{a, b}}`
- `mzipHi{a:T,b:T} : T` - `tupsel{1, mzip{a, b}}`
- `zipLo{a:T,b:T} : T` - `select{zip{a, b}, 0}`
- `zipHi{a:T,b:T} : T` - `select{zip{a, b}, 1}`
- `mzipLo{a:T,b:T} : T` - `select{mzip{a, b}, 0}`
- `mzipHi{a:T,b:T} : T` - `select{mzip{a, b}, 1}`
## Mask stuff
@ -353,4 +353,4 @@ bmi2.singeli
clmul.singeli
clmul
-->
-->

View File

@ -42,7 +42,7 @@ def storeu{p:T, v:(eltype{T}) & elwidth{T}==8} = store{p, v}
def reinterpret{T, x:X & T==X} = x
def exportN{f, ...ns} = each{export{.,f}, ns}
def exportT{name, fs} = { v:*type{tupsel{0,fs}} = fs; export{name, v} }
def exportT{name, fs} = { v:*type{select{fs,0}} = fs; export{name, v} }
# hints
@ -151,7 +151,7 @@ def collect{vars,begin,end,iter & knum{begin} & knum{end}} = {
}
# convert tuple to number in little-endian base b
def base{b,l} = if (0==tuplen{l}) 0 else tupsel{0,l}+b*base{b,slice{l,1}}
def base{b,l} = if (0==length{l}) 0 else select{l,0}+b*base{b,slice{l,1}}
@ -176,8 +176,8 @@ def {
def homMaskX{a:T} = tup{1, homMask{a}} # tup{n,mask}; mask with each bit repeated n times
def ctzX{{n,v}} = ctz{v}/n # ctz for a result of homMaskX
def homMask{...vs & tuplen{vs}>1} = {
def n = tuplen{vs}
def homMask{...vs & length{vs}>1} = {
def n = length{vs}
def T = oneType{vs}
def RT = ty_u{max{8,vcount{T}*n}}
def a = promote{RT, homMask{...slice{vs,0,n/2}}}
@ -319,13 +319,13 @@ def makeOptBranch{enable, Ts, F} = if (enable) makeBranch{Ts, F} else 'not defin
def tree_fold{F, x} = {
def h = tuplen{x}>>1
F{tree_fold{F, slice{x,0,h}}, tree_fold{F, slice{x,h,tuplen{x}}}}
def h = length{x}>>1
F{tree_fold{F, slice{x,0,h}}, tree_fold{F, slice{x,h,length{x}}}}
}
def tree_fold{F, {x}} = x
def eachx{F, ...args} = {
def l = tree_fold{max, each{{x} => if(ktup{x}) tuplen{x} else 0, args}}
def l = tree_fold{max, each{{x} => if(ktup{x}) length{x} else 0, args}}
each{F, ...each{{x} => if (istup{x}) x else l**x, args}}
}

View File

@ -74,7 +74,7 @@ def get_rtype{len} = {
}
def rtype_arr{gen} = {
def t = each{gen, rtypes}
a:*(type{tupsel{0,t}}) = t
a:*(type{select{t,0}}) = t
}
# Write the last index of v at t+v, for each unique v in w
@ -230,7 +230,7 @@ def bin_search_vec{prim, T, w:*T, wn, x:*T, xn, rp, maxwn & hasarch{'AVX2'}} = {
def un = uninterleave
def tr_half{a, b} = each{shufHalves{a,b,.}, tup{16b20, 16b31}}
def un{{a,b}} = tr_half{un{a},un{b}}
if (not lanes) tupsel{1,wv} = load{wg, 1}
if (not lanes) select{wv,1} = load{wg, 1}
wv = un{wv}
if (ex>=2 and wn >= 2*svl) {
assert{lanes} # Different transpose pattern needed
@ -238,7 +238,7 @@ def bin_search_vec{prim, T, w:*T, wn, x:*T, xn, rp, maxwn & hasarch{'AVX2'}} = {
tup{wv, wv2} = each{un, tr_half{wv, un{load{wg, 1}}}}
}
}
def ms{v}{h} = getsel{re_el{I, if (lanes) half{v,h} else tupsel{h,v}}}
def ms{v}{h} = getsel{re_el{I, if (lanes) half{v,h} else select{v,h}}}
def selw = ms{wv}{0}; def selw1 = if (ex>=1) ms{wv}{1} else 'undef'
def selw2 = if (ex>=2) each{ms{wv2}, iota{2}} else 'undef'
# Offset at end
@ -257,7 +257,7 @@ def bin_search_vec{prim, T, w:*T, wn, x:*T, xn, rp, maxwn & hasarch{'AVX2'}} = {
def cmpx{cmp}{se,ind} = cmp{xv, V~~se{re_el{I,ind}}}
def ltx = cmpx{lt}; def eqx = cmpx{==}
@unroll (j to klog) {
m := s | tupsel{klog-1-j,bits}
m := s | select{bits,klog-1-j}
s = homBlend{m, s, ltx{selw, m}}
}
r := if (isub==1) s else s>>(lb{isub}+wd-wi)
@ -345,8 +345,8 @@ def bin_search_branchless{up, w, wn, x, n, res, rtype} = {
fn bins{T, up}(w:*void, wn:u64, x:*void, xn:u64, rp:*void, rty:u8) : void = {
def param = tup{up, *T~~w, wn, *T~~x, xn, rp}
def lookup{k} = {
if (rty == k) bins_lookup{tupsel{k,rtypes}, T, ...param}
else if (k+1 < tuplen{rtypes}) lookup{k+1}
if (rty == k) bins_lookup{select{rtypes,k}, T, ...param}
else if (k+1 < length{rtypes}) lookup{k+1}
}
# For >=8 i8 values, vector bit-table is as good as binary search
def wn_vec = if (T==i8) 8 else 2*256/width{T}
@ -377,7 +377,7 @@ fn saturate{F,T,...up}(dst:*void, src:*void, n:u64) : void = {
def a = minvalue{T}; af := cast_i{F,a}
def b = maxvalue{T}; bf := cast_i{F,b}
@for (d in *T~~dst, xf in *F~~src over n) {
x := if (F==f64) (if (tupsel{0,up}) floor else ceil){xf} else xf
x := if (F==f64) (if (select{up,0}) floor else ceil){xf} else xf
d = cast_i{T, x}
if (x<af) d = a
if (x>bf) d = b

View File

@ -94,10 +94,10 @@ def loaduBitTrunc{x:(*u64), i, n & knum{n}} = truncBits{n, loaduBit{x, i, n}}
def loadBatchBit{T, x:(*u64), is & ktup{is}} = {
# def len = tuplen{is}
# def len = length{is}
# def count = vcount{T}
# assert{count*len <= 64}
# bits:= b_getBatchLo{count*len, x, tupsel{0,is}}
# bits:= b_getBatchLo{count*len, x, select{is,0}}
# @collect(i to len) spreadBits{T, truncBits{count, bits>>(i*count)}}
each{loadBatchBit{T, x, .}, is}
}

View File

@ -46,7 +46,7 @@ fn count{T}(tab:*usz, x:*T, n:u64, min_allowed:T) : T = {
total := trunc{usz, r0} # To compute last count
def count_each{js, num} = {
j := @collect (k to num) trunc{T, js+k}
c := copy{tuplen{j}, [vec]uT ** 0}
c := copy{length{j}, [vec]uT ** 0}
e := each{{j}=>V**j, j}
@for (xv over b) each{{c,e} => c -= xv == e, c, e}
def add_sum{c, j} = {

View File

@ -107,7 +107,7 @@ def runner{u, R, F} = {
}
# homAny, topAny already give masked vals; anyne doesn't, and ~andAllZero assumes no masking
def runChecks_any{F, vals} = { F{tree_fold{|, each{tupsel{1,.}, vals}}} }
def runChecks_any{F, vals} = { F{tree_fold{|, each{select{.,1}, vals}}} }
def runChecks{type=='homAny', vals, M} = runChecks_any{homAny, vals}
def runChecks{type=='topAny', vals, M} = runChecks_any{topAny, vals}
def runChecks{type=='none', vals, M} = 0
@ -124,8 +124,8 @@ def runChecks{type=='anyne', vals, M} = {
def arithProcess{F, run, overflow, M, is, cw, cx, TY} = {
def {values, checks} = flip{each{{w1, x1} => run{F, M, w1, x1}, cw, cx}}
def ctype = oneVal{each{tupsel{0,.}, checks}}
if (rare{runChecks{ctype, checks, M}}) overflow{tupsel{0,is}*vcount{TY}}
def ctype = oneVal{each{select{.,0}, checks}}
if (rare{runChecks{ctype, checks, M}}) overflow{select{is,0}*vcount{TY}}
each{{c} => TY~~c, values}
}
@ -187,7 +187,7 @@ fn arithSAf{vw, mode, F, swap, W, X, R}(r:*void, w:u64, x:*void, len:u64) : u64
def unr = tern{mode>=2, 2, 1} # same as in arithAAimpl
@muLoop{bulk, unr}(sr in tup{'g',*R~~r}, cx in tup{ty_sc{X,TY},*X~~x}, M in 'm' over is to len) {
def cws = tuplen{is}**cw
def cws = length{is}**cw
sr{arithProcess{F, run, overflow, M, is, tern{swap,cx,cws}, tern{swap,cws,cx}, TY}}
}

View File

@ -39,7 +39,7 @@ def hash_val{x:(u32) & hasarch{'SSE4.2'}} = {
# Allocates the maximum at the start, resizes downwards within the existing allocation
def hash_alloc{logsz, msz, ext, Ts, v0s, has_radix, ordered} = {
def ws = each{width,Ts}
def wt = tupsel{0,ws}
def wt = select{ws,0}
each{assert, slice{ws,0,-1} >= slice{ws,1}} # Doesn't do alignment
# Variables updated on resize
sz := usz~~1 << logsz
@ -61,7 +61,7 @@ def hash_alloc{logsz, msz, ext, Ts, v0s, has_radix, ordered} = {
sh -= m; sz <<= m
set_thresh{}
cc = 0 # Collision counter
k:tupsel{0,Ts} = 0; --k # Index where to move an element to
k:select{Ts,0} = 0; --k # Index where to move an element to
each{{p,v} => { p -= dif; memset{p, v, dif} }, ptrs, v0s}
def {hash, ...vals} = ptrs; def {h0, ...v0r} = v0s
s := sz+ext

View File

@ -9,7 +9,7 @@ fn absFn{T}(r:*void, x:*void, len:u64) : u64 = {
def bulk = arch_defvw/width{T}
def VT = [bulk]T
@muLoop{bulk, tern{T==f64, 2, 1}}(cx in tup{VT,*T~~x}, sr in tup{'g',*T~~r}, M in 'm' over is to len) {
if (T!=f64 and homAny{M{tree_fold{|, eachx{==, cx, VT**minvalue{T}}}}}) return{tupsel{0,is}*bulk}
if (T!=f64 and homAny{M{tree_fold{|, eachx{==, cx, VT**minvalue{T}}}}}) return{select{is,0}*bulk}
sr{each{abs, cx}}
}
len

View File

@ -140,7 +140,7 @@ def homMask{a:T,b:T,c:T,d:T & T==[16]u8} = {
t3:= addp{t1, t2}
extract{[2]u64~~addp{t3,t3},0}
}
def homMask{...as & tuplen{as}>1 & elwidth{type{tupsel{0,as}}}>=32} = homMask{...each{{i}=>narrowPair{tupsel{i*2,as},tupsel{i*2+1,as}}, iota{tuplen{as}/2}}}
def homMask{...as & length{as}>1 & elwidth{type{select{as,0}}}>=32} = homMask{...each{{i}=>narrowPair{select{as,i*2},select{as,i*2+1}}, iota{length{as}/2}}}
def homMask{a:T,b:T & vcount{T}*2<=elwidth{T}} = {
def n = vcount{T}
truncBits{n*2, fold_add{shrm{a,elwidth{T}-n,b} & make{T, (1<<iota{n}) | (1<<(iota{n}+n))}}}

View File

@ -116,7 +116,7 @@ def read_shuf_vecs{l, ellw:(u64), shp:P} = { # tuple of byte selectors in 1<<ell
def sh = each{{v}=>{r:=v}, l**V**0}
def tlen{e} = cdiv{l, e} # Length for e bytes, rounded up
def set{i} = { tupsel{i,sh} = each{load{shp,.}, i} }
def set{i} = { select{sh,i} = each{load{shp,.}, i} }
def ext{e} = {
def m = tlen{2*e}; def n = tlen{e} # m<n
if (ellw <= lb{e}) set{slice{iota{n},m}}
@ -150,11 +150,11 @@ def rep_const_shuffle{V, wv, onreps, xv:*V, rv:*V, n:(u64)} = { # onreps{inputVe
if_inline (hasarch{'AVX2'}) {
def rep_iter_from_sh{sh}{x, gen} = {
def l = tuplen{sh}
def l = length{sh}
def h = l>>1
def fs{v, s} = gen{sel{[16]i8, v, s}}
a := shuf{[4]u64, x, 4b1010}; each{fs{a,.}, slice{sh,0,h}}
if (l%2) fs{x, tupsel{h, sh}}
if (l%2) fs{x, select{sh, h}}
b := shuf{[4]u64, x, 4b3232}; each{fs{b,.}, slice{sh,-h}}
}
@ -201,7 +201,7 @@ fn rep_const_shuffle_partial4(wv:u64, ellw:u64, x:*i8, r:*i8, n:u64) : void = {
re := r + n*wvb - h*step
while (r <= re) {
a := shufbase{i}
@unroll (j to h) store{*V~~r, j, shufrun{a, tupsel{j,sh}}}
@unroll (j to h) store{*V~~r, j, shufrun{a, select{sh,j}}}
i += hs << ellw
r += hs*wvb
}
@ -211,7 +211,7 @@ fn rep_const_shuffle_partial4(wv:u64, ellw:u64, x:*i8, r:*i8, n:u64) : void = {
def end = makelabel{}
@unroll (j to h) {
s = shufrun{a, tupsel{j,sh}}
s = shufrun{a, select{sh,j}}
if (r > re) goto{end}
store{*V~~r, 0, s}
r+= step
@ -230,11 +230,11 @@ fn rcsh_sub{wv, V}(ellw:u64, x:*i8, r:*i8, n:u64, sh:*V) : void = {
}
fn rep_const_shuffle_any(wv:u64, ellw:u64, x:*i8, r:*i8, n:u64) : void = {
if (wv > tupsel{-1,rcsh_vals}) {
if (wv > select{rcsh_vals,-1}) {
return{rep_const_shuffle_partial4(wv, ellw, x, r, n)}
}
n <<= ellw
ri := wv - tupsel{0,rcsh_vals}
ri := wv - select{rcsh_vals,0}
sh := *sdtype~~rcsh_data + load{rcsh_offs,ri}
def try{k} = { if (wv==k) rcsh_sub{k, sdtype}(ellw, x, r, n, sh) }
each{try, rcsh_vals}

View File

@ -275,12 +275,12 @@ def simd_plus_scan_part{X, R}{x:(*X), c:(R), r:(*R), len:(u64), i:(u64)} = {
def s1{v0,v1} = tup{v0,v1+toLast{v0}}
def cr = eachx{+, widenFull{R, s1{...s0}}, cv}
cv = toLast{tupsel{-1, cr}}
cv = toLast{select{cr, -1}}
assert{type{cv} == oneType{cr}}
assert{vcount{type{cv}} * tuplen{cr} == bulk}
assert{vcount{type{cv}} * length{cr} == bulk}
each{{c:T, j} => store{*T~~(r+i), j, c}, cr, iota{tuplen{cr}}}
each{{c:T, j} => store{*T~~(r+i), j, c}, cr, iota{length{cr}}}
i = i2
}

View File

@ -1,11 +1,11 @@
# Used by scan.singeli and bins.singeli
def sel8{v:V, t} = sel{[16]u8, v, make{re_el{i8,V}, t}}
def sel8{v:V, t & w256{V} & istup{t} & tuplen{t}==16} = sel8{v, merge{t,t}}
def sel8{v:V, t & w256{V} & istup{t} & length{t}==16} = sel8{v, merge{t,t}}
def shuf{T, v, n & istup{n}} = shuf{T, v, base{4,n}}
local def rev{t} = { def l=tuplen{t}; def j=l-1; tupsel{j-range{l}, j-t} }
local def rev{t} = { def l=length{t}; def j=l-1; select{j-t, j-range{l}} }
local def rev{up,t} = if (up) t else rev{t}
def sel8{v, t, up} = sel8{v, rev{up,t}}

View File

@ -5,8 +5,8 @@ include './hashtab'
def findFirst{C, M, F, ...v1} = {
def exit = makelabel{}
def args = undef{M{...each{tupsel{0, .}, v1}}}
def am = tuplen{tupsel{0,v1}}
def args = undef{M{...each{select{., 0}, v1}}}
def am = length{select{v1,0}}
each{{last, ...v2} => {
if (last or C{...v2}) {
each{=, args, M{...v2}}
@ -291,7 +291,7 @@ def acc{unr, init:T} = {
def op{S=='get'} = a0v
def op{S=='tr', F} = { a0v = tree_fold{F, a1} }
def op{S=='upd', is, F} = {
if (tuplen{is}==1) a0 = F{a0}
if (length{is}==1) a0 = F{a0}
else a1 = F{a1}
}
}

View File

@ -70,8 +70,8 @@ def makeselx{VI, VD, nsel, xd, logv, cshuf} = {
def bb{c}{f, v} = (if (f) bblendn{c<v}; else bblend{(c&v)==v})
def bs{b, c, x} = cshuf{x, c}
def bs{b, c, x & tuplen{b}>0} = {
tupsel{0,b}{each{bs{slice{b,1}, c, .}, x}}
def bs{b, c, x & length{b}>0} = {
select{b,0}{each{bs{slice{b,1}, c, .}, x}}
}
def i = iota{logv}

View File

@ -149,10 +149,10 @@ fn slash{c==0, T & simd128{} & i16<=T & T<=i32}(w:*u64, x:arg{c,T}, r:*T, l:u64,
@for_special_buffered{r,8} (w in *u8~~w over i to sum) {
ind := load{itab, w}
pc := popc_alt{w, ind, 8}
v := mzipLo{j + I~~make{[2]u64, ind, 0}, tupsel{0,top}}
v := mzipLo{j + I~~make{[2]u64, ind, 0}, select{top,0}}
def st{k, v:V} = store{*V~~r, k, v}
if (T==i16) st{0, v}
else each{st, iota{2}, mzip{v, tupsel{1,top}}}
else each{st, iota{2}, mzip{v, select{top,1}}}
r += pc
j += I**8
inctop{i, top}
@ -375,7 +375,7 @@ fn compress_bool(w:*u64, x:*u64, r:*u64, n:u64) : void = {
}
ro = ro2%64
}
def extract{t, i & istup{t}} = tupsel{i,t}
def extract{t, i & istup{t}} = select{t,i}
def v = pext_width{}
if (v > 1) {
def V = [v]u64

View File

@ -92,21 +92,21 @@ fn squeeze{vw, X, CHR, B}(x0:*void, len:ux) : u32 = {
@muLoop{bulk, hasarch{'AARCH64'}+1, {} => { r1 = half{r2,0}|half{r2,1} }}(v0 in tup{XV,xp}, M in 'm' over is to len) {
def int = {
def {int, wdn} = {
if (hasarch{'AARCH64'} and tuplen{is}==2) {
if (hasarch{'AARCH64'} and length{is}==2) {
def intp = narrowPair{...each{cvt{i64,.}, v0}}
def wdn = each{cvt{f64,.}, widen{intp}}
tup{intp, wdn}
} else {
def ints = each{{v} => cvtNarrow{ty_s{E}, v}, v0}
def wdn = each{{v} => cvtWiden{XV, v}, ints}
if (vcount{type{tupsel{0,ints}}} == bulk) {
if (vcount{type{select{ints,0}}} == bulk) {
def intp = {
if (tuplen{ints}==1) tupsel{0, ints}
if (length{ints}==1) select{ints, 0}
else pair{ints}
}
tup{intp, wdn}
} else if (tuplen{ints}==1 and hasarch{'X86_64'} and ~hasarch{'AVX2'}) {
tup{tupsel{0, ints}, wdn}
} else if (length{ints}==1 and hasarch{'X86_64'} and ~hasarch{'AVX2'}) {
tup{select{ints, 0}, wdn}
} else assert{0}
}
}
@ -115,16 +115,16 @@ fn squeeze{vw, X, CHR, B}(x0:*void, len:ux) : u32 = {
def as = each{conv, v0}
def bs = each{conv, wdn}
def cond = {
if (tuplen{is}==1) anynePositive{...as, ...bs, M}
if (length{is}==1) anynePositive{...as, ...bs, M}
else ~homAll{tree_fold{&, each{==, as, bs}}}
}
if (cond) { # is any not an integer
if (B) case_B{tupsel{0, is}} # if B, need to give an even more special result
if (B) case_B{select{is, 0}} # if B, need to give an even more special result
else return{0xffff_ffff} # else, not integer => float
}
int
}
def acc = { if (tuplen{is}==2) r2; else r1 }
def acc = { if (length{is}==2) r2; else r1 }
acc|= M{getAcc{type{acc}, int}}
}

View File

@ -7,9 +7,9 @@ include './bitops'
# Group l (power of 2) elements into paired groups of length o
# e.g. pairs{2, iota{8}} = {{0,1,4,5}, {2,3,6,7}}
def pairs{o, x} = {
def i = iota{tuplen{x}/2}
def i = iota{length{x}/2}
def g = 2*i - i%o
tupsel{tup{g, g+o}, x}
select{x, tup{g, g+o}}
}
def unpack_pass{o, x} = merge{...each{unpackQ, ...pairs{o, x}}}
def permute_pass{o, x} = {