Jump to content United States-English
HP.com Home Products and Services Support and Drivers Solutions How to Buy
» Contact HP
More options
HP.com home
Fortran 90, Fortran 77, C, aC++: Exemplar Programming Guide > Chapter 8 Programming conventions for optimal code

Aliasing in C

» 

Technical documentation

Complete book in PDF
» Feedback
Content starts here

 » Table of Contents

 » Glossary

Because they frequently use pointers, C programs are especially susceptible to aliasing problems. By default, the optimizer assumes that a pointer can point to any object in the entire application. Thus, any two pointers are potential aliases. The C compiler has two algorithms you can specify in place of the default: an ANSI-C aliasing algorithm and a type-safe algorithm. The ANSI-C algorithm is enabled [disabled] through the +O[no]ptrs_ansi option. The type-safe algorithm is enabled [disabled] by specifying the command-line option +O[no]ptrs_strongly_typed. The defaults for these options are +Onoptrs_ansi and +Onoptrs_strongly_typed.

ANSI algorithm

ANSI C provides strict type-checking. Pointers and variables cannot alias with pointers or variables of a different base type. The ANSI C aliasing algorithm may not be safe if your program is not ANSI compliant.

Type-safe algorithm

The type-safe algorithm provides stricter type-checking. This allows the C compiler to use a stricter algorithm that eliminates many potential aliases found by the ANSI algorithm.

Specifying aliasing modes

To specify an aliasing mode, use one of the following options on the C compiler command line:

  • +Optrs_ansi

  • +Optrs_strongly_typed

These and other C aliasing options are further discussed in Appendix D, "Optimization options."

Iteration and stop values

Aliasing a variable in an array subscript can make it unsafe for the compiler to parallelize a loop. Below are several situations that can prevent parallelization.

Using potential aliases as addresses of variables

In the following example, the code passes &j to getval; getval can use that address in any number of ways, including possibly assigning it to iptr. (Even though iptr is not passed to getval, getval might still access it as a global variable or through another alias.) This situation makes j a potential alias for *iptr.

void subex(iptr, n, j)
int *iptr, n, j;
{
n = getval(&j,n);

for (j--; j<n; j++)
iptr[j] += 1;
}

This potential alias means that j and iptr[j] might occupy the same memory space for some value of j. The assignment to iptr[j] on that iteration would also change the value of j itself. The possible alteration of j prevents the compiler from safely parallelizing the loop. In this case, the Optimization Report says that no induction variable could be found for the loop, and the compiler does not parallelize the loop. (For information on Optimization Reports, see Appendix D, "Appendix E “Optimization Report”."

Avoid taking the address of any variable that will be used as the iteration variable for a loop. To parallelize the loop in subex, use a temporary variable i as shown in the following example:

void subex(iptr, n, j)
int *iptr, n, j;
{
int i;
n = getval(&j,n);
i=j;
for (i--; i<n; i++)
iptr[i] += 1;
}

Using hidden aliases as pointers

In the next example, ialex takes the address of j and assigns it to *ip. Thus, j becomes an alias for *ip and, potentially, for *iptr. Assigned values to iptr[j] within the loop could alter the value of j. As a result, the compiler cannot use j as an induction variable and, without an induction variable, it cannot count the iterations of the loop. When the compiler cannot find the loop's iteration count, the compiler cannot parallelize the loop.

int *ip;
void ialex(iptr)
int *iptr;{
int j;
*ip = &j;
for (j=0; j<2048; j++)
iptr[j] = 107;
}

To parallelize this loop, remove the line of code that takes the address of j or introduce a temporary variable.

Using a pointer as a loop counter

Compiling the following function, the compiler finds that *j is not an induction variable (because an assignment to iptr[*j] could alter the value of *j within the loop.) The compiler does not parallelize the loop.

void ialex2(iptr, j, n)
int *iptr;
int *j, n;
{
for (*j=0; *j<n; (*j)++)
iptr[*j] = 107;
}

Again, this problem can be solved by introducing a temporary iteration variable.

Aliasing stop variables

In the following code, the stop variable n becomes a possible alias for *iptr when &n is passed to foo. This means that n can be altered during the execution of the loop. As a result, the compiler cannot count the number of iterations and cannot parallelize the loop.

void salex(int *iptr, int n)
{
int i;
foo(&n);
for (i=0; i < n; i++)
iptr[i] += iptr[i];
return;
}

To parallelize the affected loop, eliminate the call to foo, move the call below the loop (in which case flow-sensitive analysis takes care of the aliasing), or create a temporary variable as shown below:

void salex(int *iptr, int n)
{
int i, tmp;
foo(&n);
tmp = n;
for (i=0; i < tmp; i++)
iptr[i] += iptr[i];
return;
}

Because tmp is not aliased to iptr, the loop has a fixed stop value and the compiler parallelizes it.

Global variables

Potential aliases involving global variables cause optimization problems in many programs. The compiler cannot tell whether another function causes a global variable to become aliased.

The following code uses a global variable, n, as a stop value. Because n may have its address taken and assigned to ik outside the scope of the function, n must be considered a potential alias for *ik. The value of n, therefore, can be altered on any iteration of the loop. The compiler cannot determine the stop value and cannot parallelize the loop.

int n, *ik;
void foo(int *ik)
{
int i;

for (i=0; i<n; i++)
ik[i]=i;
}

Using a temporary local variable solves the problem.

int n;
void foo(int *ik)
{
int i,stop = n;

for (i=0; i<stop; ++i)
ik[i]=i;
}

If ik is a global variable instead of a pointer, the problem does not occur. Global variables do not cause aliasing problems except when pointers are involved. The following code will parallelize:

int n, ik[1000];
void foo()
{
int i;

for (i=0; i<n; i++)
ik[i] = i;
}
Printable version
Privacy statement Using this site means you accept its terms Feedback to webmaster
© Hewlett-Packard Development Company, L.P.