From 041a87ff988d6d865b290103645231a08673e51c Mon Sep 17 00:00:00 2001 From: dzaima Date: Sun, 10 Jul 2022 01:51:15 +0300 Subject: [PATCH] =?UTF-8?q?make=20valgrind=20accept=20/=F0=9D=95=A9=20and?= =?UTF-8?q?=20=F0=9D=95=A8/=F0=9D=95=A9=20impls?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/sfns.c | 92 ++++++++++++++++++++++++++++++++++- src/builtins/sysfn.c | 10 ++++ src/core/stuff.c | 34 +++++++++++++ src/opt/mm_buddyTemplate.h | 4 ++ src/singeli/src/bmi2.singeli | 3 ++ src/singeli/src/slash.singeli | 6 ++- src/utils/valgrind.h | 28 +++++++++++ 7 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 src/utils/valgrind.h diff --git a/src/builtins/sfns.c b/src/builtins/sfns.c index 82413e40..61181c07 100644 --- a/src/builtins/sfns.c +++ b/src/builtins/sfns.c @@ -326,6 +326,96 @@ B pick_c2(B t, B w, B x) { #ifdef __BMI2__ #include + + #if USE_VALGRIND + #define DBG_VG_SLASH 0 + u64 loadMask(u64* p, u64 unk, u64 exp, u64 i, u64 pos) { + // #if DBG_VG_SLASH + // if (pos==0) printf("index %2ld, got %016lx\n", i, p[i]); + // #endif + if (pos==0) return ~(p[i]^exp); + u64 res = loadMask(p, unk, exp, i, pos<<1); + if (unk&pos) res&= loadMask(p, unk, exp, i|pos, pos<<1); + return res; + } + NOINLINE u64 vg_load64(u64* p, u64 i) { + u64 unk = ~vg_getDefined_u64(i); + u64 res = p[vg_withDefined_u64(i, ~0ULL)]; // result value will always be the proper indexing operation + + i32 undefCount = POPC(unk); + if (undefCount>0) { + if (undefCount>8) err("too many unknown bits in index of vg_load64"); + res = vg_withDefined_u64(res, loadMask(p, unk, res, i & ~unk, 1)); + } + #if DBG_VG_SLASH + vg_printDefined_u64("idx", i); + vg_printDefined_u64("res", res); + #endif + return res; + } + NOINLINE u64 vg_pext_u64(u64 src, u64 mask) { + u64 maskD = vg_getDefined_u64(mask); + u64 r = vg_undef_u64(0); + i32 ri = 0; + u64 undefMask = 0; + for (i32 i = 0; i < 64; i++) { + u64 c = 1ull<>i)&1) { + r|= (c&1) << i; + c>>= 1; + } + } + #if DBG_VG_SLASH + printf("pdep:\n"); + vg_printDefined_u64("src", src); + vg_printDefined_u64("msk", mask); + vg_printDefined_u64("res", r); + vg_printDefined_u64("exp", _pdep_u64(src, mask)); + #endif + return r; + } + u64 vgRand64(u64 range); + NOINLINE u64 rand_popc64(u64 x) { + u64 def = vg_getDefined_u64(x); + if (def==~0ULL) return POPC(x); + i32 min = POPC(x & def); + i32 diff = POPC(~def); + i32 res = min + vgRand64(diff); + #if DBG_VG_SLASH + printf("popc:\n"); + vg_printDefined_u64("x", x); + printf("popc in %d-%d; res: %d\n", min, min+diff, res); + #endif + return res; + } + #define _pext_u32 vg_pext_u64 + #define _pext_u64 vg_pext_u64 + #define _pdep_u32 vg_pdep_u64 + #define _pdep_u64 vg_pdep_u64 + #else + #define vg_load64(p, i) p[i] + #define rand_popc64(X) POPC(X) + #endif + void storeu_u64(u64* p, u64 v) { memcpy(p, &v, 8); } u64 loadu_u64(u64* p) { u64 v; memcpy(&v, p, 8); return v; } #if SINGELI @@ -433,7 +523,7 @@ B slash_c2(B t, B w, B x) { for (usz i=0; i=64) { diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index a3f000e2..a5aeb8f4 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -494,7 +494,17 @@ B rand_subset_c2(B t, B w, B x) { return r; } +#if USE_VALGRIND +u64 vgRandSeed; +u64 vgRand64(u64 range) { + return wy2u0k(wyrand(&vgRandSeed), range); +} +#endif + static NOINLINE void rand_init() { + #if USE_VALGRIND + vgRandSeed = nsTime(); + #endif rand_ns = m_nnsDesc("seed1", "seed2", "range", "deal", "subset"); NSDesc* d = rand_ns->nsDesc; d->expGIDs[0] = d->expGIDs[1] = -1; diff --git a/src/core/stuff.c b/src/core/stuff.c index c5e163b3..9bf2648f 100644 --- a/src/core/stuff.c +++ b/src/core/stuff.c @@ -697,6 +697,40 @@ NOINLINE void print_allocStats() { #endif } + +#if USE_VALGRIND + static void printBitDef(u8 val, u8 def) { + printf("%s", def&1? val&1?"1":"0" : val&1?"¹":"⁰"); + } + void vg_printDump_p(char* name, void* data, u64 len) { + u8 vbits[len]; + int r = VALGRIND_GET_VBITS(data, vbits, len); + + printf("%s:\n", name); + if (r!=1) printf("(failed to get vbits)\n"); + + for (u64 i = 0; i < len; i++) { + if (i!=0) printf(i&7? " " : "\n"); + u8 cv = ~vbits[i]; + u8 cd = ((u8*)data)[i]; + VALGRIND_SET_VBITS(&cd, &(u8[]){0}, 1); + for (i32 j = 7; j >= 0; j--) { + printBitDef(cd>>j, cv>>j); + } + } + putchar('\n'); + } + void vg_printDefined_u64(char* name, u64 x) { + printf("%s: ", name); + u64 d = vg_getDefined_u64(x); + u64 xv = x; + VALGRIND_MAKE_MEM_DEFINED(&xv, 8); + + for (i32 i = 63; i >= 0; i--) printBitDef(xv>>i, d>>i); + printf("\n"); + } +#endif + // for gdb B info_c2(B, B, B); Value* g_v(B x) { return v(x); } diff --git a/src/opt/mm_buddyTemplate.h b/src/opt/mm_buddyTemplate.h index 5036a4c2..8dca290b 100644 --- a/src/opt/mm_buddyTemplate.h +++ b/src/opt/mm_buddyTemplate.h @@ -1,3 +1,7 @@ +#ifdef USE_VALGRIND + #include "../utils/valgrind.h" +#endif + #define buckets BN(buckets) static void BN(free)(Value* x) { onFree(x); diff --git a/src/singeli/src/bmi2.singeli b/src/singeli/src/bmi2.singeli index b2d13147..cfb6c24b 100644 --- a/src/singeli/src/bmi2.singeli +++ b/src/singeli/src/bmi2.singeli @@ -4,3 +4,6 @@ def pext{x:u64, m:u64} = emit{u64, '_pext_u64', x, m} def pext{x:u32, m:u32} = emit{u32, '_pext_u32', x, m} def popc{x:T & isint{T} & width{T}==64} = emit{u8, '__builtin_popcountll', x} def popc{x:T & isint{T} & width{T}<=32} = emit{u8, '__builtin_popcount', x} + +def popcRand{x:T & isint{T} & width{T}==64} = emit{u8, 'rand_popc64', x} # under valgrind, return a random result in the range of possible ones +def popcRand{x:T & isint{T} & width{T}<=32} = emit{u8, 'rand_popc64', x} diff --git a/src/singeli/src/slash.singeli b/src/singeli/src/slash.singeli index 20b6f3ef..899dcb6a 100644 --- a/src/singeli/src/slash.singeli +++ b/src/singeli/src/slash.singeli @@ -20,11 +20,13 @@ def tab{n,l} = { def tab{n==0,l} = tup{0} c16lut:*u64 = tab{4,16} +def vgLoad{p:T, i & T == *u64} = emit{eltype{T}, 'vg_load64', p, i} + def comp16{w:*u64, X, r:*i16, l:u64} = { @for(w in *u8~~w over i to cdiv{l,8}) { def step{w} = { - pc:= popc{w} - storeu{*u64~~r, 0, pext{promote{u64,X{}}, load{c16lut, w}}} + pc:= popcRand{w} + storeu{*u64~~r, 0, pext{promote{u64,X{}}, vgLoad{c16lut, w}}} r+= pc } step{w&15} diff --git a/src/utils/valgrind.h b/src/utils/valgrind.h new file mode 100644 index 00000000..dec351f4 --- /dev/null +++ b/src/utils/valgrind.h @@ -0,0 +1,28 @@ +#pragma once +#include + +static u64 vg_getDefined_u64(u64 x) { // for each bit, returns whether it is defined + u64 r; + i32 v = VALGRIND_GET_VBITS(&x, &r, 8); + if(v==0) return ~0ULL; // don't do weird stuff if not on valgrind + if (v!=1) err("unexpected VALGRIND_GET_VBITS result"); + return ~r; +} +static u64 vg_withDefined_u64(u64 x, u64 where) { + where = ~where; + i32 v = VALGRIND_SET_VBITS(&x, &where, 8); + if (v>1) err("unexpected VALGRIND_SET_VBITS result"); + return x; +} +static u64 vg_undef_u64(u64 x) { + return vg_withDefined_u64(x, 0); +} +static u64 vg_def_u64(u64 x) { + return vg_withDefined_u64(x, ~0ULL); +} +static u64 vg_withBit_u64(u64 r, i32 i, bool val) { + return (r & ~(1ULL<