Fixture 212

loop with returning arm

C · 4 functions · 4 lanes · 15 of 16 function-lanes behave identically

One lane has a function that returns a different result after decompilation: clang-O2 (3/4).

A loop containing a multi-way dispatch, ONE OF WHOSE ARMS RETURNS.

WHY THE RETURNING ARM IS THE WHOLE POINT. Cfg::ipostdom is computed once per function against the function exit, with no notion of a loop-relative join. When an arm inside the loop returns, the shared function epilogue becomes the immediate post-dominator of every conditional in the loop body — even though, for every path that continues iterating, the real join is the latch. detect_if_shape's post-dominator fallback then builds both arms with stop_at = Some(epilogue), the arm that continues walks straight past the latch, and the loop body ends at the first case with the remainder stranded.

The corrective guard at the fallback cannot fire for this shape: it requires stop_at.is_some() (absent at function top level, where build_full passes None) and either that the boundary does not dominate the conditional (false inside a loop) or that a multiway block sits between the arm and the boundary (false for a comparison ladder).

This is the statemachine shape. It EXISTS in tests/decbench_corpus/, but that population is scored by metric ratchet only — no execution differential, no structural predicates, no arch sweep — so the fixture matrix has never seen it. 04_switch_shapes has a returning arm but no loop; 13_loop_early_exit has a returning loop but no dispatch; 05_cleanup_and_state_machine has a protocol FSM whose arms all break. The combination is what fails, and nothing covered it.

fsm_returns_from_arm is a byte-for-byte port of the DecBench program.

tests/decompiler_fixtures/src/212_loop_with_returning_arm.c source
#include <stdint.h>

/* A loop containing a multi-way dispatch, ONE OF WHOSE ARMS RETURNS.
 *
 * WHY THE RETURNING ARM IS THE WHOLE POINT. `Cfg::ipostdom` is computed once
 * per function against the function exit, with no notion of a loop-relative
 * join. When an arm inside the loop returns, the shared function epilogue
 * becomes the immediate post-dominator of every conditional in the loop body —
 * even though, for every path that continues iterating, the real join is the
 * latch. `detect_if_shape`'s post-dominator fallback then builds both arms with
 * `stop_at = Some(epilogue)`, the arm that continues walks straight past the
 * latch, and the loop body ends at the first case with the remainder stranded.
 *
 * The corrective guard at the fallback cannot fire for this shape: it requires
 * `stop_at.is_some()` (absent at function top level, where `build_full` passes
 * `None`) and either that the boundary does not dominate the conditional
 * (false inside a loop) or that a multiway block sits between the arm and the
 * boundary (false for a comparison ladder).
 *
 * This is the `statemachine` shape. It EXISTS in `tests/decbench_corpus/`, but
 * that population is scored by metric ratchet only — no execution differential,
 * no structural predicates, no arch sweep — so the fixture matrix has never
 * seen it. `04_switch_shapes` has a returning arm but no loop;
 * `13_loop_early_exit` has a returning loop but no dispatch;
 * `05_cleanup_and_state_machine` has a protocol FSM whose arms all `break`.
 * The combination is what fails, and nothing covered it.
 *
 * `fsm_returns_from_arm` is a byte-for-byte port of the DecBench program.
 */

/* The DecBench `statemachine` program: a for-loop containing a switch, one of
 * whose arms returns. */
__attribute__((noinline)) int32_t fsm_returns_from_arm(const uint8_t *in,
                                                       int32_t n) {
    int32_t st = 0;
    if (in == 0 || n < 0 || n > 32) {
        return -1;
    }
    for (int32_t i = 0; i < n; i++) {
        uint8_t c = in[i];
        switch (st) {
        case 0: st = (c == 'a') ? 1 : 0; break;
        case 1: st = (c == 'b') ? 2 : (c == 'a' ? 1 : 0); break;
        case 2: st = (c == 'c') ? 3 : 0; break;
        case 3: return 1;
        }
    }
    return st == 3;
}

/* Two returning arms with DIFFERENT values, so a structurer that merges them
 * into one epilogue changes the answer rather than only the shape. */
__attribute__((noinline)) int32_t two_returning_arms(const uint8_t *ops,
                                                     int32_t count) {
    int32_t acc = 0;
    if (ops == 0 || count < 0 || count > 32) {
        return -1;
    }
    for (int32_t i = 0; i < count; i++) {
        switch (ops[i] & 3) {
        case 0: acc += 1; break;
        case 1: return acc + 100;
        case 2: acc += 4; break;
        default: return acc + 200;
        }
    }
    return acc;
}

/* A returning arm in a NESTED loop: the inner dispatch's arm returns from the
 * whole function, so the epilogue post-dominates conditionals at two loop
 * depths. */
__attribute__((noinline)) int32_t nested_loop_returning_arm(const uint8_t *ops,
                                                            int32_t outer,
                                                            int32_t inner) {
    int32_t acc = 0;
    if (ops == 0 || outer < 0 || outer > 8 || inner < 0 || inner > 8) {
        return -1;
    }
    for (int32_t o = 0; o < outer; o++) {
        for (int32_t i = 0; i < inner; i++) {
            switch (ops[i] & 3) {
            case 0: acc += o; break;
            case 1: acc ^= i; break;
            case 2: return acc + 50;
            default: acc -= 1; break;
            }
        }
        acc += 7;
    }
    return acc;
}

/* CONTROL: the same loop and the same dispatch, with every arm breaking rather
 * than returning. The epilogue no longer post-dominates the body, so this must
 * recover cleanly — it isolates the returning arm as the cause. */
