Fixture 137

cpp templates

C++ · 5 functions · 4 lanes · 16 of 20 function-lanes behave identically

2 of 4 lanes have a function that returns a different result after decompilation: clang-O2 (3/5), gcc-O2 (3/5).

Templates are monomorphized: one source body becomes several distinct functions whose code differs only by operand width and operation. They are near-clones in the binary, mangled to different symbols, and a decompiler must neither merge them nor treat them as unrelated.

tests/decompiler_fixtures/src/137_cpp_templates.cpp source
/* 137_cpp_templates.cpp
 *
 * Templates are monomorphized: one source body becomes several distinct
 * functions whose code differs only by operand width and operation. They are
 * near-clones in the binary, mangled to different symbols, and a decompiler must
 * neither merge them nor treat them as unrelated.
 */
#include <stdint.h>

namespace {

template <typename T>
T accumulate_range(const T *values, int32_t count, T seed) {
    T total = seed;
    for (int32_t index = 0; index < count; ++index) {
        total = static_cast<T>(total + values[index]);
    }
    return total;
}

template <typename T>
int32_t count_above(const T *values, int32_t count, T threshold) {
    int32_t hits = 0;
    for (int32_t index = 0; index < count; ++index) {
        if (values[index] > threshold) {
            hits += 1;
        }
    }
    return hits;
}

/* A non-type template parameter: the bound is baked into each instantiation. */
template <int32_t Stride>
int32_t strided_sum(const int32_t *values, int32_t count) {
    int32_t total = 0;
    for (int32_t index = 0; index < count; index += Stride) {
        total += values[index];
    }
    return total;
}

}  // namespace

extern "C" int32_t cpp_template_int32(const int32_t *values, int32_t count) {
    if (values == 0 || count < 0 || count > 16) {
        return -1;
    }
    return accumulate_range<int32_t>(values, count, 0);
}

extern "C" int32_t cpp_template_int16(const int32_t *values, int32_t count) {
    int16_t narrowed[16];
    if (values == 0 || count < 0 || count > 16) {
        return -1;
    }
    for (int32_t index = 0; index < count; ++index) {
        narrowed[index] = static_cast<int16_t>(values[index]);
    }
    /* A distinct instantiation: 16-bit arithmetic wraps differently. */
    return accumulate_range<int16_t>(narrowed, count, 0);
}

extern "C" int32_t cpp_template_uint8(const int32_t *values, int32_t count) {
    uint8_t narrowed[16];
    if (values == 0 || count < 0 || count > 16) {
        return -1;
    }
    for (int32_t index = 0; index < count; ++index) {
        narrowed[index] = static_cast<uint8_t>(values[index]);
    }
    return accumulate_range<uint8_t>(narrowed, count, 0);
}

extern "C" int32_t cpp_template_predicate(const int32_t *values, int32_t count,
                                          int32_t threshold) {
    if (values == 0 || count < 0 || count > 16) {
        return -1;
    }
    return count_above<int32_t>(values, count, threshold);
}

