Fixture 172

float double widths

C · 6 functions · 4 lanes · 13 of 24 function-lanes behave identically

4 of 4 lanes have a function that returns a different result after decompilation: gcc-O2 (2/6), clang-O0 (3/6), clang-O2 (4/6), gcc-O0 (4/6).

IEEE binary32 against binary64: the SAME expression at two widths.

Every numeric fixture before this one is Q16.16 fixed point, because the execution differential rejected floating point at signature recovery. So nothing in the corpus ever made the decompiler recover an xmm operand, a float that is not a double, or the widening the ABI inserts between them.

These functions are deliberately paired: single_precision_horner and double_precision_horner are character-for-character the same arithmetic, and a recovery that types every floating value as a double (or reuses one width's constant pool for the other) produces identical C for both — which the bit-exact return comparison then catches on the very first inexact input.

Overflow to an infinity is an IEEE result, not undefined behaviour, so it is left to happen. NARROWING is different: converting a double whose magnitude exceeds the float range is undefined, so it is range-checked first.

tests/decompiler_fixtures/src/172_float_double_widths.c source
#include <stdint.h>

/* IEEE binary32 against binary64: the SAME expression at two widths.
 *
 * Every numeric fixture before this one is Q16.16 fixed point, because the
 * execution differential rejected floating point at signature recovery.  So
 * nothing in the corpus ever made the decompiler recover an xmm operand, a
 * `float` that is not a `double`, or the widening the ABI inserts between them.
 *
 * These functions are deliberately paired: `single_precision_horner` and
 * `double_precision_horner` are character-for-character the same arithmetic,
 * and a recovery that types every floating value as a `double` (or reuses one
 * width's constant pool for the other) produces identical C for both — which
 * the bit-exact return comparison then catches on the very first inexact input.
 *
 * Overflow to an infinity is an IEEE result, not undefined behaviour, so it is
 * left to happen.  NARROWING is different: converting a double whose magnitude
 * exceeds the float range is undefined, so it is range-checked first. */

/* Largest finite binary32, spelled as the exact binary64 value it widens to. */
#define FP172_FLOAT_MAX 3.4028234663852886e38

/* Every loop below is bounded by this literal, and the count that indexes it is
 * validated before use. */
#define FP172_TERM_LIMIT 16

static float fp172_horner_f32(float x, float a, float b) {
    return (a * x + b) * x + a;
}

static double fp172_horner_f64(double x, double a, double b) {
    return (a * x + b) * x + a;
}

__attribute__((noinline)) float single_precision_horner(float x, float a,
                                                        float b) {
    return fp172_horner_f32(x, a, b);
}

__attribute__((noinline)) double double_precision_horner(double x, double a,
                                                         double b) {
    return fp172_horner_f64(x, a, b);
}

/* One multiply performed at binary64 and delivered at binary32.  The guard is
 * written as `!(in range)` so a NaN intermediate — which `inf * 0` can produce
 * from in-range inputs — also takes the reject path instead of being narrowed.
 */
__attribute__((noinline)) float narrow_after_double_math(float left,
                                                         float right) {
    double product = (double)left * (double)right;
    double scaled = product / 3.0;
    if (!(scaled >= -FP172_FLOAT_MAX && scaled <= FP172_FLOAT_MAX)) {
        return 0.0f;
    }
    return (float)scaled;
}

/* Divide by three and multiply back.  Inexact in both formats, but by different
 * amounts, so the answer depends on the width the intermediate was kept at —
 * the one property a width-collapsing recovery cannot reproduce. */
__attribute__((noinline)) int32_t width_disagreement(float value) {
    float at_float = value / 3.0f * 3.0f;
    double at_double = (double)value / 3.0 * 3.0;
    return ((double)at_float == at_double) ? 0 : 1;
}

/* A halving series accumulated at the ELEMENT width. */
__attribute__((noinline)) float accumulate_narrow(float seed, int32_t count) {
    float total = 0.0f;
    float step = seed;
    int32_t index;
    if (count < 0 || count > FP172_TERM_LIMIT) {
        return 0.0f;
    }
    for (index = 0; index < count; ++index) {
        total += step;
        step = step * 0.5f;
    }
    return total;
}

/* The same series accumulated one width UP.  The terms are binary32 and the
 * total is binary64, so the two functions disagree exactly where the narrow
 * accumulator loses a digit — an accumulator whose width was mis-recovered is
 * visible here and nowhere else. */
__attribute__((noinline)) double accumulate_wide(float seed, int32_t count) {
    double total = 0.0;
    float step = seed;
    int32_t index;
    if (count < 0 || count > FP172_TERM_LIMIT) {
        return 0.0;
    }
    for (index = 0; index < count; ++index) {
        total += (double)step;
        step = step * 0.5f;
    }
    return total;
}

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.

gcc -O2

2/6
accumulate_narrow fail 18 lines
// glaurung: accumulate_narrow @ 0x11d0
float accumulate_narrow(float arg0, int32_t arg1) {
    int index;
    float step;
    float total;
    long ret;
    float var22;
    float var24;
    if (((unsigned long)((unsigned long)((unsigned int)((arg1 - 1)))) <= (unsigned long)(15))) {
        var22 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
        do {
            var24 = (var22 + ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(1) }).value);
            ret = (unsigned long)((unsigned int)(((union { unsigned int bits; float value; }){ .value = var24 }).bits));
            var22 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)((unsigned long)((unsigned int)(((union { unsigned int bits; float value; }){ .value = var24 }).bits))) }).value;
        } while (((unsigned int)(arg1) != (unsigned int)(((union { unsigned int bits; float value; }){ .value = var24 }).bits)));
    }
    return ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(ret) }).value;
}
accumulate_wide fail 18 lines
// glaurung: accumulate_wide @ 0x1210
double accumulate_wide(float arg0, int32_t arg1) {
    int index;
    float step;
    double total;
    long ret;
    double var22;
    double var29;
    if (((unsigned long)((unsigned long)((unsigned int)((arg1 - 1)))) <= (unsigned long)(15))) {
        var22 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
        do {
            var29 = (var22 + ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(1) }).value);
            ret = (unsigned long)((unsigned int)(((union { unsigned long long bits; double value; }){ .value = var29 }).bits));
            var22 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)((unsigned long)((unsigned int)(((union { unsigned long long bits; double value; }){ .value = var29 }).bits))) }).value;
        } while (((unsigned int)(arg1) != (unsigned int)(((union { unsigned long long bits; double value; }){ .value = var29 }).bits)));
    }
    return ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(ret) }).value;
}
double_precision_horner pass 7 lines
// glaurung: double_precision_horner @ 0x1120
double double_precision_horner(double arg0, double arg1, double arg2) {
    double var18;
    var18 = ((((arg0 * arg1) + arg2) * arg0) + arg1);
    arg0 = var18;
    return var18;
}
narrow_after_double_math fail 21 lines
// glaurung: narrow_after_double_math @ 0x1140
static unsigned char glaurung_global_2008[16] __attribute__((aligned(16)));
float narrow_after_double_math(float arg0, float arg1) {
    extern unsigned char glaurung_global_2008[16];
    double product;
    double scaled;
    long t14;
    double var9;
    var9 = (((double)(arg0) * (double)(arg1)) / ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0x4008000000000000) }).value);
    t14 = *(long *)(&glaurung_global_2008[0]);
    if (((var9 < t14) | ((var9 != var9) | (t14 != t14)))) {
        arg0 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
        return ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
    }
    if ((((0x47efffffe0000000 < var9) | (var9 != var9)) == 0)) {
        arg0 = (float)(var9);
        return arg0;
    }
    arg0 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
    return ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
}
single_precision_horner pass 7 lines
// glaurung: single_precision_horner @ 0x1100
float single_precision_horner(float arg0, float arg1, float arg2) {
    float var15;
    var15 = ((((arg0 * arg1) + arg2) * arg0) + arg1);
    arg0 = var15;
    return var15;
}
width_disagreement fail 8 lines
// glaurung: width_disagreement @ 0x1180
int32_t width_disagreement(float arg0) {
    double at_double;
    float at_float;
    arg0 = (float)((double)(arg0));
    arg0 = ((arg0 / ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x4008000000000000) }).value) * ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x4008000000000000) }).value);
    return ((union { unsigned int bits; float value; }){ .value = arg0 }).bits;
}

