Fixture 13

loop early exit

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

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

Loops whose body can leave the function.

At -O0 every return in a function jumps to ONE shared epilogue block, so a return inside a loop makes that epilogue post-dominate the loop body. A structurer that trusts the immediate post-dominator as an if/else join then places the epilogue INSIDE the loop: the loop can run at most one iteration, and the code after the loop loses its return.

sort:bsearch_i in the DecBench corpus decompiled to exactly that — an unconditional return ret; at the bottom of the loop and a trailing ret = -1; with no return — and the graph-edit-distance metric scored it fine. Only running it caught the problem, which is why these live here: the fixture gate is execution-differential per function per lane.

Each function below reaches the shared epilogue from a different place, so a fix that special-cases one shape does not pass the rest.

As committed, 19 of these 24 cells (6 functions x 4 lanes) FAIL. That is recorded in baseline.json deliberately: the gate fails on new breakage while known bugs stay visible. Two of the failures are not early-exit defects at all — see sum_positive — so do not read a green fixture 13 as proof that Phase B worked without checking WHICH cells moved.

tests/decompiler_fixtures/src/13_loop_early_exit.c source
/* Loops whose body can leave the function.
 *
 * At -O0 every `return` in a function jumps to ONE shared epilogue block, so a
 * `return` inside a loop makes that epilogue post-dominate the loop body. A
 * structurer that trusts the immediate post-dominator as an if/else join then
 * places the epilogue INSIDE the loop: the loop can run at most one iteration,
 * and the code after the loop loses its return.
 *
 * `sort:bsearch_i` in the DecBench corpus decompiled to exactly that — an
 * unconditional `return ret;` at the bottom of the loop and a trailing
 * `ret = -1;` with no `return` — and the graph-edit-distance metric scored it
 * fine. Only running it caught the problem, which is why these live here: the
 * fixture gate is execution-differential per function per lane.
 *
 * Each function below reaches the shared epilogue from a different place, so a
 * fix that special-cases one shape does not pass the rest.
 *
 * As committed, 19 of these 24 cells (6 functions x 4 lanes) FAIL. That is recorded
 * in baseline.json deliberately: the gate fails on new breakage while known bugs
 * stay visible. Two of the failures are not early-exit defects at all — see
 * `sum_positive` — so do not read a green fixture 13 as proof that Phase B worked
 * without checking WHICH cells moved.
 */

/* The canonical case: an early return from inside a loop, plus a fallthrough
 * return after it. Two paths into one epilogue. */
int find_first(const int *a, int n, int key) {
    for (int i = 0; i < n; i++) {
        if (a[i] == key) return i;
    }
    return -1;
}

/* The bsearch shape specifically: the early return is nested two conditionals
 * deep, and the sibling arms both continue the loop via a back edge. Those back
 * edges are what make the post-dominator the wrong join. */
int bisect(const int *a, int n, int key) {
    int lo = 0, hi = n - 1;
    while (lo <= hi) {
        int m = (lo + hi) / 2;
        if (a[m] == key) return m;
        if (a[m] < key) lo = m + 1;
        else hi = m - 1;
    }
    return -1;
}

/* Two early returns from the same loop, with different values, so a structurer
 * that collapses the epilogue into a single tail must still distinguish them. */
/* HOIST TRAP — measured, do not "simplify" this loop's lowering.
 *
 * This function is one of exactly four the loop-header hoist fallback protects. The
 * verbose `while (1) { pre; if (!cond) break; }` form it decompiles to is NOT an
 * accident to be tidied away: hoisting the header above the loop lets constant
 * propagation substitute the initial value that dominates at the hoist position, which
 * freezes the loop-carried value and the loop stops making progress.
 *
 * Measured on branch `recover-ged-cells` (see docs/design/ged-recovery-measured-trade.md):
 * always-hoisting recovers 50.32 GED points, 46% of a regression — and breaks exactly
 * these four functions across six lanes:
 *     03_loop_shapes:gcc:O2:while_prefix
 *     12_loop_rotation:gcc:O2:find_first_set
 *     13_loop_early_exit:{clang,gcc}:O2:classify_run
 *     14_flag_effects:{clang,gcc}:O0:countdown
 * So the compact form is worth real score, and it is wrong. That is the trade.
 *
 * FOUR predicates have been tried and all four failed, each differently: a copy-chain
 * rule, a loop-invariance rule, a use-count rule, and a post-fold check requiring only a
 * nonempty read/write intersection (which passes `find_first_set`, whose body reassigns
 * its flag lower down while the frozen value sits inside the hoisted expression). If a
 * post-fold check is attempted again it must preserve EVERY original loop-carried
 * dependency, not one overlapping register.
 *
 * The real fix is typed value identity plus dominance, where "may this expression move
 * here" is a query rather than a guess — value-model-root-cause-and-plan.md Phase 2.
 */
