Fixture 66

orbital step

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

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

One symplectic-Euler gravitational step for a body orbiting a fixed mass. The inverse-square law needs a divide by a squared radius, so an incorrect intermediate width diverges immediately rather than subtly.

tests/decompiler_fixtures/src/66_orbital_step.c source
#include <stdint.h>

/* One symplectic-Euler gravitational step for a body orbiting a fixed mass.
 * The inverse-square law needs a divide by a squared radius, so an incorrect
 * intermediate width diverges immediately rather than subtly. */

#define ORBIT_STEPS_MAX 16

static int32_t orbit_mul_q16(int32_t left, int32_t right) {
    return (int32_t)(((int64_t)left * (int64_t)right) >> 16);
}

static int32_t orbit_div_q16(int32_t numerator, int32_t denominator) {
    if (denominator == 0) {
        return 0;
    }
    return (int32_t)(((int64_t)numerator << 16) / (int64_t)denominator);
}

__attribute__((noinline)) int32_t
orbital_step(int32_t *position_x, int32_t *position_y, int32_t *velocity_x,
             int32_t *velocity_y, int32_t mu, int32_t timestep, int32_t steps) {
    int32_t step;
    if (position_x == 0 || position_y == 0 || velocity_x == 0 ||
        velocity_y == 0 || steps < 0 || steps > ORBIT_STEPS_MAX ||
        timestep <= 0 || timestep > 65536 || mu <= 0) {
        return -1;
    }
    for (step = 0; step < steps; ++step) {
        int32_t rx = *position_x;
        int32_t ry = *position_y;
        int32_t radius_squared =
            orbit_mul_q16(rx, rx) + orbit_mul_q16(ry, ry);
        int32_t acceleration;
        if (radius_squared <= 0) {
            return -2;
        }
        acceleration = orbit_div_q16(mu, radius_squared);
        *velocity_x -= orbit_mul_q16(orbit_mul_q16(acceleration, rx), timestep);
        *velocity_y -= orbit_mul_q16(orbit_mul_q16(acceleration, ry), timestep);
        *position_x += orbit_mul_q16(*velocity_x, timestep);
        *position_y += orbit_mul_q16(*velocity_y, timestep);
    }
    return steps;
}

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
orbital_step pass 76 lines
// glaurung: orbital_step @ 0x1100
int32_t orbital_step(int32_t * arg0, int32_t * arg1, int32_t * arg2, int32_t * arg3, int32_t arg4, int32_t arg5, int32_t arg6) {
    extern int orbit_div_q16(int, int);
    extern int orbit_mul_q16(int, int);
    int step;
    int rx;
    int ry;
    int radius_squared;
    int acceleration;
    int local_4;
    int local_48;
    int var10;
    int var16;
    int var18;
    int var20;
    int var27;
    int var29;
    int var37;
    int var44;
    int var8;
    if ((arg0 != 0)) {
        if ((arg1 != 0)) {
            if ((arg2 != 0)) {
                if ((arg3 != 0)) {
                    if ((0 <= (long)(arg6))) {
                        if (((((unsigned long)((unsigned int)(arg6)) == 16) | ((long)(arg6) < 16)) != 0)) {
                            if (((((unsigned long)((unsigned int)(arg5)) == 0) | ((long)(arg5) < 0)) == 0)) {
                                if (((((unsigned long)((unsigned int)(arg5)) == 0x10000) | ((long)(arg5) < 0x10000)) != 0)) {
                                    if (((((unsigned long)((unsigned int)(arg4)) == 0) | ((long)(arg4) < 0)) == 0)) {
                                        goto L_1190;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    local_4 = -1;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
    L_1190: ;
    step = 0;
    L_1197: ;
    if ((step < arg6)) {
        rx = *(int *)((long)arg0);
        ry = *(int *)((long)arg1);
        var8 = orbit_mul_q16((unsigned long)((unsigned int)(rx)), (unsigned long)((unsigned int)(rx)));
        local_48 = var8;
        var10 = orbit_mul_q16((unsigned long)((unsigned int)(ry)), (unsigned long)((unsigned int)(ry)));
        radius_squared = ((unsigned int)(local_48) + (unsigned int)(var10));
        if (((((unsigned long)((unsigned int)(radius_squared)) == 0) | ((long)(radius_squared) < 0)) != 0)) {
            local_4 = -2;
            // x86-64 epilogue: restore rbp
            return (unsigned int)(local_4);
        }
        var16 = orbit_div_q16((unsigned long)((unsigned int)(arg4)), (unsigned long)((unsigned int)(radius_squared)));
        acceleration = var16;
        var18 = orbit_mul_q16((unsigned long)((unsigned int)(acceleration)), (unsigned long)((unsigned int)(rx)));
        var20 = orbit_mul_q16((unsigned long)((unsigned int)(var18)), (unsigned long)((unsigned int)(arg5)));
        *(int *)((long)arg2) = ((unsigned long)((unsigned int)(*(int *)((long)arg2))) - (unsigned long)((unsigned int)(var20)));
        var27 = orbit_mul_q16((unsigned long)((unsigned int)(acceleration)), (unsigned long)((unsigned int)(ry)));
        var29 = orbit_mul_q16((unsigned long)((unsigned int)(var27)), (unsigned long)((unsigned int)(arg5)));
        *(int *)((long)arg3) = ((unsigned long)((unsigned int)(*(int *)((long)arg3))) - (unsigned long)((unsigned int)(var29)));
        var37 = orbit_mul_q16((unsigned long)((unsigned int)(*(int *)((long)arg2))), (unsigned long)((unsigned int)(arg5)));
        *(int *)((long)arg0) = ((unsigned long)((unsigned int)(var37)) + *(int *)((long)arg0));
        var44 = orbit_mul_q16((unsigned long)((unsigned int)(*(int *)((long)arg3))), (unsigned long)((unsigned int)(arg5)));
        *(int *)((long)arg1) = ((unsigned long)((unsigned int)(var44)) + *(int *)((long)arg1));
        step = ((unsigned int)(step) + 1);
        goto L_1197;
    }
    local_4 = arg6;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}

clang -O2

1/1
orbital_step pass 97 lines
// glaurung: orbital_step @ 0x1100
int32_t orbital_step(int32_t * arg0, int32_t * arg1, int32_t * arg2, int32_t * arg3, int32_t arg4, int32_t arg5, int32_t arg6) {
    int ry;
    int radius_squared;
    int step;
    long ret;
    long t182;
    int * var0;
    long var16;
    long var19;
    long var2;
    long var25;
    int var36;
    int var38;
    long var4;
    long var41;
    long var44;
    int var45;
    long var46;
    long var5;
    long var7;
    long var8;
    ret = 0xffffffff;
    if ((((unsigned long)((unsigned int)(arg4)) == 0) | ((long)(arg4) < 0))) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    var0 = (int *)arg2;
    if (((unsigned long)((unsigned long)((unsigned int)((arg5 - 0x10001)))) < (unsigned long)(0xffff0000))) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    if ((arg0 == 0)) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    if ((arg1 == 0)) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    if ((var0 == 0)) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    if ((arg3 == 0)) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    var2 = (unsigned long)((unsigned int)(arg6));
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg6))))) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    if (((unsigned long)((unsigned int)(var2)) == 0)) {
        // x86-64 epilogue: tear down frame
        return 0;
    }
    var4 = ((unsigned long)((unsigned int)(arg4)) << 16);
    var5 = (unsigned long)((unsigned int)(arg5));
    var7 = 0xffff00000000;
    var8 = (unsigned long)((unsigned int)(var2));
    ry = (unsigned long)((unsigned int)(*(int *)(((long)arg1))));
    goto L_11e7;
    L_1190: ;
    var16 = ((unsigned long)(((((unsigned __int128)(unsigned long)((unsigned long)((unsigned int)(0))) << 64) | (unsigned long)(var4)) / (unsigned long)(radius_squared))));
    L_1198: ;
    *(int *)((var0)) = (*(int *)((var0)) - ((unsigned long)(((long)((int)(((unsigned long)((var19 * (long)((int)(var16)))) >> 16))) * var5)) >> 16));
    *(int *)(((long)arg3)) = (*(int *)(((long)arg3)) - ((unsigned long)(((long)((int)(((unsigned long)((var25 * (long)((int)(var16)))) >> 16))) * var5)) >> 16));
    *(int *)(((long)arg0)) = (*(int *)(((long)arg0)) + ((unsigned long)(((long)((int)(*(int *)((var0)))) * var5)) >> 16));
    var36 = (((unsigned long)(((long)((int)(*(int *)(((long)arg3)))) * var5)) >> 16) + *(int *)(((long)arg1)));
    *(int *)(((long)arg1)) = var36;
    var38 = (var8 - 1);
    var8 = (unsigned long)((unsigned int)(var38));
    ry = (unsigned long)((unsigned int)(var36));
    if (((unsigned long)((unsigned int)(var38)) == 0)) {
        // x86-64 epilogue: tear down frame
        return (unsigned int)(var2);
    }
    L_11e7: ;
    var19 = (long)((int)(*(int *)(((long)arg0))));
    var41 = ((unsigned long)((var19 * var19)) >> 16);
    var25 = (long)(ry);
    var44 = ((unsigned long)(((long)(ry) * (long)(ry))) >> 16);
    t182 = ((long)((int)(var44)) < 0);
    var45 = (var44 + var41);
    var46 = (unsigned long)((unsigned int)(var45));
    if ((((unsigned long)((unsigned int)(var45)) == 0) | (((long)((int)(var45)) < 0) ^ ((t182 == ((long)((int)(var41)) < 0)) & (((long)((int)(var45)) < 0) != t182))))) {
        // x86-64 epilogue: tear down frame
        return 0xfffffffe;
    }
    radius_squared = (unsigned long)((unsigned int)(var46));
    if (((var4 & var7) != 0)) {
        goto L_1190;
    }
    var16 = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)((unsigned long)((unsigned int)(var4)))) / (unsigned int)(radius_squared))));
    goto L_1198;
}

