Fixture 121

dense expression

C · 3 functions · 4 lanes · 12 of 12 function-lanes behave identically

All 4 lanes recompile and return the same results as the original.

An IOCCC-flavoured expression: comma operators, nested conditionals, compound assignment, and subscript arithmetic packed into a few statements. It is deliberately dense but fully defined -- every side effect is separated by a sequence point.

tests/decompiler_fixtures/src/121_dense_expression.c source
#include <stdint.h>

/* An IOCCC-flavoured expression: comma operators, nested conditionals, compound
 * assignment, and subscript arithmetic packed into a few statements. It is
 * deliberately dense but fully defined -- every side effect is separated by a
 * sequence point. */

__attribute__((noinline)) int32_t
dense_fold(int32_t *state, int32_t count, int32_t seed) {
    int32_t i = 0;
    int32_t a = seed;
    int32_t b = 0;
    if (state == 0 || count < 0 || count > 16) {
        return -1;
    }
    for (; i < count; a ^= (b = (a << 1) ^ i), state[i] = a, ++i) {
        a = (a & 1) ? ((a >> 1) ^ 0x5A5A) : (a >> 1);
    }
    return (i ? (state[i - 1] ^ b) : a) + (b ? 1 : 0);
}

__attribute__((noinline)) int32_t
chained_assignment(int32_t seed, int32_t *trace) {
    int32_t a;
    int32_t b;
    int32_t c;
    if (trace == 0) {
        return -1;
    }
    a = b = c = seed;          /* right-associative */
    a += b -= c *= 2;          /* c doubles, b drops, a rises */
    trace[0] = a;
    trace[1] = b;
    trace[2] = c;
    return a + b + c;
}

__attribute__((noinline)) int32_t
conditional_lvalue_select(int32_t which, int32_t *left, int32_t *right) {
    if (left == 0 || right == 0) {
        return -1;
    }
    /* The conditional selects a pointer, then the store happens through it. */
    *(which ? left : right) += 10;
    return *left * 100 + *right;
}

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

3/3
chained_assignment pass 25 lines
// glaurung: chained_assignment @ 0x1210
int32_t chained_assignment(int32_t arg0, int32_t * arg1) {
    int c;
    int b;
    int a;
    long var3;
    long var6;
    // x86-64 prologue: save rbp
    if ((arg1 != 0)) {
        c = arg0;
        b = arg0;
        a = arg0;
        var3 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(c)) << 1)));
        c = var3;
        var6 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(b)) - var3)));
        b = var6;
        a = (var6 + a);
        *(int *)((long)arg1) = a;
        *(int *)(((long)arg1 + 0x4)) = b;
        *(int *)(((long)arg1 + 0x8)) = c;
        return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(a)) + b))) + c));
    } else {
        return (unsigned int)(-1);
    }
}
conditional_lvalue_select pass 21 lines
// glaurung: conditional_lvalue_select @ 0x1290
int32_t conditional_lvalue_select(int32_t arg0, int32_t * arg1, int32_t * arg2) {
    int * local_20;
    int local_4;
    // x86-64 prologue: save rbp
    if ((arg1 == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if ((arg2 == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    local_20 = (((unsigned long)((unsigned int)(arg0)) == 0) ? (int *)arg2 : (int *)arg1);
    *(int *)((local_20)) = ((unsigned long)((unsigned int)(*(int *)(local_20))) + 10);
    local_4 = ((*(int *)((long)arg1) * 100) + *(int *)((long)arg2));
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}
dense_fold pass 42 lines
// glaurung: dense_fold @ 0x1100
int32_t dense_fold(int32_t * arg0, int32_t arg1, int32_t arg2) {
    int i;
    int a;
    int b;
    int local_28;
    int local_2c;
    int local_4;
    long var22;
    // x86-64 prologue: save rbp
    i = 0;
    a = arg2;
    b = 0;
    if ((arg0 == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((long)(arg1) < 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    while ((i < arg1)) {
        local_28 = (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(a)) & 1))) == 0) ? ((int)(a) >> 1) : ((unsigned long)((unsigned int)(((int)(a) >> 1))) ^ 0x5a5a));
        a = local_28;
        var22 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(a)) << 1))) ^ i)));
        b = var22;
        a = (var22 ^ a);
        arg0[(long)(i)] = a;
        i = ((unsigned int)(i) + 1);
    }
    local_2c = (((unsigned long)((unsigned int)(i)) == 0) ? (unsigned long)((unsigned int)(a)) : ((unsigned long)((unsigned int)(arg0[(long)((int)(((unsigned long)((unsigned int)(i)) - 1)))])) ^ (unsigned long)((unsigned int)(b))));
    local_4 = ((unsigned int)(local_2c) + (((unsigned long)((unsigned int)(b)) != 0) ? 1 : 0));
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}

clang -O2