__attribute__((noinline)) int32_t all_arms_break(const uint8_t *ops,
                                                  int32_t count) {
    int32_t acc = 0;
    if (ops == 0 || count < 0 || count > 32) {
        return -1;
    }
    for (int32_t i = 0; i < count; i++) {
        switch (ops[i] & 3) {
        case 0: acc += 1; break;
        case 1: acc += 2; break;
        case 2: acc += 4; break;
        default: acc = 0; break;
        }
    }
    return acc;
}

Recovered C

Generated by glaurung decompile --style decbench at b47f6b43. baseline.json records the result after recompiling the C and calling it beside the original with seeded inputs.

clang -O2

3/4
all_arms_break pass 103 lines
// glaurung: all_arms_break @ 0x1410
int32_t all_arms_break(const uint8_t * arg0, int32_t arg1) {
    int i;
    int acc;
    long ret;
    long var1;
    long var10;
    long var13;
    long var15;
    long var17;
    int var22;
    long var23;
    long var25;
    long var27;
    int var39;
    long var4;
    long var40;
    long var42;
    long var9;
    ret = 0xffffffff;
    if ((arg0 == 0)) {
        return ret;
    }
    if (((unsigned long)(32) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return ret;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        return 0;
    }
    var1 = (unsigned long)((unsigned int)(arg1));
    if (((unsigned long)((unsigned int)(arg1)) != 1)) {
        var4 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var1)) & -2)));
        var9 = 0;
        var10 = 0;
        do {
            var13 = (unsigned long)((unsigned int)(((unsigned int)((unsigned char)(*(char *)(((long)arg0 + var10)))) & 3)));
            if (((unsigned long)((unsigned int)(var13)) == 2)) {
                var15 = (unsigned long)((unsigned int)((var9 + 4)));
                L_14c3: ;
                var9 = var15;
                var17 = (unsigned long)((unsigned int)(var15));
            } else {
                if (((unsigned long)((unsigned int)(var13)) == 1)) {
                    var15 = (unsigned long)((unsigned int)((var9 + 2)));
                    goto L_14c3;
                } else {
                    var17 = 0;
                    if (((unsigned long)((unsigned int)(var13)) == 0)) {
                        var15 = (unsigned long)((unsigned int)((var9 + 1)));
                        goto L_14c3;
                    }
                }
            }
            var22 = ((unsigned int)((unsigned char)(*(char *)(((long)arg0 + var10 + 0x1)))) & 3);
            var23 = (unsigned long)((unsigned int)(var22));
            if (((unsigned long)((unsigned int)(var22)) == 0)) {
                var25 = (unsigned long)((unsigned int)((var17 + 1)));
                L_1483: ;
                var27 = (unsigned long)((unsigned int)(var25));
            } else {
                if (((unsigned long)((unsigned int)(var23)) == 1)) {
                    var25 = (unsigned long)((unsigned int)((var17 + 2)));
                    goto L_1483;
                } else {
                    var27 = 0;
                    if (((unsigned long)((unsigned int)(var23)) == 2)) {
                        var25 = (unsigned long)((unsigned int)((var17 + 4)));
                        goto L_1483;
                    }
                }
            }
            i = (var10 + 2);
            var9 = var27;
            var10 = (unsigned long)((unsigned int)(i));
        } while ((var4 != i));
    } else {
        var27 = 0;
        i = 0;
    }
    ret = (unsigned long)((unsigned int)(var27));
    if (((unsigned long)((unsigned char)((var1 & 1))) == 0)) {
        return ret;
    }
    var39 = ((unsigned int)((unsigned char)(*(char *)(((long)arg0 + i)))) & 3);
    var40 = (unsigned long)((unsigned int)(var39));
    if (((unsigned long)((unsigned int)(var39)) == 0)) {
        var42 = (unsigned long)((unsigned int)((var27 + 1)));
        L_14ed: ;
        return (unsigned int)(var42);
    }
    if (((unsigned long)((unsigned int)(var40)) == 1)) {
        var42 = (unsigned long)((unsigned int)((var27 + 2)));
        goto L_14ed;
    } else {
        ret = 0;
        if (((unsigned long)((unsigned int)(var40)) != 2)) {
            return ret;
        }
        var42 = (unsigned long)((unsigned int)((var27 + 4)));
        goto L_14ed;
    }
    return ret;
}
fsm_returns_from_arm fail 41 lines
// glaurung: fsm_returns_from_arm @ 0x1100
int32_t fsm_returns_from_arm(const uint8_t * arg0, int32_t arg1) {
    int st;
    int i;
    unsigned char c;
    long ret;
    long var14;
    long var16;
    long var2;
    long var6;
    ret = 0xffffffff;
    if ((arg0 == 0)) {
        return ret;
    }
    if (((unsigned long)(32) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return ret;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        var16 = 0;
        return 0;
    }
    ret = (unsigned long)((unsigned int)(arg1));
    var2 = 0x2000;
    var6 = 0;
    st = 0;
    goto L_1145;
    L_113c: ;
    i = (var6 + 1);
    var6 = (unsigned long)((unsigned int)(i));
    st = var14;
    var16 = var14;
    if ((ret == i)) {
        return ((unsigned long)((unsigned int)(var16)) == 3);
    }
    L_1145: ;
    var14 = (unsigned long)((unsigned int)(st));
    if (((unsigned long)(3) < (unsigned long)((unsigned long)((unsigned int)(st))))) {
        goto L_113c;
    }
    /* unrecovered indirect jump through ((long)((int)(*(int *)((var2 + ((unsigned long)((unsigned int)(st)) * 4))))) + var2) */
}
nested_loop_returning_arm pass 308 lines
// glaurung: nested_loop_returning_arm @ 0x1200
int32_t nested_loop_returning_arm(const uint8_t * arg0, int32_t arg1, int32_t arg2) {
    int o;
    int acc;
    int i;
    long ret;
    int var10;
    int var11;
    int var14;
    long var15;
    long var16;
    long var17;
    long var19;
    int var20;
    int var22;
    long var23;
    int var24;
    long var25;
    long var26;
    long var29;
    int var31;
    long var32;
    int var33;
    long var34;
    long var35;
    long var38;
    int var40;
    long var41;
    int var42;
    long var43;
    long var44;
    long var47;
    int var49;
    long var50;
    int var51;
    long var52;
    long var53;
    long var56;
    int var58;
    long var59;
    int var60;
    long var61;
    long var62;
    long var65;
    int var67;
    long var68;
    int var76;
    long var77;
    ret = 0xffffffff;
    if (((unsigned long)(8) < (unsigned long)((unsigned long)((unsigned int)(arg2))))) {
        return ret;
    }
    ret = 0xffffffff;
    if ((arg0 == 0)) {
        return ret;
    }
    ret = 0xffffffff;
    if (((unsigned long)(8) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return ret;
    }
    if (((unsigned long)((unsigned int)(arg1)) != 0)) {
        o = 0;
        acc = 0;
        goto L_1250;
    }
    return 0;
    L_122e: ;
    acc = (unsigned long)((unsigned int)((acc + o)));
    L_1240: ;
    var10 = (acc + 7);
    acc = (unsigned long)((unsigned int)(var10));
    var11 = (o + 1);
    o = (unsigned long)((unsigned int)(var11));
    ret = (unsigned long)((unsigned int)(var10));
    if (((unsigned int)(arg1) == (unsigned int)(var11))) {
        return ret;
    }
    L_1250: ;
    if (((unsigned long)((unsigned int)(arg2)) == 0)) {
        goto L_1240;
    }
    var14 = ((unsigned int)((unsigned char)(*(char *)(((long)arg0)))) & 3);
    var15 = (unsigned long)((unsigned int)(var14));
    if (((unsigned long)((unsigned int)(var14)) != 0)) {
        var16 = (unsigned long)((unsigned int)(acc));
        if (((unsigned long)((unsigned int)(var15)) != 1)) {
            var17 = (unsigned long)((unsigned int)(acc));
            if (((unsigned long)((unsigned int)(var15)) == 2)) {
                return (unsigned int)((var17 + 50));
            }
            var16 = (unsigned long)((unsigned int)((acc - 1)));
        }
        acc = var16;
        if (((unsigned long)((unsigned int)(arg2)) == 1)) {
            goto L_1240;
        }
        var19 = var16;
        goto L_1288;
    }
    var20 = (acc + o);
    acc = (unsigned long)((unsigned int)(var20));
    var19 = (unsigned long)((unsigned int)(var20));
    if (((unsigned long)((unsigned int)(arg2)) == 1)) {
        goto L_1240;
    }
    L_1288: ;
    var22 = ((unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x1)))) & 3);
    var23 = (unsigned long)((unsigned int)(var22));
    if (((unsigned long)((unsigned int)(var22)) != 0)) {
        if (((unsigned long)((unsigned int)(var23)) == 1)) {
            goto L_12b3;
        }
        var17 = var19;
        if (((unsigned long)((unsigned int)(var23)) == 2)) {
            return (unsigned int)((var17 + 50));
        }
        var24 = (var19 - 1);
        var25 = (unsigned long)((unsigned int)(var24));
        acc = (unsigned long)((unsigned int)(var24));
        if (((unsigned long)((unsigned int)(arg2)) == 2)) {
            goto L_1240;
        }
        var26 = var25;
        goto L_12bb;
    }
    acc = (unsigned long)((unsigned int)((var19 + o)));
    if (((unsigned long)((unsigned int)(arg2)) == 2)) {
        goto L_1240;
    }
    var26 = (unsigned long)((unsigned int)(acc));
    goto L_12bb;
    L_12b3: ;
    var29 = (unsigned long)((unsigned int)((var19 ^ 1)));
    acc = var29;
    var26 = var29;
    if (((unsigned long)((unsigned int)(arg2)) == 2)) {
        goto L_1240;
    }
    L_12bb: ;
    var31 = ((unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x2)))) & 3);
    var32 = (unsigned long)((unsigned int)(var31));
    if (((unsigned long)((unsigned int)(var31)) != 0)) {
        if (((unsigned long)((unsigned int)(var32)) == 1)) {
            goto L_12ee;
        }
        var17 = var26;
        if (((unsigned long)((unsigned int)(var32)) == 2)) {
            return (unsigned int)((var17 + 50));
        }
        var33 = (var26 - 1);
        var34 = (unsigned long)((unsigned int)(var33));
        acc = (unsigned long)((unsigned int)(var33));
        if (((unsigned long)((unsigned int)(arg2)) == 3)) {
            goto L_1240;
        }
        var35 = var34;
        goto L_12fa;
    }
    acc = (unsigned long)((unsigned int)((var26 + o)));
    if (((unsigned long)((unsigned int)(arg2)) == 3)) {
        goto L_1240;
    }
    var35 = (unsigned long)((unsigned int)(acc));
    goto L_12fa;
    L_12ee: ;
    var38 = (unsigned long)((unsigned int)((var26 ^ 2)));
    acc = var38;
    var35 = var38;
    if (((unsigned long)((unsigned int)(arg2)) == 3)) {
        goto L_1240;
    }
    L_12fa: ;
    var40 = ((unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x3)))) & 3);
    var41 = (unsigned long)((unsigned int)(var40));
    if (((unsigned long)((unsigned int)(var40)) != 0)) {
        if (((unsigned long)((unsigned int)(var41)) == 1)) {
            goto L_132d;
        }
        var17 = var35;
        if (((unsigned long)((unsigned int)(var41)) == 2)) {
            return (unsigned int)((var17 + 50));
        }
        var42 = (var35 - 1);
        var43 = (unsigned long)((unsigned int)(var42));
        acc = (unsigned long)((unsigned int)(var42));
        if (((unsigned long)((unsigned int)(arg2)) == 4)) {
            goto L_1240;
        }
        var44 = var43;
        goto L_1339;
    }
    acc = (unsigned long)((unsigned int)((var35 + o)));
    if (((unsigned long)((unsigned int)(arg2)) == 4)) {
        goto L_1240;
    }
    var44 = (unsigned long)((unsigned int)(acc));
    goto L_1339;
    L_132d: ;
    var47 = (unsigned long)((unsigned int)((var35 ^ 3)));
    acc = var47;
    var44 = var47;
    if (((unsigned long)((unsigned int)(arg2)) == 4)) {
        goto L_1240;
    }
    L_1339: ;
    var49 = ((unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x4)))) & 3);
    var50 = (unsigned long)((unsigned int)(var49));
    if (((unsigned long)((unsigned int)(var49)) != 0)) {
        if (((unsigned long)((unsigned int)(var50)) == 1)) {
            goto L_136c;
        }
        var17 = var44;
        if (((unsigned long)((unsigned int)(var50)) == 2)) {
            return (unsigned int)((var17 + 50));
        }
        var51 = (var44 - 1);
        var52 = (unsigned long)((unsigned int)(var51));
        acc = (unsigned long)((unsigned int)(var51));
        if (((unsigned long)((unsigned int)(arg2)) == 5)) {
            goto L_1240;
        }
        var53 = var52;
        goto L_1378;
    }
    acc = (unsigned long)((unsigned int)((var44 + o)));
    if (((unsigned long)((unsigned int)(arg2)) == 5)) {
        goto L_1240;
    }
    var53 = (unsigned long)((unsigned int)(acc));
    goto L_1378;
    L_136c: ;
    var56 = (unsigned long)((unsigned int)((var44 ^ 4)));
    acc = var56;
    var53 = var56;
    if (((unsigned long)((unsigned int)(arg2)) == 5)) {
        goto L_1240;
    }
    L_1378: ;
    var58 = ((unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x5)))) & 3);
    var59 = (unsigned long)((unsigned int)(var58));
    if (((unsigned long)((unsigned int)(var58)) != 0)) {
        if (((unsigned long)((unsigned int)(var59)) == 1)) {
            goto L_13a7;
        }
        var17 = var53;
        if (((unsigned long)((unsigned int)(var59)) == 2)) {
            return (unsigned int)((var17 + 50));
        }
        var60 = (var53 - 1);
        var61 = (unsigned long)((unsigned int)(var60));
        acc = (unsigned long)((unsigned int)(var60));
        if (((unsigned long)((unsigned int)(arg2)) == 6)) {
            goto L_1240;
        }
        var62 = var61;
        goto L_13b3;
    }
    acc = (unsigned long)((unsigned int)((var53 + o)));
    if (((unsigned long)((unsigned int)(arg2)) == 6)) {
        goto L_1240;
    }
    var62 = (unsigned long)((unsigned int)(acc));
    goto L_13b3;
    L_13a7: ;
    var65 = (unsigned long)((unsigned int)((var53 ^ 5)));
    acc = var65;
    var62 = var65;
    if (((unsigned long)((unsigned int)(arg2)) == 6)) {
        goto L_1240;
    }
    L_13b3: ;
    var67 = ((unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x6)))) & 3);
    var68 = (unsigned long)((unsigned int)(var67));
    if (((unsigned long)((unsigned int)(var67)) != 0)) {
        if (((unsigned long)((unsigned int)(var68)) == 1)) {
            goto L_13d0;
        }
        var17 = var62;
        if (((unsigned long)((unsigned int)(var68)) == 2)) {
            return (unsigned int)((var17 + 50));
        }
        acc = (unsigned long)((unsigned int)((var62 - 1)));
        goto L_13d3;
    }
    acc = (unsigned long)((unsigned int)((var62 + o)));
    goto L_13d3;
    L_13d0: ;
    acc = (unsigned long)((unsigned int)((var62 ^ 6)));
    L_13d3: ;
    if (((unsigned long)((unsigned int)(arg2)) == 7)) {
        goto L_1240;
    }
    var76 = ((unsigned int)((unsigned char)(*(char *)(((long)arg0 + 0x7)))) & 3);
    var77 = (unsigned long)((unsigned int)(var76));
    if (((unsigned long)((unsigned int)(var76)) == 0)) {
        goto L_122e;
    }
    if (((unsigned long)((unsigned int)(var77)) != 1)) {
        var17 = (unsigned long)((unsigned int)(acc));
        if (((unsigned long)((unsigned int)(var77)) == 2)) {
            return (unsigned int)((var17 + 50));
        }
        acc = (unsigned long)((unsigned int)((acc - 1)));
        goto L_1240;
    }
    acc = (unsigned long)((unsigned int)((acc ^ 7)));
    goto L_1240;
}
two_returning_arms pass 59 lines
// glaurung: two_returning_arms @ 0x11a0
int32_t two_returning_arms(const uint8_t * arg0, int32_t arg1) {
    int acc;
    int i;
    long ret;
    long var0;
    long var1;
    int var12;
    long var13;
    long var7;
    int var8;
    int var9;
    var0 = 0xffffffff;
    ret = 0xffffffff;
    if ((arg0 == 0)) {
        goto L_11e5;
    }
    ret = var0;
    if (((unsigned long)(32) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        goto L_11e5;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        goto L_11e6;
    }
    var1 = (unsigned long)((unsigned int)(arg1));
    acc = 0;
    var7 = 0;
    goto L_11cb;
    L_11c0: ;
    var9 = (acc + var8);
    acc = (unsigned long)((unsigned int)(var9));
    i = (var7 + 1);
    var7 = (unsigned long)((unsigned int)(i));
    ret = (unsigned long)((unsigned int)(var9));
    if ((var1 == i)) {
        goto L_11e5;
    }
    L_11cb: ;
    var8 = 1;
    var12 = ((unsigned int)((unsigned char)(*(char *)(((long)arg0 + var7)))) & 3);
    var13 = (unsigned long)((unsigned int)(var12));
    if (((unsigned long)((unsigned int)(var12)) == 0)) {
        goto L_11c0;
    }
    if (((unsigned long)((unsigned int)(var13)) != 2)) {
        goto L_11e9;
    }
    var8 = 4;
    goto L_11c0;
    L_11e5: ;
    return ret;
    L_11e6: ;
    return 0;
    L_11e9: ;
    if (((unsigned long)((unsigned int)(var13)) != 1)) {
        return (unsigned int)((acc + 200));
    }
    return (unsigned int)((acc + 100));
}

clang -O0

4/4
all_arms_break pass 33 lines
// glaurung: all_arms_break @ 0x1450
int32_t all_arms_break(const uint8_t * arg0, int32_t arg1) {
    int acc;
    int i;
    int local_20;
    int local_4;
    int var4;
    // x86-64 prologue: save rbp
    acc = 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)) == 32) | ((long)(arg1) < 32)) == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    for (i = 0; (i < arg1); i++) {
        var4 = ((unsigned int)((unsigned char)(arg0[i])) & 3);
        local_20 = var4;
        acc = (((unsigned long)((unsigned int)(var4)) == 0) ? ((unsigned long)((unsigned int)(acc)) + 1) : (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(local_20)) - 1))) == 0) ? ((unsigned long)((unsigned int)(acc)) + 2) : (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(local_20)) - 2))) == 0) ? ((unsigned long)((unsigned int)(acc)) + 4) : 0)));
    }
    local_4 = acc;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}
