use Singeli-generated function tables for comparison

This commit is contained in:
dzaima 2022-12-16 18:51:48 +02:00
parent f49dd5e8cf
commit 2c73199ed4
5 changed files with 59 additions and 40 deletions

View File

@ -50,11 +50,14 @@ CMP_REC(ne, ne, swapped=0;)
#undef CMP_REC
#define CMPFN(A,F,S,T) A##_##F##S##_##T
#define FN_LUT(B,A,F,S) const Cmp##S##Fn B##_##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)}
#define FN_LUT_T(B,F,S,...) Cmp##S##Fn B##_##F##S
#define FN_LUT_C(B,A,F,S) FN_LUT_T(B,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)}
#define FN_LUT_A(B,F,S) FN_LUT_T(B,F,S)[8]
#if SINGELI
#include "../singeli/c/cmp.c"
#else
void cmpA_init() { }
#define BASE_CMP_LOOP(OP, W, X) \
for (usz j = 0; j < (l+7)>>3; j++) { \
u8 c = 0; \
@ -115,15 +118,17 @@ CMP_REC(ne, ne, swapped=0;)
CMP_SA_F(gt, > , CMP_TO_SLOW, wv & ~xv)
#undef CMP_SA_F
FN_LUT(cmp_fns, base, eq, AS); FN_LUT(cmp_fns, base, eq, AA);
FN_LUT(cmp_fns, base, ne, AS); FN_LUT(cmp_fns, base, ne, AA);
FN_LUT(cmp_fns, base, gt, AS); FN_LUT(cmp_fns, base, gt, AA);
FN_LUT(cmp_fns, base, ge, AS); FN_LUT(cmp_fns, base, ge, AA);
FN_LUT(cmp_fns, base, lt, AS);
FN_LUT(cmp_fns, base, le, AS);
FN_LUT_C(cmp_fns, base, eq, AS); FN_LUT_C(cmp_fns, base, eq, AA);
FN_LUT_C(cmp_fns, base, ne, AS); FN_LUT_C(cmp_fns, base, ne, AA);
FN_LUT_C(cmp_fns, base, gt, AS); FN_LUT_C(cmp_fns, base, gt, AA);
FN_LUT_C(cmp_fns, base, ge, AS); FN_LUT_C(cmp_fns, base, ge, AA);
FN_LUT_C(cmp_fns, base, lt, AS);
FN_LUT_C(cmp_fns, base, le, AS);
#endif
#if !CLANGD
#undef FN_LUT
#undef FN_LUT_B
#undef FN_LUT_C
#undef FN_LUT_T
#endif

View File

@ -8,7 +8,7 @@
#define PRECOMPILED_FILE1(X) PRECOMPILED_FILE0(X)
#define PRECOMPILED_FILE(END) PRECOMPILED_FILE1(../build/BYTECODE_DIR/gen/END)
#define FOR_INIT(F) F(base) F(harr) F(mutF) F(fillarr) F(tyarr) F(hash) F(sfns) F(fns) F(arith) F(md1) F(md2) F(derv) F(comp) F(rtWrap) F(ns) F(nfn) F(sysfn) F(inverse) F(slash) F(search) F(load) F(sysfnPost) F(dervPost) F(ffi) F(mmap) F(typesFinished)
#define FOR_INIT(F) F(base) F(harr) F(mutF) F(cmpA) F(fillarr) F(tyarr) F(hash) F(sfns) F(fns) F(arith) F(md1) F(md2) F(derv) F(comp) F(rtWrap) F(ns) F(nfn) F(sysfn) F(inverse) F(slash) F(search) F(load) F(sysfnPost) F(dervPost) F(ffi) F(mmap) F(typesFinished)
#define F(X) void X##_init(void);
FOR_INIT(F)
#undef F

View File

@ -13,10 +13,26 @@ static NOINLINE void cmp_err() { if (please_tail_call_err) thrM("Invalid compari
#include "../gen/cmp.c"
#pragma GCC diagnostic pop
FN_LUT(cmp_fns, avx2, eq, AS); FN_LUT(cmp_fns, avx2, eq, AA);
FN_LUT(cmp_fns, avx2, ne, AS); FN_LUT(cmp_fns, avx2, ne, AA);
FN_LUT(cmp_fns, avx2, gt, AS); FN_LUT(cmp_fns, avx2, gt, AA);
FN_LUT(cmp_fns, avx2, ge, AS); FN_LUT(cmp_fns, avx2, ge, AA);
FN_LUT(cmp_fns, avx2, lt, AS);
FN_LUT(cmp_fns, avx2, le, AS);
FN_LUT_A(cmp_fns, eq, AS); FN_LUT_A(cmp_fns, eq, AA);
FN_LUT_A(cmp_fns, ne, AS); FN_LUT_A(cmp_fns, ne, AA);
FN_LUT_A(cmp_fns, gt, AS); FN_LUT_A(cmp_fns, gt, AA);
FN_LUT_A(cmp_fns, ge, AS); FN_LUT_A(cmp_fns, ge, AA);
FN_LUT_A(cmp_fns, lt, AS);
FN_LUT_A(cmp_fns, le, AS);
#define ARCH(N) avx2_##N
#define DSTE(N) &(cmp_fns_##N[0])
void cmpA_init() {
{
CmpAAFn* srcs[4] = {ARCH(eqAA), ARCH(neAA), ARCH(gtAA), ARCH(geAA)};
CmpAAFn* dsts[4] = {DSTE(eqAA), DSTE(neAA), DSTE(gtAA), DSTE(geAA)};
for (i32 i=0; i<4; i++) for (i32 j=0; j<8; j++) dsts[i][j] = srcs[i][j];
}
{
CmpASFn* srcs[6] = {ARCH(eqAS), ARCH(neAS), ARCH(gtAS), ARCH(geAS), ARCH(ltAS), ARCH(leAS)};
CmpASFn* dsts[6] = {DSTE(eqAS), DSTE(neAS), DSTE(gtAS), DSTE(geAS), DSTE(ltAS), DSTE(leAS)};
for (i32 i=0; i<6; i++) for (i32 j=0; j<8; j++) dsts[i][j] = srcs[i][j];
}
}
#undef ARCH
#undef DSTE

View File

@ -112,29 +112,27 @@ bitAS{op}(dst:*u64, wr:*void, x:u64, len:Size) : void = { # show{'bitAS'}
else call{cpy, dst, *u64~~wr, len}
}
def table{aa, F, w, G_bit, G_vec} = {
tup{
G_bit{},
...each{{E}=>{
def E2 = (if (aa and isunsigned{E} and ((match{F,__eq} | match{F,__ne}) | (E==u32))) {ty_s{E}} else E)
def bulk = w/width{E2}
G_vec{[bulk]E2, max{1, 8/bulk}}
}, tup{i8, i16, i32, f64, u8, u16, u32}}
}
}
def tableAA{w, F, F_bit} = table{1, F, w, {} => bitAA{F_bit}, {V, u} => aa2bit{V, u, F}}
def tableAS{w, F } = table{0, F, w, {} => bitAS{F}, {V, u} => as2bit{V, u, F}}
# arr-arr =≠
'avx2_eqAA_i8','avx2_eqAA_u8'=aa2bit{[32]i8,1,__eq}; 'avx2_eqAA_i16','avx2_eqAA_u16'=aa2bit{[16]i16,1,__eq}; 'avx2_eqAA_i32','avx2_eqAA_u32'=aa2bit{[8]i32,1,__eq}
'avx2_neAA_i8','avx2_neAA_u8'=aa2bit{[32]i8,1,__ne}; 'avx2_neAA_i16','avx2_neAA_u16'=aa2bit{[16]i16,1,__ne}; 'avx2_neAA_i32','avx2_neAA_u32'=aa2bit{[8]i32,1,__ne}
'avx2_eqAA_u1'=bitAA{{a,b}=>a ^ ~b}; 'avx2_eqAA_f64'=aa2bit{[4]f64,2,__eq}
'avx2_neAA_u1'=bitAA{{a,b}=>a ^ b}; 'avx2_neAA_f64'=aa2bit{[4]f64,2,__ne}
# arr-arr >≥
'avx2_gtAA_i8'=aa2bit{[32]i8,1,__gt}; 'avx2_gtAA_i16'=aa2bit{[16]i16,1,__gt}; 'avx2_gtAA_i32','avx2_gtAA_u32'=aa2bit{[8]i32,1,__gt}; 'avx2_gtAA_f64'=aa2bit{[4]f64,2,__gt}
'avx2_geAA_i8'=aa2bit{[32]i8,1,__ge}; 'avx2_geAA_i16'=aa2bit{[16]i16,1,__ge}; 'avx2_geAA_i32','avx2_geAA_u32'=aa2bit{[8]i32,1,__ge}; 'avx2_geAA_f64'=aa2bit{[4]f64,2,__ge}
'avx2_gtAA_u8'=aa2bit{[32]u8,1,__gt}; 'avx2_gtAA_u16'=aa2bit{[16]u16,1,__gt}; 'avx2_gtAA_u1'=bitAA{{a,b}=>a & ~b}
'avx2_geAA_u8'=aa2bit{[32]u8,1,__ge}; 'avx2_geAA_u16'=aa2bit{[16]u16,1,__ge}; 'avx2_geAA_u1'=bitAA{{a,b}=>a | ~b}
def tup_eqAA = tableAA{256, __eq, {a,b}=>a ^ ~b}; v_eqAA:*type{tupsel{0,tup_eqAA}} = tup_eqAA; 'avx2_eqAA'=v_eqAA
def tup_neAA = tableAA{256, __ne, {a,b}=>a ^ b}; v_neAA:*type{tupsel{0,tup_neAA}} = tup_neAA; 'avx2_neAA'=v_neAA
def tup_gtAA = tableAA{256, __gt, {a,b}=>a & ~b}; v_gtAA:*type{tupsel{0,tup_gtAA}} = tup_gtAA; 'avx2_gtAA'=v_gtAA
def tup_geAA = tableAA{256, __ge, {a,b}=>a | ~b}; v_geAA:*type{tupsel{0,tup_geAA}} = tup_geAA; 'avx2_geAA'=v_geAA
# arr-scalar numeric
'avx2_eqAS_i8'=as2bit{[32]i8,1,__eq}; 'avx2_eqAS_i16'=as2bit{[16]i16,1,__eq}; 'avx2_eqAS_i32'=as2bit{[8]i32,1,__eq}; 'avx2_eqAS_f64'=as2bit{[4]f64,2,__eq}
'avx2_neAS_i8'=as2bit{[32]i8,1,__ne}; 'avx2_neAS_i16'=as2bit{[16]i16,1,__ne}; 'avx2_neAS_i32'=as2bit{[8]i32,1,__ne}; 'avx2_neAS_f64'=as2bit{[4]f64,2,__ne}
'avx2_gtAS_i8'=as2bit{[32]i8,1,__gt}; 'avx2_gtAS_i16'=as2bit{[16]i16,1,__gt}; 'avx2_gtAS_i32'=as2bit{[8]i32,1,__gt}; 'avx2_gtAS_f64'=as2bit{[4]f64,2,__gt}
'avx2_geAS_i8'=as2bit{[32]i8,1,__ge}; 'avx2_geAS_i16'=as2bit{[16]i16,1,__ge}; 'avx2_geAS_i32'=as2bit{[8]i32,1,__ge}; 'avx2_geAS_f64'=as2bit{[4]f64,2,__ge}
'avx2_ltAS_i8'=as2bit{[32]i8,1,__lt}; 'avx2_ltAS_i16'=as2bit{[16]i16,1,__lt}; 'avx2_ltAS_i32'=as2bit{[8]i32,1,__lt}; 'avx2_ltAS_f64'=as2bit{[4]f64,2,__lt}
'avx2_leAS_i8'=as2bit{[32]i8,1,__le}; 'avx2_leAS_i16'=as2bit{[16]i16,1,__le}; 'avx2_leAS_i32'=as2bit{[8]i32,1,__le}; 'avx2_leAS_f64'=as2bit{[4]f64,2,__le}
# arr-scalar character & bit
'avx2_eqAS_u8'=as2bit{[32]u8,1,__eq}; 'avx2_eqAS_u16'=as2bit{[16]u16,1,__eq}; 'avx2_eqAS_u32'=as2bit{[8]u32,1,__eq}; 'avx2_eqAS_u1'=bitAS{__eq}
'avx2_neAS_u8'=as2bit{[32]u8,1,__ne}; 'avx2_neAS_u16'=as2bit{[16]u16,1,__ne}; 'avx2_neAS_u32'=as2bit{[8]u32,1,__ne}; 'avx2_neAS_u1'=bitAS{__ne}
'avx2_gtAS_u8'=as2bit{[32]u8,1,__gt}; 'avx2_gtAS_u16'=as2bit{[16]u16,1,__gt}; 'avx2_gtAS_u32'=as2bit{[8]u32,1,__gt}; 'avx2_gtAS_u1'=bitAS{__gt}
'avx2_geAS_u8'=as2bit{[32]u8,1,__ge}; 'avx2_geAS_u16'=as2bit{[16]u16,1,__ge}; 'avx2_geAS_u32'=as2bit{[8]u32,1,__ge}; 'avx2_geAS_u1'=bitAS{__ge}
'avx2_ltAS_u8'=as2bit{[32]u8,1,__lt}; 'avx2_ltAS_u16'=as2bit{[16]u16,1,__lt}; 'avx2_ltAS_u32'=as2bit{[8]u32,1,__lt}; 'avx2_ltAS_u1'=bitAS{__lt}
'avx2_leAS_u8'=as2bit{[32]u8,1,__le}; 'avx2_leAS_u16'=as2bit{[16]u16,1,__le}; 'avx2_leAS_u32'=as2bit{[8]u32,1,__le}; 'avx2_leAS_u1'=bitAS{__le}
def tup_eqAS = tableAS{256, __eq}; v_eqAS:*type{tupsel{0,tup_eqAS}} = tup_eqAS; 'avx2_eqAS'=v_eqAS
def tup_neAS = tableAS{256, __ne}; v_neAS:*type{tupsel{0,tup_neAS}} = tup_neAS; 'avx2_neAS'=v_neAS
def tup_gtAS = tableAS{256, __gt}; v_gtAS:*type{tupsel{0,tup_gtAS}} = tup_gtAS; 'avx2_gtAS'=v_gtAS
def tup_geAS = tableAS{256, __ge}; v_geAS:*type{tupsel{0,tup_geAS}} = tup_geAS; 'avx2_geAS'=v_geAS
def tup_ltAS = tableAS{256, __lt}; v_ltAS:*type{tupsel{0,tup_ltAS}} = tup_ltAS; 'avx2_ltAS'=v_ltAS
def tup_leAS = tableAS{256, __le}; v_leAS:*type{tupsel{0,tup_leAS}} = tup_leAS; 'avx2_leAS'=v_leAS

View File

@ -17,7 +17,7 @@ extern M_FillF fillFns[el_MAX];
typedef void (*CmpAAFn)(u64*, void*, void*, u64);
typedef void (*CmpASFn)(u64*, void*, u64, u64);
#define CMP_DEF(F, S) extern const Cmp##S##Fn cmp_fns_##F##S[];
#define CMP_DEF(F, S) extern Cmp##S##Fn cmp_fns_##F##S[];
CMP_DEF(eq, AS); CMP_DEF(eq, AA);
CMP_DEF(ne, AS); CMP_DEF(ne, AA);
CMP_DEF(gt, AS); CMP_DEF(gt, AA);