int classify_run(const int *a, int n) {
    for (int i = 1; i < n; i++) {
        if (a[i] < a[i - 1]) return -1;
        if (a[i] == a[i - 1]) return 0;
    }
    return 1;
}

/* An early return from a NESTED loop: the epilogue post-dominates both loop
 * bodies, so the wrong-join failure can occur at either depth. */
int has_pair(const int *a, int n, int target) {
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            if (a[i] + a[j] == target) return 1;
        }
    }
    return 0;
}

/* A loop whose early exit is a `break` rather than a `return`: the join really
 * is inside the function, so this one should be structured as a loop with a break.
 * It was written as the counterexample that stops a fix from being "never use the
 * post-dominator" — but it does NOT currently pass. It decompiles with an
 * unconditional `return` at the bottom of the loop body and a `goto` to an empty
 * label, i.e. the same shape as `bisect`. So it is not yet a control; it is
 * another instance. Re-read this comment once Phase B lands. */
int sum_until_zero(const int *a, int n) {
    int s = 0;
    for (int i = 0; i < n; i++) {
        if (a[i] == 0) break;
        s += a[i];
    }
    return s;
}

/* A `continue` in the middle: a back edge from inside a conditional, which is
 * the same edge kind that misleads the join choice in `bisect` — but here there is
 * no early return, so structuring is NOT the problem.
 *
 * This one fails for two entirely different reasons, which is why it earns its
 * place: gcc -O0 emits the guard as `test %eax,%eax ; jle`, our `test` lifting
 * does not define Flag::Sle, so `jle` reads the stale Sle left by the loop's own
 * `cmp`; and the inverted condition then renders as `~sle`, where bitwise NOT of a
 * 0/1 flag is always true. The guard therefore never skips and the function sums
 * every element. Neither defect has anything to do with early exits — the fixture
 * found them by accident, which is the argument for fixtures over targeted cases. */
