Fixture 149

mba expressions

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

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

Mixed boolean-arithmetic (MBA): expressions that interleave a boolean algebra (&, |, ^, ~) with a ring (+, -, *) over the same words. Because the two structures do not distribute over each other, there is no normal form a compiler's simplifier can push everything into, and rewriting requires per-identity knowledge:

x + y == (x ^ y) + 2 * (x & y) x + y == (x | y) + (x & y) x + y == 2 * (x | y) - (x ^ y) x - y == (x ^ y) - 2 * (~x & y) x | y == (x & y) + (x ^ y) x & y == (x | y) - (x ^ y) 0 == (x ^ y) + 2 * (x & y) - (x | y) - (x & y) [zero polynomial]

Each holds for every uint32_t pair, wraparound included: they are identities over Z/2^32, derived from the fact that x + y splits into the carry-less sum x ^ y plus twice the carries x & y.

Why this breaks decompilers: MBA is the standard defence against symbolic simplification precisely because bit-blasting an MBA expression to a satisfiability query is exponential in the word size, and syntactic peephole rules cover only the handful of forms someone thought to encode. Two failures follow. A simplifier that misses the identity emits fifteen lines of masking where the program adds two numbers — technically faithful, analytically useless, and it drags a bogus "this is a bitmask/flags field" type inference along with it. A simplifier that over-matches applies a rule whose side condition it did not check: (x ^ y) + (x & y) and (x | y) + (x ^ y) look one token away from the identities above but equal neither x + y nor x | y. The zero polynomial is the sharpest case: it is an additive nonce that must fold away entirely, and a decompiler that folds it *almost* right emits confident, readable, wrong arithmetic.

Everything is unsigned, all shifts are by literal counts below 32, and the one buffer-taking function validates its length against a small bound.

tests/decompiler_fixtures/src/149_mba_expressions.c source
#include <stdint.h>

/* Mixed boolean-arithmetic (MBA): expressions that interleave a boolean algebra
 * (&, |, ^, ~) with a ring (+, -, *) over the same words. Because the two
 * structures do not distribute over each other, there is no normal form a
 * compiler's simplifier can push everything into, and rewriting requires
 * per-identity knowledge:
 *
 *     x + y  ==  (x ^ y) + 2 * (x & y)
 *     x + y  ==  (x | y) + (x & y)
 *     x + y  ==  2 * (x | y) - (x ^ y)
 *     x - y  ==  (x ^ y) - 2 * (~x & y)
 *     x | y  ==  (x & y) + (x ^ y)
 *     x & y  ==  (x | y) - (x ^ y)
 *     0      ==  (x ^ y) + 2 * (x & y) - (x | y) - (x & y)     [zero polynomial]
 *
 * Each holds for every uint32_t pair, wraparound included: they are identities
 * over Z/2^32, derived from the fact that `x + y` splits into the carry-less
 * sum `x ^ y` plus twice the carries `x & y`.
 *
 * Why this breaks decompilers: MBA is the standard defence against symbolic
 * simplification precisely because bit-blasting an MBA expression to a
 * satisfiability query is exponential in the word size, and syntactic peephole
 * rules cover only the handful of forms someone thought to encode. Two failures
 * follow. A simplifier that misses the identity emits fifteen lines of masking
 * where the program adds two numbers — technically faithful, analytically
 * useless, and it drags a bogus "this is a bitmask/flags field" type inference
 * along with it. A simplifier that over-matches applies a rule whose side
 * condition it did not check: `(x ^ y) + (x & y)` and `(x | y) + (x ^ y)` look
 * one token away from the identities above but equal neither `x + y` nor
 * `x | y`. The zero polynomial is the sharpest case: it is an additive nonce
 * that must fold away entirely, and a decompiler that folds it *almost* right
 * emits confident, readable, wrong arithmetic.
 *
 * Everything is unsigned, all shifts are by literal counts below 32, and the
 * one buffer-taking function validates its length against a small bound.
 */

#define MBA149_MAX_BYTES 16

