Fixture 68
thermodynamics
C · 3 functions · 4 lanes · 12 of 12 function-lanes behave identically
All 4 lanes recompile and return the same results as the original.
Ideal-gas pressure, Newton's law of cooling over discrete steps, and a mixing temperature. The cooling loop is a geometric decay whose factor is recomputed each step from two parameters.
#include <stdint.h>
/* Ideal-gas pressure, Newton's law of cooling over discrete steps, and a
* mixing temperature. The cooling loop is a geometric decay whose factor is
* recomputed each step from two parameters. */
#define THERMO_STEPS_MAX 24
static int32_t thermo_mul_q16(int32_t left, int32_t right) {
return (int32_t)(((int64_t)left * (int64_t)right) >> 16);
}
static int32_t thermo_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
ideal_gas_pressure(int32_t moles, int32_t temperature, int32_t volume) {
int32_t gas_constant = 544807; /* 8.314 in Q16.16 */
int32_t numerator;
if (volume <= 0 || moles < 0 || temperature < 0) {
return 0;
}
numerator = thermo_mul_q16(thermo_mul_q16(moles, gas_constant), temperature);
return thermo_div_q16(numerator, volume);
}
__attribute__((noinline)) int32_t
newton_cooling(int32_t temperature, int32_t ambient, int32_t rate,
int32_t steps) {
int32_t step;
if (steps < 0 || steps > THERMO_STEPS_MAX || rate < 0 || rate > 65536) {
return temperature;
}
for (step = 0; step < steps; ++step) {
int32_t difference = temperature - ambient;
temperature -= thermo_mul_q16(rate, difference);
}
return temperature;
}
__attribute__((noinline)) int32_t
mixing_temperature(int32_t mass_a, int32_t temperature_a, int32_t mass_b,
int32_t temperature_b) {
int32_t total = mass_a + mass_b;
int32_t weighted;
if (mass_a < 0 || mass_b < 0 || total <= 0) {
return 0;
}
weighted = thermo_mul_q16(mass_a, temperature_a) +
thermo_mul_q16(mass_b, temperature_b);
return thermo_div_q16(weighted, total);
} 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
3/3ideal_gas_pressure pass 32 lines
// glaurung: ideal_gas_pressure @ 0x1100
int32_t ideal_gas_pressure(int32_t arg0, int32_t arg1, int32_t arg2) {
extern int thermo_div_q16(int, int);
extern int thermo_mul_q16(int, int);
int gas_constant;
int numerator;
int local_4;
int var0;
int var2;
int var4;
// x86-64 prologue: save rbp, frame 32 bytes
gas_constant = 0x85027;
if ((((unsigned long)((unsigned int)(arg2)) == 0) | ((long)(arg2) < 0))) {
// x86-64 epilogue: restore rbp
return 0;
}
if (((long)(arg0) < 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
if (((long)(arg1) < 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
var0 = thermo_mul_q16((unsigned long)((unsigned int)(arg0)), (unsigned long)((unsigned int)(gas_constant)));
var2 = thermo_mul_q16((unsigned long)((unsigned int)(var0)), (unsigned long)((unsigned int)(arg1)));
numerator = var2;
var4 = thermo_div_q16((unsigned long)((unsigned int)(numerator)), (unsigned long)((unsigned int)(arg2)));
local_4 = var4;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} mixing_temperature pass 34 lines
// glaurung: mixing_temperature @ 0x1280
int32_t mixing_temperature(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
extern int thermo_div_q16(int, int);
extern int thermo_mul_q16(int, int);
int total;
int weighted;
int local_20;
int local_4;
int var11;
int var3;
int var5;
// x86-64 prologue: save rbp, frame 32 bytes
total = ((unsigned int)(arg0) + arg2);
if (((long)(arg0) < 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
if (((long)(arg2) < 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
if (((((unsigned long)((unsigned int)(total)) == 0) | ((long)(total) < 0)) != 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
var3 = thermo_mul_q16((unsigned long)((unsigned int)(arg0)), (unsigned long)((unsigned int)(arg1)));
local_20 = var3;
var5 = thermo_mul_q16((unsigned long)((unsigned int)(arg2)), (unsigned long)((unsigned int)(arg3)));
weighted = ((unsigned int)(local_20) + (unsigned int)(var5));
var11 = thermo_div_q16((unsigned long)((unsigned int)(weighted)), (unsigned long)((unsigned int)(total)));
local_4 = var11;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} newton_cooling pass 37 lines
// glaurung: newton_cooling @ 0x11e0
int32_t newton_cooling(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
extern int thermo_mul_q16(int, int);
int step;
int difference;
int local_4;
int var6;
// x86-64 prologue: save rbp, frame 32 bytes
if (((long)(arg3) < 0)) {
local_4 = arg0;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((((unsigned long)((unsigned int)(arg3)) == 24) | ((long)(arg3) < 24)) == 0)) {
local_4 = arg0;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((long)(arg2) < 0)) {
local_4 = arg0;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((((unsigned long)((unsigned int)(arg2)) == 0x10000) | ((long)(arg2) < 0x10000)) == 0)) {
local_4 = arg0;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
for (step = 0; (step < arg3); step++) {
difference = ((unsigned int)(arg0) - arg1);
var6 = thermo_mul_q16((unsigned long)((unsigned int)(arg2)), (unsigned long)((unsigned int)(difference)));
arg0 = ((unsigned int)(arg0) - (unsigned int)(var6));
}
local_4 = arg0;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} clang -O2
3/3ideal_gas_pressure pass 21 lines
// glaurung: ideal_gas_pressure @ 0x1100
int32_t ideal_gas_pressure(int32_t arg0, int32_t arg1, int32_t arg2) {
long ret;
long var11;
long var13;
long var14;
ret = 0;
if (((long)((int)(((unsigned long)((unsigned int)(arg1)) | arg0))) < 0)) {
return ret;
}
if ((((unsigned long)((unsigned int)(arg2)) == 0) | ((long)(arg2) < 0))) {
return ret;
}
var11 = ((long)((((long)(arg1) * ((long)((0x850270000 * (long)(arg0))) >> 32)) << 16)) >> 16);
var13 = (var11 & -0x10000LL);
var14 = (unsigned long)((unsigned int)(arg2));
if ((((unsigned long)(var11) >> 32) == 0)) {
return ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)(var13)) / (unsigned int)(var14))));
}
return ((long)((((__int128)(long)(((long)(var13) >> 63)) * (((__int128)1) << 64)) + (unsigned long)(var13)) / (long)((unsigned long)((unsigned int)(arg2)))));
} mixing_temperature pass 22 lines
// glaurung: mixing_temperature @ 0x11f0
int32_t mixing_temperature(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
int total;
long ret;
long var16;
long var17;
long var4;
ret = 0;
if (((long)((int)(((unsigned long)((unsigned int)(arg2)) | arg0))) < 0)) {
return ret;
}
var4 = (unsigned long)((unsigned int)((arg2 + arg0)));
if ((((unsigned long)((unsigned int)(var4)) == 0) | ((long)((int)(var4)) < 0))) {
return ret;
}
var16 = ((long)((int)((((unsigned long)(((long)(arg3) * (long)(arg2))) >> 16) + ((unsigned long)(((long)(arg1) * (long)(arg0))) >> 16)))) << 16);
var17 = (unsigned long)((unsigned int)(var4));
if ((((unsigned long)(var16) >> 32) == 0)) {
return ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)(var16)) / (unsigned int)(var17))));
}
return ((long)((((__int128)(long)(((long)(var16) >> 63)) * (((__int128)1) << 64)) + (unsigned long)(var16)) / (long)((unsigned long)((unsigned int)(var4)))));
} newton_cooling pass 49 lines
// glaurung: newton_cooling @ 0x1150
int32_t newton_cooling(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
int difference;
int step;
long ret;
long var0;
long var1;
long var15;
long var23;
long var31;
int var39;
long var4;
int var47;
long var5;
long var7;
ret = (unsigned long)((unsigned int)(arg0));
var0 = (unsigned long)((unsigned int)((arg3 - 1)));
if (((unsigned long)((unsigned long)((unsigned int)(var0))) <= (unsigned long)(23))) {
if (((unsigned long)(0x10000) < (unsigned long)((unsigned long)((unsigned int)(arg2))))) {
return ret;
}
var1 = (unsigned long)((unsigned int)(arg2));
var4 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg3)) & 3)));
var5 = (unsigned long)((unsigned int)(arg0));
if (((unsigned long)(3) <= (unsigned long)((unsigned long)((unsigned int)(var0))))) {
var7 = (unsigned long)((unsigned int)((arg3 & -4)));
do {
var15 = (unsigned long)((unsigned int)((ret - ((unsigned long)(((long)((int)(((unsigned long)((unsigned int)(ret)) - arg1))) * var1)) >> 16))));
var23 = (unsigned long)((unsigned int)((var15 - ((unsigned long)(((long)((int)(((unsigned long)((unsigned int)(var15)) - arg1))) * var1)) >> 16))));
var31 = (unsigned long)((unsigned int)((var23 - ((unsigned long)(((long)((int)(((unsigned long)((unsigned int)(var23)) - arg1))) * var1)) >> 16))));
ret = (unsigned long)((unsigned int)((var31 - ((unsigned long)(((long)((int)(((unsigned long)((unsigned int)(var31)) - arg1))) * var1)) >> 16))));
var39 = (var7 - 4);
var7 = (unsigned long)((unsigned int)(var39));
var5 = ret;
} while (((unsigned long)((unsigned int)(var39)) != 0));
}
ret = var5;
if (((unsigned long)((unsigned int)(var4)) == 0)) {
return ret;
}
do {
var5 = (unsigned long)((unsigned int)((var5 - ((unsigned long)(((long)((int)(((unsigned long)((unsigned int)(var5)) - arg1))) * var1)) >> 16))));
var47 = (var4 - 1);
var4 = (unsigned long)((unsigned int)(var47));
ret = var5;
} while (((unsigned long)((unsigned int)(var47)) != 0));
}
return ret;
} gcc -O0
3/3ideal_gas_pressure pass 30 lines
// glaurung: ideal_gas_pressure @ 0x114d
int32_t ideal_gas_pressure(int32_t arg0, int32_t arg1, int32_t arg2) {
extern int thermo_div_q16(int, int);
extern int thermo_mul_q16(int, int);
int gas_constant;
int numerator;
int ret;
int var2;
int var6;
// x86-64 prologue: save rbp, frame 32 bytes
gas_constant = 0x85027;
if ((((unsigned long)((unsigned int)(arg2)) == 0) | ((long)(arg2) < 0))) {
// x86-64 epilogue: restore rbp
return 0;
}
if (((long)(arg0) < 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
if (((long)(arg1) < 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
var2 = thermo_mul_q16((unsigned long)((unsigned int)(arg0)), (unsigned long)((unsigned int)(gas_constant)));
var6 = thermo_mul_q16((unsigned long)((unsigned int)(var2)), (unsigned long)((unsigned int)(arg1)));
numerator = var6;
ret = thermo_div_q16((unsigned long)((unsigned int)(numerator)), (unsigned long)((unsigned int)(arg2)));
// x86-64 epilogue: restore rbp
return ret;
} mixing_temperature pass 32 lines
// glaurung: mixing_temperature @ 0x1220
int32_t mixing_temperature(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
extern int thermo_div_q16(int, int);
extern int thermo_mul_q16(int, int);
int total;
int weighted;
int ret;
int var12;
int var7;
long var9;
// x86-64 prologue: save rbp, frame 8 bytes
total = ((unsigned int)(arg2) + (unsigned int)(arg0));
if (((long)(arg0) < 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
if (((long)(arg2) < 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
if (((((unsigned long)((unsigned int)(total)) == 0) | ((long)(total) < 0)) != 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
var7 = thermo_mul_q16((unsigned long)((unsigned int)(arg0)), (unsigned long)((unsigned int)(arg1)));
var9 = (unsigned long)((unsigned int)(var7));
var12 = thermo_mul_q16((unsigned long)((unsigned int)(arg2)), (unsigned long)((unsigned int)(arg3)));
weighted = (var12 + var9);
ret = thermo_div_q16((unsigned long)((unsigned int)(weighted)), (unsigned long)((unsigned int)(total)));
// x86-64 epilogue: restore rbp
return ret;
} newton_cooling pass 31 lines
// glaurung: newton_cooling @ 0x11b3
int32_t newton_cooling(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
extern int thermo_mul_q16(int, int);
int step;
int difference;
int var6;
// x86-64 prologue: save rbp, frame 32 bytes
if (((long)(arg3) < 0)) {
// x86-64 epilogue: restore rbp
return (unsigned int)(arg0);
}
if (((((unsigned long)((unsigned int)(arg3)) == 24) | ((long)(arg3) < 24)) == 0)) {
// x86-64 epilogue: restore rbp
return (unsigned int)(arg0);
}
if (((long)(arg2) < 0)) {
// x86-64 epilogue: restore rbp
return (unsigned int)(arg0);
}
if (((((unsigned long)((unsigned int)(arg2)) == 0x10000) | ((long)(arg2) < 0x10000)) == 0)) {
// x86-64 epilogue: restore rbp
return (unsigned int)(arg0);
}
for (step = 0; (step < arg3); step++) {
difference = ((unsigned int)(arg0) - arg1);
var6 = thermo_mul_q16((unsigned long)((unsigned int)(arg2)), (unsigned long)((unsigned int)(difference)));
arg0 = (arg0 - var6);
}
// x86-64 epilogue: restore rbp
return (unsigned int)(arg0);
} gcc -O2
3/3ideal_gas_pressure pass 11 lines
// glaurung: ideal_gas_pressure @ 0x1100
int32_t ideal_gas_pressure(int32_t arg0, int32_t arg1, int32_t arg2) {
long var13;
if ((0 <= (long)((int)(((unsigned long)((unsigned int)(arg0)) | arg1))))) {
if (((((unsigned long)((unsigned int)(arg2)) == 0) | ((long)(arg2) < 0)) == 0)) {
var13 = ((long)((int)(((long)(((long)((int)(((long)(((long)(arg0) * 0x85027)) >> 16))) * (long)(arg1))) >> 16))) << 16);
return ((long)((((__int128)(long)(((long)(var13) >> 63)) * (((__int128)1) << 64)) + (unsigned long)(var13)) / (long)((long)(arg2))));
}
}
return 0;
} mixing_temperature pass 13 lines
// glaurung: mixing_temperature @ 0x11a0
int32_t mixing_temperature(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
int total;
long var17;
total = (unsigned long)((unsigned int)((arg0 + arg2)));
if ((0 <= (long)((int)(((unsigned long)((unsigned int)(arg0)) | arg2))))) {
if (((((unsigned long)((unsigned int)(total)) == 0) | ((long)(total) < 0)) == 0)) {
var17 = ((long)((int)((((long)(((long)(arg2) * (long)(arg3))) >> 16) + ((long)(((long)(arg0) * (long)(arg1))) >> 16)))) << 16);
return ((long)((((__int128)(long)(((long)(var17) >> 63)) * (((__int128)1) << 64)) + (unsigned long)(var17)) / (long)((long)(total))));
}
}
return 0;
} newton_cooling pass 22 lines
// glaurung: newton_cooling @ 0x1150
int32_t newton_cooling(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
int step;
int difference;
long var0;
long var2;
int var7;
var0 = (unsigned long)((unsigned int)(arg0));
if (((unsigned long)((unsigned long)((unsigned int)(arg2))) <= (unsigned long)(0x10000))) {
if (((unsigned long)(23) < (unsigned long)((unsigned long)((unsigned int)((arg3 - 1)))))) {
return (unsigned int)(var0);
}
var2 = (long)(arg2);
step = 0;
do {
var7 = (step + 1);
step = (unsigned long)((unsigned int)(var7));
var0 = (unsigned long)((unsigned int)((var0 - ((long)(((long)((int)(((unsigned long)((unsigned int)(var0)) - arg1))) * var2)) >> 16))));
} while (((unsigned int)(arg3) != (unsigned int)(var7)));
}
return (unsigned int)(var0);
}