int sum_positive(const int *a, int n) {
    int s = 0;
    for (int i = 0; i < n; i++) {
        if (a[i] <= 0) continue;
        s += a[i];
    }
    return s;
}

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
bisect pass 32 lines
// glaurung: bisect @ 0x1160
int bisect(const int * arg0, int arg1, int arg2) {
    int lo;
    int hi;
    int m;
    int local_4;
    int var5;
    lo = 0;
    hi = ((unsigned int)(arg1) - 1);
    L_117e: ;
    if (((((unsigned int)(lo) == (unsigned int)(hi)) | (lo < hi)) == 0)) {
        goto L_11ea;
    }
    var5 = ((unsigned int)(lo) + hi);
    m = ((int)((((long long)(int)((((unsigned long)((long)((int)((unsigned long)((unsigned int)(var5))))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(var5)))) / (int)(2)));
    if (((unsigned int)(arg0[(long)(m)]) == (unsigned int)(arg2))) {
        local_4 = m;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((long)((int)(arg0[(long)(m)])) < (long)(arg2))) {
        lo = ((unsigned int)(m) + 1);
        goto L_11e5;
    }
    hi = ((unsigned int)(m) - 1);
    L_11e5: ;
    goto L_117e;
    L_11ea: ;
    local_4 = -1;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}
classify_run pass 26 lines
// glaurung: classify_run @ 0x1200
int classify_run(const int * arg0, int arg1) {
    int i;
    int local_4;
    i = 1;
    L_1212: ;
    if ((arg1 <= i)) {
        goto L_128b;
    }
    if (((long)((int)(arg0[(long)(i)])) < (long)((int)(arg0[(long)((int)(((unsigned long)((unsigned int)(i)) - 1)))])))) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((unsigned int)(arg0[(long)(i)]) == (unsigned int)(arg0[(long)((int)(((unsigned long)((unsigned int)(i)) - 1)))]))) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    goto L_127d;
    L_127d: ;
    i = ((unsigned int)(i) + 1);
    goto L_1212;
    L_128b: ;
    // x86-64 epilogue: restore rbp
    return 1;
}
find_first pass 23 lines
// glaurung: find_first @ 0x1100
int find_first(const int * arg0, int arg1, int arg2) {
    int i;
    int local_4;
    i = 0;
    L_1115: ;
    if ((arg1 <= i)) {
        goto L_1153;
    }
    if (((unsigned int)(arg0[(long)(i)]) == (unsigned int)(arg2))) {
        local_4 = i;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    goto L_1145;
    L_1145: ;
    i = ((unsigned int)(i) + 1);
    goto L_1115;
    L_1153: ;
    local_4 = -1;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}
has_pair pass 31 lines
// glaurung: has_pair @ 0x12a0
int has_pair(const int * arg0, int arg1, int arg2) {
    int i;
    int j;
    i = 0;
    L_12b5: ;
    if ((arg1 <= i)) {
        goto L_1327;
    }
    j = ((unsigned int)(i) + 1);
    L_12ca: ;
    if ((arg1 <= j)) {
        goto L_1314;
    }
    if (((unsigned int)(((unsigned long)((unsigned int)(arg0[(long)(i)])) + arg0[(long)(j)])) == (unsigned int)(arg2))) {
        // x86-64 epilogue: restore rbp
        return 1;
    }
    goto L_1306;
    L_1306: ;
    j = ((unsigned int)(j) + 1);
    goto L_12ca;
    L_1314: ;
    goto L_1319;
    L_1319: ;
    i = ((unsigned int)(i) + 1);
    goto L_12b5;
    L_1327: ;
    // x86-64 epilogue: restore rbp
    return 0;
}
sum_positive pass 17 lines
// glaurung: sum_positive @ 0x13a0
int sum_positive(const int * arg0, int arg1) {
    int s;
    int i;
    long t10;
    // x86-64 prologue: save rbp
    s = 0;
    for (i = 0; (i < arg1); i++) {
        t10 = arg0[(long)(i)];
        if (((((unsigned long)((unsigned int)(t10)) == 0) | ((long)((int)(t10)) < 0)) == 0)) {
            s = ((unsigned int)(arg0[(long)(i)]) + s);
        } else {
        }
    }
    // x86-64 epilogue: restore rbp
    return (unsigned int)(s);
}
sum_until_zero pass 17 lines
// glaurung: sum_until_zero @ 0x1340
int sum_until_zero(const int * arg0, int arg1) {
    int s;
    int i;
    // x86-64 prologue: save rbp
    s = 0;
    i = 0;
    while ((i < arg1)) {
        if (((unsigned long)((unsigned int)(arg0[(long)(i)])) == 0)) {
            break;
        }
        s = ((unsigned int)(arg0[(long)(i)]) + s);
        i = ((unsigned int)(i) + 1);
    }
    // x86-64 epilogue: restore rbp
    return (unsigned int)(s);
}

clang -O2

6/6
bisect pass 42 lines
// glaurung: bisect @ 0x1130
int bisect(const int * arg0, int arg1, int arg2) {
    int hi;
    int lo;
    int m;
    long ret;
    long t164;
    long var18;
    int var19;
    int var6;
    long var8;
    ret = 0xffffffff;
    if ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0))) {
        return ret;
    }
    hi = (unsigned long)((unsigned int)((arg1 - 1)));
    lo = 0;
    goto L_115c;
    L_1150: ;
    var6 = (m - 1);
    hi = (unsigned long)((unsigned int)(var6));
    if (((((unsigned int)(lo) == (unsigned int)(var6)) | (lo < var6)) == 0)) {
        return ret;
    }
    L_115c: ;
    var8 = (unsigned long)((unsigned int)((hi + lo)));
    m = (unsigned long)((unsigned int)(((int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var8)) >> 31))) + var8)) >> 1)));
    var18 = (unsigned long)((unsigned int)(arg0[(long)(m)]));
    t164 = (var18 - (unsigned long)((unsigned int)(arg2)));
    if (((unsigned int)(var18) == (unsigned int)(arg2))) {
        return (unsigned int)(m);
    }
    if (((long)(arg2) <= (long)((int)(var18)))) {
        goto L_1150;
    }
    var19 = (m + 1);
    lo = (unsigned long)((unsigned int)(var19));
    if ((((unsigned int)(var19) == (unsigned int)(hi)) | (var19 < hi))) {
        goto L_115c;
    }
    return ret;
}
classify_run pass 32 lines
// glaurung: classify_run @ 0x1190
int classify_run(const int * arg0, int arg1) {
    int i;
    long ret;
    long var0;
    long var1;
    long var4;
    long zf_3;
    ret = 1;
    if (((long)(arg1) < 2)) {
        return ret;
    }
    var0 = (unsigned long)((unsigned int)(arg1));
    var1 = (unsigned long)((unsigned int)(*(int *)(((long)arg0))));
    i = 1;
    while (1) {
        var4 = (unsigned long)((unsigned int)(var1));
        var1 = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + i * 4))));
        zf_3 = ((unsigned int)(var1) == (unsigned int)(var4));
        if (((long)((int)(var1)) < (long)((int)(var4)))) {
            break;
        }
        if (zf_3) {
            return 0;
        }
        i = (i + 1);
        if ((var0 == i)) {
            return ret;
        }
    }
    return 0xffffffff;
}
find_first pass 21 lines
// glaurung: find_first @ 0x1100
int find_first(const int * arg0, int arg1, int arg2) {
    int i;
    long ret;
    long var0;
    long var2;
    ret = 0xffffffff;
    if ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0))) {
        return ret;
    }
    var0 = (unsigned long)((unsigned int)(arg1));
    var2 = 0;
    while (((unsigned int)(*(int *)(((long)arg0 + var2 * 4))) != (unsigned int)(arg2))) {
        i = (var2 + 1);
        var2 = (unsigned long)((unsigned int)(i));
        if ((var0 == i)) {
            return ret;
        }
    }
    return (unsigned int)(var2);
}
has_pair pass 54 lines
// glaurung: has_pair @ 0x11d0
int has_pair(const int * arg0, int arg1, int arg2) {
    int i;
    long var0;
    long var10;
    long var11;
    long var12;
    long var14;
    long var15;
    long var2;
    long var3;
    long var6;
    long var7;
    long var8;
    if ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0))) {
        var10 = 0;
        // x86-64 epilogue: tear down frame
        return 0;
    }
    var0 = (unsigned long)((unsigned int)(arg1));
    var3 = ((var2 & -256) | 1);
    var6 = (unsigned long)((unsigned int)(arg1));
    var7 = (long)arg0;
    var8 = 0;
    goto L_11fd;
    L_11f0: ;
    var7 = (var7 + 4);
    var6 = (var6 - 1);
    var8 = (unsigned long)((unsigned int)(i));
    var10 = var3;
    if ((i == var0)) {
        // x86-64 epilogue: tear down frame
        return (unsigned int)(((unsigned int)((unsigned char)((var10 & 255))) & 1));
    }
    L_11fd: ;
    var11 = (unsigned long)((unsigned int)(var3));
    var12 = var8;
    i = (var8 + 1);
    var3 = ((unsigned long)(i) < (unsigned long)(var0));
    if (((unsigned long)(var0) <= (unsigned long)(i))) {
        goto L_11f0;
    }
    var14 = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + var12 * 4))));
    var15 = 1;
    do {
        if (((unsigned int)(((unsigned long)((unsigned int)(*(int *)((var7 + var15 * 4)))) + var14)) == (unsigned int)(arg2))) {
            var10 = (unsigned long)((unsigned int)(var11));
            // x86-64 epilogue: tear down frame
            return (unsigned int)(((unsigned int)((unsigned char)(((unsigned long)((unsigned int)(var11)) & 255))) & 1));
        }
        var15 = (var15 + 1);
    } while ((var6 != var15));
    goto L_11f0;
}
sum_positive pass 185 lines
// glaurung: sum_positive @ 0x1280
int sum_positive(const int * arg0, int arg1) {
    int s;
    int i;
    long ret;
    long var1;
    long var10;
    int var11;
    int var12;
    int var13;
    int var14;
    long var16;
    int var18;
    long var182;
    long var183;
    int var19;
    int var20;
    int var21;
    int var22;
    int var23;
    int var24;
    int var25;
    int var27;
    int var28;
    int var29;
    long var3;
    int var30;
    int var50;
    int var51;
    int var52;
    int var53;
    long var6;
    int var67;
    int var68;
    int var69;
    long var7;
    int var70;
    long var72;
    int var74;
    int var75;
    int var76;
    int var77;
    int var81;
    int var82;
    int var83;
    int var84;
    int var86;
    int var87;
    int var88;
    int var89;
    int var91;
    int var92;
    int var93;
    int var94;
    int var96;
    int var97;
    int var98;
    int var99;
    if ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0))) {
        return 0;
    }
    var1 = (unsigned long)((unsigned int)(arg1));
    var3 = 0;
    if (((unsigned long)(8) <= (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        var6 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var1)) & -8)));
        var7 = (var6 - 8);
        var10 = (((unsigned long)(var7) >> 3) + 1);
        if ((var7 == 0)) {
            ret = 0;
            var11 = 0;
            var12 = 0;
            var13 = 0;
            var14 = 0;
            var16 = 0;
            var18 = 0;
            var19 = 0;
            var20 = 0;
            var21 = 0;
            if (((unsigned long)((unsigned char)((var10 & 1))) != 0)) {
                L_1337: ;
                var22 = *(int *)(((long)arg0 + var16 * 4));
                var23 = *(int *)(((long)arg0 + var16 * 4 + 0x4));
                var24 = *(int *)(((long)arg0 + var16 * 4 + 0x8));
                var25 = *(int *)(((long)arg0 + var16 * 4 + 0xc));
                var27 = *(int *)(((long)arg0 + var16 * 4 + 0x10));
                var28 = *(int *)(((long)arg0 + var16 * 4 + 0x14));
                var29 = *(int *)(((long)arg0 + var16 * 4 + 0x18));
                var30 = *(int *)(((long)arg0 + var16 * 4 + 0x1c));
                var50 = (var11 + ((-(0 < var22)) & var22));
                var51 = (var12 + ((-(0 < var23)) & var23));
                var52 = (var13 + ((-(0 < var24)) & var24));
                var53 = (var14 + ((-(0 < var25)) & var25));
                var67 = (var18 + ((-(0 < var27)) & var27));
                var68 = (var19 + ((-(0 < var28)) & var28));
                var69 = (var20 + ((-(0 < var29)) & var29));
                var70 = (var21 + ((-(0 < var30)) & var30));
            } else {
                var50 = var11;
                var51 = var12;
                var52 = var13;
                var53 = var14;
                var67 = var18;
                var68 = var19;
                var69 = var20;
                var70 = var21;
            }
        } else {
            var72 = (var10 & -2);
            var74 = 0;
            var75 = 0;
            var76 = 0;
            var77 = 0;
            var16 = 0;
            var11 = 0;
            var12 = 0;
            var13 = 0;
            var14 = 0;
            var18 = 0;
            var19 = 0;
            var20 = 0;
            var21 = 0;
            do {
                var81 = *(int *)(((long)arg0 + var16 * 4));
                var82 = *(int *)(((long)arg0 + var16 * 4 + 0x4));
                var83 = *(int *)(((long)arg0 + var16 * 4 + 0x8));
                var84 = *(int *)(((long)arg0 + var16 * 4 + 0xc));
                var86 = *(int *)(((long)arg0 + var16 * 4 + 0x10));
                var87 = *(int *)(((long)arg0 + var16 * 4 + 0x14));
                var88 = *(int *)(((long)arg0 + var16 * 4 + 0x18));
                var89 = *(int *)(((long)arg0 + var16 * 4 + 0x1c));
                var91 = *(int *)(((long)arg0 + var16 * 4 + 0x20));
                var92 = *(int *)(((long)arg0 + var16 * 4 + 0x24));
                var93 = *(int *)(((long)arg0 + var16 * 4 + 0x28));
                var94 = *(int *)(((long)arg0 + var16 * 4 + 0x2c));
                var96 = *(int *)(((long)arg0 + var16 * 4 + 0x30));
                var97 = *(int *)(((long)arg0 + var16 * 4 + 0x34));
                var98 = *(int *)(((long)arg0 + var16 * 4 + 0x38));
                var99 = *(int *)(((long)arg0 + var16 * 4 + 0x3c));
                var11 = (((-(var74 < var91)) & var91) + (((-(var74 < var81)) & var81) + var11));
                var12 = (((-(var75 < var92)) & var92) + (((-(var75 < var82)) & var82) + var12));
                var13 = (((-(var76 < var93)) & var93) + (((-(var76 < var83)) & var83) + var13));
                var14 = (((-(var77 < var94)) & var94) + (((-(var77 < var84)) & var84) + var14));
                ret = ((unsigned long)((unsigned int)(var12)) | (unsigned long)((unsigned int)(var11)));
                var18 = (((-(var74 < var96)) & var96) + (((-(var74 < var86)) & var86) + var18));
                var19 = (((-(var75 < var97)) & var97) + (((-(var75 < var87)) & var87) + var19));
                var20 = (((-(var76 < var98)) & var98) + (((-(var76 < var88)) & var88) + var20));
                var21 = (((-(var77 < var99)) & var99) + (((-(var77 < var89)) & var89) + var21));
                var16 = (var16 + 16);
                var72 = (var72 - 2);
            } while ((var72 != 0));
            var50 = var11;
            var51 = var12;
            var52 = var13;
            var53 = var14;
            var67 = var18;
            var68 = var19;
            var69 = var20;
            var70 = var21;
            if (((unsigned long)((unsigned char)((var10 & 1))) == 0)) {
                goto L_1366;
            }
            goto L_1337;
        }
        L_1366: ;
        var182 = (unsigned long)((unsigned int)((((var53 + var70) + (var51 + var68)) + ((var52 + var69) + (var50 + var67)))));
        ret = var182;
        if ((var6 == var1)) {
            return ret;
        }
        L_1390: ;
        do {
            var183 = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + var6 * 4))));
            s = (var182 + (((long)((int)(var183)) < 0) ? var3 : var183));
            i = (var6 + 1);
            var182 = (unsigned long)((unsigned int)(s));
            var6 = (unsigned long)((unsigned int)(i));
            ret = (unsigned long)((unsigned int)(s));
        } while ((var1 != i));
    } else {
        var182 = 0;
        var6 = 0;
        goto L_1390;
    }
    return ret;
}
sum_until_zero pass 31 lines
// glaurung: sum_until_zero @ 0x1250
int sum_until_zero(const int * arg0, int arg1) {
    int i;
    int s;
    long ret;
    long var1;
    long var6;
    long var8;
    int var9;
    if ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0))) {
        return 0;
    }
    var1 = (unsigned long)((unsigned int)(arg1));
    var6 = 0;
    i = 0;
    while (1) {
        var8 = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + i * 4))));
        ret = var6;
        if (((unsigned long)((unsigned int)(var8)) == 0)) {
            break;
        }
        var9 = (var6 + var8);
        var6 = (unsigned long)((unsigned int)(var9));
        i = (i + 1);
        ret = (unsigned long)((unsigned int)(var9));
        if ((var1 == i)) {
            break;
        }
    }
    return ret;
}

