Fixture 120
const and literals
C · 3 functions · 4 lanes · 8 of 12 function-lanes behave identically
4 of 4 lanes have a function that returns a different result after decompilation: clang-O0 (2/3), clang-O2 (2/3), gcc-O0 (2/3), gcc-O2 (2/3).
const on the object versus const through the pointer. A const object with a constant initializer can be folded entirely; a pointer-to-const only promises this access path will not write.
#include <stdint.h>
/* const on the object versus const through the pointer. A `const` object with
* a constant initializer can be folded entirely; a pointer-to-const only
* promises this access path will not write. */
static const int32_t FOLDABLE = 41;
__attribute__((noinline)) int32_t reads_foldable_constant(void) {
return FOLDABLE + 1;
}
__attribute__((noinline)) int32_t
pointer_to_const_still_loads(const int32_t *values, int32_t index) {
if (values == 0 || index < 0 || index > 15) {
return -1;
}
/* The pointee may change between these two loads through another path, so
* neither load may be reused for the other. */
return values[index] * 2;
}
__attribute__((noinline)) int32_t
const_array_of_pointers(int32_t which, int32_t fallback) {
static const int32_t first = 7;
static const int32_t second = 8;
static const int32_t third = 9;
static const int32_t *const table[3] = {&first, &second, &third};
if (which < 0 || which > 2) {
return fallback;
}
return *table[which];
} 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/3const_array_of_pointers fail 18 lines
// glaurung: const_array_of_pointers @ 0x1160
int32_t const_array_of_pointers(int32_t arg0, int32_t arg1) {
int local_4;
// x86-64 prologue: save rbp
if (((long)(arg0) < 0)) {
local_4 = arg1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((((unsigned long)((unsigned int)(arg0)) == 2) | ((long)(arg0) < 2)) == 0)) {
local_4 = arg1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
local_4 = *(int *)(*(long *)((0x3e30 + ((long)(arg0) * 8))));
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} pointer_to_const_still_loads pass 23 lines
// glaurung: pointer_to_const_still_loads @ 0x1110
int32_t pointer_to_const_still_loads(const int32_t * arg0, int32_t arg1) {
int local_4;
// x86-64 prologue: save rbp
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)) == 15) | ((long)(arg1) < 15)) == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
local_4 = ((unsigned long)((unsigned int)(arg0[(long)(arg1)])) << 1);
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} reads_foldable_constant pass 6 lines
// glaurung: reads_foldable_constant @ 0x1100
int32_t reads_foldable_constant(void) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return 42;
} clang -O2
2/3const_array_of_pointers fail 9 lines
// glaurung: const_array_of_pointers @ 0x1130
int32_t const_array_of_pointers(int32_t arg0, int32_t arg1) {
long ret;
ret = (unsigned long)((unsigned int)(arg1));
if (((unsigned long)((unsigned long)((unsigned int)(arg0))) <= (unsigned long)(2))) {
ret = (unsigned long)((unsigned int)(*(int *)(((long)((int)((((unsigned long)((unsigned int)(arg0)) == 0) ? 0xfffffff4 : (((unsigned long)((unsigned int)(arg0)) == 1) ? 0xfffffff8 : (((unsigned long)((unsigned int)(arg0)) == 2) ? 0xfffffffc : *(int *)((0x200c + ((unsigned long)((unsigned int)(arg0)) * 4)))))))) + 0x200c))));
}
return ret;
} pointer_to_const_still_loads pass 13 lines
// glaurung: pointer_to_const_still_loads @ 0x1110
int32_t pointer_to_const_still_loads(const int32_t * arg0, int32_t arg1) {
long ret;
long var1;
ret = 0xffffffff;
if ((arg0 != 0)) {
if (((unsigned long)((unsigned long)((unsigned int)(arg1))) <= (unsigned long)(15))) {
var1 = (unsigned long)((unsigned int)(arg0[(unsigned long)((unsigned int)(arg1))]));
ret = (unsigned long)((unsigned int)((var1 + var1)));
}
}
return ret;
} reads_foldable_constant pass 4 lines
// glaurung: reads_foldable_constant @ 0x1100
int32_t reads_foldable_constant(void) {
return 42;
} gcc -O0
2/3const_array_of_pointers fail 14 lines
// glaurung: const_array_of_pointers @ 0x114e
int32_t const_array_of_pointers(int32_t arg0, int32_t arg1) {
// x86-64 prologue: save rbp
if (((long)(arg0) < 0)) {
// x86-64 epilogue: restore rbp
return (unsigned int)(arg1);
}
if (((((unsigned long)((unsigned int)(arg0)) == 2) | ((long)(arg0) < 2)) == 0)) {
// x86-64 epilogue: restore rbp
return (unsigned int)(arg1);
}
// x86-64 epilogue: restore rbp
return (unsigned int)(*(int *)(*(long *)((((long)(arg0) * 8) + 0x3e70))));
} pointer_to_const_still_loads pass 20 lines
// glaurung: pointer_to_const_still_loads @ 0x110b
int32_t pointer_to_const_still_loads(const int32_t * arg0, int32_t arg1) {
long var5;
// x86-64 prologue: save rbp
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)) == 15) | ((long)(arg1) < 15)) == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
var5 = (unsigned long)((unsigned int)(arg0[(long)(arg1)]));
// x86-64 epilogue: restore rbp
return (unsigned int)((var5 + var5));
} reads_foldable_constant pass 6 lines
// glaurung: reads_foldable_constant @ 0x10f9
int32_t reads_foldable_constant(void) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return 42;
} gcc -O2
2/3const_array_of_pointers fail 9 lines
// glaurung: const_array_of_pointers @ 0x1140
int32_t const_array_of_pointers(int32_t arg0, int32_t arg1) {
long ret;
ret = (unsigned long)((unsigned int)(arg1));
if (((unsigned long)((unsigned long)((unsigned int)(arg0))) <= (unsigned long)(2))) {
ret = (unsigned long)((unsigned int)(*(int *)(*(long *)((0x3e70 + ((long)(arg0) * 8))))));
}
return ret;
} pointer_to_const_still_loads pass 11 lines
// glaurung: pointer_to_const_still_loads @ 0x1110
int32_t pointer_to_const_still_loads(const int32_t * arg0, int32_t arg1) {
long var1;
if ((arg0 != 0)) {
if (((unsigned long)((unsigned long)((unsigned int)(arg1))) <= (unsigned long)(15))) {
var1 = (unsigned long)((unsigned int)(arg0[(long)(arg1)]));
return (unsigned int)((var1 + var1));
}
}
return 0xffffffff;
} reads_foldable_constant pass 4 lines
// glaurung: reads_foldable_constant @ 0x1100
int32_t reads_foldable_constant(void) {
return 42;
}