Fixture 23
topological sort
C · 1 functions · 4 lanes · 4 of 4 function-lanes behave identically
All 4 lanes recompile and return the same results as the original.
#include <stdint.h>
__attribute__((noinline)) int32_t topological_sort(const int32_t *adjacency,
int32_t n,
int32_t *order) {
int32_t indegree[16] = {0};
int32_t queue[16];
int32_t head = 0;
int32_t tail = 0;
int32_t count = 0;
int32_t from;
int32_t to;
if (adjacency == 0 || order == 0 || n < 0 || n > 4) {
return -1;
}
for (from = 0; from < n; ++from) {
for (to = 0; to < n; ++to) {
if (adjacency[from * n + to] != 0) {
++indegree[to];
}
}
}
for (to = 0; to < n; ++to) {
if (indegree[to] == 0) {
queue[tail++] = to;
}
}
while (head < tail) {
from = queue[head++];
order[count++] = from;
for (to = 0; to < n; ++to) {
if (adjacency[from * n + to] != 0 && --indegree[to] == 0) {
queue[tail++] = to;
}
}
}
return count == n ? count : -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
1/1topological_sort pass 83 lines
// glaurung: topological_sort @ 0x1110
__attribute__((no_stack_protector)) int32_t topological_sort(const int32_t * arg0, int32_t arg1, int32_t * arg2) {
extern void * memset(void *, int, __SIZE_TYPE__);
int head;
int tail;
int count;
int from;
int to;
int local_4;
unsigned char local_60[64];
unsigned char local_a0[64];
int local_b8;
void * var1;
long var25;
long var34;
long var42;
int var57;
long var60;
// x86-64 prologue: save rbp, frame 192 bytes
var1 = memset((void *)(&local_60[0]), 0, (__SIZE_TYPE__)(64));
head = 0;
tail = 0;
count = 0;
if ((arg0 == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if ((arg2 == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((long)(arg1) < 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((((unsigned long)((unsigned int)(arg1)) == 4) | ((long)(arg1) < 4)) == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
from = 0;
while ((from < arg1)) {
for (to = 0; (to < arg1); to++) {
if (((unsigned long)((unsigned int)(arg0[(long)((int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(from)) * arg1))) + to)))])) != 0)) {
*(int *)((&local_60[0] + ((long)(to) * 4))) = ((unsigned long)((unsigned int)(*(int *)((&local_60[0] + ((long)(to) * 4))))) + 1);
}
}
from = ((unsigned int)(from) + 1);
}
for (to = 0; (to < arg1); to++) {
if (((unsigned long)((unsigned int)(*(int *)((&local_60[0] + ((long)(to) * 4))))) == 0)) {
var25 = (unsigned long)((unsigned int)(tail));
tail = ((unsigned int)(tail) + 1);
*(int *)((&local_a0[0] + ((long)((int)(var25)) * 4))) = to;
}
}
while ((head < tail)) {
var34 = (unsigned long)((unsigned int)(head));
head = ((unsigned int)(head) + 1);
from = *(int *)((&local_a0[0] + ((long)((int)(var34)) * 4)));
var42 = (unsigned long)((unsigned int)(count));
count = ((unsigned int)(count) + 1);
arg2[(long)((int)(var42))] = from;
for (to = 0; (to < arg1); to++) {
if (((unsigned long)((unsigned int)(arg0[(long)((int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(from)) * arg1))) + to)))])) != 0)) {
var57 = ((unsigned int)(*(int *)((&local_60[0] + ((long)(to) * 4)))) - 1);
*(int *)((&local_60[0] + ((long)(to) * 4))) = var57;
if (((unsigned long)((unsigned int)(var57)) == 0)) {
var60 = (unsigned long)((unsigned int)(tail));
tail = ((unsigned int)(tail) + 1);
*(int *)((&local_a0[0] + ((long)((int)(var60)) * 4))) = to;
}
}
}
}
local_b8 = (((unsigned int)(count) != (unsigned int)(arg1)) ? 0xffffffff : (unsigned long)((unsigned int)(count)));
local_4 = local_b8;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} clang -O2
1/1topological_sort pass 167 lines
// glaurung: topological_sort @ 0x1100
__attribute__((no_stack_protector)) int32_t topological_sort(const int32_t * arg0, int32_t arg1, int32_t * arg2) {
int count;
int tail;
int from;
int to;
unsigned char local_68[104];
unsigned char local_a8[64];
long ret;
long t155;
long var12;
long var13;
long var14;
long var15;
long var16;
long var17;
long var18;
long var21;
long var22;
long var23;
int var25;
int var27;
long var32;
long var37;
long var39;
long var43;
long var51;
long var54;
long var55;
long var6;
long var8;
// x86-64 prologue: save callee registers, frame 40 bytes
*(int *)((&local_a8[0] + 48)) = 0;
*(int *)((&local_a8[0] + 52)) = 0;
*(int *)((&local_a8[0] + 56)) = 0;
*(int *)((&local_a8[0] + 60)) = 0;
*(int *)((&local_a8[0] + 32)) = 0;
*(int *)((&local_a8[0] + 36)) = 0;
*(int *)((&local_a8[0] + 40)) = 0;
*(int *)((&local_a8[0] + 44)) = 0;
*(int *)((&local_a8[0] + 16)) = 0;
*(int *)((&local_a8[0] + 20)) = 0;
*(int *)((&local_a8[0] + 24)) = 0;
*(int *)((&local_a8[0] + 28)) = 0;
*(int *)(&local_a8[0]) = 0;
*(int *)((&local_a8[0] + 4)) = 0;
*(int *)((&local_a8[0] + 8)) = 0;
*(int *)((&local_a8[0] + 12)) = 0;
ret = 0xffffffff;
if (((unsigned long)(4) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
// x86-64 epilogue: restore callee registers
return ret;
}
if ((arg0 == 0)) {
// x86-64 epilogue: restore callee registers
return ret;
}
if ((arg2 == 0)) {
// x86-64 epilogue: restore callee registers
return ret;
}
var6 = 0;
count = 0;
if (((unsigned long)((unsigned int)(arg1)) != 0)) {
var8 = (unsigned long)((unsigned int)(arg1));
var12 = (unsigned long)((unsigned int)(*(int *)((&local_a8[0] + 12))));
var13 = (long)((arg0 + 3));
var14 = ((unsigned long)((unsigned int)(arg1)) * 4);
var15 = (unsigned long)((unsigned int)(arg1));
var16 = (unsigned long)((unsigned int)(*(int *)((&local_a8[0] + 4))));
var17 = (unsigned long)((unsigned int)(*(int *)((&local_a8[0] + 8))));
var18 = (unsigned long)((unsigned int)(*(int *)(&local_a8[0])));
do {
var21 = (((unsigned long)((unsigned int)(*(int *)((var13 - 0xc)))) == 0) ? (unsigned long)((unsigned int)(var18)) : (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var18)) + 1))));
var22 = var16;
var23 = var17;
if (((unsigned long)((unsigned int)(arg1)) != 1)) {
var25 = (((unsigned long)((unsigned int)(*(int *)((var13 - 0x8)))) != 0) ? (unsigned long)((unsigned int)((var16 + 1))) : var16);
var22 = (unsigned long)((unsigned int)(var25));
var23 = var17;
if (((unsigned long)((unsigned int)(arg1)) != 2)) {
var27 = (((unsigned long)((unsigned int)(*(int *)((var13 - 0x4)))) != 0) ? (unsigned long)((unsigned int)((var17 + 1))) : var17);
var22 = (unsigned long)((unsigned int)(var25));
var23 = (unsigned long)((unsigned int)(var27));
if (((unsigned long)((unsigned int)(arg1)) != 3)) {
var12 = (unsigned long)((unsigned int)((((unsigned long)((unsigned int)(*(int *)((var13)))) == 0) ? var12 : (unsigned long)((unsigned int)((var12 + 1))))));
var22 = (unsigned long)((unsigned int)(var25));
var23 = (unsigned long)((unsigned int)(var27));
}
}
}
var13 = (var13 + var14);
var15 = (var15 - 1);
var16 = var22;
var17 = var23;
var18 = var21;
} while ((var15 != 0));
*(int *)(&local_a8[0]) = var21;
*(int *)((&local_a8[0] + 4)) = var22;
*(int *)((&local_a8[0] + 8)) = var23;
*(int *)((&local_a8[0] + 12)) = var12;
count = var6;
if (((unsigned long)((unsigned int)(arg1)) != 0)) {
var32 = 0;
if (((unsigned long)((unsigned int)(*(int *)(&local_a8[0]))) == 0)) {
*(int *)(&local_68[0]) = 0;
var32 = 1;
}
tail = var32;
if (((unsigned long)((unsigned int)(arg1)) != 1)) {
tail = var32;
if (((unsigned long)((unsigned int)(*(int *)((&local_a8[0] + 4)))) == 0)) {
tail = (unsigned long)((unsigned int)((var32 + 1)));
*(int *)((&local_68[0] + ((unsigned long)((unsigned int)(var32)) * 4))) = 1;
}
if (((unsigned long)((unsigned int)(arg1)) != 2)) {
if (((unsigned long)((unsigned int)(*(int *)((&local_a8[0] + 8)))) == 0)) {
var37 = (unsigned long)((unsigned int)(tail));
tail = (unsigned long)((unsigned int)((tail + 1)));
*(int *)((&local_68[0] + (var37 * 4))) = 2;
}
if (((unsigned long)((unsigned int)(arg1)) != 3)) {
if (((unsigned long)((unsigned int)(*(int *)((&local_a8[0] + 12)))) == 0)) {
var39 = (unsigned long)((unsigned int)(tail));
tail = (unsigned long)((unsigned int)((tail + 1)));
*(int *)((&local_68[0] + (var39 * 4))) = 3;
}
}
}
}
count = 0;
var43 = 0;
if (((((unsigned long)((unsigned int)(tail)) == 0) | ((long)(tail) < 0)) != 0)) {
// x86-64 epilogue: restore callee registers
return (((unsigned int)(count) == (unsigned int)(arg1)) ? count : 0xffffffff);
}
do {
from = (unsigned long)((unsigned int)(*(int *)((&local_68[0] + (var43 * 4)))));
*(int *)(((long)arg2 + var43 * 4)) = from;
count = (var43 + 1);
if (((unsigned long)((unsigned int)(arg1)) != 0)) {
var51 = (long)(((long)arg0 + ((long)((int)((from * arg1))) * 4)));
var54 = 0;
var55 = (unsigned long)((unsigned int)(tail));
do {
tail = var55;
if (((unsigned long)((unsigned int)(*(int *)((var51 + var54 * 4)))) != 0)) {
t155 = (*(int *)((&local_a8[0] + (var54 * 4))) - 1);
*(int *)((&local_a8[0] + (var54 * 4))) = t155;
tail = var55;
if (((unsigned long)((unsigned int)(t155)) == 0)) {
tail = (unsigned long)((unsigned int)((var55 + 1)));
*(int *)((&local_68[0] + ((long)((int)(var55)) * 4))) = var54;
}
}
to = (var54 + 1);
var54 = (unsigned long)((unsigned int)(to));
var55 = (unsigned long)((unsigned int)(tail));
} while ((var8 != to));
}
var43 = (unsigned long)((unsigned int)(count));
} while ((count < (long)(tail)));
}
}
// x86-64 epilogue: restore callee registers
return (((unsigned int)(count) == (unsigned int)(arg1)) ? count : 0xffffffff);
} gcc -O0
1/1topological_sort pass 74 lines
// glaurung: topological_sort @ 0x1119
int32_t topological_sort(const int32_t * arg0, int32_t arg1, int32_t * arg2) {
extern __attribute__((noreturn)) void __stack_chk_fail(void);
int head;
int tail;
int count;
int from;
int to;
unsigned char local_50[64];
long local_8;
unsigned char local_90[64];
long ret;
long var27;
long var32;
long var36;
long var65;
// x86-64 prologue: save rbp, frame 208 bytes
local_8 = (long)(0x28);
*(long *)(&local_90[0]) = 0;
*(long *)((&local_90[0] + 8)) = 0;
*(long *)((&local_90[0] + 16)) = 0;
*(long *)((&local_90[0] + 24)) = 0;
*(long *)((&local_90[0] + 32)) = 0;
*(long *)((&local_90[0] + 40)) = 0;
*(long *)((&local_90[0] + 48)) = 0;
*(long *)((&local_90[0] + 56)) = 0;
head = 0;
tail = 0;
count = 0;
if (((((arg0 == 0) || (arg2 == 0)) || ((long)(arg1) < 0)) || (((unsigned long)((unsigned int)(arg1)) != 4) && (4 <= (long)(arg1))))) {
ret = 0xffffffff;
} else {
from = 0;
while ((from < arg1)) {
for (to = 0; (to < arg1); to++) {
if (((unsigned long)((unsigned int)(arg0[(long)((int)(((unsigned long)((unsigned int)(to)) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(from)) * arg1))))))])) != 0)) {
*(int *)((&local_90[0] + ((long)(to) * 4))) = ((unsigned long)((unsigned int)(*(int *)((&local_90[0] + ((long)(to) * 4))))) + 1);
}
}
from = (from + 1);
}
for (to = 0; (to < arg1); to++) {
if (((unsigned long)((unsigned int)(*(int *)((&local_90[0] + ((long)(to) * 4))))) == 0)) {
var27 = (unsigned long)((unsigned int)(tail));
tail = ((unsigned int)(tail) + 1);
*(int *)((&local_50[0] + ((long)((int)(var27)) * 4))) = to;
}
}
while ((head < tail)) {
var32 = (unsigned long)((unsigned int)(head));
head = ((unsigned int)(head) + 1);
from = *(int *)((&local_50[0] + ((long)((int)(var32)) * 4)));
var36 = (unsigned long)((unsigned int)(count));
count = ((unsigned int)(count) + 1);
arg2[(long)((int)(var36))] = from;
for (to = 0; (to < arg1); to++) {
if (((unsigned long)((unsigned int)(arg0[(long)((int)(((unsigned long)((unsigned int)(to)) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(from)) * arg1))))))])) != 0)) {
*(int *)((&local_90[0] + ((long)(to) * 4))) = ((unsigned long)((unsigned int)(*(int *)((&local_90[0] + ((long)(to) * 4))))) - 1);
if (((unsigned long)((unsigned int)(*(int *)((&local_90[0] + ((long)(to) * 4))))) == 0)) {
var65 = (unsigned long)((unsigned int)(tail));
tail = ((unsigned int)(tail) + 1);
*(int *)((&local_50[0] + ((long)((int)(var65)) * 4))) = to;
}
}
}
}
ret = (((unsigned int)(count) != (unsigned int)(arg1)) ? 0xffffffff : (unsigned long)((unsigned int)(count)));
}
if ((local_8 != 0x28)) {
__stack_chk_fail();
}
// x86-64 epilogue: restore rbp
return ret;
} gcc -O2
1/1topological_sort pass 133 lines
// glaurung: topological_sort @ 0x1120
int32_t topological_sort(const int32_t * arg0, int32_t arg1, int32_t * arg2) {
extern __attribute__((noreturn)) void __stack_chk_fail(void);
int from;
int tail;
int count;
int to;
long local_20;
unsigned char local_68[64];
unsigned char local_a8[64];
long ret;
long t155;
long var10;
long var11;
long var14;
long var19;
int var21;
long var26;
long var27;
long var33;
long var35;
long var37;
long var42;
long var45;
long var5;
long var51;
long var52;
long var8;
var5 = (long)arg2;
local_20 = (long)(0x28);
var8 = 0;
*(int *)(&local_a8[0]) = 0;
*(int *)((&local_a8[0] + 4)) = 0;
*(int *)((&local_a8[0] + 8)) = 0;
*(int *)((&local_a8[0] + 12)) = 0;
*(int *)((&local_a8[0] + 16)) = 0;
*(int *)((&local_a8[0] + 20)) = 0;
*(int *)((&local_a8[0] + 24)) = 0;
*(int *)((&local_a8[0] + 28)) = 0;
*(int *)((&local_a8[0] + 32)) = 0;
*(int *)((&local_a8[0] + 36)) = 0;
*(int *)((&local_a8[0] + 40)) = 0;
*(int *)((&local_a8[0] + 44)) = 0;
*(int *)((&local_a8[0] + 48)) = 0;
*(int *)((&local_a8[0] + 52)) = 0;
*(int *)((&local_a8[0] + 56)) = 0;
*(int *)((&local_a8[0] + 60)) = 0;
if ((arg0 == 0)) {
goto L_124d;
}
if ((var5 == 0)) {
goto L_124d;
}
ret = (unsigned long)((unsigned int)(arg1));
if (((unsigned long)(4) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
goto L_124d;
}
if (((unsigned long)((unsigned int)(arg1)) == 0)) {
goto L_122e;
}
var10 = (long)arg0;
var11 = (long)arg0;
var14 = ((long)(arg1) << 2);
from = 0;
do {
var19 = 0;
do {
if (((unsigned long)((unsigned int)(*(int *)((var11 + var19 * 4)))) != 0)) {
*(int *)((&local_a8[0] + (var19 * 4))) = (*(int *)((&local_a8[0] + (var19 * 4))) + 1);
}
var8 = (var19 + 1);
var19 = var8;
} while (((((unsigned int)(ret) == (unsigned int)(var8)) | ((long)((int)(ret)) < (long)((int)(var8)))) == 0));
var21 = (from + 1);
from = (unsigned long)((unsigned int)(var21));
var11 = (var11 + var14);
} while (((unsigned int)(ret) != (unsigned int)(var21)));
var26 = 0;
var27 = 0;
do {
tail = var26;
if (((unsigned long)((unsigned int)(*(int *)((&local_a8[0] + (var27 * 4))))) == 0)) {
*(int *)((&local_68[0] + ((long)((int)(var26)) * 4))) = var27;
tail = (unsigned long)((unsigned int)((var26 + 1)));
}
var33 = (var27 + 1);
var26 = (unsigned long)((unsigned int)(tail));
var27 = var33;
} while (((((unsigned int)(from) == (unsigned int)(var33)) | ((long)(from) < (long)((int)(var33)))) == 0));
if (((unsigned long)((unsigned int)(tail)) == 0)) {
goto L_124d;
}
var35 = 0;
do {
var37 = (unsigned long)((unsigned int)(*(int *)((&local_68[0] + (var35 * 4)))));
count = (unsigned long)((unsigned int)((var35 + 1)));
*(int *)((var5 + var35 * 4)) = var37;
var42 = (var10 + ((long)((int)((var37 * from))) * 4));
var45 = (unsigned long)((unsigned int)(tail));
to = 0;
do {
tail = var45;
if (((unsigned long)((unsigned int)(*(int *)((var42 + to * 4)))) != 0)) {
t155 = (*(int *)((&local_a8[0] + (to * 4))) - 1);
*(int *)((&local_a8[0] + (to * 4))) = t155;
tail = var45;
if (((unsigned long)((unsigned int)(t155)) == 0)) {
*(int *)((&local_68[0] + ((long)((int)(var45)) * 4))) = to;
tail = (unsigned long)((unsigned int)((var45 + 1)));
}
}
var51 = ((unsigned long)((unsigned int)(to)) + 1);
var45 = (unsigned long)((unsigned int)(tail));
to = var51;
} while (((((unsigned int)(from) == (unsigned int)(var51)) | ((long)(from) < (long)((int)(var51)))) == 0));
var52 = (var35 + 1);
var35 = var52;
} while (((((unsigned int)(tail) == (unsigned int)(var52)) | ((long)(tail) < (long)((int)(var52)))) == 0));
if (((unsigned int)(count) != (unsigned int)(from))) {
goto L_124d;
}
L_122e: ;
if ((local_20 != 0x28)) {
goto L_1254;
}
// x86-64 epilogue: tear down frame
return ret;
L_124d: ;
ret = 0xffffffff;
goto L_122e;
L_1254: ;
__stack_chk_fail();
}