Fixture 217

complex arithmetic

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

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

_Complex — a C type with its own ABI class, its own register pairing, and no coverage anywhere in this corpus.

WHY IT IS NOT JUST TWO FLOATS. Under SysV a float _Complex is a single eightbyte of class SSE (both halves in one xmm register), while a double _Complex is TWO eightbytes and returns in xmm0:xmm1. On AArch64 a complex value is a homogeneous float aggregate and goes in v0/v1. On ARM32 hard-float it is a VFP register pair. Every one of those is a distinct classification path, and each is the path a decompiler gets wrong by treating the value as a struct of two scalars — which compiles, and returns garbage in the high half.

Multiplication is the shape that exposes it: (a+bi)(c+di) reads all four components and writes two, so a recovery that loses the pairing produces an answer that is wrong in one half only. That is exactly the failure a single-value return check cannot see, which is why every function here folds BOTH halves into its integer result.

197_homogeneous_float_aggregates covers HFAs built from a struct; 172_float_double_widths covers scalar float widths; 188_vector_transport covers 128-bit vector moves. None of them uses _Complex, so none exercises the compiler's complex-specific lowering (__mulsc3-style helper calls at -O0 on some targets, inline sequences at -O2) or the ABI class it selects.

Every constant is an exact binary fraction and every result is scaled to an integer, so the answers are identical whether the target computes in 32-bit, 64-bit or 80-bit intermediate precision.

tests/decompiler_fixtures/src/217_complex_arithmetic.c source
#include <stdint.h>

/* `_Complex` — a C type with its own ABI class, its own register pairing, and
 * no coverage anywhere in this corpus.
 *
 * WHY IT IS NOT JUST TWO FLOATS. Under SysV a `float _Complex` is a single
 * eightbyte of class SSE (both halves in one xmm register), while a
 * `double _Complex` is TWO eightbytes and returns in `xmm0:xmm1`. On AArch64 a
 * complex value is a homogeneous float aggregate and goes in `v0`/`v1`. On
 * ARM32 hard-float it is a VFP register pair. Every one of those is a distinct
 * classification path, and each is the path a decompiler gets wrong by treating
 * the value as a struct of two scalars — which compiles, and returns garbage in
 * the high half.
 *
 * Multiplication is the shape that exposes it: `(a+bi)(c+di)` reads all four
 * components and writes two, so a recovery that loses the pairing produces an
 * answer that is wrong in one half only. That is exactly the failure a
 * single-value return check cannot see, which is why every function here folds
 * BOTH halves into its integer result.
 *
 * `197_homogeneous_float_aggregates` covers HFAs built from a struct;
 * `172_float_double_widths` covers scalar float widths;
 * `188_vector_transport` covers 128-bit vector moves. None of them uses
 * `_Complex`, so none exercises the compiler's complex-specific lowering
 * (`__mulsc3`-style helper calls at -O0 on some targets, inline sequences at
 * -O2) or the ABI class it selects.
 *
 * Every constant is an exact binary fraction and every result is scaled to an
 * integer, so the answers are identical whether the target computes in 32-bit,
 * 64-bit or 80-bit intermediate precision.
 */

/* Complex multiply, both halves folded into the result. */
__attribute__((noinline)) int64_t complex_multiply(int32_t ar, int32_t ai,
                                                    int32_t br, int32_t bi) {
    double _Complex a = (double)ar + (double)ai * (double _Complex){0.0 + 1.0i};
    double _Complex b = (double)br + (double)bi * (double _Complex){0.0 + 1.0i};
    double _Complex p = a * b;
    return (int64_t)(__real__ p) * 1000 + (int64_t)(__imag__ p);
}

/* Addition and conjugation: cheaper lowering, still a paired value. */
__attribute__((noinline)) int64_t complex_add_conj(int32_t ar, int32_t ai,
                                                    int32_t br, int32_t bi) {
    double _Complex a = (double)ar + (double)ai * 1.0i;
    double _Complex b = (double)br + (double)bi * 1.0i;
    double _Complex s = a + ~b; /* ~ is conjugation on complex */
    return (int64_t)(__real__ s) * 1000 + (int64_t)(__imag__ s);
}

/* `float _Complex` — one eightbyte on x86-64, a different class from the
 * double form above. */
__attribute__((noinline)) int64_t complex_float_multiply(int32_t ar,
                                                          int32_t ai,
                                                          int32_t br,
                                                          int32_t bi) {
    float _Complex a = (float)ar + (float)ai * 1.0if;
    float _Complex b = (float)br + (float)bi * 1.0if;
    float _Complex p = a * b;
    return (int64_t)(__real__ p) * 1000 + (int64_t)(__imag__ p);
}

