Fixture 127
inline linkage
C · 3 functions · 4 lanes · 11 of 12 function-lanes behave identically
One lane has a function that returns a different result after decompilation: clang-O2 (2/3).
static inline may be emitted, inlined, or both. An address taken of a static inline forces an out-of-line copy to exist, so the same source function can appear zero, one or several times in the object.
#include <stdint.h>
/* static inline may be emitted, inlined, or both. An address taken of a static
* inline forces an out-of-line copy to exist, so the same source function can
* appear zero, one or several times in the object. */
static inline int32_t scale(int32_t value, int32_t factor) {
return (int32_t)((uint32_t)value * (uint32_t)factor);
}
static inline int32_t clamp(int32_t value, int32_t low, int32_t high) {
if (value < low) {
return low;
}
if (value > high) {
return high;
}
return value;
}
__attribute__((noinline)) int32_t
inline_used_twice(int32_t value, int32_t factor) {
return scale(value, factor) + scale(factor, value);
}
__attribute__((noinline)) int32_t
inline_address_taken(int32_t value, int32_t low, int32_t high) {
/* Taking the address forces an out-of-line body to exist. */
int32_t (*indirect)(int32_t, int32_t, int32_t) = clamp;
return indirect(value, low, high) + clamp(value, low, high);
}
__attribute__((noinline)) int32_t
inline_in_loop(const int32_t *values, int32_t count) {
int32_t total = 0;
int32_t index;
if (values == 0 || count < 0 || count > 16) {
return -1;
}
for (index = 0; index < count; ++index) {
total += clamp(scale(values[index], 3), -100, 100);
}
return 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 -O2
2/3inline_address_taken pass 6 lines
// glaurung: inline_address_taken @ 0x1110
int32_t inline_address_taken(int32_t arg0, int32_t arg1, int32_t arg2) {
long var1;
var1 = ((arg0 < arg1) ? arg1 : ((((unsigned int)(arg0) == (unsigned int)(arg2)) | (arg0 < arg2)) ? arg0 : arg2));
return (unsigned int)((var1 + var1));
} inline_in_loop fail 260 lines
// glaurung: inline_in_loop @ 0x1120
int32_t inline_in_loop(const int32_t * arg0, int32_t arg1) {
int index;
int total;
long ret;
int var100;
int var101;
int var102;
int var111;
int var112;
int var113;
int var114;
int var121;
int var122;
int var123;
int var124;
int var138;
int var139;
int var140;
int var141;
int var152;
int var153;
int var154;
int var155;
int var161;
int var162;
int var163;
int var164;
int var173;
int var174;
int var175;
int var176;
int var183;
int var184;
int var185;
int var186;
long var2;
int var20;
int var200;
int var201;
int var202;
int var203;
int var21;
int var214;
int var215;
int var216;
int var217;
int var22;
int var223;
int var224;
int var225;
int var226;
int var23;
int var235;
int var236;
int var237;
int var238;
int var24;
int var245;
int var246;
int var247;
int var248;
int var25;
int var26;
int var27;
long var278;
long var279;
long var280;
long var281;
long var282;
long var283;
long var285;
long var286;
int var287;
int var34;
int var35;
int var36;
int var37;
int var46;
int var47;
int var48;
int var49;
long var5;
int var51;
int var52;
int var53;
int var54;
int var6;
int var60;
int var61;
int var62;
int var63;
int var7;
int var72;
int var73;
int var74;
int var75;
int var76;
int var77;
int var78;
int var79;
int var8;
int var9;
int var90;
int var91;
int var92;
int var93;
int var99;
ret = 0xffffffff;
if ((arg0 == 0)) {
return ret;
}
ret = 0xffffffff;
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
return ret;
}
if (((unsigned long)((unsigned int)(arg1)) == 0)) {
return 0;
}
var2 = (unsigned long)((unsigned int)(arg1));
if (((unsigned long)(4) <= (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
var5 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var2)) & -4)));
var6 = *(int *)(((long)arg0));
var7 = *(int *)(((long)arg0 + 0x4));
var8 = *(int *)(((long)arg0 + 0x8));
var9 = *(int *)(((long)arg0 + 0xc));
var20 = ((var6 + var6) + var6);
var21 = ((var7 + var7) + var7);
var22 = ((var8 + var8) + var8);
var23 = ((var9 + var9) + var9);
var24 = 100;
var25 = 100;
var26 = 100;
var27 = 100;
var34 = (-(var20 < 100));
var35 = (-(var21 < 100));
var36 = (-(var22 < 100));
var37 = (-(var23 < 100));
var46 = (((~var34) & 100) | (var20 & var34));
var47 = (((~var35) & 100) | (var21 & var35));
var48 = (((~var36) & 100) | (var22 & var36));
var49 = (((~var37) & 100) | (var23 & var37));
var51 = 0xffffff9c;
var52 = 0xffffff9c;
var53 = 0xffffff9c;
var54 = 0xffffff9c;
var60 = (-(0xffffff9c < var46));
var61 = (-(0xffffff9c < var47));
var62 = (-(0xffffff9c < var48));
var63 = (-(0xffffff9c < var49));
var72 = (((~var60) & 0xffffff9c) | (var46 & var60));
var73 = (((~var61) & 0xffffff9c) | (var47 & var61));
var74 = (((~var62) & 0xffffff9c) | (var48 & var62));
var75 = (((~var63) & 0xffffff9c) | (var49 & var63));
if ((var5 != 4)) {
var76 = *(int *)(((long)arg0 + 0x10));
var77 = *(int *)(((long)arg0 + 0x14));
var78 = *(int *)(((long)arg0 + 0x18));
var79 = *(int *)(((long)arg0 + 0x1c));
var90 = ((var76 + var76) + var76);
var91 = ((var77 + var77) + var77);
var92 = ((var78 + var78) + var78);
var93 = ((var79 + var79) + var79);
var99 = (-(var90 < var24));
var100 = (-(var91 < var25));
var101 = (-(var92 < var26));
var102 = (-(var93 < var27));
var111 = (((~var99) & var24) | (var90 & var99));
var112 = (((~var100) & var25) | (var91 & var100));
var113 = (((~var101) & var26) | (var92 & var101));
var114 = (((~var102) & var27) | (var93 & var102));
var121 = (-(var51 < var111));
var122 = (-(var52 < var112));
var123 = (-(var53 < var113));
var124 = (-(var54 < var114));
var72 = (var72 + (((~var121) & var51) | (var111 & var121)));
var73 = (var73 + (((~var122) & var52) | (var112 & var122)));
var74 = (var74 + (((~var123) & var53) | (var113 & var123)));
var75 = (var75 + (((~var124) & var54) | (var114 & var124)));
if (((unsigned long)((unsigned int)(var5)) != 8)) {
var138 = *(int *)(((long)arg0 + 0x20));
var139 = *(int *)(((long)arg0 + 0x24));
var140 = *(int *)(((long)arg0 + 0x28));
var141 = *(int *)(((long)arg0 + 0x2c));
var152 = ((var138 + var138) + var138);
var153 = ((var139 + var139) + var139);
var154 = ((var140 + var140) + var140);
var155 = ((var141 + var141) + var141);
var161 = (-(var152 < var24));
var162 = (-(var153 < var25));
var163 = (-(var154 < var26));
var164 = (-(var155 < var27));
var173 = (((~var161) & var24) | (var152 & var161));
var174 = (((~var162) & var25) | (var153 & var162));
var175 = (((~var163) & var26) | (var154 & var163));
var176 = (((~var164) & var27) | (var155 & var164));
var183 = (-(var51 < var173));
var184 = (-(var52 < var174));
var185 = (-(var53 < var175));
var186 = (-(var54 < var176));
var72 = (var72 + (((~var183) & var51) | (var173 & var183)));
var73 = (var73 + (((~var184) & var52) | (var174 & var184)));
var74 = (var74 + (((~var185) & var53) | (var175 & var185)));
var75 = (var75 + (((~var186) & var54) | (var176 & var186)));
if (((unsigned long)((unsigned int)(var5)) != 12)) {
var200 = *(int *)(((long)arg0 + 0x30));
var201 = *(int *)(((long)arg0 + 0x34));
var202 = *(int *)(((long)arg0 + 0x38));
var203 = *(int *)(((long)arg0 + 0x3c));
var214 = ((var200 + var200) + var200);
var215 = ((var201 + var201) + var201);
var216 = ((var202 + var202) + var202);
var217 = ((var203 + var203) + var203);
var223 = (-(var214 < var24));
var224 = (-(var215 < var25));
var225 = (-(var216 < var26));
var226 = (-(var217 < var27));
var235 = (((~var223) & var24) | (var214 & var223));
var236 = (((~var224) & var25) | (var215 & var224));
var237 = (((~var225) & var26) | (var216 & var225));
var238 = (((~var226) & var27) | (var217 & var226));
var245 = (-(var51 < var235));
var246 = (-(var52 < var236));
var247 = (-(var53 < var237));
var248 = (-(var54 < var238));
var72 = (var72 + (((~var245) & var51) | (var235 & var245)));
var73 = (var73 + (((~var246) & var52) | (var236 & var246)));
var74 = (var74 + (((~var247) & var53) | (var237 & var247)));
var75 = (var75 + (((~var248) & var54) | (var238 & var248)));
}
}
}
var278 = (unsigned long)((unsigned int)(((var75 + var73) + (var74 + var72))));
var279 = var278;
var280 = var5;
ret = var278;
if ((var5 == var2)) {
return ret;
}
L_1283: ;
var281 = 100;
var282 = 0xffffff9c;
var283 = var279;
index = var280;
do {
var285 = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + index * 4))));
var286 = (unsigned long)((unsigned int)((var285 + (var285 * 2))));
var287 = ((100 <= (long)((int)(var286))) ? var281 : var286);
total = (var283 + (((long)((int)(var287)) < -99) ? var282 : var287));
var283 = (unsigned long)((unsigned int)(total));
index = (index + 1);
ret = (unsigned long)((unsigned int)(total));
} while ((var2 != index));
} else {
var279 = 0;
var280 = 0;
goto L_1283;
}
return ret;
} inline_used_twice pass 6 lines
// glaurung: inline_used_twice @ 0x1100
int32_t inline_used_twice(int32_t arg0, int32_t arg1) {
long var1;
var1 = (unsigned long)((unsigned int)((arg0 * arg1)));
return (unsigned int)((var1 + var1));
} clang -O0
3/3inline_address_taken pass 15 lines
// glaurung: inline_address_taken @ 0x1160
int32_t inline_address_taken(int32_t arg0, int32_t arg1, int32_t arg2) {
extern int clamp(int, int, int);
char * indirect;
int local_1c;
long var2;
int var4;
// x86-64 prologue: save rbp, frame 32 bytes
indirect = (char *)((long)(clamp));
var2 = ((long (*)(long, long, long))(indirect))((unsigned long)((unsigned int)(arg0)), (unsigned long)((unsigned int)(arg1)), (unsigned long)((unsigned int)(arg2)));
local_1c = var2;
var4 = clamp((unsigned long)((unsigned int)(arg0)), (unsigned long)((unsigned int)(arg1)), (unsigned long)((unsigned int)(arg2)));
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(local_1c)) + (unsigned long)((unsigned int)(var4))));
} inline_in_loop pass 35 lines
// glaurung: inline_in_loop @ 0x1200
int32_t inline_in_loop(const int32_t * arg0, int32_t arg1) {
extern int clamp(int, int, int);
extern int scale(int, int);
int total;
int index;
int local_4;
int var5;
int var7;
// x86-64 prologue: save rbp, frame 32 bytes
total = 0;
if ((arg0 == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((long)(arg1) < 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
for (index = 0; (index < arg1); index++) {
var5 = scale((unsigned long)((unsigned int)(arg0[(long)(index)])), 3);
var7 = clamp((unsigned long)((unsigned int)(var5)), 0xffffff9c, 100);
total = (var7 + total);
}
local_4 = total;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} inline_used_twice pass 13 lines
// glaurung: inline_used_twice @ 0x1100
int32_t inline_used_twice(int32_t arg0, int32_t arg1) {
extern int scale(int, int);
int local_c;
int var0;
int var2;
// x86-64 prologue: save rbp, frame 16 bytes
var0 = scale((unsigned long)((unsigned int)(arg0)), (unsigned long)((unsigned int)(arg1)));
local_c = var0;
var2 = scale((unsigned long)((unsigned int)(arg1)), (unsigned long)((unsigned int)(arg0)));
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(local_c)) + (unsigned long)((unsigned int)(var2))));
} gcc -O0
3/3inline_address_taken pass 15 lines
// glaurung: inline_address_taken @ 0x1179
int32_t inline_address_taken(int32_t arg0, int32_t arg1, int32_t arg2) {
extern int clamp(int, int, int);
char * indirect;
long var4;
long var6;
int var9;
// x86-64 prologue: save rbp, frame 8 bytes
indirect = (char *)((long)(clamp));
var4 = ((long (*)(long, long, long))(indirect))((unsigned long)((unsigned int)(arg0)), (unsigned long)((unsigned int)(arg1)), (unsigned long)((unsigned int)(arg2)));
var6 = (unsigned long)((unsigned int)(var4));
var9 = clamp((unsigned long)((unsigned int)(arg0)), (unsigned long)((unsigned int)(arg1)), (unsigned long)((unsigned int)(arg2)));
// x86-64 epilogue: restore rbp
return (unsigned int)((var9 + var6));
} inline_in_loop pass 30 lines
// glaurung: inline_in_loop @ 0x11ca
int32_t inline_in_loop(const int32_t * arg0, int32_t arg1) {
extern int clamp(int, int, int);
extern int scale(int, int);
int total;
int index;
int var7;
int var9;
// x86-64 prologue: save rbp, frame 32 bytes
total = 0;
if ((arg0 == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
if (((long)(arg1) < 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
for (index = 0; (index < arg1); index++) {
var7 = scale((unsigned long)((unsigned int)(arg0[(long)(index)])), 3);
var9 = clamp((unsigned long)((unsigned int)(var7)), 0xffffff9c, 100);
total = (total + var9);
}
// x86-64 epilogue: restore rbp
return (unsigned int)(total);
} inline_used_twice pass 13 lines
// glaurung: inline_used_twice @ 0x113e
int32_t inline_used_twice(int32_t arg0, int32_t arg1) {
extern int scale(int, int);
int var2;
long var4;
int var7;
// x86-64 prologue: save rbp, frame 8 bytes
var2 = scale((unsigned long)((unsigned int)(arg0)), (unsigned long)((unsigned int)(arg1)));
var4 = (unsigned long)((unsigned int)(var2));
var7 = scale((unsigned long)((unsigned int)(arg1)), (unsigned long)((unsigned int)(arg0)));
// x86-64 epilogue: restore rbp
return (unsigned int)((var7 + var4));
} gcc -O2
3/3inline_address_taken pass 6 lines
// glaurung: inline_address_taken @ 0x1110
int32_t inline_address_taken(int32_t arg0, int32_t arg1, int32_t arg2) {
long var1;
var1 = ((arg1 <= arg0) ? ((((unsigned int)(arg0) == (unsigned int)(arg2)) | (arg0 < arg2)) ? arg0 : arg2) : arg1);
return (unsigned int)((var1 + var1));
} inline_in_loop pass 36 lines
// glaurung: inline_in_loop @ 0x1130
int32_t inline_in_loop(const int32_t * arg0, int32_t arg1) {
int total;
int index;
long var1;
long var10;
long var12;
int var13;
long var7;
long var8;
long var9;
if ((arg0 == 0)) {
var1 = 0xffffffff;
return 0xffffffff;
}
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
var1 = 0xffffffff;
return 0xffffffff;
}
if (((unsigned long)((unsigned int)(arg1)) == 0)) {
return 0;
}
var7 = (long)((((long)arg0 + ((unsigned long)((unsigned int)((arg1 - 1))) * 4)) + 4));
var8 = 0;
var9 = (long)arg0;
do {
var10 = (unsigned long)((unsigned int)(*(int *)((var9))));
var12 = (unsigned long)((unsigned int)((var10 + (var10 * 2))));
var13 = (((((unsigned long)((unsigned int)(var12)) == 100) | ((long)((int)(var12)) < 100)) == 0) ? 100 : var12);
var9 = (var9 + 4);
total = (var8 + (((long)((int)(var13)) < (long)((int)(0xffffff9c))) ? 0xffffff9c : var13));
var8 = (unsigned long)((unsigned int)(total));
var1 = (unsigned long)((unsigned int)(total));
} while ((var7 != var9));
return (unsigned int)(var1);
} inline_used_twice pass 6 lines
// glaurung: inline_used_twice @ 0x1100
int32_t inline_used_twice(int32_t arg0, int32_t arg1) {
long var1;
var1 = (unsigned long)((unsigned int)((arg0 * arg1)));
return (unsigned int)((var1 + var1));
}