Fixture 44
run length
C · 2 functions · 4 lanes · 8 of 8 function-lanes behave identically
All 4 lanes recompile and return the same results as the original.
Run-length encode and decode with a bounded run counter. Encoding emits pairs, so the output index advances by two while the input index advances by a data-dependent run length.
#include <stdint.h>
/* Run-length encode and decode with a bounded run counter. Encoding emits
* pairs, so the output index advances by two while the input index advances by
* a data-dependent run length. */
#define RLE_MAX 16
__attribute__((noinline)) int32_t
rle_encode(const uint8_t *input, int32_t length, uint8_t *output,
int32_t output_capacity) {
int32_t produced = 0;
int32_t index = 0;
if (input == 0 || output == 0 || length < 0 || length > RLE_MAX ||
output_capacity < 0 || output_capacity > RLE_MAX) {
return -1;
}
while (index < length) {
uint8_t symbol = input[index];
int32_t run = 1;
while (index + run < length && input[index + run] == symbol &&
run < 255) {
run += 1;
}
if (produced + 2 > output_capacity) {
return -2;
}
output[produced] = (uint8_t)run;
output[produced + 1] = symbol;
produced += 2;
index += run;
}
return produced;
}
__attribute__((noinline)) int32_t
rle_decode(const uint8_t *input, int32_t length, uint8_t *output,
int32_t output_capacity) {
int32_t produced = 0;
int32_t index;
if (input == 0 || output == 0 || length < 0 || length > RLE_MAX ||
output_capacity < 0 || output_capacity > RLE_MAX || (length % 2) != 0) {
return -1;
}
for (index = 0; index < length; index += 2) {
int32_t run = (int32_t)input[index];
uint8_t symbol = input[index + 1];
int32_t step;
if (produced + run > output_capacity) {
return -2;
}
for (step = 0; step < run; ++step) {
output[produced] = symbol;
produced += 1;
}
}
return produced;
} 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/2rle_decode pass 59 lines
// glaurung: rle_decode @ 0x1260
int32_t rle_decode(const uint8_t * arg0, int32_t arg1, uint8_t * arg2, int32_t arg3) {
int produced;
int index;
int run;
unsigned char symbol;
int step;
int local_4;
int var17;
produced = 0;
if ((arg0 != 0)) {
if ((arg2 != 0)) {
if ((0 <= (long)(arg1))) {
if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) != 0)) {
if ((0 <= (long)(arg3))) {
if (((((unsigned long)((unsigned int)(arg3)) == 16) | ((long)(arg3) < 16)) != 0)) {
if (((unsigned long)((unsigned int)(((int)((((long long)(int)((((unsigned long)((long)((int)((unsigned long)((unsigned int)(arg1))))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg1)))) % (int)(2))))) == 0)) {
goto L_12d7;
}
}
}
}
}
}
}
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
L_12d7: ;
index = 0;
L_12de: ;
if ((arg1 <= index)) {
goto L_1372;
}
run = (unsigned char)(arg0[index]);
symbol = arg0[(long)((int)(((unsigned long)((unsigned int)(index)) + 1)))];
var17 = ((unsigned int)(produced) + run);
if (((((unsigned int)(var17) == (unsigned int)(arg3)) | (var17 < arg3)) == 0)) {
local_4 = -2;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
step = 0;
L_132e: ;
if ((step < run)) {
arg2[produced] = symbol;
produced = ((unsigned int)(produced) + 1);
step = ((unsigned int)(step) + 1);
goto L_132e;
}
goto L_1364;
L_1364: ;
index = ((unsigned int)(index) + 2);
goto L_12de;
L_1372: ;
local_4 = produced;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} rle_encode pass 65 lines
// glaurung: rle_encode @ 0x1100
int32_t rle_encode(const uint8_t * arg0, int32_t arg1, uint8_t * arg2, int32_t arg3) {
int produced;
int index;
unsigned char symbol;
int run;
signed char local_35;
int local_4;
int var15;
int var26;
produced = 0;
index = 0;
if ((arg0 != 0)) {
if ((arg2 != 0)) {
if ((0 <= (long)(arg1))) {
if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) != 0)) {
if ((0 <= (long)(arg3))) {
if ((((unsigned long)((unsigned int)(arg3)) == 16) | ((long)(arg3) < 16))) {
goto L_116a;
}
}
}
}
}
}
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
L_116a: ;
goto L_116f;
L_116f: ;
if ((arg1 <= index)) {
goto L_1246;
}
symbol = arg0[index];
run = 1;
L_1190: ;
local_35 = 0;
if (((long)((int)(((unsigned long)((unsigned int)(index)) + run))) < (long)(arg1))) {
var15 = (unsigned int)((unsigned char)(arg0[(long)((int)(((unsigned long)((unsigned int)(index)) + run)))]));
local_35 = 0;
if (((unsigned long)((unsigned int)(var15)) == (unsigned long)((unsigned long)(symbol)))) {
local_35 = ((long)(run) < 255);
}
}
if (((unsigned long)((unsigned char)((local_35 & 1))) != 0)) {
run = ((unsigned int)(run) + 1);
goto L_1190;
}
var26 = ((unsigned int)(produced) + 2);
if (((((unsigned int)(var26) == (unsigned int)(arg3)) | (var26 < arg3)) == 0)) {
local_4 = -2;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
arg2[produced] = run;
arg2[(long)((int)(((unsigned long)((unsigned int)(produced)) + 1)))] = symbol;
produced = ((unsigned int)(produced) + 2);
index = ((unsigned int)(run) + index);
goto L_116f;
L_1246: ;
local_4 = produced;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} clang -O2
2/2rle_decode pass 80 lines
// glaurung: rle_decode @ 0x11e0
int32_t rle_decode(const uint8_t * arg0, int32_t arg1, uint8_t * arg2, int32_t arg3) {
extern void * memset(void *, int, __SIZE_TYPE__);
int produced;
int run;
int index;
int step;
long var0;
long var1;
long var11;
void * var14;
long var17;
long var2;
long var3;
long var4;
long var5;
// x86-64 prologue: save callee registers, frame 56 bytes
var0 = (unsigned long)((unsigned int)(arg1));
var1 = 0xffffffff;
var2 = 0xffffffff;
if (((unsigned long)((unsigned char)(((unsigned long)((unsigned int)(arg1)) & 1))) != 0)) {
// x86-64 epilogue: restore callee registers
return (unsigned int)(var2);
}
var3 = (unsigned long)((unsigned int)(arg3));
var2 = var1;
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg3))))) {
// x86-64 epilogue: restore callee registers
return (unsigned int)(var2);
}
var2 = var1;
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(var0))))) {
// x86-64 epilogue: restore callee registers
return (unsigned int)(var2);
}
var4 = (long)arg0;
var2 = var1;
if ((arg0 == 0)) {
// x86-64 epilogue: restore callee registers
return (unsigned int)(var2);
}
var5 = (long)arg2;
var2 = var1;
if ((arg2 == 0)) {
// x86-64 epilogue: restore callee registers
return (unsigned int)(var2);
}
if (((unsigned long)((unsigned int)(var0)) == 0)) {
var2 = 0;
// x86-64 epilogue: restore callee registers
return 0;
}
produced = 0;
var11 = 0;
goto L_124e;
L_1230: ;
var14 = memset((void *)(((long)(produced) + var5)), (int)((unsigned int)((unsigned char)(*(char *)((var4 + var11 + 0x1))))), (__SIZE_TYPE__)((unsigned long)((unsigned int)(run))));
produced = (unsigned long)((unsigned int)(var17));
var2 = var17;
L_1245: ;
index = (var11 + 2);
var11 = (unsigned long)((unsigned int)(index));
if (((long)((int)(var0)) <= (long)(index))) {
// x86-64 epilogue: restore callee registers
return (unsigned int)(var2);
}
L_124e: ;
run = (unsigned int)((unsigned char)(*(char *)((var4 + var11))));
var17 = (unsigned long)((unsigned int)((produced + run)));
if (((((unsigned int)(var17) == (unsigned int)(var3)) | ((long)((int)(var17)) < (long)((int)(var3)))) == 0)) {
var2 = 0xfffffffe;
// x86-64 epilogue: restore callee registers
return 0xfffffffe;
}
if (((unsigned long)((unsigned int)(run)) != 0)) {
goto L_1230;
}
var2 = (unsigned long)((unsigned int)(produced));
goto L_1245;
} rle_encode pass 79 lines
// glaurung: rle_encode @ 0x1110
int32_t rle_encode(const uint8_t * arg0, int32_t arg1, uint8_t * arg2, int32_t arg3) {
int produced;
int index;
unsigned char symbol;
int run;
long ret;
long var0;
long var10;
long var11;
long var5;
int var9;
var0 = 0xffffffff;
ret = 0xffffffff;
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg3))))) {
// x86-64 epilogue: tear down frame
return ret;
}
ret = var0;
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
// x86-64 epilogue: tear down frame
return ret;
}
ret = var0;
if ((arg0 == 0)) {
// x86-64 epilogue: tear down frame
return ret;
}
ret = var0;
if ((arg2 == 0)) {
// x86-64 epilogue: tear down frame
return ret;
}
if (((unsigned long)((unsigned int)(arg1)) == 0)) {
// x86-64 epilogue: tear down frame
return 0;
}
produced = 0;
var5 = 0;
L_1150: ;
index = (unsigned long)((unsigned int)(var5));
symbol = (arg0[(unsigned long)((unsigned int)(var5))] & 255);
var9 = (var5 + 1);
var10 = (unsigned long)((unsigned int)(var9));
var11 = 1;
if ((arg1 <= var9)) {
goto L_11a9;
}
var11 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) - index)));
run = 1;
L_1180: ;
if (((unsigned char)(arg0[(unsigned long)((unsigned int)((index + run)))]) == (unsigned char)((symbol & 255)))) {
if (((unsigned long)(run) <= (unsigned long)(254))) {
run = (run + 1);
if ((var11 != run)) {
goto L_1180;
}
var10 = (unsigned long)((unsigned int)(arg1));
goto L_11a9;
}
}
var11 = (unsigned long)((unsigned int)(run));
var10 = (unsigned long)((unsigned int)((index + run)));
L_11a9: ;
ret = ((unsigned long)((unsigned int)(produced)) + 2);
if (((((unsigned int)(ret) == (unsigned int)(arg3)) | ((long)((int)(ret)) < (long)(arg3))) == 0)) {
// x86-64 epilogue: tear down frame
return 0xfffffffe;
}
*(signed char *)(((long)arg2 + produced)) = var11;
arg2[(produced | 1)] = symbol;
var5 = var10;
produced = ret;
if (((long)((int)(var10)) < (long)(arg1))) {
goto L_1150;
}
// x86-64 epilogue: tear down frame
return ret;
} gcc -O0
2/2rle_decode pass 53 lines
// glaurung: rle_decode @ 0x11f6
int32_t rle_decode(const uint8_t * arg0, int32_t arg1, uint8_t * arg2, int32_t arg3) {
int produced;
int index;
int run;
unsigned char symbol;
int step;
produced = 0;
if ((arg0 != 0)) {
if ((arg2 != 0)) {
if ((0 <= (long)(arg1))) {
if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) != 0)) {
if ((0 <= (long)(arg3))) {
if (((((unsigned long)((unsigned int)(arg3)) == 16) | ((long)(arg3) < 16)) != 0)) {
if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) & 1))) == 0)) {
goto L_124d;
}
}
}
}
}
}
}
// x86-64 epilogue: restore rbp
return 0xffffffff;
L_124d: ;
index = 0;
goto L_12c6;
L_1256: ;
run = (unsigned char)(((unsigned int)((unsigned char)(arg0[index])) & 255));
symbol = arg0[((long)(index) + 1)];
if (((long)(arg3) < (long)((int)(((unsigned long)((unsigned int)(run)) + (unsigned long)((unsigned int)(produced))))))) {
// x86-64 epilogue: restore rbp
return 0xfffffffe;
}
step = 0;
goto L_12ba;
L_129f: ;
arg2[produced] = symbol;
produced = (produced + 1);
step = (step + 1);
L_12ba: ;
if ((step < run)) {
goto L_129f;
}
index = (index + 2);
L_12c6: ;
if ((index < arg1)) {
goto L_1256;
}
// x86-64 epilogue: restore rbp
return (unsigned int)(produced);
} rle_encode pass 56 lines
// glaurung: rle_encode @ 0x10f9
int32_t rle_encode(const uint8_t * arg0, int32_t arg1, uint8_t * arg2, int32_t arg3) {
int produced;
int index;
unsigned char symbol;
int run;
int var18;
int var7;
produced = 0;
index = 0;
if ((arg0 != 0)) {
if ((arg2 != 0)) {
if ((0 <= (long)(arg1))) {
if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) != 0)) {
if ((0 <= (long)(arg3))) {
if ((((unsigned long)((unsigned int)(arg3)) == 16) | ((long)(arg3) < 16))) {
goto L_11e5;
}
}
}
}
}
}
// x86-64 epilogue: restore rbp
return 0xffffffff;
L_1151: ;
symbol = arg0[index];
run = 1;
goto L_1171;
L_116d: ;
run = (run + 1);
L_1171: ;
var7 = ((unsigned int)(run) + (unsigned int)(index));
if (((((unsigned int)(arg1) == (unsigned int)(var7)) | (arg1 < var7)) == 0)) {
if ((symbol == (unsigned long)((unsigned char)(((unsigned int)((unsigned char)(arg0[(long)((int)(((unsigned long)((unsigned int)(run)) + (unsigned long)((unsigned int)(index)))))])) & 255))))) {
if ((((unsigned long)((unsigned int)(run)) == 254) | ((long)(run) < 254))) {
goto L_116d;
}
}
}
var18 = ((unsigned int)(produced) + 1);
if (((((unsigned int)(arg3) == (unsigned int)(var18)) | (arg3 < var18)) != 0)) {
// x86-64 epilogue: restore rbp
return 0xfffffffe;
}
arg2[produced] = run;
arg2[((long)(produced) + 1)] = symbol;
produced = (produced + 2);
index = (index + (unsigned int)(run));
L_11e5: ;
if ((index < arg1)) {
goto L_1151;
}
// x86-64 epilogue: restore rbp
return (unsigned int)(produced);
} gcc -O2
2/2rle_decode pass 127 lines
// glaurung: rle_decode @ 0x11d0
int32_t rle_decode(const uint8_t * arg0, int32_t arg1, uint8_t * arg2, int32_t arg3) {
int produced;
int run;
int index;
int step;
unsigned char symbol;
long df_1;
long t157;
long t164;
long var0;
long var1;
long var15;
long var18;
long var19;
long var2;
long var20;
int var23;
long var24;
long var28;
int var3;
int var4;
long var40;
long var5;
long var8;
df_1 = 0;
if ((arg0 == 0)) {
goto L_12e1;
}
var0 = (unsigned long)((unsigned int)(arg1));
var1 = (long)arg2;
if ((arg2 == 0)) {
goto L_12e1;
}
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(var0))))) {
goto L_12e1;
}
var2 = (unsigned long)((unsigned int)(arg3));
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg3))))) {
goto L_12e1;
}
if (((unsigned long)((unsigned char)((var0 & 1))) != 0)) {
goto L_12e1;
}
if (((unsigned long)((unsigned int)(var0)) == 0)) {
goto L_12da;
}
var3 = (unsigned int)((unsigned char)(*(char *)(((long)arg0))));
var4 = (unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x1))));
var5 = (long)arg0;
if ((arg3 < var3)) {
goto L_12e9;
}
var8 = 0x101010101010101;
var15 = (long)(((long)arg0 + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var0 - 1))) >> 1))) * 2)));
produced = 0;
run = var3;
var18 = (unsigned long)((unsigned int)(var4));
goto L_1282;
L_1250: ;
if (((unsigned long)((unsigned char)((run & 4))) != 0)) {
goto L_12c5;
}
if (((unsigned long)((unsigned int)(run)) == 0)) {
goto L_1263;
}
*(signed char *)((var19)) = var20;
if (((unsigned long)((unsigned char)((run & 2))) != 0)) {
goto L_12d0;
}
L_1263: ;
produced = (unsigned long)((unsigned int)((produced + run)));
L_1266: ;
if ((var15 == var5)) {
goto L_12bf;
}
run = (unsigned int)((unsigned char)(*(char *)((var5 + 0x2))));
var23 = (unsigned int)((unsigned char)(*(char *)((var5 + 0x3))));
var5 = (var5 + 2);
var24 = (unsigned long)((unsigned int)((run + produced)));
var18 = (unsigned long)((unsigned int)(var23));
if (((((unsigned int)(var24) == (unsigned int)(var2)) | ((long)((int)(var24)) < (long)((int)(var2)))) == 0)) {
goto L_12b9;
}
L_1282: ;
if (((unsigned long)((unsigned int)(run)) == 0)) {
goto L_1266;
}
var20 = (var18 * var8);
var19 = ((long)(produced) + var1);
if (((unsigned long)((unsigned long)((unsigned int)(run))) < (unsigned long)(8))) {
goto L_1250;
}
*(long *)((var19)) = var20;
var28 = ((var19 + 8) & -8);
*(long *)(((var19 + (unsigned long)((unsigned int)(run))) - 8)) = var20;
t157 = var28;
t164 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((run + (var19 - var28)))) >> 3)));
while ((t164 != 0)) {
*(long *)(t157) = var20;
t157 = (t157 + ((df_1 != 0) ? -8 : 8));
t164 = (t164 - 1);
}
goto L_1263;
L_12b9: ;
produced = 0xfffffffe;
L_12bf: ;
// x86-64 epilogue: tear down frame
return (unsigned int)(produced);
L_12c5: ;
*(int *)((var19)) = var20;
*(int *)(((var19 + (unsigned long)((unsigned int)(run))) - 4)) = var20;
goto L_1263;
L_12d0: ;
*(short *)(((var19 + (unsigned long)((unsigned int)(run))) - 2)) = var20;
goto L_1263;
L_12da: ;
var40 = 0;
L_12dd: ;
return (unsigned int)(var40);
L_12e1: ;
var40 = 0xffffffff;
goto L_12dd;
L_12e9: ;
var40 = 0xfffffffe;
goto L_12dd;
} rle_encode pass 106 lines
// glaurung: rle_encode @ 0x1100
int32_t rle_encode(const uint8_t * arg0, int32_t arg1, uint8_t * arg2, int32_t arg3) {
int index;
unsigned char symbol;
int run;
int produced;
long local_8;
long var0;
long var1;
long var12;
long var14;
long var17;
long var19;
long var2;
long var20;
long var21;
int var22;
long var26;
int var27;
long var28;
long var7;
long var9;
local_8 = var0;
if ((arg0 == 0)) {
goto L_11bc;
}
if ((arg2 == 0)) {
goto L_11bc;
}
var1 = (unsigned long)((unsigned int)(arg1));
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
goto L_11bc;
}
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg3))))) {
goto L_11bc;
}
if (((unsigned long)((unsigned int)(arg1)) == 0)) {
goto L_11b7;
}
var2 = (long)arg0;
var7 = 0;
index = 0;
var9 = (long)arg2;
L_1140: ;
symbol = (unsigned int)((unsigned char)(*(char *)((var2 + (long)(index)))));
var12 = (unsigned long)((unsigned int)((index + 1)));
if ((((unsigned int)(var1) == (unsigned int)(var12)) | ((long)((int)(var1)) < (long)((int)(var12))))) {
goto L_11ae;
}
var14 = (long)((int)(var12));
var17 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var1)) - index)));
run = 1;
goto L_1177;
L_1160: ;
var19 = var20;
var21 = (unsigned long)((unsigned int)(run));
if (((unsigned long)((unsigned int)(run)) == 255)) {
goto L_117f;
}
var22 = (run + 1);
var14 = (var14 + 1);
run = (unsigned long)((unsigned int)(var22));
var19 = (unsigned long)((unsigned int)((var20 + 1)));
var21 = (unsigned long)((unsigned int)(var22));
if (((unsigned int)(var22) == (unsigned int)(var17))) {
goto L_117f;
}
L_1177: ;
var20 = (unsigned long)((unsigned int)(var14));
var19 = (unsigned long)((unsigned int)(var14));
var21 = (unsigned long)((unsigned int)(run));
if (((unsigned char)(*(char *)((var2 + var14))) == (unsigned char)((symbol & 255)))) {
goto L_1160;
}
L_117f: ;
var26 = (unsigned long)((unsigned int)((var7 + 1)));
if ((((unsigned int)(arg3) == (unsigned int)(var26)) | ((long)(arg3) < (long)((int)(var26))))) {
goto L_11a2;
}
*(signed char *)((var9)) = var21;
var27 = (var7 + 2);
var7 = (unsigned long)((unsigned int)(var27));
var9 = (var9 + 2);
*(signed char *)((var9 - 0x1)) = symbol;
index = var19;
var28 = (unsigned long)((unsigned int)(var27));
if (((((unsigned int)(var1) == (unsigned int)(var19)) | ((long)((int)(var1)) < (long)((int)(var19)))) == 0)) {
goto L_1140;
}
L_119c: ;
// x86-64 epilogue: tear down frame
return (unsigned int)(var28);
L_11a2: ;
// x86-64 epilogue: tear down frame
return 0xfffffffe;
L_11ae: ;
var19 = (unsigned long)((unsigned int)(var12));
var21 = 1;
goto L_117f;
L_11b7: ;
var28 = 0;
goto L_119c;
L_11bc: ;
var28 = 0xffffffff;
goto L_119c;
}