Fixture 97
signed unsigned pitfalls
C · 4 functions · 4 lanes · 16 of 16 function-lanes behave identically
All 4 lanes recompile and return the same results as the original.
The classic conversion traps, written with explicit casts so the intent is unambiguous and the build stays warning-clean. Each returns a value that differs from the naive signed reading.
#include <stdint.h>
/* The classic conversion traps, written with explicit casts so the intent is
* unambiguous and the build stays warning-clean. Each returns a value that
* differs from the naive signed reading. */
__attribute__((noinline)) int32_t
negative_compares_greater(int32_t value, uint32_t bound) {
/* -1 converted to unsigned is UINT32_MAX, so it is NOT less than bound. */
return ((uint32_t)value < bound) ? 1 : 0;
}
__attribute__((noinline)) uint32_t
unsigned_subtraction_wraps(uint32_t left, uint32_t right) {
/* Defined modular arithmetic: 3 - 5 is UINT32_MAX - 1. */
return left - right;
}
__attribute__((noinline)) int32_t
size_like_loop(int32_t count) {
uint32_t index;
int32_t iterations = 0;
if (count < 0 || count > 16) {
return -1;
}
/* A reverse loop on an unsigned counter must not test `index >= 0`; this
* one tests the post-decrement value instead. */
for (index = (uint32_t)count; index-- > 0u;) {
iterations += 1;
}
return iterations;
}
__attribute__((noinline)) int32_t
division_truncates_toward_zero(int32_t numerator, int32_t denominator) {
if (denominator == 0 || (numerator == (-2147483647 - 1) && denominator == -1)) {
return 0;
}
/* C99 requires truncation toward zero, so -7/2 is -3 and -7%2 is -1. */
return (numerator / denominator) * 100 + (numerator % denominator);
} 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/4division_truncates_toward_zero pass 21 lines
// glaurung: division_truncates_toward_zero @ 0x11b0
int32_t division_truncates_toward_zero(int32_t arg0, int32_t arg1) {
int local_10;
int local_4;
if (((unsigned long)((unsigned int)(arg1)) != 0)) {
if (((unsigned long)((unsigned int)(arg0)) != 0x80000000)) {
goto L_11e7;
}
if (((unsigned long)((unsigned int)(arg1)) != 0xffffffff)) {
goto L_11e7;
}
}
local_4 = 0;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
L_11e7: ;
local_10 = (((int)((((long long)(int)((((unsigned long)((long)((int)((unsigned long)((unsigned int)(arg0))))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg0)))) / (int)(arg1))) * 100);
local_4 = ((unsigned int)(local_10) + ((int)((((long long)(int)((((unsigned long)((long)((int)((unsigned long)((unsigned int)(arg0))))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg0)))) % (int)(arg1))));
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} negative_compares_greater pass 6 lines
// glaurung: negative_compares_greater @ 0x1100
int32_t negative_compares_greater(int32_t arg0, uint32_t arg1) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (((unsigned long)((unsigned long)((unsigned int)(arg0))) < (unsigned long)((unsigned long)(arg1))) ? 1 : 0);
} size_like_loop pass 31 lines
// glaurung: size_like_loop @ 0x1140
int32_t size_like_loop(int32_t arg0) {
int iterations;
unsigned int index;
int local_4;
long var1;
// x86-64 prologue: save rbp
iterations = 0;
if (((long)(arg0) < 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((((unsigned long)((unsigned int)(arg0)) == 16) | ((long)(arg0) < 16)) == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
index = arg0;
while (1) {
var1 = (unsigned long)(index);
index = (index - 1);
if (((unsigned long)((unsigned long)((unsigned int)(var1))) <= (unsigned long)(0))) {
break;
}
iterations = ((unsigned int)(iterations) + 1);
}
local_4 = iterations;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} unsigned_subtraction_wraps pass 6 lines
// glaurung: unsigned_subtraction_wraps @ 0x1120
uint32_t unsigned_subtraction_wraps(uint32_t arg0, uint32_t arg1) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)(arg0) - arg1));
} clang -O2
4/4division_truncates_toward_zero pass 29 lines
// glaurung: division_truncates_toward_zero @ 0x1130
int32_t division_truncates_toward_zero(int32_t arg0, int32_t arg1) {
long ret;
long var2;
int var3;
int var4;
long var5;
int var6;
ret = 0;
if (((unsigned long)((unsigned int)(arg1)) != 0)) {
if (((unsigned long)((unsigned int)(arg0)) != 0x80000000)) {
var2 = (((unsigned long)((long)(arg0)) >> 32) & 0xffffffff);
var3 = ((int)((((long long)(int)(var2) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg0)))) / (int)(arg1)));
var4 = ((int)((((long long)(int)(var2) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg0)))) % (int)(arg1)));
var5 = ((unsigned long)((unsigned int)(var3)) * 100);
var6 = (var5 + var4);
return (unsigned int)(var6);
}
if (((unsigned long)((unsigned int)(arg1)) != 0xffffffff)) {
var2 = (((unsigned long)((long)(arg0)) >> 32) & 0xffffffff);
var3 = ((int)((((long long)(int)(var2) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg0)))) / (int)(arg1)));
var4 = ((int)((((long long)(int)(var2) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg0)))) % (int)(arg1)));
var5 = ((unsigned long)((unsigned int)(var3)) * 100);
var6 = (var5 + var4);
return (unsigned int)(var6);
}
}
return ret;
} negative_compares_greater pass 4 lines
// glaurung: negative_compares_greater @ 0x1100
int32_t negative_compares_greater(int32_t arg0, uint32_t arg1) {
return ((unsigned long)((unsigned long)((unsigned int)(arg0))) < (unsigned long)((unsigned long)(arg1)));
} size_like_loop pass 4 lines
// glaurung: size_like_loop @ 0x1120
int32_t size_like_loop(int32_t arg0) {
return (((unsigned long)((unsigned long)((unsigned int)(arg0))) < (unsigned long)(17)) ? arg0 : 0xffffffff);
} unsigned_subtraction_wraps pass 4 lines
// glaurung: unsigned_subtraction_wraps @ 0x1110
uint32_t unsigned_subtraction_wraps(uint32_t arg0, uint32_t arg1) {
return (unsigned int)(((unsigned long)(arg0) - arg1));
} gcc -O0
4/4division_truncates_toward_zero pass 17 lines
// glaurung: division_truncates_toward_zero @ 0x116e
int32_t division_truncates_toward_zero(int32_t arg0, int32_t arg1) {
if (((unsigned long)((unsigned int)(arg1)) == 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
if (((unsigned long)((unsigned int)(arg0)) != 0x80000000)) {
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(((int)((((long long)(int)((((unsigned long)((long)((int)((unsigned long)((unsigned int)(arg0))))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg0)))) % (int)(arg1))))) + (((int)((((long long)(int)((((unsigned long)((long)((int)((unsigned long)((unsigned int)(arg0))))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg0)))) / (int)(arg1))) * 100)));
}
if (((unsigned long)((unsigned int)(arg1)) != 0xffffffff)) {
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(((int)((((long long)(int)((((unsigned long)((long)((int)((unsigned long)((unsigned int)(arg0))))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg0)))) % (int)(arg1))))) + (((int)((((long long)(int)((((unsigned long)((long)((int)((unsigned long)((unsigned int)(arg0))))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg0)))) / (int)(arg1))) * 100)));
}
// x86-64 epilogue: restore rbp
return 0;
} negative_compares_greater pass 6 lines
// glaurung: negative_compares_greater @ 0x10f9
int32_t negative_compares_greater(int32_t arg0, uint32_t arg1) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return ((unsigned long)((unsigned long)((unsigned int)(arg0))) < (unsigned long)((unsigned long)(arg1)));
} size_like_loop pass 27 lines
// glaurung: size_like_loop @ 0x112b
int32_t size_like_loop(int32_t arg0) {
int iterations;
unsigned int index;
long var1;
// x86-64 prologue: save rbp
iterations = 0;
if (((long)(arg0) < 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
if (((((unsigned long)((unsigned int)(arg0)) == 16) | ((long)(arg0) < 16)) == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
index = arg0;
while (1) {
var1 = (unsigned long)(index);
index = (index - 1);
if (((unsigned long)((unsigned int)(var1)) == 0)) {
break;
}
iterations = (iterations + 1);
}
// x86-64 epilogue: restore rbp
return (unsigned int)(iterations);
} unsigned_subtraction_wraps pass 6 lines
// glaurung: unsigned_subtraction_wraps @ 0x1115
uint32_t unsigned_subtraction_wraps(uint32_t arg0, uint32_t arg1) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)(arg0) - arg1));
} gcc -O2
4/4division_truncates_toward_zero pass 19 lines
// glaurung: division_truncates_toward_zero @ 0x1140
int32_t division_truncates_toward_zero(int32_t arg0, int32_t arg1) {
long t70;
long var1;
var1 = 0;
if (((unsigned long)((unsigned int)(arg1)) != 0)) {
if (((unsigned long)((unsigned int)(arg0)) != 0x80000000)) {
t70 = (((unsigned long)((long)(arg0)) >> 32) & 0xffffffff);
var1 = (unsigned long)((unsigned int)(((((int)((((long long)(int)(t70) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg0)))) / (int)(arg1))) * 100) + ((int)((((long long)(int)(t70) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg0)))) % (int)(arg1))))));
return (unsigned int)(var1);
}
if (((unsigned long)((unsigned int)(arg1)) == 0xffffffff)) {
return (unsigned int)(var1);
}
t70 = (((unsigned long)((long)(arg0)) >> 32) & 0xffffffff);
var1 = (unsigned long)((unsigned int)(((((int)((((long long)(int)(t70) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg0)))) / (int)(arg1))) * 100) + ((int)((((long long)(int)(t70) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg0)))) % (int)(arg1))))));
}
return (unsigned int)(var1);
} negative_compares_greater pass 4 lines
// glaurung: negative_compares_greater @ 0x1100
int32_t negative_compares_greater(int32_t arg0, uint32_t arg1) {
return ((unsigned long)((unsigned long)((unsigned int)(arg0))) < (unsigned long)((unsigned long)(arg1)));
} size_like_loop pass 8 lines
// glaurung: size_like_loop @ 0x1120
int32_t size_like_loop(int32_t arg0) {
int iterations;
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg0))))) {
return 0xffffffff;
}
return (unsigned int)(arg0);
} unsigned_subtraction_wraps pass 4 lines
// glaurung: unsigned_subtraction_wraps @ 0x1110
uint32_t unsigned_subtraction_wraps(uint32_t arg0, uint32_t arg1) {
return (unsigned int)(((unsigned long)(arg0) - arg1));
}