Fixture 73
present value
C · 2 functions · 4 lanes · 8 of 8 function-lanes behave identically
All 4 lanes recompile and return the same results as the original.
Net present value of a cash-flow series and an internal rate of return found by bisection on that NPV. The discount factor is recomputed by repeated division, so the inner loop is nested inside the search loop.
#include <stdint.h>
/* Net present value of a cash-flow series and an internal rate of return
* found by bisection on that NPV. The discount factor is recomputed by
* repeated division, so the inner loop is nested inside the search loop. */
#define CASHFLOW_MAX 12
#define IRR_ITERATIONS 32
static int32_t pv_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
net_present_value(const int32_t *cashflows, int32_t count, int32_t rate) {
int32_t total = 0;
int32_t discount = 65536;
int32_t index;
if (cashflows == 0 || count < 0 || count > CASHFLOW_MAX || rate < 0 ||
rate > 65536) {
return 0;
}
for (index = 0; index < count; ++index) {
total += pv_div_q16(cashflows[index], discount) * 1;
discount = (int32_t)(((int64_t)discount * (int64_t)(65536 + rate)) >> 16);
if (discount <= 0) {
return total;
}
}
return total;
}
__attribute__((noinline)) int32_t
internal_rate_of_return(const int32_t *cashflows, int32_t count) {
int32_t low = 0;
int32_t high = 65536;
int32_t iteration;
if (cashflows == 0 || count < 1 || count > CASHFLOW_MAX) {
return -1;
}
for (iteration = 0; iteration < IRR_ITERATIONS; ++iteration) {
int32_t middle = low + (high - low) / 2;
int32_t value = net_present_value(cashflows, count, middle);
if (value == 0) {
return middle;
}
if (value > 0) {
low = middle;
} else {
high = middle;
}
}
return low + (high - low) / 2;
} 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
2/2internal_rate_of_return pass 59 lines
// glaurung: internal_rate_of_return @ 0x1240
int32_t internal_rate_of_return(const int32_t * arg0, int32_t arg1) {
extern int net_present_value(int *, int, int);
int low;
int high;
int iteration;
int middle;
int value;
int local_2c;
int local_30;
int local_4;
int var12;
long var23;
long var3;
low = 0;
high = 0x10000;
if ((arg0 != 0)) {
if ((1 <= (long)(arg1))) {
if ((((unsigned long)((unsigned int)(arg1)) == 12) | ((long)(arg1) < 12))) {
goto L_1288;
}
}
}
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
L_1288: ;
iteration = 0;
L_128f: ;
if ((32 <= (long)(iteration))) {
goto L_130c;
}
local_2c = low;
var3 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(high)) - low)));
middle = ((unsigned int)(local_2c) + (unsigned int)(((int)((((long long)(int)((((unsigned long)((long)((int)(var3))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)(var3)) / (int)(2)))));
var12 = net_present_value((int *)(arg0), (unsigned long)((unsigned int)(arg1)), (unsigned long)((unsigned int)(middle)));
value = var12;
if (((unsigned long)((unsigned int)(value)) == 0)) {
local_4 = middle;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((((unsigned long)((unsigned int)(value)) == 0) | ((long)(value) < 0)) == 0)) {
low = middle;
goto L_12f9;
}
high = middle;
L_12f9: ;
goto L_12fe;
L_12fe: ;
iteration = ((unsigned int)(iteration) + 1);
goto L_128f;
L_130c: ;
local_30 = low;
var23 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(high)) - low)));
local_4 = ((unsigned int)(local_30) + (unsigned int)(((int)((((long long)(int)((((unsigned long)((long)((int)(var23))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)(var23)) / (int)(2)))));
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} net_present_value pass 47 lines
// glaurung: net_present_value @ 0x1110
int32_t net_present_value(const int32_t * arg0, int32_t arg1, int32_t arg2) {
extern int pv_div_q16(int, int);
int total;
int discount;
int index;
int local_4;
int var3;
total = 0;
discount = 0x10000;
if ((arg0 != 0)) {
if ((0 <= (long)(arg1))) {
if (((((unsigned long)((unsigned int)(arg1)) == 12) | ((long)(arg1) < 12)) != 0)) {
if ((0 <= (long)(arg2))) {
if ((((unsigned long)((unsigned int)(arg2)) == 0x10000) | ((long)(arg2) < 0x10000))) {
goto L_1172;
}
}
}
}
}
local_4 = 0;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
L_1172: ;
index = 0;
L_1179: ;
if ((arg1 <= index)) {
goto L_11e4;
}
var3 = pv_div_q16((unsigned long)((unsigned int)(arg0[(long)(index)])), (unsigned long)((unsigned int)(discount)));
total = ((unsigned int)(var3) + total);
discount = ((long)(((long)(discount) * (long)((int)(((unsigned long)((unsigned int)(arg2)) + 0x10000))))) >> 16);
if (((((unsigned long)((unsigned int)(discount)) == 0) | ((long)(discount) < 0)) != 0)) {
local_4 = total;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
goto L_11d6;
L_11d6: ;
index = ((unsigned int)(index) + 1);
goto L_1179;
L_11e4: ;
local_4 = total;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} clang -O2
2/2internal_rate_of_return pass 80 lines
// glaurung: internal_rate_of_return @ 0x11a0
int32_t internal_rate_of_return(const int32_t * arg0, int32_t arg1) {
extern int net_present_value(int *, int, int);
int middle;
int high;
int low;
int value;
long of_10;
long sf_10;
long var0;
long var11;
int var12;
long var13;
long var16;
long var2;
int var26;
int var27;
int var29;
long var31;
int * var4;
long var8;
long zf_10;
// x86-64 prologue: save callee registers, frame 56 bytes
var0 = 0xffffffff;
middle = 0xffffffff;
if ((arg0 == 0)) {
// x86-64 epilogue: restore callee registers
return (unsigned int)(middle);
}
var2 = (unsigned long)((unsigned int)(arg1));
middle = var0;
if (((unsigned long)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) - 13)))) < (unsigned long)(0xfffffff4))) {
// x86-64 epilogue: restore callee registers
return (unsigned int)(middle);
}
var4 = (int *)arg0;
var8 = 32;
high = 0x10000;
low = 0;
goto L_11e8;
L_11e0: ;
var11 = (unsigned long)((unsigned int)(middle));
var12 = (var8 - 1);
var8 = (unsigned long)((unsigned int)(var12));
high = (unsigned long)((unsigned int)(middle));
var13 = (unsigned long)((unsigned int)(low));
if (((unsigned long)((unsigned int)(var12)) == 0)) {
var31 = (unsigned long)((unsigned int)((var11 - var13)));
middle = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var31)) >> 31))) + var31)) >> 1))) + var13)));
// x86-64 epilogue: restore callee registers
return (unsigned int)(middle);
}
L_11e8: ;
var16 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(high)) - low)));
var26 = ((unsigned int)(((int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var16)) >> 31))) + var16)) >> 1)) + low);
middle = (unsigned long)((unsigned int)(var26));
var27 = net_present_value(var4, (unsigned long)((unsigned int)(var2)), (unsigned long)((unsigned int)(var26)));
zf_10 = ((unsigned long)((unsigned int)(var27)) == 0);
sf_10 = ((long)((int)(var27)) < 0);
of_10 = 0;
if (((unsigned long)((unsigned int)(var27)) == 0)) {
// x86-64 epilogue: restore callee registers
return (unsigned int)(middle);
}
if ((zf_10 | (sf_10 ^ of_10))) {
goto L_11e0;
}
var13 = (unsigned long)((unsigned int)(middle));
var29 = (var8 - 1);
var8 = (unsigned long)((unsigned int)(var29));
low = (unsigned long)((unsigned int)(middle));
var11 = (unsigned long)((unsigned int)(high));
if (((unsigned long)((unsigned int)(var29)) != 0)) {
goto L_11e8;
}
var31 = (unsigned long)((unsigned int)((var11 - var13)));
middle = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var31)) >> 31))) + var31)) >> 1))) + var13)));
// x86-64 epilogue: restore callee registers
return (unsigned int)(middle);
} net_present_value pass 60 lines
// glaurung: net_present_value @ 0x1110
int32_t net_present_value(const int32_t * arg0, int32_t arg1, int32_t arg2) {
int index;
int discount;
int total;
long cf_19;
long var11;
long var14;
long var15;
long var2;
long var21;
int var26;
long var5;
long var6;
long var9;
var2 = 0;
if (((unsigned long)(0x10000) < (unsigned long)((unsigned long)((unsigned int)(arg2))))) {
return (unsigned int)(var2);
}
var2 = 0;
if ((arg0 == 0)) {
return (unsigned int)(var2);
}
var2 = 0;
if (((unsigned long)(12) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
return (unsigned int)(var2);
}
var2 = 0;
if ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0))) {
return (unsigned int)(var2);
}
var5 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg2)) + 0x10000)));
var6 = (unsigned long)((unsigned int)(arg1));
var9 = 0x10000;
var11 = 0;
index = 1;
L_1150: ;
var14 = ((long)((int)(*(int *)(((long)arg0 + index * 4 - 0x4)))) << 16);
var15 = (unsigned long)((unsigned int)(var9));
if ((((unsigned long)(var14) >> 32) != 0)) {
var21 = ((long)((((__int128)(long)(((long)(var14) >> 63)) * (((__int128)1) << 64)) + (unsigned long)(var14)) / (long)(var15)));
goto L_1174;
}
var21 = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)(var14)) / (unsigned int)(var15))));
L_1174: ;
var26 = (var11 + var21);
var11 = (unsigned long)((unsigned int)(var26));
var9 = ((unsigned long)((var15 * var5)) >> 16);
var2 = (unsigned long)((unsigned int)(var26));
if ((((unsigned long)((unsigned int)(var9)) == 0) | ((long)((int)(var9)) < 0))) {
return (unsigned int)(var2);
}
cf_19 = ((unsigned long)(index) < (unsigned long)(var6));
index = (index + 1);
var2 = (unsigned long)((unsigned int)(var26));
if (cf_19) {
goto L_1150;
}
return (unsigned int)(var2);
} gcc -O0
2/2internal_rate_of_return pass 49 lines
// glaurung: internal_rate_of_return @ 0x11fc
int32_t internal_rate_of_return(const int32_t * arg0, int32_t arg1) {
extern int net_present_value(int *, int, int);
int low;
int high;
int iteration;
int middle;
int value;
int var18;
long var2;
long var24;
low = 0;
high = 0x10000;
if ((arg0 != 0)) {
if (((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0)) == 0)) {
if ((((unsigned long)((unsigned int)(arg1)) == 12) | ((long)(arg1) < 12))) {
goto L_1237;
}
}
}
// x86-64 epilogue: restore rbp
return 0xffffffff;
L_1237: ;
iteration = 0;
goto L_1293;
L_1240: ;
var2 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(high)) - low)));
middle = ((unsigned int)(low) + (unsigned int)(((int)((var2 + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var2)) >> 31))))) >> 1)));
var18 = net_present_value((int *)(arg0), (unsigned long)((unsigned int)(arg1)), (unsigned long)((unsigned int)(middle)));
value = var18;
if (((unsigned long)((unsigned int)(value)) == 0)) {
// x86-64 epilogue: restore rbp
return (unsigned int)(middle);
}
if (((((unsigned long)((unsigned int)(value)) == 0) | ((long)(value) < 0)) == 0)) {
low = middle;
goto L_128f;
}
high = middle;
L_128f: ;
iteration = (iteration + 1);
L_1293: ;
if ((((unsigned long)((unsigned int)(iteration)) == 31) | ((long)(iteration) < 31))) {
goto L_1240;
}
var24 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(high)) - low)));
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(low)) + (unsigned long)((unsigned int)(((int)((var24 + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var24)) >> 31))))) >> 1)))));
} net_present_value pass 41 lines
// glaurung: net_present_value @ 0x114a
int32_t net_present_value(const int32_t * arg0, int32_t arg1, int32_t arg2) {
extern int pv_div_q16(int, int);
int total;
int discount;
int index;
int var7;
total = 0;
discount = 0x10000;
if ((arg0 != 0)) {
if ((0 <= (long)(arg1))) {
if (((((unsigned long)((unsigned int)(arg1)) == 12) | ((long)(arg1) < 12)) != 0)) {
if ((0 <= (long)(arg2))) {
if ((((unsigned long)((unsigned int)(arg2)) == 0x10000) | ((long)(arg2) < 0x10000))) {
goto L_1197;
}
}
}
}
}
// x86-64 epilogue: restore rbp
return 0;
L_1197: ;
index = 0;
goto L_11ef;
L_11a0: ;
var7 = pv_div_q16((unsigned long)((unsigned int)(arg0[(long)(index)])), (unsigned long)((unsigned int)(discount)));
total = (total + var7);
discount = ((long)(((long)((int)(((unsigned long)((unsigned int)(arg2)) + 0x10000))) * (long)(discount))) >> 16);
if (((((unsigned long)((unsigned int)(discount)) == 0) | ((long)(discount) < 0)) != 0)) {
// x86-64 epilogue: restore rbp
return (unsigned int)(total);
}
index = (index + 1);
L_11ef: ;
if ((index < arg1)) {
goto L_11a0;
}
// x86-64 epilogue: restore rbp
return (unsigned int)(total);
} gcc -O2
2/2internal_rate_of_return pass 71 lines
// glaurung: internal_rate_of_return @ 0x11b0
int32_t internal_rate_of_return(const int32_t * arg0, int32_t arg1) {
extern int net_present_value(int *, int, int);
int low;
int middle;
int high;
int value;
int local_3c;
long of_10;
long sf_10;
long t142;
long t144;
int * var1;
long var13;
long var16;
long var2;
int var25;
long var6;
long var9;
long zf_10;
if (((unsigned long)(11) < (unsigned long)((unsigned long)((unsigned int)((arg1 - 1)))))) {
goto L_1252;
}
var1 = (int *)arg0;
if ((arg0 == 0)) {
goto L_1252;
}
local_3c = 32;
var2 = (unsigned long)((unsigned int)(arg1));
var6 = 0x10000;
low = 0;
goto L_1200;
L_11f0: ;
var9 = (unsigned long)((unsigned int)(middle));
t142 = ((unsigned long)((unsigned int)(local_3c)) - 1);
local_3c = t142;
low = (unsigned long)((unsigned int)(middle));
var13 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var6)) - middle)));
if (((unsigned long)((unsigned int)(t142)) == 0)) {
goto L_1230;
}
L_1200: ;
var16 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var6)) - low)));
var13 = (unsigned long)((unsigned int)(((int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var16)) >> 31))) + var16)) >> 1)));
middle = (unsigned long)((unsigned int)((var13 + low)));
var25 = net_present_value(var1, (unsigned long)((unsigned int)(var2)), (unsigned long)((unsigned int)(middle)));
zf_10 = ((unsigned long)((unsigned int)(var25)) == 0);
sf_10 = ((long)((int)(var25)) < 0);
of_10 = 0;
if (((unsigned long)((unsigned int)(var25)) == 0)) {
goto L_1240;
}
if (((zf_10 | (sf_10 ^ of_10)) == 0)) {
goto L_11f0;
}
t144 = ((unsigned long)((unsigned int)(local_3c)) - 1);
local_3c = t144;
var6 = (unsigned long)((unsigned int)(middle));
var9 = (unsigned long)((unsigned int)(low));
if (((unsigned long)((unsigned int)(t144)) != 0)) {
goto L_1200;
}
L_1230: ;
middle = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var13)) >> 31))) + var13)) >> 1))) + var9)));
L_1240: ;
// x86-64 epilogue: tear down frame
return (unsigned int)(middle);
L_1252: ;
middle = 0xffffffff;
goto L_1240;
} net_present_value pass 53 lines
// glaurung: net_present_value @ 0x1120
int32_t net_present_value(const int32_t * arg0, int32_t arg1, int32_t arg2) {
int discount;
int index;
int total;
long var11;
long var12;
long var13;
long var16;
long var17;
long var19;
long var2;
long var20;
long var25;
int var26;
long var4;
long var6;
int var9;
var2 = 0;
if ((arg0 == 0)) {
return (unsigned int)(var2);
}
var2 = 0;
if (((unsigned long)(0x10000) < (unsigned long)((unsigned long)((unsigned int)(arg2))))) {
return (unsigned int)(var2);
}
var4 = (unsigned long)((unsigned int)((arg1 - 1)));
var2 = 0;
if (((unsigned long)(11) < (unsigned long)((unsigned long)((unsigned int)(var4))))) {
return (unsigned int)(var2);
}
var6 = ((long)((int)(*(int *)(((long)arg0)))) << 16);
var9 = (arg2 + 0x10000);
var11 = (long)((arg0 + 1));
var12 = (long)((int)(var9));
var13 = (var11 + (var4 * 4));
var16 = ((long)(((0 <= var6) ? var6 : (var6 + 0xffff))) >> 16);
var17 = (unsigned long)((unsigned int)(var9));
while ((var13 != var11)) {
var19 = (long)((int)(*(int *)((var11))));
var11 = (var11 + 4);
var20 = (var19 << 16);
var25 = ((long)(((long)((int)(var17)) * var12)) >> 16);
var26 = (var16 + ((long)((((__int128)(long)(((long)(var20) >> 63)) * (((__int128)1) << 64)) + (unsigned long)(var20)) / (long)((long)((int)(var17))))));
var16 = (unsigned long)((unsigned int)(var26));
var17 = (unsigned long)((unsigned int)(var25));
var2 = (unsigned long)((unsigned int)(var26));
if ((((unsigned long)((unsigned int)(var25)) == 0) | ((long)((int)(var25)) < 0))) {
return (unsigned int)(var2);
}
}
return (unsigned int)(var16);
}