Fixture 109
subscript commutativity
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-O0 (2/3).
a[i] is defined as *(a + i), so i[a] is the same object. The IOCCC leans on this; the point here is that the recovered code should express the addressing plainly regardless of which spelling produced it.
#include <stdint.h>
/* a[i] is defined as *(a + i), so i[a] is the same object. The IOCCC leans on
* this; the point here is that the recovered code should express the addressing
* plainly regardless of which spelling produced it. */
__attribute__((noinline)) int32_t
reversed_subscript(const int32_t *values, int32_t index, int32_t bound) {
if (values == 0 || index < 0 || bound < 0 || bound > 16 || index >= bound) {
return -1;
}
return index[values]; /* identical to values[index] */
}
__attribute__((noinline)) int32_t
mixed_subscript_sum(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 += (index & 1) ? index[values] : values[index];
}
return total;
}
__attribute__((noinline)) int32_t
negative_offset_from_interior(const int32_t *values, int32_t count) {
const int32_t *interior;
if (values == 0 || count < 2 || count > 16) {
return -1;
}
interior = values + count - 1;
/* A negative subscript on an interior pointer is ordinary arithmetic. */
return interior[-1] + interior[0];
} 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/3mixed_subscript_sum pass 31 lines
// glaurung: mixed_subscript_sum @ 0x1170
int32_t mixed_subscript_sum(const int32_t * arg0, int32_t arg1) {
int total;
int index;
int local_20;
int local_4;
// x86-64 prologue: save rbp
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++) {
local_20 = (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(index)) & 1))) == 0) ? arg0[(long)(index)] : arg0[(long)(index)]);
total = ((unsigned int)(local_20) + total);
}
local_4 = total;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} negative_offset_from_interior fail 25 lines
// glaurung: negative_offset_from_interior @ 0x1220
int32_t negative_offset_from_interior(const int32_t * arg0, int32_t arg1) {
int * interior;
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) < 2)) {
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);
}
interior = (int *)((((long)arg0 + ((long)(arg1) << 2)) - 4));
local_4 = ((unsigned int)(*(int *)((interior - 0x4))) + *(int *)(interior));
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} reversed_subscript pass 33 lines
// glaurung: reversed_subscript @ 0x1100
int32_t reversed_subscript(const int32_t * arg0, int32_t arg1, int32_t arg2) {
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 (((long)(arg2) < 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((((unsigned long)((unsigned int)(arg2)) == 16) | ((long)(arg2) < 16)) == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if ((arg2 <= arg1)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
local_4 = arg0[(long)(arg1)];
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} clang -O2
3/3mixed_subscript_sum pass 68 lines
// glaurung: mixed_subscript_sum @ 0x1120
int32_t mixed_subscript_sum(const int32_t * arg0, int32_t arg1) {
int total;
int index;
long ret;
long var2;
long var41;
long var5;
int var6;
int var7;
int var8;
int var9;
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));
if ((var5 != 4)) {
var6 = (var6 + *(int *)(((long)arg0 + 0x10)));
var7 = (var7 + *(int *)(((long)arg0 + 0x14)));
var8 = (var8 + *(int *)(((long)arg0 + 0x18)));
var9 = (var9 + *(int *)(((long)arg0 + 0x1c)));
if (((unsigned long)((unsigned int)(var5)) != 8)) {
var6 = (var6 + *(int *)(((long)arg0 + 0x20)));
var7 = (var7 + *(int *)(((long)arg0 + 0x24)));
var8 = (var8 + *(int *)(((long)arg0 + 0x28)));
var9 = (var9 + *(int *)(((long)arg0 + 0x2c)));
if (((unsigned long)((unsigned int)(var5)) != 12)) {
var6 = (var6 + *(int *)(((long)arg0 + 0x30)));
var7 = (var7 + *(int *)(((long)arg0 + 0x34)));
var8 = (var8 + *(int *)(((long)arg0 + 0x38)));
var9 = (var9 + *(int *)(((long)arg0 + 0x3c)));
}
}
}
var41 = (unsigned long)((unsigned int)(((var9 + var7) + (var8 + var6))));
ret = var41;
if ((var5 == var2)) {
return ret;
}
L_11a0: ;
do {
total = (var41 + *(int *)(((long)arg0 + var5 * 4)));
index = (var5 + 1);
var41 = (unsigned long)((unsigned int)(total));
var5 = (unsigned long)((unsigned int)(index));
ret = (unsigned long)((unsigned int)(total));
} while ((var2 != index));
} else {
var41 = 0;
var5 = 0;
goto L_11a0;
}
return ret;
} negative_offset_from_interior pass 11 lines
// glaurung: negative_offset_from_interior @ 0x11b0
int32_t negative_offset_from_interior(const int32_t * arg0, int32_t arg1) {
long ret;
ret = 0xffffffff;
if ((arg0 != 0)) {
if (((unsigned long)(0xfffffff1) <= (unsigned long)((unsigned long)((unsigned int)((arg1 - 17)))))) {
ret = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)((((long)arg0 + ((unsigned long)((unsigned int)(arg1)) * 4)) - 4)))) + *(int *)((((long)arg0 + ((unsigned long)((unsigned int)(arg1)) * 4)) - 8)))));
}
}
return ret;
} reversed_subscript pass 17 lines
// glaurung: reversed_subscript @ 0x1100
int32_t reversed_subscript(const int32_t * arg0, int32_t arg1, int32_t arg2) {
long ret;
ret = 0xffffffff;
if ((arg1 < arg2)) {
if (((((unsigned long)((unsigned int)(arg2)) == 16) | ((long)(arg2) < 16)) == 0)) {
return ret;
}
if ((arg0 == 0)) {
return ret;
}
if ((0 <= (long)((int)((arg2 | arg1))))) {
ret = (unsigned long)((unsigned int)(arg0[(long)(arg1)]));
}
}
return ret;
} gcc -O0
3/3mixed_subscript_sum pass 24 lines
// glaurung: mixed_subscript_sum @ 0x114b
int32_t mixed_subscript_sum(const int32_t * arg0, int32_t arg1) {
int total;
int index;
// x86-64 prologue: save rbp
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++) {
total = (total + (unsigned int)(arg0[(long)(index)]));
}
// x86-64 epilogue: restore rbp
return (unsigned int)(total);
} negative_offset_from_interior pass 20 lines
// glaurung: negative_offset_from_interior @ 0x11ae
int32_t negative_offset_from_interior(const int32_t * arg0, int32_t arg1) {
int * interior;
// x86-64 prologue: save rbp
if ((arg0 == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
if ((((unsigned long)((unsigned int)(arg1)) == 1) | ((long)(arg1) < 1))) {
// 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;
}
interior = (int *)(((long)arg0 + (((long)(arg1) << 2) - 4)));
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(*(int *)(interior))) + (unsigned long)((unsigned int)(*(int *)((interior - 1))))));
} reversed_subscript pass 26 lines
// glaurung: reversed_subscript @ 0x10f9
int32_t reversed_subscript(const int32_t * arg0, int32_t arg1, int32_t arg2) {
// 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 (((long)(arg2) < 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
if (((((unsigned long)((unsigned int)(arg2)) == 16) | ((long)(arg2) < 16)) == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
if ((arg2 <= arg1)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
// x86-64 epilogue: restore rbp
return (unsigned int)(arg0[(long)(arg1)]);
} gcc -O2
3/3mixed_subscript_sum pass 25 lines
// glaurung: mixed_subscript_sum @ 0x1130
int32_t mixed_subscript_sum(const int32_t * arg0, int32_t arg1) {
int index;
int total;
long ret;
long var2;
long var5;
if ((arg0 == 0)) {
return 0xffffffff;
}
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
return 0xffffffff;
}
if (((unsigned long)((unsigned int)(arg1)) == 0)) {
return 0;
}
var2 = (long)((((long)arg0 + ((unsigned long)((unsigned int)((arg1 - 1))) * 4)) + 4));
ret = 0;
var5 = (long)arg0;
do {
ret = (unsigned long)((unsigned int)((ret + *(int *)((var5)))));
var5 = (var5 + 4);
} while ((var5 != var2));
return ret;
} negative_offset_from_interior pass 7 lines
// glaurung: negative_offset_from_interior @ 0x1170
int32_t negative_offset_from_interior(const int32_t * arg0, int32_t arg1) {
if ((((unsigned long)(14) < (unsigned long)((unsigned long)((unsigned int)((arg1 - 2))))) || (arg0 == 0))) {
return 0xffffffff;
}
return (unsigned int)(((unsigned long)((unsigned int)(*(int *)((((long)arg0 + ((long)(arg1) * 4)) - 8)))) + *(int *)((((long)arg0 + ((long)(arg1) * 4)) - 4))));
} reversed_subscript pass 13 lines
// glaurung: reversed_subscript @ 0x1100
int32_t reversed_subscript(const int32_t * arg0, int32_t arg1, int32_t arg2) {
if ((arg0 == 0)) {
return 0xffffffff;
}
if (((long)(arg1) < 0)) {
return 0xffffffff;
}
if ((((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg2)))) || (arg2 <= arg1))) {
return 0xffffffff;
}
return (unsigned int)(arg0[(long)(arg1)]);
}