diff --git a/src/builtins/slash.c b/src/builtins/slash.c index 98810542..f108c7f8 100644 --- a/src/builtins/slash.c +++ b/src/builtins/slash.c @@ -768,7 +768,7 @@ B slash_c2(B t, B w, B x) { u64* xp = bitarr_ptr(x); u64* rp; r = m_bitarrv(&rp, s); #if SINGELI - if (si_constrep_bool(wv, xp, rp, s)) ; // Handles small wv + if (wv <= 64) si_constrep_bool(wv, xp, rp, s); else #endif if (wv <= 256) { BOOL_REP_XOR_SCAN(wv) } diff --git a/src/singeli/src/replicate.singeli b/src/singeli/src/replicate.singeli index 1a311fa3..c96fd248 100644 --- a/src/singeli/src/replicate.singeli +++ b/src/singeli/src/replicate.singeli @@ -59,6 +59,9 @@ exportT{'si_replicate_scan', flat_table{rep_by_scan, ind_types, dat_types}} # Constant replicate +def incl{a,b} = slice{iota{b+1},a} +def basic_rep = incl{2, 7} + if_inline (not (hasarch{'SSSE3'} or hasarch{'AARCH64'})) { fn rep_const{T}(wv:u64, x:*void, r:*void, n:u64) : void = { @@ -69,14 +72,11 @@ fn rep_const{T}(wv:u64, x:*void, r:*void, n:u64) : void = { def has_bytesel_128 = not hasarch{'AVX2'} -def incl{a,b} = slice{iota{b+1},a} - # 1+˝∨`⌾⌽0=div|⌜range def makefact{divisor, range} = { def t = table{{a,b}=>0==b%a, divisor, range} fold{+, 1, reverse{scan{|, reverse{t}}}} } -def basic_rep = incl{2, 7} def fact_size = 128 def fact_inds = slice{iota{fact_size},8} def fact_tab = makefact{basic_rep, fact_inds} @@ -289,17 +289,23 @@ exportT{'si_constrep', each{rep_const, dat_types}} # Constant replicate on boolean -fn rep_const_bool{}(wv:usz, x:*u64, r:*u64, rlen:usz) : u1 = { - if (wv > 64) return{0} +fn rep_const_bool{}(wv:usz, x:*u64, r:*u64, rlen:usz) : void = { + assert{wv >= 2}; assert{wv <= 64} nw := cdiv{rlen, 64} if (wv&1 == 0) { p := ctz{wv | 8} # Power of two for second replicate wf := wv>>p if (wf == 1) { rep_const_bool_div8{wv, x, r, nw} + } else if (hasarch{'SSSE3'} and p == 3 and wv <= 8*select{basic_rep, -1}) { + # (higher wv double-factors, which doesn't work with in-place pointers) + tlen := rlen / wf + t := r + cdiv{rlen, 64} - cdiv{tlen, 64} + rep_const_bool{}(8, x, t, tlen) + rep_const{select{dat_types,0}}(promote{u64,wf}, *void~~t, *void~~r, promote{u64,tlen/8}) } else { - tlen := rlen>>p - wq := usz~~1<
> p + wq := usz~~1 << p if (p == 1 and (not hasarch{'SSSE3'} or wv>=24)) { # Expanding odd second is faster tlen = rlen / wf @@ -312,7 +318,6 @@ fn rep_const_bool{}(wv:usz, x:*u64, r:*u64, rlen:usz) : u1 = { } else { rep_const_bool_odd{wv, x, r, nw} } - 1 } def rep_const_bool_div8{wv, x, r, nw} = { # wv in 2,4,8