clang -O0

3/6
accumulate_narrow pass 30 lines
// glaurung: accumulate_narrow @ 0x1310
float accumulate_narrow(float arg0, int32_t arg1) {
    float total;
    float step;
    int index;
    float local_4;
    // x86-64 prologue: save rbp
    total = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
    step = arg0;
    if (((long)(arg1) < 0)) {
        local_4 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
        arg0 = local_4;
        // x86-64 epilogue: restore rbp
        return local_4;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        local_4 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
        arg0 = local_4;
        // x86-64 epilogue: restore rbp
        return local_4;
    }
    for (index = 0; (index < arg1); index++) {
        total = (step + total);
        step = (((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x3f000000) }).value * step);
    }
    local_4 = total;
    arg0 = local_4;
    // x86-64 epilogue: restore rbp
    return local_4;
}
accumulate_wide pass 30 lines
// glaurung: accumulate_wide @ 0x13b0
double accumulate_wide(float arg0, int32_t arg1) {
    double total;
    float step;
    int index;
    double local_8;
    // x86-64 prologue: save rbp
    total = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
    step = arg0;
    if (((long)(arg1) < 0)) {
        local_8 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
        arg0 = (float)(local_8);
        // x86-64 epilogue: restore rbp
        return local_8;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        local_8 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
        arg0 = (float)(local_8);
        // x86-64 epilogue: restore rbp
        return local_8;
    }
    for (index = 0; (index < arg1); index++) {
        total = ((double)(step) + total);
        step = (((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x3f000000) }).value * step);
    }
    local_8 = total;
    arg0 = (float)(local_8);
    // x86-64 epilogue: restore rbp
    return local_8;
}
double_precision_horner pass 9 lines
// glaurung: double_precision_horner @ 0x1180
double double_precision_horner(double arg0, double arg1, double arg2) {
    extern double fp172_horner_f64(double, double, double);
    long var15;
    // x86-64 prologue: save rbp, frame 32 bytes
    var15 = ((long (*)(double, double, double))fp172_horner_f64)(arg0, arg1, arg2);
    // x86-64 epilogue: restore rbp
    return ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(var15) }).value;
}
narrow_after_double_math fail 29 lines
// glaurung: narrow_after_double_math @ 0x1200
static unsigned char glaurung_global_2000[16] __attribute__((aligned(16)));
float narrow_after_double_math(float arg0, float arg1) {
    extern unsigned char glaurung_global_2000[16];
    double product;
    double scaled;
    double local_4;
    double var37;
    // x86-64 prologue: save rbp
    product = ((double)(arg0) * (double)(arg1));
    scaled = (product / ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0x4008000000000000) }).value);
    var37 = *(double *)(&glaurung_global_2000[0]);
    if (((scaled < var37) | ((scaled != scaled) | (var37 != var37)))) {
        local_4 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
        arg0 = (float)(local_4);
        // x86-64 epilogue: restore rbp
        return (float)(local_4);
    }
    if ((((0x47efffffe0000000 < scaled) | (scaled != scaled)) != 0)) {
        local_4 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
        arg0 = (float)(local_4);
        // x86-64 epilogue: restore rbp
        return (float)(local_4);
    }
    local_4 = (double)((float)(scaled));
    arg0 = (float)(local_4);
    // x86-64 epilogue: restore rbp
    return (float)(local_4);
}
single_precision_horner fail 9 lines
// glaurung: single_precision_horner @ 0x1100
float single_precision_horner(float arg0, float arg1, float arg2) {
    extern float fp172_horner_f32(float, float, float);
    long var15;
    // x86-64 prologue: save rbp, frame 16 bytes
    var15 = ((long (*)(float, float, float))fp172_horner_f32)(arg0, arg1, arg2);
    // x86-64 epilogue: restore rbp
    return ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(var15) }).value;
}
width_disagreement fail 10 lines
// glaurung: width_disagreement @ 0x1290
int32_t width_disagreement(float arg0) {
    float at_float;
    double at_double;
    // x86-64 prologue: save rbp
    at_float = ((arg0 / ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x40400000) }).value) * ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x40400000) }).value);
    at_double = (((double)(arg0) / ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0x4008000000000000) }).value) * ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0x4008000000000000) }).value);
    // x86-64 epilogue: restore rbp
    return 1;
}

