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.
#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/1csr_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/1csr_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/1csr_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/1csr_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);
}