/* A complex value passed THROUGH a call boundary and returned, so the argument
 * and return classifications are both exercised rather than only the local
 * arithmetic. */
static double _Complex scale_complex(double _Complex v, double factor) {
    return v * factor;
}

__attribute__((noinline)) int64_t complex_through_call(int32_t ar, int32_t ai,
                                                       int32_t factor) {
    double _Complex a = (double)ar + (double)ai * 1.0i;
    double _Complex s = scale_complex(a, (double)(factor & 7) + 0.5);
    return (int64_t)(__real__ s * 2.0) * 1000 + (int64_t)(__imag__ s * 2.0);
}

/* An array of complex values summed in a loop: a stride of two doubles, which
 * an object model must see as one element rather than two. */
__attribute__((noinline)) int64_t complex_array_sum(const int32_t *pairs,
                                                     int32_t count) {
    double _Complex total = 0.0 + 0.0i;
    if (pairs == 0 || count < 0 || count > 8) {
        return -1;
    }
    for (int32_t i = 0; i < count; i++) {
        total += (double)(pairs[i] & 0xff) + (double)((pairs[i] >> 8) & 0xff) * 1.0i;
    }
    return (int64_t)(__real__ total) * 1000 + (int64_t)(__imag__ total);
}

/* CONTROL: the same arithmetic on a struct of two doubles, which is an
 * ordinary aggregate rather than a complex. If this passes and the complex
 * versions fail, the ABI class is the cause and not the float arithmetic. */
struct two_doubles {
    double re;
    double im;
};

__attribute__((noinline)) int64_t struct_pair_control(int32_t ar, int32_t ai,
                                                       int32_t br, int32_t bi) {
    struct two_doubles a = {(double)ar, (double)ai};
    struct two_doubles b = {(double)br, (double)bi};
    struct two_doubles p = {a.re * b.re - a.im * b.im,
                            a.re * b.im + a.im * b.re};
    return (int64_t)p.re * 1000 + (int64_t)p.im;
}

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

