From 8eb3989d847a88a9a5c582ed0d2e62c28f5fc748 Mon Sep 17 00:00:00 2001 From: dzaima Date: Mon, 25 Oct 2021 16:18:03 +0300 Subject: [PATCH] separate avx file --- src/singeli/src/avx.singeli | 44 +++++++++++++++++++++++++++++++++++ src/singeli/src/avx2.singeli | 45 +----------------------------------- src/singeli/src/base.singeli | 6 +++++ src/singeli/src/cmp.singeli | 5 ++-- 4 files changed, 54 insertions(+), 46 deletions(-) create mode 100644 src/singeli/src/avx.singeli diff --git a/src/singeli/src/avx.singeli b/src/singeli/src/avx.singeli new file mode 100644 index 00000000..e51c8561 --- /dev/null +++ b/src/singeli/src/avx.singeli @@ -0,0 +1,44 @@ +# ugh the intrinsics have their own broken type system +def r_d2i{R, a:T} = emit{R, '_mm256_castpd_si256', a} +def r_f2i{R, a:T} = emit{R, '_mm256_castps_si256', a} +def r_i2d{a:T} = emit{[4]f64, '_mm256_castsi256_pd', a} +def r_f2d{a:T} = emit{[4]f64, '_mm256_castps_pd', a} +def r_d2f{a:T} = emit{[8]f32, '_mm256_castpd_ps', a} +def r_i2f{a:T} = emit{[8]f32, '_mm256_castsi256_ps', a} +# various utilities +def isunsigned{T} = isint{T} & ~issigned{T} +def isintv{T} = isint{eltype{T}} +def isfloatv{T} = isfloat{eltype{T}} +def issignedv{T} = issigned{eltype{T}} +def isunsignedv{T} = isunsigned{eltype{T}} +def w256{T} = width{T}==256 +def isintv{T,w} = isintv{T} & width{eltype{T}}==w +# load +def cast_vp{T, a & w256{T}} = emit{*T, '(void*)', a} +def vload{a:T, n & w256{eltype{T}} & isintv{eltype{T}}} = emit{eltype{T}, '_mm256_loadu_si256', emit{T, 'op +', a, n}} +def vload{a:T, n & w256{eltype{T}} & isfloatv{eltype{T}}} = r_i2d{vload{cast_vp{[4]u64, a}, n}} # TODO use the proper float load + +# broadcast; TODO restrict v +def broadcast{T, v & w256{T} & isintv{T, 8}} = emit{T, '_mm256_set1_epi8', v} +def broadcast{T, v & w256{T} & isintv{T, 16}} = emit{T, '_mm256_set1_epi16', v} +def broadcast{T, v & w256{T} & isintv{T, 32}} = emit{T, '_mm256_set1_epi32', v} +def broadcast{T, v & w256{T} & isintv{T, 64}} = emit{T, '_mm256_set1_epi64x',v} +def broadcast{T, v & w256{T} & eltype{T}==f64} = emit{T, '_mm256_set1_pd', v} + +def __xor{a:T, b:T & w256{T} & isunsignedv{T}} = r_f2i{T, emit{[8]f32, '_mm256_xor_ps', r_i2f{a}, r_i2f{b}}} +def __and{a:T, b:T & w256{T} & isunsignedv{T}} = r_f2i{T, emit{[8]f32, '_mm256_and_ps', r_i2f{a}, r_i2f{b}}} +def __or {a:T, b:T & w256{T} & isunsignedv{T}} = r_f2i{T, emit{[8]f32, '_mm256_or_ps', r_i2f{a}, r_i2f{b}}} + +def __not{a:T & w256{T} & isunsignedv{T}} = a ^ broadcast{T, ~cast{eltype{T},0}} + +# float comparison +def fcmpAVX{a,b,n} = r_d2i{[4]u64, emit{[4]f64, '_mm256_cmp_pd', a, b, n}} +def __eq{a:T,b:T & T==[4]f64} = fcmpAVX{a,b, 0} +def __ne{a:T,b:T & T==[4]f64} = fcmpAVX{a,b, 4} +def __gt{a:T,b:T & T==[4]f64} = fcmpAVX{a,b,30} +def __ge{a:T,b:T & T==[4]f64} = fcmpAVX{a,b,29} +def __lt{a:T,b:T & T==[4]f64} = fcmpAVX{a,b,17} +def __le{a:T,b:T & T==[4]f64} = fcmpAVX{a,b,18} + +def getmask{x:[8]u32} = emit{u8, '_mm256_movemask_ps', r_i2f{x}} +def getmask{x:[4]u64} = emit{u8, '_mm256_movemask_pd', r_i2d{x}} \ No newline at end of file diff --git a/src/singeli/src/avx2.singeli b/src/singeli/src/avx2.singeli index f5d25542..5dc2634e 100644 --- a/src/singeli/src/avx2.singeli +++ b/src/singeli/src/avx2.singeli @@ -1,36 +1,3 @@ -# ugh the intrinsics have their own broken type system -def r_d2i{R, a:T} = emit{R, '_mm256_castpd_si256', a} -def r_f2i{R, a:T} = emit{R, '_mm256_castps_si256', a} -def r_i2d{a:T} = emit{[4]f64, '_mm256_castsi256_pd', a} -def r_f2d{a:T} = emit{[4]f64, '_mm256_castps_pd', a} -def r_d2f{a:T} = emit{[8]f32, '_mm256_castpd_ps', a} -def r_i2f{a:T} = emit{[8]f32, '_mm256_castsi256_ps', a} -# various utilities -def isunsigned{T} = isint{T} & ~issigned{T} -def isintv{T} = isint{eltype{T}} -def isfloatv{T} = isfloat{eltype{T}} -def issignedv{T} = issigned{eltype{T}} -def isunsignedv{T} = isunsigned{eltype{T}} -def w256{T} = width{T}==256 -def isintv{T,w} = isintv{T} & width{eltype{T}}==w -# load -def cast_vp{T, a & w256{T}} = emit{*T, '(void*)', a} -def vload{a:T, n & w256{eltype{T}} & isintv{eltype{T}}} = emit{eltype{T}, '_mm256_loadu_si256', emit{T, 'op +', a, n}} -def vload{a:T, n & w256{eltype{T}} & isfloatv{eltype{T}}} = r_i2d{vload{cast_vp{[4]u64, a}, n}} # TODO use the proper float load - -# ops - -# broadcast; TODO restrict v -def broadcast{T, v & w256{T} & isintv{T, 8}} = emit{T, '_mm256_set1_epi8', v} -def broadcast{T, v & w256{T} & isintv{T, 16}} = emit{T, '_mm256_set1_epi16', v} -def broadcast{T, v & w256{T} & isintv{T, 32}} = emit{T, '_mm256_set1_epi32', v} -def broadcast{T, v & w256{T} & isintv{T, 64}} = emit{T, '_mm256_set1_epi64x',v} -def broadcast{T, v & w256{T} & eltype{T}==f64} = emit{T, '_mm256_set1_pd', v} - -def __xor{a:T, b:T & w256{T} & isunsignedv{T}} = r_f2i{T, emit{[8]f32, '_mm256_xor_ps', r_i2f{a}, r_i2f{b}}} - -def __not{a:T & w256{T} & isunsignedv{T}} = a ^ broadcast{T, ~cast{eltype{T},0}} - # min & max def min{a:T,b:T & T==[32]i8 } = emit{T, '_mm256_min_epi8', a, b}; def min{a:T,b:T & T==[32]u8 } = emit{T, '_mm256_min_epu8', a, b} def min{a:T,b:T & T==[16]i16} = emit{T, '_mm256_min_epi16', a, b}; def min{a:T,b:T & T==[16]u16} = emit{T, '_mm256_min_epu16', a, b} @@ -39,14 +6,6 @@ def max{a:T,b:T & T==[32]i8 } = emit{T, '_mm256_max_epi8', a, b}; def max{a:T,b def max{a:T,b:T & T==[16]i16} = emit{T, '_mm256_max_epi16', a, b}; def max{a:T,b:T & T==[16]u16} = emit{T, '_mm256_max_epu16', a, b} def max{a:T,b:T & T==[ 8]i32} = emit{T, '_mm256_max_epi32', a, b}; def max{a:T,b:T & T==[ 8]u32} = emit{T, '_mm256_max_epu32', a, b} -# float comparison -def fcmpAVX{a,b,n} = r_d2i{[4]u64, emit{[4]f64, '_mm256_cmp_pd', a, b, n}} -def __eq{a:T,b:T & T==[4]f64} = fcmpAVX{a,b, 0} -def __ne{a:T,b:T & T==[4]f64} = fcmpAVX{a,b, 4} -def __gt{a:T,b:T & T==[4]f64} = fcmpAVX{a,b,30} -def __ge{a:T,b:T & T==[4]f64} = fcmpAVX{a,b,29} -def __lt{a:T,b:T & T==[4]f64} = fcmpAVX{a,b,17} -def __le{a:T,b:T & T==[4]f64} = fcmpAVX{a,b,18} # signed comparison def __eq{a:T,b:T & T==[32]i8 } = emit{[32]u8, '_mm256_cmpeq_epi8', a, b} def __eq{a:T,b:T & T==[16]i16} = emit{[16]u16, '_mm256_cmpeq_epi16', a, b} @@ -69,9 +28,7 @@ def __gt{a:T,b:T & w256{T} & isunsignedv{T}} = ~(a<=b) def __ne{a:T,b:T & w256{T} & isintv{T}} = ~(b==a) def getmask{x:[32]u8} = emit{u32, '_mm256_movemask_epi8', x} -def getmask{x:[8]u32} = emit{u8, '_mm256_movemask_ps', r_i2f{x}} -def getmask{x:[4]u64} = emit{u8, '_mm256_movemask_pd', r_i2d{x}} def getmask{x:[16]u16} = { msk:u32 = getmask{emit{[32]u8, '_mm256_packs_epi16', x, broadcast{[16]u16, 0}}} (msk&255) | (msk>>8) # TODO try out permute4x64 for fixing up -} +} \ No newline at end of file diff --git a/src/singeli/src/base.singeli b/src/singeli/src/base.singeli index 1e01870e..100037df 100644 --- a/src/singeli/src/base.singeli +++ b/src/singeli/src/base.singeli @@ -23,3 +23,9 @@ def for{vars,begin,end,block} = { def maxvalue{T & T==u8 } = 0xff def maxvalue{T & T==u16} = 0xffff def maxvalue{T & T==u32} = 0xffffffff + +# various utilities +def isintv{T} = isint{eltype{T}} +def isfloatv{T} = isfloat{eltype{T}} +def issignedv{T} = issigned{eltype{T}} +def isunsignedv{T} = isunsigned{eltype{T}} \ No newline at end of file diff --git a/src/singeli/src/cmp.singeli b/src/singeli/src/cmp.singeli index 0fb0d8cb..d11761d1 100644 --- a/src/singeli/src/cmp.singeli +++ b/src/singeli/src/cmp.singeli @@ -2,6 +2,7 @@ def Size = u64 include './base' include './f64' include './cbqnDefs' +include './avx' include './avx2' include './bitops' @@ -89,7 +90,7 @@ aa2bit{VT, unr, op}(dst:*u64, wr:*u8, xr:*u8, len:Size) : void = { any2bit{VT, unr, op, {i}=>load{ws,i}, {i}=>vload{wv,i}, {i}=>load{xs,i}, {i}=>vload{xv,i}, dst, len} } -as2bit{VT, unr, op}(dst:*u64, wr:*u8, x:u64, len:Size) : void = { show{VT,unr,fmt{op}} +as2bit{VT, unr, op}(dst:*u64, wr:*u8, x:u64, len:Size) : void = { # show{VT,unr,fmt{op}} wv:= cast_vp{VT, wr}; ws:= cast_p{*eltype{VT}, wr} xv:= broadcast{VT, pathAS{dst, len, eltype{VT}, op, x}} any2bit{VT, unr, op, {i}=>load{ws,i}, {i}=>vload{wv,i}, {i}=>x, {i}=>xv, dst, len} @@ -104,7 +105,7 @@ bitAA{bitop}(dst:*u64, wr:*u8, xr:*u8, len:Size) : void = { not(dst:*u64, x:*u64, len:Size) : void = { am:=cdiv{len,64}; assert{am>0}; @for (dst,x over _ from 0 to am) dst = ~x } cpy(dst:*u64, x:*u64, len:Size) : void = { am:=cdiv{len,64}; assert{am>0}; @for (dst,x over _ from 0 to am) dst = x } -bitAS{op}(dst:*u64, wr:*u8, x:u64, len:Size) : void = { show{'bitAS'} +bitAS{op}(dst:*u64, wr:*u8, x:u64, len:Size) : void = { # show{'bitAS'} xf:f64 = interp_f64{x} r0:u1 = op{0,xf} r1:u1 = op{1,xf}