gcc -O0

6/6
bisect pass 30 lines
// glaurung: bisect @ 0x1147
int bisect(const int * arg0, int arg1, int arg2) {
    int lo;
    int hi;
    int m;
    long var27;
    int var5;
    lo = 0;
    hi = ((unsigned int)(arg1) - 1);
    goto L_11ce;
    L_116b: ;
    var5 = ((unsigned int)(hi) + (unsigned int)(lo));
    m = ((int)(((unsigned long)((unsigned int)(var5)) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var5)) >> 31))))) >> 1);
    if (((unsigned int)(arg2) == (unsigned int)(arg0[(long)(m)]))) {
        // x86-64 epilogue: restore rbp
        return (unsigned int)(m);
    }
    var27 = (unsigned long)((unsigned int)(arg0[(long)(m)]));
    if (((((unsigned int)(arg2) == (unsigned int)(var27)) | ((long)(arg2) < (long)((int)(var27)))) == 0)) {
        lo = ((unsigned int)(m) + 1);
        goto L_11ce;
    }
    hi = ((unsigned int)(m) - 1);
    L_11ce: ;
    if ((((unsigned int)(lo) == (unsigned int)(hi)) | (lo < hi))) {
        goto L_116b;
    }
    // x86-64 epilogue: restore rbp
    return 0xffffffff;
}
classify_run pass 22 lines
// glaurung: classify_run @ 0x11dd
int classify_run(const int * arg0, int arg1) {
    int i;
    i = 1;
    goto L_1267;
    L_11f5: ;
    if (((long)((int)(arg0[(long)(i)])) < (long)((int)(*(int *)(((long)arg0 + (((long)(i) << 2) - 4))))))) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((unsigned int)(arg0[(long)(i)]) == (unsigned int)(*(int *)(((long)arg0 + (((long)(i) << 2) - 4)))))) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    i = (i + 1);
    L_1267: ;
    if ((i < arg1)) {
        goto L_11f5;
    }
    // x86-64 epilogue: restore rbp
    return 1;
}
find_first pass 18 lines
// glaurung: find_first @ 0x10f9
int find_first(const int * arg0, int arg1, int arg2) {
    int i;
    i = 0;
    goto L_1138;
    L_1114: ;
    if (((unsigned int)(arg2) == (unsigned int)(arg0[(long)(i)]))) {
        // x86-64 epilogue: restore rbp
        return (unsigned int)(i);
    }
    i = (i + 1);
    L_1138: ;
    if ((i < arg1)) {
        goto L_1114;
    }
    // x86-64 epilogue: restore rbp
    return 0xffffffff;
}
has_pair pass 27 lines
// glaurung: has_pair @ 0x1276
int has_pair(const int * arg0, int arg1, int arg2) {
    int i;
    int j;
    i = 0;
    goto L_12e6;
    L_1291: ;
    j = ((unsigned int)(i) + 1);
    goto L_12da;
    L_129c: ;
    if (((unsigned int)(arg2) == (unsigned int)(((unsigned long)((unsigned int)(arg0[(long)(j)])) + (unsigned long)((unsigned int)(arg0[(long)(i)])))))) {
        // x86-64 epilogue: restore rbp
        return 1;
    }
    j = (j + 1);
    L_12da: ;
    if ((j < arg1)) {
        goto L_129c;
    }
    i = (i + 1);
    L_12e6: ;
    if ((i < arg1)) {
        goto L_1291;
    }
    // x86-64 epilogue: restore rbp
    return 0;
}
sum_positive pass 17 lines
// glaurung: sum_positive @ 0x135b
int sum_positive(const int * arg0, int arg1) {
    int s;
    int i;
    long t140;
    // x86-64 prologue: save rbp
    s = 0;
    for (i = 0; (i < arg1); i++) {
        t140 = (unsigned long)((unsigned int)(arg0[(long)(i)]));
        if ((((unsigned long)((unsigned int)(t140)) == 0) | ((long)((int)(t140)) < 0))) {
        } else {
            s = (s + (unsigned int)(arg0[(long)(i)]));
        }
    }
    // x86-64 epilogue: restore rbp
    return (unsigned int)(s);
}
sum_until_zero pass 21 lines
// glaurung: sum_until_zero @ 0x12f5
int sum_until_zero(const int * arg0, int arg1) {
    int s;
    int i;
    s = 0;
    i = 0;
    goto L_134b;
    L_1314: ;
    if (((unsigned long)((unsigned int)(arg0[(long)(i)])) == 0)) {
        // x86-64 epilogue: restore rbp
        return (unsigned int)(s);
    }
    s = (s + (unsigned int)(arg0[(long)(i)]));
    i = (i + 1);
    L_134b: ;
    if ((i < arg1)) {
        goto L_1314;
    }
    // x86-64 epilogue: restore rbp
    return (unsigned int)(s);
}