gcc -O0

1/1
orbital_step pass 74 lines
// glaurung: orbital_step @ 0x114d
int32_t orbital_step(int32_t * arg0, int32_t * arg1, int32_t * arg2, int32_t * arg3, int32_t arg4, int32_t arg5, int32_t arg6) {
    extern int orbit_div_q16(int, int);
    extern int orbit_mul_q16(int, int);
    int step;
    int rx;
    int ry;
    int radius_squared;
    int acceleration;
    int var12;
    int var18;
    int var22;
    int var26;
    int var37;
    int var41;
    int var53;
    int var64;
    int var7;
    long var9;
    if ((arg0 != 0)) {
        if ((arg1 != 0)) {
            if ((arg2 != 0)) {
                if ((arg3 != 0)) {
                    if ((0 <= (long)(arg6))) {
                        if (((((unsigned long)((unsigned int)(arg6)) == 16) | ((long)(arg6) < 16)) != 0)) {
                            if (((((unsigned long)((unsigned int)(arg5)) == 0) | ((long)(arg5) < 0)) == 0)) {
                                if (((((unsigned long)((unsigned int)(arg5)) == 0x10000) | ((long)(arg5) < 0x10000)) != 0)) {
                                    if (((((unsigned long)((unsigned int)(arg4)) == 0) | ((long)(arg4) < 0)) == 0)) {
                                        goto L_11b9;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    // x86-64 epilogue: restore rbp
    return 0xffffffff;
    L_11b9: ;
    step = 0;
    goto L_12c4;
    L_11c5: ;
    rx = *(int *)((long)arg0);
    ry = *(int *)((long)arg1);
    var7 = orbit_mul_q16((unsigned long)((unsigned int)(rx)), (unsigned long)((unsigned int)(rx)));
    var9 = (unsigned long)((unsigned int)(var7));
    var12 = orbit_mul_q16((unsigned long)((unsigned int)(ry)), (unsigned long)((unsigned int)(ry)));
    radius_squared = (var12 + var9);
    if (((((unsigned long)((unsigned int)(radius_squared)) == 0) | ((long)(radius_squared) < 0)) != 0)) {
        // x86-64 epilogue: restore rbp
        return 0xfffffffe;
    }
    var18 = orbit_div_q16((unsigned long)((unsigned int)(arg4)), (unsigned long)((unsigned int)(radius_squared)));
    acceleration = var18;
    var22 = orbit_mul_q16((unsigned long)((unsigned int)(acceleration)), (unsigned long)((unsigned int)(rx)));
    var26 = orbit_mul_q16((unsigned long)((unsigned int)(var22)), (unsigned long)((unsigned int)(arg5)));
    *(int *)((long)arg2) = ((unsigned long)((unsigned int)(*(int *)((long)arg2))) - (unsigned long)((unsigned int)(var26)));
    var37 = orbit_mul_q16((unsigned long)((unsigned int)(acceleration)), (unsigned long)((unsigned int)(ry)));
    var41 = orbit_mul_q16((unsigned long)((unsigned int)(var37)), (unsigned long)((unsigned int)(arg5)));
    *(int *)((long)arg3) = ((unsigned long)((unsigned int)(*(int *)((long)arg3))) - (unsigned long)((unsigned int)(var41)));
    var53 = orbit_mul_q16((unsigned long)((unsigned int)(*(int *)((long)arg2))), (unsigned long)((unsigned int)(arg5)));
    *(int *)((long)arg0) = ((unsigned long)((unsigned int)(var53)) + (unsigned long)((unsigned int)(*(int *)((long)arg0))));
    var64 = orbit_mul_q16((unsigned long)((unsigned int)(*(int *)((long)arg3))), (unsigned long)((unsigned int)(arg5)));
    *(int *)((long)arg1) = ((unsigned long)((unsigned int)(var64)) + (unsigned long)((unsigned int)(*(int *)((long)arg1))));
    step = (step + 1);
    L_12c4: ;
    if ((step < arg6)) {
        goto L_11c5;
    }
    // x86-64 epilogue: restore rbp
    return (unsigned int)(arg6);
}

gcc -O2

1/1
orbital_step pass 92 lines
// glaurung: orbital_step @ 0x1100
int32_t orbital_step(int32_t * arg0, int32_t * arg1, int32_t * arg2, int32_t * arg3, int32_t arg4, int32_t arg5, int32_t arg6) {
    int radius_squared;
    int step;
    long local_10;
    long local_20;
    long local_8;
    long var0;
    long var1;
    int * var10;
    int * var11;
    long var18;
    long var2;
    long var21;
    long var22;
    long var23;
    long var24;
    long var25;
    long var3;
    int var32;
    int var36;
    long var41;
    int var58;
    int * var9;
    local_8 = var0;
    local_10 = var1;
    local_20 = var2;
    var3 = (unsigned long)((unsigned int)(arg6));
    if ((arg0 == 0)) {
        // x86-64 epilogue: tear down frame
        return 0xffffffff;
    }
    var9 = (int *)arg1;
    if ((arg1 == 0)) {
        // x86-64 epilogue: tear down frame
        return 0xffffffff;
    }
    var10 = (int *)arg2;
    if ((arg2 == 0)) {
        // x86-64 epilogue: tear down frame
        return 0xffffffff;
    }
    var11 = (int *)arg3;
    if ((arg3 == 0)) {
        // x86-64 epilogue: tear down frame
        return 0xffffffff;
    }
    if (((unsigned long)(0xffff) < (unsigned long)((unsigned long)((unsigned int)((arg5 - 1)))))) {
        // x86-64 epilogue: tear down frame
        return 0xffffffff;
    }
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(var3))))) {
        // x86-64 epilogue: tear down frame
        return 0xffffffff;
    }
    if ((((unsigned long)((unsigned int)(arg4)) == 0) | ((long)(arg4) < 0))) {
        // x86-64 epilogue: tear down frame
        return 0xffffffff;
    }
    if (((unsigned long)((unsigned int)(var3)) == 0)) {
        // x86-64 epilogue: tear down frame
        return (unsigned int)(var3);
    }
    var18 = (unsigned long)((unsigned int)(*(int *)(((long)arg1))));
    var21 = (long)(arg5);
    var22 = ((long)(arg4) << 16);
    var23 = 0;
    while (1) {
        var24 = (long)((int)(*(int *)(((long)arg0))));
        var25 = (long)((int)(var18));
        var32 = (((long)(((long)((int)(var18)) * (long)((int)(var18)))) >> 16) + ((long)((var24 * var24)) >> 16));
        radius_squared = (unsigned long)((unsigned int)(var32));
        if (((((unsigned long)((unsigned int)(var32)) == 0) | ((long)((int)(var32)) < 0)) != 0)) {
            break;
        }
        var36 = (var23 + 1);
        var41 = (long)((int)(((long)((((__int128)(long)(((long)(var22) >> 63)) * (((__int128)1) << 64)) + (unsigned long)(var22)) / (long)((long)(radius_squared))))));
        *(int *)((var10)) = (*(int *)((var10)) - ((long)(((long)((int)(((long)((var24 * var41)) >> 16))) * var21)) >> 16));
        *(int *)((var11)) = (*(int *)((var11)) - ((long)(((long)((int)(((long)((var25 * var41)) >> 16))) * var21)) >> 16));
        *(int *)(((long)arg0)) = (*(int *)(((long)arg0)) + ((long)(((long)((int)(*(int *)((var10)))) * var21)) >> 16));
        var58 = (((long)(((long)((int)(*(int *)((var11)))) * var21)) >> 16) + *(int *)((var9)));
        var18 = (unsigned long)((unsigned int)(var58));
        *(int *)((var9)) = var58;
        var23 = (unsigned long)((unsigned int)(var36));
        if (((unsigned int)(var3) == (unsigned int)(var36))) {
            // x86-64 epilogue: tear down frame
            return (unsigned int)(var3);
        }
    }
    // x86-64 epilogue: tear down frame
    return 0xfffffffe;
}

← 213 fixtures