Fixture 63
numerical integration
C · 2 functions · 4 lanes · 6 of 8 function-lanes behave identically
One lane has a function that returns a different result after decompilation: gcc-O2 (0/2).
Trapezoid and Simpson quadrature of a fixed cubic in Q16.16. Simpson's alternating 4/2 weights produce a parity test inside the accumulation loop, which is a small but reliable structuring probe.
#include <stdint.h>
/* Trapezoid and Simpson quadrature of a fixed cubic in Q16.16. Simpson's
* alternating 4/2 weights produce a parity test inside the accumulation loop,
* which is a small but reliable structuring probe. */
#define QUAD_STEPS_MAX 32
static int32_t quad_mul_q16(int32_t left, int32_t right) {
return (int32_t)(((int64_t)left * (int64_t)right) >> 16);
}
static int32_t quad_cubic(int32_t x) {
int32_t square = quad_mul_q16(x, x);
int32_t cube = quad_mul_q16(square, x);
return cube - quad_mul_q16(2 * 65536, square) + x;
}
__attribute__((noinline)) int32_t
trapezoid_integrate(int32_t lower, int32_t upper, int32_t steps) {
int64_t total = 0;
int32_t width;
int32_t index;
if (steps < 1 || steps > QUAD_STEPS_MAX || upper < lower) {
return 0;
}
width = (upper - lower) / steps;
for (index = 0; index <= steps; ++index) {
int32_t sample = quad_cubic(lower + width * index);
if (index == 0 || index == steps) {
total += sample;
} else {
total += 2 * (int64_t)sample;
}
}
return (int32_t)((total * (int64_t)width) / (2 * 65536));
}
__attribute__((noinline)) int32_t
simpson_integrate(int32_t lower, int32_t upper, int32_t steps) {
int64_t total = 0;
int32_t width;
int32_t index;
if (steps < 2 || steps > QUAD_STEPS_MAX || (steps % 2) != 0 ||
upper < lower) {
return 0;
}
width = (upper - lower) / steps;
for (index = 0; index <= steps; ++index) {
int32_t sample = quad_cubic(lower + width * index);
if (index == 0 || index == steps) {
total += sample;
} else if ((index % 2) == 1) {
total += 4 * (int64_t)sample;
} else {
total += 2 * (int64_t)sample;
}
}
return (int32_t)((total * (int64_t)width) / (3 * 65536));
} 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.
gcc -O2
0/2simpson_integrate fail 75 lines
// glaurung: simpson_integrate @ 0x11a0
int32_t simpson_integrate(int32_t arg0, int32_t arg1, int32_t arg2) {
int width;
int index;
int sample;
long total;
long ret;
long var0;
long var16;
long var2;
int var20;
long var26;
int var36;
int var38;
long var42;
long var9;
var0 = (unsigned long)((unsigned int)(arg2));
var2 = (unsigned long)((unsigned int)(arg0));
ret = 0;
if (((unsigned long)(30) < (unsigned long)((unsigned long)((unsigned int)((arg2 - 2)))))) {
return ret;
}
if ((arg1 < arg0)) {
return 0;
}
if (((unsigned long)((unsigned char)(((unsigned long)((unsigned int)(arg2)) & 1))) != 0)) {
return 0;
}
var9 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) - arg0)));
width = ((int)((((long long)(int)((((unsigned long)((long)((int)(var9))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)(var9)) / (int)((unsigned long)((unsigned int)(arg2)))));
index = 0;
var16 = 0;
L_11f6: ;
while (1) {
var20 = ((unsigned int)(((unsigned long)((unsigned int)(width)) * index)) + var2);
var26 = (long)((int)(((long)(((long)((int)(var20)) * (long)((int)(var20)))) >> 16)));
sample = (long)((int)(((unsigned long)((unsigned int)((((long)(((long)((int)(var20)) * var26)) >> 16) - (var26 + var26)))) + (unsigned long)((unsigned int)(var20)))));
if (((unsigned long)((unsigned int)(index)) == 0)) {
goto L_122d;
}
goto L_1228;
L_11e0: ;
if (((unsigned long)((unsigned char)((index & 1))) != 0)) {
goto L_1268;
}
total = (var16 + ((unsigned long)((unsigned int)(sample)) * 2));
L_11ee: ;
var36 = (index + 1);
index = (unsigned long)((unsigned int)(var36));
var16 = total;
if (((long)((int)(var0)) < (long)((int)(var36)))) {
goto L_1238;
}
goto L_11f6;
L_1228: ;
if (((unsigned int)(var0) != (unsigned int)(index))) {
goto L_11e0;
}
L_122d: ;
var38 = (index + 1);
total = (var16 + (unsigned long)((unsigned int)(sample)));
index = (unsigned long)((unsigned int)(var38));
var16 = total;
if (((long)((int)(var38)) <= (long)((int)(var0)))) {
goto L_11f6;
}
goto L_1238;
L_1268: ;
total = (var16 + ((unsigned long)((unsigned int)(sample)) * 4));
goto L_11ee;
}
L_1238: ;
var42 = ((long)(width) * total);
return (unsigned int)((((long)(((long)(((unsigned __int128)((__int128)(long)(var42) * (__int128)(long)(0x2aaaaaaaaaaaaaab))) >> 64))) >> 15) - ((long)(var42) >> 63)));
} trapezoid_integrate fail 63 lines
// glaurung: trapezoid_integrate @ 0x1100
int32_t trapezoid_integrate(int32_t arg0, int32_t arg1, int32_t arg2) {
int width;
int index;
int sample;
long total;
long var0;
long var15;
int var19;
long var2;
long var25;
int var34;
int var37;
long var40;
long var6;
var0 = (unsigned long)((unsigned int)(arg2));
var2 = (unsigned long)((unsigned int)(arg0));
if (((unsigned long)(31) < (unsigned long)((unsigned long)((unsigned int)((arg2 - 1)))))) {
return 0;
}
if ((arg1 < arg0)) {
return 0;
}
var6 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) - arg0)));
width = ((int)((((long long)(int)((((unsigned long)((long)((int)(var6))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)(var6)) / (int)((unsigned long)((unsigned int)(arg2)))));
index = 0;
var15 = 0;
L_1134: ;
while (1) {
var19 = ((unsigned int)(((unsigned long)((unsigned int)(width)) * index)) + var2);
var25 = (long)((int)(((long)(((long)((int)(var19)) * (long)((int)(var19)))) >> 16)));
sample = (long)((int)(((unsigned long)((unsigned int)((((long)(((long)((int)(var19)) * var25)) >> 16) - (var25 + var25)))) + (unsigned long)((unsigned int)(var19)))));
if (((unsigned long)((unsigned int)(index)) == 0)) {
goto L_116b;
}
goto L_1166;
L_1128: ;
var34 = (index + 1);
total = (var15 + ((unsigned long)((unsigned int)(sample)) * 2));
index = (unsigned long)((unsigned int)(var34));
var15 = total;
if (((long)((int)(var0)) < (long)((int)(var34)))) {
goto L_1176;
}
goto L_1134;
L_1166: ;
if (((unsigned int)(var0) != (unsigned int)(index))) {
goto L_1128;
}
L_116b: ;
var37 = (index + 1);
total = (var15 + (unsigned long)((unsigned int)(sample)));
index = (unsigned long)((unsigned int)(var37));
var15 = total;
if (((long)((int)(var37)) <= (long)((int)(var0)))) {
goto L_1134;
}
goto L_1176;
}
L_1176: ;
var40 = ((long)(width) * total);
return ((long)(((var40 < 0) ? (var40 + 0x1ffff) : var40)) >> 17);
} clang -O0
2/2simpson_integrate pass 41 lines
// glaurung: simpson_integrate @ 0x1240
int32_t simpson_integrate(int32_t arg0, int32_t arg1, int32_t arg2) {
extern int quad_cubic(int);
long total;
int width;
int index;
int sample;
int local_4;
int var18;
long var37;
long var8;
// x86-64 prologue: save rbp, frame 48 bytes
total = 0;
if (((long)(arg2) < 2)) {
// x86-64 epilogue: restore rbp
return 0;
}
if (((((unsigned long)((unsigned int)(arg2)) == 32) | ((long)(arg2) < 32)) == 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
if (((unsigned long)((unsigned int)(((int)((((long long)(int)((((unsigned long)((long)((int)((unsigned long)((unsigned int)(arg2))))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg2)))) % (int)(2))))) != 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
if ((arg1 < arg0)) {
// x86-64 epilogue: restore rbp
return 0;
}
var8 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) - arg0)));
width = ((int)((((long long)(int)((((unsigned long)((long)((int)(var8))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)(var8)) / (int)(arg2)));
for (index = 0; ((((unsigned int)(index) == (unsigned int)(arg2)) | (index < arg2)) != 0); index++) {
var18 = quad_cubic((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(width)) * index)))))));
sample = var18;
total = ((((unsigned long)((unsigned int)(index)) == 0) || ((unsigned int)(index) == (unsigned int)(arg2))) ? ((long)(sample) + total) : (((unsigned long)((unsigned int)(((int)((((long long)(int)((((unsigned long)((long)((int)((unsigned long)((unsigned int)(index))))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(index)))) % (int)(2))))) != 1) ? (((long)(sample) << 1) + total) : (((long)(sample) << 2) + total)));
}
var37 = (total * (long)(width));
local_4 = ((long)((((__int128)(long)(((long)(var37) >> 63)) * (((__int128)1) << 64)) + (unsigned long)(var37)) / (long)(0x30000)));
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} trapezoid_integrate pass 37 lines
// glaurung: trapezoid_integrate @ 0x1100
int32_t trapezoid_integrate(int32_t arg0, int32_t arg1, int32_t arg2) {
extern int quad_cubic(int);
long total;
int width;
int index;
int sample;
int local_4;
int var13;
long var26;
long var3;
// x86-64 prologue: save rbp, frame 48 bytes
total = 0;
if (((long)(arg2) < 1)) {
// x86-64 epilogue: restore rbp
return 0;
}
if (((((unsigned long)((unsigned int)(arg2)) == 32) | ((long)(arg2) < 32)) == 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
if ((arg1 < arg0)) {
// x86-64 epilogue: restore rbp
return 0;
}
var3 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) - arg0)));
width = ((int)((((long long)(int)((((unsigned long)((long)((int)(var3))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)(var3)) / (int)(arg2)));
for (index = 0; ((((unsigned int)(index) == (unsigned int)(arg2)) | (index < arg2)) != 0); index++) {
var13 = quad_cubic((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(width)) * index)))))));
sample = var13;
total = ((((unsigned long)((unsigned int)(index)) == 0) || ((unsigned int)(index) == (unsigned int)(arg2))) ? ((long)(sample) + total) : (((long)(sample) << 1) + total));
}
var26 = (total * (long)(width));
local_4 = ((long)((((__int128)(long)(((long)(var26) >> 63)) * (((__int128)1) << 64)) + (unsigned long)(var26)) / (long)(0x20000)));
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} clang -O2
2/2simpson_integrate pass 58 lines
// glaurung: simpson_integrate @ 0x11b0
int32_t simpson_integrate(int32_t arg0, int32_t arg1, int32_t arg2) {
long total;
int index;
int width;
long ret;
int var1;
long var12;
long var13;
long var14;
long var16;
long var18;
long var20;
long var26;
long var29;
long var37;
long var38;
long var42;
int var47;
ret = 0;
var1 = (arg1 - arg0);
if ((arg1 < arg0)) {
return ret;
}
if (((unsigned long)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg2)) - 33)))) < (unsigned long)(0xffffffe1))) {
return ret;
}
if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg2)) & 1))) != 0)) {
return ret;
}
var12 = (unsigned long)((unsigned int)(arg2));
var13 = (long)((int)(((int)((((long long)(int)((((unsigned long)((long)((int)((unsigned long)((unsigned int)((unsigned long)((unsigned int)(var1))))))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)((unsigned long)((unsigned int)(var1)))))) / (int)((unsigned long)((unsigned int)(arg2)))))));
var14 = (long)(arg0);
var16 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg2)) + 1)));
var18 = ((long)(arg0) << 16);
var20 = (var13 << 16);
total = 0;
var26 = 0;
do {
var29 = ((long)((var18 * var14)) >> 32);
var37 = (long)((int)(((unsigned long)((unsigned int)((((unsigned long)((var29 * var14)) >> 16) - (unsigned long)((unsigned int)((var29 + var29)))))) + var14)));
if ((var26 != 0)) {
if ((var12 != var26)) {
var37 = (((unsigned long)((unsigned char)((var26 & 1))) == 0) ? (var37 + var37) : (var37 << 2));
}
}
total = (total + var37);
var38 = (var26 + 1);
var14 = (var14 + var13);
var18 = (var18 + var20);
var26 = var38;
} while ((var16 != var38));
var42 = ((long)(((unsigned __int128)((__int128)(long)((total * var13)) * (__int128)(long)(0x2aaaaaaaaaaaaaab))) >> 64));
var47 = (((unsigned long)(var42) >> 15) + ((unsigned long)(var42) >> 63));
ret = (unsigned long)((unsigned int)(var47));
// x86-64 epilogue: tear down frame
return (unsigned int)(var47);
} trapezoid_integrate pass 42 lines
// glaurung: trapezoid_integrate @ 0x1100
int32_t trapezoid_integrate(int32_t arg0, int32_t arg1, int32_t arg2) {
int index;
long total;
int width;
long ret;
int var1;
long var10;
long var11;
long var13;
long var15;
long var17;
long var26;
long var44;
long var9;
ret = 0;
var1 = (arg1 - arg0);
if ((arg1 < arg0)) {
return ret;
}
if (((unsigned long)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg2)) - 33)))) < (unsigned long)(0xffffffe0))) {
return ret;
}
var9 = (unsigned long)((unsigned int)(arg2));
var10 = (long)((int)(((int)((((long long)(int)((((unsigned long)((long)((int)((unsigned long)((unsigned int)((unsigned long)((unsigned int)(var1))))))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)((unsigned long)((unsigned int)(var1)))))) / (int)((unsigned long)((unsigned int)(arg2)))))));
var11 = (long)(arg0);
var13 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg2)) + 1)));
var15 = ((long)(arg0) << 16);
var17 = (var10 << 16);
index = 0;
total = 0;
do {
var26 = ((long)((var15 * var11)) >> 32);
total = (total + ((long)((int)(((unsigned long)((unsigned int)((((unsigned long)((var26 * var11)) >> 16) - (unsigned long)((unsigned int)((var26 + var26)))))) + var11))) << (((var9 != index) & (index != 0)) & 63)));
index = (index + 1);
var11 = (var11 + var10);
var15 = (var15 + var17);
} while ((var13 != index));
var44 = (total * var10);
// x86-64 epilogue: tear down frame
return ((unsigned long)(((0 <= var44) ? var44 : (var44 + 0x1ffff))) >> 17);
} gcc -O0
2/2simpson_integrate pass 45 lines
// glaurung: simpson_integrate @ 0x1223
int32_t simpson_integrate(int32_t arg0, int32_t arg1, int32_t arg2) {
extern int quad_cubic(int);
long total;
int width;
int index;
int sample;
int var18;
long var27;
long var43;
long var6;
// x86-64 prologue: save rbp, frame 48 bytes
total = 0;
if ((((unsigned long)((unsigned int)(arg2)) == 1) | ((long)(arg2) < 1))) {
// x86-64 epilogue: restore rbp
return 0;
}
if (((((unsigned long)((unsigned int)(arg2)) == 32) | ((long)(arg2) < 32)) == 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg2)) & 1))) != 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
if ((arg1 < arg0)) {
// x86-64 epilogue: restore rbp
return 0;
}
var6 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) - arg0)));
width = ((int)((((long long)(int)((((unsigned long)((long)((int)(var6))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)(var6)) / (int)(arg2)));
for (index = 0; ((((unsigned int)(index) == (unsigned int)(arg2)) | (index < arg2)) != 0); index++) {
var18 = quad_cubic((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(width)) * index)))))));
sample = var18;
if ((((unsigned long)((unsigned int)(index)) == 0) || ((unsigned int)(index) == (unsigned int)(arg2)))) {
total = (total + (long)(sample));
} else {
var27 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((((unsigned long)((long)(index)) >> 32) & 0xffffffff))) >> 31)));
total = (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(index)) + var27))) & 1))) - var27))) != 1) ? (total + ((long)(sample) + (long)(sample))) : (total + ((long)(sample) << 2)));
}
}
var43 = ((long)(width) * total);
// x86-64 epilogue: restore rbp
return (((long)(((long)(((unsigned __int128)((__int128)(long)(var43) * (__int128)(long)(0x2aaaaaaaaaaaaaab))) >> 64))) >> 15) - ((long)(var43) >> 63));
} trapezoid_integrate pass 35 lines
// glaurung: trapezoid_integrate @ 0x116e
int32_t trapezoid_integrate(int32_t arg0, int32_t arg1, int32_t arg2) {
extern int quad_cubic(int);
long total;
int width;
int index;
int sample;
int var15;
long var25;
long var3;
// x86-64 prologue: save rbp, frame 48 bytes
total = 0;
if ((((unsigned long)((unsigned int)(arg2)) == 0) | ((long)(arg2) < 0))) {
// x86-64 epilogue: restore rbp
return 0;
}
if (((((unsigned long)((unsigned int)(arg2)) == 32) | ((long)(arg2) < 32)) == 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
if ((arg1 < arg0)) {
// x86-64 epilogue: restore rbp
return 0;
}
var3 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) - arg0)));
width = ((int)((((long long)(int)((((unsigned long)((long)((int)(var3))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)(var3)) / (int)(arg2)));
for (index = 0; ((((unsigned int)(index) == (unsigned int)(arg2)) | (index < arg2)) != 0); index++) {
var15 = quad_cubic((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(width)) * index)))))));
sample = var15;
total = ((((unsigned long)((unsigned int)(index)) == 0) || ((unsigned int)(index) == (unsigned int)(arg2))) ? (total + (long)(sample)) : (total + ((long)(sample) + (long)(sample))));
}
var25 = ((long)(width) * total);
// x86-64 epilogue: restore rbp
return ((long)(((var25 < 0) ? (var25 + 0x1ffff) : var25)) >> 17);
}