Fixture 174
float compare classify
C · 7 functions · 4 lanes · 15 of 28 function-lanes behave identically
4 of 4 lanes have a function that returns a different result after decompilation: clang-O2 (1/7), gcc-O0 (4/7), gcc-O2 (4/7), clang-O0 (6/7).
Floating-point comparison and classification.
Two things here are invisible to an integer corpus. First, a float compare has FOUR outcomes, not three: <, >, == and UNORDERED, the last of which makes every one of the first three false at once. On x86 that is the parity flag, and a recovery that lowers ucomiss as if it were cmp produces code that is right on ordered inputs and wrong on unordered ones. Second, zero has a sign: -0.0 == 0.0 is true while their bit patterns differ, so a recovery that folds one into the other is invisible to a value comparison and caught immediately by a bitwise one.
The NaN is BUILT FROM ITS BIT PATTERN rather than by dividing zero by zero. A bit pattern is exact and unconditionally defined; 0.0/0.0 is defined only through Annex F, and a fixture should not depend on an annex to be free of undefined behaviour. Its payload is taken from the input so the value is not a compile-time constant and the comparison is really performed.
#include <stdint.h>
#include <string.h>
/* Floating-point comparison and classification.
*
* Two things here are invisible to an integer corpus. First, a float compare
* has FOUR outcomes, not three: `<`, `>`, `==` and UNORDERED, the last of which
* makes every one of the first three false at once. On x86 that is the parity
* flag, and a recovery that lowers `ucomiss` as if it were `cmp` produces code
* that is right on ordered inputs and wrong on unordered ones. Second, zero
* has a sign: `-0.0 == 0.0` is true while their bit patterns differ, so a
* recovery that folds one into the other is invisible to a value comparison and
* caught immediately by a bitwise one.
*
* The NaN is BUILT FROM ITS BIT PATTERN rather than by dividing zero by zero.
* A bit pattern is exact and unconditionally defined; `0.0/0.0` is defined only
* through Annex F, and a fixture should not depend on an annex to be free of
* undefined behaviour. Its payload is taken from the input so the value is not
* a compile-time constant and the comparison is really performed. */
#define FP174_QUIET_NAN_BITS 0x7FC00000u
#define FP174_SIGN_MASK 0x80000000u
#define FP174_EXPONENT_MASK 0x7F800000u
#define FP174_MANTISSA_MASK 0x007FFFFFu
/* Class codes returned by `classify_binary32`. */
#define FP174_CLASS_ZERO 0
#define FP174_CLASS_SUBNORMAL 1
#define FP174_CLASS_NORMAL 2
#define FP174_CLASS_INFINITE 3
#define FP174_CLASS_NAN 4
_Static_assert(sizeof(float) == sizeof(uint32_t), "binary32 is four bytes");
/* `memcpy` rather than a union or a cast: it is the one spelling that is
* defined regardless of the aliasing rules the optimiser is applying, and both
* compilers turn a four-byte copy into a single register move. */
static uint32_t fp174_float_bits(float value) {
uint32_t bits;
memcpy(&bits, &value, sizeof bits);
return bits;
}
static float fp174_bits_to_float(uint32_t bits) {
float value;
memcpy(&value, &bits, sizeof value);
return value;
}
/* -1 / 0 / 1 as usual, and 2 for the fourth outcome an integer compare does not
* have. Reachable only when an operand is a NaN, which arithmetic inside a
* caller can produce from finite inputs. */
__attribute__((noinline)) int32_t ordered_compare_binary32(float left,
float right) {
if (left < right) {
return -1;
}
if (left > right) {
return 1;
}
if (left == right) {
return 0;
}
return 2;
}
/* Every relational operator against a quiet NaN, as a bitmask. The answer is
* always 8 (`!=` alone is true), so any other value from either side is a
* mis-lowered unordered compare rather than a disagreement about arithmetic. */
__attribute__((noinline)) int32_t unordered_compare_flags(float value) {
uint32_t payload = fp174_float_bits(value) & FP174_MANTISSA_MASK;
float nan_value = fp174_bits_to_float(FP174_QUIET_NAN_BITS | payload);
int32_t flags = 0;
if (value < nan_value) {
flags |= 1;
}
if (value > nan_value) {
flags |= 2;
}
if (value == nan_value) {
flags |= 4;
}
if (value != nan_value) {
flags |= 8;
}
if (value <= nan_value) {
flags |= 16;
}
if (value >= nan_value) {
flags |= 32;
}
return flags;
}
/* The sign bit itself, which is the only way to tell -0.0 from 0.0. */
__attribute__((noinline)) int32_t sign_bit_of_binary32(float value) {
return (int32_t)((fp174_float_bits(value) & FP174_SIGN_MASK) >> 31);
}
/* Negation is a sign-bit flip, not a subtraction from zero: `-(0.0f)` is
* `-0.0f`, while `0.0f - 0.0f` is `+0.0f`. The bit-exact return comparison is
* what makes the difference observable. */
__attribute__((noinline)) float negate_binary32(float value) {
return -value;
}
__attribute__((noinline)) float absolute_binary32(float value) {
return fp174_bits_to_float(fp174_float_bits(value) & ~FP174_SIGN_MASK);
}
__attribute__((noinline)) int32_t classify_binary32(float value) {
uint32_t bits = fp174_float_bits(value);
uint32_t exponent = bits & FP174_EXPONENT_MASK;
uint32_t mantissa = bits & FP174_MANTISSA_MASK;
if (exponent == FP174_EXPONENT_MASK) {
return (mantissa != 0u) ? FP174_CLASS_NAN : FP174_CLASS_INFINITE;
}
if (exponent == 0u) {
return (mantissa != 0u) ? FP174_CLASS_SUBNORMAL : FP174_CLASS_ZERO;
}
return FP174_CLASS_NORMAL;
}
/* A signed zero the harness cannot hand in directly: multiplying by zero keeps
* the operand's sign, so a negative input yields -0.0 and a positive one +0.0,
* and the two are `==` but not identical. An infinite input yields a NaN
* instead, which the guard rejects with -1. */
__attribute__((noinline)) int32_t zero_sign_from_product(float value) {
float product = value * 0.0f;
if (!(product == 0.0f)) {
return -1;
}
return (fp174_float_bits(product) == fp174_float_bits(0.0f)) ? 0 : 1;
} 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 -O2
1/7absolute_binary32 fail 5 lines
// glaurung: absolute_binary32 @ 0x11b0
float absolute_binary32(float arg0) {
long var2;
return ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(((var2 & 0x7fffffff) | (arg0 & 0x7fffffff))) }).value;
} classify_binary32 pass 18 lines
// glaurung: classify_binary32 @ 0x11c0
int32_t classify_binary32(float arg0) {
unsigned int bits;
unsigned int exponent;
long ret;
long var0;
int var2;
var0 = (unsigned long)((unsigned int)(((union { unsigned int bits; float value; }){ .value = arg0 }).bits));
var2 = ((unsigned int)(((union { unsigned int bits; float value; }){ .value = arg0 }).bits) & 0x7f800000);
if (((unsigned long)((unsigned int)(var2)) == 0)) {
return ((unsigned long)((unsigned int)((var0 & 0x7fffff))) != 0);
}
ret = 2;
if (((unsigned long)((unsigned int)(var2)) != 0x7f800000)) {
return ret;
}
return (unsigned int)((4 - ((unsigned long)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((union { unsigned int bits; float value; }){ .value = arg0 }).bits)) & 0x7fffff)))) < (unsigned long)(1))));
} negate_binary32 fail 5 lines
// glaurung: negate_binary32 @ 0x11a0
float negate_binary32(float arg0) {
long var2;
return ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(((var2 ^ 0x80000000) | (arg0 ^ 0x80000000))) }).value;
} ordered_compare_binary32 fail 16 lines
// glaurung: ordered_compare_binary32 @ 0x1100
int32_t ordered_compare_binary32(float arg0, float arg1) {
long ret;
long var1;
long var3;
ret = 0xffffffff;
if (((((arg1 < arg0) | ((arg1 != arg1) | (arg0 != arg0))) | ((arg1 == arg0) | ((arg1 != arg1) | (arg0 != arg0)))) != 0)) {
ret = 1;
if (((((arg0 < arg1) | ((arg0 != arg0) | (arg1 != arg1))) | ((arg0 == arg1) | ((arg0 != arg0) | (arg1 != arg1)))) != 0)) {
/* asm: cmpss */
var3 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var1)) & 1)));
ret = (unsigned long)((unsigned int)((var3 + var3)));
}
}
return ret;
} sign_bit_of_binary32 fail 7 lines
// glaurung: sign_bit_of_binary32 @ 0x1190
int32_t sign_bit_of_binary32(float arg0) {
long var3;
long var5;
long var7;
return (unsigned int)((((((arg0 < 0) | ((var3 < 0) << 1)) | ((var5 < 0) << 2)) | ((var7 < 0) << 3)) & 1));
} unordered_compare_flags fail 19 lines
// glaurung: unordered_compare_flags @ 0x1130
int32_t unordered_compare_flags(float arg0) {
int flags;
float nan_value;
long var1;
long var10;
long var14;
long var18;
int var23;
var10 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var1)) & 0x3fffff))) | 0x7fc00000)));
flags = ((((var10 < arg0) | ((var10 != var10) | (arg0 != arg0))) | ((var10 == arg0) | ((var10 != var10) | (arg0 != arg0)))) == 0);
var14 = ((((arg0 < var10) | ((arg0 != arg0) | (var10 != var10))) | ((arg0 == var10) | ((arg0 != arg0) | (var10 != var10)))) ? flags : (unsigned long)((unsigned int)((flags + 2))));
flags = (((var10 != var10) | (arg0 != arg0)) ? var14 : ((((var10 == arg0) | ((var10 != var10) | (arg0 != arg0))) == 0) ? var14 : (unsigned long)((unsigned int)((var14 + 4)))));
var18 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(flags)) | 8)));
flags = (((var10 != var10) | (arg0 != arg0)) ? var18 : ((((var10 == arg0) | ((var10 != var10) | (arg0 != arg0))) == 0) ? var18 : flags));
var23 = (((var10 < arg0) | ((var10 != var10) | (arg0 != arg0))) ? flags : (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(flags)) | 16))));
flags = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var23)) | 32)));
return (((arg0 < var10) | ((arg0 != arg0) | (var10 != var10))) ? var23 : flags);
} zero_sign_from_product fail 5 lines
// glaurung: zero_sign_from_product @ 0x1200
int32_t zero_sign_from_product(float arg0) {
float product;
return 0;
} gcc -O0
4/7absolute_binary32 fail 12 lines
// glaurung: absolute_binary32 @ 0x12ec
float absolute_binary32(float arg0) {
extern float fp174_bits_to_float(unsigned int);
extern unsigned int fp174_float_bits(float);
float ret;
unsigned int var5;
// x86-64 prologue: save rbp, frame 16 bytes
var5 = fp174_float_bits(arg0);
ret = fp174_bits_to_float((unsigned long)((unsigned int)((var5 & 0x7fffffff))));
// x86-64 epilogue: restore rbp
return ret;
} classify_binary32 pass 26 lines
// glaurung: classify_binary32 @ 0x1317
int32_t classify_binary32(float arg0) {
extern unsigned int fp174_float_bits(float);
unsigned int bits;
unsigned int exponent;
unsigned int mantissa;
unsigned int var5;
// x86-64 prologue: save rbp, frame 32 bytes
var5 = fp174_float_bits(arg0);
bits = var5;
exponent = (bits & 0x7f800000);
mantissa = (bits & 0x7fffff);
if ((exponent != 0x7f800000)) {
if ((exponent != 0)) {
return 2;
} else {
return ((unsigned long)(mantissa) != 0);
}
} else {
if ((mantissa == 0)) {
return 3;
} else {
return 4;
}
}
} negate_binary32 pass 7 lines
// glaurung: negate_binary32 @ 0x12cd
float negate_binary32(float arg0) {
// x86-64 prologue: save rbp
arg0 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(((unsigned int)(((union { unsigned int bits; float value; }){ .value = arg0 }).bits) ^ 0x80000000)) }).value;
// x86-64 epilogue: restore rbp
return arg0;
} ordered_compare_binary32 pass 21 lines
// glaurung: ordered_compare_binary32 @ 0x1197
int32_t ordered_compare_binary32(float arg0, float arg1) {
// x86-64 prologue: save rbp
if ((((arg1 < arg0) | ((arg1 != arg1) | (arg0 != arg0))) | ((arg1 == arg0) | ((arg1 != arg1) | (arg0 != arg0))))) {
if ((((arg0 < arg1) | ((arg0 != arg0) | (arg1 != arg1))) | ((arg0 == arg1) | ((arg0 != arg0) | (arg1 != arg1))))) {
if (((arg0 != arg0) | (arg1 != arg1))) {
// x86-64 epilogue: restore rbp
return 2;
}
if ((((arg0 == arg1) | ((arg0 != arg0) | (arg1 != arg1))) == 0)) {
// x86-64 epilogue: restore rbp
return 2;
}
return 0;
} else {
return 1;
}
} else {
return 0xffffffff;
}
} sign_bit_of_binary32 pass 9 lines
// glaurung: sign_bit_of_binary32 @ 0x12a8
int32_t sign_bit_of_binary32(float arg0) {
extern unsigned int fp174_float_bits(float);
unsigned int var5;
// x86-64 prologue: save rbp, frame 16 bytes
var5 = fp174_float_bits(arg0);
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var5)) >> 31))) & 1));
} unordered_compare_flags fail 45 lines
// glaurung: unordered_compare_flags @ 0x11f1
int32_t unordered_compare_flags(float arg0) {
extern float fp174_bits_to_float(unsigned int);
extern unsigned int fp174_float_bits(float);
unsigned int payload;
float nan_value;
int flags;
float var12;
unsigned int var5;
// x86-64 prologue: save rbp, frame 32 bytes
var5 = fp174_float_bits(arg0);
payload = (var5 & 0x7fffff);
var12 = fp174_bits_to_float((unsigned long)((unsigned int)((payload | 0x7fc00000))));
nan_value = var12;
flags = 0;
if (((((nan_value < arg0) | ((nan_value != nan_value) | (arg0 != arg0))) | ((nan_value == arg0) | ((nan_value != nan_value) | (arg0 != arg0)))) == 0)) {
flags = (flags | 1);
}
if (((((arg0 < nan_value) | ((arg0 != arg0) | (nan_value != nan_value))) | ((arg0 == nan_value) | ((arg0 != arg0) | (nan_value != nan_value)))) == 0)) {
flags = (flags | 2);
}
if ((((arg0 != arg0) | (nan_value != nan_value)) == 0)) {
if ((((arg0 == nan_value) | ((arg0 != arg0) | (nan_value != nan_value))) != 0)) {
flags = (flags | 4);
}
}
if (((arg0 != arg0) | (nan_value != nan_value))) {
L_1281: ;
flags = (flags | 8);
} else {
if (((arg0 == nan_value) | ((arg0 != arg0) | (nan_value != nan_value)))) {
goto L_1285;
}
goto L_1281;
}
L_1285: ;
if ((((nan_value < arg0) | ((nan_value != nan_value) | (arg0 != arg0))) == 0)) {
flags = (flags | 16);
}
if ((((arg0 < nan_value) | ((arg0 != arg0) | (nan_value != nan_value))) == 0)) {
flags = (flags | 32);
}
// x86-64 epilogue: restore rbp
return (unsigned int)(flags);
} zero_sign_from_product fail 23 lines
// glaurung: zero_sign_from_product @ 0x1383
int32_t zero_sign_from_product(float arg0) {
extern unsigned int fp174_float_bits(float);
float product;
unsigned int var28;
long var30;
unsigned int var36;
// x86-64 prologue: save rbp, frame 8 bytes
product = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
if ((product != product)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
if ((((0 == product) | (product != product)) == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
var28 = fp174_float_bits((float)(((union { unsigned int bits; float value; }){ .bits = (unsigned int)((unsigned long)((unsigned int)(((union { unsigned int bits; float value; }){ .value = product }).bits))) }).value));
var30 = (unsigned long)(var28);
var36 = fp174_float_bits((float)(((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value));
// x86-64 epilogue: restore rbp
return ((unsigned int)(var30) != (unsigned int)(var36));
} gcc -O2
4/7absolute_binary32 pass 4 lines
// glaurung: absolute_binary32 @ 0x11b0
float absolute_binary32(float arg0) {
return ((union { unsigned int bits; float value; }){ .bits = (unsigned int)((unsigned int)(((unsigned long)((unsigned int)(((union { unsigned int bits; float value; }){ .value = arg0 }).bits)) & 0x7fffffff))) }).value;
} classify_binary32 pass 15 lines
// glaurung: classify_binary32 @ 0x11d0
int32_t classify_binary32(float arg0) {
unsigned int exponent;
unsigned int mantissa;
unsigned int bits;
exponent = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((union { unsigned int bits; float value; }){ .value = arg0 }).bits)) & 0x7f800000)));
mantissa = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((union { unsigned int bits; float value; }){ .value = arg0 }).bits)) & 0x7fffff)));
if ((exponent == 0x7f800000)) {
return (unsigned int)((4 - ((unsigned long)((unsigned long)(mantissa)) < (unsigned long)(1))));
}
if ((exponent == 0)) {
return ((unsigned long)(mantissa) != 0);
}
return 2;
} negate_binary32 fail 5 lines
// glaurung: negate_binary32 @ 0x11a0
float negate_binary32(float arg0) {
long var2;
return ((union { unsigned int bits; float value; }){ .bits = (unsigned int)((var2 | (arg0 ^ 0x80000000))) }).value;
} ordered_compare_binary32 pass 14 lines
// glaurung: ordered_compare_binary32 @ 0x1100
int32_t ordered_compare_binary32(float arg0, float arg1) {
long ret;
int var4;
if (((((arg1 < arg0) | ((arg1 != arg1) | (arg0 != arg0))) | ((arg1 == arg0) | ((arg1 != arg1) | (arg0 != arg0)))) == 0)) {
return 0xffffffff;
}
ret = 1;
if (((((arg0 < arg1) | ((arg0 != arg0) | (arg1 != arg1))) | ((arg0 == arg1) | ((arg0 != arg0) | (arg1 != arg1)))) == 0)) {
return ret;
}
var4 = (((arg0 == arg1) | ((arg0 != arg0) | (arg1 != arg1))) ? (((arg0 != arg0) | (arg1 != arg1)) & 255) : 1);
return (unsigned int)((var4 + var4));
} sign_bit_of_binary32 pass 4 lines
// glaurung: sign_bit_of_binary32 @ 0x1190
int32_t sign_bit_of_binary32(float arg0) {
return (unsigned int)(((unsigned long)((unsigned int)(((union { unsigned int bits; float value; }){ .value = arg0 }).bits)) >> 31));
} unordered_compare_flags fail 47 lines
// glaurung: unordered_compare_flags @ 0x1130
int32_t unordered_compare_flags(float arg0) {
int flags;
float nan_value;
unsigned int payload;
int local_4;
long var1;
long var10;
long var14;
long zf_10;
local_4 = var1;
var10 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((0x7fffff & local_4))) | 0x7fc00000)));
flags = ((((var10 < arg0) | ((var10 != var10) | (arg0 != arg0))) | ((var10 == arg0) | ((var10 != var10) | (arg0 != arg0)))) == 0);
if ((((arg0 < var10) | ((arg0 != arg0) | (var10 != var10))) | ((arg0 == var10) | ((arg0 != arg0) | (var10 != var10))))) {
goto L_1168;
}
flags = (unsigned long)((unsigned int)((flags | 10)));
var14 = flags;
if ((((var10 < arg0) | ((var10 != var10) | (arg0 != arg0))) == 0)) {
goto L_1172;
}
L_1161: ;
return (unsigned int)((flags | 32));
L_1168: ;
zf_10 = ((arg0 == var10) | ((arg0 != arg0) | (var10 != var10)));
if (((arg0 != arg0) | (var10 != var10))) {
goto L_117b;
}
if ((zf_10 == 0)) {
goto L_117b;
}
var14 = (unsigned long)((unsigned int)((flags | 4)));
L_1172: ;
flags = (unsigned long)((unsigned int)((var14 | 16)));
L_1175: ;
if ((((arg0 < var10) | ((arg0 != arg0) | (var10 != var10))) == 0)) {
goto L_1161;
}
return flags;
L_117b: ;
flags = (unsigned long)((unsigned int)((flags | 8)));
if (((var10 < arg0) | ((var10 != var10) | (arg0 != arg0)))) {
goto L_1175;
}
var14 = flags;
goto L_1172;
} zero_sign_from_product fail 13 lines
// glaurung: zero_sign_from_product @ 0x1230
int32_t zero_sign_from_product(float arg0) {
float product;
int var6;
var6 = 0;
if (0) {
return 0xffffffff;
}
if (1) {
return ((unsigned long)((unsigned int)(var6)) != 0);
}
return 0xffffffff;
} clang -O0
6/7absolute_binary32 pass 12 lines
// glaurung: absolute_binary32 @ 0x1300
float absolute_binary32(float arg0) {
extern float fp174_bits_to_float(unsigned int);
extern unsigned int fp174_float_bits(float);
unsigned int var5;
float var9;
// x86-64 prologue: save rbp, frame 16 bytes
var5 = fp174_float_bits(arg0);
var9 = fp174_bits_to_float((unsigned long)((unsigned int)((var5 & 0x7fffffff))));
// x86-64 epilogue: restore rbp
return var9;
} classify_binary32 pass 22 lines
// glaurung: classify_binary32 @ 0x1330
int32_t classify_binary32(float arg0) {
extern unsigned int fp174_float_bits(float);
unsigned int bits;
unsigned int exponent;
unsigned int mantissa;
unsigned int var5;
// x86-64 prologue: save rbp, frame 32 bytes
var5 = fp174_float_bits(arg0);
bits = var5;
exponent = (bits & 0x7f800000);
mantissa = (bits & 0x7fffff);
if ((exponent != 0x7f800000)) {
if ((exponent != 0)) {
return 2;
} else {
return (unsigned int)(((unsigned long)(mantissa) != 0) ? 1 : 0);
}
} else {
return (unsigned int)(((unsigned long)(mantissa) != 0) ? 4 : 3);
}
} negate_binary32 pass 6 lines
// glaurung: negate_binary32 @ 0x12e0
float negate_binary32(float arg0) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return ((union { unsigned int bits; float value; }){ .bits = (unsigned int)((unsigned int)(((unsigned long)((unsigned int)(((union { unsigned int bits; float value; }){ .value = arg0 }).bits)) ^ -0x80000000LL))) }).value;
} ordered_compare_binary32 pass 23 lines
// glaurung: ordered_compare_binary32 @ 0x1100
int32_t ordered_compare_binary32(float arg0, float arg1) {
long pf_3;
// x86-64 prologue: save rbp
if ((((arg1 < arg0) | ((arg1 != arg1) | (arg0 != arg0))) | ((arg1 == arg0) | ((arg1 != arg1) | (arg0 != arg0))))) {
if ((((arg0 < arg1) | ((arg0 != arg0) | (arg1 != arg1))) | ((arg0 == arg1) | ((arg0 != arg0) | (arg1 != arg1))))) {
pf_3 = ((arg0 != arg0) | (arg1 != arg1));
if ((((arg0 == arg1) | ((arg0 != arg0) | (arg1 != arg1))) == 0)) {
// x86-64 epilogue: restore rbp
return 2;
}
if (pf_3) {
// x86-64 epilogue: restore rbp
return 2;
}
return 0;
} else {
return 1;
}
} else {
return (unsigned int)(-1);
}
} sign_bit_of_binary32 pass 9 lines
// glaurung: sign_bit_of_binary32 @ 0x12b0
int32_t sign_bit_of_binary32(float arg0) {
extern unsigned int fp174_float_bits(float);
unsigned int var5;
// x86-64 prologue: save rbp, frame 16 bytes
var5 = fp174_float_bits(arg0);
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)((var5 & -0x80000000LL))) >> 31));
} unordered_compare_flags pass 41 lines
// glaurung: unordered_compare_flags @ 0x1180
int32_t unordered_compare_flags(float arg0) {
extern float fp174_bits_to_float(unsigned int);
extern unsigned int fp174_float_bits(float);
unsigned int payload;
float nan_value;
int flags;
long pf_10;
float var11;
unsigned int var5;
// x86-64 prologue: save rbp, frame 16 bytes
var5 = fp174_float_bits(arg0);
payload = (var5 & 0x7fffff);
var11 = fp174_bits_to_float((unsigned long)((unsigned int)((payload | 0x7fc00000))));
nan_value = var11;
flags = 0;
if (((((nan_value < arg0) | ((nan_value != nan_value) | (arg0 != arg0))) | ((nan_value == arg0) | ((nan_value != nan_value) | (arg0 != arg0)))) == 0)) {
flags = ((unsigned int)(flags) | 1);
}
if (((((arg0 < nan_value) | ((arg0 != arg0) | (nan_value != nan_value))) | ((arg0 == nan_value) | ((arg0 != arg0) | (nan_value != nan_value)))) == 0)) {
flags = ((unsigned int)(flags) | 2);
}
pf_10 = ((arg0 != arg0) | (nan_value != nan_value));
if ((((arg0 == nan_value) | ((arg0 != arg0) | (nan_value != nan_value))) != 0)) {
if ((pf_10 == 0)) {
flags = ((unsigned int)(flags) | 4);
}
}
if (((((arg0 == nan_value) | ((arg0 != arg0) | (nan_value != nan_value))) == 0) || ((arg0 != arg0) | (nan_value != nan_value)))) {
flags = ((unsigned int)(flags) | 8);
} else {
}
if ((((nan_value < arg0) | ((nan_value != nan_value) | (arg0 != arg0))) == 0)) {
flags = ((unsigned int)(flags) | 16);
}
if ((((arg0 < nan_value) | ((arg0 != arg0) | (nan_value != nan_value))) == 0)) {
flags = ((unsigned int)(flags) | 32);
}
// x86-64 epilogue: restore rbp
return (unsigned int)(flags);
} zero_sign_from_product fail 28 lines
// glaurung: zero_sign_from_product @ 0x13c0
int32_t zero_sign_from_product(float arg0) {
extern unsigned int fp174_float_bits(float);
float product;
int local_10;
int local_4;
long pf_2;
unsigned int var22;
unsigned int var28;
// x86-64 prologue: save rbp, frame 16 bytes
product = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
pf_2 = (product != product);
if ((((product == 0) | (product != product)) == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (pf_2) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
var22 = fp174_float_bits(product);
local_10 = var22;
var28 = fp174_float_bits((float)(((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value));
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned int)(local_10) == (unsigned int)(var28)) ? 0 : 1);
}