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.

tests/decompiler_fixtures/src/63_numerical_integration.c source
#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/2
simpson_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/2
simpson_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/2
simpson_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/2
simpson_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);
}

← 213 fixtures