3.4.4. Using pointers

For vectorization purposes, it is generally better to use arrays rather than pointers. The compiler is able to vectorize loops containing pointers if it can determine that the loop is safe. Both array references and pointer references in loops are analyzed to see if there is any vector access to memory. In some cases, the compiler creates a run-time test, and executes a vector version or scalar version of the loop depending on the result of the test.

Often function arguments are passed as pointers. If several pointer variables are passed to a function, it is possible that pointing to overlapping sections of memory can occur. Often, at runtime, this is not the case but the compiler always follows the safe method and avoids optimizing loops that involve pointers appearing on both the left and right sides of an assignment operator. For example, consider the function in Example 3.8.

Example 3.8.  Non vectorizable pointers

void func (int *pa, int *pb, int x)
	for (i = 0; i < 100; i++) 		*(pa + i) = *(pb + i) + x;

In this example, if pa and pb overlap in memory in a way that causes results from one loop pass to feedback to a subsequent loop pass, then vectorization of the loop can give incorrect results. If the function is called with the following arguments, vectorization might be ambiguous:

int *a;

func (a, a-1);

The compiler performs a runtime test to see if pointer aliasing occurs. If pointer aliasing does not occur, it executes a vectorized version of the code. If pointer aliasing occurs, the original non vectorized code is executes instead. This leads to a small cost in runtime efficiency and code size.

In actual practice, it is very rare for data dependence to exist because of function arguments. Programs that pass overlapping pointers are very hard to understand and debug, apart from any vectorization concerns.

See restrict for more information.

Indirect addressing

Indirect addressing occurs when an array is accessed by a vector of values. If the array is being fetched from memory, the operation is called a gather. If the array is being stored into memory, the operation is called a scatter. In Example 3.9, a is being scattered, and b is being gathered.

Example 3.9. Non vectorizable indirect addressing

float a[99], b[99];
int ia[99], ib[99], i, n, j;
for (i = 0; i < n; i++) a[ia[i]] = b[j + ib[i]];

Indirect addressing is not vectorizable with the NEON unit because it can only deal with vectors that are stored consecutively in memory. If there is indirect addressing and significant calculations in a loop, it might be more efficient for you to move the indirect addressing into a separate non vector loop. This enables the calculations to vectorize efficiently.

Copyright © 2007 ARM Limited. All rights reserved.ARM DUI 0350A