1/6
complex_add_conj fail 18 lines
// glaurung: complex_add_conj @ 0x1290
int64_t complex_add_conj(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    double local_18;
    double local_20;
    double local_28;
    double local_30;
    double local_38;
    double local_40;
    // x86-64 prologue: save rbp
    local_20 = (double)((int)(arg0));
    local_18 = ((double)((int)(arg1)) * ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0x3ff0000000000000) }).value);
    local_30 = (double)((int)(arg2));
    local_28 = ((double)((int)(arg3)) * ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0x3ff0000000000000) }).value);
    local_40 = (local_20 + local_30);
    local_38 = (local_18 + ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)((local_28 ^ (-0x7fffffffffffffffLL - 1LL))) }).value);
    // x86-64 epilogue: restore rbp
    return (((long long)(local_40) * 1000) + (long long)(local_38));
}
complex_array_sum pass 34 lines
// glaurung: complex_array_sum @ 0x15c0
int64_t complex_array_sum(const int32_t * arg0, int32_t arg1) {
    int i;
    double local_20;
    double local_28;
    long local_8;
    double var69;
    // x86-64 prologue: save rbp
    local_28 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
    local_20 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
    if ((arg0 == 0)) {
        local_8 = -1;
        // x86-64 epilogue: restore rbp
        return local_8;
    }
    if (((long)(arg1) < 0)) {
        local_8 = -1;
        // x86-64 epilogue: restore rbp
        return local_8;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 8) | ((long)(arg1) < 8)) == 0)) {
        local_8 = -1;
        // x86-64 epilogue: restore rbp
        return local_8;
    }
    for (i = 0; (i < arg1); i++) {
        var69 = (local_20 + ((double)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((int)((unsigned long)((unsigned int)(arg0[(long)(i)]))) >> 8))) & 255))))) * ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0x3ff0000000000000) }).value));
        local_28 = (local_28 + (double)((int)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0[(long)(i)])) & 255))))));
        local_20 = var69;
    }
    local_8 = (((long long)(local_28) * 1000) + (long long)(local_20));
    // x86-64 epilogue: restore rbp
    return local_8;
}
complex_float_multiply fail 64 lines
// glaurung: complex_float_multiply @ 0x1360
int64_t complex_float_multiply(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    extern float __mulsc3(int);
    float local_14;
    float local_18;
    float local_1c;
    float local_20;
    float local_24;
    float local_28;
    float local_30;
    float local_34;
    float local_38;
    float local_3c;
    float local_40;
    float local_44;
    float local_48;
    float local_4c;
    float local_50;
    long var105;
    long var106;
    long var107;
    float var138;
    float var91;
    float var93;
    // x86-64 prologue: save rbp, frame 80 bytes
    local_18 = (float)((int)(arg0));
    local_14 = ((float)((int)(arg1)) * ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x3f800000) }).value);
    local_20 = (float)((int)(arg2));
    local_1c = ((float)((int)(arg3)) * ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x3f800000) }).value);
    local_50 = local_18;
    local_4c = local_14;
    local_48 = local_20;
    local_44 = local_1c;
    var91 = ((((union { unsigned int bits; float value; }){ .bits = (unsigned int)((unsigned int)(((union { unsigned int bits; float value; }){ .value = local_18 }).bits)) }).value * ((union { unsigned int bits; float value; }){ .bits = (unsigned int)((unsigned int)(((union { unsigned int bits; float value; }){ .value = local_20 }).bits)) }).value) - (local_14 * local_1c));
    local_40 = var91;
    var93 = ((((union { unsigned int bits; float value; }){ .bits = (unsigned int)((unsigned int)(((union { unsigned int bits; float value; }){ .value = local_18 }).bits)) }).value * local_1c) + (local_14 * ((union { unsigned int bits; float value; }){ .bits = (unsigned int)((unsigned int)(((union { unsigned int bits; float value; }){ .value = local_20 }).bits)) }).value));
    local_3c = var93;
    local_38 = var91;
    local_34 = var93;
    if ((var91 == var91)) {
        local_28 = local_38;
        local_24 = local_34;
        var105 = (long long)(((union { unsigned int bits; float value; }){ .bits = (unsigned int)((unsigned int)(((unsigned long)(((union { unsigned int bits; float value; }){ .value = local_28 }).bits) >> 0))) }).value);
        var106 = (var105 * 1000);
        var107 = (long long)(local_24);
        // x86-64 epilogue: restore rbp
        return (var106 + var107);
    }
    local_38 = local_40;
    local_34 = local_3c;
    if ((local_3c != local_3c)) {
        var138 = __mulsc3(arg0);
        local_30 = var138;
        local_38 = local_30;
        local_34 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(((unsigned long)(((union { unsigned int bits; float value; }){ .value = local_30 }).bits) >> 32)) }).value;
    }
    local_28 = local_38;
    local_24 = local_34;
    var105 = (long long)(((union { unsigned int bits; float value; }){ .bits = (unsigned int)((unsigned int)(((unsigned long)(((union { unsigned int bits; float value; }){ .value = local_28 }).bits) >> 0))) }).value);
    var106 = (var105 * 1000);
    var107 = (long long)(local_24);
    // x86-64 epilogue: restore rbp
    return (var106 + var107);
}
complex_multiply fail 76 lines
// glaurung: complex_multiply @ 0x1100
int64_t complex_multiply(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    extern double __muldc3(int);
    double local_18;
    double local_20;
    double local_28;
    double local_30;
    double local_38;
    double local_40;
    double local_48;
    double local_50;
    double local_58;
    double local_60;
    double local_68;
    double local_70;
    double local_78;
    double local_80;
    double local_88;
    double local_90;
    double local_98;
    double local_a0;
    double var124;
    double var127;
    long var140;
    long var141;
    long var142;
    double var163;
    double var173;
    double var3;
    double var45;
    // x86-64 prologue: save rbp, frame 160 bytes
    var3 = (double)((int)(arg1));
    local_30 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
    local_28 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0x3ff0000000000000) }).value;
    local_20 = ((double)((int)(arg0)) + (var3 * local_30));
    local_18 = (var3 * local_28);
    var45 = (double)((int)(arg3));
    local_50 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
    local_48 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0x3ff0000000000000) }).value;
    local_40 = ((double)((int)(arg2)) + (var45 * local_50));
    local_38 = (var45 * local_48);
    local_a0 = local_20;
    local_98 = local_18;
    local_90 = local_40;
    local_88 = local_38;
    var124 = ((local_20 * local_40) - (local_18 * local_38));
    local_80 = var124;
    var127 = ((local_20 * local_38) + (local_18 * local_40));
    local_78 = var127;
    local_70 = var124;
    local_68 = var127;
    if ((var124 == var124)) {
        local_60 = local_70;
        local_58 = local_68;
        var140 = (long long)(local_60);
        var141 = (var140 * 1000);
        var142 = (long long)(local_58);
        // x86-64 epilogue: restore rbp
        return (var141 + var142);
    }
    local_70 = local_80;
    local_68 = local_78;
    if ((local_78 != local_78)) {
        var163 = local_98;
        var173 = __muldc3(arg0);
        local_70 = var173;
        local_68 = var163;
    }
    local_60 = local_70;
    local_58 = local_68;
    var140 = (long long)(local_60);
    var141 = (var140 * 1000);
    var142 = (long long)(local_58);
    // x86-64 epilogue: restore rbp
    return (var141 + var142);
}
complex_through_call fail 22 lines
// glaurung: complex_through_call @ 0x14c0
int64_t complex_through_call(int32_t arg0, int32_t arg1, int32_t arg2) {
    extern long scale_complex(float, double);
    double local_18;
    double local_20;
    double local_28;
    double local_30;
    double local_38;
    double local_40;
    double var61;
    long var65;
    // x86-64 prologue: save rbp, frame 64 bytes
    local_20 = (double)((int)(arg0));
    local_18 = ((double)((int)(arg1)) * ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0x3ff0000000000000) }).value);
    local_40 = local_20;
    local_38 = local_18;
    var65 = scale_complex((float)((float)(local_40)), local_38);
    local_30 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(var65) }).value;
    local_28 = var61;
    // x86-64 epilogue: restore rbp
    return (((long long)((((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0x4000000000000000) }).value * local_30)) * 1000) + (long long)((((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0x4000000000000000) }).value * local_28)));
}
struct_pair_control fail 15 lines
// glaurung: struct_pair_control @ 0x16b0
__attribute__((no_stack_protector)) int64_t struct_pair_control(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    unsigned char local_20[16];
    unsigned char local_30[16];
    unsigned char local_40[16];
    // x86-64 prologue: save rbp
    *(double *)(&local_20[0]) = (double)((int)(arg0));
    *(double *)((&local_20[0] + 8)) = (double)((int)(arg1));
    *(double *)(&local_30[0]) = (double)((int)(arg2));
    *(double *)((&local_30[0] + 8)) = (double)((int)(arg3));
    *(long *)(&local_40[0]) = ((*(long *)(&local_20[0]) * *(long *)(&local_30[0])) + ((*(long *)((&local_20[0] + 8)) * *(long *)((&local_30[0] + 8))) ^ (-0x7fffffffffffffffLL - 1LL)));
    *(long *)((&local_40[0] + 8)) = ((*(long *)(&local_20[0]) * *(long *)((&local_30[0] + 8))) + (*(long *)((&local_20[0] + 8)) * *(long *)(&local_30[0])));
    // x86-64 epilogue: restore rbp
    return (((long long)(*(double *)(&local_40[0])) * 1000) + (long long)(*(double *)((&local_40[0] + 8))));
}

