Fixture 38
insertion shell sort
C · 2 functions · 4 lanes · 8 of 8 function-lanes behave identically
All 4 lanes recompile and return the same results as the original.
Insertion sort and Shell sort with the Knuth 3h+1 gap sequence. Both are inner loops whose trip count depends on the data, and Shell's outer gap loop divides by three, which lowers to a multiply-high sequence at -O2.
#include <stdint.h>
/* Insertion sort and Shell sort with the Knuth 3h+1 gap sequence. Both are
* inner loops whose trip count depends on the data, and Shell's outer gap loop
* divides by three, which lowers to a multiply-high sequence at -O2. */
#define SORT_MAX 16
__attribute__((noinline)) int32_t
insertion_sort_i32(int32_t *values, int32_t count) {
int32_t index;
if (values == 0 || count < 0 || count > SORT_MAX) {
return -1;
}
for (index = 1; index < count; ++index) {
int32_t key = values[index];
int32_t scan = index - 1;
while (scan >= 0 && values[scan] > key) {
values[scan + 1] = values[scan];
scan -= 1;
}
values[scan + 1] = key;
}
return count;
}
__attribute__((noinline)) int32_t
shell_sort_i32(int32_t *values, int32_t count) {
int32_t gap = 1;
int32_t index;
if (values == 0 || count < 0 || count > SORT_MAX) {
return -1;
}
while (gap < count / 3) {
gap = 3 * gap + 1;
}
while (gap >= 1) {
for (index = gap; index < count; ++index) {
int32_t key = values[index];
int32_t scan = index - gap;
while (scan >= 0 && values[scan] > key) {
values[scan + gap] = values[scan];
scan -= gap;
}
values[scan + gap] = key;
}
gap = gap / 3;
}
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
2/2insertion_sort_i32 pass 48 lines
// glaurung: insertion_sort_i32 @ 0x1100
int32_t insertion_sort_i32(int32_t * arg0, int32_t arg1) {
int index;
int key;
int scan;
signed char local_21;
int local_4;
long var11;
long var6;
if ((arg0 != 0)) {
if ((0 <= (long)(arg1))) {
if ((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16))) {
goto L_1136;
}
}
}
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
L_1136: ;
index = 1;
L_113d: ;
if ((arg1 <= index)) {
goto L_11dd;
}
key = arg0[(long)(index)];
var6 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(index)) - 1)));
scan = var6;
L_1160: ;
local_21 = 0;
if ((0 <= (long)(scan))) {
var11 = (unsigned long)((unsigned int)(arg0[(long)(scan)]));
local_21 = ((((unsigned int)(var11) == (unsigned int)(key)) | ((long)((int)(var11)) < (long)(key))) == 0);
}
if (((unsigned long)((unsigned char)((local_21 & 1))) != 0)) {
arg0[(long)((int)(((unsigned long)((unsigned int)(scan)) + 1)))] = arg0[(long)(scan)];
var6 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(scan)) - 1)));
scan = var6;
goto L_1160;
}
arg0[(long)((int)(((unsigned long)((unsigned int)(scan)) + 1)))] = key;
index = ((unsigned int)(index) + 1);
goto L_113d;
L_11dd: ;
local_4 = arg1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} shell_sort_i32 pass 84 lines
// glaurung: shell_sort_i32 @ 0x11f0
int32_t shell_sort_i32(int32_t * arg0, int32_t arg1) {
int gap;
int index;
int key;
int scan;
int local_28;
signed char local_29;
int local_4;
long t177;
long var18;
long var23;
long var59;
gap = 1;
if ((arg0 != 0)) {
if ((0 <= (long)(arg1))) {
if ((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16))) {
goto L_122d;
}
}
}
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
L_122d: ;
goto L_1232;
L_1232: ;
local_28 = gap;
if (((long)(local_28) < (long)((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)(3))))))) {
gap = ((gap * 3) + 1);
goto L_1232;
}
goto L_1264;
L_1264: ;
if (((long)(gap) < 1)) {
goto L_1329;
}
index = gap;
L_1274: ;
if ((arg1 <= index)) {
goto L_1316;
}
key = arg0[(long)(index)];
var18 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(index)) - gap)));
scan = var18;
L_1297: ;
local_29 = 0;
if ((0 <= (long)(scan))) {
var23 = (unsigned long)((unsigned int)(arg0[(long)(scan)]));
local_29 = ((((unsigned int)(var23) == (unsigned int)(key)) | ((long)((int)(var23)) < (long)(key))) == 0);
}
if (((unsigned long)((unsigned char)((local_29 & 1))) != 0)) {
arg0[(long)((int)(((unsigned long)((unsigned int)(scan)) + gap)))] = arg0[(long)(scan)];
var18 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(scan)) - (unsigned long)((unsigned int)(gap)))));
scan = var18;
goto L_1297;
}
arg0[(long)((int)(((unsigned long)((unsigned int)(scan)) + gap)))] = key;
index = ((unsigned int)(index) + 1);
goto L_1274;
L_1316: ;
gap = ((int)((((long long)(int)((((unsigned long)((long)((int)((unsigned long)((unsigned int)(gap))))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(gap)))) / (int)(3)));
goto L_1264;
L_1329: ;
index = 1;
L_1330: ;
if ((arg1 <= index)) {
goto L_137c;
}
var59 = (unsigned long)((unsigned int)(arg0[(long)((int)(((unsigned long)((unsigned int)(index)) - 1)))]));
t177 = arg0[(long)(index)];
if (((((unsigned int)(var59) == (unsigned int)(t177)) | ((long)((int)(var59)) < (long)((int)(t177)))) == 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
goto L_136e;
L_136e: ;
index = ((unsigned int)(index) + 1);
goto L_1330;
L_137c: ;
local_4 = arg1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} clang -O2
2/2insertion_sort_i32 pass 43 lines
// glaurung: insertion_sort_i32 @ 0x1100
int32_t insertion_sort_i32(int32_t * arg0, int32_t arg1) {
int key;
int index;
long ret;
long var0;
long var2;
long var4;
long var5;
long var7;
ret = 0xffffffff;
if ((arg0 == 0)) {
return ret;
}
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
return ret;
}
if (((unsigned long)(2) <= (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
var0 = (unsigned long)((unsigned int)(arg1));
var2 = 1;
do {
key = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + var2 * 4))));
var4 = var2;
while (1) {
var5 = (var4 - 1);
var7 = (unsigned long)((unsigned int)(arg0[(unsigned long)((unsigned int)(var5))]));
if (((((unsigned int)(var7) == (unsigned int)(key)) | ((long)((int)(var7)) < (long)(key))) != 0)) {
break;
}
*(int *)(((long)arg0 + var4 * 4)) = var7;
var4 = var5;
if (((var5 + 1) <= 1)) {
var4 = 0;
break;
}
}
arg0[(long)((int)(var4))] = key;
index = (var2 + 1);
var2 = (unsigned long)((unsigned int)(index));
} while ((index != var0));
}
return (unsigned int)(arg1);
} shell_sort_i32 pass 109 lines
// glaurung: shell_sort_i32 @ 0x1170
int32_t shell_sort_i32(int32_t * arg0, int32_t arg1) {
int gap;
int key;
int index;
int scan;
long local_8;
long ret;
long t21;
long var0;
long var13;
long var14;
long var16;
int var18;
long var23;
long var3;
long var34;
long var36;
int var38;
long var4;
long var40;
long var41;
long var43;
long var44;
long var6;
long var8;
local_8 = var0;
ret = 0xffffffff;
if ((arg0 == 0)) {
// x86-64 epilogue: tear down frame
return ret;
}
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
// x86-64 epilogue: tear down frame
return ret;
}
var3 = 1;
if (((unsigned long)((unsigned long)((unsigned int)(arg1))) < (unsigned long)(6))) {
L_11c4: ;
var4 = (long)(arg1);
gap = var3;
do {
var6 = (long)(gap);
if ((gap < arg1)) {
var8 = var6;
do {
key = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + var8 * 4))));
var13 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var8)) - gap)));
while (1) {
var14 = (unsigned long)((unsigned int)((gap + var13)));
var16 = (unsigned long)((unsigned int)(arg0[(unsigned long)((unsigned int)(var13))]));
if (((((unsigned int)(var16) == (unsigned int)(key)) | ((long)((int)(var16)) < (long)(key))) != 0)) {
break;
}
arg0[(long)((int)(var14))] = var16;
var18 = (var13 - gap);
var13 = (unsigned long)((unsigned int)(var18));
if (((long)((int)(var18)) < 0)) {
var14 = (unsigned long)((unsigned int)((var13 + gap)));
break;
}
}
arg0[(long)((int)(var14))] = key;
index = (var8 + 1);
var8 = (unsigned long)((unsigned int)(index));
} while ((index != var4));
}
var23 = (var6 * 0x55555556);
t21 = (((unsigned long)((unsigned int)(gap)) == 2) | ((long)(gap) < 2));
gap = (unsigned long)((unsigned int)((((unsigned long)(var23) >> 32) + ((unsigned long)(var23) >> 63))));
} while ((t21 == 0));
} else {
var34 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)((unsigned char)((arg1 & 255))) * 171))) >> 9)));
var3 = 1;
do {
var36 = (unsigned long)((unsigned int)(var3));
var38 = ((unsigned int)(((unsigned long)((unsigned int)(var3)) + ((unsigned long)((unsigned int)(var3)) * 2))) + 1);
var3 = (unsigned long)((unsigned int)(var38));
} while (((long)((int)(var38)) < (long)((int)(var34))));
if (((long)((int)(var36)) < 0)) {
goto L_123e;
}
goto L_11c4;
}
L_123e: ;
if (((long)(arg1) < 2)) {
ret = (unsigned long)((unsigned int)(arg1));
// x86-64 epilogue: tear down frame
return (unsigned int)(arg1);
}
var40 = (unsigned long)((unsigned int)(arg1));
var41 = (unsigned long)((unsigned int)(*(int *)(((long)arg0))));
var43 = 1;
while (1) {
var44 = (unsigned long)((unsigned int)(var41));
var41 = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + var43 * 4))));
if (((((unsigned int)(var44) == (unsigned int)(var41)) | ((long)((int)(var44)) < (long)((int)(var41)))) == 0)) {
break;
}
var43 = (var43 + 1);
if ((var40 == var43)) {
ret = (unsigned long)((unsigned int)(arg1));
// x86-64 epilogue: tear down frame
return (unsigned int)(arg1);
}
}
// x86-64 epilogue: tear down frame
return 0;
} gcc -O0
2/2insertion_sort_i32 pass 35 lines
// glaurung: insertion_sort_i32 @ 0x10f9
int32_t insertion_sort_i32(int32_t * arg0, int32_t arg1) {
int index;
int key;
int scan;
// x86-64 prologue: save rbp
if ((arg0 == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
if (((long)(arg1) < 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
index = 1;
while ((index < arg1)) {
key = arg0[(long)(index)];
scan = ((unsigned int)(index) - 1);
while ((0 <= (long)(scan))) {
if (((long)((int)(arg0[(long)(scan)])) <= (long)(key))) {
break;
}
arg0[((long)(scan) + 1)] = arg0[(long)(scan)];
scan = (scan - 1);
}
arg0[((long)(scan) + 1)] = key;
index = (index + 1);
}
// x86-64 epilogue: restore rbp
return (unsigned int)(arg1);
} shell_sort_i32 pass 69 lines
// glaurung: shell_sort_i32 @ 0x11dd
int32_t shell_sort_i32(int32_t * arg0, int32_t arg1) {
int gap;
int index;
int key;
int scan;
long var77;
long var83;
gap = 1;
if ((arg0 != 0)) {
if ((0 <= (long)(arg1))) {
if ((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16))) {
goto L_121f;
}
}
}
// x86-64 epilogue: restore rbp
return 0xffffffff;
L_1210: ;
gap = ((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(gap)) + (unsigned long)((unsigned int)(gap))))) + (unsigned long)((unsigned int)(gap)))) + 1);
L_121f: ;
if (((long)(gap) < (long)((int)(((unsigned long)((unsigned int)(((unsigned long)(((long)(arg1) * 0x55555556)) >> 32))) - (unsigned long)((unsigned int)(((int)(arg1) >> 31)))))))) {
goto L_1210;
}
goto L_1316;
L_1243: ;
index = gap;
goto L_12ed;
L_124e: ;
key = arg0[(long)(index)];
scan = ((unsigned int)(index) - gap);
goto L_12aa;
L_1272: ;
arg0[(long)((int)(((unsigned long)((unsigned int)(gap)) + (unsigned long)((unsigned int)(scan)))))] = arg0[(long)(scan)];
scan = (scan - (unsigned int)(gap));
L_12aa: ;
if ((0 <= (long)(scan))) {
if (((long)(key) < (long)((int)(arg0[(long)(scan)])))) {
goto L_1272;
}
}
arg0[(long)((int)(((unsigned long)((unsigned int)(gap)) + (unsigned long)((unsigned int)(scan)))))] = key;
index = (index + 1);
L_12ed: ;
if ((index < arg1)) {
goto L_124e;
}
gap = ((unsigned int)(((unsigned long)(((long)(gap) * 0x55555556)) >> 32)) - (unsigned int)(((int)(gap) >> 31)));
L_1316: ;
if (((((unsigned long)((unsigned int)(gap)) == 0) | ((long)(gap) < 0)) == 0)) {
goto L_1243;
}
index = 1;
goto L_1364;
L_1329: ;
var77 = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + (((long)(index) << 2) - 4)))));
var83 = (unsigned long)((unsigned int)(arg0[(long)(index)]));
if (((((unsigned int)(var77) == (unsigned int)(var83)) | ((long)((int)(var77)) < (long)((int)(var83)))) == 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
index = (index + 1);
L_1364: ;
if ((index < arg1)) {
goto L_1329;
}
// x86-64 epilogue: restore rbp
return (unsigned int)(arg1);
} gcc -O2
2/2insertion_sort_i32 pass 54 lines
// glaurung: insertion_sort_i32 @ 0x1100
int32_t insertion_sort_i32(int32_t * arg0, int32_t arg1) {
int key;
int index;
int scan;
long ret;
long var0;
long var11;
long var3;
long var6;
long var7;
long var8;
long var9;
ret = (unsigned long)((unsigned int)(arg1));
if ((arg0 == 0)) {
return 0xffffffff;
}
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
return 0xffffffff;
}
var0 = (unsigned long)((unsigned int)((arg1 - 2)));
if ((((unsigned long)((unsigned int)(arg1)) == 1) | ((long)(arg1) < 1))) {
return ret;
}
var3 = 0;
L_1120: ;
key = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + var3 * 4 + 0x4))));
var6 = var3;
do {
var7 = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + var6 * 4))));
var8 = (unsigned long)((unsigned int)(var6));
if ((((unsigned int)(var7) == (unsigned int)(key)) | ((long)((int)(var7)) < (long)(key)))) {
goto L_1160;
}
*(int *)(((long)arg0 + var6 * 4 + 0x4)) = var7;
var9 = (var6 - 1);
var6 = var9;
} while (((unsigned long)((unsigned int)(var9)) != 0xffffffff));
*(int *)((long)arg0) = key;
var11 = (var3 + 1);
if ((var0 == var3)) {
return ret;
}
L_1157: ;
var3 = var11;
goto L_1120;
L_1160: ;
arg0[(long)((int)((var8 + 1)))] = key;
var11 = (var3 + 1);
if ((var0 != var3)) {
goto L_1157;
}
return ret;
} shell_sort_i32 pass 125 lines
// glaurung: shell_sort_i32 @ 0x1180
int32_t shell_sort_i32(int32_t * arg0, int32_t arg1) {
int gap;
int key;
int scan;
long t10;
long var0;
long var10;
long var11;
long var12;
long var14;
long var15;
long var22;
long var23;
long var25;
long var26;
long var29;
long var3;
long var30;
long var31;
long var32;
long var33;
int var34;
int var35;
long var38;
long var40;
long var41;
long var42;
int var45;
if ((arg0 == 0)) {
goto L_12a1;
}
var0 = (unsigned long)((unsigned int)(arg1));
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
goto L_12a1;
}
var3 = (long)arg0;
var10 = (unsigned long)((unsigned int)((((unsigned long)(((long)(arg1) * 0x55555556)) >> 32) - (unsigned long)((unsigned int)(((int)(arg1) >> 31))))));
if ((((unsigned long)((unsigned int)(arg1)) == 5) | ((long)(arg1) < 5))) {
goto L_1297;
}
var11 = 1;
do {
var12 = (unsigned long)((unsigned int)(((var11 + (var11 * 2)) + 1)));
var11 = 4;
var14 = var12;
} while (((((unsigned int)(var10) == (unsigned int)(var12)) | ((long)((int)(var10)) < (long)((int)(var12)))) == 0));
L_11dd: ;
var15 = 0xaaaaaaab;
gap = var14;
L_11e8: ;
if ((((unsigned int)(var0) == (unsigned int)(gap)) | ((long)((int)(var0)) < (long)(gap)))) {
goto L_1234;
}
var22 = 0;
var23 = ((long)(gap) << 2);
var25 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var0)) - gap)));
var26 = (var3 + var23);
L_1200: ;
key = (unsigned long)((unsigned int)(*(int *)((var26))));
var29 = (unsigned long)((unsigned int)(var22));
var30 = var26;
var31 = (var26 - var23);
do {
var32 = (unsigned long)((unsigned int)(*(int *)((var31))));
var33 = var31;
if ((((unsigned int)(var32) == (unsigned int)(key)) | ((long)((int)(var32)) < (long)(key)))) {
goto L_1280;
}
*(int *)((var30)) = var32;
var31 = (var31 - var23);
var30 = (var30 - var23);
var34 = (var29 - gap);
var29 = (unsigned long)((unsigned int)(var34));
} while ((0 <= (long)((int)(var34))));
var35 = (var22 + 1);
var22 = (unsigned long)((unsigned int)(var35));
*(int *)((var33)) = key;
var26 = (var26 + 4);
if (((unsigned int)(var25) != (unsigned int)(var35))) {
goto L_1200;
}
L_1234: ;
var38 = ((unsigned long)(((unsigned long)((unsigned int)(gap)) * var15)) >> 33);
gap = var38;
if (((unsigned long)((unsigned int)(var38)) != 0)) {
goto L_11e8;
}
if ((((unsigned long)((unsigned int)(var0)) == 1) | ((long)((int)(var0)) < 1))) {
goto L_1273;
}
var40 = var3;
var41 = ((var3 + ((unsigned long)((unsigned int)((var0 - 2))) * 4)) + 4);
goto L_1269;
L_1260: ;
var40 = (var40 + 4);
if ((var40 == var41)) {
goto L_1273;
}
L_1269: ;
var42 = (unsigned long)((unsigned int)(*(int *)((var40 + 0x4))));
t10 = *(int *)((var40));
if ((((unsigned int)(t10) == (unsigned int)(var42)) | ((long)((int)(t10)) < (long)((int)(var42))))) {
goto L_1260;
}
var0 = 0;
L_1273: ;
// x86-64 epilogue: tear down frame
return (unsigned int)(var0);
L_1280: ;
var45 = (var22 + 1);
var22 = (unsigned long)((unsigned int)(var45));
var26 = (var26 + 4);
*(int *)(var30) = key;
if (((unsigned int)(var25) != (unsigned int)(var45))) {
goto L_1200;
}
goto L_1234;
L_1297: ;
var14 = 1;
goto L_11dd;
L_12a1: ;
var0 = 0xffffffff;
goto L_1273;
}