Skip to content

Commit

Permalink
Switch folding engine to semi-perfect hash function
Browse files Browse the repository at this point in the history
  • Loading branch information
dstogov committed Mar 13, 2024
1 parent 714db32 commit 1d3df9f
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 7 deletions.
53 changes: 47 additions & 6 deletions gen_ir_fold_hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
#define MAX_RULES 2048
#define MAX_SLOTS (MAX_RULES * 4)

#define USE_SEMI_PERFECT_HASH 1
#define USE_SHL_HASH 1
#define USE_ROL_HASH 0

static ir_strtab strtab;

void print_hash(uint32_t *mask, uint32_t count)
Expand All @@ -28,12 +32,14 @@ void print_hash(uint32_t *mask, uint32_t count)
printf("};\n\n");
}

#if 0
#if USE_SHL_HASH
static uint32_t hash_shl2(uint32_t mask, uint32_t r1, uint32_t r2)
{
return ((mask << r1) - mask) << r2;
}
#else
#endif

#if USE_ROL_HASH
#define ir_rol(x, n) (((x)<<(n)) | ((x)>>(-(int)(n)&(8*sizeof(x)-1))))
#define ir_ror(x, n) (((x)<<(-(int)(n)&(8*sizeof(x)-1))) | ((x)>>(n)))

Expand All @@ -50,29 +56,64 @@ int find_hash(uint32_t *mask, uint32_t count)
uint32_t n, r1, r2, i, h;

for (n = (count | 1); n < MAX_SLOTS; n += 2) {
#if USE_SEMI_PERFECT_HASH
int semi_perfect = 0;
#endif

for (r1 = 0; r1 < 31; r1++) {
for (r2 = 0; r2 < 32; r2++) {
#if 0
#if USE_SHL_HASH
memset(hash, 0, n * sizeof(uint32_t));
for (i = 0; i < count; i++) {
h = hash_shl2(mask[i] & 0x1fffff, r1, r2) % n;
if (hash[h]) break; /* collision */
if (hash[h]) {
#if USE_SEMI_PERFECT_HASH
h++;
if (!hash[h]) {
hash[h] = mask[i];
semi_perfect = 1;
continue;
}
#endif
break; /* collision */
}
hash[h] = mask[i];
}
if (i == count) {
print_hash(hash, n);
#if USE_SEMI_PERFECT_HASH
if (semi_perfect) {
printf("#define IR_FOLD_SEMI_PERFECT_HASH\n\n");
}
#endif
printf("static uint32_t _ir_fold_hashkey(uint32_t h)\n{\n\treturn (((h << %d) - h) << %d) %% %d;\n}\n", r1, r2, n);
return 1;
}
#else
#endif
#if USE_ROL_HASH
memset(hash, 0, n * sizeof(uint32_t));
for (i = 0; i < count; i++) {
h = hash_rol2(mask[i] & 0x1fffff, r1, r2) % n;
if (hash[h]) break; /* collision */
if (hash[h]) {
#if USE_SEMI_PERFECT_HASH
h++;
if (!hash[h]) {
hash[h] = mask[i];
semi_perfect = 1;
continue;
}
#endif
break; /* collision */
}
hash[h] = mask[i];
}
if (i == count) {
print_hash(hash, n);
#if USE_SEMI_PERFECT_HASH
if (semi_perfect) {
printf("#define IR_FOLD_SEMI_PERFECT_HASH\n\n");
}
#endif
printf("static uint32_t _ir_fold_hashkey(uint32_t h)\n{\nreturn ir_rol32((ir_rol32(h, %d) - h), %d) %% %d;\n}\n", r1, r2, n);
return 1;
}
Expand Down
6 changes: 5 additions & 1 deletion ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -926,7 +926,11 @@ ir_ref ir_folding(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2, ir_ref op3,
uint32_t k = key & any;
uint32_t h = _ir_fold_hashkey(k);
uint32_t fh = _ir_fold_hash[h];
if (IR_FOLD_KEY(fh) == k /*|| (fh = _ir_fold_hash[h+1], (fh & 0x1fffff) == k)*/) {
if (IR_FOLD_KEY(fh) == k
#ifdef IR_FOLD_SEMI_PERFECT_HASH
|| (fh = _ir_fold_hash[h+1], (fh & 0x1fffff) == k)
#endif
) {
switch (IR_FOLD_RULE(fh)) {
#include "ir_fold.h"
default:
Expand Down

0 comments on commit 1d3df9f

Please sign in to comment.