Fixture 37
heapsort
C · 1 functions · 4 lanes · 4 of 4 function-lanes behave identically
All 4 lanes recompile and return the same results as the original.
In-place heapsort: sift-down with two child indices and a trailing swap loop. The child-index arithmetic (2i+1, 2i+2) and its bounds test are a compact strength-reduction target at -O2.
#include <stdint.h>
/* In-place heapsort: sift-down with two child indices and a trailing swap
* loop. The child-index arithmetic (2i+1, 2i+2) and its bounds test are a
* compact strength-reduction target at -O2. */
#define HS_MAX 16
static void sift_down(int32_t *values, int32_t root, int32_t count) {
int32_t guard;
for (guard = 0; guard < HS_MAX; ++guard) {
int32_t left = 2 * root + 1;
int32_t right = left + 1;
int32_t largest = root;
int32_t swap;
if (left < count && values[left] > values[largest]) {
largest = left;
}
if (right < count && values[right] > values[largest]) {
largest = right;
}
if (largest == root) {
return;
}
swap = values[root];
values[root] = values[largest];
values[largest] = swap;
root = largest;
}
}
__attribute__((noinline)) int32_t
heapsort_i32(int32_t *values, int32_t count) {
int32_t index;
if (values == 0 || count < 0 || count > HS_MAX) {
return -1;
}
for (index = count / 2 - 1; index >= 0; --index) {
sift_down(values, index, count);
}
for (index = count - 1; index > 0; --index) {
int32_t swap = values[0];
values[0] = values[index];
values[index] = swap;
sift_down(values, 0, index);
}
for (index = 1; index < count; ++index) {
if (values[index - 1] > values[index]) {
return 0;
}
}
return count;
} 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/1heapsort_i32 pass 56 lines
// glaurung: heapsort_i32 @ 0x1100
int32_t heapsort_i32(int32_t * arg0, int32_t arg1) {
extern void sift_down(int *, int, int);
int index;
int swap;
int local_4;
long t158;
long var33;
if ((arg0 != 0)) {
if ((0 <= (long)(arg1))) {
if ((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16))) {
goto L_113a;
}
}
}
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
L_113a: ;
index = (((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))) - 1);
L_114b: ;
if ((0 <= (long)(index))) {
sift_down((int *)(arg0), (unsigned long)((unsigned int)(index)), (unsigned long)((unsigned int)(arg1)));
index = ((unsigned int)(index) - 1);
goto L_114b;
}
index = ((unsigned int)(arg1) - 1);
L_117b: ;
if (((((unsigned long)((unsigned int)(index)) == 0) | ((long)(index) < 0)) == 0)) {
swap = *(int *)((long)arg0);
*(int *)((long)arg0) = arg0[(long)(index)];
arg0[(long)(index)] = swap;
sift_down((int *)(arg0), 0, (unsigned long)((unsigned int)(index)));
index = ((unsigned int)(index) - 1);
goto L_117b;
}
index = 1;
L_11d0: ;
if ((arg1 <= index)) {
goto L_121c;
}
var33 = (unsigned long)((unsigned int)(arg0[(long)((int)(((unsigned long)((unsigned int)(index)) - 1)))]));
t158 = arg0[(long)(index)];
if (((((unsigned int)(var33) == (unsigned int)(t158)) | ((long)((int)(var33)) < (long)((int)(t158)))) == 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
goto L_120e;
L_120e: ;
index = ((unsigned int)(index) + 1);
goto L_11d0;
L_121c: ;
local_4 = arg1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} clang -O2
1/1heapsort_i32 pass 177 lines
// glaurung: heapsort_i32 @ 0x1100
int32_t heapsort_i32(int32_t * arg0, int32_t arg1) {
int left;
int right;
int swap;
int index;
int largest;
long ret;
long t11;
long t158;
long t159;
long t160;
long var0;
long var1;
long var10;
int var12;
long var13;
long var14;
long var16;
long var18;
long var2;
int var22;
long var23;
long var24;
long var26;
long var29;
long var3;
int var33;
long var37;
long var38;
long var39;
long var41;
int var43;
long var45;
long var47;
long var49;
int var53;
long var55;
long var57;
int var64;
long var65;
long var68;
long var9;
ret = 0xffffffff;
if ((arg0 == 0)) {
goto L_1284;
}
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
goto L_1284;
}
if (((unsigned long)(2) <= (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
goto L_11d0;
}
L_1124: ;
if (((long)(arg1) < 2)) {
goto L_1282;
}
var0 = (unsigned long)((unsigned int)(arg1));
var1 = (unsigned long)((unsigned int)(arg1));
goto L_114a;
L_1140: ;
if ((var2 <= 2)) {
goto L_125a;
}
L_114a: ;
var2 = var1;
var1 = (var1 - 1);
var3 = (unsigned long)((unsigned int)(*(int *)(((long)arg0))));
*(int *)(((long)arg0)) = arg0[(unsigned long)((unsigned int)(var1))];
arg0[(unsigned long)((unsigned int)(var1))] = var3;
var9 = 16;
var10 = 0;
do {
var12 = ((unsigned int)((var10 + var10)) + 1);
var13 = (unsigned long)((unsigned int)(var12));
var14 = (long)((int)(var10));
var16 = (unsigned long)((unsigned int)(var10));
if (((long)((int)(var12)) < (long)((int)(var1)))) {
var18 = (unsigned long)((unsigned int)(arg0[(long)((int)(var13))]));
t11 = *(int *)(((long)arg0 + var14 * 4));
if (((((unsigned int)(var18) == (unsigned int)(t11)) | ((long)((int)(var18)) < (long)((int)(t11)))) != 0)) {
var13 = (unsigned long)((unsigned int)(var10));
}
var16 = (unsigned long)((unsigned int)(var13));
}
var22 = ((unsigned int)((var10 + var10)) + 2);
var23 = (unsigned long)((unsigned int)(var22));
var24 = var16;
if (((long)((int)(var22)) < (long)((int)(var1)))) {
var26 = (unsigned long)((unsigned int)(arg0[(long)((int)(var23))]));
t158 = arg0[(long)((int)(var16))];
if (((((unsigned int)(var26) == (unsigned int)(t158)) | ((long)((int)(var26)) < (long)((int)(t158)))) != 0)) {
var23 = (unsigned long)((unsigned int)(var16));
}
var24 = (unsigned long)((unsigned int)(var23));
}
if (((unsigned int)(var24) == (unsigned int)(var10))) {
goto L_1140;
}
var29 = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + var14 * 4))));
*(int *)(((long)arg0 + var14 * 4)) = arg0[(long)((int)(var24))];
arg0[(long)((int)(var24))] = var29;
var33 = (var9 - 1);
var9 = (unsigned long)((unsigned int)(var33));
var10 = (unsigned long)((unsigned int)(var24));
} while (((unsigned long)((unsigned int)(var33)) != 0));
goto L_1140;
L_11d0: ;
var37 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) >> 1)));
goto L_11ea;
L_11e0: ;
if ((((unsigned long)((unsigned int)(var38)) == 1) | ((long)((int)(var38)) < 1))) {
goto L_1124;
}
L_11ea: ;
var38 = (unsigned long)((unsigned int)(var37));
var37 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var37)) - 1)));
var39 = 16;
var41 = (unsigned long)((unsigned int)(var37));
do {
var43 = ((unsigned int)((var41 + var41)) + 1);
left = (unsigned long)((unsigned int)(var43));
var45 = (long)((int)(var41));
var47 = (unsigned long)((unsigned int)(var41));
if ((var43 < arg1)) {
var49 = (unsigned long)((unsigned int)(arg0[(long)(left)]));
t159 = *(int *)(((long)arg0 + var45 * 4));
if (((((unsigned int)(var49) == (unsigned int)(t159)) | ((long)((int)(var49)) < (long)((int)(t159)))) != 0)) {
left = (unsigned long)((unsigned int)(var41));
}
var47 = (unsigned long)((unsigned int)(left));
}
var53 = ((unsigned int)((var41 + var41)) + 2);
right = (unsigned long)((unsigned int)(var53));
var55 = var47;
if ((var53 < arg1)) {
var57 = (unsigned long)((unsigned int)(arg0[(long)(right)]));
t160 = arg0[(long)((int)(var47))];
if (((((unsigned int)(var57) == (unsigned int)(t160)) | ((long)((int)(var57)) < (long)((int)(t160)))) != 0)) {
right = (unsigned long)((unsigned int)(var47));
}
var55 = (unsigned long)((unsigned int)(right));
}
if (((unsigned int)(var55) == (unsigned int)(var41))) {
goto L_11e0;
}
swap = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + var45 * 4))));
*(int *)(((long)arg0 + var45 * 4)) = arg0[(long)((int)(var55))];
arg0[(long)((int)(var55))] = swap;
var64 = (var39 - 1);
var39 = (unsigned long)((unsigned int)(var64));
var41 = (unsigned long)((unsigned int)(var55));
} while (((unsigned long)((unsigned int)(var64)) != 0));
goto L_11e0;
L_125a: ;
if (((long)(arg1) < 2)) {
goto L_1282;
}
var65 = (unsigned long)((unsigned int)(*(int *)(((long)arg0))));
index = 1;
do {
var68 = (unsigned long)((unsigned int)(var65));
var65 = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + index * 4))));
if (((((unsigned int)(var68) == (unsigned int)(var65)) | ((long)((int)(var68)) < (long)((int)(var65)))) == 0)) {
goto L_1289;
}
index = (index + 1);
} while ((var0 != index));
L_1282: ;
ret = (unsigned long)((unsigned int)(arg1));
L_1284: ;
// x86-64 epilogue: tear down frame
return ret;
L_1289: ;
ret = 0;
goto L_1284;
} gcc -O0
1/1heapsort_i32 pass 55 lines
// glaurung: heapsort_i32 @ 0x122d
int32_t heapsort_i32(int32_t * arg0, int32_t arg1) {
extern void sift_down(int *, int, int);
int index;
int swap;
long var41;
long var47;
if ((arg0 != 0)) {
if ((0 <= (long)(arg1))) {
if ((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16))) {
goto L_125d;
}
}
}
// x86-64 epilogue: restore rbp
return 0xffffffff;
L_125d: ;
index = ((unsigned int)(((int)(((unsigned long)((unsigned int)(arg1)) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) >> 31))))) >> 1)) - 1);
goto L_1289;
L_1271: ;
sift_down((int *)(arg0), (unsigned long)((unsigned int)(index)), (unsigned long)((unsigned int)(arg1)));
index = (index - 1);
L_1289: ;
if ((0 <= (long)(index))) {
goto L_1271;
}
index = ((unsigned int)(arg1) - 1);
goto L_12f0;
L_129a: ;
swap = *(int *)((long)arg0);
*(int *)((long)arg0) = arg0[(long)(index)];
arg0[(long)(index)] = swap;
sift_down((int *)(arg0), 0, (unsigned long)((unsigned int)(index)));
index = (index - 1);
L_12f0: ;
if (((((unsigned long)((unsigned int)(index)) == 0) | ((long)(index) < 0)) == 0)) {
goto L_129a;
}
index = 1;
goto L_133a;
L_12ff: ;
var41 = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + (((long)(index) << 2) - 4)))));
var47 = (unsigned long)((unsigned int)(arg0[(long)(index)]));
if (((((unsigned int)(var41) == (unsigned int)(var47)) | ((long)((int)(var41)) < (long)((int)(var47)))) == 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
index = (index + 1);
L_133a: ;
if ((index < arg1)) {
goto L_12ff;
}
// x86-64 epilogue: restore rbp
return (unsigned int)(arg1);
} gcc -O2
1/1heapsort_i32 pass 75 lines
// glaurung: heapsort_i32 @ 0x1190
int32_t heapsort_i32(int32_t * arg0, int32_t arg1) {
extern void sift_down(int *, int, int);
int index;
int swap;
long cf_5;
long local_18;
long local_8;
long t10;
long var0;
long var1;
long var11;
long var14;
long var2;
long var20;
long var22;
long var23;
long var7;
int var9;
local_8 = var0;
local_18 = var1;
if ((arg0 == 0)) {
var2 = 0xffffffff;
// x86-64 epilogue: tear down frame
return 0xffffffff;
}
var2 = (unsigned long)((unsigned int)(arg1));
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
var2 = 0xffffffff;
// x86-64 epilogue: tear down frame
return 0xffffffff;
}
var7 = (long)arg0;
var9 = ((int)(arg1) >> 1);
var11 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var9)) - 1)));
if (((unsigned long)((unsigned int)(var9)) != 0)) {
do {
sift_down((int *)(var7), (unsigned long)((unsigned int)(var11)), (unsigned long)((unsigned int)(var2)));
cf_5 = ((unsigned long)((unsigned long)((unsigned int)(var11))) < (unsigned long)(1));
var11 = (unsigned long)((unsigned int)((var11 - 1)));
} while ((cf_5 == 0));
}
var14 = (unsigned long)((unsigned int)((var2 - 1)));
if (((((unsigned long)((unsigned int)(var14)) == 0) | ((long)((int)(var14)) < 0)) == 0)) {
index = (long)((int)(var14));
do {
swap = (unsigned long)((unsigned int)(*(int *)((var7))));
*(int *)((var7)) = *(int *)((var7 + index * 4));
var20 = (unsigned long)((unsigned int)(index));
*(int *)((var7 + index * 4)) = swap;
index = (index - 1);
sift_down((int *)(var7), 0, var20);
} while (((((unsigned long)((unsigned int)(index)) == 0) | ((long)(index) < 0)) == 0));
}
if ((((unsigned long)((unsigned int)(var2)) == 1) | ((long)((int)(var2)) < 1))) {
// x86-64 epilogue: tear down frame
return (unsigned int)(var2);
}
var22 = ((var7 + ((unsigned long)((unsigned int)((var2 - 2))) * 4)) + 4);
while (1) {
var23 = (unsigned long)((unsigned int)(*(int *)((var7 + 0x4))));
t10 = *(int *)((var7));
if (((((unsigned int)(t10) == (unsigned int)(var23)) | ((long)((int)(t10)) < (long)((int)(var23)))) == 0)) {
break;
}
var7 = (var7 + 4);
if ((var22 == var7)) {
// x86-64 epilogue: tear down frame
return (unsigned int)(var2);
}
}
var2 = 0;
// x86-64 epilogue: tear down frame
return 0;
}