Fixture 26

sparse matrix

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/26_sparse_matrix.c source
#include <stdint.h>

__attribute__((noinline)) uint32_t
csr_matvec(const int32_t *row_offsets, const int32_t *column_indices,
           const int32_t *values, const int32_t *vector, uint32_t *output,
           int32_t rows, int32_t columns, int32_t nonzeros) {
    uint32_t checksum = 0;
    int32_t row;
    if (row_offsets == 0 || column_indices == 0 || values == 0 || vector == 0 ||
        output == 0 || rows < 0 || rows > 15 || columns < 0 || columns > 16 ||
        nonzeros < 0 || nonzeros > 16) {
        return 0;
    }
    for (row = 0; row < rows; ++row) {
        int32_t begin = row_offsets[row];
        int32_t end = row_offsets[row + 1];
        uint32_t sum = 0;
        int32_t position;
        if (begin < 0 || end < begin || end > nonzeros) {
            output[row] = 0;
            continue;
        }
        for (position = begin; position < end; ++position) {
            int32_t column = column_indices[position];
            if (column >= 0 && column < columns) {
                sum += (uint32_t)values[position] * (uint32_t)vector[column];
            }
        }
        output[row] = sum;
        checksum = checksum * 31u + sum;
    }
    return checksum;
}

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
csr_matvec pass 81 lines
// glaurung: csr_matvec @ 0x1100
uint32_t csr_matvec(const int32_t * arg0, const int32_t * arg1, const int32_t * arg2, const int32_t * arg3, uint32_t * arg4, int32_t arg5, int32_t arg6, int32_t arg7) {
    unsigned int checksum;
    int row;
    int begin;
    int end;
    unsigned int sum;
    int position;
    int column;
    int local_4;
    // x86-64 prologue: save rbp
    checksum = 0;
    if ((arg0 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if ((arg1 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if ((arg2 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if ((arg3 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if ((arg4 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if (((long)(arg5) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if (((((unsigned long)((unsigned int)(arg5)) == 15) | ((long)(arg5) < 15)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if (((long)(arg6) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if (((((unsigned long)((unsigned int)(arg6)) == 16) | ((long)(arg6) < 16)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if (((long)(arg7) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if (((((unsigned long)((unsigned int)(arg7)) == 16) | ((long)(arg7) < 16)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    row = 0;
    while ((row < arg5)) {
        begin = arg0[(long)(row)];
        end = arg0[(long)((int)(((unsigned long)((unsigned int)(row)) + 1)))];
        sum = 0;
        if (((((long)(begin) < 0) || (end < begin)) || (((unsigned int)(end) != (unsigned int)(arg7)) && (arg7 <= end)))) {
            arg4[(long)(row)] = 0;
        } else {
            for (position = begin; (position < end); position++) {
                column = arg1[(long)(position)];
                if ((0 <= (long)(column))) {
                    if ((column < arg6)) {
                        sum = ((unsigned int)(((unsigned long)((unsigned int)(arg2[(long)(position)])) * arg3[(long)(column)])) + sum);
                    }
                }
            }
            arg4[(long)(row)] = sum;
            checksum = ((checksum * 31) + sum);
        }
        row = ((unsigned int)(row) + 1);
    }
    local_4 = checksum;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}

clang -O2

1/1
csr_matvec pass 157 lines
// glaurung: csr_matvec @ 0x1100
uint32_t csr_matvec(const int32_t * arg0, const int32_t * arg1, const int32_t * arg2, const int32_t * arg3, uint32_t * arg4, int32_t arg5, int32_t arg6, int32_t arg7) {
    unsigned int checksum;
    int begin;
    int end;
    int column;
    int row;
    unsigned int sum;
    long local_10;
    long local_18;
    long local_20;
    long local_28;
    long local_30;
    long local_38;
    long ret;
    long var0;
    long var1;
    long var14;
    long var15;
    long var2;
    long var21;
    long var24;
    long var28;
    long var3;
    long var31;
    long var37;
    long var39;
    long var4;
    long var42;
    long var43;
    long var44;
    long var49;
    long var5;
    long var54;
    long var55;
    long var7;
    local_10 = var0;
    local_18 = var1;
    local_20 = var2;
    local_28 = var3;
    local_30 = var4;
    var5 = (unsigned long)((unsigned int)(arg7));
    var7 = 0;
    ret = 0;
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg7))))) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    var14 = (unsigned long)((unsigned int)(arg6));
    ret = var7;
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg6))))) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    ret = var7;
    if (((unsigned long)(15) < (unsigned long)((unsigned long)((unsigned int)(arg5))))) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    ret = var7;
    if ((arg0 == 0)) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    ret = var7;
    if ((arg1 == 0)) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    ret = var7;
    if ((arg2 == 0)) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    ret = var7;
    if ((arg3 == 0)) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    ret = var7;
    if ((arg4 == 0)) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    ret = var7;
    if ((((unsigned long)((unsigned int)(arg5)) == 0) | ((long)(arg5) < 0))) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    var15 = (unsigned long)((unsigned int)(arg5));
    local_38 = (unsigned int)(arg5);
    var21 = 0;
    checksum = 0;
    do {
        begin = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + var21 * 4))));
        var24 = (var21 + 1);
        if (((long)(begin) < 0)) {
            L_1180: ;
            *(int *)(((long)arg4 + var21 * 4)) = 0;
        } else {
            end = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + var21 * 4 + 0x4))));
            if ((end < begin)) {
                goto L_1180;
            } else {
                if (((((unsigned int)(end) == (unsigned int)(var5)) | ((long)(end) < (long)((int)(var5)))) == 0)) {
                    goto L_1180;
                } else {
                    var28 = 0;
                    if ((begin < end)) {
                        var31 = ((long)(end) - (unsigned long)((unsigned int)(begin)));
                        var28 = 0;
                        var37 = (unsigned long)((unsigned int)(begin));
                        if ((((~begin) + (long)(end)) != 0)) {
                            var39 = (var31 & -2);
                            var42 = 0;
                            do {
                                var43 = (unsigned long)((unsigned int)(*(int *)(((long)arg1 + begin * 4))));
                                var44 = var42;
                                if (((0 <= (long)((int)(var43))) && ((long)((int)(var43)) < (long)((int)(var14))))) {
                                    var44 = (unsigned long)((unsigned int)((var42 + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)(((long)arg3 + var43 * 4)))) * *(int *)(((long)arg2 + begin * 4))))))));
                                }
                                var49 = (unsigned long)((unsigned int)(*(int *)(((long)arg1 + begin * 4 + 0x4))));
                                if ((0 <= (long)((int)(var49)))) {
                                    if (((long)((int)(var49)) < (long)((int)(var14)))) {
                                        var44 = (unsigned long)((unsigned int)((var44 + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)(((long)arg3 + var49 * 4)))) * *(int *)(((long)arg2 + begin * 4 + 0x4))))))));
                                    }
                                }
                                var54 = ((unsigned long)((unsigned int)(begin)) + 2);
                                var39 = (var39 - 2);
                                var28 = var44;
                                var37 = var54;
                                var42 = var44;
                                begin = var54;
                            } while ((var39 != 0));
                        }
                        var5 = (unsigned long)((unsigned int)(arg7));
                        var15 = local_38;
                        if (((unsigned long)((unsigned char)((var31 & 1))) != 0)) {
                            var55 = (unsigned long)((unsigned int)(*(int *)(((long)arg1 + var37 * 4))));
                            if ((0 <= (long)((int)(var55)))) {
                                if (((long)((int)(var55)) < (long)((int)(var14)))) {
                                    var28 = (unsigned long)((unsigned int)((var28 + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)(((long)arg3 + var55 * 4)))) * *(int *)(((long)arg2 + var37 * 4))))))));
                                }
                            }
                        }
                    }
                    *(int *)(((long)arg4 + var21 * 4)) = var28;
                    checksum = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((checksum << 5))) - checksum))) + var28)));
                }
            }
        }
        var21 = var24;
        ret = (unsigned long)(checksum);
    } while ((var24 != var15));
    // x86-64 epilogue: tear down frame
    return ret;
}