clang -O2

4/6
accumulate_narrow pass 72 lines
// glaurung: accumulate_narrow @ 0x11d0
float accumulate_narrow(float arg0, int32_t arg1) {
    int index;
    float step;
    float total;
    long var0;
    float var1;
    long var12;
    long var14;
    float var15;
    float var17;
    float var22;
    float var25;
    float var29;
    float var33;
    float var37;
    float var41;
    float var45;
    float var49;
    int var52;
    float var53;
    float var54;
    float var55;
    int var61;
    var0 = (unsigned long)((unsigned int)((arg1 - 1)));
    var1 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
    if (((unsigned long)(15) < (unsigned long)((unsigned long)((unsigned int)(var0))))) {
        arg0 = var1;
        return var1;
    }
    var12 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) & 7)));
    if (((unsigned long)(7) <= (unsigned long)((unsigned long)((unsigned int)(var0))))) {
        var14 = (unsigned long)((unsigned int)((arg1 & -8)));
        var15 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
        var17 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x3f000000) }).value;
        var22 = arg0;
        do {
            var25 = (var22 * var17);
            var29 = (var25 * var17);
            var33 = (var29 * var17);
            var37 = (var33 * var17);
            var41 = (var37 * var17);
            var45 = (var41 * var17);
            var49 = (var45 * var17);
            var15 = ((((((((var15 + var22) + var25) + var29) + var33) + var37) + var41) + var45) + var49);
            var22 = (var49 * var17);
            var52 = (var14 - 8);
            var14 = (unsigned long)((unsigned int)(var52));
            var53 = var22;
            var54 = var15;
        } while (((unsigned long)((unsigned int)(var52)) != 0));
    } else {
        var54 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
        var53 = arg0;
    }
    var1 = var54;
    if (((unsigned long)((unsigned int)(var12)) == 0)) {
        arg0 = var1;
        return var1;
    }
    var55 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x3f000000) }).value;
    do {
        var54 = (var54 + var53);
        arg0 = (var53 * var55);
        var61 = (var12 - 1);
        var12 = (unsigned long)((unsigned int)(var61));
        var53 = arg0;
        var1 = var54;
    } while (((unsigned long)((unsigned int)(var61)) != 0));
    arg0 = var1;
    return var1;
}
accumulate_wide pass 64 lines
// glaurung: accumulate_wide @ 0x1280
double accumulate_wide(float arg0, int32_t arg1) {
    int index;
    float step;
    double total;
    long var0;
    double var1;
    long var12;
    long var14;
    double var15;
    float var20;
    double var25;
    double var37;
    double var50;
    double var63;
    int var72;
    double var73;
    double var74;
    float var75;
    int var89;
    var0 = (unsigned long)((unsigned int)((arg1 - 1)));
    var1 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
    if (((unsigned long)(15) < (unsigned long)((unsigned long)((unsigned int)(var0))))) {
        arg0 = (float)(var1);
        return var1;
    }
    var12 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) & 3)));
    if (((unsigned long)(3) <= (unsigned long)((unsigned long)((unsigned int)(var0))))) {
        var14 = (unsigned long)((unsigned int)((arg1 & -4)));
        var15 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
        var20 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x3f000000) }).value;
        var25 = (double)(arg0);
        do {
            var37 = (var25 * (double)(var20));
            var50 = (var37 * (double)(var20));
            var63 = (var50 * (double)(var20));
            var15 = ((double)((float)(var63)) + ((double)((float)(var50)) + ((double)((float)(var37)) + ((double)((float)(var25)) + var15))));
            var25 = (var63 * (double)(var20));
            var72 = (var14 - 4);
            var14 = (unsigned long)((unsigned int)(var72));
            var73 = var25;
            var74 = var15;
        } while (((unsigned long)((unsigned int)(var72)) != 0));
    } else {
        var74 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
        var73 = (double)(arg0);
    }
    var1 = var74;
    if (((unsigned long)((unsigned int)(var12)) == 0)) {
        arg0 = (float)(var1);
        return var1;
    }
    var75 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x3f000000) }).value;
    do {
        var74 = (var74 + (double)((float)(var73)));
        arg0 = ((float)(var73) * var75);
        var89 = (var12 - 1);
        var12 = (unsigned long)((unsigned int)(var89));
        var73 = (double)(arg0);
        var1 = var74;
    } while (((unsigned long)((unsigned int)(var89)) != 0));
    arg0 = (float)(var1);
    return var1;
}
double_precision_horner pass 4 lines
// glaurung: double_precision_horner @ 0x1120
double double_precision_horner(double arg0, double arg1, double arg2) {
    return ((arg0 * ((arg1 * arg0) + arg2)) + arg1);
}
narrow_after_double_math fail 26 lines
// glaurung: narrow_after_double_math @ 0x1140
static unsigned char glaurung_global_2010[16] __attribute__((aligned(16)));
float narrow_after_double_math(float arg0, float arg1) {
    extern unsigned char glaurung_global_2010[16];
    double product;
    double scaled;
    long t14;
    long t23;
    double var9;
    var9 = (((double)(arg1) * (double)(arg0)) / ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0x4008000000000000) }).value);
    if ((((0x47efffffe0000000 < var9) | (var9 != var9)) == 0)) {
        arg0 = (float)(var9);
        t23 = *(long *)(&glaurung_global_2010[0]);
        if ((((var9 < t23) | ((var9 != var9) | (t23 != t23))) == 0)) {
            return arg0;
        }
        return ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
    }
    arg0 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
    t14 = *(long *)(&glaurung_global_2010[0]);
    if (((var9 < t14) | ((var9 != var9) | (t14 != t14)))) {
        arg0 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
        return ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
    }
    return arg0;
}
single_precision_horner pass 4 lines
// glaurung: single_precision_horner @ 0x1100
float single_precision_horner(float arg0, float arg1, float arg2) {
    return ((arg0 * ((arg1 * arg0) + arg2)) + arg1);
}
width_disagreement fail 10 lines
// glaurung: width_disagreement @ 0x1190
int32_t width_disagreement(float arg0) {
    extern long __unknown(long, ...);
    double at_double;
    float at_float;
    double var23;
    var23 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(__unknown(0)) }).value;
    /* asm: cmpsd */
    return (unsigned int)((var23 & 1));
}

