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.
#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/1orbital_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/1orbital_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/1orbital_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/1orbital_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;
}