gcc -O0

1/1
csr_matvec pass 79 lines
// glaurung: csr_matvec @ 0x10f9
uint32_t csr_matvec(const int32_t * arg0, const int32_t * arg1, const int32_t * arg2, const int32_t * arg3, uint32_t * arg4, int32_t arg5, int32_t arg6, int32_t arg7) {
    unsigned int checksum;
    int row;
    int begin;
    int end;
    unsigned int sum;
    int position;
    int column;
    // x86-64 prologue: save rbp
    checksum = 0;
    if ((arg0 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if ((arg1 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if ((arg2 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if ((arg3 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if ((arg4 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if (((long)(arg5) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if (((((unsigned long)((unsigned int)(arg5)) == 15) | ((long)(arg5) < 15)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if (((long)(arg6) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if (((((unsigned long)((unsigned int)(arg6)) == 16) | ((long)(arg6) < 16)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if (((long)(arg7) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if (((((unsigned long)((unsigned int)(arg7)) == 16) | ((long)(arg7) < 16)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    row = 0;
    while ((row < arg5)) {
        begin = arg0[(long)(row)];
        end = arg0[((long)(row) + 1)];
        sum = 0;
        if (((((long)(begin) < 0) || (end < begin)) || (((unsigned int)(end) != (unsigned int)(arg7)) && (arg7 <= end)))) {
            arg4[(long)(row)] = 0;
        } else {
            for (position = begin; (position < end); position++) {
                column = arg1[(long)(position)];
                if ((0 <= (long)(column))) {
                    if ((column < arg6)) {
                        sum = (sum + (unsigned int)(((unsigned long)((unsigned int)(arg3[(long)(column)])) * (unsigned long)((unsigned int)(arg2[(long)(position)])))));
                    }
                }
            }
            arg4[(long)(row)] = sum;
            checksum = (sum + (unsigned int)(((unsigned long)((unsigned int)((checksum << 5))) - checksum)));
        }
        row = (row + 1);
    }
    // x86-64 epilogue: restore rbp
    return checksum;
}

gcc -O2

1/1
csr_matvec pass 115 lines
// glaurung: csr_matvec @ 0x1100
uint32_t csr_matvec(const int32_t * arg0, const int32_t * arg1, const int32_t * arg2, const int32_t * arg3, uint32_t * arg4, int32_t arg5, int32_t arg6, int32_t arg7) {
    unsigned int checksum;
    int row;
    int begin;
    int end;
    int column;
    unsigned int sum;
    long local_10;
    long local_20;
    long local_8;
    long var0;
    long var1;
    long var12;
    long var15;
    long var2;
    long var3;
    long var30;
    long var31;
    long var32;
    long var33;
    long var34;
    long var4;
    long var40;
    long var46;
    long var7;
    local_8 = var0;
    local_10 = var1;
    local_20 = var2;
    var3 = (unsigned long)((unsigned int)(arg6));
    var4 = var1;
    if ((arg0 == 0)) {
        var7 = 0;
        // x86-64 epilogue: tear down frame
        return 0;
    }
    var4 = var1;
    if ((arg1 == 0)) {
        var7 = 0;
        // x86-64 epilogue: tear down frame
        return 0;
    }
    var12 = (long)arg2;
    var4 = 0;
    var7 = 0;
    if ((arg2 == 0)) {
        // x86-64 epilogue: tear down frame
        return (unsigned int)(var7);
    }
    var7 = var4;
    if ((arg3 == 0)) {
        // x86-64 epilogue: tear down frame
        return (unsigned int)(var7);
    }
    var7 = var4;
    if ((arg4 == 0)) {
        // x86-64 epilogue: tear down frame
        return (unsigned int)(var7);
    }
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(var3))))) {
        var7 = 0;
        // x86-64 epilogue: tear down frame
        return 0;
    }
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg7))))) {
        var7 = 0;
        // x86-64 epilogue: tear down frame
        return 0;
    }
    var7 = var4;
    if (((unsigned long)(14) < (unsigned long)((unsigned long)((unsigned int)((arg5 - 1)))))) {
        // x86-64 epilogue: tear down frame
        return (unsigned int)(var7);
    }
    var15 = (unsigned long)((unsigned int)(arg5));
    checksum = var4;
    row = 0;
    do {
        begin = (long)((int)(*(int *)(((long)arg0 + row * 4))));
        end = (unsigned long)((unsigned int)(*(int *)(((long)arg0 + row * 4 + 0x4))));
        var30 = 0;
        var31 = (unsigned long)(checksum);
        var32 = 0;
        if (((unsigned long)((unsigned char)((((((unsigned int)(begin) == (unsigned int)(end)) | (begin < end)) == 0) | ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(begin)) >> 31))) & 255)))) == 0)) {
            var31 = (unsigned long)(checksum);
            var32 = var30;
            if ((end <= arg7)) {
                if ((begin < end)) {
                    var33 = var30;
                    var34 = (unsigned long)((unsigned int)(begin));
                    do {
                        column = (long)((int)(*(int *)(((long)arg1 + var34 * 4))));
                        if ((0 <= (long)(column))) {
                            if (((((unsigned int)(var3) == (unsigned int)(column)) | ((long)((int)(var3)) < (long)(column))) == 0)) {
                                var33 = (unsigned long)((unsigned int)((var33 + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)(((long)arg3 + column * 4)))) * *(int *)((var12 + var34 * 4))))))));
                            }
                        }
                        var40 = (var34 + 1);
                        var34 = var40;
                        var30 = var33;
                    } while (((((unsigned int)(end) == (unsigned int)(var40)) | ((long)(end) < (long)((int)(var40)))) == 0));
                }
                var31 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((checksum << 5))) - checksum))) + var30)));
                var32 = var30;
            }
        }
        *(int *)(((long)arg4 + row * 4)) = var32;
        var46 = ((unsigned long)((unsigned int)(row)) + 1);
        checksum = var31;
        row = var46;
        var7 = var31;
    } while ((var15 != var46));
    // x86-64 epilogue: tear down frame
    return (unsigned int)(var7);
}

← 213 fixtures