fsm_returns_from_arm pass 43 lines
// glaurung: fsm_returns_from_arm @ 0x1100
int32_t fsm_returns_from_arm(const uint8_t * arg0, int32_t arg1) {
    int st;
    int i;
    unsigned char c;
    int local_4;
    // x86-64 prologue: save rbp
    st = 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)) == 32) | ((long)(arg1) < 32)) == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    for (i = 0; (i < arg1); i++) {
        c = arg0[i];
        switch ((unsigned int)(st)) {
            case 0:
                st = (((unsigned long)((unsigned long)(c)) == 97) ? 1 : 0);
                break;
            case 1:
                st = (((unsigned long)((unsigned long)(c)) != 98) ? (((unsigned long)((unsigned long)(c)) == 97) ? 1 : 0) : 2);
                break;
            case 2:
                st = (((unsigned long)((unsigned long)(c)) == 99) ? 3 : 0);
                break;
            case 3:
                // x86-64 epilogue: restore rbp
                return 1;
        }
    }
    // x86-64 epilogue: restore rbp
    return ((unsigned long)((unsigned int)(st)) == 3);
}
nested_loop_returning_arm pass 76 lines
// glaurung: nested_loop_returning_arm @ 0x1320
int32_t nested_loop_returning_arm(const uint8_t * arg0, int32_t arg1, int32_t arg2) {
    int acc;
    int o;
    int i;
    int local_28;
    int local_4;
    int var5;
    acc = 0;
    if ((arg0 != 0)) {
        if ((0 <= (long)(arg1))) {
            if (((((unsigned long)((unsigned int)(arg1)) == 8) | ((long)(arg1) < 8)) != 0)) {
                if ((0 <= (long)(arg2))) {
                    if ((((unsigned long)((unsigned int)(arg2)) == 8) | ((long)(arg2) < 8))) {
                        goto L_1374;
                    }
                }
            }
        }
    }
    local_4 = -1;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
    L_1374: ;
    o = 0;
    L_137b: ;
    if ((arg1 <= o)) {
        goto L_1436;
    }
    i = 0;
    L_138e: ;
    if ((arg2 <= i)) {
        goto L_141f;
    }
    var5 = ((unsigned int)((unsigned char)(arg0[i])) & 3);
    local_28 = var5;
    if (((unsigned long)((unsigned int)(var5)) == 0)) {
        goto L_13d9;
    }
    goto L_13b7;
    L_13b7: ;
    if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(local_28)) - 1))) == 0)) {
        goto L_13e7;
    }
    goto L_13c8;
    L_13c8: ;
    if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(local_28)) - 2))) == 0)) {
        goto L_13f5;
    }
    goto L_1403;
    L_13d9: ;
    acc = ((unsigned int)(o) + acc);
    goto L_140c;
    L_13e7: ;
    acc = ((unsigned int)(i) ^ acc);
    goto L_140c;
    L_13f5: ;
    local_4 = ((unsigned int)(acc) + 50);
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
    L_1403: ;
    acc = ((unsigned int)(acc) - 1);
    L_140c: ;
    goto L_1411;
    L_1411: ;
    i = ((unsigned int)(i) + 1);
    goto L_138e;
    L_141f: ;
    acc = ((unsigned int)(acc) + 7);
    o = ((unsigned int)(o) + 1);
    goto L_137b;
    L_1436: ;
    local_4 = acc;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}
