Fixture 25

kmp search

C · 1 functions · 4 lanes · 4 of 4 function-lanes behave identically

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

tests/decompiler_fixtures/src/25_kmp_search.c source
#include <stdint.h>

__attribute__((noinline)) int32_t kmp_search(const uint8_t *text, int32_t n,
                                              const uint8_t *pattern,
                                              int32_t m) {
    int32_t prefix[16];
    int32_t i;
    int32_t matched = 0;
    if (text == 0 || pattern == 0 || n < 0 || n > 16 || m < 0 || m > 16) {
        return -1;
    }
    if (m == 0) {
        return 0;
    }
    prefix[0] = 0;
    for (i = 1; i < m; ++i) {
        while (matched > 0 && pattern[i] != pattern[matched]) {
            matched = prefix[matched - 1];
        }
        if (pattern[i] == pattern[matched]) {
            ++matched;
        }
        prefix[i] = matched;
    }
    matched = 0;
    for (i = 0; i < n; ++i) {
        while (matched > 0 && text[i] != pattern[matched]) {
            matched = prefix[matched - 1];
        }
        if (text[i] == pattern[matched]) {
            ++matched;
        }
        if (matched == m) {
            return i - m + 1;
        }
    }
    return -1;
}

Recovered C

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

clang -O0