extern "C" int32_t cpp_template_nontype(const int32_t *values, int32_t count,
                                        int32_t which) {
    if (values == 0 || count < 0 || count > 16) {
        return -1;
    }
    /* Two instantiations with the stride folded in as a constant. */
    return (which & 1) ? strided_sum<1>(values, count)
                       : strided_sum<2>(values, count);
}

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/5
cpp_template_int16 fail 128 lines
// glaurung: cpp_template_int16 @ 0x1190
__attribute__((no_stack_protector)) int32_t cpp_template_int16(const int32_t * arg0, int32_t arg1) {
    int index;
    short total;
    unsigned char local_28[40];
    long ret;
    long t270;
    long t271;
    long t272;
    long t86;
    long var0;
    long var100;
    long var118;
    long var119;
    long var122;
    long var4;
    long var77;
    long var78;
    long var81;
    long var84;
    long var85;
    int var90;
    long var92;
    long var98;
    var0 = 0xffffffff;
    ret = 0xffffffff;
    if ((arg0 == 0)) {
        return ret;
    }
    ret = 0xffffffff;
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return ret;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        return 0;
    }
    var0 = (unsigned long)((unsigned int)(arg1));
    if (((unsigned long)(4) <= (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        var4 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var0)) & -4)));
        t86 = ((unsigned int)((unsigned short)(*(int *)(((long)arg0 + 0x8)))) | ((unsigned int)((unsigned short)(*(int *)(((long)arg0 + 0xc)))) << 16));
        *(int *)(&local_28[0]) = ((unsigned int)((unsigned short)(*(int *)(((long)arg0)))) | ((unsigned int)((unsigned short)(*(int *)(((long)arg0 + 0x4)))) << 16));
        *(int *)((&local_28[0] + 4)) = t86;
        if ((var4 != 4)) {
            t270 = ((unsigned int)((unsigned short)(*(int *)(((long)arg0 + 0x18)))) | ((unsigned int)((unsigned short)(*(int *)(((long)arg0 + 0x1c)))) << 16));
            *(int *)((&local_28[0] + 8)) = ((unsigned int)((unsigned short)(*(int *)(((long)arg0 + 0x10)))) | ((unsigned int)((unsigned short)(*(int *)(((long)arg0 + 0x14)))) << 16));
            *(int *)((&local_28[0] + 12)) = t270;
            if (((unsigned long)((unsigned int)(var4)) != 8)) {
                t271 = ((unsigned int)((unsigned short)(*(int *)(((long)arg0 + 0x28)))) | ((unsigned int)((unsigned short)(*(int *)(((long)arg0 + 0x2c)))) << 16));
                *(int *)((&local_28[0] + 16)) = ((unsigned int)((unsigned short)(*(int *)(((long)arg0 + 0x20)))) | ((unsigned int)((unsigned short)(*(int *)(((long)arg0 + 0x24)))) << 16));
                *(int *)((&local_28[0] + 20)) = t271;
                if (((unsigned long)((unsigned int)(var4)) != 12)) {
                    t272 = ((unsigned int)((unsigned short)(*(int *)(((long)arg0 + 0x38)))) | ((unsigned int)((unsigned short)(*(int *)(((long)arg0 + 0x3c)))) << 16));
                    *(int *)((&local_28[0] + 24)) = ((unsigned int)((unsigned short)(*(int *)(((long)arg0 + 0x30)))) | ((unsigned int)((unsigned short)(*(int *)(((long)arg0 + 0x34)))) << 16));
                    *(int *)((&local_28[0] + 28)) = t272;
                }
            }
        }
        if ((var4 != var0)) {
            L_1240: ;
            do {
                *(short *)((&local_28[0] + (var4 * 2))) = *(short *)(((long)arg0 + var4 * 4));
                index = (var4 + 1);
                var4 = (unsigned long)((unsigned int)(index));
            } while ((var0 != index));
        }
    } else {
        var4 = 0;
        goto L_1240;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        return 0;
    }
    if (((unsigned long)(8) <= (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        var77 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var0)) & -8)));
        var78 = (var77 - 8);
        var81 = (((unsigned long)(var78) >> 3) + 1);
        var84 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var81)) & 7)));
        if (((unsigned long)(56) <= (unsigned long)(var78))) {
            var85 = (var81 & -8);
            var90 = 0;
            var92 = 0;
            do {
                /* asm: paddw */
                /* asm: paddw */
                /* asm: paddw */
                /* asm: paddw */
                /* asm: paddw */
                /* asm: paddw */
                /* asm: paddw */
                /* asm: paddw */
                var92 = (var92 + 64);
                var85 = (var85 - 8);
                var81 = var85;
            } while ((var85 != 0));
        } else {
            var90 = 0;
        }
        if ((var84 != 0)) {
            var98 = (var84 << 4);
            var100 = 0;
            do {
                /* asm: paddw */
                var100 = (var100 + 16);
            } while ((var98 != var100));
        }
        /* asm: paddw */
        ret = (unsigned long)((unsigned int)(var90));
        /* asm: paddw */
        /* asm: paddw */
        var118 = (unsigned long)((unsigned int)(((unsigned int)(var90) >> 16)));
        var119 = var118;
        if ((var77 != var0)) {
            L_1330: ;
            do {
                total = (((var118 & 0xffff) + *(short *)((&local_28[0] + (var77 * 2)))) & 0xffff);
                var122 = (var77 + 1);
                var77 = var122;
                var118 = (unsigned long)((unsigned short)(total));
                var119 = (unsigned long)((unsigned short)(total));
            } while ((var0 != var122));
        }
    } else {
        var77 = 0;
        var118 = 0;
        goto L_1330;
    }
    return (int)((short)((var119 & 0xffff)));
}
cpp_template_int32 pass 68 lines
// glaurung: cpp_template_int32 @ 0x1100
int32_t cpp_template_int32(const int32_t * arg0, int32_t arg1) {
    int total;
    int index;
    long ret;
    long var2;
    long var41;
    long var5;
    int var6;
    int var7;
    int var8;
    int var9;
    ret = 0xffffffff;
    if ((arg0 == 0)) {
        return ret;
    }
    ret = 0xffffffff;
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return ret;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        return 0;
    }
    var2 = (unsigned long)((unsigned int)(arg1));
    if (((unsigned long)(4) <= (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        var5 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var2)) & -4)));
        var6 = *(int *)(((long)arg0));
        var7 = *(int *)(((long)arg0 + 0x4));
        var8 = *(int *)(((long)arg0 + 0x8));
        var9 = *(int *)(((long)arg0 + 0xc));
        if ((var5 != 4)) {
            var6 = (var6 + *(int *)(((long)arg0 + 0x10)));
            var7 = (var7 + *(int *)(((long)arg0 + 0x14)));
            var8 = (var8 + *(int *)(((long)arg0 + 0x18)));
            var9 = (var9 + *(int *)(((long)arg0 + 0x1c)));
            if (((unsigned long)((unsigned int)(var5)) != 8)) {
                var6 = (var6 + *(int *)(((long)arg0 + 0x20)));
                var7 = (var7 + *(int *)(((long)arg0 + 0x24)));
                var8 = (var8 + *(int *)(((long)arg0 + 0x28)));
                var9 = (var9 + *(int *)(((long)arg0 + 0x2c)));
                if (((unsigned long)((unsigned int)(var5)) != 12)) {
                    var6 = (var6 + *(int *)(((long)arg0 + 0x30)));
                    var7 = (var7 + *(int *)(((long)arg0 + 0x34)));
                    var8 = (var8 + *(int *)(((long)arg0 + 0x38)));
                    var9 = (var9 + *(int *)(((long)arg0 + 0x3c)));
                }
            }
        }
        var41 = (unsigned long)((unsigned int)(((var9 + var7) + (var8 + var6))));
        ret = var41;
        if ((var5 == var2)) {
            return ret;
        }
        L_1180: ;
        do {
            total = (var41 + *(int *)(((long)arg0 + var5 * 4)));
            index = (var5 + 1);
            var41 = (unsigned long)((unsigned int)(total));
            var5 = (unsigned long)((unsigned int)(index));
            ret = (unsigned long)((unsigned int)(total));
        } while ((var2 != index));
    } else {
        var41 = 0;
        var5 = 0;
        goto L_1180;
    }
    return ret;
}
cpp_template_nontype pass 141 lines
// glaurung: cpp_template_nontype @ 0x1610
int32_t cpp_template_nontype(const int32_t * arg0, int32_t arg1, int32_t arg2) {
    int total;
    int index;
    long ret;
    long var1;
    int var122;
    long var124;
    long var14;
    long var15;
    long var18;
    long var2;
    long var21;
    long var24;
    int var26;
    int var27;
    int var28;
    int var29;
    long var31;
    int var33;
    int var34;
    int var35;
    int var36;
    long var7;
    long var8;
    long var83;
    int var87;
    int var88;
    int var89;
    long var9;
    int var90;
    ret = 0xffffffff;
    if ((arg0 == 0)) {
        return ret;
    }
    ret = 0xffffffff;
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return ret;
    }
    if (((unsigned long)((unsigned char)((arg2 & 1))) == 0)) {
        if (((unsigned long)((unsigned int)(arg1)) == 0)) {
            goto L_165d;
        }
        var1 = (unsigned long)((unsigned int)(arg1));
        var2 = ((unsigned long)((unsigned int)(arg1)) - 1);
        if (((unsigned long)(16) <= (unsigned long)(var2))) {
            goto L_1660;
        }
        var7 = 0;
        var8 = 0;
        goto L_16e0;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        goto L_165d;
    }
    var9 = (unsigned long)((unsigned int)(arg1));
    if (((unsigned long)(4) <= (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        goto L_16ee;
    }
    var14 = 0;
    var15 = 0;
    goto L_1740;
    L_165d: ;
    return 0;
    L_1660: ;
    var18 = (((unsigned long)(var2) >> 1) + 1);
    var21 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var18)) & 7)));
    var24 = (var18 - ((var21 != 0) ? var21 : 8));
    var8 = (var24 + var24);
    var26 = 0;
    var27 = 0;
    var28 = 0;
    var29 = 0;
    var31 = 0;
    var33 = 0;
    var34 = 0;
    var35 = 0;
    var36 = 0;
    do {
        var26 = (var26 + *(int *)(((long)arg0 + var31 * 8)));
        var27 = (var27 + *(int *)(((long)arg0 + var31 * 8 + 0x8)));
        var28 = (var28 + *(int *)(((long)arg0 + var31 * 8 + 0x10)));
        var29 = (var29 + *(int *)(((long)arg0 + var31 * 8 + 0x18)));
        ret = ((unsigned long)((unsigned int)(var27)) | (unsigned long)((unsigned int)(var26)));
        var33 = (var33 + *(int *)(((long)arg0 + var31 * 8 + 0x20)));
        var34 = (var34 + *(int *)(((long)arg0 + var31 * 8 + 0x28)));
        var35 = (var35 + *(int *)(((long)arg0 + var31 * 8 + 0x30)));
        var36 = (var36 + *(int *)(((long)arg0 + var31 * 8 + 0x38)));
        var31 = (var31 + 8);
    } while ((var24 != var31));
    var7 = (unsigned long)((unsigned int)((((var36 + var29) + (var34 + var27)) + ((var35 + var28) + (var33 + var26)))));
    L_16e0: ;
    total = (var7 + *(int *)(((long)arg0 + var8 * 4)));
    var83 = (unsigned long)((unsigned int)(total));
    index = (var8 + 2);
    var7 = (unsigned long)((unsigned int)(total));
    var8 = (unsigned long)((unsigned int)(index));
    if (((unsigned long)(index) < (unsigned long)(var1))) {
        goto L_16e0;
    }
    return var83;
    L_16ee: ;
    var15 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var9)) & -4)));
    var87 = *(int *)(((long)arg0));
    var88 = *(int *)(((long)arg0 + 0x4));
    var89 = *(int *)(((long)arg0 + 0x8));
    var90 = *(int *)(((long)arg0 + 0xc));
    if ((var15 != 4)) {
        var87 = (var87 + *(int *)(((long)arg0 + 0x10)));
        var88 = (var88 + *(int *)(((long)arg0 + 0x14)));
        var89 = (var89 + *(int *)(((long)arg0 + 0x18)));
        var90 = (var90 + *(int *)(((long)arg0 + 0x1c)));
        if (((unsigned long)((unsigned int)(var15)) != 8)) {
            var87 = (var87 + *(int *)(((long)arg0 + 0x20)));
            var88 = (var88 + *(int *)(((long)arg0 + 0x24)));
            var89 = (var89 + *(int *)(((long)arg0 + 0x28)));
            var90 = (var90 + *(int *)(((long)arg0 + 0x2c)));
            if (((unsigned long)((unsigned int)(var15)) != 12)) {
                var87 = (var87 + *(int *)(((long)arg0 + 0x30)));
                var88 = (var88 + *(int *)(((long)arg0 + 0x34)));
                var89 = (var89 + *(int *)(((long)arg0 + 0x38)));
                var90 = (var90 + *(int *)(((long)arg0 + 0x3c)));
            }
        }
    }
    var14 = (unsigned long)((unsigned int)(((var90 + var88) + (var89 + var87))));
    ret = var14;
    if ((var15 == var9)) {
        return ret;
    }
    L_1740: ;
    var122 = (var14 + *(int *)(((long)arg0 + var15 * 4)));
    var124 = (var15 + 1);
    var14 = (unsigned long)((unsigned int)(var122));
    var15 = var124;
    ret = (unsigned long)((unsigned int)(var122));
    if ((var9 != var124)) {
        goto L_1740;
    }
    return ret;
}
cpp_template_predicate pass 78 lines
// glaurung: cpp_template_predicate @ 0x1550
int32_t cpp_template_predicate(const int32_t * arg0, int32_t arg1, int32_t arg2) {
    int hits;
    int index;
    long ret;
    long t10;
    int var10;
    int var11;
    int var12;
    int var13;
    long var2;
    int var22;
    int var23;
    int var24;
    int var25;
    long var5;
    long var69;
    ret = 0xffffffff;
    if ((arg0 == 0)) {
        return ret;
    }
    ret = 0xffffffff;
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return ret;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        return 0;
    }
    var2 = (unsigned long)((unsigned int)(arg1));
    if (((unsigned long)(4) <= (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        var5 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var2)) & -4)));
        var10 = arg2;
        var11 = arg2;
        var12 = arg2;
        var13 = arg2;
        var22 = ((unsigned int)((-(arg2 < *(int *)(((long)arg0))))) >> 31);
        var23 = ((unsigned int)((-(arg2 < *(int *)(((long)arg0 + 0x4))))) >> 31);
        var24 = ((unsigned int)((-(arg2 < *(int *)(((long)arg0 + 0x8))))) >> 31);
        var25 = ((unsigned int)((-(arg2 < *(int *)(((long)arg0 + 0xc))))) >> 31);
        if ((var5 != 4)) {
            var22 = (var22 - (-(var10 < *(int *)(((long)arg0 + 0x10)))));
            var23 = (var23 - (-(var11 < *(int *)(((long)arg0 + 0x14)))));
            var24 = (var24 - (-(var12 < *(int *)(((long)arg0 + 0x18)))));
            var25 = (var25 - (-(var13 < *(int *)(((long)arg0 + 0x1c)))));
            if (((unsigned long)((unsigned int)(var5)) != 8)) {
                var22 = (var22 - (-(var10 < *(int *)(((long)arg0 + 0x20)))));
                var23 = (var23 - (-(var11 < *(int *)(((long)arg0 + 0x24)))));
                var24 = (var24 - (-(var12 < *(int *)(((long)arg0 + 0x28)))));
                var25 = (var25 - (-(var13 < *(int *)(((long)arg0 + 0x2c)))));
                if (((unsigned long)((unsigned int)(var5)) != 12)) {
                    var22 = (var22 - (-(var10 < *(int *)(((long)arg0 + 0x30)))));
                    var23 = (var23 - (-(var11 < *(int *)(((long)arg0 + 0x34)))));
                    var24 = (var24 - (-(var12 < *(int *)(((long)arg0 + 0x38)))));
                    var25 = (var25 - (-(var13 < *(int *)(((long)arg0 + 0x3c)))));
                }
            }
        }
        var69 = (unsigned long)((unsigned int)(((var25 + var23) + (var24 + var22))));
        ret = var69;
        if ((var5 == var2)) {
            return ret;
        }
        L_15f0: ;
        do {
            t10 = *(int *)(((long)arg0 + var5 * 4));
            hits = (var69 + ((((unsigned int)(t10) == (unsigned int)(arg2)) | ((long)((int)(t10)) < (long)(arg2))) == 0));
            index = (var5 + 1);
            var69 = (unsigned long)((unsigned int)(hits));
            var5 = (unsigned long)((unsigned int)(index));
            ret = (unsigned long)((unsigned int)(hits));
        } while ((var2 != index));
    } else {
        var69 = 0;
        var5 = 0;
        goto L_15f0;
    }
    return ret;
}
cpp_template_uint8 fail 159 lines
// glaurung: cpp_template_uint8 @ 0x1350
__attribute__((no_stack_protector)) int32_t cpp_template_uint8(const int32_t * arg0, int32_t arg1) {
    int index;
    unsigned char total;
    unsigned char local_14[20];
    unsigned char local_18[4];
    long ret;
    long var0;
    long var107;
    long var3;
    long var46;
    long var50;
    long var52;
    long var53;
    long var56;
    int var58;
    long var71;
    long var72;
    long var75;
    long var78;
    long var81;
    long var89;
    long var92;
    long var95;
    long var97;
    var0 = 0xffffffff;
    ret = 0xffffffff;
    if ((arg0 == 0)) {
        return ret;
    }
    ret = 0xffffffff;
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return ret;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        goto L_1433;
    }
    var0 = (unsigned long)((unsigned int)(arg1));
    if (((unsigned long)((unsigned long)((unsigned int)(arg1))) < (unsigned long)(4))) {
        var3 = 0;
        goto L_1410;
    }
    var3 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var0)) & -4)));
    /* asm: packuswb */
    /* asm: packuswb */
    *(int *)(&local_18[0]) = (*(int *)(((long)arg0)) & 255);
    if ((var3 != 4)) {
        /* asm: packuswb */
        /* asm: packuswb */
        *(int *)(&local_14[0]) = (*(int *)(((long)arg0 + 0x10)) & 255);
        if (((unsigned long)((unsigned int)(var3)) != 8)) {
            /* asm: packuswb */
            /* asm: packuswb */
            *(int *)((&local_14[0] + 4)) = (*(int *)(((long)arg0 + 0x20)) & 255);
            if (((unsigned long)((unsigned int)(var3)) != 12)) {
                /* asm: packuswb */
                /* asm: packuswb */
                *(int *)((&local_14[0] + 8)) = (*(int *)(((long)arg0 + 0x30)) & 255);
            }
        }
    }
    if ((var3 == var0)) {
        goto L_1421;
    }
    L_1410: ;
    *(signed char *)((&local_18[0] + var3)) = *(char *)(((long)arg0 + var3 * 4));
    index = (var3 + 1);
    var3 = (unsigned long)((unsigned int)(index));
    if ((var0 != index)) {
        goto L_1410;
    }
    L_1421: ;
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        goto L_1433;
    }
    if (((unsigned long)(8) <= (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        goto L_1436;
    }
    var46 = 0;
    total = 0;
    goto L_1530;
    L_1433: ;
    return 0;
    L_1436: ;
    if (((unsigned long)(16) <= (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        goto L_147d;
    }
    var50 = 0;
    var52 = 0;
    L_143f: ;
    var53 = var52;
    var56 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var0)) & -8)));
    var58 = (unsigned int)((unsigned char)((var50 & 255)));
    do {
        /* asm: paddb */
        var53 = (var53 + 8);
    } while ((var56 != var53));
    /* asm: psadbw */
    var71 = (unsigned long)((unsigned int)(var58));
    var46 = var56;
    total = (unsigned long)((unsigned int)(var58));
    if ((var56 != var0)) {
        goto L_1530;
    }
    var72 = var71;
    return (unsigned int)((unsigned char)((var71 & 255)));
    L_147d: ;
    var52 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var0)) & -16)));
    var75 = (var52 - 16);
    var78 = (((unsigned long)(var75) >> 4) + 1);
    var81 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var78)) & 7)));
    if (((unsigned long)(112) <= (unsigned long)(var75))) {
        var89 = (var78 & -8);
        var92 = 0;
        do {
            /* asm: paddb */
            /* asm: paddb */
            /* asm: paddb */
            /* asm: paddb */
            /* asm: paddb */
            /* asm: paddb */
            /* asm: paddb */
            /* asm: paddb */
            var92 = (var92 + 128);
            var89 = (var89 - 8);
            var78 = var89;
        } while ((var89 != 0));
    }
    if ((var81 != 0)) {
        var95 = (var81 << 4);
        var97 = 0;
        do {
            /* asm: paddb */
            var97 = (var97 + 16);
        } while ((var95 != var97));
    }
    /* asm: paddb */
    ret = 0;
    /* asm: psadbw */
    var50 = 0;
    var72 = 0;
    if ((var52 == var0)) {
        return (unsigned int)((unsigned char)((var72 & 255)));
    }
    var46 = var52;
    total = 0;
    if (((unsigned long)((unsigned char)((var0 & 8))) != 0)) {
        goto L_143f;
    }
    L_1530: ;
    total = (((total & 255) + *(char *)((&local_18[0] + var46))) & 255);
    var107 = (var46 + 1);
    var46 = var107;
    var72 = (unsigned long)(total);
    if ((var0 != var107)) {
        goto L_1530;
    }
    return (unsigned int)((unsigned char)((var72 & 255)));
}