two_returning_arms pass 64 lines
// glaurung: two_returning_arms @ 0x1230
int32_t two_returning_arms(const uint8_t * arg0, int32_t arg1) {
    int acc;
    int i;
    int local_20;
    int local_4;
    int var4;
    acc = 0;
    if ((arg0 != 0)) {
        if ((0 <= (long)(arg1))) {
            if ((((unsigned long)((unsigned int)(arg1)) == 32) | ((long)(arg1) < 32))) {
                goto L_126d;
            }
        }
    }
    local_4 = -1;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
    L_126d: ;
    i = 0;
    L_1274: ;
    if ((arg1 <= i)) {
        goto L_130c;
    }
    var4 = ((unsigned int)((unsigned char)(arg0[i])) & 3);
    local_20 = var4;
    if (((unsigned long)((unsigned int)(var4)) == 0)) {
        goto L_12bf;
    }
    goto L_129d;
    L_129d: ;
    if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(local_20)) - 1))) == 0)) {
        goto L_12cd;
    }
    goto L_12ae;
    L_12ae: ;
    if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(local_20)) - 2))) == 0)) {
        goto L_12db;
    }
    goto L_12e9;
    L_12bf: ;
    acc = ((unsigned int)(acc) + 1);
    goto L_12f9;
    L_12cd: ;
    local_4 = ((unsigned int)(acc) + 100);
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
    L_12db: ;
    acc = ((unsigned int)(acc) + 4);
    goto L_12f9;
    L_12e9: ;
    local_4 = ((unsigned int)(acc) + 200);
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
    L_12f9: ;
    goto L_12fe;
    L_12fe: ;
    i = ((unsigned int)(i) + 1);
    goto L_1274;
    L_130c: ;
    local_4 = acc;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}