1/1
kmp_search pass 86 lines
// glaurung: kmp_search @ 0x1100
__attribute__((no_stack_protector)) int32_t kmp_search(const uint8_t * arg0, int32_t arg1, const uint8_t * arg2, int32_t arg3) {
    int matched;
    int i;
    int local_4;
    unsigned char local_70[64];
    signed char local_79;
    signed char local_7a;
    matched = 0;
    if ((arg0 != 0)) {
        if ((arg2 != 0)) {
            if ((0 <= (long)(arg1))) {
                if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) != 0)) {
                    if ((0 <= (long)(arg3))) {
                        if ((((unsigned long)((unsigned int)(arg3)) == 16) | ((long)(arg3) < 16))) {
                            goto L_1163;
                        }
                    }
                }
            }
        }
    }
    local_4 = -1;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
    L_1163: ;
    if (((unsigned long)((unsigned int)(arg3)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    *(int *)(&local_70[0]) = 0;
    i = 1;
    L_1187: ;
    if ((arg3 <= i)) {
        goto L_122d;
    }
    goto L_1198;
    L_1198: ;
    local_79 = 0;
    if (((((unsigned long)((unsigned int)(matched)) == 0) | ((long)(matched) < 0)) == 0)) {
        local_79 = ((unsigned int)((unsigned char)(arg2[i])) != (unsigned int)((unsigned char)(arg2[matched])));
    }
    if (((unsigned long)((unsigned char)((local_79 & 1))) != 0)) {
        matched = *(int *)((&local_70[0] + ((long)((int)(((unsigned long)((unsigned int)(matched)) - 1))) * 4)));
        goto L_1198;
    }
    if (((unsigned int)((unsigned char)(arg2[i])) == (unsigned int)((unsigned char)(arg2[matched])))) {
        matched = ((unsigned int)(matched) + 1);
    }
    *(int *)((&local_70[0] + ((long)(i) * 4))) = matched;
    i = ((unsigned int)(i) + 1);
    goto L_1187;
    L_122d: ;
    matched = 0;
    i = 0;
    L_123b: ;
    if ((arg1 <= i)) {
        goto L_12f8;
    }
    goto L_124c;
    L_124c: ;
    local_7a = 0;
    if (((((unsigned long)((unsigned int)(matched)) == 0) | ((long)(matched) < 0)) == 0)) {
        local_7a = ((unsigned int)((unsigned char)(arg0[i])) != (unsigned int)((unsigned char)(arg2[matched])));
    }
    if (((unsigned long)((unsigned char)((local_7a & 1))) != 0)) {
        matched = *(int *)((&local_70[0] + ((long)((int)(((unsigned long)((unsigned int)(matched)) - 1))) * 4)));
        goto L_124c;
    }
    if (((unsigned int)((unsigned char)(arg0[i])) == (unsigned int)((unsigned char)(arg2[matched])))) {
        matched = ((unsigned int)(matched) + 1);
    }
    if (((unsigned int)(matched) == (unsigned int)(arg3))) {
        local_4 = ((unsigned int)(((unsigned long)((unsigned int)(i)) - arg3)) + 1);
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    goto L_12ea;
    L_12ea: ;
    i = ((unsigned int)(i) + 1);
    goto L_123b;
    L_12f8: ;
    local_4 = -1;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}

clang -O2

1/1
kmp_search pass 113 lines
// glaurung: kmp_search @ 0x1100
__attribute__((no_stack_protector)) int32_t kmp_search(const uint8_t * arg0, int32_t arg1, const uint8_t * arg2, int32_t arg3) {
    int i;
    int matched;
    unsigned char local_48[72];
    long ret;
    long var10;
    long var12;
    long var13;
    long var2;
    int var20;
    long var21;
    long var23;
    long var27;
    long var3;
    long var31;
    long var34;
    int var36;
    long var37;
    long var4;
    int var43;
    // x86-64 prologue: save callee registers, frame 8 bytes
    ret = 0xffffffff;
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg3))))) {
        goto L_117e;
    }
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        goto L_117e;
    }
    if ((arg0 == 0)) {
        goto L_117e;
    }
    if ((arg2 == 0)) {
        goto L_117e;
    }
    if (((unsigned long)((unsigned int)(arg3)) == 0)) {
        goto L_1180;
    }
    *(int *)(&local_48[0]) = 0;
    var2 = var3;
    if (((unsigned long)((unsigned int)(arg3)) != 1)) {
        goto L_1184;
    }
    L_112b: ;
    if ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0))) {
        goto L_117e;
    }
    var4 = (unsigned long)((unsigned int)(arg1));
    i = 0;
    var10 = 0;
    do {
        var12 = (*(char *)(((long)arg0 + i)) & 255);
        if (((((unsigned long)((unsigned int)(var10)) == 0) | ((long)((int)(var10)) < 0)) == 0)) {
            var13 = var10;
            do {
                var2 = (unsigned long)((unsigned int)(var13));
                var10 = var13;
                if (((unsigned char)((var12 & 255)) == (unsigned char)(arg2[(unsigned long)((unsigned int)(var13))]))) {
                    break;
                }
                var13 = (unsigned long)((unsigned int)(*(int *)((&local_48[0] + ((unsigned long)((unsigned int)((var13 - 1))) * 4)))));
                var10 = var13;
            } while (((((unsigned long)((unsigned int)(var13)) == 0) | ((long)((int)(var13)) < 0)) == 0));
        }
        var2 = ((unsigned char)((var12 & 255)) == (unsigned char)(arg2[(long)((int)(var10))]));
        var20 = ((long)((int)(var10)) + var2);
        var21 = (unsigned long)((unsigned int)(var20));
        if (((unsigned int)(var20) == (unsigned int)(arg3))) {
            var43 = ((unsigned int)((i - arg3)) + 1);
            ret = (unsigned long)((unsigned int)(var43));
            // x86-64 epilogue: restore callee registers
            return (unsigned int)(var43);
        }
        i = (i + 1);
        var10 = var21;
    } while ((i != var4));
    L_117e: ;
    // x86-64 epilogue: restore callee registers
    return ret;
    L_1180: ;
    // x86-64 epilogue: restore callee registers
    return 0;
    L_1184: ;
    var23 = (unsigned long)((unsigned int)(arg3));
    var27 = 1;
    matched = 0;
    goto L_11c1;
    L_11a0: ;
    var2 = ((unsigned char)((var34 & 255)) == (unsigned char)(arg2[(long)((int)(var31))]));
    var36 = ((long)((int)(var31)) + var2);
    *(int *)((&local_48[0] + (var27 * 4))) = var36;
    var37 = (var27 + 1);
    var27 = var37;
    matched = (unsigned long)((unsigned int)(var36));
    if ((var37 == var23)) {
        goto L_112b;
    }
    L_11c1: ;
    var34 = (*(char *)(((long)arg2 + var27)) & 255);
    var31 = (unsigned long)((unsigned int)(matched));
    if ((((unsigned long)((unsigned int)(matched)) == 0) | ((long)(matched) < 0))) {
        goto L_11a0;
    }
    do {
        var31 = (unsigned long)((unsigned int)(matched));
        if (((unsigned char)((var34 & 255)) == (unsigned char)(arg2[(unsigned long)((unsigned int)(matched))]))) {
            goto L_11a0;
        }
        matched = (unsigned long)((unsigned int)(*(int *)((&local_48[0] + ((unsigned long)((unsigned int)((matched - 1))) * 4)))));
    } while (((((unsigned long)((unsigned int)(matched)) == 0) | ((long)(matched) < 0)) == 0));
    var31 = (unsigned long)((unsigned int)(matched));
    goto L_11a0;
}

