Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/datamining/correlation/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/datamining/correlation/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/datamining/correlation/CMakeLists.txt @@ -5,4 +5,5 @@ list(APPEND CFLAGS -DSMALL_DATASET) endif() set(HASH_PROGRAM_OUTPUT 1) +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/datamining/correlation/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/datamining/correlation/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/datamining/correlation/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = correlation -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 ifdef SMALL_PROBLEM_SIZE CFLAGS += -DSMALL_DATASET Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/datamining/correlation/correlation.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/datamining/correlation/correlation.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/datamining/correlation/correlation.c @@ -19,12 +19,13 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array (int m, int n, DATA_TYPE *float_n, DATA_TYPE POLYBENCH_2D(data,M,N,m,n)) { +#pragma STDC FP_CONTRACT OFF int i, j; *float_n = 1.2; @@ -120,6 +121,91 @@ } +__attribute__((optnone)) static void +kernel_correlation_StrictFP(int m, int n, + DATA_TYPE float_n, + DATA_TYPE POLYBENCH_2D(data,M,N,m,n), + DATA_TYPE POLYBENCH_2D(symmat,M,M,m,m), + DATA_TYPE POLYBENCH_1D(mean,M,m), + DATA_TYPE POLYBENCH_1D(stddev,M,m)) +{ +#pragma STDC FP_CONTRACT OFF + int i, j, j1, j2; + + DATA_TYPE eps = 0.1f; + +#define sqrt_of_array_cell(x,j) sqrt(x[j]) + + /* Determine mean of column vectors of input data matrix */ + for (j = 0; j < _PB_M; j++) + { + mean[j] = 0.0; + for (i = 0; i < _PB_N; i++) + mean[j] += data[i][j]; + mean[j] /= float_n; + } + + /* Determine standard deviations of column vectors of data matrix. */ + for (j = 0; j < _PB_M; j++) + { + stddev[j] = 0.0; + for (i = 0; i < _PB_N; i++) + stddev[j] += (data[i][j] - mean[j]) * (data[i][j] - mean[j]); + stddev[j] /= float_n; + stddev[j] = sqrt_of_array_cell(stddev, j); + /* The following in an inelegant but usual way to handle + near-zero std. dev. values, which below would cause a zero- + divide. */ + stddev[j] = stddev[j] <= eps ? 1.0 : stddev[j]; + } + + /* Center and reduce the column vectors. */ + for (i = 0; i < _PB_N; i++) + for (j = 0; j < _PB_M; j++) + { + data[i][j] -= mean[j]; + data[i][j] /= sqrt(float_n) * stddev[j]; + } + + /* Calculate the m * m correlation matrix. */ + for (j1 = 0; j1 < _PB_M-1; j1++) + { + symmat[j1][j1] = 1.0; + for (j2 = j1+1; j2 < _PB_M; j2++) + { + symmat[j1][j2] = 0.0; + for (i = 0; i < _PB_N; i++) + symmat[j1][j2] += (data[i][j1] * data[i][j2]); + symmat[j2][j1] = symmat[j1][j2]; + } + } + symmat[_PB_M-1][_PB_M-1] = 1.0; +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static inline int +check_FP(int m, + DATA_TYPE POLYBENCH_2D(A,M,M,m,m), + DATA_TYPE POLYBENCH_2D(B,M,M,m,m)) { + int i, j; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_M; i++) + for (j = 0; j < _PB_M; j++) + { + double V1 = A[i][j]; + double V2 = B[i][j]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d][%d] = %lf and B[%d][%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, j, V1, i, j, V2, AbsTolerance); + return 0; + } + } + + /* All elements are within the allowed FP_ABSTOLERANCE error margin. */ + return 1; +} int main(int argc, char** argv) { @@ -131,6 +217,7 @@ DATA_TYPE float_n; POLYBENCH_2D_ARRAY_DECL(data,DATA_TYPE,M,N,m,n); POLYBENCH_2D_ARRAY_DECL(symmat,DATA_TYPE,M,M,m,m); + POLYBENCH_2D_ARRAY_DECL(symmat_StrictFP,DATA_TYPE,M,M,m,m); POLYBENCH_1D_ARRAY_DECL(mean,DATA_TYPE,M,m); POLYBENCH_1D_ARRAY_DECL(stddev,DATA_TYPE,M,m); @@ -151,13 +238,23 @@ polybench_stop_instruments; polybench_print_instruments; + init_array (m, n, &float_n, POLYBENCH_ARRAY(data)); + kernel_correlation (m, n, float_n, + POLYBENCH_ARRAY(data), + POLYBENCH_ARRAY(symmat_StrictFP), + POLYBENCH_ARRAY(mean), + POLYBENCH_ARRAY(stddev)); + if (!check_FP(m, POLYBENCH_ARRAY(symmat), POLYBENCH_ARRAY(symmat_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(m, POLYBENCH_ARRAY(symmat))); + polybench_prevent_dce(print_array(m, POLYBENCH_ARRAY(symmat_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(data); POLYBENCH_FREE_ARRAY(symmat); + POLYBENCH_FREE_ARRAY(symmat_StrictFP); POLYBENCH_FREE_ARRAY(mean); POLYBENCH_FREE_ARRAY(stddev); Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/datamining/covariance/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/datamining/covariance/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/datamining/covariance/CMakeLists.txt @@ -5,4 +5,5 @@ list(APPEND CFLAGS -DSMALL_DATASET) endif() set(HASH_PROGRAM_OUTPUT 1) +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/datamining/covariance/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/datamining/covariance/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/datamining/covariance/Makefile @@ -3,7 +3,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = covariance -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 ifdef SMALL_PROBLEM_SIZE CFLAGS += -DSMALL_DATASET Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/datamining/covariance/covariance.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/datamining/covariance/covariance.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/datamining/covariance/covariance.c @@ -19,11 +19,12 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array (int m, int n, DATA_TYPE *float_n, DATA_TYPE POLYBENCH_2D(data,M,N,m,n)) { +#pragma STDC FP_CONTRACT OFF int i, j; *float_n = 1.2; @@ -92,6 +93,65 @@ } +__attribute__((optnone)) static void +kernel_covariance_StrictFP(int m, int n, + DATA_TYPE float_n, + DATA_TYPE POLYBENCH_2D(data,M,N,m,n), + DATA_TYPE POLYBENCH_2D(symmat,M,M,m,m), + DATA_TYPE POLYBENCH_1D(mean,M,m)) +{ +#pragma STDC FP_CONTRACT OFF + int i, j, j1, j2; + + /* Determine mean of column vectors of input data matrix */ + for (j = 0; j < _PB_M; j++) + { + mean[j] = 0.0; + for (i = 0; i < _PB_N; i++) + mean[j] += data[i][j]; + mean[j] /= float_n; + } + + /* Center the column vectors. */ + for (i = 0; i < _PB_N; i++) + for (j = 0; j < _PB_M; j++) + data[i][j] -= mean[j]; + + /* Calculate the m * m covariance matrix. */ + for (j1 = 0; j1 < _PB_M; j1++) + for (j2 = j1; j2 < _PB_M; j2++) + { + symmat[j1][j2] = 0.0; + for (i = 0; i < _PB_N; i++) + symmat[j1][j2] += data[i][j1] * data[i][j2]; + symmat[j2][j1] = symmat[j1][j2]; + } +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static inline int +check_FP(int m, + DATA_TYPE POLYBENCH_2D(A,M,M,m,m), + DATA_TYPE POLYBENCH_2D(B,M,M,m,m)) { + int i, j; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_M; i++) + for (j = 0; j < _PB_M; j++) + { + double V1 = A[i][j]; + double V2 = B[i][j]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d][%d] = %lf and B[%d][%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, j, V1, i, j, V2, AbsTolerance); + return 0; + } + } + + /* All elements are within the allowed FP_ABSTOLERANCE error margin. */ + return 1; +} int main(int argc, char** argv) { @@ -103,6 +163,7 @@ DATA_TYPE float_n; POLYBENCH_2D_ARRAY_DECL(data,DATA_TYPE,M,N,m,n); POLYBENCH_2D_ARRAY_DECL(symmat,DATA_TYPE,M,M,m,m); + POLYBENCH_2D_ARRAY_DECL(symmat_StrictFP,DATA_TYPE,M,M,m,m); POLYBENCH_1D_ARRAY_DECL(mean,DATA_TYPE,M,m); @@ -122,13 +183,22 @@ polybench_stop_instruments; polybench_print_instruments; + init_array (m, n, &float_n, POLYBENCH_ARRAY(data)); + kernel_covariance (m, n, float_n, + POLYBENCH_ARRAY(data), + POLYBENCH_ARRAY(symmat_StrictFP), + POLYBENCH_ARRAY(mean)); + if (!check_FP(m, POLYBENCH_ARRAY(symmat), POLYBENCH_ARRAY(symmat_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(m, POLYBENCH_ARRAY(symmat))); + polybench_prevent_dce(print_array(m, POLYBENCH_ARRAY(symmat_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(data); POLYBENCH_FREE_ARRAY(symmat); + POLYBENCH_FREE_ARRAY(symmat_StrictFP); POLYBENCH_FREE_ARRAY(mean); return 0; Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/2mm/2mm.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/2mm/2mm.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/2mm/2mm.c @@ -19,15 +19,17 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array(int ni, int nj, int nk, int nl, DATA_TYPE *alpha, DATA_TYPE *beta, DATA_TYPE POLYBENCH_2D(A,NI,NK,ni,nl), DATA_TYPE POLYBENCH_2D(B,NK,NJ,nk,nj), DATA_TYPE POLYBENCH_2D(C,NL,NJ,nl,nj), - DATA_TYPE POLYBENCH_2D(D,NI,NL,ni,nl)) + DATA_TYPE POLYBENCH_2D(D,NI,NL,ni,nl), + DATA_TYPE POLYBENCH_2D(D_StrictFP,NI,NL,ni,nl)) { +#pragma STDC FP_CONTRACT OFF int i, j; *alpha = 32412; @@ -43,7 +45,7 @@ C[i][j] = ((DATA_TYPE) i*(j+3)) / nl; for (i = 0; i < ni; i++) for (j = 0; j < nl; j++) - D[i][j] = ((DATA_TYPE) i*(j+2)) / nk; + D_StrictFP[i][j] = D[i][j] = ((DATA_TYPE) i*(j+2)) / nk; } @@ -99,6 +101,60 @@ } +__attribute__((optnone)) static void +kernel_2mm_StrictFP(int ni, int nj, int nk, int nl, + DATA_TYPE alpha, + DATA_TYPE beta, + DATA_TYPE POLYBENCH_2D(tmp,NI,NJ,ni,nj), + DATA_TYPE POLYBENCH_2D(A,NI,NK,ni,nk), + DATA_TYPE POLYBENCH_2D(B,NK,NJ,nk,nj), + DATA_TYPE POLYBENCH_2D(C,NL,NJ,nl,nj), + DATA_TYPE POLYBENCH_2D(D,NI,NL,ni,nl)) +{ +#pragma STDC FP_CONTRACT OFF + int i, j, k; + + /* D := alpha*A*B*C + beta*D */ + for (i = 0; i < _PB_NI; i++) + for (j = 0; j < _PB_NJ; j++) + { + tmp[i][j] = 0; + for (k = 0; k < _PB_NK; ++k) + tmp[i][j] += alpha * A[i][k] * B[k][j]; + } + for (i = 0; i < _PB_NI; i++) + for (j = 0; j < _PB_NL; j++) + { + D[i][j] *= beta; + for (k = 0; k < _PB_NJ; ++k) + D[i][j] += tmp[i][k] * C[k][j]; + } +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static inline int +check_FP(int ni, int nl, + DATA_TYPE POLYBENCH_2D(A,NI,NL,ni,nl), + DATA_TYPE POLYBENCH_2D(B,NI,NL,ni,nl)) { + int i, j; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_NI; i++) + for (j = 0; j < _PB_NL; j++) + { + double V1 = A[i][j]; + double V2 = B[i][j]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d][%d] = %lf and B[%d][%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, j, V1, i, j, V2, AbsTolerance); + return 0; + } + } + + /* All elements are within the allowed FP_ABSTOLERANCE error margin. */ + return 1; +} int main(int argc, char** argv) { @@ -116,13 +172,15 @@ POLYBENCH_2D_ARRAY_DECL(B,DATA_TYPE,NK,NJ,nk,nj); POLYBENCH_2D_ARRAY_DECL(C,DATA_TYPE,NL,NJ,nl,nj); POLYBENCH_2D_ARRAY_DECL(D,DATA_TYPE,NI,NL,ni,nl); + POLYBENCH_2D_ARRAY_DECL(D_StrictFP,DATA_TYPE,NI,NL,ni,nl); /* Initialize array(s). */ init_array (ni, nj, nk, nl, &alpha, &beta, POLYBENCH_ARRAY(A), POLYBENCH_ARRAY(B), POLYBENCH_ARRAY(C), - POLYBENCH_ARRAY(D)); + POLYBENCH_ARRAY(D), + POLYBENCH_ARRAY(D_StrictFP)); /* Start timer. */ polybench_start_instruments; @@ -140,9 +198,20 @@ polybench_stop_instruments; polybench_print_instruments; + kernel_2mm_StrictFP(ni, nj, nk, nl, + alpha, beta, + POLYBENCH_ARRAY(tmp), + POLYBENCH_ARRAY(A), + POLYBENCH_ARRAY(B), + POLYBENCH_ARRAY(C), + POLYBENCH_ARRAY(D_StrictFP)); + + if (!check_FP(ni, nl, POLYBENCH_ARRAY(D), POLYBENCH_ARRAY(D_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(ni, nl, POLYBENCH_ARRAY(D))); + polybench_prevent_dce(print_array(ni, nl, POLYBENCH_ARRAY(D_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(tmp); @@ -150,6 +219,7 @@ POLYBENCH_FREE_ARRAY(B); POLYBENCH_FREE_ARRAY(C); POLYBENCH_FREE_ARRAY(D); + POLYBENCH_FREE_ARRAY(D_StrictFP); return 0; } Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/2mm/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/2mm/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/2mm/CMakeLists.txt @@ -15,4 +15,5 @@ set(RUNTIMELIMIT 1000) endif() set(HASH_PROGRAM_OUTPUT 1) +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/2mm/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/2mm/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/2mm/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = 2mm -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 ifdef SMALL_PROBLEM_SIZE CFLAGS += -DSMALL_DATASET Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/3mm/3mm.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/3mm/3mm.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/3mm/3mm.c @@ -19,13 +19,14 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array(int ni, int nj, int nk, int nl, int nm, DATA_TYPE POLYBENCH_2D(A,NI,NK,ni,nk), DATA_TYPE POLYBENCH_2D(B,NK,NJ,nk,nj), DATA_TYPE POLYBENCH_2D(C,NJ,NM,nj,nm), DATA_TYPE POLYBENCH_2D(D,NM,NL,nm,nl)) { +#pragma STDC FP_CONTRACT OFF int i, j; for (i = 0; i < ni; i++) @@ -104,6 +105,68 @@ } +__attribute__((optnone)) static +void kernel_3mm_StrictFP(int ni, int nj, int nk, int nl, int nm, + DATA_TYPE POLYBENCH_2D(E,NI,NJ,ni,nj), + DATA_TYPE POLYBENCH_2D(A,NI,NK,ni,nk), + DATA_TYPE POLYBENCH_2D(B,NK,NJ,nk,nj), + DATA_TYPE POLYBENCH_2D(F,NJ,NL,nj,nl), + DATA_TYPE POLYBENCH_2D(C,NJ,NM,nj,nm), + DATA_TYPE POLYBENCH_2D(D,NM,NL,nm,nl), + DATA_TYPE POLYBENCH_2D(G,NI,NL,ni,nl)) +{ +#pragma STDC FP_CONTRACT OFF + int i, j, k; + + /* E := A*B */ + for (i = 0; i < _PB_NI; i++) + for (j = 0; j < _PB_NJ; j++) + { + E[i][j] = 0; + for (k = 0; k < _PB_NK; ++k) + E[i][j] += A[i][k] * B[k][j]; + } + /* F := C*D */ + for (i = 0; i < _PB_NJ; i++) + for (j = 0; j < _PB_NL; j++) + { + F[i][j] = 0; + for (k = 0; k < _PB_NM; ++k) + F[i][j] += C[i][k] * D[k][j]; + } + /* G := E*F */ + for (i = 0; i < _PB_NI; i++) + for (j = 0; j < _PB_NL; j++) + { + G[i][j] = 0; + for (k = 0; k < _PB_NJ; ++k) + G[i][j] += E[i][k] * F[k][j]; + } +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static inline int +check_FP(int ni, int nl, + DATA_TYPE POLYBENCH_2D(A,NI,NL,ni,nl), + DATA_TYPE POLYBENCH_2D(B,NI,NL,ni,nl)) { + int i, j; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_NI; i++) + for (j = 0; j < _PB_NL; j++) + { + double V1 = A[i][j]; + double V2 = B[i][j]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d][%d] = %lf and B[%d][%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, j, V1, i, j, V2, AbsTolerance); + return 0; + } + } + + return 1; +} int main(int argc, char** argv) { @@ -122,6 +185,7 @@ POLYBENCH_2D_ARRAY_DECL(C, DATA_TYPE, NJ, NM, nj, nm); POLYBENCH_2D_ARRAY_DECL(D, DATA_TYPE, NM, NL, nm, nl); POLYBENCH_2D_ARRAY_DECL(G, DATA_TYPE, NI, NL, ni, nl); + POLYBENCH_2D_ARRAY_DECL(G_StrictFP, DATA_TYPE, NI, NL, ni, nl); /* Initialize array(s). */ init_array (ni, nj, nk, nl, nm, @@ -147,9 +211,20 @@ polybench_stop_instruments; polybench_print_instruments; + kernel_3mm_StrictFP(ni, nj, nk, nl, nm, + POLYBENCH_ARRAY(E), + POLYBENCH_ARRAY(A), + POLYBENCH_ARRAY(B), + POLYBENCH_ARRAY(F), + POLYBENCH_ARRAY(C), + POLYBENCH_ARRAY(D), + POLYBENCH_ARRAY(G_StrictFP)); + if (!check_FP(ni, nl, POLYBENCH_ARRAY(G), POLYBENCH_ARRAY(G_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(ni, nl, POLYBENCH_ARRAY(G))); + polybench_prevent_dce(print_array(ni, nl, POLYBENCH_ARRAY(G_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(E); @@ -159,6 +234,7 @@ POLYBENCH_FREE_ARRAY(C); POLYBENCH_FREE_ARRAY(D); POLYBENCH_FREE_ARRAY(G); + POLYBENCH_FREE_ARRAY(G_StrictFP); return 0; } Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/3mm/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/3mm/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/3mm/CMakeLists.txt @@ -15,4 +15,5 @@ set(RUNTIMELIMIT 1000) endif() set(HASH_PROGRAM_OUTPUT 1) +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/3mm/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/3mm/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/3mm/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = 3mm -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 ifdef SMALL_PROBLEM_SIZE CFLAGS += -DSMALL_DATASET Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/atax/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/atax/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/atax/CMakeLists.txt @@ -5,4 +5,5 @@ if(ARCH STREQUAL "XCore") set(XCORE_TARGET_NEEDS_MEMORY 128) endif() +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/atax/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/atax/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/atax/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = atax -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 HASH_PROGRAM_OUTPUT = 1 Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/atax/atax.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/atax/atax.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/atax/atax.c @@ -19,11 +19,12 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array (int nx, int ny, DATA_TYPE POLYBENCH_2D(A,NX,NY,nx,ny), DATA_TYPE POLYBENCH_1D(x,NY,ny)) { +#pragma STDC FP_CONTRACT OFF int i, j; for (i = 0; i < ny; i++) @@ -33,7 +34,6 @@ A[i][j] = ((DATA_TYPE) i*(j+1)) / nx; } - /* DCE code. Must scan the entire live-out data. Can be used also to check the correctness of the output. */ static @@ -77,6 +77,50 @@ } +__attribute__((optnone)) static void +kernel_atax_StrictFP(int nx, int ny, + DATA_TYPE POLYBENCH_2D(A,NX,NY,nx,ny), + DATA_TYPE POLYBENCH_1D(x,NY,ny), + DATA_TYPE POLYBENCH_1D(y,NY,ny), + DATA_TYPE POLYBENCH_1D(tmp,NX,nx)) +{ +#pragma STDC FP_CONTRACT OFF + int i, j; + + for (i = 0; i < _PB_NY; i++) + y[i] = 0; + for (i = 0; i < _PB_NX; i++) + { + tmp[i] = 0; + for (j = 0; j < _PB_NY; j++) + tmp[i] = tmp[i] + A[i][j] * x[j]; + for (j = 0; j < _PB_NY; j++) + y[j] = y[j] + A[i][j] * tmp[i]; + } +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static int +check_FP(int ny, + DATA_TYPE POLYBENCH_1D(A,NY,ny), + DATA_TYPE POLYBENCH_1D(B,NY,ny)) { + int i; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_NY; i++) + { + double V1 = A[i]; + double V2 = B[i]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d] = %lf and B[%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, V1, i, V2, AbsTolerance); + return 0; + } + } + + return 1; +} int main(int argc, char** argv) { @@ -88,6 +132,7 @@ POLYBENCH_2D_ARRAY_DECL(A, DATA_TYPE, NX, NY, nx, ny); POLYBENCH_1D_ARRAY_DECL(x, DATA_TYPE, NY, ny); POLYBENCH_1D_ARRAY_DECL(y, DATA_TYPE, NY, ny); + POLYBENCH_1D_ARRAY_DECL(y_StrictFP, DATA_TYPE, NY, ny); POLYBENCH_1D_ARRAY_DECL(tmp, DATA_TYPE, NX, nx); /* Initialize array(s). */ @@ -107,14 +152,23 @@ polybench_stop_instruments; polybench_print_instruments; + kernel_atax_StrictFP (nx, ny, + POLYBENCH_ARRAY(A), + POLYBENCH_ARRAY(x), + POLYBENCH_ARRAY(y_StrictFP), + POLYBENCH_ARRAY(tmp)); + if (!check_FP(ny, POLYBENCH_ARRAY(y), POLYBENCH_ARRAY(y_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(nx, POLYBENCH_ARRAY(y))); + polybench_prevent_dce(print_array(nx, POLYBENCH_ARRAY(y_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(A); POLYBENCH_FREE_ARRAY(x); POLYBENCH_FREE_ARRAY(y); + POLYBENCH_FREE_ARRAY(y_StrictFP); POLYBENCH_FREE_ARRAY(tmp); return 0; Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/bicg/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/bicg/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/bicg/CMakeLists.txt @@ -5,4 +5,5 @@ if(ARCH STREQUAL "XCore") set(XCORE_TARGET_NEEDS_MEMORY 128) endif() +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/bicg/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/bicg/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/bicg/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = bicg -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 HASH_PROGRAM_OUTPUT = 1 Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/bicg/bicg.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/bicg/bicg.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/bicg/bicg.c @@ -19,12 +19,13 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array (int nx, int ny, DATA_TYPE POLYBENCH_2D(A,NX,NY,nx,ny), DATA_TYPE POLYBENCH_1D(r,NX,nx), DATA_TYPE POLYBENCH_1D(p,NY,ny)) { +#pragma STDC FP_CONTRACT OFF int i, j; for (i = 0; i < ny; i++) @@ -89,6 +90,53 @@ } +__attribute__((optnone)) static +void kernel_bicg_StrictFP(int nx, int ny, + DATA_TYPE POLYBENCH_2D(A,NX,NY,nx,ny), + DATA_TYPE POLYBENCH_1D(s,NY,ny), + DATA_TYPE POLYBENCH_1D(q,NX,nx), + DATA_TYPE POLYBENCH_1D(p,NY,ny), + DATA_TYPE POLYBENCH_1D(r,NX,nx)) +{ +#pragma STDC FP_CONTRACT OFF + int i, j; + + for (i = 0; i < _PB_NY; i++) + s[i] = 0; + for (i = 0; i < _PB_NX; i++) + { + q[i] = 0; + for (j = 0; j < _PB_NY; j++) + { + s[j] = s[j] + r[i] * A[i][j]; + q[i] = q[i] + A[i][j] * p[j]; + } + } +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static int +check_FP(int ny, + DATA_TYPE POLYBENCH_1D(A,NY,ny), + DATA_TYPE POLYBENCH_1D(B,NX,nx)) { + int i; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_NY; i++) + { + double V1 = A[i]; + double V2 = B[i]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d] = %lf and B[%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, V1, i, V2, AbsTolerance); + return 0; + } + } + + /* All elements are within the allowed FP_ABSTOLERANCE error margin. */ + return 1; +} int main(int argc, char** argv) { @@ -102,6 +150,8 @@ POLYBENCH_1D_ARRAY_DECL(q, DATA_TYPE, NX, nx); POLYBENCH_1D_ARRAY_DECL(p, DATA_TYPE, NY, ny); POLYBENCH_1D_ARRAY_DECL(r, DATA_TYPE, NX, nx); + POLYBENCH_1D_ARRAY_DECL(s_StrictFP, DATA_TYPE, NY, ny); + POLYBENCH_1D_ARRAY_DECL(q_StrictFP, DATA_TYPE, NX, nx); /* Initialize array(s). */ init_array (nx, ny, @@ -124,9 +174,22 @@ polybench_stop_instruments; polybench_print_instruments; + kernel_bicg_StrictFP(nx, ny, + POLYBENCH_ARRAY(A), + POLYBENCH_ARRAY(s_StrictFP), + POLYBENCH_ARRAY(q_StrictFP), + POLYBENCH_ARRAY(p), + POLYBENCH_ARRAY(r)); + + if (!check_FP(ny, POLYBENCH_ARRAY(s), POLYBENCH_ARRAY(s_StrictFP))) + return 1; + if (!check_FP(ny, POLYBENCH_ARRAY(q), POLYBENCH_ARRAY(q_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(nx, ny, POLYBENCH_ARRAY(s), POLYBENCH_ARRAY(q))); + polybench_prevent_dce(print_array(nx, ny, POLYBENCH_ARRAY(s_StrictFP), + POLYBENCH_ARRAY(q_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(A); @@ -134,6 +197,8 @@ POLYBENCH_FREE_ARRAY(q); POLYBENCH_FREE_ARRAY(p); POLYBENCH_FREE_ARRAY(r); + POLYBENCH_FREE_ARRAY(s_StrictFP); + POLYBENCH_FREE_ARRAY(q_StrictFP); return 0; } Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/cholesky/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/cholesky/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/cholesky/CMakeLists.txt @@ -5,4 +5,5 @@ list(APPEND CFLAGS -DSMALL_DATASET) endif() set(HASH_PROGRAM_OUTPUT 1) +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/cholesky/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/cholesky/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/cholesky/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = cholesky -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 ifdef SMALL_PROBLEM_SIZE CFLAGS += -DSMALL_DATASET Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/cholesky/cholesky.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/cholesky/cholesky.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/cholesky/cholesky.c @@ -19,11 +19,13 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array(int n, DATA_TYPE POLYBENCH_1D(p,N,n), - DATA_TYPE POLYBENCH_2D(A,N,N,n,n)) + DATA_TYPE POLYBENCH_2D(A,N,N,n,n), + DATA_TYPE POLYBENCH_2D(A_StrictFP,N,N,n,n)) { +#pragma STDC FP_CONTRACT OFF int i, j; /* LLVM: This change ensures we do not calculate nan values, which are @@ -43,6 +45,12 @@ for (j = 0; j < n; j++) A[i][j] = j + n; } + for (i = 0; i < n; i++) + { + p[i] = i + n; + for (j = 0; j < n; j++) + A_StrictFP[i][j] = j + n; + } } @@ -102,6 +110,62 @@ } +__attribute__((optnone)) static +void kernel_cholesky_StrictFP(int n, + DATA_TYPE POLYBENCH_1D(p,N,n), + DATA_TYPE POLYBENCH_2D(A,N,N,n,n)) +{ +#pragma STDC FP_CONTRACT OFF + int i, j, k; + + DATA_TYPE x; + +for (i = 0; i < _PB_N; ++i) + { + /* + LLVM: This change ensures we do not calculate nan values, which are + formatted differently on different platforms and which may also + be optimized unexpectedly. + Original line: + x = A[i][i]; + */ + x = A[i][i] * n; + for (j = 0; j <= i - 1; ++j) + x = x - A[i][j] * A[i][j]; + p[i] = 1.0 / sqrt(x); + for (j = i + 1; j < _PB_N; ++j) + { + x = A[i][j]; + for (k = 0; k <= i - 1; ++k) + x = x - A[j][k] * A[i][k]; + A[j][i] = x * p[i]; + } + } +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static inline int +check_FP(int n, + DATA_TYPE POLYBENCH_2D(A,N,N,n,n), + DATA_TYPE POLYBENCH_2D(B,N,N,n,n)) { + int i, j; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_N; i++) + for (j = 0; j < _PB_N; j++) + { + double V1 = A[i][j]; + double V2 = B[i][j]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d][%d] = %lf and B[%d][%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, j, V1, i, j, V2, AbsTolerance); + return 0; + } + } + + return 1; +} int main(int argc, char** argv) { @@ -111,10 +175,12 @@ /* Variable declaration/allocation. */ POLYBENCH_2D_ARRAY_DECL(A, DATA_TYPE, N, N, n, n); POLYBENCH_1D_ARRAY_DECL(p, DATA_TYPE, N, n); + POLYBENCH_2D_ARRAY_DECL(A_StrictFP, DATA_TYPE, N, N, n, n); /* Initialize array(s). */ - init_array (n, POLYBENCH_ARRAY(p), POLYBENCH_ARRAY(A)); + init_array (n, POLYBENCH_ARRAY(p), POLYBENCH_ARRAY(A), + POLYBENCH_ARRAY(A_StrictFP)); /* Start timer. */ polybench_start_instruments; @@ -126,12 +192,17 @@ polybench_stop_instruments; polybench_print_instruments; + kernel_cholesky_StrictFP(n, POLYBENCH_ARRAY(p), POLYBENCH_ARRAY(A_StrictFP)); + if (!check_FP(n, POLYBENCH_ARRAY(A), POLYBENCH_ARRAY(A_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(A))); + polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(A_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(A); + POLYBENCH_FREE_ARRAY(A_StrictFP); POLYBENCH_FREE_ARRAY(p); return 0; Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/doitgen/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/doitgen/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/doitgen/CMakeLists.txt @@ -9,4 +9,5 @@ endif() endif() set(HASH_PROGRAM_OUTPUT 1) +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/doitgen/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/doitgen/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/doitgen/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = doitgen -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 ifdef SMALL_PROBLEM_SIZE CFLAGS += -DSMALL_DATASET Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/doitgen/doitgen.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/doitgen/doitgen.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/doitgen/doitgen.c @@ -19,17 +19,19 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array(int nr, int nq, int np, DATA_TYPE POLYBENCH_3D(A,NR,NQ,NP,nr,nq,np), + DATA_TYPE POLYBENCH_3D(A_StrictFP,NR,NQ,NP,nr,nq,np), DATA_TYPE POLYBENCH_2D(C4,NP,NP,np,np)) { +#pragma STDC FP_CONTRACT OFF int i, j, k; for (i = 0; i < nr; i++) for (j = 0; j < nq; j++) for (k = 0; k < np; k++) - A[i][j][k] = ((DATA_TYPE) i*j + k) / np; + A_StrictFP[i][j][k] = A[i][j][k] = ((DATA_TYPE) i*j + k) / np; for (i = 0; i < np; i++) for (j = 0; j < np; j++) C4[i][j] = ((DATA_TYPE) i*j) / np; @@ -80,6 +82,51 @@ } +__attribute__((optnone)) static +void kernel_doitgen_StrictFP(int nr, int nq, int np, + DATA_TYPE POLYBENCH_3D(A,NR,NQ,NP,nr,nq,np), + DATA_TYPE POLYBENCH_2D(C4,NP,NP,np,np), + DATA_TYPE POLYBENCH_3D(sum,NR,NQ,NP,nr,nq,np)) +{ +#pragma STDC FP_CONTRACT OFF + int r, q, p, s; + + for (r = 0; r < _PB_NR; r++) + for (q = 0; q < _PB_NQ; q++) { + for (p = 0; p < _PB_NP; p++) { + sum[r][q][p] = 0; + for (s = 0; s < _PB_NP; s++) + sum[r][q][p] = sum[r][q][p] + A[r][q][s] * C4[s][p]; + } + for (p = 0; p < _PB_NR; p++) + A[r][q][p] = sum[r][q][p]; + } +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static inline int +check_FP(int nr, int nq, int np, + DATA_TYPE POLYBENCH_3D(A,NR,NQ,NP,nr,nq,np), + DATA_TYPE POLYBENCH_3D(B,NR,NQ,NP,nr,nq,np)) { + double AbsTolerance = FP_ABSTOLERANCE; + int r, q, p, s; + + for (r = 0; r < _PB_NR; r++) + for (q = 0; q < _PB_NQ; q++) + for (p = 0; p < _PB_NP; p++) { + double V1 = A[r][q][p]; + double V2 = B[r][q][p]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d][%d][%d] = %lf and B[%d][%d][%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", r, q, p, V1, r, q, p, V2, AbsTolerance); + return 0; + } + } + + return 1; +} int main(int argc, char** argv) { @@ -90,12 +137,14 @@ /* Variable declaration/allocation. */ POLYBENCH_3D_ARRAY_DECL(A,DATA_TYPE,NR,NQ,NP,nr,nq,np); + POLYBENCH_3D_ARRAY_DECL(A_StrictFP,DATA_TYPE,NR,NQ,NP,nr,nq,np); POLYBENCH_3D_ARRAY_DECL(sum,DATA_TYPE,NR,NQ,NP,nr,nq,np); POLYBENCH_2D_ARRAY_DECL(C4,DATA_TYPE,NP,NP,np,np); /* Initialize array(s). */ init_array (nr, nq, np, POLYBENCH_ARRAY(A), + POLYBENCH_ARRAY(A_StrictFP), POLYBENCH_ARRAY(C4)); /* Start timer. */ @@ -111,12 +160,21 @@ polybench_stop_instruments; polybench_print_instruments; + kernel_doitgen_StrictFP(nr, nq, np, + POLYBENCH_ARRAY(A_StrictFP), + POLYBENCH_ARRAY(C4), + POLYBENCH_ARRAY(sum)); + + if (!check_FP(nr, nq, np, POLYBENCH_ARRAY(A), POLYBENCH_ARRAY(A_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(nr, nq, np, POLYBENCH_ARRAY(A))); + polybench_prevent_dce(print_array(nr, nq, np, POLYBENCH_ARRAY(A_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(A); + POLYBENCH_FREE_ARRAY(A_StrictFP); POLYBENCH_FREE_ARRAY(sum); POLYBENCH_FREE_ARRAY(C4); Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gemm/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gemm/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gemm/CMakeLists.txt @@ -5,4 +5,5 @@ list(APPEND CFLAGS -DSMALL_DATASET) endif() set(HASH_PROGRAM_OUTPUT 1) +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gemm/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gemm/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gemm/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = gemm -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 ifdef SMALL_PROBLEM_SIZE CFLAGS += -DSMALL_DATASET Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gemm/gemm.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gemm/gemm.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gemm/gemm.c @@ -19,21 +19,23 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array(int ni, int nj, int nk, DATA_TYPE *alpha, DATA_TYPE *beta, DATA_TYPE POLYBENCH_2D(C,NI,NJ,ni,nj), + DATA_TYPE POLYBENCH_2D(C_StrictFP,NI,NJ,ni,nj), DATA_TYPE POLYBENCH_2D(A,NI,NK,ni,nk), DATA_TYPE POLYBENCH_2D(B,NK,NJ,nk,nj)) { +#pragma STDC FP_CONTRACT OFF int i, j; *alpha = 32412; *beta = 2123; for (i = 0; i < ni; i++) for (j = 0; j < nj; j++) - C[i][j] = ((DATA_TYPE) i*j) / ni; + C_StrictFP[i][j] = C[i][j] = ((DATA_TYPE) i*j) / ni; for (i = 0; i < ni; i++) for (j = 0; j < nk; j++) A[i][j] = ((DATA_TYPE) i*j) / ni; @@ -86,6 +88,51 @@ } +__attribute__((optnone)) static +void kernel_gemm_StrictFP(int ni, int nj, int nk, + DATA_TYPE alpha, + DATA_TYPE beta, + DATA_TYPE POLYBENCH_2D(C,NI,NJ,ni,nj), + DATA_TYPE POLYBENCH_2D(A,NI,NK,ni,nk), + DATA_TYPE POLYBENCH_2D(B,NK,NJ,nk,nj)) +{ +#pragma STDC FP_CONTRACT OFF + int i, j, k; + + /* C := alpha*A*B + beta*C */ + for (i = 0; i < _PB_NI; i++) + for (j = 0; j < _PB_NJ; j++) + { + C[i][j] *= beta; + for (k = 0; k < _PB_NK; ++k) + C[i][j] += alpha * A[i][k] * B[k][j]; + } +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static inline int +check_FP(int ni, int nk, + DATA_TYPE POLYBENCH_2D(A,NI,NK,ni,nk), + DATA_TYPE POLYBENCH_2D(B,NI,NK,ni,nk)) { + int i, j; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_NI; i++) + for (j = 0; j < _PB_NK; j++) + { + double V1 = A[i][j]; + double V2 = B[i][j]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d][%d] = %lf and B[%d][%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, j, V1, i, j, V2, AbsTolerance); + return 0; + } + } + + /* All elements are within the allowed FP_ABSTOLERANCE error margin. */ + return 1; +} int main(int argc, char** argv) { @@ -98,12 +145,14 @@ DATA_TYPE alpha; DATA_TYPE beta; POLYBENCH_2D_ARRAY_DECL(C,DATA_TYPE,NI,NJ,ni,nj); + POLYBENCH_2D_ARRAY_DECL(C_StrictFP,DATA_TYPE,NI,NJ,ni,nj); POLYBENCH_2D_ARRAY_DECL(A,DATA_TYPE,NI,NK,ni,nk); POLYBENCH_2D_ARRAY_DECL(B,DATA_TYPE,NK,NJ,nk,nj); /* Initialize array(s). */ init_array (ni, nj, nk, &alpha, &beta, POLYBENCH_ARRAY(C), + POLYBENCH_ARRAY(C_StrictFP), POLYBENCH_ARRAY(A), POLYBENCH_ARRAY(B)); @@ -121,12 +170,21 @@ polybench_stop_instruments; polybench_print_instruments; + kernel_gemm_StrictFP(ni, nj, nk, + alpha, beta, + POLYBENCH_ARRAY(C_StrictFP), + POLYBENCH_ARRAY(A), + POLYBENCH_ARRAY(B)); + if (!check_FP(ni, nk, POLYBENCH_ARRAY(C), POLYBENCH_ARRAY(C_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(ni, nj, POLYBENCH_ARRAY(C))); + polybench_prevent_dce(print_array(ni, nj, POLYBENCH_ARRAY(C_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(C); + POLYBENCH_FREE_ARRAY(C_StrictFP); POLYBENCH_FREE_ARRAY(A); POLYBENCH_FREE_ARRAY(B); Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gemver/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gemver/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gemver/CMakeLists.txt @@ -5,4 +5,5 @@ if(ARCH STREQUAL "XCore") set(XCORE_TARGET_NEEDS_MEMORY 128) endif() +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gemver/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gemver/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gemver/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = gemver -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 HASH_PROGRAM_OUTPUT = 1 Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gemver/gemver.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gemver/gemver.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gemver/gemver.c @@ -19,7 +19,7 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array (int n, DATA_TYPE *alpha, DATA_TYPE *beta, @@ -29,10 +29,11 @@ DATA_TYPE POLYBENCH_1D(u2,N,n), DATA_TYPE POLYBENCH_1D(v2,N,n), DATA_TYPE POLYBENCH_1D(w,N,n), - DATA_TYPE POLYBENCH_1D(x,N,n), + DATA_TYPE POLYBENCH_1D(w_StrictFP,N,n), DATA_TYPE POLYBENCH_1D(y,N,n), DATA_TYPE POLYBENCH_1D(z,N,n)) { +#pragma STDC FP_CONTRACT OFF int i, j; *alpha = 43532; @@ -46,8 +47,7 @@ v2[i] = (i+1)/n/6.0; y[i] = (i+1)/n/8.0; z[i] = (i+1)/n/9.0; - x[i] = 0.0; - w[i] = 0.0; + w_StrictFP[i] = w[i] = 0.0; for (j = 0; j < n; j++) A[i][j] = ((DATA_TYPE) i*j) / n; } @@ -75,6 +75,7 @@ DATA_TYPE alpha, DATA_TYPE beta, DATA_TYPE POLYBENCH_2D(A,N,N,n,n), + DATA_TYPE POLYBENCH_2D(A_tmp,N,N,n,n), DATA_TYPE POLYBENCH_1D(u1,N,n), DATA_TYPE POLYBENCH_1D(v1,N,n), DATA_TYPE POLYBENCH_1D(u2,N,n), @@ -90,22 +91,82 @@ for (i = 0; i < _PB_N; i++) for (j = 0; j < _PB_N; j++) - A[i][j] = A[i][j] + u1[i] * v1[j] + u2[i] * v2[j]; + A_tmp[i][j] = A[i][j] + u1[i] * v1[j] + u2[i] * v2[j]; - for (i = 0; i < _PB_N; i++) + for (i = 0; i < _PB_N; i++) { + x[i] = 0.0; for (j = 0; j < _PB_N; j++) - x[i] = x[i] + beta * A[j][i] * y[j]; + x[i] = x[i] + beta * A_tmp[j][i] * y[j]; + } for (i = 0; i < _PB_N; i++) x[i] = x[i] + z[i]; for (i = 0; i < _PB_N; i++) for (j = 0; j < _PB_N; j++) - w[i] = w[i] + alpha * A[i][j] * x[j]; + w[i] = w[i] + alpha * A_tmp[i][j] * x[j]; #pragma endscop } +__attribute__((optnone)) static +void kernel_gemver_StrictFP(int n, + DATA_TYPE alpha, + DATA_TYPE beta, + DATA_TYPE POLYBENCH_2D(A,N,N,n,n), + DATA_TYPE POLYBENCH_2D(A_tmp,N,N,n,n), + DATA_TYPE POLYBENCH_1D(u1,N,n), + DATA_TYPE POLYBENCH_1D(v1,N,n), + DATA_TYPE POLYBENCH_1D(u2,N,n), + DATA_TYPE POLYBENCH_1D(v2,N,n), + DATA_TYPE POLYBENCH_1D(w,N,n), + DATA_TYPE POLYBENCH_1D(x,N,n), + DATA_TYPE POLYBENCH_1D(y,N,n), + DATA_TYPE POLYBENCH_1D(z,N,n)) +{ +#pragma STDC FP_CONTRACT OFF + int i, j; + + for (i = 0; i < _PB_N; i++) + for (j = 0; j < _PB_N; j++) + A_tmp[i][j] = A[i][j] + u1[i] * v1[j] + u2[i] * v2[j]; + + for (i = 0; i < _PB_N; i++) { + x[i] = 0.0; + for (j = 0; j < _PB_N; j++) + x[i] = x[i] + beta * A_tmp[j][i] * y[j]; + } + + for (i = 0; i < _PB_N; i++) + x[i] = x[i] + z[i]; + + for (i = 0; i < _PB_N; i++) + for (j = 0; j < _PB_N; j++) + w[i] = w[i] + alpha * A_tmp[i][j] * x[j]; +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static int +check_FP(int n, + DATA_TYPE POLYBENCH_1D(A,N,n), + DATA_TYPE POLYBENCH_1D(B,N,n)) { + int i; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_N; i++) + { + double V1 = A[i]; + double V2 = B[i]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d] = %lf and B[%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, V1, i, V2, AbsTolerance); + return 0; + } + } + + return 1; +} int main(int argc, char** argv) { @@ -116,11 +177,13 @@ DATA_TYPE alpha; DATA_TYPE beta; POLYBENCH_2D_ARRAY_DECL(A, DATA_TYPE, N, N, n, n); + POLYBENCH_2D_ARRAY_DECL(A_tmp, DATA_TYPE, N, N, n, n); POLYBENCH_1D_ARRAY_DECL(u1, DATA_TYPE, N, n); POLYBENCH_1D_ARRAY_DECL(v1, DATA_TYPE, N, n); POLYBENCH_1D_ARRAY_DECL(u2, DATA_TYPE, N, n); POLYBENCH_1D_ARRAY_DECL(v2, DATA_TYPE, N, n); POLYBENCH_1D_ARRAY_DECL(w, DATA_TYPE, N, n); + POLYBENCH_1D_ARRAY_DECL(w_StrictFP, DATA_TYPE, N, n); POLYBENCH_1D_ARRAY_DECL(x, DATA_TYPE, N, n); POLYBENCH_1D_ARRAY_DECL(y, DATA_TYPE, N, n); POLYBENCH_1D_ARRAY_DECL(z, DATA_TYPE, N, n); @@ -134,7 +197,7 @@ POLYBENCH_ARRAY(u2), POLYBENCH_ARRAY(v2), POLYBENCH_ARRAY(w), - POLYBENCH_ARRAY(x), + POLYBENCH_ARRAY(w_StrictFP), POLYBENCH_ARRAY(y), POLYBENCH_ARRAY(z)); @@ -144,6 +207,7 @@ /* Run kernel. */ kernel_gemver (n, alpha, beta, POLYBENCH_ARRAY(A), + POLYBENCH_ARRAY(A_tmp), POLYBENCH_ARRAY(u1), POLYBENCH_ARRAY(v1), POLYBENCH_ARRAY(u2), @@ -157,17 +221,33 @@ polybench_stop_instruments; polybench_print_instruments; + kernel_gemver_StrictFP(n, alpha, beta, + POLYBENCH_ARRAY(A), + POLYBENCH_ARRAY(A_tmp), + POLYBENCH_ARRAY(u1), + POLYBENCH_ARRAY(v1), + POLYBENCH_ARRAY(u2), + POLYBENCH_ARRAY(v2), + POLYBENCH_ARRAY(w_StrictFP), + POLYBENCH_ARRAY(x), + POLYBENCH_ARRAY(y), + POLYBENCH_ARRAY(z)); + if (!check_FP(n, POLYBENCH_ARRAY(w), POLYBENCH_ARRAY(w_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(w))); + polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(w_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(A); + POLYBENCH_FREE_ARRAY(A_tmp); POLYBENCH_FREE_ARRAY(u1); POLYBENCH_FREE_ARRAY(v1); POLYBENCH_FREE_ARRAY(u2); POLYBENCH_FREE_ARRAY(v2); POLYBENCH_FREE_ARRAY(w); + POLYBENCH_FREE_ARRAY(w_StrictFP); POLYBENCH_FREE_ARRAY(x); POLYBENCH_FREE_ARRAY(y); POLYBENCH_FREE_ARRAY(z); Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gesummv/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gesummv/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gesummv/CMakeLists.txt @@ -9,4 +9,5 @@ endif() endif() set(HASH_PROGRAM_OUTPUT 1) +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gesummv/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gesummv/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gesummv/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = gesummv -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 ifdef SMALL_PROBLEM_SIZE CFLAGS += -DSMALL_DATASET Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gesummv/gesummv.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gesummv/gesummv.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/gesummv/gesummv.c @@ -19,7 +19,7 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array(int n, DATA_TYPE *alpha, DATA_TYPE *beta, @@ -27,6 +27,7 @@ DATA_TYPE POLYBENCH_2D(B,N,N,n,n), DATA_TYPE POLYBENCH_1D(x,N,n)) { +#pragma STDC FP_CONTRACT OFF int i, j; *alpha = 43532; @@ -89,6 +90,54 @@ } +__attribute__((optnone)) static +void kernel_gesummv_StrictFP(int n, + DATA_TYPE alpha, + DATA_TYPE beta, + DATA_TYPE POLYBENCH_2D(A,N,N,n,n), + DATA_TYPE POLYBENCH_2D(B,N,N,n,n), + DATA_TYPE POLYBENCH_1D(tmp,N,n), + DATA_TYPE POLYBENCH_1D(x,N,n), + DATA_TYPE POLYBENCH_1D(y,N,n)) +{ +#pragma STDC FP_CONTRACT OFF + int i, j; + + for (i = 0; i < _PB_N; i++) + { + tmp[i] = 0; + y[i] = 0; + for (j = 0; j < _PB_N; j++) + { + tmp[i] = A[i][j] * x[j] + tmp[i]; + y[i] = B[i][j] * x[j] + y[i]; + } + y[i] = alpha * tmp[i] + beta * y[i]; + } +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static int +check_FP(int n, + DATA_TYPE POLYBENCH_1D(A,N,n), + DATA_TYPE POLYBENCH_1D(B,N,n)) { + int i; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_N; i++) + { + double V1 = A[i]; + double V2 = B[i]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d] = %lf and B[%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, V1, i, V2, AbsTolerance); + return 0; + } + } + + return 1; +} int main(int argc, char** argv) { @@ -103,6 +152,7 @@ POLYBENCH_1D_ARRAY_DECL(tmp, DATA_TYPE, N, n); POLYBENCH_1D_ARRAY_DECL(x, DATA_TYPE, N, n); POLYBENCH_1D_ARRAY_DECL(y, DATA_TYPE, N, n); + POLYBENCH_1D_ARRAY_DECL(y_StrictFP, DATA_TYPE, N, n); /* Initialize array(s). */ @@ -126,9 +176,18 @@ polybench_stop_instruments; polybench_print_instruments; + kernel_gesummv_StrictFP(n, alpha, beta, + POLYBENCH_ARRAY(A), + POLYBENCH_ARRAY(B), + POLYBENCH_ARRAY(tmp), + POLYBENCH_ARRAY(x), + POLYBENCH_ARRAY(y_StrictFP)); + if (!check_FP(n, POLYBENCH_ARRAY(y), POLYBENCH_ARRAY(y_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(y))); + polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(y_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(A); Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/mvt/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/mvt/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/mvt/CMakeLists.txt @@ -5,4 +5,5 @@ if(ARCH STREQUAL "XCore") set(XCORE_TARGET_NEEDS_MEMORY 128) endif() +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/mvt/mvt.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/mvt/mvt.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/mvt/mvt.c @@ -19,20 +19,23 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array(int n, DATA_TYPE POLYBENCH_1D(x1,N,n), DATA_TYPE POLYBENCH_1D(x2,N,n), + DATA_TYPE POLYBENCH_1D(x1_StrictFP,N,n), + DATA_TYPE POLYBENCH_1D(x2_StrictFP,N,n), DATA_TYPE POLYBENCH_1D(y_1,N,n), DATA_TYPE POLYBENCH_1D(y_2,N,n), DATA_TYPE POLYBENCH_2D(A,N,N,n,n)) { +#pragma STDC FP_CONTRACT OFF int i, j; for (i = 0; i < n; i++) { - x1[i] = ((DATA_TYPE) i) / n; - x2[i] = ((DATA_TYPE) i + 1) / n; + x1_StrictFP[i] = x1[i] = ((DATA_TYPE) i) / n; + x2_StrictFP[i] = x2[i] = ((DATA_TYPE) i + 1) / n; y_1[i] = ((DATA_TYPE) i + 3) / n; y_2[i] = ((DATA_TYPE) i + 4) / n; for (j = 0; j < n; j++) @@ -85,6 +88,47 @@ } +__attribute__((optnone)) static +void kernel_mvt_StrictFP(int n, + DATA_TYPE POLYBENCH_1D(x1,N,n), + DATA_TYPE POLYBENCH_1D(x2,N,n), + DATA_TYPE POLYBENCH_1D(y_1,N,n), + DATA_TYPE POLYBENCH_1D(y_2,N,n), + DATA_TYPE POLYBENCH_2D(A,N,N,n,n)) +{ +#pragma STDC FP_CONTRACT OFF + int i, j; + + for (i = 0; i < _PB_N; i++) + for (j = 0; j < _PB_N; j++) + x1[i] = x1[i] + A[i][j] * y_1[j]; + for (i = 0; i < _PB_N; i++) + for (j = 0; j < _PB_N; j++) + x2[i] = x2[i] + A[j][i] * y_2[j]; +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static int +check_FP(int n, + DATA_TYPE POLYBENCH_1D(A,N,n), + DATA_TYPE POLYBENCH_1D(B,N,n)) { + int i; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_N; i++) + { + double V1 = A[i]; + double V2 = B[i]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d] = %lf and B[%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, V1, i, V2, AbsTolerance); + return 0; + } + } + + return 1; +} int main(int argc, char** argv) { @@ -95,6 +139,8 @@ POLYBENCH_2D_ARRAY_DECL(A, DATA_TYPE, N, N, n, n); POLYBENCH_1D_ARRAY_DECL(x1, DATA_TYPE, N, n); POLYBENCH_1D_ARRAY_DECL(x2, DATA_TYPE, N, n); + POLYBENCH_1D_ARRAY_DECL(x1_StrictFP, DATA_TYPE, N, n); + POLYBENCH_1D_ARRAY_DECL(x2_StrictFP, DATA_TYPE, N, n); POLYBENCH_1D_ARRAY_DECL(y_1, DATA_TYPE, N, n); POLYBENCH_1D_ARRAY_DECL(y_2, DATA_TYPE, N, n); @@ -103,6 +149,8 @@ init_array (n, POLYBENCH_ARRAY(x1), POLYBENCH_ARRAY(x2), + POLYBENCH_ARRAY(x1_StrictFP), + POLYBENCH_ARRAY(x2_StrictFP), POLYBENCH_ARRAY(y_1), POLYBENCH_ARRAY(y_2), POLYBENCH_ARRAY(A)); @@ -122,14 +170,28 @@ polybench_stop_instruments; polybench_print_instruments; + kernel_mvt_StrictFP(n, + POLYBENCH_ARRAY(x1_StrictFP), + POLYBENCH_ARRAY(x2_StrictFP), + POLYBENCH_ARRAY(y_1), + POLYBENCH_ARRAY(y_2), + POLYBENCH_ARRAY(A)); + + if (!check_FP(n, POLYBENCH_ARRAY(x1), POLYBENCH_ARRAY(x1_StrictFP))) + return 1; + if (!check_FP(n, POLYBENCH_ARRAY(x2), POLYBENCH_ARRAY(x2_StrictFP))) + return 1; /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(x1), POLYBENCH_ARRAY(x2))); + polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(x1_StrictFP), + POLYBENCH_ARRAY(x2_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(A); POLYBENCH_FREE_ARRAY(x1); POLYBENCH_FREE_ARRAY(x2); + POLYBENCH_FREE_ARRAY(x1_StrictFP); + POLYBENCH_FREE_ARRAY(x2_StrictFP); POLYBENCH_FREE_ARRAY(y_1); POLYBENCH_FREE_ARRAY(y_2); Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/symm/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/symm/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/symm/CMakeLists.txt @@ -8,4 +8,5 @@ list(APPEND CFLAGS -DSMALL_DATASET) endif() set(HASH_PROGRAM_OUTPUT 1) +add_definitions(-DFP_ABSTOLERANCE=10) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/symm/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/symm/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/symm/Makefile @@ -2,7 +2,8 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = symm -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=10 + ifeq ($(ARCH),Mips) RUNTIMELIMIT := 2000 Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/symm/symm.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/symm/symm.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/symm/symm.c @@ -19,21 +19,23 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array(int ni, int nj, DATA_TYPE *alpha, DATA_TYPE *beta, DATA_TYPE POLYBENCH_2D(C,NI,NJ,ni,nj), + DATA_TYPE POLYBENCH_2D(C_StrictFP,NI,NJ,ni,nj), DATA_TYPE POLYBENCH_2D(A,NJ,NJ,nj,nj), DATA_TYPE POLYBENCH_2D(B,NI,NJ,ni,nj)) { +#pragma STDC FP_CONTRACT OFF int i, j; *alpha = 32412; *beta = 2123; for (i = 0; i < ni; i++) for (j = 0; j < nj; j++) { - C[i][j] = ((DATA_TYPE) i*j) / ni; + C_StrictFP[i][j] = C[i][j] = ((DATA_TYPE) i*j) / ni; B[i][j] = ((DATA_TYPE) i*j) / ni; } for (i = 0; i < nj; i++) @@ -90,6 +92,56 @@ } +__attribute__((optnone)) static +void kernel_symm_StrictFP(int ni, int nj, + DATA_TYPE alpha, + DATA_TYPE beta, + DATA_TYPE POLYBENCH_2D(C,NI,NJ,ni,nj), + DATA_TYPE POLYBENCH_2D(A,NJ,NJ,nj,nj), + DATA_TYPE POLYBENCH_2D(B,NI,NJ,ni,nj)) +{ +#pragma STDC FP_CONTRACT OFF + int i, j, k; + DATA_TYPE acc; + + /* C := alpha*A*B + beta*C, A is symetric */ + for (i = 0; i < _PB_NI; i++) + for (j = 0; j < _PB_NJ; j++) + { + acc = 0; + for (k = 0; k < j - 1; k++) + { + C[k][j] += alpha * A[k][i] * B[i][j]; + acc += B[k][j] * A[k][i]; + } + C[i][j] = beta * C[i][j] + alpha * A[i][i] * B[i][j] + alpha * acc; + } +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static inline int +check_FP(int ni, int nj, + DATA_TYPE POLYBENCH_2D(A,NI,NJ,ni,nj), + DATA_TYPE POLYBENCH_2D(B,NI,NJ,ni,nj)) { + int i, j; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_NI; i++) + for (j = 0; j < _PB_NJ; j++) + { + double V1 = A[i][j]; + double V2 = B[i][j]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d][%d] = %lf and B[%d][%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, j, V1, i, j, V2, AbsTolerance); + return 0; + } + } + + /* All elements are within the allowed FP_ABSTOLERANCE error margin. */ + return 1; +} int main(int argc, char** argv) { @@ -101,12 +153,14 @@ DATA_TYPE alpha; DATA_TYPE beta; POLYBENCH_2D_ARRAY_DECL(C,DATA_TYPE,NI,NJ,ni,nj); + POLYBENCH_2D_ARRAY_DECL(C_StrictFP,DATA_TYPE,NI,NJ,ni,nj); POLYBENCH_2D_ARRAY_DECL(A,DATA_TYPE,NJ,NJ,nj,nj); POLYBENCH_2D_ARRAY_DECL(B,DATA_TYPE,NI,NJ,ni,nj); /* Initialize array(s). */ init_array (ni, nj, &alpha, &beta, POLYBENCH_ARRAY(C), + POLYBENCH_ARRAY(C_StrictFP), POLYBENCH_ARRAY(A), POLYBENCH_ARRAY(B)); @@ -124,9 +178,17 @@ polybench_stop_instruments; polybench_print_instruments; + kernel_symm_StrictFP(ni, nj, + alpha, beta, + POLYBENCH_ARRAY(C_StrictFP), + POLYBENCH_ARRAY(A), + POLYBENCH_ARRAY(B)); + if (!check_FP(ni, nj, POLYBENCH_ARRAY(C), POLYBENCH_ARRAY(C_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(ni, nj, POLYBENCH_ARRAY(C))); + polybench_prevent_dce(print_array(ni, nj, POLYBENCH_ARRAY(C_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(C); Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/syr2k/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/syr2k/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/syr2k/CMakeLists.txt @@ -5,4 +5,5 @@ list(APPEND CFLAGS -DSMALL_DATASET) endif() set(HASH_PROGRAM_OUTPUT 1) +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/syr2k/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/syr2k/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/syr2k/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = syr2k -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 ifdef SMALL_PROBLEM_SIZE CFLAGS += -DSMALL_DATASET Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/syr2k/syr2k.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/syr2k/syr2k.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/syr2k/syr2k.c @@ -19,14 +19,16 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array(int ni, int nj, DATA_TYPE *alpha, DATA_TYPE *beta, DATA_TYPE POLYBENCH_2D(C,NI,NI,ni,ni), + DATA_TYPE POLYBENCH_2D(C_StrictFP,NI,NI,ni,ni), DATA_TYPE POLYBENCH_2D(A,NI,NJ,ni,nj), DATA_TYPE POLYBENCH_2D(B,NI,NJ,ni,nj)) { +#pragma STDC FP_CONTRACT OFF int i, j; *alpha = 32412; @@ -38,7 +40,7 @@ } for (i = 0; i < ni; i++) for (j = 0; j < ni; j++) - C[i][j] = ((DATA_TYPE) i*j) / ni; + C_StrictFP[i][j] = C[i][j] = ((DATA_TYPE) i*j) / ni; } @@ -88,6 +90,54 @@ } +__attribute__((optnone)) static void +kernel_syr2k_StrictFP(int ni, int nj, + DATA_TYPE alpha, + DATA_TYPE beta, + DATA_TYPE POLYBENCH_2D(C,NI,NI,ni,ni), + DATA_TYPE POLYBENCH_2D(A,NI,NJ,ni,nj), + DATA_TYPE POLYBENCH_2D(B,NI,NJ,ni,nj)) +{ +#pragma STDC FP_CONTRACT OFF + int i, j, k; + + /* C := alpha*A*B' + alpha*B*A' + beta*C */ + for (i = 0; i < _PB_NI; i++) + for (j = 0; j < _PB_NI; j++) + C[i][j] *= beta; + for (i = 0; i < _PB_NI; i++) + for (j = 0; j < _PB_NI; j++) + for (k = 0; k < _PB_NJ; k++) + { + C[i][j] += alpha * A[i][k] * B[j][k]; + C[i][j] += alpha * B[i][k] * A[j][k]; + } +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static inline int +check_FP(int ni, + DATA_TYPE POLYBENCH_2D(A,NI,NI,ni,ni), + DATA_TYPE POLYBENCH_2D(B,NI,NI,ni,ni)) { + int i, j; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_NI; i++) + for (j = 0; j < _PB_NI; j++) + { + double V1 = A[i][j]; + double V2 = B[i][j]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d][%d] = %lf and B[%d][%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, j, V1, i, j, V2, AbsTolerance); + return 0; + } + } + + /* All elements are within the allowed FP_ABSTOLERANCE error margin. */ + return 1; +} int main(int argc, char** argv) { @@ -99,12 +149,14 @@ DATA_TYPE alpha; DATA_TYPE beta; POLYBENCH_2D_ARRAY_DECL(C,DATA_TYPE,NI,NI,ni,ni); + POLYBENCH_2D_ARRAY_DECL(C_StrictFP,DATA_TYPE,NI,NI,ni,ni); POLYBENCH_2D_ARRAY_DECL(A,DATA_TYPE,NI,NJ,ni,nj); POLYBENCH_2D_ARRAY_DECL(B,DATA_TYPE,NI,NJ,ni,nj); /* Initialize array(s). */ init_array (ni, nj, &alpha, &beta, POLYBENCH_ARRAY(C), + POLYBENCH_ARRAY(C_StrictFP), POLYBENCH_ARRAY(A), POLYBENCH_ARRAY(B)); @@ -122,12 +174,22 @@ polybench_stop_instruments; polybench_print_instruments; + kernel_syr2k_StrictFP(ni, nj, + alpha, beta, + POLYBENCH_ARRAY(C_StrictFP), + POLYBENCH_ARRAY(A), + POLYBENCH_ARRAY(B)); + + if (!check_FP(ni, POLYBENCH_ARRAY(C), POLYBENCH_ARRAY(C_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(ni, POLYBENCH_ARRAY(C))); + polybench_prevent_dce(print_array(ni, POLYBENCH_ARRAY(C_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(C); + POLYBENCH_FREE_ARRAY(C_StrictFP); POLYBENCH_FREE_ARRAY(A); POLYBENCH_FREE_ARRAY(B); Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/syrk/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/syrk/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/syrk/CMakeLists.txt @@ -5,4 +5,5 @@ list(APPEND CFLAGS -DSMALL_DATASET) endif() set(HASH_PROGRAM_OUTPUT 1) +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/syrk/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/syrk/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/syrk/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = syrk -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 ifdef SMALL_PROBLEM_SIZE CFLAGS += -DSMALL_DATASET Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/syrk/syrk.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/syrk/syrk.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/syrk/syrk.c @@ -19,13 +19,15 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array(int ni, int nj, DATA_TYPE *alpha, DATA_TYPE *beta, DATA_TYPE POLYBENCH_2D(C,NI,NI,ni,ni), + DATA_TYPE POLYBENCH_2D(C_StrictFP,NI,NI,ni,ni), DATA_TYPE POLYBENCH_2D(A,NI,NJ,ni,nj)) { +#pragma STDC FP_CONTRACT OFF int i, j; *alpha = 32412; @@ -35,7 +37,7 @@ A[i][j] = ((DATA_TYPE) i*j) / ni; for (i = 0; i < ni; i++) for (j = 0; j < ni; j++) - C[i][j] = ((DATA_TYPE) i*j) / ni; + C_StrictFP[i][j] = C[i][j] = ((DATA_TYPE) i*j) / ni; } @@ -81,6 +83,50 @@ } +__attribute__((optnone)) static +void kernel_syrk_StrictFP(int ni, int nj, + DATA_TYPE alpha, + DATA_TYPE beta, + DATA_TYPE POLYBENCH_2D(C,NI,NI,ni,ni), + DATA_TYPE POLYBENCH_2D(A,NI,NJ,ni,nj)) +{ +#pragma STDC FP_CONTRACT OFF + int i, j, k; + + /* C := alpha*A*A' + beta*C */ + for (i = 0; i < _PB_NI; i++) + for (j = 0; j < _PB_NI; j++) + C[i][j] *= beta; + for (i = 0; i < _PB_NI; i++) + for (j = 0; j < _PB_NI; j++) + for (k = 0; k < _PB_NJ; k++) + C[i][j] += alpha * A[i][k] * A[j][k]; +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static inline int +check_FP(int ni, + DATA_TYPE POLYBENCH_2D(A,NI,NI,ni,ni), + DATA_TYPE POLYBENCH_2D(B,NI,NI,ni,ni)) { + int i, j; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_NI; i++) + for (j = 0; j < _PB_NI; j++) + { + double V1 = A[i][j]; + double V2 = B[i][j]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d][%d] = %lf and B[%d][%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, j, V1, i, j, V2, AbsTolerance); + return 0; + } + } + + /* All elements are within the allowed FP_ABSTOLERANCE error margin. */ + return 1; +} int main(int argc, char** argv) { @@ -92,10 +138,12 @@ DATA_TYPE alpha; DATA_TYPE beta; POLYBENCH_2D_ARRAY_DECL(C,DATA_TYPE,NI,NI,ni,ni); + POLYBENCH_2D_ARRAY_DECL(C_StrictFP,DATA_TYPE,NI,NI,ni,ni); POLYBENCH_2D_ARRAY_DECL(A,DATA_TYPE,NI,NJ,ni,nj); /* Initialize array(s). */ - init_array (ni, nj, &alpha, &beta, POLYBENCH_ARRAY(C), POLYBENCH_ARRAY(A)); + init_array (ni, nj, &alpha, &beta, POLYBENCH_ARRAY(C), + POLYBENCH_ARRAY(C_StrictFP), POLYBENCH_ARRAY(A)); /* Start timer. */ polybench_start_instruments; @@ -107,12 +155,19 @@ polybench_stop_instruments; polybench_print_instruments; + kernel_syrk_StrictFP(ni, nj, alpha, beta, POLYBENCH_ARRAY(C_StrictFP), + POLYBENCH_ARRAY(A)); + + if (!check_FP(ni, POLYBENCH_ARRAY(C), POLYBENCH_ARRAY(C_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(ni, POLYBENCH_ARRAY(C))); + polybench_prevent_dce(print_array(ni, POLYBENCH_ARRAY(C_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(C); + POLYBENCH_FREE_ARRAY(C_StrictFP); POLYBENCH_FREE_ARRAY(A); return 0; Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/trisolv/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/trisolv/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/trisolv/CMakeLists.txt @@ -5,4 +5,5 @@ if(ARCH STREQUAL "XCore") set(XCORE_TARGET_NEEDS_MEMORY 128) endif() +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/trisolv/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/trisolv/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/trisolv/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = trisolv -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 HASH_PROGRAM_OUTPUT = 1 Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/trisolv/trisolv.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/trisolv/trisolv.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/trisolv/trisolv.c @@ -19,12 +19,14 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array(int n, DATA_TYPE POLYBENCH_2D(A,N,N,n,n), DATA_TYPE POLYBENCH_1D(x,N,n), + DATA_TYPE POLYBENCH_1D(x_StrictFP,N,n), DATA_TYPE POLYBENCH_1D(c,N,n)) { +#pragma STDC FP_CONTRACT OFF int i, j; /* LLVM: This change ensures we do not calculate nan values, which are @@ -40,7 +42,7 @@ */ for (i = 0; i < n; i++) { - c[i] = x[i] = ((DATA_TYPE) i+n) / n; + c[i] = x_StrictFP[i] = x[i] = ((DATA_TYPE) i+n) / n; for (j = 0; j < n; j++) A[i][j] = ((DATA_TYPE) i*j+n) / n; } @@ -86,6 +88,46 @@ } +__attribute__((optnone)) static void +kernel_trisolv_StrictFP(int n, + DATA_TYPE POLYBENCH_2D(A,N,N,n,n), + DATA_TYPE POLYBENCH_1D(x,N,n), + DATA_TYPE POLYBENCH_1D(c,N,n)) +{ +#pragma STDC FP_CONTRACT OFF + int i, j; + + for (i = 0; i < _PB_N; i++) + { + x[i] = c[i]; + for (j = 0; j <= i - 1; j++) + x[i] = x[i] - A[i][j] * x[j]; + x[i] = x[i] / A[i][i]; + } +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static int +check_FP(int n, + DATA_TYPE POLYBENCH_1D(A,N,n), + DATA_TYPE POLYBENCH_1D(B,N,n)) { + int i; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_N; i++) + { + double V1 = A[i]; + double V2 = B[i]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d] = %lf and B[%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, V1, i, V2, AbsTolerance); + return 0; + } + } + + return 1; +} int main(int argc, char** argv) { @@ -95,11 +137,13 @@ /* Variable declaration/allocation. */ POLYBENCH_2D_ARRAY_DECL(A, DATA_TYPE, N, N, n, n); POLYBENCH_1D_ARRAY_DECL(x, DATA_TYPE, N, n); + POLYBENCH_1D_ARRAY_DECL(x_StrictFP, DATA_TYPE, N, n); POLYBENCH_1D_ARRAY_DECL(c, DATA_TYPE, N, n); /* Initialize array(s). */ - init_array (n, POLYBENCH_ARRAY(A), POLYBENCH_ARRAY(x), POLYBENCH_ARRAY(c)); + init_array (n, POLYBENCH_ARRAY(A), POLYBENCH_ARRAY(x), + POLYBENCH_ARRAY(x_StrictFP), POLYBENCH_ARRAY(c)); /* Start timer. */ polybench_start_instruments; @@ -111,13 +155,16 @@ polybench_stop_instruments; polybench_print_instruments; + kernel_trisolv (n, POLYBENCH_ARRAY(A), POLYBENCH_ARRAY(x_StrictFP), POLYBENCH_ARRAY(c)); + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(x))); + polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(x_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(A); POLYBENCH_FREE_ARRAY(x); + POLYBENCH_FREE_ARRAY(x_StrictFP); POLYBENCH_FREE_ARRAY(c); return 0; Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/trmm/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/trmm/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/trmm/CMakeLists.txt @@ -5,4 +5,5 @@ list(APPEND CFLAGS -DSMALL_DATASET) endif() set(HASH_PROGRAM_OUTPUT 1) +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/trmm/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/trmm/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/trmm/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = trmm -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 ifdef SMALL_PROBLEM_SIZE CFLAGS += -DSMALL_DATASET Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/trmm/trmm.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/trmm/trmm.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/kernels/trmm/trmm.c @@ -19,19 +19,21 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array(int ni, DATA_TYPE *alpha, DATA_TYPE POLYBENCH_2D(A,NI,NI,ni,ni), - DATA_TYPE POLYBENCH_2D(B,NI,NI,ni,ni)) + DATA_TYPE POLYBENCH_2D(B,NI,NI,ni,ni), + DATA_TYPE POLYBENCH_2D(B_StrictFP,NI,NI,ni,ni)) { +#pragma STDC FP_CONTRACT OFF int i, j; *alpha = 32412; for (i = 0; i < ni; i++) for (j = 0; j < ni; j++) { A[i][j] = ((DATA_TYPE) i*j) / ni; - B[i][j] = ((DATA_TYPE) i*j) / ni; + B_StrictFP[i][j] = B[i][j] = ((DATA_TYPE) i*j) / ni; } } @@ -74,6 +76,46 @@ } +__attribute__((optnone)) static void +kernel_trmm_StrictFP(int ni, + DATA_TYPE alpha, + DATA_TYPE POLYBENCH_2D(A,NI,NI,ni,ni), + DATA_TYPE POLYBENCH_2D(B,NI,NI,ni,ni)) +{ +#pragma STDC FP_CONTRACT OFF + int i, j, k; + + /* B := alpha*A'*B, A triangular */ + for (i = 1; i < _PB_NI; i++) + for (j = 0; j < _PB_NI; j++) + for (k = 0; k < i; k++) + B[i][j] += alpha * A[i][k] * B[j][k]; +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static inline int +check_FP(int ni, + DATA_TYPE POLYBENCH_2D(A,NI,NI,ni,ni), + DATA_TYPE POLYBENCH_2D(B,NI,NI,ni,ni)) { + int i, j; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_NI; i++) + for (j = 0; j < _PB_NI; j++) + { + double V1 = A[i][j]; + double V2 = B[i][j]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d][%d] = %lf and B[%d][%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, j, V1, i, j, V2, AbsTolerance); + return 0; + } + } + + /* All elements are within the allowed FP_ABSTOLERANCE error margin. */ + return 1; +} int main(int argc, char** argv) { @@ -84,9 +126,11 @@ DATA_TYPE alpha; POLYBENCH_2D_ARRAY_DECL(A,DATA_TYPE,NI,NI,ni,ni); POLYBENCH_2D_ARRAY_DECL(B,DATA_TYPE,NI,NI,ni,ni); + POLYBENCH_2D_ARRAY_DECL(B_StrictFP,DATA_TYPE,NI,NI,ni,ni); /* Initialize array(s). */ - init_array (ni, &alpha, POLYBENCH_ARRAY(A), POLYBENCH_ARRAY(B)); + init_array (ni, &alpha, POLYBENCH_ARRAY(A), POLYBENCH_ARRAY(B), + POLYBENCH_ARRAY(B_StrictFP)); /* Start timer. */ polybench_start_instruments; @@ -98,9 +142,15 @@ polybench_stop_instruments; polybench_print_instruments; + kernel_trmm_StrictFP(ni, alpha, POLYBENCH_ARRAY(A), + POLYBENCH_ARRAY(B_StrictFP)); + + if (!check_FP(ni, POLYBENCH_ARRAY(B), POLYBENCH_ARRAY(B_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(ni, POLYBENCH_ARRAY(B))); + polybench_prevent_dce(print_array(ni, POLYBENCH_ARRAY(B_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(A); Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/durbin/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/durbin/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/durbin/CMakeLists.txt @@ -5,4 +5,5 @@ if(ARCH STREQUAL "XCore") set(XCORE_TARGET_NEEDS_MEMORY 256) endif() +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/durbin/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/durbin/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/durbin/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = durbin -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 HASH_PROGRAM_OUTPUT = 1 Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/durbin/durbin.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/durbin/durbin.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/durbin/durbin.c @@ -19,7 +19,7 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array (int n, DATA_TYPE POLYBENCH_2D(y,N,N,n,n), DATA_TYPE POLYBENCH_2D(sum,N,N,n,n), @@ -27,6 +27,7 @@ DATA_TYPE POLYBENCH_1D(beta,N,n), DATA_TYPE POLYBENCH_1D(r,N,n)) { +#pragma STDC FP_CONTRACT OFF int i, j; for (i = 0; i < n; i++) @@ -91,6 +92,58 @@ } +__attribute__((optnone)) static +void kernel_durbin_StrictFP(int n, + DATA_TYPE POLYBENCH_2D(y,N,N,n,n), + DATA_TYPE POLYBENCH_2D(sum,N,N,n,n), + DATA_TYPE POLYBENCH_1D(alpha,N,n), + DATA_TYPE POLYBENCH_1D(beta,N,n), + DATA_TYPE POLYBENCH_1D(r,N,n), + DATA_TYPE POLYBENCH_1D(out,N,n)) +{ +#pragma STDC FP_CONTRACT OFF + int i, k; + + y[0][0] = r[0]; + beta[0] = 1; + alpha[0] = r[0]; + for (k = 1; k < _PB_N; k++) + { + beta[k] = beta[k-1] - alpha[k-1] * alpha[k-1] * beta[k-1]; + sum[0][k] = r[k]; + for (i = 0; i <= k - 1; i++) + sum[i+1][k] = sum[i][k] + r[k-i-1] * y[i][k-1]; + alpha[k] = -sum[k][k] * beta[k]; + for (i = 0; i <= k-1; i++) + y[i][k] = y[i][k-1] + alpha[k] * y[k-i-1][k-1]; + y[k][k] = alpha[k]; + } + for (i = 0; i < _PB_N; i++) + out[i] = y[i][_PB_N-1]; +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static int +check_FP(int n, + DATA_TYPE POLYBENCH_1D(A,N,n), + DATA_TYPE POLYBENCH_1D(B,N,n)) { + int i; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_N; i++) + { + double V1 = A[i]; + double V2 = B[i]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d] = %lf and B[%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, V1, i, V2, AbsTolerance); + return 0; + } + } + + return 1; +} int main(int argc, char** argv) { @@ -104,6 +157,7 @@ POLYBENCH_1D_ARRAY_DECL(beta, DATA_TYPE, N, n); POLYBENCH_1D_ARRAY_DECL(r, DATA_TYPE, N, n); POLYBENCH_1D_ARRAY_DECL(out, DATA_TYPE, N, n); + POLYBENCH_1D_ARRAY_DECL(out_StrictFP, DATA_TYPE, N, n); /* Initialize array(s). */ @@ -130,9 +184,27 @@ polybench_stop_instruments; polybench_print_instruments; + init_array (n, + POLYBENCH_ARRAY(y), + POLYBENCH_ARRAY(sum), + POLYBENCH_ARRAY(alpha), + POLYBENCH_ARRAY(beta), + POLYBENCH_ARRAY(r)); + + kernel_durbin_StrictFP (n, + POLYBENCH_ARRAY(y), + POLYBENCH_ARRAY(sum), + POLYBENCH_ARRAY(alpha), + POLYBENCH_ARRAY(beta), + POLYBENCH_ARRAY(r), + POLYBENCH_ARRAY(out_StrictFP)); + + if (!check_FP(n, POLYBENCH_ARRAY(out), POLYBENCH_ARRAY(out_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(out))); + polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(out_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(y); Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/dynprog/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/dynprog/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/dynprog/CMakeLists.txt @@ -2,4 +2,5 @@ set(PROG dynprog) list(APPEND CFLAGS -I ${CMAKE_SOURCE_DIR}/${POLYBENCH_UTILS} -DPOLYBENCH_DUMP_ARRAYS) set(HASH_PROGRAM_OUTPUT 1) +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/dynprog/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/dynprog/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/dynprog/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = dynprog -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 HASH_PROGRAM_OUTPUT = 1 Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/dynprog/dynprog.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/dynprog/dynprog.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/dynprog/dynprog.c @@ -19,11 +19,12 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array(int length, DATA_TYPE POLYBENCH_2D(c,LENGTH,LENGTH,length,length), DATA_TYPE POLYBENCH_2D(W,LENGTH,LENGTH,length,length)) { +#pragma STDC FP_CONTRACT OFF int i, j; for (i = 0; i < length; i++) for (j = 0; j < length; j++) { @@ -80,6 +81,56 @@ *out = out_l; } +__attribute__((optnone)) static void +kernel_dynprog_StrictFP(int tsteps, int length, + DATA_TYPE POLYBENCH_2D(c,LENGTH,LENGTH,length,length), + DATA_TYPE POLYBENCH_2D(W,LENGTH,LENGTH,length,length), + DATA_TYPE POLYBENCH_3D(sum_c,LENGTH,LENGTH,LENGTH,length,length,length), + DATA_TYPE *out) +{ +#pragma STDC FP_CONTRACT OFF + int iter, i, j, k; + + DATA_TYPE out_l = 0; + + for (iter = 0; iter < _PB_TSTEPS; iter++) + { + for (i = 0; i <= _PB_LENGTH - 1; i++) + for (j = 0; j <= _PB_LENGTH - 1; j++) + c[i][j] = 0; + + for (i = 0; i <= _PB_LENGTH - 2; i++) + { + for (j = i + 1; j <= _PB_LENGTH - 1; j++) + { + sum_c[i][j][i] = 0; + for (k = i + 1; k <= j-1; k++) + sum_c[i][j][k] = sum_c[i][j][k - 1] + c[i][k] + c[k][j]; + c[i][j] = sum_c[i][j][j-1] + W[i][j]; + } + } + out_l += c[0][_PB_LENGTH - 1]; + } + + *out = out_l; +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static int +check_FP(DATA_TYPE A, + DATA_TYPE B) { + double AbsTolerance = FP_ABSTOLERANCE; + double V1 = A; + double V2 = B; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A = %lf and B = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", V1, V2, AbsTolerance); + return 0; + } + return 1; +} int main(int argc, char** argv) { @@ -88,7 +139,7 @@ int tsteps = TSTEPS; /* Variable declaration/allocation. */ - DATA_TYPE out; + DATA_TYPE out, out_StrictFP; POLYBENCH_3D_ARRAY_DECL(sum_c,DATA_TYPE,LENGTH,LENGTH,LENGTH,length,length,length); POLYBENCH_2D_ARRAY_DECL(c,DATA_TYPE,LENGTH,LENGTH,length,length); POLYBENCH_2D_ARRAY_DECL(W,DATA_TYPE,LENGTH,LENGTH,length,length); @@ -110,9 +161,19 @@ polybench_stop_instruments; polybench_print_instruments; + init_array (length, POLYBENCH_ARRAY(c), POLYBENCH_ARRAY(W)); + kernel_dynprog (tsteps, length, + POLYBENCH_ARRAY(c), + POLYBENCH_ARRAY(W), + POLYBENCH_ARRAY(sum_c), + &out_StrictFP); + + if (!check_FP(out, out_StrictFP)) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(out)); + polybench_prevent_dce(print_array(out_StrictFP)); /* Be clean. */ POLYBENCH_FREE_ARRAY(sum_c); Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/gramschmidt/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/gramschmidt/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/gramschmidt/CMakeLists.txt @@ -5,4 +5,5 @@ list(APPEND CFLAGS -DSMALL_DATASET) endif() set(HASH_PROGRAM_OUTPUT 1) +add_definitions(-DFP_ABSTOLERANCE=1) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/gramschmidt/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/gramschmidt/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/gramschmidt/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = gramschmidt -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1 ifdef SMALL_PROBLEM_SIZE CFLAGS += -DSMALL_DATASET Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/gramschmidt/gramschmidt.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/gramschmidt/gramschmidt.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/gramschmidt/gramschmidt.c @@ -19,12 +19,13 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array(int ni, int nj, DATA_TYPE POLYBENCH_2D(A,NI,NJ,ni,nj), DATA_TYPE POLYBENCH_2D(R,NJ,NJ,nj,nj), DATA_TYPE POLYBENCH_2D(Q,NI,NJ,ni,nj)) { +#pragma STDC FP_CONTRACT OFF int i, j; /* LLVM: This change ensures we do not calculate nan values, which are @@ -119,6 +120,60 @@ } +__attribute__((optnone)) static void +kernel_gramschmidt_StrictFP(int ni, int nj, + DATA_TYPE POLYBENCH_2D(A,NI,NJ,ni,nj), + DATA_TYPE POLYBENCH_2D(R,NJ,NJ,nj,nj), + DATA_TYPE POLYBENCH_2D(Q,NI,NJ,ni,nj)) +{ +#pragma STDC FP_CONTRACT OFF + int i, j, k; + + DATA_TYPE nrm; + + for (k = 0; k < _PB_NJ; k++) + { + nrm = 0; + for (i = 0; i < _PB_NI; i++) + nrm += A[i][k] * A[i][k]; + R[k][k] = sqrt(nrm); + for (i = 0; i < _PB_NI; i++) + Q[i][k] = A[i][k] / R[k][k]; + for (j = k + 1; j < _PB_NJ; j++) + { + R[k][j] = 0; + for (i = 0; i < _PB_NI; i++) + R[k][j] += Q[i][k] * A[i][j]; + for (i = 0; i < _PB_NI; i++) + A[i][j] = A[i][j] - Q[i][k] * R[k][j]; + } + } +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static inline int +check_FP(int ni, int nj, + DATA_TYPE POLYBENCH_2D(A,NI,NJ,ni,nj), + DATA_TYPE POLYBENCH_2D(B,NI,NJ,ni,nj)) { + int i, j; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_NI; i++) + for (j = 0; j < _PB_NJ; j++) + { + double V1 = A[i][j]; + double V2 = B[i][j]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d][%d] = %lf and B[%d][%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, j, V1, i, j, V2, AbsTolerance); + return 0; + } + } + + /* All elements are within the allowed FP_ABSTOLERANCE error margin. */ + return 1; +} int main(int argc, char** argv) { @@ -130,6 +185,9 @@ POLYBENCH_2D_ARRAY_DECL(A,DATA_TYPE,NI,NJ,ni,nj); POLYBENCH_2D_ARRAY_DECL(R,DATA_TYPE,NJ,NJ,nj,nj); POLYBENCH_2D_ARRAY_DECL(Q,DATA_TYPE,NI,NJ,ni,nj); + POLYBENCH_2D_ARRAY_DECL(A_StrictFP,DATA_TYPE,NI,NJ,ni,nj); + POLYBENCH_2D_ARRAY_DECL(R_StrictFP,DATA_TYPE,NJ,NJ,nj,nj); + POLYBENCH_2D_ARRAY_DECL(Q_StrictFP,DATA_TYPE,NI,NJ,ni,nj); /* Initialize array(s). */ init_array (ni, nj, @@ -150,14 +208,36 @@ polybench_stop_instruments; polybench_print_instruments; + init_array (ni, nj, + POLYBENCH_ARRAY(A_StrictFP), + POLYBENCH_ARRAY(R_StrictFP), + POLYBENCH_ARRAY(Q_StrictFP)); + kernel_gramschmidt_StrictFP(ni, nj, + POLYBENCH_ARRAY(A_StrictFP), + POLYBENCH_ARRAY(R_StrictFP), + POLYBENCH_ARRAY(Q_StrictFP)); + + if (!check_FP(ni, nj, POLYBENCH_ARRAY(A), POLYBENCH_ARRAY(A_StrictFP))) + return 1; + if (!check_FP(ni, nj, POLYBENCH_ARRAY(R), POLYBENCH_ARRAY(R_StrictFP))) + return 1; + if (!check_FP(ni, nj, POLYBENCH_ARRAY(Q), POLYBENCH_ARRAY(Q_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(ni, nj, POLYBENCH_ARRAY(A), POLYBENCH_ARRAY(R), POLYBENCH_ARRAY(Q))); + polybench_prevent_dce(print_array(ni, nj, + POLYBENCH_ARRAY(A_StrictFP), + POLYBENCH_ARRAY(R_StrictFP), + POLYBENCH_ARRAY(Q_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(A); POLYBENCH_FREE_ARRAY(R); POLYBENCH_FREE_ARRAY(Q); + POLYBENCH_FREE_ARRAY(A_StrictFP); + POLYBENCH_FREE_ARRAY(R_StrictFP); + POLYBENCH_FREE_ARRAY(Q_StrictFP); return 0; } Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/lu/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/lu/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/lu/CMakeLists.txt @@ -2,4 +2,5 @@ set(PROG lu) list(APPEND CFLAGS -I ${CMAKE_SOURCE_DIR}/${POLYBENCH_UTILS} -DPOLYBENCH_DUMP_ARRAYS) set(HASH_PROGRAM_OUTPUT 1) +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/lu/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/lu/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/lu/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = lu -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 HASH_PROGRAM_OUTPUT = 1 Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/lu/lu.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/lu/lu.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/lu/lu.c @@ -19,10 +19,11 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array (int n, DATA_TYPE POLYBENCH_2D(A,N,N,n,n)) { +#pragma STDC FP_CONTRACT OFF int i, j; for (i = 0; i < n; i++) @@ -79,6 +80,53 @@ } +__attribute__((optnone)) static void +kernel_lu_StrictFP(int n, + DATA_TYPE POLYBENCH_2D(A,N,N,n,n)) +{ +#pragma STDC FP_CONTRACT OFF + int i, j, k; + + for (k = 0; k < _PB_N; k++) + { + for (j = k + 1; j < _PB_N; j++) + A[k][j] = A[k][j] / A[k][k]; + for(i = k + 1; i < _PB_N; i++) + /* + LLVM: This change ensures we do not calculate nan values, which are + formatted differently on different platforms and which may also + be optimized unexpectedly. + Original code: + for (j = k + 1; j < _PB_N; j++) + A[i][j] = A[i][j] - A[i][k] * A[k][j]; + */ + for (j = k + 1; j < _PB_N; j++) + A[i][j] = A[i][j] + A[i][k] * A[k][j]; + } +} + +static inline int +check_FP(int n, + DATA_TYPE POLYBENCH_2D(A,N,N,n,n), + DATA_TYPE POLYBENCH_2D(B,N,N,n,n)) { + int i, j; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_N; i++) + for (j = 0; j < _PB_N; j++) + { + double V1 = A[i][j]; + double V2 = B[i][j]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d][%d] = %lf and B[%d][%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, j, V1, i, j, V2, AbsTolerance); + return 0; + } + } + + /* All elements are within the allowed FP_ABSTOLERANCE error margin. */ + return 1; +} int main(int argc, char** argv) { @@ -87,7 +135,7 @@ /* Variable declaration/allocation. */ POLYBENCH_2D_ARRAY_DECL(A, DATA_TYPE, N, N, n, n); - + POLYBENCH_2D_ARRAY_DECL(A_StrictFP, DATA_TYPE, N, N, n, n); /* Initialize array(s). */ init_array (n, POLYBENCH_ARRAY(A)); @@ -102,12 +150,18 @@ polybench_stop_instruments; polybench_print_instruments; + init_array (n, POLYBENCH_ARRAY(A_StrictFP)); + kernel_lu (n, POLYBENCH_ARRAY(A_StrictFP)); + if (!check_FP(n, POLYBENCH_ARRAY(A), POLYBENCH_ARRAY(A_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(A))); + polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(A_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(A); + POLYBENCH_FREE_ARRAY(A_StrictFP); return 0; } Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/ludcmp/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/ludcmp/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/ludcmp/CMakeLists.txt @@ -2,4 +2,5 @@ set(PROG ludcmp) list(APPEND CFLAGS -I ${CMAKE_SOURCE_DIR}/${POLYBENCH_UTILS} -DPOLYBENCH_DUMP_ARRAYS) set(HASH_PROGRAM_OUTPUT 1) +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/ludcmp/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/ludcmp/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/ludcmp/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = ludcmp -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 HASH_PROGRAM_OUTPUT = 1 Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/ludcmp/ludcmp.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/ludcmp/ludcmp.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/linear-algebra/solvers/ludcmp/ludcmp.c @@ -19,13 +19,14 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array (int n, DATA_TYPE POLYBENCH_2D(A,N+1,N+1,n+1,n+1), DATA_TYPE POLYBENCH_1D(b,N+1,n+1), DATA_TYPE POLYBENCH_1D(x,N+1,n+1), DATA_TYPE POLYBENCH_1D(y,N+1,n+1)) { +#pragma STDC FP_CONTRACT OFF int i, j; for (i = 0; i <= n; i++) @@ -108,6 +109,76 @@ } +__attribute__((optnone)) static void +kernel_ludcmp_StrictFP(int n, + DATA_TYPE POLYBENCH_2D(A,N+1,N+1,n+1,n+1), + DATA_TYPE POLYBENCH_1D(b,N+1,n+1), + DATA_TYPE POLYBENCH_1D(x,N+1,n+1), + DATA_TYPE POLYBENCH_1D(y,N+1,n+1)) +{ +#pragma STDC FP_CONTRACT OFF + int i, j, k; + + DATA_TYPE w; + + b[0] = 1.0; + for (i = 0; i < _PB_N; i++) + { + for (j = i+1; j <= _PB_N; j++) + { + w = A[j][i]; + for (k = 0; k < i; k++) + w = w- A[j][k] * A[k][i]; + A[j][i] = w / A[i][i]; + } + for (j = i+1; j <= _PB_N; j++) + { + w = A[i+1][j]; + for (k = 0; k <= i; k++) + w = w - A[i+1][k] * A[k][j]; + A[i+1][j] = w; + } + } + y[0] = b[0]; + for (i = 1; i <= _PB_N; i++) + { + w = b[i]; + for (j = 0; j < i; j++) + w = w - A[i][j] * y[j]; + y[i] = w; + } + x[_PB_N] = y[_PB_N] / A[_PB_N][_PB_N]; + for (i = 0; i <= _PB_N - 1; i++) + { + w = y[_PB_N - 1 - (i)]; + for (j = _PB_N - i; j <= _PB_N; j++) + w = w - A[_PB_N - 1 - i][j] * x[j]; + x[_PB_N - 1 - i] = w / A[_PB_N - 1 - (i)][_PB_N - 1-(i)]; + } +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static int +check_FP(int n, + DATA_TYPE POLYBENCH_1D(A,N+1,n), + DATA_TYPE POLYBENCH_1D(B,N+1,n)) { + int i; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_N+1; i++) + { + double V1 = A[i]; + double V2 = B[i]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d] = %lf and B[%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, V1, i, V2, AbsTolerance); + return 0; + } + } + + return 1; +} int main(int argc, char** argv) { @@ -118,6 +189,7 @@ POLYBENCH_2D_ARRAY_DECL(A, DATA_TYPE, N+1, N+1, n+1, n+1); POLYBENCH_1D_ARRAY_DECL(b, DATA_TYPE, N+1, n+1); POLYBENCH_1D_ARRAY_DECL(x, DATA_TYPE, N+1, n+1); + POLYBENCH_1D_ARRAY_DECL(x_StrictFP, DATA_TYPE, N+1, n+1); POLYBENCH_1D_ARRAY_DECL(y, DATA_TYPE, N+1, n+1); @@ -142,14 +214,28 @@ polybench_stop_instruments; polybench_print_instruments; + init_array (n, + POLYBENCH_ARRAY(A), + POLYBENCH_ARRAY(b), + POLYBENCH_ARRAY(x_StrictFP), + POLYBENCH_ARRAY(y)); + kernel_ludcmp (n, + POLYBENCH_ARRAY(A), + POLYBENCH_ARRAY(b), + POLYBENCH_ARRAY(x_StrictFP), + POLYBENCH_ARRAY(y)); + if (!check_FP(n, POLYBENCH_ARRAY(x), POLYBENCH_ARRAY(x_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(x))); + polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(x_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(A); POLYBENCH_FREE_ARRAY(b); POLYBENCH_FREE_ARRAY(x); + POLYBENCH_FREE_ARRAY(x_StrictFP); POLYBENCH_FREE_ARRAY(y); return 0; Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/medley/floyd-warshall/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/medley/floyd-warshall/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/medley/floyd-warshall/CMakeLists.txt @@ -5,4 +5,5 @@ list(APPEND CFLAGS -DSMALL_DATASET) endif() set(HASH_PROGRAM_OUTPUT 1) +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/medley/floyd-warshall/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/medley/floyd-warshall/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/medley/floyd-warshall/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = floyd-warshall -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 ifdef SMALL_PROBLEM_SIZE CFLAGS += -DSMALL_DATASET Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/medley/floyd-warshall/floyd-warshall.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/medley/floyd-warshall/floyd-warshall.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/medley/floyd-warshall/floyd-warshall.c @@ -19,10 +19,11 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array (int n, DATA_TYPE POLYBENCH_2D(path,N,N,n,n)) { +#pragma STDC FP_CONTRACT OFF int i, j; for (i = 0; i < n; i++) @@ -70,6 +71,45 @@ } +__attribute__((optnone)) static void +kernel_floyd_warshall_StrictFP(int n, DATA_TYPE POLYBENCH_2D(path,N,N,n,n)) +{ +#pragma STDC FP_CONTRACT OFF + int i, j, k; + + for (k = 0; k < _PB_N; k++) + { + for(i = 0; i < _PB_N; i++) + for (j = 0; j < _PB_N; j++) + path[i][j] = path[i][j] < path[i][k] + path[k][j] ? + path[i][j] : path[i][k] + path[k][j]; + } +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static inline int +check_FP(int n, + DATA_TYPE POLYBENCH_2D(A,N,N,n,n), + DATA_TYPE POLYBENCH_2D(B,N,N,n,n)) { + int i, j; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_N; i++) + for (j = 0; j < _PB_N; j++) + { + double V1 = A[i][j]; + double V2 = B[i][j]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d][%d] = %lf and B[%d][%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, j, V1, i, j, V2, AbsTolerance); + return 0; + } + } + + /* All elements are within the allowed FP_ABSTOLERANCE error margin. */ + return 1; +} int main(int argc, char** argv) { @@ -78,7 +118,7 @@ /* Variable declaration/allocation. */ POLYBENCH_2D_ARRAY_DECL(path, DATA_TYPE, N, N, n, n); - + POLYBENCH_2D_ARRAY_DECL(path_StrictFP, DATA_TYPE, N, N, n, n); /* Initialize array(s). */ init_array (n, POLYBENCH_ARRAY(path)); @@ -93,12 +133,18 @@ polybench_stop_instruments; polybench_print_instruments; + init_array (n, POLYBENCH_ARRAY(path_StrictFP)); + kernel_floyd_warshall_StrictFP(n, POLYBENCH_ARRAY(path_StrictFP)); + if (!check_FP(n, POLYBENCH_ARRAY(path), POLYBENCH_ARRAY(path_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(path))); + polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(path_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(path); + POLYBENCH_FREE_ARRAY(path_StrictFP); return 0; } Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/medley/reg_detect/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/medley/reg_detect/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/medley/reg_detect/CMakeLists.txt @@ -2,4 +2,5 @@ set(PROG reg_detect) list(APPEND CFLAGS -I ${CMAKE_SOURCE_DIR}/${POLYBENCH_UTILS} -DPOLYBENCH_DUMP_ARRAYS) set(HASH_PROGRAM_OUTPUT 1) +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/medley/reg_detect/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/medley/reg_detect/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/medley/reg_detect/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = reg_detect -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 HASH_PROGRAM_OUTPUT = 1 Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/medley/reg_detect/reg_detect.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/medley/reg_detect/reg_detect.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/medley/reg_detect/reg_detect.c @@ -19,12 +19,13 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array(int maxgrid, DATA_TYPE POLYBENCH_2D(sum_tang,MAXGRID,MAXGRID,maxgrid,maxgrid), DATA_TYPE POLYBENCH_2D(mean,MAXGRID,MAXGRID,maxgrid,maxgrid), DATA_TYPE POLYBENCH_2D(path,MAXGRID,MAXGRID,maxgrid,maxgrid)) -{ +{ +#pragma STDC FP_CONTRACT OFF int i, j; for (i = 0; i < maxgrid; i++) @@ -99,6 +100,68 @@ } +__attribute__((optnone)) static void +kernel_reg_detect_StrictFP(int niter, int maxgrid, int length, + DATA_TYPE POLYBENCH_2D(sum_tang,MAXGRID,MAXGRID,maxgrid,maxgrid), + DATA_TYPE POLYBENCH_2D(mean,MAXGRID,MAXGRID,maxgrid,maxgrid), + DATA_TYPE POLYBENCH_2D(path,MAXGRID,MAXGRID,maxgrid,maxgrid), + DATA_TYPE POLYBENCH_3D(diff,MAXGRID,MAXGRID,LENGTH,maxgrid,maxgrid,length), + DATA_TYPE POLYBENCH_3D(sum_diff,MAXGRID,MAXGRID,LENGTH,maxgrid,maxgrid,length)) +{ +#pragma STDC FP_CONTRACT OFF + int t, i, j, cnt; + + for (t = 0; t < _PB_NITER; t++) + { + for (j = 0; j <= _PB_MAXGRID - 1; j++) + for (i = j; i <= _PB_MAXGRID - 1; i++) + for (cnt = 0; cnt <= _PB_LENGTH - 1; cnt++) + diff[j][i][cnt] = sum_tang[j][i]; + + for (j = 0; j <= _PB_MAXGRID - 1; j++) + { + for (i = j; i <= _PB_MAXGRID - 1; i++) + { + sum_diff[j][i][0] = diff[j][i][0]; + for (cnt = 1; cnt <= _PB_LENGTH - 1; cnt++) + sum_diff[j][i][cnt] = sum_diff[j][i][cnt - 1] + diff[j][i][cnt]; + mean[j][i] = sum_diff[j][i][_PB_LENGTH - 1]; + } + } + + for (i = 0; i <= _PB_MAXGRID - 1; i++) + path[0][i] = mean[0][i]; + + for (j = 1; j <= _PB_MAXGRID - 1; j++) + for (i = j; i <= _PB_MAXGRID - 1; i++) + path[j][i] = path[j - 1][i - 1] + mean[j][i]; + } +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static inline int +check_FP(int maxgrid, + DATA_TYPE POLYBENCH_2D(A,MAXGRID,MAXGRID,maxgrid,maxgrid), + DATA_TYPE POLYBENCH_2D(B,MAXGRID,MAXGRID,maxgrid,maxgrid)) { + int i, j; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_MAXGRID; i++) + for (j = 0; j < _PB_MAXGRID; j++) + { + double V1 = A[i][j]; + double V2 = B[i][j]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d][%d] = %lf and B[%d][%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, j, V1, i, j, V2, AbsTolerance); + return 0; + } + } + + /* All elements are within the allowed FP_ABSTOLERANCE error margin. */ + return 1; +} int main(int argc, char** argv) { @@ -111,6 +174,7 @@ POLYBENCH_2D_ARRAY_DECL(sum_tang, DATA_TYPE, MAXGRID, MAXGRID, maxgrid, maxgrid); POLYBENCH_2D_ARRAY_DECL(mean, DATA_TYPE, MAXGRID, MAXGRID, maxgrid, maxgrid); POLYBENCH_2D_ARRAY_DECL(path, DATA_TYPE, MAXGRID, MAXGRID, maxgrid, maxgrid); + POLYBENCH_2D_ARRAY_DECL(path_StrictFP, DATA_TYPE, MAXGRID, MAXGRID, maxgrid, maxgrid); POLYBENCH_3D_ARRAY_DECL(diff, DATA_TYPE, MAXGRID, MAXGRID, LENGTH, maxgrid, maxgrid, length); POLYBENCH_3D_ARRAY_DECL(sum_diff, DATA_TYPE, MAXGRID, MAXGRID, LENGTH, maxgrid, maxgrid, length); @@ -135,14 +199,28 @@ polybench_stop_instruments; polybench_print_instruments; + init_array (maxgrid, + POLYBENCH_ARRAY(sum_tang), + POLYBENCH_ARRAY(mean), + POLYBENCH_ARRAY(path_StrictFP)); + kernel_reg_detect_StrictFP(niter, maxgrid, length, + POLYBENCH_ARRAY(sum_tang), + POLYBENCH_ARRAY(mean), + POLYBENCH_ARRAY(path_StrictFP), + POLYBENCH_ARRAY(diff), + POLYBENCH_ARRAY(sum_diff)); + if (!check_FP(maxgrid, POLYBENCH_ARRAY(path), POLYBENCH_ARRAY(path_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(maxgrid, POLYBENCH_ARRAY(path))); + polybench_prevent_dce(print_array(maxgrid, POLYBENCH_ARRAY(path_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(sum_tang); POLYBENCH_FREE_ARRAY(mean); POLYBENCH_FREE_ARRAY(path); + POLYBENCH_FREE_ARRAY(path_StrictFP); POLYBENCH_FREE_ARRAY(diff); POLYBENCH_FREE_ARRAY(sum_diff); Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/adi/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/adi/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/adi/CMakeLists.txt @@ -5,4 +5,5 @@ list(APPEND CFLAGS -DSMALL_DATASET) endif() set(HASH_PROGRAM_OUTPUT 1) +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/adi/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/adi/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/adi/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = adi -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 ifdef SMALL_PROBLEM_SIZE CFLAGS += -DSMALL_DATASET Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/adi/adi.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/adi/adi.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/adi/adi.c @@ -19,12 +19,13 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array (int n, DATA_TYPE POLYBENCH_2D(X,N,N,n,n), DATA_TYPE POLYBENCH_2D(A,N,N,n,n), DATA_TYPE POLYBENCH_2D(B,N,N,n,n)) { +#pragma STDC FP_CONTRACT OFF int i, j; for (i = 0; i < n; i++) @@ -101,6 +102,71 @@ } +__attribute__((optnone)) static void +kernel_adi_StrictFP(int tsteps, + int n, + DATA_TYPE POLYBENCH_2D(X,N,N,n,n), + DATA_TYPE POLYBENCH_2D(A,N,N,n,n), + DATA_TYPE POLYBENCH_2D(B,N,N,n,n)) +{ +#pragma STDC FP_CONTRACT OFF + int t, i1, i2; + + for (t = 0; t < _PB_TSTEPS; t++) + { + for (i1 = 0; i1 < _PB_N; i1++) + for (i2 = 1; i2 < _PB_N; i2++) + { + X[i1][i2] = X[i1][i2] - X[i1][i2-1] * A[i1][i2] / B[i1][i2-1]; + B[i1][i2] = B[i1][i2] - A[i1][i2] * A[i1][i2] / B[i1][i2-1]; + } + + for (i1 = 0; i1 < _PB_N; i1++) + X[i1][_PB_N-1] = X[i1][_PB_N-1] / B[i1][_PB_N-1]; + + for (i1 = 0; i1 < _PB_N; i1++) + for (i2 = 0; i2 < _PB_N-2; i2++) + X[i1][_PB_N-i2-2] = (X[i1][_PB_N-2-i2] - X[i1][_PB_N-2-i2-1] * A[i1][_PB_N-i2-3]) / B[i1][_PB_N-3-i2]; + + for (i1 = 1; i1 < _PB_N; i1++) + for (i2 = 0; i2 < _PB_N; i2++) { + X[i1][i2] = X[i1][i2] - X[i1-1][i2] * A[i1][i2] / B[i1-1][i2]; + B[i1][i2] = B[i1][i2] - A[i1][i2] * A[i1][i2] / B[i1-1][i2]; + } + + for (i2 = 0; i2 < _PB_N; i2++) + X[_PB_N-1][i2] = X[_PB_N-1][i2] / B[_PB_N-1][i2]; + + for (i1 = 0; i1 < _PB_N-2; i1++) + for (i2 = 0; i2 < _PB_N; i2++) + X[_PB_N-2-i1][i2] = (X[_PB_N-2-i1][i2] - X[_PB_N-i1-3][i2] * A[_PB_N-3-i1][i2]) / B[_PB_N-2-i1][i2]; + } +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static inline int +check_FP(int n, + DATA_TYPE POLYBENCH_2D(A,N,N,n,n), + DATA_TYPE POLYBENCH_2D(B,N,N,n,n)) { + int i, j; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_N; i++) + for (j = 0; j < _PB_N; j++) + { + double V1 = A[i][j]; + double V2 = B[i][j]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d][%d] = %lf and B[%d][%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, j, V1, i, j, V2, AbsTolerance); + return 0; + } + } + + /* All elements are within the allowed FP_ABSTOLERANCE error margin. */ + return 1; +} int main(int argc, char** argv) { @@ -110,6 +176,7 @@ /* Variable declaration/allocation. */ POLYBENCH_2D_ARRAY_DECL(X, DATA_TYPE, N, N, n, n); + POLYBENCH_2D_ARRAY_DECL(X_StrictFP, DATA_TYPE, N, N, n, n); POLYBENCH_2D_ARRAY_DECL(A, DATA_TYPE, N, N, n, n); POLYBENCH_2D_ARRAY_DECL(B, DATA_TYPE, N, N, n, n); @@ -128,12 +195,20 @@ polybench_stop_instruments; polybench_print_instruments; + init_array (n, POLYBENCH_ARRAY(X_StrictFP), POLYBENCH_ARRAY(A), + POLYBENCH_ARRAY(B)); + kernel_adi (tsteps, n, POLYBENCH_ARRAY(X_StrictFP), + POLYBENCH_ARRAY(A), POLYBENCH_ARRAY(B)); + if (!check_FP(n, POLYBENCH_ARRAY(X), POLYBENCH_ARRAY(X_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(X))); + polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(X_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(X); + POLYBENCH_FREE_ARRAY(X_StrictFP); POLYBENCH_FREE_ARRAY(A); POLYBENCH_FREE_ARRAY(B); Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/fdtd-2d/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/fdtd-2d/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/fdtd-2d/CMakeLists.txt @@ -5,4 +5,5 @@ list(APPEND CFLAGS -DSMALL_DATASET) endif() set(HASH_PROGRAM_OUTPUT 1) +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/fdtd-2d/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/fdtd-2d/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/fdtd-2d/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = fdtd-2d -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 ifdef SMALL_PROBLEM_SIZE CFLAGS += -DSMALL_DATASET Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/fdtd-2d/fdtd-2d.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/fdtd-2d/fdtd-2d.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/fdtd-2d/fdtd-2d.c @@ -19,7 +19,7 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array (int tmax, int nx, int ny, @@ -28,6 +28,7 @@ DATA_TYPE POLYBENCH_2D(hz,NX,NY,nx,ny), DATA_TYPE POLYBENCH_1D(_fict_,TMAX,tmax)) { +#pragma STDC FP_CONTRACT OFF int i, j; for (i = 0; i < tmax; i++) @@ -103,6 +104,59 @@ #pragma endscop } +__attribute__((optnone)) static void +kernel_fdtd_2d_StrictFP(int tmax, + int nx, + int ny, + DATA_TYPE POLYBENCH_2D(ex,NX,NY,nx,ny), + DATA_TYPE POLYBENCH_2D(ey,NX,NY,nx,ny), + DATA_TYPE POLYBENCH_2D(hz,NX,NY,nx,ny), + DATA_TYPE POLYBENCH_1D(_fict_,TMAX,tmax)) +{ +#pragma STDC FP_CONTRACT OFF + int t, i, j; + + for(t = 0; t < _PB_TMAX; t++) + { + for (j = 0; j < _PB_NY; j++) + ey[0][j] = _fict_[t]; + for (i = 1; i < _PB_NX; i++) + for (j = 0; j < _PB_NY; j++) + ey[i][j] = ey[i][j] - 0.5*(hz[i][j]-hz[i-1][j]); + for (i = 0; i < _PB_NX; i++) + for (j = 1; j < _PB_NY; j++) + ex[i][j] = ex[i][j] - 0.5*(hz[i][j]-hz[i][j-1]); + for (i = 0; i < _PB_NX - 1; i++) + for (j = 0; j < _PB_NY - 1; j++) + hz[i][j] = hz[i][j] - 0.7* (ex[i][j+1] - ex[i][j] + + ey[i+1][j] - ey[i][j]); + } +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static inline int +check_FP(int nx, int ny, + DATA_TYPE POLYBENCH_2D(A,NX,NY,nx,ny), + DATA_TYPE POLYBENCH_2D(B,NX,NY,nx,ny)) { + int i, j; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_NX; i++) + for (j = 0; j < _PB_NY; j++) + { + double V1 = A[i][j]; + double V2 = B[i][j]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d][%d] = %lf and B[%d][%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, j, V1, i, j, V2, AbsTolerance); + return 0; + } + } + + /* All elements are within the allowed FP_ABSTOLERANCE error margin. */ + return 1; +} int main(int argc, char** argv) { @@ -115,6 +169,9 @@ POLYBENCH_2D_ARRAY_DECL(ex,DATA_TYPE,NX,NY,nx,ny); POLYBENCH_2D_ARRAY_DECL(ey,DATA_TYPE,NX,NY,nx,ny); POLYBENCH_2D_ARRAY_DECL(hz,DATA_TYPE,NX,NY,nx,ny); + POLYBENCH_2D_ARRAY_DECL(ex_StrictFP,DATA_TYPE,NX,NY,nx,ny); + POLYBENCH_2D_ARRAY_DECL(ey_StrictFP,DATA_TYPE,NX,NY,nx,ny); + POLYBENCH_2D_ARRAY_DECL(hz_StrictFP,DATA_TYPE,NX,NY,nx,ny); POLYBENCH_1D_ARRAY_DECL(_fict_,DATA_TYPE,TMAX,tmax); /* Initialize array(s). */ @@ -139,16 +196,30 @@ polybench_stop_instruments; polybench_print_instruments; + init_array (tmax, nx, ny, + POLYBENCH_ARRAY(ex_StrictFP), + POLYBENCH_ARRAY(ey_StrictFP), + POLYBENCH_ARRAY(hz_StrictFP), + POLYBENCH_ARRAY(_fict_)); + kernel_fdtd_2d_StrictFP(tmax, nx, ny, + POLYBENCH_ARRAY(ex_StrictFP), + POLYBENCH_ARRAY(ey_StrictFP), + POLYBENCH_ARRAY(hz_StrictFP), + POLYBENCH_ARRAY(_fict_)); + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(nx, ny, POLYBENCH_ARRAY(ex), - POLYBENCH_ARRAY(ey), - POLYBENCH_ARRAY(hz))); + polybench_prevent_dce(print_array(nx, ny, POLYBENCH_ARRAY(ex_StrictFP), + POLYBENCH_ARRAY(ey_StrictFP), + POLYBENCH_ARRAY(hz_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(ex); POLYBENCH_FREE_ARRAY(ey); POLYBENCH_FREE_ARRAY(hz); + POLYBENCH_FREE_ARRAY(ex_StrictFP); + POLYBENCH_FREE_ARRAY(ey_StrictFP); + POLYBENCH_FREE_ARRAY(hz_StrictFP); POLYBENCH_FREE_ARRAY(_fict_); return 0; Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/fdtd-apml/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/fdtd-apml/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/fdtd-apml/CMakeLists.txt @@ -5,4 +5,5 @@ list(APPEND CFLAGS -DSMALL_DATASET) endif() set(HASH_PROGRAM_OUTPUT 1) +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/fdtd-apml/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/fdtd-apml/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/fdtd-apml/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = fdtd-apml -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 ifdef SMALL_PROBLEM_SIZE CFLAGS += -DSMALL_DATASET Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/fdtd-apml/fdtd-apml.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/fdtd-apml/fdtd-apml.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/fdtd-apml/fdtd-apml.c @@ -19,7 +19,7 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array (int cz, int cxm, int cym, @@ -37,6 +37,7 @@ DATA_TYPE POLYBENCH_1D(cymh,CYM+1,cym+1), DATA_TYPE POLYBENCH_1D(cyph,CYM+1,cym+1)) { +#pragma STDC FP_CONTRACT OFF int i, j, k; *mui = 2341; *ch = 42; @@ -165,6 +166,93 @@ } +__attribute__((optnone)) static void +kernel_fdtd_apml_StrictFP(int cz, + int cxm, + int cym, + DATA_TYPE mui, + DATA_TYPE ch, + DATA_TYPE POLYBENCH_2D(Ax,CZ+1,CYM+1,cz+1,cym+1), + DATA_TYPE POLYBENCH_2D(Ry,CZ+1,CYM+1,cz+1,cym+1), + DATA_TYPE POLYBENCH_2D(clf,CYM+1,CXM+1,cym+1,cxm+1), + DATA_TYPE POLYBENCH_2D(tmp,CYM+1,CXM+1,cym+1,cxm+1), + DATA_TYPE POLYBENCH_3D(Bza,CZ+1,CYM+1,CXM+1,cz+1,cym+1,cxm+1), + DATA_TYPE POLYBENCH_3D(Ex,CZ+1,CYM+1,CXM+1,cz+1,cym+1,cxm+1), + DATA_TYPE POLYBENCH_3D(Ey,CZ+1,CYM+1,CXM+1,cz+1,cym+1,cxm+1), + DATA_TYPE POLYBENCH_3D(Hz,CZ+1,CYM+1,CXM+1,cz+1,cym+1,cxm+1), + DATA_TYPE POLYBENCH_1D(czm,CZ+1,cz+1), + DATA_TYPE POLYBENCH_1D(czp,CZ+1,cz+1), + DATA_TYPE POLYBENCH_1D(cxmh,CXM+1,cxm+1), + DATA_TYPE POLYBENCH_1D(cxph,CXM+1,cxm+1), + DATA_TYPE POLYBENCH_1D(cymh,CYM+1,cym+1), + DATA_TYPE POLYBENCH_1D(cyph,CYM+1,cym+1)) +{ +#pragma STDC FP_CONTRACT OFF + int iz, iy, ix; + + for (iz = 0; iz < _PB_CZ; iz++) + { + for (iy = 0; iy < _PB_CYM; iy++) + { + for (ix = 0; ix < _PB_CXM; ix++) + { + clf[iz][iy] = Ex[iz][iy][ix] - Ex[iz][iy+1][ix] + Ey[iz][iy][ix+1] - Ey[iz][iy][ix]; + tmp[iz][iy] = (cymh[iy] / cyph[iy]) * Bza[iz][iy][ix] - (ch / cyph[iy]) * clf[iz][iy]; + Hz[iz][iy][ix] = (cxmh[ix] /cxph[ix]) * Hz[iz][iy][ix] + + (mui * czp[iz] / cxph[ix]) * tmp[iz][iy] + - (mui * czm[iz] / cxph[ix]) * Bza[iz][iy][ix]; + Bza[iz][iy][ix] = tmp[iz][iy]; + } + clf[iz][iy] = Ex[iz][iy][_PB_CXM] - Ex[iz][iy+1][_PB_CXM] + Ry[iz][iy] - Ey[iz][iy][_PB_CXM]; + tmp[iz][iy] = (cymh[iy] / cyph[iy]) * Bza[iz][iy][_PB_CXM] - (ch / cyph[iy]) * clf[iz][iy]; + Hz[iz][iy][_PB_CXM]=(cxmh[_PB_CXM] / cxph[_PB_CXM]) * Hz[iz][iy][_PB_CXM] + + (mui * czp[iz] / cxph[_PB_CXM]) * tmp[iz][iy] + - (mui * czm[iz] / cxph[_PB_CXM]) * Bza[iz][iy][_PB_CXM]; + Bza[iz][iy][_PB_CXM] = tmp[iz][iy]; + for (ix = 0; ix < _PB_CXM; ix++) + { + clf[iz][iy] = Ex[iz][_PB_CYM][ix] - Ax[iz][ix] + Ey[iz][_PB_CYM][ix+1] - Ey[iz][_PB_CYM][ix]; + tmp[iz][iy] = (cymh[_PB_CYM] / cyph[iy]) * Bza[iz][iy][ix] - (ch / cyph[iy]) * clf[iz][iy]; + Hz[iz][_PB_CYM][ix] = (cxmh[ix] / cxph[ix]) * Hz[iz][_PB_CYM][ix] + + (mui * czp[iz] / cxph[ix]) * tmp[iz][iy] + - (mui * czm[iz] / cxph[ix]) * Bza[iz][_PB_CYM][ix]; + Bza[iz][_PB_CYM][ix] = tmp[iz][iy]; + } + clf[iz][iy] = Ex[iz][_PB_CYM][_PB_CXM] - Ax[iz][_PB_CXM] + Ry[iz][_PB_CYM] - Ey[iz][_PB_CYM][_PB_CXM]; + tmp[iz][iy] = (cymh[_PB_CYM] / cyph[_PB_CYM]) * Bza[iz][_PB_CYM][_PB_CXM] - (ch / cyph[_PB_CYM]) * clf[iz][iy]; + Hz[iz][_PB_CYM][_PB_CXM] = (cxmh[_PB_CXM] / cxph[_PB_CXM]) * Hz[iz][_PB_CYM][_PB_CXM] + + (mui * czp[iz] / cxph[_PB_CXM]) * tmp[iz][iy] + - (mui * czm[iz] / cxph[_PB_CXM]) * Bza[iz][_PB_CYM][_PB_CXM]; + Bza[iz][_PB_CYM][_PB_CXM] = tmp[iz][iy]; + } + } +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static inline int +check_FP(int cz, int cxm, int cym, + DATA_TYPE POLYBENCH_3D(A,CZ+1,CYM+1,CXM+1,cz+1,cym+1,cxm+1), + DATA_TYPE POLYBENCH_3D(B,CZ+1,CYM+1,CXM+1,cz+1,cym+1,cxm+1)) { + int i, j, k; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_CZ + 1; i++) + for (j = 0; j < _PB_CYM + 1; j++) + for (k = 0; k < _PB_CXM + 1; k++) + { + double V1 = A[i][j][k]; + double V2 = B[i][j][k]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d][%d][%d] = %lf and B[%d][%d][%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, j, k, V1, i, j, k, V2, AbsTolerance); + return 0; + } + } + + /* All elements are within the allowed FP_ABSTOLERANCE error margin. */ + return 1; +} int main(int argc, char** argv) { @@ -184,6 +272,10 @@ POLYBENCH_3D_ARRAY_DECL(Ex,DATA_TYPE,CZ+1,CYM+1,CXM+1,cz+1,cym+1,cxm+1); POLYBENCH_3D_ARRAY_DECL(Ey,DATA_TYPE,CZ+1,CYM+1,CXM+1,cz+1,cym+1,cxm+1); POLYBENCH_3D_ARRAY_DECL(Hz,DATA_TYPE,CZ+1,CYM+1,CXM+1,cz+1,cym+1,cxm+1); + POLYBENCH_3D_ARRAY_DECL(Bza_StrictFP,DATA_TYPE,CZ+1,CYM+1,CXM+1,cz+1,cym+1,cxm+1); + POLYBENCH_3D_ARRAY_DECL(Ex_StrictFP,DATA_TYPE,CZ+1,CYM+1,CXM+1,cz+1,cym+1,cxm+1); + POLYBENCH_3D_ARRAY_DECL(Ey_StrictFP,DATA_TYPE,CZ+1,CYM+1,CXM+1,cz+1,cym+1,cxm+1); + POLYBENCH_3D_ARRAY_DECL(Hz_StrictFP,DATA_TYPE,CZ+1,CYM+1,CXM+1,cz+1,cym+1,cxm+1); POLYBENCH_1D_ARRAY_DECL(czm,DATA_TYPE,CZ+1,cz+1); POLYBENCH_1D_ARRAY_DECL(czp,DATA_TYPE,CZ+1,cz+1); POLYBENCH_1D_ARRAY_DECL(cxmh,DATA_TYPE,CXM+1,cxm+1); @@ -229,13 +321,49 @@ polybench_stop_instruments; polybench_print_instruments; + init_array (cz, cxm, cym, &mui, &ch, + POLYBENCH_ARRAY(Ax), + POLYBENCH_ARRAY(Ry), + POLYBENCH_ARRAY(Ex_StrictFP), + POLYBENCH_ARRAY(Ey_StrictFP), + POLYBENCH_ARRAY(Hz_StrictFP), + POLYBENCH_ARRAY(czm), + POLYBENCH_ARRAY(czp), + POLYBENCH_ARRAY(cxmh), + POLYBENCH_ARRAY(cxph), + POLYBENCH_ARRAY(cymh), + POLYBENCH_ARRAY(cyph)); + kernel_fdtd_apml_StrictFP(cz, cxm, cym, mui, ch, + POLYBENCH_ARRAY(Ax), + POLYBENCH_ARRAY(Ry), + POLYBENCH_ARRAY(clf), + POLYBENCH_ARRAY(tmp), + POLYBENCH_ARRAY(Bza_StrictFP), + POLYBENCH_ARRAY(Ex_StrictFP), + POLYBENCH_ARRAY(Ey_StrictFP), + POLYBENCH_ARRAY(Hz_StrictFP), + POLYBENCH_ARRAY(czm), + POLYBENCH_ARRAY(czp), + POLYBENCH_ARRAY(cxmh), + POLYBENCH_ARRAY(cxph), + POLYBENCH_ARRAY(cymh), + POLYBENCH_ARRAY(cyph)); + if (!check_FP(cz, cxm, cym, POLYBENCH_ARRAY(Bza), POLYBENCH_ARRAY(Bza_StrictFP))) + return 1; + if (!check_FP(cz, cxm, cym, POLYBENCH_ARRAY(Ex), POLYBENCH_ARRAY(Ex_StrictFP))) + return 1; + if (!check_FP(cz, cxm, cym, POLYBENCH_ARRAY(Ey), POLYBENCH_ARRAY(Ey_StrictFP))) + return 1; + if (!check_FP(cz, cxm, cym, POLYBENCH_ARRAY(Hz), POLYBENCH_ARRAY(Hz_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ polybench_prevent_dce(print_array(cz, cxm, cym, - POLYBENCH_ARRAY(Bza), - POLYBENCH_ARRAY(Ex), - POLYBENCH_ARRAY(Ey), - POLYBENCH_ARRAY(Hz))); + POLYBENCH_ARRAY(Bza_StrictFP), + POLYBENCH_ARRAY(Ex_StrictFP), + POLYBENCH_ARRAY(Ey_StrictFP), + POLYBENCH_ARRAY(Hz_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(Ax); @@ -246,6 +374,10 @@ POLYBENCH_FREE_ARRAY(Ex); POLYBENCH_FREE_ARRAY(Ey); POLYBENCH_FREE_ARRAY(Hz); + POLYBENCH_FREE_ARRAY(Bza_StrictFP); + POLYBENCH_FREE_ARRAY(Ex_StrictFP); + POLYBENCH_FREE_ARRAY(Ey_StrictFP); + POLYBENCH_FREE_ARRAY(Hz_StrictFP); POLYBENCH_FREE_ARRAY(czm); POLYBENCH_FREE_ARRAY(czp); POLYBENCH_FREE_ARRAY(cxmh); Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/jacobi-1d-imper/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/jacobi-1d-imper/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/jacobi-1d-imper/CMakeLists.txt @@ -2,4 +2,5 @@ set(PROG jacobi-1d-imper) list(APPEND CFLAGS -I ${CMAKE_SOURCE_DIR}/${POLYBENCH_UTILS} -DPOLYBENCH_DUMP_ARRAYS) set(HASH_PROGRAM_OUTPUT 1) +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/jacobi-1d-imper/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/jacobi-1d-imper/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/jacobi-1d-imper/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = jacobi-1d-imper -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 HASH_PROGRAM_OUTPUT = 1 Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/jacobi-1d-imper/jacobi-1d-imper.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/jacobi-1d-imper/jacobi-1d-imper.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/jacobi-1d-imper/jacobi-1d-imper.c @@ -19,11 +19,12 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array (int n, DATA_TYPE POLYBENCH_1D(A,N,n), DATA_TYPE POLYBENCH_1D(B,N,n)) { +#pragma STDC FP_CONTRACT OFF int i; for (i = 0; i < n; i++) @@ -73,6 +74,46 @@ } +__attribute__((optnone)) static void +kernel_jacobi_1d_imper_StrictFP(int tsteps, + int n, + DATA_TYPE POLYBENCH_1D(A,N,n), + DATA_TYPE POLYBENCH_1D(B,N,n)) +{ + #pragma STDC FP_CONTRACT OFF + int t, i, j; + + for (t = 0; t < _PB_TSTEPS; t++) + { + for (i = 1; i < _PB_N - 1; i++) + B[i] = 0.33333 * (A[i-1] + A[i] + A[i + 1]); + for (j = 1; j < _PB_N - 1; j++) + A[j] = B[j]; + } +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static int +check_FP(int n, + DATA_TYPE POLYBENCH_1D(A,N,n), + DATA_TYPE POLYBENCH_1D(B,N,n)) { + int i; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_N; i++) + { + double V1 = A[i]; + double V2 = B[i]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d] = %lf and B[%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, V1, i, V2, AbsTolerance); + return 0; + } + } + + return 1; +} int main(int argc, char** argv) { @@ -82,6 +123,7 @@ /* Variable declaration/allocation. */ POLYBENCH_1D_ARRAY_DECL(A, DATA_TYPE, N, n); + POLYBENCH_1D_ARRAY_DECL(A_StrictFP, DATA_TYPE, N, n); POLYBENCH_1D_ARRAY_DECL(B, DATA_TYPE, N, n); @@ -98,9 +140,15 @@ polybench_stop_instruments; polybench_print_instruments; + init_array (n, POLYBENCH_ARRAY(A_StrictFP), POLYBENCH_ARRAY(B)); + kernel_jacobi_1d_imper (tsteps, n, POLYBENCH_ARRAY(A_StrictFP), + POLYBENCH_ARRAY(B)); + if (!check_FP(n, POLYBENCH_ARRAY(A), POLYBENCH_ARRAY(A_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(A))); + polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(A_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(A); Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/jacobi-2d-imper/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/jacobi-2d-imper/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/jacobi-2d-imper/CMakeLists.txt @@ -5,4 +5,5 @@ list(APPEND CFLAGS -DSMALL_DATASET) endif() set(HASH_PROGRAM_OUTPUT 1) +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/jacobi-2d-imper/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/jacobi-2d-imper/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/jacobi-2d-imper/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = jacobi-2d-imper -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 ifdef SMALL_PROBLEM_SIZE CFLAGS += -DSMALL_DATASET Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/jacobi-2d-imper/jacobi-2d-imper.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/jacobi-2d-imper/jacobi-2d-imper.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/jacobi-2d-imper/jacobi-2d-imper.c @@ -19,11 +19,12 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array (int n, DATA_TYPE POLYBENCH_2D(A,N,N,n,n), DATA_TYPE POLYBENCH_2D(B,N,N,n,n)) { +#pragma STDC FP_CONTRACT OFF int i, j; for (i = 0; i < n; i++) @@ -78,6 +79,50 @@ } +__attribute__((optnone)) static void +kernel_jacobi_2d_imper_StrictFP(int tsteps, + int n, + DATA_TYPE POLYBENCH_2D(A,N,N,n,n), + DATA_TYPE POLYBENCH_2D(B,N,N,n,n)) +{ +#pragma STDC FP_CONTRACT OFF + int t, i, j; + + for (t = 0; t < _PB_TSTEPS; t++) + { + for (i = 1; i < _PB_N - 1; i++) + for (j = 1; j < _PB_N - 1; j++) + B[i][j] = 0.2 * (A[i][j] + A[i][j-1] + A[i][1+j] + A[1+i][j] + A[i-1][j]); + for (i = 1; i < _PB_N-1; i++) + for (j = 1; j < _PB_N-1; j++) + A[i][j] = B[i][j]; + } +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static inline int +check_FP(int n, + DATA_TYPE POLYBENCH_2D(A,N,N,n,n), + DATA_TYPE POLYBENCH_2D(B,N,N,n,n)) { + int i, j; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_N; i++) + for (j = 0; j < _PB_N; j++) + { + double V1 = A[i][j]; + double V2 = B[i][j]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d][%d] = %lf and B[%d][%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, j, V1, i, j, V2, AbsTolerance); + return 0; + } + } + + /* All elements are within the allowed FP_ABSTOLERANCE error margin. */ + return 1; +} int main(int argc, char** argv) { @@ -87,6 +132,7 @@ /* Variable declaration/allocation. */ POLYBENCH_2D_ARRAY_DECL(A, DATA_TYPE, N, N, n, n); + POLYBENCH_2D_ARRAY_DECL(A_StrictFP, DATA_TYPE, N, N, n, n); POLYBENCH_2D_ARRAY_DECL(B, DATA_TYPE, N, N, n, n); @@ -103,12 +149,19 @@ polybench_stop_instruments; polybench_print_instruments; + init_array (n, POLYBENCH_ARRAY(A_StrictFP), POLYBENCH_ARRAY(B)); + kernel_jacobi_2d_imper_StrictFP(tsteps, n, POLYBENCH_ARRAY(A_StrictFP), + POLYBENCH_ARRAY(B)); + if (!check_FP(n, POLYBENCH_ARRAY(A), POLYBENCH_ARRAY(A_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ - polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(A))); + polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(A_StrictFP))); /* Be clean. */ POLYBENCH_FREE_ARRAY(A); + POLYBENCH_FREE_ARRAY(A_StrictFP); POLYBENCH_FREE_ARRAY(B); return 0; Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/seidel-2d/CMakeLists.txt =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/seidel-2d/CMakeLists.txt +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/seidel-2d/CMakeLists.txt @@ -5,4 +5,5 @@ list(APPEND CFLAGS -DSMALL_DATASET) endif() set(HASH_PROGRAM_OUTPUT 1) +add_definitions(-DFP_ABSTOLERANCE=1e-5) llvm_singlesource() Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/seidel-2d/Makefile =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/seidel-2d/Makefile +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/seidel-2d/Makefile @@ -2,7 +2,7 @@ POLYBENCH_UTILS = SingleSource/Benchmarks/Polybench/utilities PROG = seidel-2d -CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS +CFLAGS += -I $(PROJ_SRC_ROOT)/$(POLYBENCH_UTILS) -DPOLYBENCH_DUMP_ARRAYS -DFP_ABSTOLERANCE=1e-5 ifdef SMALL_PROBLEM_SIZE CFLAGS += -DSMALL_DATASET Index: test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/seidel-2d/seidel-2d.c =================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/seidel-2d/seidel-2d.c +++ test-suite/trunk/SingleSource/Benchmarks/Polybench/stencils/seidel-2d/seidel-2d.c @@ -19,10 +19,11 @@ /* Array initialization. */ -static +__attribute__((optnone)) static void init_array (int n, DATA_TYPE POLYBENCH_2D(A,N,N,n,n)) { +#pragma STDC FP_CONTRACT OFF int i, j; for (i = 0; i < n; i++) @@ -70,6 +71,46 @@ } +__attribute__((optnone)) static void +kernel_seidel_2d_StrictFP(int tsteps, + int n, + DATA_TYPE POLYBENCH_2D(A,N,N,n,n)) +{ +#pragma STDC FP_CONTRACT OFF + int t, i, j; + + for (t = 0; t <= _PB_TSTEPS - 1; t++) + for (i = 1; i<= _PB_N - 2; i++) + for (j = 1; j <= _PB_N - 2; j++) + A[i][j] = (A[i-1][j-1] + A[i-1][j] + A[i-1][j+1] + + A[i][j-1] + A[i][j] + A[i][j+1] + + A[i+1][j-1] + A[i+1][j] + A[i+1][j+1])/9.0; +} + +/* Return 0 when one of the elements of arrays A and B do not match within the + allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ +static inline int +check_FP(int n, + DATA_TYPE POLYBENCH_2D(A,N,N,n,n), + DATA_TYPE POLYBENCH_2D(B,N,N,n,n)) { + int i, j; + double AbsTolerance = FP_ABSTOLERANCE; + for (i = 0; i < _PB_N; i++) + for (j = 0; j < _PB_N; j++) + { + double V1 = A[i][j]; + double V2 = B[i][j]; + double Diff = fabs(V1 - V2); + if (Diff > AbsTolerance) { + fprintf(stderr, "A[%d][%d] = %lf and B[%d][%d] = %lf differ more than" + " FP_ABSTOLERANCE = %lf\n", i, j, V1, i, j, V2, AbsTolerance); + return 0; + } + } + + /* All elements are within the allowed FP_ABSTOLERANCE error margin. */ + return 1; +} int main(int argc, char** argv) { @@ -79,6 +120,7 @@ /* Variable declaration/allocation. */ POLYBENCH_2D_ARRAY_DECL(A, DATA_TYPE, N, N, n, n); + POLYBENCH_2D_ARRAY_DECL(A_StrictFP, DATA_TYPE, N, N, n, n); /* Initialize array(s). */ @@ -94,12 +136,19 @@ polybench_stop_instruments; polybench_print_instruments; + init_array (n, POLYBENCH_ARRAY(A_StrictFP)); + kernel_seidel_2d (tsteps, n, POLYBENCH_ARRAY(A_StrictFP)); + + if (!check_FP(n, POLYBENCH_ARRAY(A), POLYBENCH_ARRAY(A_StrictFP))) + return 1; + /* Prevent dead-code elimination. All live-out data must be printed by the function call in argument. */ polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(A))); /* Be clean. */ POLYBENCH_FREE_ARRAY(A); + POLYBENCH_FREE_ARRAY(A_StrictFP); return 0; }