I've been trying to find somewhere on the Intel site to file a bug report but it seems virtually impossible to do this, so I thought I'd try posting it here. If anyone has a link to a proper bug reporting page then I'd be happy to file it there too.
Here's a self-contained example which illustrates a serious code gen bug in ICC 13 and 14 which shows up at -O2 and above. ICC 11 is fine. There is also a workaround included:
#include <assert.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> void ReverseData( const int n, // IN: data height and width (it must be square) uint16_t data[] // IN: data to be mirrored. Must not be NULL. // OUT: data image with columns reversed. ) { uint16_t *pRowStart = &data[0]; // point to row 0 column 0 uint16_t *pRowEnd = &data[n-1]; // point to row 0 column n-1 int r; for (r = 0; r < n; ++r) { int c; for (c = 0; c < n/2; ++c) { uint16_t *pLeft = pRowStart + c; uint16_t *pRight = pRowEnd - c; uint16_t dLeft = *pLeft; uint16_t dRight = *pRight; #ifdef WORKAROUND // NB: these asserts are a workaround for an apparent code generation bug in ICC versions 13 // and 14 - without these asserts we get memory corruption beyond the end of the data. // Note: this bug does not appear to be present in ICC 11. assert(pLeft >= &data[0] && pLeft < &data[n*n]); assert(pRight >= &data[0] && pRight < &data[n*n]); #endif *pLeft = dRight; *pRight = dLeft; } pRowStart += n; pRowEnd += n; } } // end: ReverseData() int main() { const int n = 32; const int size = n * n + n; // data is nxn but add an additional row for test purposes - uint16_t *data = NULL; // this additional guard row should not get over-written int r, c; // unless we have a code generation bug int errors = 0; data = calloc(size, sizeof(data[0])); // allocate and init all data to zero for (r = 0; r < n; ++r) // init nxn data to distinct values, leaving additionl guard row set to zero { for (c = 0; c < n; ++c) { data[r * n + c] = r * n + c; } } printf("Call ReverseData(%d, %p)...\n", n, data); ReverseData(n, data); // call our function to reverse nxn data for (c = 0; c < n; ++c) // check to see whether anything has been written to our guard row { if (data[r * n + c] != 0) { printf("Error at index %d, data should be 0 but is actually %u !\n", r * n + c, data[r * n + c]); errors++; } } printf("%s\n", errors == 0 ? "PASS" : "FAIL"); free(data); return 0; }