gcc -O0

1/6
complex_add_conj fail 30 lines
// glaurung: complex_add_conj @ 0x1210
int64_t complex_add_conj(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    double local_10;
    double local_18;
    double local_20;
    double local_28;
    double local_30;
    double local_38;
    double local_40;
    double local_48;
    double local_50;
    double local_58;
    double local_60;
    double local_8;
    // x86-64 prologue: save rbp
    local_50 = (double)((int)(arg1));
    local_60 = (double)((int)(arg0));
    local_30 = local_60;
    local_28 = local_50;
    local_48 = (double)((int)(arg3));
    local_58 = (double)((int)(arg2));
    local_20 = local_58;
    local_18 = local_48;
    local_40 = (local_60 + local_58);
    local_38 = (local_50 + ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(((0x80000000 ^ (((unsigned long)(local_48) >> 32) & 0xffffffff)) | (unsigned int)(((union { unsigned long long bits; double value; }){ .value = local_48 }).bits))) }).value);
    local_10 = local_40;
    local_8 = local_38;
    // x86-64 epilogue: restore rbp
    return ((long long)(local_38) + ((long long)(local_40) * 1000));
}
complex_array_sum pass 39 lines
// glaurung: complex_array_sum @ 0x150e
int64_t complex_array_sum(const int32_t * arg0, int32_t arg1) {
    int i;
    double local_10;
    double local_18;
    double local_20;
    double local_8;
    double var82;
    double var85;
    // x86-64 prologue: save rbp
    local_10 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
    local_8 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
    if ((arg0 == 0)) {
        // x86-64 epilogue: restore rbp
        return -1;
    }
    if (((long)(arg1) < 0)) {
        // x86-64 epilogue: restore rbp
        return -1;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 8) | ((long)(arg1) < 8)) == 0)) {
        // x86-64 epilogue: restore rbp
        return -1;
    }
    i = 0;
    local_18 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
    local_20 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
    while ((i < arg1)) {
        var82 = ((double)((int)((unsigned int)((unsigned char)(((unsigned long)((unsigned int)(arg0[(long)((int)((unsigned long)((unsigned int)(i))))])) & 255))))) + local_20);
        var85 = ((double)((int)((unsigned int)((unsigned char)(((unsigned long)((unsigned int)(((int)((unsigned long)((unsigned int)(arg0[(long)((int)((unsigned long)((unsigned int)(i))))]))) >> 8))) & 255))))) + local_18);
        local_10 = var82;
        local_8 = var85;
        local_20 = var82;
        local_18 = var85;
        i = (i + 1);
    }
    // x86-64 epilogue: restore rbp
    return ((long long)(local_18) + ((long long)(local_20) * 1000));
}
complex_float_multiply fail 31 lines
// glaurung: complex_float_multiply @ 0x1308
int64_t complex_float_multiply(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    extern float __mulsc3(void);
    float local_10;
    float local_14;
    float local_18;
    float local_1c;
    float local_20;
    float local_24;
    float local_28;
    float local_2c;
    float local_30;
    float local_8;
    float local_c;
    float var111;
    // x86-64 prologue: save rbp, frame 64 bytes
    local_28 = (float)((int)(arg1));
    local_30 = (float)((int)(arg0));
    local_18 = local_30;
    local_14 = local_28;
    local_24 = (float)((int)(arg3));
    local_2c = (float)((int)(arg2));
    local_10 = local_2c;
    local_c = local_24;
    var111 = __mulsc3();
    local_8 = var111;
    local_20 = local_8;
    local_1c = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(((unsigned long)(((union { unsigned int bits; float value; }){ .value = local_8 }).bits) >> 32)) }).value;
    // x86-64 epilogue: restore rbp
    return ((long long)(local_1c) + ((long long)(local_20) * 1000));
}
complex_multiply fail 35 lines
// glaurung: complex_multiply @ 0x10f9
int64_t complex_multiply(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    extern double __muldc3(void);
    double local_10;
    double local_18;
    double local_20;
    double local_28;
    double local_30;
    double local_38;
    double local_40;
    double local_48;
    double local_50;
    double local_58;
    double local_60;
    long local_8;
    double var119;
    double var125;
    // x86-64 prologue: save rbp, frame 112 bytes
    local_60 = (double)((int)(arg0));
    local_58 = ((double)((int)(arg1)) * ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0x3ff0000000000000) }).value);
    local_30 = local_60;
    local_28 = local_58;
    local_50 = (double)((int)(arg2));
    local_48 = ((double)((int)(arg3)) * ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0x3ff0000000000000) }).value);
    local_20 = local_50;
    local_18 = local_48;
    var119 = local_58;
    var125 = __muldc3();
    local_10 = var125;
    local_8 = ((union { unsigned long long bits; double value; }){ .value = var119 }).bits;
    local_40 = local_10;
    local_38 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(local_8) }).value;
    // x86-64 epilogue: restore rbp
    return ((long long)(local_38) + ((long long)(local_40) * 1000));
}
complex_through_call fail 18 lines
// glaurung: complex_through_call @ 0x1466
int64_t complex_through_call(int32_t arg0, int32_t arg1, int32_t arg2) {
    extern long scale_complex(float, double);
    double local_10;
    double local_18;
    double local_20;
    long local_8;
    double var47;
    long var60;
    // x86-64 prologue: save rbp, frame 48 bytes
    local_20 = (double)((int)(arg0));
    local_18 = (double)((int)(arg1));
    var60 = scale_complex((float)((float)(local_20)), local_18);
    local_10 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(var60) }).value;
    local_8 = ((union { unsigned long long bits; double value; }){ .value = var47 }).bits;
    // x86-64 epilogue: restore rbp
    return ((long long)((((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(local_8) }).value + ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(local_8) }).value)) + ((long long)((local_10 + local_10)) * 1000));
}
struct_pair_control fail 15 lines
// glaurung: struct_pair_control @ 0x162f
__attribute__((no_stack_protector)) int64_t struct_pair_control(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    unsigned char local_10[16];
    unsigned char local_20[16];
    unsigned char local_30[16];
    // x86-64 prologue: save rbp
    *(double *)(&local_30[0]) = (double)((int)(arg0));
    *(double *)((&local_30[0] + 8)) = (double)((int)(arg1));
    *(double *)(&local_20[0]) = (double)((int)(arg2));
    *(double *)((&local_20[0] + 8)) = (double)((int)(arg3));
    *(long *)(&local_10[0]) = ((*(long *)(&local_20[0]) * *(long *)(&local_30[0])) - (*(long *)((&local_20[0] + 8)) * *(long *)((&local_30[0] + 8))));
    *(long *)((&local_10[0] + 8)) = ((*(long *)(&local_20[0]) * *(long *)((&local_30[0] + 8))) + (*(long *)(&local_30[0]) * *(long *)((&local_20[0] + 8))));
    // x86-64 epilogue: restore rbp
    return ((long long)(*(double *)((&local_10[0] + 8))) + ((long long)(*(double *)(&local_10[0])) * 1000));
}

