diff --git a/build/src/build.bqn b/build/src/build.bqn index 03d41eea..87fb03f7 100755 --- a/build/src/build.bqn +++ b/build/src/build.bqn @@ -562,6 +562,7 @@ cachedBin‿linkerCache ← { "xa"‿"src/builtins/arithd.c"‿"dyarith", "xa"‿"src/builtins/cmp.c"‿"cmp", "xa"‿"src/builtins/squeeze.c"‿"squeeze" "x."‿"src/builtins/select.c"‿"select", "x."‿"src/builtins/fold.c"‿"fold", "x."‿"src/builtins/scan.c"‿"scan" "x."‿"src/builtins/scan.c"‿"neq", "x."‿"src/builtins/slash.c"‿"slash", "x."‿"src/builtins/slash.c"‿"constrep" + "x."‿"src/builtins/sfns.c"‿"transpose" ⟩ objs ← ⟨⟩ diff --git a/makefile b/makefile index ea59c895..b4ca4eea 100644 --- a/makefile +++ b/makefile @@ -299,7 +299,7 @@ endif @"${MAKE}" i_singeli=0 singeli=0 force_build_dir=build/obj/presingeli REPLXX=0 f= lf= postmsg="singeli sources:" i_t=presingeli i_f='-O1 -DPRE_SINGELI' FFI=0 OUTPUT=build/obj/presingeli/BQN c -build_singeli: ${addprefix src/singeli/gen/, cmp.c dyarith.c monarith.c copy.c equal.c squeeze.c select.c fold.c scan.c neq.c slash.c constrep.c bits.c} +build_singeli: ${addprefix src/singeli/gen/, cmp.c dyarith.c monarith.c copy.c equal.c squeeze.c select.c fold.c scan.c neq.c slash.c constrep.c bits.c transpose.c} @echo $(postmsg) src/singeli/gen/%.c: src/singeli/src/%.singeli preSingeliBin @echo $< | cut -c 17- | sed 's/^/ /' diff --git a/src/builtins/sfns.c b/src/builtins/sfns.c index fa9eefc2..d112202b 100644 --- a/src/builtins/sfns.c +++ b/src/builtins/sfns.c @@ -1254,6 +1254,13 @@ B reverse_c2(B t, B w, B x) { #endif #endif +#if SINGELI_X86_64 + static NOINLINE void base_transpose_u32(u32* rp, u32* xp, u64 w, u64 h, u64 xo, u64 ro) { PLAINLOOP for(usz y=0;y=8 && h>=8) { u32* xp=tyany_ptr(x); u32* rp = m_tyarrp(&r,4,ia,el2t(xe)); simd_transpose_i32(rp, xp, w, h); break; } + #endif + { u32* xp=tyany_ptr(x); u32* rp = m_tyarrp(&r,4,ia,el2t(xe)); PLAINLOOP for(usz y=0;y unpackQ{tupsel{i*2,x}, tupsel{i*2+1,x}}, iota{4}}} + def t2 = merge{...each{{i} => unpackQ{tupsel{i, t1}, tupsel{i+2, t1}}, tup{0,1,4,5}}} + each{{i} => emit{[8]i32, '_mm256_permute2f128_si256', tupsel{i%4,t2}, tupsel{i%4+4,t2}, tern{i>=4,16b31,16b20}}, iota{8}} +} + + + +transpose_rec{T}(rpo:*T, xpo:*T, w:u64, h:u64, wm:i64, hm:i64, scl:u64) : void = { + if (wm<=0 or hm<=0) return{} + + if (scl==1) { + assert{T==u32} + def VT = [8]i32 + def xvs = each{{i}=>load{*VT~~(xpo+i*w), 0}, iota{vcount{VT}}} + def rvs = vtranspose{xvs} + each{{i,v}=>store{*VT~~(rpo+i*h), 0, v}, iota{vcount{VT}}, rvs} + } else { + o:= (scl+1)>>1; s:= i64~~o + transpose_rec{T}(rpo , xpo , w, h, wm , hm , o) + transpose_rec{T}(rpo + o*8, xpo + o*8*w , w, h, wm , hm-s, o) + transpose_rec{T}(rpo + o*8*h , xpo + o*8, w, h, wm-s, hm , o) + transpose_rec{T}(rpo + o*8*h + o*8, xpo + o*8*w + o*8, w, h, wm-s, hm-s, o) + } +} + +transpose{T}(r0:*void, x0:*void, w:u64, h:u64) : void = { + rp:*T = *T~~r0 + xp:*T = *T~~x0 + + @for (y to h/8) { + @for (x to w/8) { + def VT = [8]i32 + xpo:= xp + y*8*w + x*8 + rpo:= rp + x*8*h + y*8 + def xvs = each{{i}=>load{*VT~~(xpo+i*w), 0}, iota{vcount{VT}}} + def rvs = vtranspose{xvs} + each{{i,v}=>store{*VT~~(rpo+i*h), 0, v}, iota{vcount{VT}}, rvs} + } + } + + # wm:= w/8 + # hm:= h/8 + # transpose_rec{T}(rp, xp, w, h, i64~~wm, i64~~hm, tern{wm>hm, wm, hm}) + + if (w%8) emit{void, 'base_transpose_u32', rp+h*(w-w%8), xp+(w-w%8), w%8, h, w, h} + if (h%8) emit{void, 'base_transpose_u32', rp+(h-h%8), xp+w*(h-h%8), w-w%8, h%8, w, h} +} + +'simd_transpose_i32' = transpose{u32} \ No newline at end of file