3/3
chained_assignment pass 12 lines
// glaurung: chained_assignment @ 0x11c0
int32_t chained_assignment(int32_t arg0, int32_t * arg1) {
    int b;
    int c;
    if ((arg1 == 0)) {
        return 0xffffffff;
    }
    *(int *)(((long)arg1)) = 0;
    *(int *)(((long)arg1 + 0x4)) = (-(unsigned long)((unsigned int)(arg0)));
    *(int *)(((long)arg1 + 0x8)) = ((unsigned long)((unsigned int)(arg0)) + (unsigned long)((unsigned int)(arg0)));
    return (unsigned int)(arg0);
}
conditional_lvalue_select pass 14 lines
// glaurung: conditional_lvalue_select @ 0x11f0
int32_t conditional_lvalue_select(int32_t arg0, int32_t * arg1, int32_t * arg2) {
    long ret;
    int * var1;
    ret = 0xffffffff;
    if ((arg1 != 0)) {
        if ((arg2 != 0)) {
            var1 = (((unsigned long)((unsigned int)(arg0)) == 0) ? (int *)arg2 : (int *)arg1);
            *(int *)((var1)) = (*(int *)((var1)) + 10);
            ret = (unsigned long)((unsigned int)(((*(int *)(((long)arg1)) * 100) + *(int *)(((long)arg2)))));
        }
    }
    return ret;
}
dense_fold pass 66 lines
// glaurung: dense_fold @ 0x1100
int32_t dense_fold(int32_t * arg0, int32_t arg1, int32_t arg2) {
    int i;
    int a;
    int b;
    long ret;
    long var1;
    long var13;
    long var17;
    long var2;
    long var23;
    long var26;
    long var3;
    long var30;
    long var36;
    long var37;
    long var40;
    long var44;
    long var48;
    long var6;
    ret = 0xffffffff;
    if ((arg0 == 0)) {
        return ret;
    }
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return ret;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        var1 = 0;
        var2 = (unsigned long)((unsigned int)(arg2));
    } else {
        var3 = (unsigned long)((unsigned int)(arg1));
        if (((unsigned long)((unsigned int)(arg1)) != 1)) {
            var6 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var3)) & -2)));
            i = 0;
            a = arg2;
            do {
                var13 = (unsigned long)((unsigned int)(((int)(a) >> 1)));
                var17 = (((unsigned long)((unsigned char)((a & 1))) == 0) ? var13 : (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var13)) ^ 0x5a5a))));
                var23 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(i)) ^ var17))) ^ (unsigned long)((unsigned int)((var17 + var17))))));
                *(int *)(((long)arg0 + i * 4)) = var23;
                var26 = (unsigned long)((unsigned int)(((int)(var23) >> 1)));
                var30 = (((unsigned long)((unsigned char)((var17 & 1))) == 0) ? var26 : (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var26)) ^ 0x5a5a))));
                b = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((i + 1))) ^ (unsigned long)((unsigned int)((var30 + var30))))));
                a = (unsigned long)((unsigned int)((var30 ^ b)));
                *(int *)(((long)arg0 + i * 4 + 0x4)) = a;
                i = (i + 2);
                var36 = (unsigned long)((unsigned int)(i));
                var37 = (unsigned long)((unsigned int)(a));
            } while ((i != var6));
        } else {
            var36 = 0;
            b = var40;
            var37 = (unsigned long)((unsigned int)(arg2));
        }
        if (((unsigned long)((unsigned char)((var3 & 1))) != 0)) {
            var44 = (unsigned long)((unsigned int)(((int)(var37) >> 1)));
            var48 = (((unsigned long)((unsigned char)((var37 & 1))) == 0) ? var44 : (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var44)) ^ 0x5a5a))));
            b = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var36)) ^ (unsigned long)((unsigned int)((var48 + var48))))));
            *(int *)(((long)arg0 + var36 * 4)) = (var48 ^ b);
        }
        var1 = ((unsigned long)((unsigned int)(b)) != 0);
        var2 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)((((long)arg0 + ((long)(arg1) * 4)) - 4)))) ^ b)));
    }
    return (unsigned int)((var1 + var2));
}

gcc -O0