clang -O2

4/6
complex_add_conj pass 4 lines
// glaurung: complex_add_conj @ 0x1190
int64_t complex_add_conj(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    return ((((long)(arg2) + (long)(arg0)) * 1000) + ((long)(arg1) - (long)(arg3)));
}
complex_array_sum pass 88 lines
// glaurung: complex_array_sum @ 0x12a0
int64_t complex_array_sum(const int32_t * arg0, int32_t arg1) {
    int i;
    long ret;
    long var1;
    double var10;
    double var102;
    long var115;
    double var133;
    long var148;
    double var163;
    long var176;
    double var194;
    long var209;
    double var224;
    double var28;
    long var31;
    double var41;
    long var54;
    double var7;
    double var72;
    long var87;
    ret = -1;
    if ((arg0 == 0)) {
        return ret;
    }
    if (((unsigned long)(8) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return ret;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        return 0;
    }
    var1 = (unsigned long)((unsigned int)(*(int *)(((long)arg0))));
    var7 = (double)((int)((unsigned int)((unsigned char)((((unsigned long)(var1) >> 8) & 255)))));
    var10 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
    var28 = (double)((int)((unsigned int)((unsigned char)((var1 & 255)))));
    if (((unsigned long)((unsigned int)(arg1)) != 1)) {
        var31 = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + 0x4))));
        ret = (unsigned int)((unsigned char)((((unsigned long)(var31) >> 8) & 255)));
        var41 = (double)((int)(ret));
        var28 = (var28 + ((var10 * var41) + (double)((int)((unsigned int)((unsigned char)((var31 & 255)))))));
        var7 = (var7 + var41);
        if (((unsigned long)((unsigned int)(arg1)) != 2)) {
            var54 = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + 0x8))));
            ret = (unsigned int)((unsigned char)((((unsigned long)(var54) >> 8) & 255)));
            var72 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
            var7 = (var7 + (double)((int)(ret)));
            var28 = (var28 + (double)((int)((unsigned int)((unsigned char)((var54 & 255))))));
            if (((unsigned long)((unsigned int)(arg1)) != 3)) {
                var87 = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + 0xc))));
                ret = (unsigned int)((unsigned char)((((unsigned long)(var87) >> 8) & 255)));
                var102 = (double)((int)(ret));
                var28 = (var28 + ((var72 * var102) + (double)((int)((unsigned int)((unsigned char)((var87 & 255)))))));
                var7 = (var7 + var102);
                if (((unsigned long)((unsigned int)(arg1)) != 4)) {
                    var115 = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + 0x10))));
                    ret = (unsigned int)((unsigned char)((((unsigned long)(var115) >> 8) & 255)));
                    var133 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
                    var7 = (var7 + (double)((int)(ret)));
                    var28 = (var28 + (double)((int)((unsigned int)((unsigned char)((var115 & 255))))));
                    if (((unsigned long)((unsigned int)(arg1)) != 5)) {
                        var148 = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + 0x14))));
                        ret = (unsigned int)((unsigned char)((((unsigned long)(var148) >> 8) & 255)));
                        var163 = (double)((int)(ret));
                        var28 = (var28 + ((var133 * var163) + (double)((int)((unsigned int)((unsigned char)((var148 & 255)))))));
                        var7 = (var7 + var163);
                        if (((unsigned long)((unsigned int)(arg1)) != 6)) {
                            var176 = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + 0x18))));
                            ret = (unsigned int)((unsigned char)((((unsigned long)(var176) >> 8) & 255)));
                            var194 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
                            var7 = (var7 + (double)((int)(ret)));
                            var28 = (var28 + (double)((int)((unsigned int)((unsigned char)((var176 & 255))))));
                            if (((unsigned long)((unsigned int)(arg1)) != 7)) {
                                var209 = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + 0x1c))));
                                ret = (unsigned int)((unsigned char)((((unsigned long)(var209) >> 8) & 255)));
                                var224 = (double)((int)(ret));
                                var28 = (var28 + ((var194 * var224) + (double)((int)((unsigned int)((unsigned char)((var209 & 255)))))));
                                var7 = (var7 + var224);
                            }
                        }
                    }
                }
            }
        }
    }
    ret = (long long)(var28);
    return ((long long)(var7) + (ret * 1000));
}
complex_float_multiply fail 43 lines
// glaurung: complex_float_multiply @ 0x11b0
int64_t complex_float_multiply(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    extern long __unknown(long, ...);
    extern long __mulsc3(int);
    long local_8;
    long ret;
    long rsp;
    long var25;
    int var27;
    float var62;
    float var84;
    long var86;
    long var87;
    long var88;
    long var89;
    /* asm: cvtdq2ps */
    /* asm: cvtdq2ps */
    var25 = 0;
    var27 = 0;
    /* asm: mulps */
    /* asm: addps */
    var62 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(__unknown(0)) }).value;
    /* asm: mulps */
    var84 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(__unknown(0)) }).value;
    if ((var62 == var62)) {
        var86 = __unknown(0);
        var87 = (var86 * 1000);
        var88 = __unknown(0);
        return (var88 + var87);
    }
    if ((var84 != var84)) {
        rsp = (rsp - 8);
        local_8 = ret;
        var89 = __mulsc3(arg0);
        var62 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(var25) }).value;
        var84 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)((unsigned long)((unsigned int)(var27))) }).value;
        rsp = (rsp + 8);
    }
    var86 = __unknown(0);
    var87 = (var86 * 1000);
    var88 = __unknown(0);
    return (var88 + var87);
}
complex_multiply fail 38 lines
// glaurung: complex_multiply @ 0x1100
int64_t complex_multiply(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    extern long __muldc3(int);
    long local_8;
    long ret;
    double var21;
    double var3;
    double var32;
    double var38;
    double var57;
    double var76;
    long var79;
    long var80;
    long var81;
    long var86;
    var3 = (double)((int)(arg1));
    var21 = (double)((int)(arg0));
    var32 = (double)((int)(arg3));
    var38 = (double)((int)(arg2));
    var57 = ((var21 * var38) - (var3 * var32));
    var76 = ((var38 * var3) + (var21 * var32));
    if ((var57 == var57)) {
        var79 = (long long)(var57);
        var80 = (var79 * 1000);
        var81 = (long long)(var76);
        return (var81 + var80);
    }
    if ((var76 != var76)) {
        local_8 = ret;
        var57 = var21;
        var86 = __muldc3(arg0);
        var76 = var3;
    }
    var79 = (long long)(var57);
    var80 = (var79 * 1000);
    var81 = (long long)(var76);
    return (var81 + var80);
}
complex_through_call pass 10 lines
// glaurung: complex_through_call @ 0x1250
int64_t complex_through_call(int32_t arg0, int32_t arg1, int32_t arg2) {
    double var27;
    double var30;
    double var33;
    var27 = ((double)((int)((unsigned long)((unsigned int)((arg2 & 7))))) + ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0x3fe0000000000000) }).value);
    var30 = ((double)((int)(arg0)) * var27);
    var33 = (var27 * (double)((int)(arg1)));
    return ((long long)((var33 + var33)) + ((long long)((var30 + var30)) * 1000));
}
struct_pair_control pass 12 lines
// glaurung: struct_pair_control @ 0x1450
int64_t struct_pair_control(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    double var0;
    double var3;
    double var6;
    double var9;
    var0 = (double)((int)(arg0));
    var3 = (double)((int)(arg1));
    var6 = (double)((int)(arg2));
    var9 = (double)((int)(arg3));
    return ((long long)(((var0 * var9) + (var3 * var6))) + ((long long)(((var0 * var6) - (var3 * var9))) * 1000));
}

