When you use pointers to access array data in C/C++, the compiler cannot assume that the memory accessed by pointers will not be altered by other pointers that refer to the same address. For example, if two pointer input parameters share memory, the instruction to store the second parameter can overwrite the memory read from the first load instruction. This means that, after a store for a pointer variable, any load from a pointer must be reloaded. Consider the following code example:
int i = *p; *q = 0; j = *p;
If *q aliases *p, then the value must be reloaded from memory. If *q does not alias *p, the old value that is already loaded into i can be used.
To avoid the overhead of reloading values from memory every time they are referenced in the code, and allow the compiler to simply manipulate values that are already resident in registers, there are several strategies you can use. One approach is to assign input array element values to local variables and perform computations only on the local variables, as shown in Figure 2.
#include <math.h> void reciprocal_roots (const double* x, double* f) { double x0 = x[0] ; double x1 = x[1] ; double r0 = 1.0/sqrt(x0) ; double r1 = 1.0/sqrt(x1) ; f[0] = r0 ; f[1] = r1 ; }
If you are certain that two references do not share the same memory address, another approach is to use the #pragma disjoint directive. This directive asserts that two identifiers do not share the same storage within the scope of their use. Specifically, you can use the pragma to inform the compiler that two pointer variables do not point to the same memory address. The directive in the following exampleFigure 3 indicates to the compiler that the pointers-to-arrays of double x and f do not share memory:
__inline void ten_reciprocal_roots (double* x, double* f) { #pragma disjoint (*x, *f) int i; for (i=0; i < 10; i++) f[i]= 1.0 / sqrt (x[i]); }