gcc -O2

3/5
cpp_template_int16 fail 44 lines
// glaurung: cpp_template_int16 @ 0x1160
int32_t cpp_template_int16(const int32_t * arg0, int32_t arg1) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    int index;
    short total;
    long local_10;
    unsigned char local_38[32];
    long ret;
    long var12;
    long var7;
    long var8;
    long zf_9;
    local_10 = (long)(0x28);
    index = 0;
    if ((arg0 == 0)) {
        L_11dc: ;
        ret = 0xffffffff;
    } else {
        if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
            goto L_11dc;
        } else {
            if (((unsigned long)((unsigned int)(arg1)) == 0)) {
                ret = 0;
            } else {
                var7 = (unsigned long)((unsigned int)((arg1 - 1)));
                var8 = (long)(&local_38[0]);
                do {
                    *(short *)((var8 + index * 2)) = *(int *)(((long)arg0 + index * 4));
                    zf_9 = (var7 == index);
                    index = (index + 1);
                } while ((zf_9 == 0));
                var12 = (long)(((&local_38[0] + (var7 * 2)) + 2));
                do {
                    var8 = (var8 + 2);
                } while ((var12 != var8));
                ret = (int)((short)(ret));
            }
        }
    }
    if ((local_10 != 0x28)) {
        __stack_chk_fail();
    }
    return ret;
}
cpp_template_int32 pass 25 lines
// glaurung: cpp_template_int32 @ 0x1120
int32_t cpp_template_int32(const int32_t * arg0, int32_t arg1) {
    int index;
    int total;
    long ret;
    long var2;
    long var5;
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return 0xffffffff;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        return 0;
    }
    var2 = (long)((((long)arg0 + ((unsigned long)((unsigned int)((arg1 - 1))) * 4)) + 4));
    ret = 0;
    var5 = (long)arg0;
    do {
        ret = (unsigned long)((unsigned int)((ret + *(int *)((var5)))));
        var5 = (var5 + 4);
    } while ((var5 != var2));
    return ret;
}
cpp_template_nontype pass 41 lines
// glaurung: cpp_template_nontype @ 0x12d0
int32_t cpp_template_nontype(const int32_t * arg0, int32_t arg1, int32_t arg2) {
    int index;
    int total;
    long ret;
    int var1;
    long var13;
    long var14;
    long var3;
    long var6;
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return 0xffffffff;
    }
    var1 = ((unsigned long)((unsigned int)(arg2)) & 1);
    ret = (unsigned long)((unsigned int)(var1));
    if (((unsigned long)((unsigned int)(var1)) != 0)) {
        if (((unsigned long)((unsigned int)(arg1)) == 0)) {
            return 0;
        }
        var3 = (long)((((long)arg0 + ((unsigned long)((unsigned int)((arg1 - 1))) * 4)) + 4));
        ret = 0;
        var6 = (long)arg0;
        do {
            ret = (unsigned long)((unsigned int)((ret + *(int *)((var6)))));
            var6 = (var6 + 4);
        } while ((var6 != var3));
        return ret;
    }
    if (((unsigned long)((unsigned int)(arg1)) != 0)) {
        var13 = (long)((((long)arg0 + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg1 - 1))) >> 1))) * 8)) + 8));
        var14 = (long)arg0;
        do {
            ret = (unsigned long)((unsigned int)((ret + *(int *)((var14)))));
            var14 = (var14 + 8);
        } while ((var14 != var13));
    }
    return ret;
}
cpp_template_predicate pass 27 lines
// glaurung: cpp_template_predicate @ 0x1280
int32_t cpp_template_predicate(const int32_t * arg0, int32_t arg1, int32_t arg2) {
    int hits;
    int index;
    long ret;
    long t11;
    long var2;
    long var7;
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return 0xffffffff;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        return 0;
    }
    var2 = (long)((((long)arg0 + ((unsigned long)((unsigned int)((arg1 - 1))) * 4)) + 4));
    ret = 0;
    var7 = (long)arg0;
    do {
        t11 = *(int *)((var7));
        var7 = (var7 + 4);
        ret = (unsigned long)((unsigned int)((ret + ((long)(arg2) < (long)((int)(t11))))));
    } while ((var7 != var2));
    return ret;
}
cpp_template_uint8 fail 51 lines
// glaurung: cpp_template_uint8 @ 0x11f0
int32_t cpp_template_uint8(const int32_t * arg0, int32_t arg1) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    int index;
    unsigned char total;
    long local_10;
    unsigned char local_28[16];
    long ret;
    long rsp;
    long var12;
    long var15;
    long var7;
    long var8;
    long zf_9;
    rsp = (rsp - 40);
    local_10 = (long)(0x28);
    index = 0;
    if ((arg0 == 0)) {
        L_126c: ;
        ret = 0xffffffff;
    } else {
        if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
            goto L_126c;
        } else {
            if (((unsigned long)((unsigned int)(arg1)) == 0)) {
                ret = 0;
            } else {
                var7 = (unsigned long)((unsigned int)((arg1 - 1)));
                var8 = (long)(&local_28[0]);
                do {
                    *(signed char *)((var8 + index)) = *(int *)(((long)arg0 + index * 4));
                    zf_9 = (index == var7);
                    index = (index + 1);
                } while ((zf_9 == 0));
                var12 = ((rsp + var7) + 1);
                var15 = 0;
                do {
                    total = (((var15 & 255) + *(char *)((var8))) & 255);
                    var8 = (var8 + 1);
                    var15 = (unsigned long)(total);
                } while ((var12 != var8));
                ret = (unsigned int)((unsigned char)((total & 255)));
            }
        }
    }
    if ((local_10 != 0x28)) {
        __stack_chk_fail();
    }
    // x86-64 epilogue: tear down frame
    return ret;
}