static uint32_t mba149_add_xor_and(uint32_t x, uint32_t y) {
    return (x ^ y) + ((x & y) << 1);
}

static uint32_t mba149_add_or_and(uint32_t x, uint32_t y) {
    return (x | y) + (x & y);
}

static uint32_t mba149_add_or_xor(uint32_t x, uint32_t y) {
    return ((x | y) << 1) - (x ^ y);
}

static uint32_t mba149_sub_xor_andnot(uint32_t x, uint32_t y) {
    return (x ^ y) - (((~x) & y) << 1);
}

/* Identically zero for every input pair: (x + y) - (x | y) - (x & y). */
static uint32_t mba149_zero(uint32_t x, uint32_t y) {
    return ((x ^ y) + ((x & y) << 1)) - (x | y) - (x & y);
}

/* Three independent encodings of the same addition, combined. `divergence` is
 * zero in every execution — it is an opaque zero built out of the identities
 * disagreeing with each other, which they never do. */
__attribute__((noinline)) uint32_t
mba_add_identities(uint32_t x, uint32_t y) {
    uint32_t a = mba149_add_xor_and(x, y);
    uint32_t b = mba149_add_or_and(x, y);
    uint32_t c = mba149_add_or_xor(x, y);
    uint32_t divergence = (a ^ b) | (b ^ c);
    return (a + (c ^ 0x9E3779B9u)) ^ divergence;
}

/* Subtraction via the carry-borrow identity, then re-added through a different
 * identity: the round trip must recover `x`. */
__attribute__((noinline)) uint32_t
mba_sub_identity(uint32_t x, uint32_t y) {
    uint32_t difference = mba149_sub_xor_andnot(x, y);
    return mba149_add_or_and(difference, y) ^ difference;
}

/* An MBA zero polynomial used as an additive nonce around a real computation.
 * Correct output is `x * y + (x ^ y)`; anything else means the nonce did not
 * fold to zero. */
__attribute__((noinline)) uint32_t
mba_zero_polynomial(uint32_t x, uint32_t y) {
    uint32_t nonce = mba149_zero(x, y);
    uint32_t nonce2 = mba149_zero(y, x ^ 0xFFFFu);
    return (x * y) + (x ^ y) + nonce + (nonce2 << 3);
}

/* Branchless select written in MBA form. `flag`'s low bit picks a value; the
 * mask is built by negation and the blend by xor-and-xor, so no comparison and
 * no branch appear in the source at all. */
__attribute__((noinline)) uint32_t
mba_select(uint32_t x, uint32_t y, uint32_t flag) {
    uint32_t mask = 0u - (flag & 1u);
    uint32_t blended = x ^ ((x ^ y) & mask);
    return mba149_add_xor_and(blended, mba149_zero(x, y));
}

/* Bit-count by the classic SWAR reduction, but with every add replaced by an
 * MBA encoding. The closed form is popcount; a decompiler that recovers the
 * masks but mangles one adder returns a plausible near-popcount. */
__attribute__((noinline)) uint32_t
mba_bit_population(uint32_t value) {
    uint32_t v = value - ((value >> 1) & 0x55555555u);
    v = mba149_add_or_and(v & 0x33333333u, (v >> 2) & 0x33333333u);
    v = mba149_add_xor_and(v, v >> 4) & 0x0F0F0F0Fu;
    return (v * 0x01010101u) >> 24;
}

/* An MBA-mixed rolling hash over a caller-owned byte buffer. Each round uses a
 * different identity so no single peephole rule cleans the loop up. */
__attribute__((noinline)) uint32_t
mba_mix_buffer(uint8_t *data, int32_t length, uint32_t seed) {
    int32_t index;
    uint32_t acc = seed;

    if (data == 0 || length < 0 || length > MBA149_MAX_BYTES) {
        return 0u;
    }

    for (index = 0; index < length; ++index) {
        uint32_t byte = (uint32_t)data[index];
        acc = mba149_add_xor_and(acc, byte);
        acc = mba149_add_or_xor(acc << 3, acc >> 7);
        acc = mba149_sub_xor_andnot(acc, mba149_zero(acc, byte));
    }
    return mba149_add_or_and(acc, (uint32_t)length);
}

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

