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