Fixture 144
inline asm
C · 4 functions · 4 lanes · 16 of 16 function-lanes behave identically
All 4 lanes recompile and return the same results as the original.
Inline assembly is a region the compiler does not model: the decompiler sees instructions with no source-level intent, and the constraints decide which registers are read, written and clobbered. Guarded per architecture with a portable fallback so every lane of the cross-architecture matrix builds.
#include <stdint.h>
/* Inline assembly is a region the compiler does not model: the decompiler sees
* instructions with no source-level intent, and the constraints decide which
* registers are read, written and clobbered. Guarded per architecture with a
* portable fallback so every lane of the cross-architecture matrix builds. */
__attribute__((noinline)) int32_t asm_add_via_constraints(int32_t left,
int32_t right) {
#if defined(__x86_64__) || defined(__i386__)
int32_t result = left;
__asm__("addl %1, %0" : "+r"(result) : "r"(right) : "cc");
return result;
#elif defined(__aarch64__)
int32_t result;
__asm__("add %w0, %w1, %w2" : "=r"(result) : "r"(left), "r"(right));
return result;
#elif defined(__arm__)
int32_t result;
__asm__("add %0, %1, %2" : "=r"(result) : "r"(left), "r"(right));
return result;
#else
return (int32_t)((uint32_t)left + (uint32_t)right);
#endif
}
__attribute__((noinline)) int32_t asm_memory_barrier(int32_t *cell,
int32_t value) {
if (cell == 0) {
return -1;
}
*cell = value;
/* A full compiler barrier: no memory operation may be moved across it. */
__asm__ __volatile__("" ::: "memory");
*cell += 1;
return *cell;
}
__attribute__((noinline)) int32_t builtin_bit_intrinsics(uint32_t value,
int32_t which) {
switch (which & 3) {
case 0:
/* clz is undefined at zero, so the zero case is spelled out. */
return (value == 0u) ? 32 : __builtin_clz(value);
case 1:
return (value == 0u) ? 32 : __builtin_ctz(value);
case 2:
return (int32_t)__builtin_popcount(value);
default:
return (int32_t)__builtin_bswap32(value);
}
}
__attribute__((noinline)) int32_t builtin_overflow_checked(int32_t left,
int32_t right,
int32_t *result) {
if (result == 0) {
return -1;
}
/* Returns 1 on overflow without ever executing signed overflow itself. */
if (__builtin_add_overflow(left, right, result)) {
*result = 0;
return 1;
}
return 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
4/4asm_add_via_constraints pass 9 lines
// glaurung: asm_add_via_constraints @ 0x1100
int32_t asm_add_via_constraints(int32_t arg0, int32_t arg1) {
int result;
// x86-64 prologue: save rbp
result = arg0;
result = ((unsigned int)(result) + (unsigned int)(arg1));
// x86-64 epilogue: restore rbp
return (unsigned int)(result);
} asm_memory_barrier pass 11 lines
// glaurung: asm_memory_barrier @ 0x1120
int32_t asm_memory_barrier(int32_t * arg0, int32_t arg1) {
// x86-64 prologue: save rbp
if ((arg0 != 0)) {
*(int *)((long)arg0) = arg1;
*(int *)((long)arg0) = ((unsigned long)((unsigned int)(*(int *)((long)arg0))) + 1);
return (unsigned int)(*(int *)((long)arg0));
} else {
return (unsigned int)(-1);
}
} builtin_bit_intrinsics pass 25 lines
// glaurung: builtin_bit_intrinsics @ 0x1170
int32_t builtin_bit_intrinsics(uint32_t arg0, int32_t arg1) {
int local_10;
int var1;
long var27;
int var36;
// x86-64 prologue: save rbp
var1 = ((unsigned int)(arg1) & 3);
local_10 = var1;
if (((unsigned long)((unsigned int)(var1)) == 0)) {
return (unsigned int)(((unsigned long)(arg0) != 0) ? ((31 - (((unsigned int)((unsigned long)((unsigned int)((unsigned long)(arg0)))) == 0) ? 32 : __builtin_clz((unsigned int)((unsigned long)((unsigned int)((unsigned long)(arg0))))))) ^ 31) : 32);
} else {
if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(local_10)) - 1))) == 0)) {
return (unsigned int)(((unsigned long)(arg0) != 0) ? (31 - (((unsigned int)(((unsigned long)((unsigned int)((unsigned long)(arg0))) ^ ((unsigned long)((unsigned int)((unsigned long)(arg0))) - 1))) == 0) ? 32 : __builtin_clz((unsigned int)(((unsigned long)((unsigned int)((unsigned long)(arg0))) ^ ((unsigned long)((unsigned int)((unsigned long)(arg0))) - 1)))))) : 32);
} else {
if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(local_10)) - 2))) == 0)) {
var27 = (unsigned long)((unsigned int)((arg0 - (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(arg0) >> 1))) & 0x55555555))))));
var36 = ((unsigned int)(((unsigned long)((unsigned int)(var27)) & 0x33333333)) + (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var27)) >> 2))) & 0x33333333)));
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var36)) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var36)) >> 4)))))) & 0xf0f0f0f))) * 0x1010101))) >> 24));
} else {
return (unsigned int)((((((arg0 & 255) << 24) | (((arg0 >> 8) & 255) << 16)) | (((arg0 >> 16) & 255) << 8)) | ((arg0 >> 24) & 255)));
}
}
}
} builtin_overflow_checked pass 19 lines
// glaurung: builtin_overflow_checked @ 0x1260
int32_t builtin_overflow_checked(int32_t arg0, int32_t arg1, int32_t * arg2) {
long t143;
int var3;
// x86-64 prologue: save rbp
if ((arg2 != 0)) {
t143 = ((long)(arg0) < 0);
var3 = ((unsigned int)(arg0) + (unsigned int)(arg1));
*(int *)((long)arg2) = var3;
if (((t143 == ((long)(arg1) < 0)) && (((long)((int)(var3)) < 0) != t143))) {
*(int *)((long)arg2) = 0;
return 1;
} else {
return 0;
}
} else {
return (unsigned int)(-1);
}
} clang -O2
4/4asm_add_via_constraints pass 4 lines
// glaurung: asm_add_via_constraints @ 0x1100
int32_t asm_add_via_constraints(int32_t arg0, int32_t arg1) {
return (unsigned int)(((unsigned long)((unsigned int)(arg0)) + arg1));
} asm_memory_barrier pass 11 lines
// glaurung: asm_memory_barrier @ 0x1110
int32_t asm_memory_barrier(int32_t * arg0, int32_t arg1) {
int var1;
if ((arg0 == 0)) {
return 0xffffffff;
}
*(int *)(((long)arg0)) = arg1;
var1 = ((unsigned int)(*(int *)(((long)arg0))) + 1);
*(int *)(((long)arg0)) = var1;
return (unsigned int)(var1);
} builtin_bit_intrinsics pass 27 lines
// glaurung: builtin_bit_intrinsics @ 0x1130
int32_t builtin_bit_intrinsics(uint32_t arg0, int32_t arg1) {
long var1;
long var11;
int var20;
var1 = (unsigned long)((unsigned int)((arg1 & 3)));
if (((unsigned long)((unsigned int)(var1)) != 2)) {
if (((unsigned long)((unsigned int)(var1)) == 1)) {
goto L_117f;
}
if (((unsigned long)((unsigned int)(var1)) != 0)) {
return (unsigned int)((((((arg0 & 255) << 24) | (((arg0 >> 8) & 255) << 16)) | (((arg0 >> 16) & 255) << 8)) | ((arg0 >> 24) & 255)));
}
if ((arg0 == 0)) {
return 32;
}
return (unsigned int)(((31 - (((unsigned int)((unsigned long)(arg0)) == 0) ? 32 : __builtin_clz((unsigned int)((unsigned long)(arg0))))) ^ 31));
}
var11 = (unsigned long)((unsigned int)((arg0 - (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(arg0) >> 1))) & 0x55555555))))));
var20 = ((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var11)) >> 2))) & 0x33333333)) + (unsigned int)(((unsigned long)((unsigned int)(var11)) & 0x33333333)));
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var20)) >> 4))) + (unsigned long)((unsigned int)(var20))))) & 0xf0f0f0f))) * 0x1010101))) >> 24));
L_117f: ;
if ((arg0 == 0)) {
return 32;
}
return (31 - (((unsigned int)(((unsigned long)(arg0) ^ ((unsigned long)(arg0) - 1))) == 0) ? 32 : __builtin_clz((unsigned int)(((unsigned long)(arg0) ^ ((unsigned long)(arg0) - 1))))));
} builtin_overflow_checked pass 12 lines
// glaurung: builtin_overflow_checked @ 0x11a0
int32_t builtin_overflow_checked(int32_t arg0, int32_t arg1, int32_t * arg2) {
long t33;
int var4;
if ((arg2 == 0)) {
return 0xffffffff;
}
t33 = ((long)(arg0) < 0);
var4 = (arg0 + arg1);
*(int *)(((long)arg2)) = (((t33 == ((long)(arg1) < 0)) & (((long)((int)(var4)) < 0) != t33)) ? 0 : (unsigned long)((unsigned int)(var4)));
return (((t33 == ((long)(arg1) < 0)) & (((long)((int)(var4)) < 0) != t33)) & 255);
} gcc -O0
4/4asm_add_via_constraints pass 9 lines
// glaurung: asm_add_via_constraints @ 0x10f9
int32_t asm_add_via_constraints(int32_t arg0, int32_t arg1) {
int result;
// x86-64 prologue: save rbp
result = arg0;
result = ((unsigned int)(result) + (unsigned int)(arg1));
// x86-64 epilogue: restore rbp
return (unsigned int)(result);
} asm_memory_barrier pass 11 lines
// glaurung: asm_memory_barrier @ 0x111d
int32_t asm_memory_barrier(int32_t * arg0, int32_t arg1) {
// x86-64 prologue: save rbp
if ((arg0 != 0)) {
*(int *)((long)arg0) = arg1;
*(int *)((long)arg0) = ((unsigned long)((unsigned int)(*(int *)((long)arg0))) + 1);
return (unsigned int)(*(int *)((long)arg0));
} else {
return 0xffffffff;
}
} builtin_bit_intrinsics pass 37 lines
// glaurung: builtin_bit_intrinsics @ 0x115a
int32_t builtin_bit_intrinsics(uint32_t arg0, int32_t arg1) {
extern unsigned long __popcountdi2(unsigned long);
long var2;
unsigned long var4;
long var7;
// x86-64 prologue: save rbp, frame 16 bytes
var2 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) & 3)));
if (((unsigned long)((unsigned int)(var2)) == 2)) {
var4 = __popcountdi2(arg0);
return var4;
} else {
if (((((unsigned long)((unsigned int)(var2)) == 2) | ((long)((int)(var2)) < 2)) == 0)) {
var7 = (unsigned int)((((((arg0 & 255) << 24) | (((arg0 >> 8) & 255) << 16)) | (((arg0 >> 16) & 255) << 8)) | ((arg0 >> 24) & 255)));
// x86-64 epilogue: restore rbp
return var7;
}
if (((unsigned long)((unsigned int)(var2)) == 0)) {
if ((arg0 == 0)) {
return 32;
} else {
return (unsigned int)(((31 - (((unsigned int)((unsigned long)(arg0)) == 0) ? 32 : __builtin_clz((unsigned int)((unsigned long)(arg0))))) ^ 31));
}
} else {
if (((unsigned long)((unsigned int)(var2)) == 1)) {
if ((arg0 == 0)) {
return 32;
} else {
return (((unsigned int)((unsigned long)(arg0)) == 0) ? 32 : __builtin_ctz((unsigned int)((unsigned long)(arg0))));
}
} else {
var7 = (unsigned int)((((((arg0 & 255) << 24) | (((arg0 >> 8) & 255) << 16)) | (((arg0 >> 16) & 255) << 8)) | ((arg0 >> 24) & 255)));
return var7;
}
}
}
} builtin_overflow_checked pass 26 lines
// glaurung: builtin_overflow_checked @ 0x11c7
int32_t builtin_overflow_checked(int32_t arg0, int32_t arg1, int32_t * arg2) {
long t142;
int var0;
int var3;
long var4;
// x86-64 prologue: save rbp
if ((arg2 != 0)) {
var0 = 0;
t142 = ((long)(arg1) < 0);
var3 = ((unsigned int)(arg1) + (unsigned int)(arg0));
var4 = (unsigned long)((unsigned int)(var3));
if ((((t142 == ((long)(arg0) < 0)) & (((long)((int)(var3)) < 0) != t142)) != 0)) {
var0 = 1;
}
*(int *)((long)arg2) = var4;
if (((unsigned long)((unsigned char)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var0)) & 1))) & 255))) == 0)) {
return 0;
} else {
*(int *)((long)arg2) = 0;
return 1;
}
} else {
return 0xffffffff;
}
} gcc -O2
4/4asm_add_via_constraints pass 4 lines
// glaurung: asm_add_via_constraints @ 0x1100
int32_t asm_add_via_constraints(int32_t arg0, int32_t arg1) {
return (unsigned int)(((unsigned long)((unsigned int)(arg0)) + arg1));
} asm_memory_barrier pass 11 lines
// glaurung: asm_memory_barrier @ 0x1110
int32_t asm_memory_barrier(int32_t * arg0, int32_t arg1) {
int var1;
if ((arg0 == 0)) {
return 0xffffffff;
}
*(int *)(((long)arg0)) = arg1;
var1 = ((unsigned int)(*(int *)(((long)arg0))) + 1);
*(int *)(((long)arg0)) = var1;
return (unsigned int)(var1);
} builtin_bit_intrinsics pass 23 lines
// glaurung: builtin_bit_intrinsics @ 0x1130
int32_t builtin_bit_intrinsics(uint32_t arg0, int32_t arg1) {
extern unsigned long __popcountdi2(unsigned long);
unsigned long ret;
long var1;
var1 = (unsigned long)((unsigned int)((arg1 & 3)));
if (((unsigned long)((unsigned int)(var1)) == 1)) {
return (((unsigned long)(arg0) == 0) ? 32 : (((unsigned int)((unsigned long)(arg0)) == 0) ? 32 : __builtin_ctz((unsigned int)((unsigned long)(arg0)))));
}
if (((unsigned long)((unsigned int)(var1)) == 2)) {
ret = __popcountdi2(arg0);
return ret;
}
ret = (unsigned int)((((((arg0 & 255) << 24) | (((arg0 >> 8) & 255) << 16)) | (((arg0 >> 16) & 255) << 8)) | ((arg0 >> 24) & 255)));
if (((unsigned long)((unsigned int)(var1)) != 0)) {
return ret;
}
ret = 32;
if ((arg0 != 0)) {
return (unsigned int)(((31 - (((unsigned int)((unsigned long)(arg0)) == 0) ? 32 : __builtin_clz((unsigned int)((unsigned long)(arg0))))) ^ 31));
}
return 32;
} builtin_overflow_checked pass 14 lines
// glaurung: builtin_overflow_checked @ 0x1190
int32_t builtin_overflow_checked(int32_t arg0, int32_t arg1, int32_t * arg2) {
long ret;
long t33;
int var2;
if ((arg2 == 0)) {
return 0xffffffff;
}
t33 = ((long)(arg0) < 0);
var2 = (arg0 + arg1);
ret = (((t33 == ((long)(arg1) < 0)) & (((long)((int)(var2)) < 0) != t33)) & 255);
*(int *)(((long)arg2)) = (((unsigned long)((unsigned int)(ret)) != 0) ? 0 : (unsigned long)((unsigned int)(var2)));
return ret;
}