6/6
mba_add_identities pass 23 lines
// glaurung: mba_add_identities @ 0x1100
uint32_t mba_add_identities(uint32_t arg0, uint32_t arg1) {
    extern unsigned int mba149_add_or_and(unsigned int, unsigned int);
    extern unsigned int mba149_add_or_xor(unsigned int, unsigned int);
    extern unsigned int mba149_add_xor_and(unsigned int, unsigned int);
    unsigned int a;
    unsigned int b;
    unsigned int c;
    unsigned int divergence;
    unsigned int var0;
    unsigned int var2;
    unsigned int var4;
    // x86-64 prologue: save rbp, frame 32 bytes
    var0 = mba149_add_xor_and(arg0, arg1);
    a = var0;
    var2 = mba149_add_or_and(arg0, arg1);
    b = var2;
    var4 = mba149_add_or_xor(arg0, arg1);
    c = var4;
    divergence = ((unsigned int)((a ^ b)) | (unsigned int)((b ^ c)));
    // x86-64 epilogue: restore rbp
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(a) + (unsigned long)((unsigned int)(((unsigned long)(c) ^ -0x61c88647LL)))))) ^ divergence));
}
mba_bit_population pass 16 lines
// glaurung: mba_bit_population @ 0x12e0
uint32_t mba_bit_population(uint32_t arg0) {
    extern unsigned int mba149_add_or_and(unsigned int, unsigned int);
    extern unsigned int mba149_add_xor_and(unsigned int, unsigned int);
    unsigned int v;
    unsigned int var16;
    unsigned int var21;
    // x86-64 prologue: save rbp, frame 16 bytes
    v = (arg0 - (unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(arg0) >> 1))) & 0x55555555)));
    var16 = mba149_add_or_and((unsigned long)((unsigned int)((v & 0x33333333))), (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(v) >> 2))) & 0x33333333))));
    v = var16;
    var21 = mba149_add_xor_and(v, (unsigned long)((unsigned int)(((unsigned int)(v) >> 4))));
    v = (var21 & 0xf0f0f0f);
    // x86-64 epilogue: restore rbp
    return (unsigned int)(((unsigned long)((unsigned int)((v * 0x1010101))) >> 24));
}
mba_mix_buffer pass 47 lines
// glaurung: mba_mix_buffer @ 0x1350
uint32_t mba_mix_buffer(uint8_t * arg0, int32_t arg1, uint32_t arg2) {
    extern unsigned int mba149_add_or_and(unsigned int, unsigned int);
    extern unsigned int mba149_add_or_xor(unsigned int, unsigned int);
    extern unsigned int mba149_add_xor_and(unsigned int, unsigned int);
    extern unsigned int mba149_sub_xor_andnot(unsigned int, unsigned int);
    extern unsigned int mba149_zero(unsigned int, unsigned int);
    unsigned int acc;
    int index;
    unsigned int byte;
    int local_28;
    int local_4;
    unsigned int var14;
    unsigned int var17;
    unsigned int var19;
    unsigned int var24;
    unsigned int var7;
    // x86-64 prologue: save rbp, frame 48 bytes
    acc = arg2;
    if ((arg0 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if (((long)(arg1) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    for (index = 0; (index < arg1); index++) {
        byte = (unsigned char)(arg0[index]);
        var7 = mba149_add_xor_and(acc, byte);
        acc = var7;
        var14 = mba149_add_or_xor((unsigned long)((unsigned int)((acc << 3))), (unsigned long)((unsigned int)(((unsigned int)(acc) >> 7))));
        acc = var14;
        local_28 = acc;
        var17 = mba149_zero(acc, byte);
        var19 = mba149_sub_xor_andnot((unsigned long)((unsigned int)(local_28)), var17);
        acc = var19;
    }
    var24 = mba149_add_or_and(acc, (unsigned long)((unsigned int)(arg1)));
    local_4 = var24;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}
mba_select pass 18 lines
// glaurung: mba_select @ 0x1290
uint32_t mba_select(uint32_t arg0, uint32_t arg1, uint32_t arg2) {
    extern unsigned int mba149_add_xor_and(unsigned int, unsigned int);
    extern unsigned int mba149_zero(unsigned int, unsigned int);
    unsigned int mask;
    unsigned int blended;
    int local_18;
    unsigned int ret;
    unsigned int var16;
    // x86-64 prologue: save rbp, frame 32 bytes
    mask = (0 - (unsigned int)((arg2 & 1)));
    blended = (arg0 ^ (unsigned int)(((unsigned long)((unsigned int)((arg0 ^ arg1))) & mask)));
    local_18 = blended;
    var16 = mba149_zero(arg0, arg1);
    ret = mba149_add_xor_and((unsigned long)((unsigned int)(local_18)), var16);
    // x86-64 epilogue: restore rbp
    return ret;
}
mba_sub_identity pass 14 lines
// glaurung: mba_sub_identity @ 0x11c0
uint32_t mba_sub_identity(uint32_t arg0, uint32_t arg1) {
    extern unsigned int mba149_add_or_and(unsigned int, unsigned int);
    extern unsigned int mba149_sub_xor_andnot(unsigned int, unsigned int);
    unsigned int difference;
    unsigned int var0;
    unsigned int var2;
    // x86-64 prologue: save rbp, frame 16 bytes
    var0 = mba149_sub_xor_andnot(arg0, arg1);
    difference = var0;
    var2 = mba149_add_or_and(difference, arg1);
    // x86-64 epilogue: restore rbp
    return (unsigned int)((var2 ^ difference));
}
mba_zero_polynomial pass 15 lines
// glaurung: mba_zero_polynomial @ 0x1210
uint32_t mba_zero_polynomial(uint32_t arg0, uint32_t arg1) {
    extern unsigned int mba149_zero(unsigned int, unsigned int);
    unsigned int nonce;
    unsigned int nonce2;
    unsigned int var0;
    unsigned int var4;
    // x86-64 prologue: save rbp, frame 16 bytes
    var0 = mba149_zero(arg0, arg1);
    nonce = var0;
    var4 = mba149_zero(arg1, (unsigned long)((unsigned int)((arg0 ^ 0xffff))));
    nonce2 = var4;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) * arg1))) + (unsigned long)((unsigned int)(((unsigned long)(arg0) ^ arg1)))))) + nonce))) + (unsigned long)((unsigned int)(((unsigned long)(nonce2) << 3)))));
}