3/3
chained_assignment pass 21 lines
// glaurung: chained_assignment @ 0x11c2
int32_t chained_assignment(int32_t arg0, int32_t * arg1) {
    int c;
    int b;
    int a;
    // x86-64 prologue: save rbp
    if ((arg1 != 0)) {
        c = arg0;
        b = c;
        a = b;
        c = (c << 1);
        b = (b - (unsigned int)(c));
        a = (a + (unsigned int)(b));
        *(int *)((long)arg1) = a;
        *(int *)((arg1 + 1)) = b;
        *(int *)((arg1 + 2)) = c;
        return (unsigned int)(((unsigned long)((unsigned int)(c)) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(a)) + (unsigned long)((unsigned int)(b)))))));
    } else {
        return 0xffffffff;
    }
}
conditional_lvalue_select pass 15 lines
// glaurung: conditional_lvalue_select @ 0x1232
int32_t conditional_lvalue_select(int32_t arg0, int32_t * arg1, int32_t * arg2) {
    // x86-64 prologue: save rbp
    if ((arg1 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if ((arg2 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    *(int *)((((unsigned long)((unsigned int)(arg0)) == 0) ? (long)arg2 : (long)arg1)) = ((unsigned long)((unsigned int)(*(int *)((((unsigned long)((unsigned int)(arg0)) == 0) ? (long)arg2 : (long)arg1)))) + 10);
    // x86-64 epilogue: restore rbp
    return (unsigned int)(((unsigned long)((unsigned int)(*(int *)((long)arg2))) + ((unsigned long)((unsigned int)(*(int *)((long)arg1))) * 100)));
}
dense_fold pass 31 lines
// glaurung: dense_fold @ 0x10f9
int32_t dense_fold(int32_t * arg0, int32_t arg1, int32_t arg2) {
    int i;
    int a;
    int b;
    // x86-64 prologue: save rbp
    i = 0;
    a = arg2;
    b = 0;
    if ((arg0 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((long)(arg1) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    while ((i < arg1)) {
        a = (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(a)) & 1))) == 0) ? (unsigned long)((unsigned int)(((int)(a) >> 1))) : (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((int)(a) >> 1))) ^ 0x5a5a))));
        b = ((unsigned int)(((unsigned long)((unsigned int)(a)) + (unsigned long)((unsigned int)(a)))) ^ i);
        a = (a ^ (unsigned int)(b));
        arg0[(long)(i)] = a;
        i = (i + 1);
    }
    // x86-64 epilogue: restore rbp
    return (unsigned int)(((((unsigned long)((unsigned int)(i)) == 0) ? (unsigned long)((unsigned int)(a)) : (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)(((long)arg0 + (((long)(i) << 2) - 4))))) ^ b)))) + ((unsigned long)((unsigned int)(b)) != 0)));
}

gcc -O2

3/3
chained_assignment pass 15 lines
// glaurung: chained_assignment @ 0x1180
int32_t chained_assignment(int32_t arg0, int32_t * arg1) {
    int c;
    long t138;
    long var0;
    if ((arg1 == 0)) {
        return 0xffffffff;
    }
    var0 = (unsigned long)((unsigned int)((arg0 + arg0)));
    t138 = (-(unsigned long)((unsigned int)(arg0)));
    *(int *)(((long)arg1)) = 0;
    *(int *)(((long)arg1 + 0x8)) = var0;
    *(int *)(((long)arg1 + 0x4)) = t138;
    return (unsigned int)((var0 + t138));
}
conditional_lvalue_select pass 12 lines
// glaurung: conditional_lvalue_select @ 0x11b0
int32_t conditional_lvalue_select(int32_t arg0, int32_t * arg1, int32_t * arg2) {
    int * var1;
    if ((arg1 != 0)) {
        if ((arg2 != 0)) {
            var1 = (((unsigned long)((unsigned int)(arg0)) != 0) ? (int *)arg1 : (int *)arg2);
            *(int *)((var1)) = (*(int *)((var1)) + 10);
            return (unsigned int)(((*(int *)(((long)arg1)) * 100) + *(int *)(((long)arg2))));
        }
    }
    return 0xffffffff;
}
dense_fold pass 41 lines
// glaurung: dense_fold @ 0x1100
int32_t dense_fold(int32_t * arg0, int32_t arg1, int32_t arg2) {
    int i;
    int a;
    int b;
    long var0;
    long var1;
    int var15;
    long var16;
    long var18;
    long var21;
    long var5;
    long var9;
    var0 = (long)arg0;
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return 0xffffffff;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        return (unsigned int)(arg2);
    }
    var1 = (unsigned long)((unsigned int)((arg1 - 1)));
    i = 0;
    var5 = (unsigned long)((unsigned int)(arg2));
    while (1) {
        var9 = (unsigned long)((unsigned int)(((int)(var5) >> 1)));
        var15 = (((unsigned long)((unsigned int)((var5 & 1))) != 0) ? (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var9)) ^ 0x5a5a))) : var9);
        var16 = (unsigned long)((unsigned int)((var15 + var15)));
        var18 = ((unsigned long)((unsigned int)(i)) + 1);
        var21 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var16)) ^ i)));
        var5 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var15)) ^ var21)));
        *(int *)((var0 + i * 4)) = var5;
        if ((i == var1)) {
            break;
        }
        i = var18;
    }
    return (unsigned int)((((unsigned int)(var16) != (unsigned int)(i)) + (unsigned long)((unsigned int)((var21 ^ *(int *)(((var0 + ((long)(arg1) * 4)) - 4)))))));
}

← 213 fixtures