diff --git a/makefile b/makefile index b8649cf9..6c5a5aba 100644 --- a/makefile +++ b/makefile @@ -271,7 +271,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 copy.c equal.c squeeze.c scan.c neq.c slash.c constrep.c bits.c} +build_singeli: ${addprefix src/singeli/gen/, cmp.c dyarith.c copy.c equal.c squeeze.c fold.c scan.c neq.c slash.c constrep.c bits.c} @echo $(postmsg) src/singeli/gen/%.c: src/singeli/src/%.singeli preSingeliBin @echo $< | cut -c 17- | sed 's/^/ /' diff --git a/src/builtins/fold.c b/src/builtins/fold.c index 4c55020a..fcced21e 100644 --- a/src/builtins/fold.c +++ b/src/builtins/fold.c @@ -1,6 +1,13 @@ #include "../core.h" #include "../builtins.h" +#if SINGELI + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wunused-variable" + #include "../singeli/gen/fold.c" + #pragma GCC diagnostic pop +#endif + static bool fold_ne(u64* x, u64 am) { u64 r = 0; for (u64 i = 0; i < (am>>6); i++) r^= x[i]; @@ -55,7 +62,13 @@ static f64 (*const sum_fns[])(void*, usz, f64) = { sum_i8, sum_i16, sum_i32, sum #define DEF_MIN_MAX(T) \ static f64 min_##T(void* xv, usz ia) { MIN_MAX(T,<) } \ static f64 max_##T(void* xv, usz ia) { MIN_MAX(T,>) } -DEF_MIN_MAX(i8) DEF_MIN_MAX(i16) DEF_MIN_MAX(i32) DEF_MIN_MAX(f64) +DEF_MIN_MAX(i8) DEF_MIN_MAX(i16) DEF_MIN_MAX(i32) +#if SINGELI + static f64 min_f64(void* xv, usz ia) { return avx2_fold_min_f64(xv,ia); } + static f64 max_f64(void* xv, usz ia) { return avx2_fold_max_f64(xv,ia); } +#else + DEF_MIN_MAX(f64) +#endif #undef DEF_MIN_MAX #undef MIN_MAX static f64 (*const min_fns[])(void*, usz) = { min_i8, min_i16, min_i32, min_f64 }; diff --git a/src/singeli/src/fold.singeli b/src/singeli/src/fold.singeli new file mode 100644 index 00000000..7986a361 --- /dev/null +++ b/src/singeli/src/fold.singeli @@ -0,0 +1,41 @@ +include './base' +include './sse3' +include './avx' +include './avx2' +include './mask' + +fold_idem{T==f64, op}(x:*T, len:u64) : T = { + def step = 256/width{T} + def V = [step]T + xv:= *V ~~ x + r:V = broadcast{[4]f64, 0} + if (len < step) { + # Can't overlap like the long case + assert{len > 0} + r = load{xv} + if (len > 1) { + if (len > 2) r = op{r, shuf{[4]u64, r, 4b2222}} + r = op{r, shuf{[4]u64, r, 4b1111}} + } + } else { + # Pairwise combination to shorten dependency chains + def pairwise{p, i, k} = { + def l = k-1 + op{pairwise{p, i , l}, + pairwise{p, i+(1<> pk + @for (i to f) r = op{r, pairwise{xv+(i<