Fixture 28

euler ode

C · 1 functions · 4 lanes · 4 of 4 function-lanes behave identically

All 4 lanes recompile and return the same results as the original.

tests/decompiler_fixtures/src/28_euler_ode.c source
#include <limits.h>
#include <stdint.h>

__attribute__((noinline)) int32_t euler_decay_q16(int32_t initial_q16,
                                                  int32_t rate_q16,
                                                  int32_t steps) {
    int64_t state = initial_q16;
    int32_t step;
    if (steps < 0 || steps > 32) {
        return initial_q16;
    }
    for (step = 0; step < steps; ++step) {
        int64_t delta = (state * (int64_t)rate_q16) / 65536;
        state -= delta;
        if (state > INT32_MAX) {
            state = INT32_MAX;
        } else if (state < INT32_MIN) {
            state = INT32_MIN;
        }
    }
    return (int32_t)state;
}

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/1
euler_decay_q16 pass 35 lines
// glaurung: euler_decay_q16 @ 0x1100
int32_t euler_decay_q16(int32_t arg0, int32_t arg1, int32_t arg2) {
    long state;
    int step;
    long delta;
    int local_4;
    long var5;
    // x86-64 prologue: save rbp
    state = arg0;
    if (((long)(arg2) < 0)) {
        local_4 = arg0;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg2)) == 32) | ((long)(arg2) < 32)) == 0)) {
        local_4 = arg0;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    for (step = 0; (step < arg2); step++) {
        var5 = (state * (long)(arg1));
        delta = ((long)((((__int128)(long)(((long)(var5) >> 63)) * (((__int128)1) << 64)) + (unsigned long)(var5)) / (long)(0x10000)));
        state = (state - delta);
        if ((state <= 0x7fffffff)) {
            if ((state < -0x80000000LL)) {
                state = -0x80000000LL;
            }
        } else {
            state = 0x7fffffff;
        }
    }
    local_4 = state;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}

clang -O2

1/1
euler_decay_q16 pass 67 lines
// glaurung: euler_decay_q16 @ 0x1100
int32_t euler_decay_q16(int32_t arg0, int32_t arg1, int32_t arg2) {
    long state;
    int step;
    long var1;
    long var11;
    long var12;
    long var14;
    long var16;
    int var21;
    long var22;
    long var26;
    long var28;
    long var4;
    long var5;
    long var7;
    state = (unsigned long)((unsigned int)(arg0));
    if (((unsigned long)(32) < (unsigned long)((unsigned long)((unsigned int)(arg2))))) {
        return state;
    }
    state = (long)(arg0);
    if (((unsigned long)((unsigned int)(arg2)) == 0)) {
        return state;
    }
    var1 = (long)(arg1);
    if (((unsigned long)((unsigned int)(arg2)) != 1)) {
        var4 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg2)) & -2)));
        var5 = state;
        do {
            var7 = (var5 * var1);
            var11 = (var5 - ((long)(((0 <= var7) ? var7 : (var7 + 0xffff))) >> 16));
            var12 = var11;
            if ((var11 < -0x7fffffffLL)) {
                var12 = -0x80000000LL;
            }
            var14 = var12;
            if ((0x7fffffff <= var12)) {
                var14 = 0x7fffffff;
            }
            var16 = (var14 * var1);
            state = (var14 - ((long)(((0 <= var16) ? var16 : (var16 + 0xffff))) >> 16));
            if ((state < -0x7fffffffLL)) {
                state = -0x80000000LL;
                if (1) {
                    goto L_1160;
                }
                goto L_11df;
            } else {
                if ((0x7fffffff <= state)) {
                    L_11df: ;
                    state = 0x7fffffff;
                }
            }
            L_1160: ;
            var21 = (var4 - 2);
            var4 = (unsigned long)((unsigned int)(var21));
            var5 = state;
        } while (((unsigned long)((unsigned int)(var21)) != 0));
    }
    if (((unsigned long)((unsigned char)((arg2 & 1))) != 0)) {
        var22 = (var1 * state);
        var26 = (state - ((long)(((0 <= var22) ? var22 : (var22 + 0xffff))) >> 16));
        var28 = ((-0x7fffffffLL <= var26) ? var26 : -0x80000000LL);
        state = ((var28 < 0x7fffffff) ? var28 : 0x7fffffff);
    }
    return state;
}

gcc -O0

1/1
euler_decay_q16 pass 31 lines
// glaurung: euler_decay_q16 @ 0x10f9
int32_t euler_decay_q16(int32_t arg0, int32_t arg1, int32_t arg2) {
    long state;
    int step;
    long delta;
    long var5;
    // x86-64 prologue: save rbp
    state = arg0;
    if (((long)(arg2) < 0)) {
        // x86-64 epilogue: restore rbp
        return (unsigned int)(arg0);
    }
    if (((((unsigned long)((unsigned int)(arg2)) == 32) | ((long)(arg2) < 32)) == 0)) {
        // x86-64 epilogue: restore rbp
        return (unsigned int)(arg0);
    }
    for (step = 0; (step < arg2); step++) {
        var5 = ((long)(arg1) * state);
        delta = ((long)(((var5 < 0) ? (var5 + 0xffff) : var5)) >> 16);
        state = (state - delta);
        if ((state < 0x80000000)) {
            if ((state <= -0x80000001LL)) {
                state = -0x80000000LL;
            }
        } else {
            state = 0x7fffffff;
        }
    }
    // x86-64 epilogue: restore rbp
    return state;
}

gcc -O2

1/1
euler_decay_q16 pass 31 lines
// glaurung: euler_decay_q16 @ 0x1100
int32_t euler_decay_q16(int32_t arg0, int32_t arg1, int32_t arg2) {
    int step;
    long state;
    long delta;
    long ret;
    long var0;
    long var1;
    long var12;
    int var14;
    long var6;
    ret = (unsigned long)((unsigned int)(arg0));
    if (((unsigned long)(32) < (unsigned long)((unsigned long)((unsigned int)(arg2))))) {
        return ret;
    }
    var0 = (long)(arg0);
    if (((unsigned long)((unsigned int)(arg2)) == 0)) {
        return ret;
    }
    var1 = (long)(arg1);
    step = 0;
    do {
        var6 = (var0 * var1);
        state = (var0 - ((long)(((0 <= var6) ? var6 : (var6 + 0xffff))) >> 16));
        var12 = ((state < -0x80000000LL) ? -0x80000000LL : state);
        var0 = ((0x7fffffff < var12) ? 0x7fffffff : var12);
        var14 = (step + 1);
        step = (unsigned long)((unsigned int)(var14));
    } while (((unsigned int)(arg2) != (unsigned int)(var14)));
    return (unsigned int)(var0);
}

← 213 fixtures