clang -O2

6/6
mba_add_identities pass 17 lines
// glaurung: mba_add_identities @ 0x1100
uint32_t mba_add_identities(uint32_t arg0, uint32_t arg1) {
    unsigned int a;
    unsigned int b;
    unsigned int c;
    unsigned int divergence;
    long var12;
    long var2;
    long var7;
    long var9;
    var2 = (unsigned long)((unsigned int)((arg1 ^ arg0)));
    a = (unsigned long)((unsigned int)((var2 + ((unsigned long)((unsigned int)((arg1 & arg0))) * 2))));
    var7 = (unsigned long)((unsigned int)((arg1 + arg0)));
    var9 = (unsigned long)((unsigned int)((arg1 | arg0)));
    var12 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var9 + var9))) - var2)));
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var12 ^ -0x61c88647LL))) + a))) ^ (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var7 ^ var12))) | (unsigned long)((unsigned int)(((unsigned long)(a) ^ var7))))))));
}
mba_bit_population pass 11 lines
// glaurung: mba_bit_population @ 0x11b0
uint32_t mba_bit_population(uint32_t arg0) {
    unsigned int v;
    int var16;
    long var21;
    long var7;
    var7 = (unsigned long)((unsigned int)((arg0 - (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(arg0) >> 1))) & 0x55555555))))));
    var16 = ((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var7)) >> 2))) & 0x33333333)) + (unsigned int)(((unsigned long)((unsigned int)(var7)) & 0x33333333)));
    var21 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var16)) >> 4)));
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var21)) ^ (unsigned long)((unsigned int)(var16))))) + ((unsigned long)((unsigned int)((var21 & (unsigned long)((unsigned int)(var16))))) * 2)))) & 0xf0f0f0f))) * 0x1010101))) >> 24));
}
mba_mix_buffer pass 43 lines
// glaurung: mba_mix_buffer @ 0x11f0
uint32_t mba_mix_buffer(uint8_t * arg0, int32_t arg1, uint32_t arg2) {
    int index;
    unsigned int byte;
    unsigned int acc;
    long ret;
    long var1;
    long var13;
    long var14;
    long var17;
    long var20;
    long var37;
    long var43;
    long var47;
    long var6;
    ret = 0;
    if ((arg0 == 0)) {
        return ret;
    }
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return ret;
    }
    var1 = (unsigned long)(arg2);
    if (((unsigned long)((unsigned int)(arg1)) != 0)) {
        index = 0;
        var6 = (unsigned long)(arg2);
        while (((unsigned long)((unsigned int)(arg1)) != index)) {
            byte = (unsigned int)((unsigned char)(*(char *)(((long)arg0 + index))));
            var13 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var6)) ^ byte))) + ((unsigned long)((unsigned int)((var6 & byte))) * 2))));
            var14 = (unsigned long)((unsigned int)((var13 * 8)));
            var17 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var13)) >> 7)));
            var20 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var17)) | var14)));
            acc = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var20 + var20))) - (unsigned long)((unsigned int)((var17 ^ var14))))));
            var37 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((acc ^ byte))) - (unsigned long)((unsigned int)((byte + acc)))))) + ((unsigned long)((unsigned int)((acc & byte))) * 2))));
            var43 = (unsigned long)((unsigned int)(((~acc) & var37)));
            var47 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var37)) ^ acc))) - (unsigned long)((unsigned int)((var43 + var43))))));
            index = (index + 1);
            var6 = var47;
            var1 = var47;
        }
    }
    return (unsigned int)((var1 + arg1));
}
mba_select pass 12 lines
// glaurung: mba_select @ 0x1180
uint32_t mba_select(uint32_t arg0, uint32_t arg1, uint32_t arg2) {
    unsigned int blended;
    unsigned int mask;
    long var17;
    long var5;
    long var9;
    var5 = (unsigned long)((unsigned int)((arg1 ^ arg0)));
    var9 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((-(unsigned long)((unsigned int)((arg2 & 1)))) & var5))) ^ arg0)));
    var17 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var5 - (unsigned long)((unsigned int)((arg1 + arg0)))))) + ((unsigned long)((unsigned int)((arg1 & arg0))) * 2))));
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var9)) ^ var17))) + ((unsigned long)((unsigned int)((var9 & var17))) * 2)));
}
mba_sub_identity pass 8 lines
// glaurung: mba_sub_identity @ 0x1130
uint32_t mba_sub_identity(uint32_t arg0, uint32_t arg1) {
    unsigned int difference;
    long var5;
    var5 = (unsigned long)((unsigned int)(((~arg0) & arg1)));
    difference = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg1 ^ arg0))) - (unsigned long)((unsigned int)((var5 + var5))))));
    return (unsigned int)(((unsigned long)((unsigned int)((arg1 + difference))) ^ difference));
}
mba_zero_polynomial pass 7 lines
// glaurung: mba_zero_polynomial @ 0x1150
uint32_t mba_zero_polynomial(uint32_t arg0, uint32_t arg1) {
    unsigned int nonce2;
    long var2;
    var2 = (unsigned long)((unsigned int)((arg0 ^ 0xffff)));
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg1) * arg0))) - (unsigned long)((unsigned int)((arg1 + arg0)))))) + ((unsigned long)((unsigned int)(((unsigned long)(arg1) | arg0))) * 2)))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var2)) ^ arg1))) - (unsigned long)((unsigned int)((var2 + arg1)))))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var2)) & arg1))) * 2)))) * 8)));
}