gcc -O0

4/6
accumulate_narrow pass 26 lines
// glaurung: accumulate_narrow @ 0x12e8
float accumulate_narrow(float arg0, int32_t arg1) {
    float total;
    float step;
    int index;
    // x86-64 prologue: save rbp
    total = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
    step = arg0;
    if (((long)(arg1) < 0)) {
        arg0 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
        // x86-64 epilogue: restore rbp
        return ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        arg0 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
        // x86-64 epilogue: restore rbp
        return ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
    }
    for (index = 0; (index < arg1); index++) {
        total = (total + step);
        step = (((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x3f000000) }).value * step);
    }
    arg0 = total;
    // x86-64 epilogue: restore rbp
    return total;
}
accumulate_wide pass 26 lines
// glaurung: accumulate_wide @ 0x135e
double accumulate_wide(float arg0, int32_t arg1) {
    double total;
    float step;
    int index;
    // x86-64 prologue: save rbp
    total = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
    step = arg0;
    if (((long)(arg1) < 0)) {
        arg0 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
        // x86-64 epilogue: restore rbp
        return ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        arg0 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
        // x86-64 epilogue: restore rbp
        return ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
    }
    for (index = 0; (index < arg1); index++) {
        total = ((double)(step) + total);
        step = (((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x3f000000) }).value * step);
    }
    arg0 = (float)(total);
    // x86-64 epilogue: restore rbp
    return total;
}
double_precision_horner fail 12 lines
// glaurung: double_precision_horner @ 0x11a0
double double_precision_horner(double arg0, double arg1, double arg2) {
    extern double fp172_horner_f64(double, double, double);
    long ret;
    long var22;
    // x86-64 prologue: save rbp, frame 24 bytes
    ret = ((union { unsigned long long bits; double value; }){ .value = arg0 }).bits;
    var22 = ((long (*)(double, double, double))fp172_horner_f64)(arg0, arg1, arg2);
    arg0 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(var22) }).value;
    // x86-64 epilogue: restore rbp
    return ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(ret) }).value;
}
narrow_after_double_math fail 30 lines
// glaurung: narrow_after_double_math @ 0x11e7
static unsigned char glaurung_global_2008[16] __attribute__((aligned(16)));
float narrow_after_double_math(float arg0, float arg1) {
    extern unsigned char glaurung_global_2008[16];
    double product;
    double scaled;
    long ret;
    long t14;
    long var39;
    // x86-64 prologue: save rbp
    product = ((double)(arg1) * (double)(arg0));
    scaled = (product / ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0x4008000000000000) }).value);
    arg0 = (float)(scaled);
    t14 = *(long *)(&glaurung_global_2008[0]);
    var39 = (unsigned long)((unsigned int)((((ret & -256) | (((scaled < t14) | ((scaled != scaled) | (t14 != t14))) == 0)) ^ 1)));
    if (((unsigned long)((unsigned char)((var39 & 255))) != 0)) {
        arg0 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
        // x86-64 epilogue: restore rbp
        return ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
    }
    arg0 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x47efffffe0000000) }).value;
    if (((unsigned long)((unsigned char)(((unsigned long)((unsigned int)((((var39 & -256) | (((0x47efffffe0000000 < scaled) | (scaled != scaled)) == 0)) ^ 1))) & 255))) != 0)) {
        arg0 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
        // x86-64 epilogue: restore rbp
        return ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0) }).value;
    }
    arg0 = (float)(scaled);
    // x86-64 epilogue: restore rbp
    return arg0;
}
single_precision_horner pass 10 lines
// glaurung: single_precision_horner @ 0x1167
float single_precision_horner(float arg0, float arg1, float arg2) {
    extern float fp172_horner_f32(float, float, float);
    float ret;
    // x86-64 prologue: save rbp, frame 16 bytes
    ret = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)((unsigned long)((unsigned int)(((union { unsigned int bits; float value; }){ .value = arg0 }).bits))) }).value;
    ret = ((float (*)(float))fp172_horner_f32)(arg0);
    // x86-64 epilogue: restore rbp
    return ret;
}
width_disagreement pass 12 lines
// glaurung: width_disagreement @ 0x1269
int32_t width_disagreement(float arg0) {
    float at_float;
    double at_double;
    double var58;
    // x86-64 prologue: save rbp
    at_float = (((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x40400000) }).value * (arg0 / ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x40400000) }).value));
    at_double = (((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0x4008000000000000) }).value * ((double)(arg0) / ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0x4008000000000000) }).value));
    var58 = (double)(at_float);
    // x86-64 epilogue: restore rbp
    return (unsigned int)((unsigned char)((((((var58 == at_double) | ((var58 != var58) | (at_double != at_double))) == 0) ? 1 : (((var58 != var58) | (at_double != at_double)) & 255)) & 255)));
}

← 213 fixtures