Fixture 50
varint
C · 4 functions · 4 lanes · 16 of 16 function-lanes behave identically
All 4 lanes recompile and return the same results as the original.
LEB128 varint encode/decode with zigzag mapping for signed values. The continuation-bit loop mixes a 64-bit accumulator with a 7-bit shift, so the recovered shift amount and the accumulator width both matter.
#include <stdint.h>
/* LEB128 varint encode/decode with zigzag mapping for signed values. The
* continuation-bit loop mixes a 64-bit accumulator with a 7-bit shift, so the
* recovered shift amount and the accumulator width both matter. */
#define VARINT_MAX 16
__attribute__((noinline)) uint32_t zigzag_encode(int32_t value) {
return ((uint32_t)value << 1) ^ (uint32_t)(value >> 31);
}
__attribute__((noinline)) int32_t zigzag_decode(uint32_t encoded) {
return (int32_t)((encoded >> 1) ^ (uint32_t)(-(int32_t)(encoded & 1u)));
}
__attribute__((noinline)) int32_t
varint_encode(uint32_t value, uint8_t *output, int32_t capacity) {
int32_t produced = 0;
if (output == 0 || capacity < 1 || capacity > VARINT_MAX) {
return -1;
}
do {
uint8_t chunk = (uint8_t)(value & 0x7Fu);
value >>= 7;
if (value != 0u) {
chunk |= 0x80u;
}
if (produced >= capacity) {
return -2;
}
output[produced] = chunk;
produced += 1;
} while (value != 0u);
return produced;
}
__attribute__((noinline)) int32_t
varint_decode(const uint8_t *input, int32_t length, uint32_t *value) {
uint64_t accumulator = 0;
int32_t shift = 0;
int32_t index;
if (input == 0 || value == 0 || length < 0 || length > VARINT_MAX) {
return -1;
}
for (index = 0; index < length; ++index) {
uint8_t chunk = input[index];
if (shift > 28) {
return -2;
}
accumulator |= (uint64_t)(chunk & 0x7Fu) << (uint32_t)shift;
shift += 7;
if ((chunk & 0x80u) == 0u) {
if (accumulator > 0xFFFFFFFFULL) {
return -3;
}
*value = (uint32_t)accumulator;
return index + 1;
}
}
return -4;
} 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
4/4varint_decode pass 55 lines
// glaurung: varint_decode @ 0x1200
int32_t varint_decode(const uint8_t * arg0, int32_t arg1, uint32_t * arg2) {
unsigned long accumulator;
int shift;
int index;
unsigned char chunk;
int local_4;
accumulator = 0;
shift = 0;
if ((arg0 != 0)) {
if ((arg2 != 0)) {
if ((0 <= (long)(arg1))) {
if ((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16))) {
goto L_1254;
}
}
}
}
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
L_1254: ;
index = 0;
L_125b: ;
if ((arg1 <= index)) {
goto L_1305;
}
chunk = arg0[index];
if (((((unsigned long)((unsigned int)(shift)) == 28) | ((long)(shift) < 28)) == 0)) {
local_4 = -2;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
accumulator = (((unsigned long)((unsigned int)(((unsigned int)(chunk) & 127))) << ((unsigned long)((unsigned int)(shift)) & 63)) | accumulator);
shift = ((unsigned int)(shift) + 7);
if (((unsigned long)((unsigned int)(((unsigned int)(chunk) & 128))) == 0)) {
if (((unsigned long)(0xffffffff) < (unsigned long)(accumulator))) {
local_4 = -3;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
*(int *)((long)arg2) = accumulator;
local_4 = ((unsigned int)(index) + 1);
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
goto L_12f7;
L_12f7: ;
index = ((unsigned int)(index) + 1);
goto L_125b;
L_1305: ;
local_4 = -4;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} varint_encode pass 38 lines
// glaurung: varint_encode @ 0x1140
int32_t varint_encode(uint32_t arg0, uint8_t * arg1, int32_t arg2) {
int produced;
unsigned char chunk;
int local_4;
produced = 0;
if ((arg1 != 0)) {
if ((1 <= (long)(arg2))) {
if ((((unsigned long)((unsigned int)(arg2)) == 16) | ((long)(arg2) < 16))) {
goto L_1180;
}
}
}
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
L_1180: ;
goto L_1185;
L_1185: ;
chunk = (arg0 & 127);
arg0 = ((unsigned int)(arg0) >> 7);
if ((arg0 != 0)) {
chunk = (chunk | 128);
}
if ((arg2 <= produced)) {
local_4 = -2;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
arg1[produced] = chunk;
produced = ((unsigned int)(produced) + 1);
if ((arg0 != 0)) {
goto L_1185;
}
local_4 = produced;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} zigzag_decode pass 6 lines
// glaurung: zigzag_decode @ 0x1120
int32_t zigzag_decode(uint32_t arg0) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) >> 1))) ^ (unsigned long)((unsigned int)((0 - (unsigned long)((unsigned int)(((unsigned long)(arg0) & 1))))))));
} zigzag_encode pass 6 lines
// glaurung: zigzag_encode @ 0x1100
uint32_t zigzag_encode(int32_t arg0) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) << 1))) ^ (unsigned long)((unsigned int)(((int)(arg0) >> 31)))));
} clang -O2
4/4varint_decode pass 80 lines
// glaurung: varint_decode @ 0x1180
int32_t varint_decode(const uint8_t * arg0, int32_t arg1, uint32_t * arg2) {
unsigned long accumulator;
int index;
int shift;
long ret;
int var0;
int var11;
int var17;
int var23;
long var32;
int var4;
int var5;
ret = 0xffffffff;
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
return ret;
}
if ((arg0 == 0)) {
return ret;
}
if ((arg2 == 0)) {
return ret;
}
ret = 0xfffffffc;
if (((unsigned long)((unsigned int)(arg1)) == 0)) {
return ret;
}
var0 = (unsigned int)((unsigned char)(*(char *)(((long)arg0))));
accumulator = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var0)) & 127)));
var4 = 1;
if (((unsigned long)((unsigned char)((var0 & 128))) == 0)) {
goto L_123c;
}
if (((unsigned long)((unsigned int)(arg1)) == 1)) {
return ret;
}
var5 = (unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x1))));
accumulator = ((unsigned long)((unsigned int)(accumulator)) | ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var5)) & 127))) << 7));
var4 = 2;
if (((unsigned long)((unsigned char)((var5 & 128))) == 0)) {
goto L_123c;
}
if (((unsigned long)((unsigned int)(arg1)) == 2)) {
return ret;
}
var11 = (unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x2))));
accumulator = ((unsigned long)((unsigned int)(accumulator)) | ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var11)) & 127))) << 14));
var4 = 3;
if (((unsigned long)((unsigned char)((var11 & 128))) == 0)) {
goto L_123c;
}
if (((unsigned long)((unsigned int)(arg1)) == 3)) {
return ret;
}
var17 = (unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x3))));
accumulator = ((unsigned long)((unsigned int)(accumulator)) | ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var17)) & 127))) << 21));
var4 = 4;
if (((unsigned long)((unsigned char)((var17 & 128))) != 0)) {
goto L_1243;
}
L_123c: ;
*(int *)(((long)arg2)) = accumulator;
return (unsigned int)(var4);
L_1243: ;
if (((unsigned long)((unsigned int)(arg1)) == 4)) {
return ret;
}
var23 = (unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x4))));
if (((unsigned long)((unsigned char)((var23 & 128))) != 0)) {
var32 = ((unsigned long)((unsigned int)(arg1)) != 5);
return (unsigned int)(((unsigned long)((unsigned int)((var32 + var32))) | -4));
}
accumulator = (accumulator | ((unsigned long)((unsigned int)((var23 & 127))) << 28));
var4 = 5;
ret = 0xfffffffd;
if ((((unsigned long)(accumulator) >> 32) == 0)) {
goto L_123c;
}
return ret;
} varint_encode pass 36 lines
// glaurung: varint_encode @ 0x1120
int32_t varint_encode(uint32_t arg0, uint8_t * arg1, int32_t arg2) {
int produced;
unsigned char chunk;
long cf_12;
long ret;
long var2;
long var5;
long zf_12;
ret = 0xffffffff;
if ((arg1 == 0)) {
return ret;
}
ret = 0xffffffff;
if (((unsigned long)((unsigned long)((unsigned int)((arg2 - 17)))) < (unsigned long)(0xfffffff0))) {
return ret;
}
var2 = (unsigned long)((unsigned int)(arg2));
produced = 0;
var5 = (unsigned long)(arg0);
while (((unsigned long)((unsigned int)(arg2)) != produced)) {
ret = ((unsigned long)((unsigned int)(produced)) + 1);
*(signed char *)(((long)arg1 + produced)) = (((((unsigned long)(127) < (unsigned long)((unsigned long)((unsigned int)(var5)))) << 7) & 255) | ((unsigned long)((unsigned int)(var5)) & 127));
if (((unsigned long)(var2) <= (unsigned long)(produced))) {
return ret;
}
zf_12 = ((unsigned long)((unsigned int)(var5)) == 127);
cf_12 = ((unsigned long)((unsigned long)((unsigned int)(var5))) < (unsigned long)(127));
var5 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var5)) >> 7)));
produced = ret;
if (((cf_12 | zf_12) != 0)) {
return ret;
}
}
return 0xfffffffe;
} zigzag_decode pass 4 lines
// glaurung: zigzag_decode @ 0x1110
int32_t zigzag_decode(uint32_t arg0) {
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) >> 1))) ^ (-(unsigned long)((unsigned int)((arg0 & 1))))));
} zigzag_encode pass 4 lines
// glaurung: zigzag_encode @ 0x1100
uint32_t zigzag_encode(int32_t arg0) {
return (unsigned int)(((unsigned long)((unsigned int)((arg0 + arg0))) ^ (unsigned long)((unsigned int)(((int)(arg0) >> 31)))));
} gcc -O0
4/4varint_decode pass 47 lines
// glaurung: varint_decode @ 0x11ad
int32_t varint_decode(const uint8_t * arg0, int32_t arg1, uint32_t * arg2) {
unsigned long accumulator;
int shift;
int index;
unsigned char chunk;
accumulator = 0;
shift = 0;
if ((arg0 != 0)) {
if ((arg2 != 0)) {
if ((0 <= (long)(arg1))) {
if ((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16))) {
goto L_11f3;
}
}
}
}
// x86-64 epilogue: restore rbp
return 0xffffffff;
L_11f3: ;
index = 0;
goto L_126b;
L_11fc: ;
chunk = arg0[index];
if (((((unsigned long)((unsigned int)(shift)) == 28) | ((long)(shift) < 28)) == 0)) {
// x86-64 epilogue: restore rbp
return 0xfffffffe;
}
accumulator = (accumulator | ((unsigned long)((unsigned int)(((unsigned int)(chunk) & 127))) << ((unsigned long)((unsigned int)(shift)) & 63)));
shift = (shift + 7);
if ((0 <= (long)((signed char)((chunk & 255))))) {
if (((unsigned long)(0xffffffff) < (unsigned long)(accumulator))) {
// x86-64 epilogue: restore rbp
return 0xfffffffd;
}
*(int *)((long)arg2) = accumulator;
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(index)) + 1));
}
index = (index + 1);
L_126b: ;
if ((index < arg1)) {
goto L_11fc;
}
// x86-64 epilogue: restore rbp
return 0xfffffffc;
} varint_encode pass 32 lines
// glaurung: varint_encode @ 0x1132
int32_t varint_encode(uint32_t arg0, uint8_t * arg1, int32_t arg2) {
int produced;
unsigned char chunk;
produced = 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))) {
goto L_1165;
}
}
}
// x86-64 epilogue: restore rbp
return 0xffffffff;
L_1165: ;
chunk = (arg0 & 127);
arg0 = ((unsigned int)(arg0) >> 7);
if ((arg0 != 0)) {
chunk = (chunk | -128);
}
if ((arg2 <= produced)) {
// x86-64 epilogue: restore rbp
return 0xfffffffe;
}
arg1[produced] = chunk;
produced = (produced + 1);
if ((arg0 != 0)) {
goto L_1165;
}
// x86-64 epilogue: restore rbp
return (unsigned int)(produced);
} zigzag_decode pass 6 lines
// glaurung: zigzag_decode @ 0x1114
int32_t zigzag_decode(uint32_t arg0) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)(((-(unsigned long)((unsigned int)(((unsigned long)(arg0) & 1)))) ^ (unsigned long)((unsigned int)(((unsigned long)(arg0) >> 1)))));
} zigzag_encode pass 6 lines
// glaurung: zigzag_encode @ 0x10f9
uint32_t zigzag_encode(int32_t arg0) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(((int)(arg0) >> 31))) ^ (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) + (unsigned long)((unsigned int)(arg0)))))));
} gcc -O2
4/4varint_decode pass 54 lines
// glaurung: varint_decode @ 0x1180
int32_t varint_decode(const uint8_t * arg0, int32_t arg1, uint32_t * arg2) {
unsigned char chunk;
int shift;
unsigned long accumulator;
int index;
long var0;
long var10;
long var11;
long var13;
long var15;
long var8;
var0 = (long)arg0;
if ((arg0 == 0)) {
return 0xffffffff;
}
if ((arg2 == 0)) {
return 0xffffffff;
}
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
return 0xffffffff;
}
if (((unsigned long)((unsigned int)(arg1)) == 0)) {
return 0xfffffffc;
}
var8 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg1 * 8))) - arg1)));
var10 = 0;
var11 = 0;
chunk = (unsigned int)((unsigned char)(*(char *)(((long)arg0))));
var13 = 0;
while (1) {
var15 = (unsigned long)((unsigned int)(var10));
shift = (unsigned long)((unsigned int)((var13 + 7)));
accumulator = (var11 | ((unsigned long)((unsigned int)(((unsigned int)(chunk) & 127))) << (var13 & 63)));
if ((0 <= (long)((signed char)((chunk & 255))))) {
break;
}
if (((unsigned int)(shift) == (unsigned int)(var8))) {
return 0xfffffffc;
}
chunk = (unsigned int)((unsigned char)(*(char *)((var0 + var10 + 0x1))));
var10 = (var10 + 1);
var11 = accumulator;
var13 = (unsigned long)((unsigned int)(shift));
if (((unsigned long)((unsigned int)(shift)) == 35)) {
return 0xfffffffe;
}
}
if ((((unsigned long)(accumulator) >> 32) != 0)) {
return 0xfffffffd;
}
*(int *)(((long)arg2)) = accumulator;
return (unsigned int)((var15 + 1));
} varint_encode pass 37 lines
// glaurung: varint_encode @ 0x1120
int32_t varint_encode(uint32_t arg0, uint8_t * arg1, int32_t arg2) {
unsigned char chunk;
int produced;
long var2;
long var3;
long var5;
long var7;
int var9;
if (((unsigned long)(15) < (unsigned long)((unsigned long)((unsigned int)((arg2 - 1)))))) {
return 0xffffffff;
}
if ((arg1 == 0)) {
return 0xffffffff;
}
var2 = 0;
var3 = (unsigned long)(arg0);
while (1) {
var5 = (unsigned long)((unsigned int)(var2));
var7 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var3)) & 127)));
var9 = ((unsigned long)((unsigned int)(var3)) >> 7);
var3 = (unsigned long)((unsigned int)(var9));
if (((unsigned long)((unsigned int)(var9)) == 0)) {
break;
}
if ((((unsigned int)(arg2) == (unsigned int)(var2)) | ((long)(arg2) < (long)((int)(var2))))) {
return 0xfffffffe;
}
*(signed char *)(((long)arg1 + var2)) = (var7 | -128);
var2 = (var2 + 1);
}
if (((long)((int)(var2)) < (long)(arg2))) {
arg1[(long)((int)(var2))] = var7;
return (unsigned int)((var5 + 1));
}
return 0xfffffffe;
} zigzag_decode pass 4 lines
// glaurung: zigzag_decode @ 0x1110
int32_t zigzag_decode(uint32_t arg0) {
return (unsigned int)(((-(unsigned long)((unsigned int)(((unsigned long)(arg0) & 1)))) ^ (unsigned long)((unsigned int)(((unsigned long)(arg0) >> 1)))));
} zigzag_encode pass 4 lines
// glaurung: zigzag_encode @ 0x1100
uint32_t zigzag_encode(int32_t arg0) {
return (unsigned int)(((unsigned long)((unsigned int)((arg0 + arg0))) ^ (unsigned long)((unsigned int)(((int)(arg0) >> 31)))));
}