gcc -O0

6/6
mba_add_identities pass 23 lines
// glaurung: mba_add_identities @ 0x11b0
uint32_t mba_add_identities(uint32_t arg0, uint32_t arg1) {
    extern unsigned int mba149_add_or_and(unsigned int, unsigned int);
    extern unsigned int mba149_add_or_xor(unsigned int, unsigned int);
    extern unsigned int mba149_add_xor_and(unsigned int, unsigned int);
    unsigned int a;
    unsigned int b;
    unsigned int c;
    unsigned int divergence;
    unsigned int var10;
    unsigned int var2;
    unsigned int var6;
    // x86-64 prologue: save rbp, frame 24 bytes
    var2 = mba149_add_xor_and(arg0, arg1);
    a = var2;
    var6 = mba149_add_or_and(arg0, arg1);
    b = var6;
    var10 = mba149_add_or_xor(arg0, arg1);
    c = var10;
    divergence = ((unsigned int)((b ^ c)) | (unsigned int)((a ^ b)));
    // x86-64 epilogue: restore rbp
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(a) + (unsigned long)((unsigned int)(((unsigned long)(c) ^ -0x61c88647LL)))))) ^ divergence));
}
mba_bit_population pass 16 lines
// glaurung: mba_bit_population @ 0x1302
uint32_t mba_bit_population(uint32_t arg0) {
    extern unsigned int mba149_add_or_and(unsigned int, unsigned int);
    extern unsigned int mba149_add_xor_and(unsigned int, unsigned int);
    unsigned int v;
    unsigned int var20;
    unsigned int var28;
    // x86-64 prologue: save rbp, frame 24 bytes
    v = (arg0 - (unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(arg0) >> 1))) & 0x55555555)));
    var20 = mba149_add_or_and((unsigned long)((unsigned int)((v & 0x33333333))), (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(v) >> 2))) & 0x33333333))));
    v = var20;
    var28 = mba149_add_xor_and(v, (unsigned long)((unsigned int)(((unsigned int)(v) >> 4))));
    v = (var28 & 0xf0f0f0f);
    // x86-64 epilogue: restore rbp
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(v) * 0x1010101))) >> 24));
}
mba_mix_buffer pass 43 lines
// glaurung: mba_mix_buffer @ 0x1370
uint32_t mba_mix_buffer(uint8_t * arg0, int32_t arg1, uint32_t arg2) {
    extern unsigned int mba149_add_or_and(unsigned int, unsigned int);
    extern unsigned int mba149_add_or_xor(unsigned int, unsigned int);
    extern unsigned int mba149_add_xor_and(unsigned int, unsigned int);
    extern unsigned int mba149_sub_xor_andnot(unsigned int, unsigned int);
    extern unsigned int mba149_zero(unsigned int, unsigned int);
    unsigned int acc;
    int index;
    unsigned int byte;
    unsigned int ret;
    unsigned int var10;
    unsigned int var20;
    unsigned int var24;
    unsigned int var28;
    // x86-64 prologue: save rbp, frame 32 bytes
    acc = arg2;
    if ((arg0 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if (((long)(arg1) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    for (index = 0; (index < arg1); index++) {
        byte = (unsigned char)(((unsigned int)((unsigned char)(arg0[index])) & 255));
        var10 = mba149_add_xor_and(acc, byte);
        acc = var10;
        var20 = mba149_add_or_xor((unsigned long)((unsigned int)((acc << 3))), (unsigned long)((unsigned int)(((unsigned int)(acc) >> 7))));
        acc = var20;
        var24 = mba149_zero(acc, byte);
        var28 = mba149_sub_xor_andnot(acc, var24);
        acc = var28;
    }
    ret = mba149_add_or_and(acc, (unsigned long)((unsigned int)(arg1)));
    // x86-64 epilogue: restore rbp
    return ret;
}
mba_select pass 16 lines
// glaurung: mba_select @ 0x12b4
uint32_t mba_select(uint32_t arg0, uint32_t arg1, uint32_t arg2) {
    extern unsigned int mba149_add_xor_and(unsigned int, unsigned int);
    extern unsigned int mba149_zero(unsigned int, unsigned int);
    unsigned int mask;
    unsigned int blended;
    unsigned int ret;
    unsigned int var13;
    // x86-64 prologue: save rbp, frame 32 bytes
    mask = (-(unsigned long)((unsigned int)((arg2 & 1))));
    blended = ((unsigned int)(((unsigned long)((unsigned int)((arg0 ^ arg1))) & mask)) ^ arg0);
    var13 = mba149_zero(arg0, arg1);
    ret = mba149_add_xor_and(blended, var13);
    // x86-64 epilogue: restore rbp
    return ret;
}
mba_sub_identity pass 14 lines
// glaurung: mba_sub_identity @ 0x121f
uint32_t mba_sub_identity(uint32_t arg0, uint32_t arg1) {
    extern unsigned int mba149_add_or_and(unsigned int, unsigned int);
    extern unsigned int mba149_sub_xor_andnot(unsigned int, unsigned int);
    unsigned int difference;
    unsigned int var2;
    unsigned int var6;
    // x86-64 prologue: save rbp, frame 24 bytes
    var2 = mba149_sub_xor_andnot(arg0, arg1);
    difference = var2;
    var6 = mba149_add_or_and(difference, arg1);
    // x86-64 epilogue: restore rbp
    return (unsigned int)((var6 ^ difference));
}
mba_zero_polynomial pass 15 lines
// glaurung: mba_zero_polynomial @ 0x1257
uint32_t mba_zero_polynomial(uint32_t arg0, uint32_t arg1) {
    extern unsigned int mba149_zero(unsigned int, unsigned int);
    unsigned int nonce;
    unsigned int nonce2;
    unsigned int var2;
    unsigned int var9;
    // x86-64 prologue: save rbp, frame 24 bytes
    var2 = mba149_zero(arg0, arg1);
    nonce = var2;
    var9 = mba149_zero(arg1, (unsigned long)((unsigned int)((arg0 ^ 0xffff))));
    nonce2 = var9;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(nonce2) << 3))) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) * arg1))) + (unsigned long)((unsigned int)(((unsigned long)(arg0) ^ arg1)))))) + (unsigned long)(nonce))))));
}

