Fixture 17
hash table
C · 2 functions · 4 lanes · 8 of 8 function-lanes behave identically
All 4 lanes recompile and return the same results as the original.
#include <stdint.h>
#define HASH_EMPTY INT32_MIN
static uint32_t hash_slot(int32_t key, int32_t capacity) {
return ((uint32_t)key * 2654435761u) % (uint32_t)capacity;
}
__attribute__((noinline)) int32_t hash_lookup(const int32_t *keys,
const int32_t *values,
int32_t capacity, int32_t key) {
uint32_t start;
int32_t probe;
if (keys == 0 || values == 0 || capacity <= 0 || capacity > 16 ||
key == HASH_EMPTY) {
return -1;
}
start = hash_slot(key, capacity);
for (probe = 0; probe < capacity; ++probe) {
uint32_t slot = (start + (uint32_t)probe) % (uint32_t)capacity;
if (keys[slot] == HASH_EMPTY) {
return -1;
}
if (keys[slot] == key) {
return values[slot];
}
}
return -1;
}
__attribute__((noinline)) int32_t hash_insert(int32_t *keys, int32_t *values,
int32_t capacity, int32_t key,
int32_t value) {
uint32_t start;
int32_t probe;
if (keys == 0 || values == 0 || capacity <= 0 || capacity > 16 ||
key == HASH_EMPTY) {
return -1;
}
start = hash_slot(key, capacity);
for (probe = 0; probe < capacity; ++probe) {
uint32_t slot = (start + (uint32_t)probe) % (uint32_t)capacity;
if (keys[slot] == HASH_EMPTY || keys[slot] == key) {
keys[slot] = key;
values[slot] = value;
return (int32_t)slot;
}
}
return -1;
} Recovered C
Generated by glaurung decompile --style decbench at b47f6b43.
baseline.json records the result after recompiling the C and calling it beside the
original with seeded inputs.
clang -O0
2/2hash_insert pass 51 lines
// glaurung: hash_insert @ 0x1210
int32_t hash_insert(int32_t * arg0, int32_t * arg1, int32_t arg2, int32_t arg3, int32_t arg4) {
extern unsigned int hash_slot(int, int);
unsigned int start;
int probe;
unsigned int slot;
int local_4;
unsigned int var0;
if ((arg0 != 0)) {
if ((arg1 != 0)) {
if (((((unsigned long)((unsigned int)(arg2)) == 0) | ((long)(arg2) < 0)) == 0)) {
if (((((unsigned long)((unsigned int)(arg2)) == 16) | ((long)(arg2) < 16)) != 0)) {
if (((unsigned long)((unsigned int)(arg3)) != 0x80000000)) {
goto L_126d;
}
}
}
}
}
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
L_126d: ;
var0 = hash_slot((unsigned long)((unsigned int)(arg3)), (unsigned long)((unsigned int)(arg2)));
start = var0;
probe = 0;
L_1282: ;
if ((arg2 <= probe)) {
goto L_12fb;
}
slot = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)((unsigned long)((unsigned int)((start + probe))))) % (unsigned int)(arg2))));
if (((unsigned long)((unsigned int)(arg0[slot])) != 0x80000000)) {
if (((unsigned int)(arg0[slot]) != (unsigned int)(arg3))) {
goto L_12e8;
}
}
arg0[slot] = arg3;
arg1[slot] = arg4;
local_4 = slot;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
L_12e8: ;
goto L_12ed;
L_12ed: ;
probe = ((unsigned int)(probe) + 1);
goto L_1282;
L_12fb: ;
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} hash_lookup pass 50 lines
// glaurung: hash_lookup @ 0x1100
int32_t hash_lookup(const int32_t * arg0, const int32_t * arg1, int32_t arg2, int32_t arg3) {
extern unsigned int hash_slot(int, int);
unsigned int start;
int probe;
unsigned int slot;
int local_4;
unsigned int var0;
if ((arg0 != 0)) {
if ((arg1 != 0)) {
if (((((unsigned long)((unsigned int)(arg2)) == 0) | ((long)(arg2) < 0)) == 0)) {
if (((((unsigned long)((unsigned int)(arg2)) == 16) | ((long)(arg2) < 16)) != 0)) {
if (((unsigned long)((unsigned int)(arg3)) != 0x80000000)) {
goto L_1159;
}
}
}
}
}
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
L_1159: ;
var0 = hash_slot((unsigned long)((unsigned int)(arg3)), (unsigned long)((unsigned int)(arg2)));
start = var0;
probe = 0;
L_116e: ;
if ((arg2 <= probe)) {
goto L_11e0;
}
slot = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)((unsigned long)((unsigned int)((start + probe))))) % (unsigned int)(arg2))));
if (((unsigned long)((unsigned int)(arg0[slot])) == 0x80000000)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((unsigned int)(arg0[slot]) == (unsigned int)(arg3))) {
local_4 = arg1[slot];
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
goto L_11d2;
L_11d2: ;
probe = ((unsigned int)(probe) + 1);
goto L_116e;
L_11e0: ;
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} clang -O2
2/2hash_insert pass 58 lines
// glaurung: hash_insert @ 0x1170
int32_t hash_insert(int32_t * arg0, int32_t * arg1, int32_t arg2, int32_t arg3, int32_t arg4) {
unsigned int start;
unsigned int slot;
int probe;
long local_10;
long var0;
long var1;
long var14;
long var15;
long var21;
int var23;
long var4;
local_10 = var0;
var1 = 0xffffffff;
if (((unsigned long)((unsigned int)(arg3)) == 0x80000000)) {
// x86-64 epilogue: tear down frame
return (unsigned int)(var1);
}
if ((arg0 == 0)) {
// x86-64 epilogue: tear down frame
return (unsigned int)(var1);
}
if ((arg1 == 0)) {
// x86-64 epilogue: tear down frame
return (unsigned int)(var1);
}
var4 = (unsigned long)((unsigned int)(arg2));
if (((unsigned long)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg2)) - 17)))) < (unsigned long)(0xfffffff0))) {
// x86-64 epilogue: tear down frame
return (unsigned int)(var1);
}
start = (unsigned long)((unsigned int)(((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)((arg3 * -0x61c8864fLL))) % (unsigned int)(var4))))));
var14 = (unsigned long)((unsigned int)(var4));
var15 = 0;
L_11b0: ;
while (1) {
slot = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)((unsigned long)((unsigned int)((var15 + start))))) % (unsigned int)(var4))));
var21 = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + slot * 4))));
if ((((unsigned long)((unsigned int)(var21)) == 0x80000000) || ((unsigned int)(var21) == (unsigned int)(arg3)))) {
break;
}
var15 = (unsigned long)((unsigned int)((var15 + 1)));
var23 = (var14 - 1);
var14 = (unsigned long)((unsigned int)(var23));
if (((unsigned long)((unsigned int)(var23)) != 0)) {
goto L_11b0;
} else {
}
// x86-64 epilogue: tear down frame
return (unsigned int)(var1);
}
arg0[slot] = arg3;
arg1[slot] = arg4;
var1 = (unsigned long)(slot);
// x86-64 epilogue: tear down frame
return slot;
} hash_lookup pass 51 lines
// glaurung: hash_lookup @ 0x1100
int32_t hash_lookup(const int32_t * arg0, const int32_t * arg1, int32_t arg2, int32_t arg3) {
unsigned int start;
unsigned int slot;
int probe;
long var0;
long var1;
long var11;
long var12;
long var18;
int var20;
var0 = 0xffffffff;
if (((unsigned long)((unsigned int)(arg3)) == 0x80000000)) {
// x86-64 epilogue: tear down frame
return (unsigned int)(var0);
}
if ((arg0 == 0)) {
// x86-64 epilogue: tear down frame
return (unsigned int)(var0);
}
if ((arg1 == 0)) {
// x86-64 epilogue: tear down frame
return (unsigned int)(var0);
}
var1 = (unsigned long)((unsigned int)(arg2));
if (((unsigned long)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg2)) - 17)))) < (unsigned long)(0xfffffff0))) {
// x86-64 epilogue: tear down frame
return (unsigned int)(var0);
}
start = (unsigned long)((unsigned int)(((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)((arg3 * -0x61c8864fLL))) % (unsigned int)(var1))))));
var11 = (unsigned long)((unsigned int)(var1));
var12 = 0;
do {
slot = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)((unsigned long)((unsigned int)((var12 + start))))) % (unsigned int)(var1))));
var18 = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + slot * 4))));
if (((unsigned long)((unsigned int)(var18)) == 0x80000000)) {
// x86-64 epilogue: tear down frame
return (unsigned int)(var0);
}
if (((unsigned int)(var18) == (unsigned int)(arg3))) {
var0 = (unsigned long)((unsigned int)(arg1[slot]));
// x86-64 epilogue: tear down frame
return (unsigned int)(var0);
}
var12 = (unsigned long)((unsigned int)((var12 + 1)));
var20 = (var11 - 1);
var11 = (unsigned long)((unsigned int)(var20));
} while (((unsigned long)((unsigned int)(var20)) != 0));
// x86-64 epilogue: tear down frame
return (unsigned int)(var0);
} gcc -O0
2/2hash_insert pass 45 lines
// glaurung: hash_insert @ 0x11f9
int32_t hash_insert(int32_t * arg0, int32_t * arg1, int32_t arg2, int32_t arg3, int32_t arg4) {
extern unsigned int hash_slot(int, int);
unsigned int start;
int probe;
unsigned int slot;
unsigned int var2;
if ((arg0 != 0)) {
if ((arg1 != 0)) {
if (((((unsigned long)((unsigned int)(arg2)) == 0) | ((long)(arg2) < 0)) == 0)) {
if (((((unsigned long)((unsigned int)(arg2)) == 16) | ((long)(arg2) < 16)) != 0)) {
if (((unsigned long)((unsigned int)(arg3)) != 0x80000000)) {
goto L_1244;
}
}
}
}
}
// x86-64 epilogue: restore rbp
return 0xffffffff;
L_1244: ;
var2 = hash_slot((unsigned long)((unsigned int)(arg3)), (unsigned long)((unsigned int)(arg2)));
start = var2;
probe = 0;
goto L_12e2;
L_1262: ;
slot = ((unsigned int)(((((unsigned long long)(unsigned int)(0) << 32) | (unsigned int)((unsigned long)((unsigned int)((start + (unsigned long)((unsigned int)(probe))))))) % (unsigned int)((unsigned long)((unsigned int)(arg2))))));
if (((unsigned long)((unsigned int)(arg0[slot])) != 0x80000000)) {
if (((unsigned int)(arg3) != (unsigned int)(arg0[slot]))) {
goto L_12de;
}
}
arg0[slot] = arg3;
arg1[slot] = arg4;
// x86-64 epilogue: restore rbp
return slot;
L_12de: ;
probe = (probe + 1);
L_12e2: ;
if ((probe < arg2)) {
goto L_1262;
}
// x86-64 epilogue: restore rbp
return 0xffffffff;
} hash_lookup pass 43 lines
// glaurung: hash_lookup @ 0x111e
int32_t hash_lookup(const int32_t * arg0, const int32_t * arg1, int32_t arg2, int32_t arg3) {
extern unsigned int hash_slot(int, int);
unsigned int start;
int probe;
unsigned int slot;
unsigned int var2;
if ((arg0 != 0)) {
if ((arg1 != 0)) {
if (((((unsigned long)((unsigned int)(arg2)) == 0) | ((long)(arg2) < 0)) == 0)) {
if (((((unsigned long)((unsigned int)(arg2)) == 16) | ((long)(arg2) < 16)) != 0)) {
if (((unsigned long)((unsigned int)(arg3)) != 0x80000000)) {
goto L_1165;
}
}
}
}
}
// x86-64 epilogue: restore rbp
return 0xffffffff;
L_1165: ;
var2 = hash_slot((unsigned long)((unsigned int)(arg3)), (unsigned long)((unsigned int)(arg2)));
start = var2;
probe = 0;
goto L_11ea;
L_1180: ;
slot = ((unsigned int)(((((unsigned long long)(unsigned int)(0) << 32) | (unsigned int)((unsigned long)((unsigned int)((start + (unsigned long)((unsigned int)(probe))))))) % (unsigned int)((unsigned long)((unsigned int)(arg2))))));
if (((unsigned long)((unsigned int)(arg0[slot])) == 0x80000000)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
if (((unsigned int)(arg3) == (unsigned int)(arg0[slot]))) {
// x86-64 epilogue: restore rbp
return (unsigned int)(arg1[(unsigned long)(slot)]);
}
probe = (probe + 1);
L_11ea: ;
if ((probe < arg2)) {
goto L_1180;
}
// x86-64 epilogue: restore rbp
return 0xffffffff;
} gcc -O2
2/2hash_insert pass 57 lines
// glaurung: hash_insert @ 0x1180
int32_t hash_insert(int32_t * arg0, int32_t * arg1, int32_t arg2, int32_t arg3, int32_t arg4) {
unsigned int start;
int probe;
unsigned int slot;
long local_10;
long var0;
int var12;
long var2;
long var21;
long var22;
long var23;
int var24;
long var3;
long var7;
long var8;
if ((arg0 == 0)) {
return 0xffffffff;
}
var0 = (long)arg1;
if ((arg1 == 0)) {
return 0xffffffff;
}
var2 = (unsigned long)((unsigned int)(arg2));
if (((unsigned long)(15) < (unsigned long)((unsigned long)((unsigned int)((arg2 - 1)))))) {
return 0xffffffff;
}
var3 = (unsigned long)((unsigned int)(arg3));
if (((unsigned long)((unsigned int)(arg3)) == 0x80000000)) {
return 0xffffffff;
}
var7 = (long)arg0;
local_10 = var8;
var12 = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)((arg3 * -0x61c8864fLL))) % (unsigned int)((unsigned long)((unsigned int)(arg2))))));
start = (unsigned long)((unsigned int)(var12));
probe = 0;
slot = var12;
while (1) {
slot = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)((unsigned long)((unsigned int)((probe + start))))) % (unsigned int)(var2))));
var21 = ((unsigned long)(slot) << 2);
var22 = (var7 + var21);
var23 = (unsigned long)((unsigned int)(*(int *)((var22))));
if ((((unsigned int)(var23) == (unsigned int)(var3)) || ((unsigned long)((unsigned int)(var23)) == 0x80000000))) {
break;
}
var24 = (probe + 1);
probe = (unsigned long)((unsigned int)(var24));
if (((((unsigned int)(var2) == (unsigned int)(var24)) | ((long)((int)(var2)) < (long)((int)(var24)))) != 0)) {
// x86-64 epilogue: tear down frame
return 0xffffffff;
}
}
*(int *)((var22)) = var3;
*(int *)((var0 + var21)) = arg4;
// x86-64 epilogue: tear down frame
return slot;
} hash_lookup pass 48 lines
// glaurung: hash_lookup @ 0x1100
int32_t hash_lookup(const int32_t * arg0, const int32_t * arg1, int32_t arg2, int32_t arg3) {
unsigned int start;
int probe;
long var0;
long var1;
int var11;
long var18;
long var19;
long var2;
int var20;
long var3;
var0 = (long)arg0;
var1 = (long)arg1;
var2 = (unsigned long)((unsigned int)(arg3));
var3 = (unsigned long)((unsigned int)(arg2));
if ((arg0 != 0)) {
if ((arg1 == 0)) {
return 0xffffffff;
}
if (((unsigned long)(15) < (unsigned long)((unsigned long)((unsigned int)((arg2 - 1)))))) {
return 0xffffffff;
}
if (((unsigned long)((unsigned int)(arg3)) == 0x80000000)) {
return 0xffffffff;
}
var11 = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)((arg3 * -0x61c8864fLL))) % (unsigned int)((unsigned long)((unsigned int)(arg2))))));
start = (unsigned long)((unsigned int)(var11));
probe = 0;
while (1) {
var11 = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)((unsigned long)((unsigned int)((probe + start))))) % (unsigned int)(var3))));
var18 = (unsigned long)((unsigned int)(*(int *)((var0 + var11 * 4))));
var19 = ((unsigned long)((unsigned int)(var11)) * 4);
if (((unsigned long)((unsigned int)(var18)) == 0x80000000)) {
break;
}
if (((unsigned int)(var18) == (unsigned int)(var2))) {
return (unsigned int)(*(int *)((var1 + var19)));
}
var20 = (probe + 1);
probe = (unsigned long)((unsigned int)(var20));
if (((((unsigned int)(var3) == (unsigned int)(var20)) | ((long)((int)(var3)) < (long)((int)(var20)))) != 0)) {
break;
}
}
}
return 0xffffffff;
}