diff --git a/src/singeli/builtins/cmp.c b/src/singeli/builtins/cmp.c index 065890e3..26405da2 100644 --- a/src/singeli/builtins/cmp.c +++ b/src/singeli/builtins/cmp.c @@ -17,9 +17,9 @@ static NORETURN void cmp_err() { thrM("Invalid comparison"); } #include "../gen/cmp.c" #pragma GCC diagnostic pop -typedef void (*CmpAAFn)(u64*, void*, void*, u64); -typedef void (*CmpASFn)(u64*, void*, u64, u64); -#define CMPFN(A,F,S,T) (Cmp##S##Fn) A##_##F##S##_##T +typedef void (*CmpAAFn)(u64*, u8*, u8*, u64); +typedef void (*CmpASFn)(u64*, u8*, u64, u64); +#define CMPFN(A,F,S,T) A##_##F##S##_##T #define FN_LUT(A,F,S) static const Cmp##S##Fn lut_##A##_##F##S[] = {CMPFN(A,F,S,u1), CMPFN(A,F,S,i8), CMPFN(A,F,S,i16), CMPFN(A,F,S,i32), CMPFN(A,F,S,f64), CMPFN(A,F,S,u8), CMPFN(A,F,S,u16), CMPFN(A,F,S,u32)} FN_LUT(avx2, eq, AS); FN_LUT(avx2, eq, AA); @@ -49,14 +49,14 @@ static void* tyany_ptr(B x) { w=tw; x=tx; \ } \ AL(x) \ - lut_avx2_##PNAME##AA[we](rp, tyany_ptr(L), tyany_ptr(R), ria); \ + lut_avx2_##PNAME##AA[we](rp, (u8*)tyany_ptr(L), (u8*)tyany_ptr(R), ria); \ dec(w);dec(x); return r; \ } \ } else { \ - AL(w) lut_avx2_##NAME##AS[we](rp, tyany_ptr(w), x.u, ria); dec(w); return r; \ + AL(w) lut_avx2_##NAME##AS[we](rp, (u8*)tyany_ptr(w), x.u, ria); dec(w); return r; \ } \ } else if (isArr(x)) { u8 xe = TI(x,elType); if (xe==el_B) goto end; \ - AL(x) lut_avx2_##RNAME##AS[xe](rp, tyany_ptr(x), w.u, ria); dec(x); return r; \ + AL(x) lut_avx2_##RNAME##AS[xe](rp, (u8*)tyany_ptr(x), w.u, ria); dec(x); return r; \ } \ if (isF64(w)&isC32(x)) return m_i32(FC); \ if (isC32(w)&isF64(x)) return m_i32(CF); \ diff --git a/src/singeli/src/cmp.singeli b/src/singeli/src/cmp.singeli index bf0c7cba..ff75fd8d 100644 --- a/src/singeli/src/cmp.singeli +++ b/src/singeli/src/cmp.singeli @@ -5,13 +5,10 @@ include './cbqnDefs' include './avx2' include './bitops' -def name{T} = 'unknown' -def name{T & match{T,__eq}} = 'eq' -def name{T & match{T,__ne}} = 'ne' -def name{T & match{T,__gt}} = 'gt' -def name{T & match{T,__ge}} = 'ge' -def name{T & match{T,__lt}} = 'lt' -def name{T & match{T,__le}} = 'le' +def fmt{T} = 'unknown' +def fmt{T&match{T,__eq}}='='; def fmt{T&match{T,__ne}}='≠' +def fmt{T&match{T,__gt}}='>'; def fmt{T&match{T,__ge}}='≥' +def fmt{T&match{T,__lt}}='<'; def fmt{T&match{T,__le}}='≤' def cif{v, G} = { show{'cif argument not known at compile time!'}; G{} } @@ -33,19 +30,18 @@ cmpIX(dst:*u64, len:Size, x:u64, v:u1) : void = { def eqne{op} = match{op,__eq}|match{op,__ne} def pathAS{dst, len, T, op, x & issigned{T}} = { - def XC{f & eqne{op}} = { + def R{f & eqne{op}} = { if (rare{floor{f}!=f}) fillbits{dst, len, op{0,1}} # also includes check for NaN/sNaN ftrunc_i64{f} } - def XC{f & match{op,__lt}|match{op,__ge}} = ftrunc_i64{ceil{f}} - def XC{f & match{op,__gt}|match{op,__le}} = ftrunc_i64{floor{f}} + def R{f & match{op,__lt}|match{op,__ge}} = ftrunc_i64{ceil{f}} + def R{f & match{op,__gt}|match{op,__le}} = ftrunc_i64{floor{f}} xf:f64 = interp_f64{x} - xi64:i64 = XC{xf} - + xi64:i64 = R{xf} xT:T = cast_i{T, xi64} if (rare{(cast_i{i64, xT}!=xi64)}) { - cif{~eqne{op}, {_}=>{ + cif{~eqne{op}, {_}=>{ # NaN was already checked for ≠/= if (isNaN{xf}) { call{cmpIX, dst, len, x, op{0,1}}; return{}; } }} fillbits{dst, len, op{0,xf}} @@ -87,28 +83,30 @@ def any2bit{VT, unr, op, wS, wV, xS, xV, dst:*u64, len:(Size)} = { ri = ri+1 } } -aa2bit{VT, unr, op}(dst:*u64, w:*eltype{VT}, x:*eltype{VT}, len:Size) : void = { +aa2bit{VT, unr, op}(dst:*u64, wr:*u8, xr:*u8, len:Size) : void = { if (len==0) return{} - wv:*VT = cast_vp{VT, w} - xv:*VT = cast_vp{VT, x} - any2bit{VT, unr, op, {i}=>load{w,i}, {i}=>vload{wv,i}, {i}=>load{x,i}, {i}=>vload{xv,i}, dst, len} + wv:= cast_vp{VT, wr}; ws:= cast_p{*eltype{VT}, wr} + xv:= cast_vp{VT, xr}; xs:= cast_p{*eltype{VT}, xr} + 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, w:*eltype{VT}, x:u64, len:Size) : void = { show{VT,unr,name{op}} +as2bit{VT, unr, op}(dst:*u64, wr:*u8, x:u64, len:Size) : void = { show{VT,unr,fmt{op}} if (len==0) return{} - wv:*VT = cast_vp{VT, w} - xv: VT = broadcast{VT, pathAS{dst, len, eltype{VT}, op, x}} - any2bit{VT, unr, op, {i}=>load{w,i}, {i}=>vload{wv,i}, {i}=>x, {i}=>xv, dst, len} + 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} } -bitAA{bitop}(dst:*u64, w:*u64, x:*u64, len:Size) : void = { - @for (dst,w,x over _ from 0 to cdiv{len,64}) dst = bitop{w,x} +bitAA{bitop}(dst:*u64, wr:*u8, xr:*u8, len:Size) : void = { + ws:= cast_p{*u64, wr} + xs:= cast_p{*u64, xr} + @for (dst,ws,xs over _ from 0 to cdiv{len,64}) dst = bitop{ws,xs} } not(dst:*u64, x:*u64, len:Size) : void = { @for (dst,x over _ from 0 to cdiv{len,64}) dst = ~x } cpy(dst:*u64, x:*u64, len:Size) : void = { @for (dst,x over _ from 0 to cdiv{len,64}) dst = x } -bitAS{op}(dst:*u64, w:*u64, x:u64, len:Size) : void = { show{'bitAS'} +bitAS{op}(dst:*u64, wr:*u8, x:u64, len:Size) : void = { show{'bitAS'} if (len==0) return{} xf:f64 = interp_f64{x} r0:u1 = op{0,xf} @@ -120,8 +118,8 @@ bitAS{op}(dst:*u64, w:*u64, x:u64, len:Size) : void = { show{'bitAS'} fillbits{dst, len, r0} return{} } - if (r0) call{not, dst, w, len} - else call{cpy, dst, w, len} + if (r0) call{not, dst, cast_p{*u64,wr}, len} + else call{cpy, dst, cast_p{*u64,wr}, len} } diff --git a/src/singeli/src/f64.singeli b/src/singeli/src/f64.singeli index 1b4717ee..208d3c17 100644 --- a/src/singeli/src/f64.singeli +++ b/src/singeli/src/f64.singeli @@ -3,6 +3,7 @@ def floor{x:f64} = emit{f64, 'floor', x} def NaN = 0.0/0.0 def isNaN{x:f64} = x!=x +def qNaN{x:u64} = (x<<1) == (cast{u64, 0x8ff8} << 49) def ftrunc_i32{x:f64} = emit{i32, '', x} # maybe explicitly use _mm_cvtsd_si32 def ftrunc_i64{x:f64} = emit{i64, '', x}