gcc -O0

1/1
kmp_search pass 83 lines
// glaurung: kmp_search @ 0x1119
int32_t kmp_search(const uint8_t * arg0, int32_t arg1, const uint8_t * arg2, int32_t arg3) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    int matched;
    int i;
    unsigned char local_50[64];
    long local_8;
    long ret;
    local_8 = (long)(0x28);
    matched = 0;
    if ((arg0 != 0)) {
        if ((arg2 != 0)) {
            if ((0 <= (long)(arg1))) {
                if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) != 0)) {
                    if ((0 <= (long)(arg3))) {
                        if ((((unsigned long)((unsigned int)(arg3)) == 16) | ((long)(arg3) < 16))) {
                            goto L_1179;
                        }
                    }
                }
            }
        }
    }
    ret = 0xffffffff;
    goto L_12a7;
    L_1179: ;
    if (((unsigned long)((unsigned int)(arg3)) == 0)) {
        ret = 0;
        goto L_12a7;
    }
    *(int *)(&local_50[0]) = 0;
    i = 1;
    goto L_120a;
    L_1199: ;
    matched = *(int *)((&local_50[0] + ((long)((int)(((unsigned long)((unsigned int)(matched)) - 1))) * 4)));
    L_11a8: ;
    if (((((unsigned long)((unsigned int)(matched)) == 0) | ((long)(matched) < 0)) == 0)) {
        if (((unsigned char)(((unsigned int)((unsigned char)(arg2[i])) & 255)) != (unsigned char)(((unsigned int)((unsigned char)(arg2[matched])) & 255)))) {
            goto L_1199;
        }
    }
    if (((unsigned char)(((unsigned int)((unsigned char)(arg2[i])) & 255)) == (unsigned char)(((unsigned int)((unsigned char)(arg2[matched])) & 255)))) {
        matched = (matched + 1);
    }
    *(int *)((&local_50[0] + ((long)(i) * 4))) = matched;
    i = (i + 1);
    L_120a: ;
    if ((i < arg3)) {
        goto L_11a8;
    }
    matched = 0;
    i = 0;
    goto L_129a;
    L_1222: ;
    matched = *(int *)((&local_50[0] + ((long)((int)(((unsigned long)((unsigned int)(matched)) - 1))) * 4)));
    L_1231: ;
    if (((((unsigned long)((unsigned int)(matched)) == 0) | ((long)(matched) < 0)) == 0)) {
        if (((unsigned char)(((unsigned int)((unsigned char)(arg0[i])) & 255)) != (unsigned char)(((unsigned int)((unsigned char)(arg2[matched])) & 255)))) {
            goto L_1222;
        }
    }
    if (((unsigned char)(((unsigned int)((unsigned char)(arg0[i])) & 255)) == (unsigned char)(((unsigned int)((unsigned char)(arg2[matched])) & 255)))) {
        matched = (matched + 1);
    }
    if (((unsigned int)(matched) == (unsigned int)(arg3))) {
        ret = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(i)) - arg3))) + 1)));
        goto L_12a7;
    }
    i = (i + 1);
    L_129a: ;
    if ((i < arg1)) {
        goto L_1231;
    }
    ret = 0xffffffff;
    L_12a7: ;
    if ((local_8 == 0x28)) {
        // x86-64 epilogue: restore rbp
        return ret;
    }
    __stack_chk_fail();
    // x86-64 epilogue: restore rbp
    return ret;
}

gcc -O2

