/* Test of origin tracking through floating point code and in the case where there are large amounts of uninitialised data floating around. This program creates 3 matrices of 2300x2300 doubles, makes one value in them undefined, does arithmetic, and tests the result, which is then undefined. This also tests the secondary otag cache (ocacheL2), since the amount of uninitialised data is somewhat over 43MB and it appears that quite a lot of non-zero-otag lines are pushed into ocacheL2. This program needs to be compiled with -O. */ #include <assert.h> #include <stdio.h> #include <stdlib.h> #include "../memcheck.h" double** alloc_square_array ( int nArr ) { int i; double** vec; assert(nArr >= 1); vec = malloc(nArr * sizeof(double*)); assert(vec); for (i = 0; i < nArr; i++) { vec[i] = malloc(nArr * sizeof(double)); assert(vec); } return vec; } double** do3x3smooth ( double** arr, int nArr ) { int i, j; double** out; assert(nArr >= 3); out = alloc_square_array(nArr - 2); assert(out); for (i = 1; i < nArr-1; i++) { for (j = 1; j < nArr-1; j++) { double s = arr[i-1][j-1] + arr[i-1][j ] + arr[i-1][j+1] + arr[i ][j-1] + arr[i ][j ] + arr[i ][j+1] + arr[i+1][j-1] + arr[i+1][j ] + arr[i+1][j+1]; out[i-1][j-1] = s / 9.0; } } return out; } double sum ( double** arr, int nArr ) { int i, j; double s = 0.0; assert(nArr >= 1); for (i = 0; i < nArr; i++) { for (j = 0; j < nArr; j++) { s += arr[i][j]; } } return s; } void setup_arr ( /*OUT*/double** arr, int nArr ) { int i, j; assert(nArr >= 1); for (i = 0; i < nArr; i++) { for (j = 0; j < nArr; j++) { arr[i][j] = (double)(i * j); if (i == nArr/2 && j == nArr/2) { unsigned char* p = (unsigned char*)&arr[i][j]; (void) VALGRIND_MAKE_MEM_UNDEFINED(p, 1); } } } } int main ( void ) { int nArr = 2300; int ri; double r, **arr, **arr2, **arr3; arr = alloc_square_array(nArr); setup_arr( arr, nArr ); arr2 = do3x3smooth( arr, nArr ); arr3 = do3x3smooth( arr2, nArr-2 ); r = sum( arr3, nArr-4 ); /* Convert answer to int before testing it, so as to guarantee there's only one conditional branch. */ if (0) fprintf(stderr, "r = %g\n", r ); r /= 10000.0; ri = (int)r; if (0) fprintf(stderr, "ri = %d\n", ri); if (ri == 696565111) { fprintf(stderr, "Test succeeded.\n"); } else { fprintf(stderr, "Test FAILED !\n"); assert(0); } return 0; }