clang -O0

5/5
cpp_template_int16 pass 30 lines
// glaurung: cpp_template_int16 @ 0x11b0
__attribute__((no_stack_protector)) int32_t cpp_template_int16(const int32_t * arg0, int32_t arg1) {
    extern short _ZN12_GLOBAL__N_116accumulate_rangeIsEET_PKS1_iS1_(short *, int, short);
    int index;
    int local_4;
    unsigned char local_40[32];
    short var13;
    // x86-64 prologue: save rbp, frame 80 bytes
    if ((arg0 == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((long)(arg1) < 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    for (index = 0; (index < arg1); index++) {
        *(short *)((&local_40[0] + ((long)(index) * 2))) = arg0[(long)(index)];
    }
    var13 = _ZN12_GLOBAL__N_116accumulate_rangeIsEET_PKS1_iS1_((short *)(&local_40[0]), (unsigned long)((unsigned int)(arg1)), 0);
    // x86-64 epilogue: restore rbp
    return (unsigned int)((short)(var13));
}
cpp_template_int32 pass 26 lines
// glaurung: cpp_template_int32 @ 0x1100
int32_t cpp_template_int32(const int32_t * arg0, int32_t arg1) {
    extern int _ZN12_GLOBAL__N_116accumulate_rangeIiEET_PKS1_iS1_(int *, int, int);
    int local_4;
    int var1;
    // x86-64 prologue: save rbp, frame 32 bytes
    if ((arg0 == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((long)(arg1) < 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    var1 = _ZN12_GLOBAL__N_116accumulate_rangeIiEET_PKS1_iS1_((int *)(arg0), (unsigned long)((unsigned int)(arg1)), 0);
    local_4 = var1;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}
cpp_template_nontype pass 35 lines
// glaurung: cpp_template_nontype @ 0x1450
int32_t cpp_template_nontype(const int32_t * arg0, int32_t arg1, int32_t arg2) {
    extern int _ZN12_GLOBAL__N_111strided_sumILi1EEEiPKii(int *, int);
    extern int _ZN12_GLOBAL__N_111strided_sumILi2EEEiPKii(int *, int);
    int local_1c;
    int local_4;
    int var3;
    int var5;
    // x86-64 prologue: save rbp, frame 32 bytes
    if ((arg0 == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((long)(arg1) < 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg2)) & 1))) == 0)) {
        var3 = _ZN12_GLOBAL__N_111strided_sumILi2EEEiPKii((int *)(arg0), (unsigned long)((unsigned int)(arg1)));
        local_1c = var3;
    } else {
        var5 = _ZN12_GLOBAL__N_111strided_sumILi1EEEiPKii((int *)(arg0), (unsigned long)((unsigned int)(arg1)));
        local_1c = var5;
    }
    local_4 = local_1c;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}
cpp_template_predicate pass 26 lines
// glaurung: cpp_template_predicate @ 0x1390
int32_t cpp_template_predicate(const int32_t * arg0, int32_t arg1, int32_t arg2) {
    extern int _ZN12_GLOBAL__N_111count_aboveIiEEiPKT_iS1_(int *, int, int);
    int local_4;
    int var0;
    // x86-64 prologue: save rbp, frame 32 bytes
    if ((arg0 == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((long)(arg1) < 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    var0 = _ZN12_GLOBAL__N_111count_aboveIiEEiPKT_iS1_((int *)(arg0), (unsigned long)((unsigned int)(arg1)), (unsigned long)((unsigned int)(arg2)));
    local_4 = var0;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}
cpp_template_uint8 pass 30 lines
// glaurung: cpp_template_uint8 @ 0x12a0
__attribute__((no_stack_protector)) int32_t cpp_template_uint8(const int32_t * arg0, int32_t arg1) {
    extern unsigned char _ZN12_GLOBAL__N_116accumulate_rangeIhEET_PKS1_iS1_(char *, int, unsigned char);
    int index;
    unsigned char local_30[16];
    int local_4;
    unsigned char var13;
    // x86-64 prologue: save rbp, frame 64 bytes
    if ((arg0 == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((long)(arg1) < 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    for (index = 0; (index < arg1); index++) {
        *(signed char *)((&local_30[0] + (long)(index))) = arg0[(long)(index)];
    }
    var13 = _ZN12_GLOBAL__N_116accumulate_rangeIhEET_PKS1_iS1_((char *)(&local_30[0]), (unsigned long)((unsigned int)(arg1)), 0);
    // x86-64 epilogue: restore rbp
    return (unsigned int)((unsigned char)((var13 & 255)));
}

gcc -O0

5/5
cpp_template_int16 pass 26 lines
// glaurung: cpp_template_int16 @ 0x115f
int32_t cpp_template_int16(const int32_t * arg0, int32_t arg1) {
    extern short _ZN12_GLOBAL__N_116accumulate_rangeIsEET_PKS1_iS1_(short *, int, short);
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    int index;
    unsigned char local_30[32];
    long local_8;
    long ret;
    short var15;
    // x86-64 prologue: save rbp, frame 80 bytes
    local_8 = (long)(0x28);
    if ((((arg0 == 0) || ((long)(arg1) < 0)) || (((unsigned long)((unsigned int)(arg1)) != 16) && (16 <= (long)(arg1))))) {
        ret = 0xffffffff;
    } else {
        for (index = 0; (index < arg1); index++) {
            *(short *)((&local_30[0] + ((long)(index) * 2))) = arg0[(long)(index)];
        }
        var15 = _ZN12_GLOBAL__N_116accumulate_rangeIsEET_PKS1_iS1_((short *)(&local_30[0]), (unsigned long)((unsigned int)(arg1)), 0);
        ret = (int)((short)(var15));
    }
    if ((local_8 != 0x28)) {
        __stack_chk_fail();
    }
    // x86-64 epilogue: restore rbp
    return ret;
}
cpp_template_int32 pass 21 lines
// glaurung: cpp_template_int32 @ 0x1119
int32_t cpp_template_int32(const int32_t * arg0, int32_t arg1) {
    extern int _ZN12_GLOBAL__N_116accumulate_rangeIiEET_PKS1_iS1_(int *, int, int);
    int ret;
    // x86-64 prologue: save rbp, frame 16 bytes
    if ((arg0 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((long)(arg1) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    ret = _ZN12_GLOBAL__N_116accumulate_rangeIiEET_PKS1_iS1_((int *)(arg0), (unsigned long)((unsigned int)(arg1)), 0);
    // x86-64 epilogue: restore rbp
    return ret;
}
cpp_template_nontype pass 27 lines
// glaurung: cpp_template_nontype @ 0x12e7
int32_t cpp_template_nontype(const int32_t * arg0, int32_t arg1, int32_t arg2) {
    extern int _ZN12_GLOBAL__N_111strided_sumILi1EEEiPKii(int *, int);
    extern int _ZN12_GLOBAL__N_111strided_sumILi2EEEiPKii(int *, int);
    int var5;
    int var8;
    // x86-64 prologue: save rbp, frame 16 bytes
    if ((arg0 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((long)(arg1) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg2)) & 1))) == 0)) {
        var5 = _ZN12_GLOBAL__N_111strided_sumILi2EEEiPKii((int *)(arg0), (unsigned long)((unsigned int)(arg1)));
        return var5;
    } else {
        var8 = _ZN12_GLOBAL__N_111strided_sumILi1EEEiPKii((int *)(arg0), (unsigned long)((unsigned int)(arg1)));
        return var8;
    }
}
cpp_template_predicate pass 21 lines
// glaurung: cpp_template_predicate @ 0x12a0
int32_t cpp_template_predicate(const int32_t * arg0, int32_t arg1, int32_t arg2) {
    extern int _ZN12_GLOBAL__N_111count_aboveIiEEiPKT_iS1_(int *, int, int);
    int ret;
    // x86-64 prologue: save rbp, frame 16 bytes
    if ((arg0 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((long)(arg1) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    ret = _ZN12_GLOBAL__N_111count_aboveIiEEiPKT_iS1_((int *)(arg0), (unsigned long)((unsigned int)(arg1)), (unsigned long)((unsigned int)(arg2)));
    // x86-64 epilogue: restore rbp
    return ret;
}
cpp_template_uint8 pass 26 lines
// glaurung: cpp_template_uint8 @ 0x11ff
int32_t cpp_template_uint8(const int32_t * arg0, int32_t arg1) {
    extern unsigned char _ZN12_GLOBAL__N_116accumulate_rangeIhEET_PKS1_iS1_(char *, int, unsigned char);
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    int index;
    unsigned char local_20[16];
    long local_8;
    long ret;
    unsigned char var15;
    // x86-64 prologue: save rbp, frame 64 bytes
    local_8 = (long)(0x28);
    if ((((arg0 == 0) || ((long)(arg1) < 0)) || (((unsigned long)((unsigned int)(arg1)) != 16) && (16 <= (long)(arg1))))) {
        ret = 0xffffffff;
    } else {
        for (index = 0; (index < arg1); index++) {
            *(signed char *)((&local_20[0] + (long)(index))) = arg0[(long)(index)];
        }
        var15 = _ZN12_GLOBAL__N_116accumulate_rangeIhEET_PKS1_iS1_((char *)(&local_20[0]), (unsigned long)((unsigned int)(arg1)), 0);
        ret = (unsigned int)((unsigned char)((var15 & 255)));
    }
    if ((local_8 != 0x28)) {
        __stack_chk_fail();
    }
    // x86-64 epilogue: restore rbp
    return ret;
}

← 213 fixtures