From f8798affc4233bed09746ccd0d10130f4d730f2b Mon Sep 17 00:00:00 2001 From: dzaima Date: Mon, 25 Oct 2021 01:42:29 +0300 Subject: [PATCH] full array-scalar comparison error checking in singeli --- makefile | 4 +-- src/singeli/builtins/cmp.c | 6 +--- src/singeli/src/base.singeli | 4 +++ src/singeli/src/cbqnDefs.singeli | 6 ++-- src/singeli/src/cmp.singeli | 54 +++++++++++++++++++------------- 5 files changed, 43 insertions(+), 31 deletions(-) diff --git a/makefile b/makefile index 62128f69..a4fb566b 100644 --- a/makefile +++ b/makefile @@ -19,10 +19,10 @@ heapverify: @${MAKE} singeli=0 t=heapverify f="-DDEBUG -g -DHEAP_VERIFY" c o3n-singeli: @${MAKE} singeli=1 t=o3n_si f="-O3 -march=native" c +o3ng-singeli: + @${MAKE} singeli=1 t=o3ng_si f="-g -O3 -march=native" c debugn-singeli: @${MAKE} singeli=1 t=debugn_si f="-g -DDEBUG -march=native" c -debug-singeli: - @${MAKE} singeli=1 t=debug_si f="-g -DDEBUG" c diff --git a/src/singeli/builtins/cmp.c b/src/singeli/builtins/cmp.c index 9f07f32a..919605f8 100644 --- a/src/singeli/builtins/cmp.c +++ b/src/singeli/builtins/cmp.c @@ -6,15 +6,11 @@ static NOINLINE void fillBits(u64* dst, u64 sz, bool v) { u64 x = 0-(u64)v; for (usz i = 0; i < (sz+63)/64; i++) dst[i] = x; } +static NORETURN void cmp_err() { thrM("Invalid comparison"); } #define BCALL(N, X) N(b(X)) #define interp_f64(X) b(X).f -#define TMPF(T, N, V) static NOINLINE void def_##N##_##T(u64* dst, u64 len, u64 xu) { if (len) fillBits(dst, len, o2bu(c2(bi_##N, V(0), b(xu)))); } -TMPF(f,eq,m_f64) TMPF(f,ne,m_f64) TMPF(f,gt,m_f64) TMPF(f,ge,m_f64) TMPF(f,lt,m_f64) TMPF(f,le,m_f64) -TMPF(c,eq,m_c32) TMPF(c,ne,m_c32) TMPF(c,gt,m_c32) TMPF(c,ge,m_c32) TMPF(c,lt,m_c32) TMPF(c,le,m_c32) -#undef TMPF -#define defcmp(T, N, dst, len, x) def_##N##_##T(dst, len, x) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-variable" diff --git a/src/singeli/src/base.singeli b/src/singeli/src/base.singeli index c4461964..ba2ae14a 100644 --- a/src/singeli/src/base.singeli +++ b/src/singeli/src/base.singeli @@ -2,6 +2,7 @@ include 'skin/c' include 'arch/c' def cdiv{a,b} = (a+b-1)/b def rare{x:u1} = emit{u1, '__builtin_expect', x, 0} +def isunsigned{T} = isint{T} & ~issigned{T} def unroll{vars,begin,end,block & match{kind{begin},'number'} & match{kind{end},'number'}} = { def f{i,l & i==l} = 0 @@ -18,3 +19,6 @@ def for{vars,begin,end,block} = { i = i+1 } } +def maxvalue{T & T==u8 } = 0xff +def maxvalue{T & T==u16} = 0xffff +def maxvalue{T & T==u32} = 0xffffffff \ No newline at end of file diff --git a/src/singeli/src/cbqnDefs.singeli b/src/singeli/src/cbqnDefs.singeli index b084e363..1d604b16 100644 --- a/src/singeli/src/cbqnDefs.singeli +++ b/src/singeli/src/cbqnDefs.singeli @@ -1,10 +1,10 @@ def bcall{T, f, x} = emit{T, 'BCALL', f, x} def from_B{T, x & T==f64} = bcall{T, 'o2fu', x} -def from_B{T, x & T<=i32} = bcall{T, 'o2iu', x} -def from_B{T, x & T<=u32} = bcall{T, 'o2cu', x} +def from_B{T, x & T<=i32 & issigned{T}} = bcall{T, 'o2iu', x} +def from_B{T, x & T<=u32 & isunsigned{T}} = bcall{T, 'o2cu', x} def q_f64{x} = bcall{u1, 'q_f64', x} -def q_c32{x} = bcall{u1, 'q_c32', x} +def q_chr{x} = bcall{u1, 'q_c32', x} def q_chr{T,x & T==u8 } = bcall{u1, 'q_c8', x} def q_chr{T,x & T==u16} = bcall{u1, 'q_c16', x} def q_chr{T,x & T==u32} = bcall{u1, 'q_c32', x} diff --git a/src/singeli/src/cmp.singeli b/src/singeli/src/cmp.singeli index 29b94e65..ecfa0706 100644 --- a/src/singeli/src/cmp.singeli +++ b/src/singeli/src/cmp.singeli @@ -22,15 +22,18 @@ def fillbits{dst:*u64, len:(Size), v} = { emit{void, 'fillBits', dst, len, v} return{} } -def defcmp{op, ty, dst, len, x} = { - emit{void, 'defcmp', ty, name{op}, dst, len, x} - return{} +def cmp_err{x} = { emit{void, 'cmp_err'}; return{}; } + +cmpIX(dst:*u64, len:Size, x:u64, v:u1) : void = { + nan:u1 = q_f64{x} + if (~(nan | q_chr{x})) cmp_err{x} + fillbits{dst, len, v & ~nan} } +def eqne{op} = match{op,__eq}|match{op,__ne} + def pathAS{dst, len, T, op, x & issigned{T}} = { - def eqne = match{op,__eq}|match{op,__ne} - - def XC{f & eqne} = { + def XC{f & eqne{op}} = { if (rare{floor{f}!=f}) fillbits{dst, len, op{0,1}} # also includes check for NaN/sNaN ftrunc_i64{f} } @@ -41,10 +44,9 @@ def pathAS{dst, len, T, op, x & issigned{T}} = { xi64:i64 = XC{xf} xT:T = cast_i{T, xi64} - #emit{void, 'printf', '"%lu\n"', xi64} - if (rare{(cast_i{i64, xT}!=xi64) | (xi64==cast_i{i64, cast{u64,1}<<63})}) { - cif{~eqne, {_}=>{ - if (isNaN{xf}) defcmp{op, 'f', dst, len, x} + if (rare{(cast_i{i64, xT}!=xi64)}) { + cif{~eqne{op}, {_}=>{ + if (isNaN{xf}) { call{cmpIX, dst, len, x, op{0,1}}; return{}; } }} fillbits{dst, len, op{0,xf}} } @@ -52,13 +54,21 @@ def pathAS{dst, len, T, op, x & issigned{T}} = { } def pathAS{dst, len, T, op, x & T==f64} = { - if (rare{~q_f64{x}}) defcmp{op, 'f', dst, len, x} # fillbits{dst, len, op{0,1}} + if (rare{~q_f64{x}}) { + cif{~eqne{op}, {_}=>{ if(~q_chr{x}) cmp_err{x}; }} + fillbits{dst, len, op{0,1}} + } from_B{T,x} } def pathAS{dst, len, T, op, x & isunsigned{T}} = { - if (rare{~q_chr{T,x}}) defcmp{op, 'c', dst, len, x} # fillbits{dst, len, op{0,1}} - from_B{T,x} + if (rare{~q_chr{x}}) { + cif{~eqne{op}, {_}=>{ if(~q_f64{x}) cmp_err{x}; }} + fillbits{dst, len, op{1,0}} + } + xc32:u32 = from_B{u32,x} + if (xc32 > maxvalue{T}) fillbits{dst, len, op{0,1}} + cast_i{T, xc32} } @@ -67,7 +77,8 @@ def any2bit{VT, unr, op, wS, wV, xS, xV, dst:*u64, len:(Size)} = { xi:Size = 0 ri:Size = 0 def bam = vcount{VT}*unr - while (ri < cdiv{len,bam}) { + len:Size = cdiv{len,bam} + while (ri < len) { r:u64 = 0 @unroll (j from 0 to unr) r = r | (cast_i{u64, getmask{op{wV{xi+j}, xV{xi+j}}}} << (j*vcount{VT})) b_set{bam, dst, ri, r} @@ -76,12 +87,14 @@ def any2bit{VT, unr, op, wS, wV, xS, xV, dst:*u64, len:(Size)} = { } } aa2bit{VT, unr, op}(dst:*u64, w:*eltype{VT}, x:*eltype{VT}, 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} } as2bit{VT, unr, op}(dst:*u64, w:*eltype{VT}, x:u64, len:Size) : void = { show{VT,unr,name{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} @@ -94,16 +107,15 @@ bitAA{bitop}(dst:*u64, w:*u64, x:*u64, len:Size) : void = { 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, w:*u64, x:u64, len:Size) : void = { show{'bitAS'} + if (len==0) return{} xf:f64 = interp_f64{x} - if (rare{isNaN{xf}}) { - defcmp{op, 'f', dst, len, x} - return{} - } r0:u1 = op{0,xf} r1:u1 = op{1,xf} - if (rare{r0==r1}) { + if (r0==r1) { + cif{~eqne{op}, {_}=>{ + if (rare{isNaN{xf}}) { call{cmpIX, dst, len, x, op{0,1}}; return{}; } + }} fillbits{dst, len, r0} return{} }