Fixture 100
struct layout
C · 3 functions · 4 lanes · 12 of 12 function-lanes behave identically
All 4 lanes recompile and return the same results as the original.
Padding is part of the object but not of any member. Copying a struct copies the padding; comparing member-by-member does not. The two orderings below hold identical members and differ only in size.
#include <stdint.h>
#include <stddef.h>
/* Padding is part of the object but not of any member. Copying a struct copies
* the padding; comparing member-by-member does not. The two orderings below
* hold identical members and differ only in size. */
struct Wasteful {
uint8_t tag;
int32_t value;
uint8_t flag;
int32_t extra;
};
struct Tight {
int32_t value;
int32_t extra;
uint8_t tag;
uint8_t flag;
};
__attribute__((noinline)) int32_t layout_size_delta(void) {
return (int32_t)(sizeof(struct Wasteful) - sizeof(struct Tight));
}
__attribute__((noinline)) int32_t layout_offsets(int32_t which) {
switch (which & 3) {
case 0:
return (int32_t)offsetof(struct Wasteful, value);
case 1:
return (int32_t)offsetof(struct Wasteful, extra);
case 2:
return (int32_t)offsetof(struct Tight, tag);
default:
return (int32_t)offsetof(struct Tight, flag);
}
}
__attribute__((noinline)) int32_t
struct_assignment_copies(int32_t tag, int32_t value) {
struct Tight source;
struct Tight destination;
source.value = value;
source.extra = value * 2;
source.tag = (uint8_t)tag;
source.flag = (uint8_t)(tag + 1);
destination = source; /* whole-object copy, padding included */
return destination.value + destination.extra + (int32_t)destination.tag +
(int32_t)destination.flag;
} 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/3layout_offsets pass 21 lines
// glaurung: layout_offsets @ 0x1110
int32_t layout_offsets(int32_t arg0) {
int local_c;
int var1;
// x86-64 prologue: save rbp
var1 = ((unsigned int)(arg0) & 3);
local_c = var1;
if (((unsigned long)((unsigned int)(var1)) == 0)) {
return 4;
} else {
if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(local_c)) - 1))) == 0)) {
return 12;
} else {
if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(local_c)) - 2))) == 0)) {
return 8;
} else {
return 9;
}
}
}
} layout_size_delta pass 6 lines
// glaurung: layout_size_delta @ 0x1100
int32_t layout_size_delta(void) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return 4;
} struct_assignment_copies pass 14 lines
// glaurung: struct_assignment_copies @ 0x1180
__attribute__((no_stack_protector)) int32_t struct_assignment_copies(int32_t arg0, int32_t arg1) {
unsigned char local_18[12];
unsigned char local_28[12];
// x86-64 prologue: save rbp
*(int *)(&local_18[0]) = arg1;
*(int *)((&local_18[0] + 4)) = ((unsigned long)((unsigned int)(arg1)) << 1);
*(signed char *)((&local_18[0] + 8)) = arg0;
*(signed char *)((&local_18[0] + 9)) = ((unsigned long)((unsigned int)(arg0)) + 1);
*(long *)(&local_28[0]) = *(long *)(&local_18[0]);
*(int *)((&local_28[0] + 8)) = *(int *)((&local_18[0] + 8));
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)(&local_28[0]))) + *(int *)((&local_28[0] + 4))))) + (unsigned int)((unsigned char)(*(char *)((&local_28[0] + 8))))))) + (unsigned int)((unsigned char)(*(char *)((&local_28[0] + 9))))));
} clang -O2
3/3layout_offsets pass 11 lines
// glaurung: layout_offsets @ 0x1110
int32_t layout_offsets(int32_t arg0) {
long ret;
long var1;
var1 = (unsigned long)((unsigned int)((arg0 & 3)));
ret = 9;
if (((unsigned long)((unsigned int)(var1)) != 3)) {
ret = (unsigned long)((unsigned int)((((unsigned long)((unsigned int)(var1)) == 0) ? 4 : (((unsigned long)((unsigned int)(var1)) == 1) ? 12 : (((unsigned long)((unsigned int)(var1)) == 2) ? 8 : *(int *)((0x2000 + ((unsigned long)((unsigned int)(var1)) * 4))))))));
}
return ret;
} layout_size_delta pass 4 lines
// glaurung: layout_size_delta @ 0x1100
int32_t layout_size_delta(void) {
return 4;
} struct_assignment_copies pass 4 lines
// glaurung: struct_assignment_copies @ 0x1130
int32_t struct_assignment_copies(int32_t arg0, int32_t arg1) {
return (unsigned int)(((unsigned int)((unsigned char)(((unsigned long)((unsigned int)((arg0 + 1))) & 255))) + (unsigned long)((unsigned int)(((unsigned int)((unsigned char)((arg0 & 255))) + (unsigned long)((unsigned int)((arg1 + (arg1 * 2)))))))));
} gcc -O0
3/3layout_offsets pass 23 lines
// glaurung: layout_offsets @ 0x1108
int32_t layout_offsets(int32_t arg0) {
long var2;
// x86-64 prologue: save rbp
var2 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 3)));
if (((unsigned long)((unsigned int)(var2)) == 2)) {
return 8;
} else {
if (((((unsigned long)((unsigned int)(var2)) == 2) | ((long)((int)(var2)) < 2)) == 0)) {
// x86-64 epilogue: restore rbp
return 9;
}
if (((unsigned long)((unsigned int)(var2)) == 0)) {
return 4;
} else {
if (((unsigned long)((unsigned int)(var2)) == 1)) {
return 12;
} else {
return 9;
}
}
}
} layout_size_delta pass 6 lines
// glaurung: layout_size_delta @ 0x10f9
int32_t layout_size_delta(void) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return 4;
} struct_assignment_copies pass 14 lines
// glaurung: struct_assignment_copies @ 0x114a
__attribute__((no_stack_protector)) int32_t struct_assignment_copies(int32_t arg0, int32_t arg1) {
unsigned char local_18[12];
unsigned char local_c[12];
// x86-64 prologue: save rbp
*(int *)(&local_18[0]) = arg1;
*(int *)((&local_18[0] + 4)) = ((unsigned long)((unsigned int)(arg1)) + (unsigned long)((unsigned int)(arg1)));
*(signed char *)((&local_18[0] + 8)) = arg0;
*(signed char *)((&local_18[0] + 9)) = ((unsigned long)((unsigned int)(arg0)) + 1);
*(long *)(&local_c[0]) = *(long *)(&local_18[0]);
*(int *)((&local_c[0] + 8)) = *(int *)((&local_18[0] + 8));
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned int)((unsigned char)(((unsigned int)((unsigned char)(*(char *)((&local_c[0] + 9)))) & 255))) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)(&local_c[0]))) + (unsigned long)((unsigned int)(*(int *)((&local_c[0] + 4))))))) + (unsigned int)((unsigned char)(((unsigned int)((unsigned char)(*(char *)((&local_c[0] + 8)))) & 255))))))));
} gcc -O2
3/3layout_offsets pass 11 lines
// glaurung: layout_offsets @ 0x1110
int32_t layout_offsets(int32_t arg0) {
long ret;
long var1;
var1 = (unsigned long)((unsigned int)((arg0 & 3)));
ret = 9;
if (((unsigned long)((unsigned int)(var1)) != 3)) {
ret = (unsigned long)((unsigned int)(((var1 == 0) ? 4 : ((var1 == 1) ? 12 : ((var1 == 2) ? 8 : *(int *)((0x2000 + (var1 * 4))))))));
}
return ret;
} layout_size_delta pass 4 lines
// glaurung: layout_size_delta @ 0x1100
int32_t layout_size_delta(void) {
return 4;
} struct_assignment_copies pass 4 lines
// glaurung: struct_assignment_copies @ 0x1130
int32_t struct_assignment_copies(int32_t arg0, int32_t arg1) {
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg1 + (arg1 * 2)))) + (unsigned int)((unsigned char)((arg0 & 255)))))) + (unsigned int)((unsigned char)(((unsigned long)((unsigned int)((arg0 + 1))) & 255)))));
}