gcc -O0

4/4
all_arms_break pass 45 lines
// glaurung: all_arms_break @ 0x1323
int32_t all_arms_break(const uint8_t * arg0, int32_t arg1) {
    int acc;
    int i;
    long var8;
    // x86-64 prologue: save rbp
    acc = 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)) == 32) | ((long)(arg1) < 32)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    i = 0;
    while ((i < arg1)) {
        var8 = (unsigned long)((unsigned int)(((unsigned int)((unsigned char)(((unsigned int)((unsigned char)(arg0[i])) & 255))) & 3)));
        if (((unsigned long)((unsigned int)(var8)) == 2)) {
            acc = (acc + 4);
        } else {
            if (((((unsigned long)((unsigned int)(var8)) == 2) | ((long)((int)(var8)) < 2)) == 0)) {
                L_1399: ;
                acc = 0;
            } else {
                if (((unsigned long)((unsigned int)(var8)) == 0)) {
                    acc = (acc + 1);
                } else {
                    if (((unsigned long)((unsigned int)(var8)) == 1)) {
                        acc = (acc + 2);
                    } else {
                        goto L_1399;
                    }
                }
            }
        }
        i = (i + 1);
    }
    // x86-64 epilogue: restore rbp
    return (unsigned int)(acc);
}
fsm_returns_from_arm pass 56 lines
// glaurung: fsm_returns_from_arm @ 0x10f9
int32_t fsm_returns_from_arm(const uint8_t * arg0, int32_t arg1) {
    int st;
    int i;
    unsigned char c;
    int var10;
    long var11;
    st = 0;
    if ((arg0 != 0)) {
        if ((0 <= (long)(arg1))) {
            if ((((unsigned long)((unsigned int)(arg1)) == 32) | ((long)(arg1) < 32))) {
                goto L_112c;
            }
        }
    }
    // x86-64 epilogue: restore rbp
    return 0xffffffff;
    L_112c: ;
    i = 0;
    goto L_11be;
    L_1138: ;
    c = arg0[i];
    switch (st) {
        case 0:
            st = (c == 97);
            break;
        case 1:
            if ((c != 98)) {
                var10 = (c == 97);
                goto L_1197;
            }
            var10 = 2;
            L_1197: ;
            st = var10;
            break;
        case 2:
            if ((c == 99)) {
                var11 = 3;
                goto L_11ae;
            }
            var11 = 0;
            L_11ae: ;
            st = var11;
            break;
        case 3:
            // x86-64 epilogue: restore rbp
            return 1;
    }
    i = (i + 1);
    L_11be: ;
    if ((i < arg1)) {
        goto L_1138;
    }
    // x86-64 epilogue: restore rbp
    return ((unsigned long)((unsigned int)(st)) == 3);
}
nested_loop_returning_arm pass 65 lines
// glaurung: nested_loop_returning_arm @ 0x1269
int32_t nested_loop_returning_arm(const uint8_t * arg0, int32_t arg1, int32_t arg2) {
    int acc;
    int o;
    int i;
    long var7;
    acc = 0;
    if ((arg0 != 0)) {
        if ((0 <= (long)(arg1))) {
            if (((((unsigned long)((unsigned int)(arg1)) == 8) | ((long)(arg1) < 8)) != 0)) {
                if ((0 <= (long)(arg2))) {
                    if ((((unsigned long)((unsigned int)(arg2)) == 8) | ((long)(arg2) < 8))) {
                        goto L_12a8;
                    }
                }
            }
        }
    }
    // x86-64 epilogue: restore rbp
    return 0xffffffff;
    L_12a8: ;
    o = 0;
    goto L_1316;
    L_12b1: ;
    i = 0;
    goto L_1306;
    L_12ba: ;
    var7 = (unsigned long)((unsigned int)(((unsigned int)((unsigned char)(((unsigned int)((unsigned char)(arg0[i])) & 255))) & 3)));
    if (((unsigned long)((unsigned int)(var7)) == 2)) {
        goto L_12f5;
    }
    if (((((unsigned long)((unsigned int)(var7)) == 2) | ((long)((int)(var7)) < 2)) == 0)) {
        goto L_12fd;
    }
    if (((unsigned long)((unsigned int)(var7)) != 0)) {
        if (((unsigned long)((unsigned int)(var7)) == 1)) {
            goto L_12ed;
        }
        goto L_12fd;
    }
    acc = (acc + (unsigned int)(o));
    goto L_1302;
    L_12ed: ;
    acc = (acc ^ (unsigned int)(i));
    goto L_1302;
    L_12f5: ;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(((unsigned long)((unsigned int)(acc)) + 50));
    L_12fd: ;
    acc = (acc - 1);
    L_1302: ;
    i = (i + 1);
    L_1306: ;
    if ((i < arg2)) {
        goto L_12ba;
    }
    acc = (acc + 7);
    o = (o + 1);
    L_1316: ;
    if ((o < arg1)) {
        goto L_12b1;
    }
    // x86-64 epilogue: restore rbp
    return (unsigned int)(acc);
}
two_returning_arms pass 52 lines
// glaurung: two_returning_arms @ 0x11d6
int32_t two_returning_arms(const uint8_t * arg0, int32_t arg1) {
    int acc;
    int i;
    long var7;
    acc = 0;
    if ((arg0 != 0)) {
        if ((0 <= (long)(arg1))) {
            if ((((unsigned long)((unsigned int)(arg1)) == 32) | ((long)(arg1) < 32))) {
                goto L_1206;
            }
        }
    }
    // x86-64 epilogue: restore rbp
    return 0xffffffff;
    L_1206: ;
    i = 0;
    goto L_125c;
    L_120f: ;
    var7 = (unsigned long)((unsigned int)(((unsigned int)((unsigned char)(((unsigned int)((unsigned char)(arg0[i])) & 255))) & 3)));
    if (((unsigned long)((unsigned int)(var7)) == 2)) {
        goto L_1248;
    }
    if (((((unsigned long)((unsigned int)(var7)) == 2) | ((long)((int)(var7)) < 2)) == 0)) {
        goto L_124e;
    }
    if (((unsigned long)((unsigned int)(var7)) != 0)) {
        if (((unsigned long)((unsigned int)(var7)) == 1)) {
            goto L_1240;
        }
        goto L_124e;
    }
    acc = (acc + 1);
    goto L_1258;
    L_1240: ;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(((unsigned long)((unsigned int)(acc)) + 100));
    L_1248: ;
    acc = (acc + 4);
    goto L_1258;
    L_124e: ;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(((unsigned long)((unsigned int)(acc)) + 200));
    L_1258: ;
    i = (i + 1);
    L_125c: ;
    if ((i < arg1)) {
        goto L_120f;
    }
    // x86-64 epilogue: restore rbp
    return (unsigned int)(acc);
}