gcc -O2

6/6
bisect pass 39 lines
// glaurung: bisect @ 0x1140
int bisect(const int * arg0, int arg1, int arg2) {
    int hi;
    int m;
    int lo;
    long t10;
    long t152;
    int var0;
    long var4;
    long var6;
    var0 = (arg1 - 1);
    if (((long)((int)(var0)) < 0)) {
        return 0xffffffff;
    }
    var4 = 0;
    hi = (unsigned long)((unsigned int)(var0));
    goto L_1157;
    L_1150: ;
    var6 = (unsigned long)((unsigned int)((m + 1)));
    var4 = var6;
    if (((long)(hi) < (long)((int)(var6)))) {
        return 0xffffffff;
    }
    L_1157: ;
    m = (unsigned long)((unsigned int)(((int)((hi + var4)) >> 1)));
    t10 = arg0[(long)(m)];
    t152 = (t10 - (unsigned long)((unsigned int)(arg2)));
    if (((unsigned int)(t10) == (unsigned int)(arg2))) {
        return m;
    }
    if (((long)((int)(t10)) < (long)(arg2))) {
        goto L_1150;
    }
    hi = (unsigned long)((unsigned int)((m - 1)));
    if (((long)((int)(var4)) <= (long)(hi))) {
        goto L_1157;
    }
    return 0xffffffff;
}
classify_run pass 30 lines
// glaurung: classify_run @ 0x1180
int classify_run(const int * arg0, int arg1) {
    int i;
    long t10;
    long var1;
    long var2;
    long var3;
    long zf_3;
    if ((((unsigned long)((unsigned int)(arg1)) == 1) | ((long)(arg1) < 1))) {
        return 1;
    }
    var1 = (long)((((long)arg0 + ((unsigned long)((unsigned int)((arg1 - 2))) * 4)) + 4));
    var2 = (long)arg0;
    while (1) {
        var3 = (unsigned long)((unsigned int)(*(int *)((var2))));
        t10 = *(int *)((var2 + 0x4));
        zf_3 = ((unsigned int)(t10) == (unsigned int)(var3));
        if (((long)((int)(t10)) < (long)((int)(var3)))) {
            break;
        }
        if (zf_3) {
            return 0;
        }
        var2 = (var2 + 4);
        if ((var2 == var1)) {
            return 1;
        }
    }
    return 0xffffffff;
}
find_first pass 24 lines
// glaurung: find_first @ 0x1100
int find_first(const int * arg0, int arg1, int arg2) {
    int i;
    long var1;
    long var5;
    long var6;
    if ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0))) {
        return 0xffffffff;
    }
    var1 = (long)(arg1);
    i = 0;
    while (1) {
        var5 = (unsigned long)((unsigned int)(i));
        if (((unsigned int)(*(int *)(((long)arg0 + i * 4))) == (unsigned int)(arg2))) {
            break;
        }
        var6 = ((unsigned long)((unsigned int)(i)) + 1);
        i = var6;
        if ((var6 == var1)) {
            return 0xffffffff;
        }
    }
    return (unsigned int)(var5);
}
has_pair pass 40 lines
// glaurung: has_pair @ 0x11d0
int has_pair(const int * arg0, int arg1, int arg2) {
    int i;
    long ret;
    long var0;
    long var1;
    long var4;
    long var6;
    var0 = ret;
    if ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0))) {
        return 0;
    }
    var1 = (long)(arg1);
    i = 1;
    var0 = ret;
    if ((1 == (long)(arg1))) {
        return 0;
    }
    L_11e6: ;
    var4 = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + i * 4 - 0x4))));
    var6 = (unsigned long)((unsigned int)(i));
    goto L_11f8;
    L_11f0: ;
    var0 = (var6 + 1);
    var6 = var0;
    if ((((unsigned int)(arg1) == (unsigned int)(var0)) | ((long)(arg1) < (long)((int)(var0))))) {
        goto L_1210;
    }
    L_11f8: ;
    if (((unsigned int)(((unsigned long)((unsigned int)(*(int *)(((long)arg0 + var6 * 4)))) + var4)) != (unsigned int)(arg2))) {
        goto L_11f0;
    }
    return 1;
    L_1210: ;
    i = (i + 1);
    if ((i != var1)) {
        goto L_11e6;
    }
    return 0;
}
sum_positive pass 23 lines
// glaurung: sum_positive @ 0x1260
int sum_positive(const int * arg0, int arg1) {
    int i;
    int s;
    long ret;
    long var2;
    long var5;
    long var6;
    long var7;
    if ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0))) {
        return 0;
    }
    var2 = (long)((((long)arg0 + ((unsigned long)((unsigned int)((arg1 - 1))) * 4)) + 4));
    var5 = 0;
    var6 = (long)arg0;
    do {
        var7 = (unsigned long)((unsigned int)(*(int *)((var6))));
        ret = (((((unsigned long)((unsigned int)(var7)) == 0) | ((long)((int)(var7)) < 0)) == 0) ? (unsigned long)((unsigned int)((var5 + var7))) : var5);
        var6 = (var6 + 4);
        var5 = ret;
    } while ((var6 != var2));
    return ret;
}
sum_until_zero pass 31 lines
// glaurung: sum_until_zero @ 0x1220
int sum_until_zero(const int * arg0, int arg1) {
    int s;
    int i;
    long var2;
    long var6;
    long var7;
    long var8;
    long var9;
    if ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0))) {
        return 0;
    }
    var6 = (long)((((long)arg0 + ((unsigned long)((unsigned int)((arg1 - 1))) * 4)) + 4));
    var7 = 0;
    var8 = (long)arg0;
    while (1) {
        var9 = (unsigned long)((unsigned int)(*(int *)((var8))));
        var2 = var7;
        if (((unsigned long)((unsigned int)(var9)) == 0)) {
            break;
        }
        var8 = (var8 + 4);
        s = (var7 + var9);
        var7 = (unsigned long)((unsigned int)(s));
        var2 = (unsigned long)((unsigned int)(s));
        if ((var8 == var6)) {
            break;
        }
    }
    return (unsigned int)(var2);
}

← 213 fixtures