1/1
kmp_search pass 159 lines
// glaurung: kmp_search @ 0x1120
int32_t kmp_search(const uint8_t * arg0, int32_t arg1, const uint8_t * arg2, int32_t arg3) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    int matched;
    int i;
    long local_10;
    unsigned char local_58[64];
    long ret;
    long var10;
    int var11;
    long var19;
    long var2;
    long var23;
    int var24;
    long var25;
    long var26;
    long var27;
    long var3;
    int var32;
    long var34;
    long var35;
    long var36;
    long var4;
    long var5;
    long var7;
    long var9;
    local_10 = (long)(0x28);
    ret = 0;
    if ((arg0 == 0)) {
        goto L_1270;
    }
    if ((arg2 == 0)) {
        goto L_1270;
    }
    var2 = (unsigned long)((unsigned int)(arg1));
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        goto L_1270;
    }
    var3 = (unsigned long)((unsigned int)(arg3));
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg3))))) {
        goto L_1270;
    }
    if (((unsigned long)((unsigned int)(arg3)) == 0)) {
        goto L_123d;
    }
    *(int *)(&local_58[0]) = 0;
    var4 = var5;
    if (((unsigned long)((unsigned int)(arg3)) == 1)) {
        goto L_11c9;
    }
    var7 = 1;
    var9 = ((unsigned long)((unsigned int)((arg3 - 2))) + 2);
    var10 = ret;
    L_1190: ;
    var11 = (unsigned int)((unsigned char)(*(char *)(((long)arg2 + var7))));
    if (((((unsigned long)((unsigned int)(var10)) == 0) | ((long)((int)(var10)) < 0)) == 0)) {
        goto L_11b0;
    }
    ret = var10;
    goto L_1258;
    L_11a0: ;
    ret = (unsigned long)((unsigned int)(*(int *)((&local_58[0] + ((long)((int)((var10 - 1))) * 4)))));
    var10 = ret;
    if ((((unsigned long)((unsigned int)(ret)) == 0) | ((long)((int)(ret)) < 0))) {
        goto L_1258;
    }
    L_11b0: ;
    ret = var10;
    if (((unsigned char)((var11 & 255)) != (unsigned char)(arg2[(long)((int)(var10))]))) {
        goto L_11a0;
    }
    L_11b9: ;
    ret = (unsigned long)((unsigned int)((ret + 1)));
    L_11bc: ;
    *(int *)((&local_58[0] + (var7 * 4))) = ret;
    var4 = (var7 + 1);
    var7 = var4;
    var10 = ret;
    if ((var9 != var4)) {
        goto L_1190;
    }
    L_11c9: ;
    if (((unsigned long)((unsigned int)(var2)) == 0)) {
        goto L_1270;
    }
    var19 = 0;
    matched = 0;
    var23 = (unsigned long)((unsigned int)((var2 - 1)));
    var24 = (unsigned int)((unsigned char)(*(char *)((long)arg0)));
    var25 = 0;
    var26 = 0;
    var27 = 0;
    if (0) {
        goto L_11fc;
    }
    goto L_1228;
    L_11f0: ;
    matched = (unsigned long)((unsigned int)(*(int *)((&local_58[0] + ((long)((int)((var27 - 1))) * 4)))));
    var27 = (unsigned long)((unsigned int)(matched));
    var19 = var26;
    if ((((unsigned long)((unsigned int)(matched)) == 0) | ((long)(matched) < 0))) {
        goto L_1228;
    }
    L_11fc: ;
    var19 = var26;
    matched = var27;
    if (((unsigned char)(arg2[(long)((int)(var27))]) != (unsigned char)((var24 & 255)))) {
        goto L_11f0;
    }
    L_1205: ;
    var32 = (matched + 1);
    var34 = var19;
    var27 = (unsigned long)((unsigned int)(var32));
    var35 = (unsigned long)((unsigned int)(var32));
    if (((unsigned int)(var32) == (unsigned int)(var3))) {
        goto L_1236;
    }
    L_120d: ;
    var36 = (var34 + 1);
    if ((var23 == var34)) {
        goto L_1270;
    }
    var19 = var36;
    var24 = (unsigned int)((unsigned char)(*(char *)(((long)arg0 + var36))));
    var25 = (unsigned long)((unsigned int)(var36));
    var26 = var36;
    if (((((unsigned long)((unsigned int)(var27)) == 0) | ((long)((int)(var27)) < 0)) == 0)) {
        goto L_11fc;
    }
    matched = var27;
    L_1228: ;
    if (((unsigned char)(arg2[matched]) == (unsigned char)((var24 & 255)))) {
        goto L_1205;
    }
    var34 = var19;
    var27 = (unsigned long)((unsigned int)(matched));
    var35 = (unsigned long)((unsigned int)(matched));
    if (((unsigned int)(matched) != (unsigned int)(var3))) {
        goto L_120d;
    }
    L_1236: ;
    ret = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var25 - var35))) + 1)));
    L_123d: ;
    if ((local_10 != 0x28)) {
        goto L_1277;
    }
    // x86-64 epilogue: tear down frame
    return ret;
    L_1258: ;
    if (((unsigned char)((var11 & 255)) != (unsigned char)(arg2[(long)((int)(ret))]))) {
        goto L_11bc;
    }
    goto L_11b9;
    L_1270: ;
    ret = 0xffffffff;
    goto L_123d;
    L_1277: ;
    __stack_chk_fail();
}

← 213 fixtures