gcc -O2

4/6
complex_add_conj pass 8 lines
// glaurung: complex_add_conj @ 0x11a0
int64_t complex_add_conj(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    double var15;
    double var23;
    var15 = (double)((int)(arg1));
    var23 = (double)((int)(arg3));
    return (((long long)((((double)((int)(arg0)) + (var15 * ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value)) + ((((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value * var23) + (double)((int)(arg2))))) * 1000) + (long long)((var15 - var23)));
}
complex_array_sum pass 33 lines
// glaurung: complex_array_sum @ 0x1300
int64_t complex_array_sum(const int32_t * arg0, int32_t arg1) {
    int i;
    double var1;
    double var12;
    double var17;
    long var18;
    long var19;
    double var31;
    long var7;
    if ((arg0 == 0)) {
        return -1;
    }
    if (((unsigned long)(8) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return -1;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        return 0;
    }
    var1 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
    var7 = (long)((((long)arg0 + ((unsigned long)((unsigned int)((arg1 - 1))) * 4)) + 4));
    var12 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
    var17 = ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0) }).value;
    var18 = (long)arg0;
    do {
        var19 = (unsigned long)((unsigned int)(*(int *)((var18))));
        var18 = (var18 + 4);
        var31 = (double)((int)((unsigned int)((unsigned char)((((unsigned long)(var19) >> 8) & 255)))));
        var12 = (var12 + var31);
        var17 = (var17 + ((double)((int)((unsigned int)((unsigned char)((var19 & 255))))) + (var31 * var1)));
    } while ((var7 != var18));
    return (((long long)(var17) * 1000) + (long long)(var12));
}
complex_float_multiply fail 29 lines
// glaurung: complex_float_multiply @ 0x1200
int64_t complex_float_multiply(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    extern long __mulsc3(int);
    int local_10;
    int local_c;
    int var12;
    float var15;
    float var22;
    float var35;
    float var49;
    float var67;
    float var76;
    long var78;
    var12 = 0;
    var15 = (float)((int)(arg1));
    var22 = (float)((int)(arg3));
    var35 = (float)((int)(arg0));
    var49 = (float)((int)(arg2));
    var67 = ((var35 * var49) - (var15 * var22));
    var76 = ((var35 * var22) + (var49 * var15));
    if (((var67 != var67) | (var76 != var76))) {
        var78 = __mulsc3(arg0);
        local_10 = var78;
        local_c = var12;
        var67 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)((unsigned long)((unsigned int)(local_10))) }).value;
        var76 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)((unsigned long)((unsigned int)(local_c))) }).value;
    }
    return (((long long)(var67) * 1000) + (long long)(var76));
}
complex_multiply fail 23 lines
// glaurung: complex_multiply @ 0x1100
int64_t complex_multiply(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    extern long __muldc3(int);
    double var15;
    double var23;
    double var48;
    double var59;
    double var78;
    double var89;
    long var96;
    var15 = (double)((int)(arg1));
    var23 = (double)((int)(arg3));
    var48 = (double)((int)(arg0));
    var59 = (double)((int)(arg2));
    var78 = ((var48 * var59) - (var15 * var23));
    var89 = ((var48 * var23) + (var59 * var15));
    if (((var78 != var78) | (var89 != var89))) {
        var78 = var48;
        var96 = __muldc3(arg0);
        var89 = var15;
    }
    return (((long long)(var78) * 1000) + (long long)(var89));
}
complex_through_call pass 10 lines
// glaurung: complex_through_call @ 0x12a0
int64_t complex_through_call(int32_t arg0, int32_t arg1, int32_t arg2) {
    double var31;
    double var40;
    double var43;
    var31 = ((double)((int)((unsigned long)((unsigned int)((arg2 & 7))))) + ((union { unsigned long long bits; double value; }){ .bits = (unsigned long long)(0x3fe0000000000000) }).value);
    var40 = ((double)((int)(arg0)) * var31);
    var43 = (var31 * (double)((int)(arg1)));
    return (((long long)((var40 + var40)) * 1000) + (long long)((var43 + var43)));
}
struct_pair_control pass 12 lines
// glaurung: struct_pair_control @ 0x1390
int64_t struct_pair_control(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
    double var15;
    double var23;
    double var26;
    double var29;
    var15 = (double)((int)(arg0));
    var23 = (double)((int)(arg1));
    var26 = (double)((int)(arg2));
    var29 = (double)((int)(arg3));
    return (((long long)(((var15 * var26) - (var23 * var29))) * 1000) + (long long)(((var15 * var29) + (var23 * var26))));
}

← 213 fixtures