gcc -O2

6/6
mba_add_identities pass 17 lines
// glaurung: mba_add_identities @ 0x1100
uint32_t mba_add_identities(uint32_t arg0, uint32_t arg1) {
    unsigned int a;
    unsigned int b;
    unsigned int c;
    unsigned int divergence;
    long var13;
    long var3;
    long var7;
    long var9;
    var3 = (unsigned long)((unsigned int)((arg0 ^ arg1)));
    a = (unsigned long)((unsigned int)((var3 + ((unsigned long)((unsigned int)((arg0 & arg1))) * 2))));
    var7 = (unsigned long)((unsigned int)((arg0 + arg1)));
    var9 = (unsigned long)((unsigned int)((arg0 | arg1)));
    var13 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var9 + var9))) - var3)));
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var7)) ^ a))) | (unsigned long)((unsigned int)((var7 ^ var13)))))) ^ (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var13 ^ -0x61c88647LL))) + a)))));
}
mba_bit_population pass 11 lines
// glaurung: mba_bit_population @ 0x11d0
uint32_t mba_bit_population(uint32_t arg0) {
    unsigned int v;
    int var16;
    long var21;
    long var7;
    var7 = (unsigned long)((unsigned int)((arg0 - (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(arg0) >> 1))) & 0x55555555))))));
    var16 = ((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var7)) >> 2))) & 0x33333333)) + (unsigned int)((var7 & 0x33333333)));
    var21 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var16)) >> 4)));
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var21 ^ (unsigned long)((unsigned int)(var16))))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var21)) & (unsigned long)((unsigned int)(var16))))) * 2)))) & 0xf0f0f0f))) * 0x1010101))) >> 24));
}
mba_mix_buffer pass 52 lines
// glaurung: mba_mix_buffer @ 0x1210
uint32_t mba_mix_buffer(uint8_t * arg0, int32_t arg1, uint32_t arg2) {
    unsigned int byte;
    unsigned int acc;
    int index;
    long var0;
    long var15;
    long var18;
    long var2;
    long var21;
    long var26;
    int var3;
    long var33;
    long var44;
    long var5;
    long var50;
    long var54;
    long var6;
    long var7;
    var0 = (unsigned long)((unsigned int)(arg1));
    if ((arg0 == 0)) {
        return 0;
    }
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return 0;
    }
    var2 = (unsigned long)(arg2);
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        var3 = (var0 + var2);
        return (unsigned int)(var3);
    }
    var5 = (long)((((long)arg0 + (unsigned long)((unsigned int)((arg1 - 1)))) + 1));
    var6 = (long)arg0;
    var7 = (unsigned long)(arg2);
    do {
        byte = (unsigned int)((unsigned char)(*(char *)((var6))));
        var6 = (var6 + 1);
        var15 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var7 ^ byte))) + ((unsigned long)((unsigned int)((byte & var7))) * 2))));
        var18 = (unsigned long)((unsigned int)((var15 << 3)));
        var21 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var15)) >> 7)));
        var26 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var21)) | var18)));
        acc = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var26 + var26))) - (unsigned long)((unsigned int)((var21 ^ var18))))));
        var33 = (unsigned long)((unsigned int)((byte & acc)));
        var44 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var33 + var33))) - (unsigned long)((unsigned int)((byte | acc)))))) + (unsigned long)((unsigned int)((byte ^ acc)))))) - var33)));
        var50 = (unsigned long)((unsigned int)(((~acc) & var44)));
        var54 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var44)) ^ acc))) - (unsigned long)((unsigned int)((var50 + var50))))));
        var7 = var54;
        var2 = var54;
    } while ((var5 != var6));
    var3 = (var0 + var2);
    return (unsigned int)(var3);
}
mba_select pass 12 lines
// glaurung: mba_select @ 0x11a0
uint32_t mba_select(uint32_t arg0, uint32_t arg1, uint32_t arg2) {
    unsigned int blended;
    unsigned int mask;
    long var14;
    long var18;
    long var5;
    var5 = (unsigned long)((unsigned int)((arg0 ^ arg1)));
    var14 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((-(unsigned long)((unsigned int)((arg2 & 1)))) & var5))) ^ arg0)));
    var18 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var5 + (unsigned long)((unsigned int)((arg0 & arg1)))))) - (unsigned long)((unsigned int)((arg0 | arg1))))));
    return (unsigned int)(((unsigned long)((unsigned int)((var14 ^ var18))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var14)) & var18))) * 2)));
}
mba_sub_identity pass 8 lines
// glaurung: mba_sub_identity @ 0x1130
uint32_t mba_sub_identity(uint32_t arg0, uint32_t arg1) {
    unsigned int difference;
    long var3;
    var3 = (unsigned long)((unsigned int)(((~arg0) & arg1)));
    difference = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg0 ^ arg1))) - (unsigned long)((unsigned int)((var3 + var3))))));
    return (unsigned int)(((unsigned long)((unsigned int)((arg1 + difference))) ^ difference));
}
mba_zero_polynomial pass 10 lines
// glaurung: mba_zero_polynomial @ 0x1150
uint32_t mba_zero_polynomial(uint32_t arg0, uint32_t arg1) {
    long var17;
    long var4;
    long var8;
    var4 = (unsigned long)((unsigned int)((arg0 & arg1)));
    var8 = (unsigned long)((unsigned int)((arg0 ^ 0xffff)));
    var17 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var8)) & arg1)));
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) * arg1))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) ^ arg1))) + var4))) * 2)))) - (unsigned long)((unsigned int)((arg0 | arg1)))))) - var4))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var17 + var17))) - (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var8)) | arg1)))))) + (unsigned long)((unsigned int)((var8 ^ arg1)))))) - var17))) * 8)));
}

← 213 fixtures