gcc -O2

4/4
all_arms_break pass 60 lines
// glaurung: all_arms_break @ 0x1270
int32_t all_arms_break(const uint8_t * arg0, int32_t arg1) {
    int acc;
    int i;
    long ret;
    long var11;
    long var15;
    int var16;
    long var3;
    long var4;
    long var8;
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    if (((unsigned long)(32) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return 0xffffffff;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        return 0;
    }
    var3 = 0;
    var4 = (long)((((long)arg0 + (unsigned long)((unsigned int)((arg1 - 1)))) + 1));
    acc = 0;
    var8 = (long)arg0;
    L_12a1: ;
    while (1) {
        var11 = (unsigned long)((unsigned int)(((unsigned int)((unsigned char)(*(char *)((var8)))) & 3)));
        if (((unsigned long)((unsigned char)((var11 & 255))) == 1)) {
            goto L_12c0;
        }
        goto L_12ac;
        L_1290: ;
        var15 = (((unsigned long)((unsigned char)((var11 & 255))) != 0) ? var3 : (unsigned long)((unsigned int)((acc + 1))));
        L_1298: ;
        var8 = (var8 + 1);
        acc = var15;
        ret = var15;
        if ((var8 == var4)) {
            goto L_12bd;
        }
        goto L_12a1;
        L_12ac: ;
        if (((unsigned long)((unsigned char)((var11 & 255))) != 2)) {
            goto L_1290;
        }
        var8 = (var8 + 1);
        var16 = (acc + 4);
        acc = (unsigned long)((unsigned int)(var16));
        ret = (unsigned long)((unsigned int)(var16));
        if ((var8 != var4)) {
            goto L_12a1;
        }
        goto L_12bd;
        L_12c0: ;
        var15 = (unsigned long)((unsigned int)((acc + 2)));
        goto L_1298;
    }
    L_12bd: ;
    return ret;
}
fsm_returns_from_arm pass 63 lines
// glaurung: fsm_returns_from_arm @ 0x1100
int32_t fsm_returns_from_arm(const uint8_t * arg0, int32_t arg1) {
    int st;
    int i;
    unsigned char c;
    long var10;
    long var11;
    int var15;
    long var17;
    long var18;
    if ((arg0 == 0)) {
        goto L_1140;
    }
    if (((unsigned long)(32) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        goto L_1140;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        goto L_113a;
    }
    st = 0;
    i = 0;
    L_1117: ;
    c = (unsigned int)((unsigned char)(arg0[i]));
    var10 = (unsigned long)((unsigned int)(i));
    var11 = (unsigned long)(c);
    if (((unsigned long)((unsigned int)(st)) != 1)) {
        goto L_1129;
    }
    var10 = (unsigned long)((unsigned int)(i));
    var11 = (unsigned long)(c);
    if (((unsigned long)((unsigned char)((c & 255))) == 98)) {
        goto L_1150;
    }
    L_1129: ;
    var15 = (var10 + 1);
    i = (unsigned long)((unsigned int)(var15));
    st = ((unsigned long)((unsigned char)((var11 & 255))) == 97);
    if (((((unsigned int)(arg1) == (unsigned int)(var15)) | (arg1 < var15)) == 0)) {
        goto L_1117;
    }
    L_113a: ;
    var17 = 0;
    goto L_1146;
    L_1140: ;
    var17 = 0xffffffff;
    L_1146: ;
    return (unsigned int)(var17);
    L_1150: ;
    var18 = (unsigned long)((unsigned int)((i + 1)));
    if ((((unsigned int)(arg1) == (unsigned int)(var18)) | ((long)(arg1) < (long)((int)(var18))))) {
        goto L_113a;
    }
    var10 = (unsigned long)((unsigned int)((i + 2)));
    var17 = (unsigned long)((unsigned int)(st));
    if (((unsigned long)((unsigned char)(arg0[(long)((int)(var18))])) == 99)) {
        goto L_1146;
    }
    if ((((unsigned int)(arg1) == (unsigned int)(var10)) | ((long)(arg1) < (long)((int)(var10))))) {
        goto L_113a;
    }
    var11 = (unsigned int)((unsigned char)(arg0[(long)((int)(var10))]));
    goto L_1129;
}
nested_loop_returning_arm pass 70 lines
// glaurung: nested_loop_returning_arm @ 0x11f0
int32_t nested_loop_returning_arm(const uint8_t * arg0, int32_t arg1, int32_t arg2) {
    int i;
    int acc;
    int o;
    long ret;
    long var10;
    long var13;
    long var18;
    int var19;
    int var21;
    long var3;
    long var4;
    long var5;
    long var6;
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    if (((unsigned long)(8) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return 0xffffffff;
    }
    if (((unsigned long)(8) < (unsigned long)((unsigned long)((unsigned int)(arg2))))) {
        return 0xffffffff;
    }
    ret = 0;
    var3 = 0;
    var4 = var5;
    var6 = 0;
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        return ret;
    }
    L_120c: ;
    var4 = 0;
    i = 0;
    acc = var6;
    var10 = var6;
    if (((unsigned long)((unsigned int)(arg2)) == 0)) {
        goto L_123b;
    }
    L_1213: ;
    var13 = (unsigned long)((unsigned int)(((unsigned int)((unsigned char)(*(char *)(((long)arg0 + i)))) & 3)));
    if (((unsigned long)((unsigned char)((var13 & 255))) == 1)) {
        goto L_1250;
    }
    if (((unsigned long)((unsigned char)((var13 & 255))) == 2)) {
        return (unsigned int)((acc + 50));
    }
    var18 = (((unsigned long)((unsigned char)((var13 & 255))) == 0) ? (unsigned long)((unsigned int)((acc + var3))) : (unsigned long)((unsigned int)((acc - 1))));
    L_1232: ;
    var4 = ((unsigned long)((unsigned int)(i)) + 1);
    i = var4;
    acc = var18;
    var10 = var18;
    if (((((unsigned int)(arg2) == (unsigned int)(var4)) | ((long)(arg2) < (long)((int)(var4)))) == 0)) {
        goto L_1213;
    }
    L_123b: ;
    var19 = (var3 + 1);
    var21 = (var10 + 7);
    ret = (unsigned long)((unsigned int)(var21));
    var3 = (unsigned long)((unsigned int)(var19));
    var6 = (unsigned long)((unsigned int)(var21));
    if (((unsigned int)(arg1) != (unsigned int)(var19))) {
        goto L_120c;
    }
    return ret;
    L_1250: ;
    var18 = (unsigned long)((unsigned int)((acc ^ i)));
    goto L_1232;
}
two_returning_arms pass 57 lines
// glaurung: two_returning_arms @ 0x1170
int32_t two_returning_arms(const uint8_t * arg0, int32_t arg1) {
    int acc;
    int i;
    long var11;
    long var15;
    long var3;
    long var5;
    long var8;
    if ((arg0 == 0)) {
        goto L_11e8;
    }
    if (((unsigned long)(32) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        goto L_11e8;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        goto L_11e0;
    }
    var3 = (long)((((long)arg0 + (unsigned long)((unsigned int)((arg1 - 1)))) + 1));
    acc = 0;
    var5 = (long)arg0;
    L_118d: ;
    var8 = (unsigned long)((unsigned int)(((unsigned int)((unsigned char)(*(char *)((var5)))) & 3)));
    if (((unsigned long)((unsigned char)((var8 & 255))) == 1)) {
        goto L_11b0;
    }
    if (((unsigned long)((unsigned char)((var8 & 255))) == 2)) {
        goto L_11d0;
    }
    if (((unsigned long)((unsigned char)((var8 & 255))) == 0)) {
        goto L_11c0;
    }
    var11 = (unsigned long)((unsigned int)((acc + 200)));
    L_11a6: ;
    return (unsigned int)(var11);
    L_11b0: ;
    return (unsigned int)((acc + 100));
    L_11c0: ;
    var15 = (unsigned long)((unsigned int)((acc + 1)));
    L_11c4: ;
    var5 = (var5 + 1);
    acc = var15;
    if ((var5 != var3)) {
        goto L_118d;
    }
    var11 = var15;
    goto L_11a6;
    L_11d0: ;
    var15 = (unsigned long)((unsigned int)((acc + 4)));
    goto L_11c4;
    L_11e0: ;
    var11 = 0;
    goto L_11a6;
    L_11e8: ;
    var11 = 0xffffffff;
    goto L_11a6;
}

← 213 fixtures