is_pow2 helper

This commit is contained in:
dzaima 2025-04-24 18:31:25 +03:00
parent 0ec37303ea
commit 98f1c97653
4 changed files with 9 additions and 8 deletions

View File

@ -21,6 +21,7 @@ def any_num = match { {x:T}=>primt{T}; {x} => knum{x} }
def any_int = match { {x:T}=>isint{T}; {x} => knum{x} and (x>>0) == x } def any_int = match { {x:T}=>isint{T}; {x} => knum{x} and (x>>0) == x }
def int_idx{_, _} = 0 def int_idx{_, _} = 0
def int_idx{k if knum{k}, l} = (k>>0)==k and k>=0 and k<l def int_idx{k if knum{k}, l} = (k>>0)==k and k>=0 and k<l
def is_pow2{i if any_int{i}} = (i & (i-1)) == 0
def elwidth{T} = width{eltype{T}} def elwidth{T} = width{eltype{T}}
def reinterpret{T, x:T} = x def reinterpret{T, x:T} = x

View File

@ -239,7 +239,7 @@ fn extract_column(x0:*void, r0:*void, n:usz, l:usz, el:u8) : usz = {
def thr = __min{vl+2, 20} def thr = __min{vl+2, 20}
if ((not has_simd) or n < vl or l > usz~~thr>>el or l<<el >= thr) return{0} if ((not has_simd) or n < vl or l > usz~~thr>>el or l<<el >= thr) return{0}
nv := n / vl nv := n / vl
if (has_simd and (l & (l-1)) == 0) { if (has_simd and is_pow2{l}) {
def try_unzip{T, k} = if (k < thr and l == k) { def try_unzip{T, k} = if (k < thr and l == k) {
extract_column_pow2{T, x0, r0, nv, k} extract_column_pow2{T, x0, r0, nv, k}
goto{'ret'} goto{'ret'}
@ -319,8 +319,8 @@ def fold_rows_bit_lt64{
# Emulate pext with 1, 2, or 3 multiply/mask steps. # Emulate pext with 1, 2, or 3 multiply/mask steps.
# To move size-a groups spaced at distance b together, # To move size-a groups spaced at distance b together,
# the multiplier has up to b/a bits spaced by b-a. # the multiplier has up to b/a bits spaced by b-a.
dm:= cast_i{usz, popc{el}} # minimum output bits per word dm:= cast_i{usz, popc{el}} # minimum output bits per word
dm-= promote{usz, l&(l-1) == 0} # for divisors of 64, e0 effectively overflows; subtract 1 to correct dm-= promote{usz, is_pow2{l}} # for divisors of 64, e0 effectively overflows; subtract 1 to correct
def loop{...par} = { def loop{...par} = {
et:= e0 << clz{e0} et:= e0 << clz{e0}
@for (xo in xp over nw) { @for (xo in xp over nw) {

View File

@ -556,7 +556,7 @@ fn scan_rows_andor{id}(src:*u64, dst:*u64, nl:usz, l:usz) : void = {
if (qand) s & (~f | c) else s | (f & c) if (qand) s & (~f | c) else s | (f & c)
} }
if (l < 64) { if (l < 64) {
if ((l & (l-1)) == 0) { if (is_pow2{l}) {
if (l == 2) { if (l == 2) {
@for (r in dst, x in src over nw) { @for (r in dst, x in src over nw) {
r = (if (qand) x & (x<<1 | 64w2b01) else x | (x<<1 & 64w2b10)) r = (if (qand) x & (x<<1 | 64w2b01) else x | (x<<1 & 64w2b10))
@ -637,7 +637,7 @@ fn scan_rows_neq(x:*u64, r:*u64, nl:usz, l:usz) : void = {
b:= s<<1 & m # last bit of previous row b:= s<<1 & m # last bit of previous row
s ^ (b<<l - b) s ^ (b<<l - b)
} }
if ((l & (l-1)) == 0) { if (is_pow2{l}) {
m:u64 = aligned_spaced_mask{l} m:u64 = aligned_spaced_mask{l}
@for (r, x over nw) r = apply_mask{scan_word{x}, m} @for (r, x over nw) r = apply_mask{scan_word{x}, m}
} else if (has_simd) { } else if (has_simd) {
@ -690,7 +690,7 @@ fn scan_rows_left(x:*u64, r:*u64, nl:usz, l:usz) : void = {
def apply_carry{s, c, f} = s | (f & c) def apply_carry{s, c, f} = s | (f & c)
if (l < 64) { if (l < 64) {
def apply_mask{x, m} = { b:= x & m; b<<l - b } def apply_mask{x, m} = { b:= x & m; b<<l - b }
if ((l & (l-1)) == 0) { if (is_pow2{l}) {
m:u64 = aligned_spaced_mask{l} m:u64 = aligned_spaced_mask{l}
@for (r, x over nw) r = apply_mask{x, m} @for (r, x over nw) r = apply_mask{x, m}
} else if (has_simd) { } else if (has_simd) {
@ -740,7 +740,7 @@ fn scan_stride_bool_assoc{op}(x:*u64, r:*u64, nl:usz, l:usz) : void = {
def {flip,opf} = if (same{op, &}) tup{~,|} else tup{{x}=>x,op} # such that identity of opf is 0 def {flip,opf} = if (same{op, &}) tup{~,|} else tup{{x}=>x,op} # such that identity of opf is 0
nw:= cdiv{nl, 64} nw:= cdiv{nl, 64}
if (l <= 64) { if (l <= 64) {
if (same{op, ^} and hasarch{'PCLMUL'} and (l & (l-1)) == 0) { if (same{op, ^} and hasarch{'PCLMUL'} and is_pow2{l}) {
clmul_scan_ne_any{}(*void~~x, *void~~r, 0, nw, aligned_spaced_mask{l}) clmul_scan_ne_any{}(*void~~x, *void~~r, 0, nw, aligned_spaced_mask{l})
return{} return{}
} }

View File

@ -2,7 +2,7 @@ def spaced_mask_of{l} = emit{u64, 'get_spaced_mask', l} # see slash.singeli
def aligned_spaced_mask{l} = { def aligned_spaced_mask{l} = {
assert{l <= 64} assert{l <= 64}
assert{l&(l-1) == 0} assert{is_pow2{l}}
spaced_mask_of{l} spaced_mask_of{l}
} }