C User's Guide Supplement | ![]() ![]() ![]() ![]() ![]() |
Type-Based Alias Analysis
This document explains how you can use a new Sun WorkShop Compilers C option and several new pragmas to enable the compiler to perform type-based alias analysis and optimizations. You use these extensions to express type-based information about the way pointers are used in your C program. The C compiler uses this information, in turn, to do a significantly better job of alias disambiguation for pointer-based memory references in your program.
This document contains the following sections:
Introduction
You can use the new
-xalias_level
option to specify one of seven alias levels. Each level specifies a certain set of properties about the way you use pointers in your C program.As you compile with higher levels of the
-xalias_level
option, the compiler makes increasingly extensive assumptions about the pointers in your code. You have greater programming freedom when the compiler makes fewer assumptions. However, the optimizations that result from these narrow assumptions may not result in significant runtime performance improvement. If you code in accordance with the compiler assumptions of the more advanced levels of the-xalias_level
option, there is a greater chance that the resulting optimizations will enhance runtime performance.The
-xalias_level
option specifies which alias level applies to each translation unit. For cases where more detail is beneficial, you can use new pragmas to override whatever alias levels are in effect so that you can explicitly specify the aliasing relationships between individual types or pointer variables in the translation unit. These pragmas are most useful when the pointer usage in a translation unit is covered by one of the available alias levels, but a few specific pointer variables are used in an irregular way that is not allowed by one of the available levels.The
-xalias_level
OptionThe compiler uses the
-xalias_level
option to determine what assumptions it can make in order to perform optimizations using type-based alias analysis. This option places the indicated alias level into effect for the translation units being compiled. The first default is-xalias_level=any
, which means there is no type-based alias analysis. If you specify-xalias_level
without a value, the default is-xalias_level=layout
.Remember that if you issue the
-xalias_level
option but you fail to adhere to all of the assumptions and restrictions about aliasing described for any of the alias levels, the behavior of your program is undefined.
-xalias_level=
listReplace list with one of the terms in the following table.
Pragmas
For cases in which type-based analysis can benefit from more detail, you can use the following pragmas to override the alias level in effect and specify the aliasing relationships between individual types or pointer variables in the translation unit. These pragmas provide the most benefit when the use of pointers in a translation unit is consistent with one of the available alias levels, but a few specific pointer variables are used in an irregular way not allowed by one of the available levels.
Note You must declare the named type or variable prior to the pragma or a warning message is issued and the pragma is ignored. The results of the program are undefined if the pragma appears after the first memory reference to which its meaning applies.
The following terms are used in the pragma definitions.
level Any of the alias levels listed under The -xalias_level Option. type Any of the following: char
,short
,int
,long
,long
long
,float
,double
,long
double
void
, which denotes all pointer typestypedef
name, which is the name of a defined type from atypedef
declarationstruct
name, which is the keywordstruct
followed by a struct tag nameunion
, which is the keywordunion
followed by a union tag namepointer_name The name of any variable of pointer type in the translation unit.
#pragma
alias_level
levellist
Replace level with one of the seven alias levels:
any
,basic
,weak
,layout
,strict
,std
, orstrong
. You can replace list with either a single type or a comma-delimited list of types, or you can replace list with either a single pointer or a comma-delimited list of pointers. For example, you can issue#pragma
alias_level
as follows:
#pragma
alias_level
level(type [,
type])
#pragma
alias_level
level(pointer [, pointer])
This pragma specifies that the indicated alias level applies either to all of the memory references of the translation unit for the listed types, or to all of the dereferences of the translation unit where any of the named pointer variables are being dereferenced.
If you specify more than one alias level to be applied to a particular dereference, the level that is applied by the pointer name, if any, has precedence over all other levels. The level applied by the type name, if any, has precedence over the level applied by the option. In the following example, the
std
level applies to p if the program is compiled with#pragma
alias_level
set higher thanany
.
typedef int*
int_ptr;int_ptr p;#pragma alias_level strong (int_ptr)#pragma alias_level std (p)
#pragma
alias (type,
type [, type]...)
This pragma specifies that all the listed types alias each other. In the following example, the compiler assumes that the indirect access
*pt
aliases the indirect access*pf
.
#pragma alias (int, float)int*
pt;float*
pf;
#pragma
alias
(pointer,
pointer [, pointer]...)
This pragma specifies that at the point of any dereference of any of the named pointer variables, the pointer value being dereferenced can point to the same object as any of the other named pointer variables. This pragma overrides the aliasing assumptions of any applied alias levels. In the following example, the compiler assumes that the indirect access
*p
aliases the indirect access*q
regardless of the types of the two pointers.
#pragma alias(p, q)
#pragma
may_point_to (pointer, variable [, variable]...)
This pragma specifies that at the point of any dereference of the named pointer variable, the pointer value being dereferenced can point to the objects that are contained in any of the named variables. This pragma overrides the aliasing assumptions of any applied alias levels. In the following example, the compiler assumes that the indirect access
*p
aliases the direct accessesa
,b
, andc
.
#pragma alias may_point_to(p, a, b, c)
#pragma
noalias (type,
type [, type]...)
This pragma specifies that the listed types do not alias each other. In the following example, the compiler assumes that the indirect access
*p
does not alias the indirect access*ps
.
struct S {float f;...} *ps;#pragma noalias(int, struct S)int*
p;
#pragma
noalias (pointer,
pointer [, pointer]...)
This pragma specifies that at the point of any dereference of any of the named pointer variables, the pointer value being dereferenced does not point to the same object as any of the other named pointer variables. This pragma overrides all other applied alias levels. In the following example, the compiler assumes that the indirect access
*p
does not alias the indirect access*q
regardless of the types of the two pointers.
#pragma noalias(p, q)
#pragma may_not_point_to (pointer, variable [, variable]...)
This pragma specifies that at the point of any dereference of the named pointer variable, the pointer value being dereferenced does not point to the objects that are contained in any of the named variables. This pragma overrides all other applied alias levels. In the following example, the compiler assumes that the indirect access
*p
does not alias the direct accessesa
,b
, orc
.
#pragma may_not_point_to(p, a, b, c)Examples
This section provides examples of how memory references are constrained in your program when you use the
-xalias_level
option.Example 1
Consider the following code example that can compile with different levels of aliasing to demonstrate the aliasing relationship of the shown types.
struct foo {int f1;short f2;short f3;int f4;} *fp;struct bar {int b1;int b2;int b3;} *bp;int*
ip;short*
sp;If Example 1 is compiled with the
-xalias_level=any
option, the compiler considers the following indirect accesses as aliases to each other:
*ip
,*sp
,*fp
,*bp
,fp->f1
,fp->f2
,fp->f3
,fp->f4
,bp->b1
,bp->b2
,bp->b3
If Example 1 is compiled with the
-xalias_level=basic
option, the compiler considers the following indirect accesses as aliases to each other:
*ip
,*bp
,fp->f1
,fp->f4
,bp->b1
,bp->b2
,bp->b3
Additionally,
*sp
,fp->f2
, andfp->f3
can alias each other, and*sp
and*fp
can alias each other.However, under
-xalias_level=basic
, the compiler assumes the following:
*ip
does not alias*sp
.*ip
does not aliasfp->f2
andfp->f3
.*sp
does not aliasfp->f1
,fp->f4
,bp->b1
,bp->b2
, andbp->b3
.The compiler makes these assumptions because the access types of the two indirect accesses are different basic types.
If Example 1 is compiled with the
-xalias_level=weak
option, the compiler assumes the following alias information:
*ip
can alias*fp
,fp->f1
,fp->f4
,*bp
,bp->b1
,bp->b2
, andbp->b3
.*sp
can alias*fp
,fp->f2
andfp->f3
.fp->f1
can aliasbp->b1.
fp->f4
can aliasbp->b3.
The compiler assumes that
fp->fp1
does not aliasbp->b2
becausef1
is a field with offset 0 in a structure, whereasb2
is a field with a 4-byte offset in a structure. Similarly, the compiler assumes thatfp->f1
does not aliasbp->b3
, andfp->f4
does not alias eitherbp->b1
orbp->b2
.If Example 1 is compiled with the
-xalias_level=layout
option, the compiler assumes the following information:
*ip
can alias*fp
,*bp
,fp->f1
,fp->f4
,bp->b1
,bp->b2
, andbp->b3
.*sp
can alias*fp
,fp->f2
, andfp->f3
.fp->f1
can aliasbp->b1
and*bp
.*fp
and*bp
can alias each other.
fp->f4
does not aliasbp->b3
becausef4
andb3
are not corresponding fields in the common initial sequence offoo
andbar
.If Example 1 is compiled with the
-xalias_level=strict
option, the compiler assumes the following alias information:
*ip
can alias*fp
,fp->f1
,fp->f4
,*bp
,bp->b1
,bp->b2
, andbp->b3
.*sp
can alias*fp
,fp->f2
, andfp->f3
.With
-xalias_level=strict
, the compiler assumes that*fp
,*bp
,fp->f1
,fp->f2
,fp->f3
,fp->f4
,bp->b1
,bp->b2
, andbp->b3
do not alias each other becausefoo
andbar
are not the same when field names are ignored. However,fp
aliasesfp->f1
andbp
aliasesbp->b1
.If Example 1 is compiled with the
-xalias_level=std
option, the compiler assumes the following alias information:
*ip
can alias*fp
,fp->f1
,fp->f4
,*bp
,bp->b1
,bp->b2
, andbp->b3
.*sp
can alias*fp
,fp->f2
, andfp->f3
.However,
fp->f1
does not aliasbp->b1
,bp->b2
, orbp->b3
becausefoo
andbar
are not the same when field names are considered.If Example 1 is compiled with the
-xalias_level=strong
option, the compiler assumes the following alias information:
*ip
does not aliasfp->f1
,fp->f4
,bp->b1
,bp->b2
, andbp->b3
because a pointer, such as*ip
, should not point to the interior of a structure.- Similarly,
*sp
does not aliasfp->f1
orfp->f3
.*ip
does not alias*fp
,*bp
, and*sp
due to differing types.*sp
does not alias*fp
,*bp
, and*ip
due to differing types.Example 2
Consider the following example source code that can compile with different levels of aliasing to demonstrate the aliasing relationship of the shown types.
struct foo {int f1;int f2;int f3;}*
fp;struct bar {int b1;int b2;int b3;}*
bp;If Example 2 is compiled with the
-xalias_level=any
option, the compiler assumes the following alias information:
*fp
,*bp
,fp->f1
,fp->f2
,fp->f3
,bp->b1
,bp->b2
andbp->b3
all can alias each other because any two memory accesses alias each other at the level of-xalias_level=any
.If Example 2 is compiled with the
-xalias_level=basic
option, the compiler assumes the following alias information:
*fp
,*bp
,fp->f1
,fp->f2
,fp->f3
,bp->b1
,bp->b2
andbp->b3
all can alias each other. Any two field accesses using pointers*fp
and*bp
can alias each other in this example because all the structure fields are the same basic type.If Example 2 is compiled with the
-xalias_level=weak
option, the compiler assumes the following alias information:
*fp
and*fp
can alias each other.fp->f1
can aliasbp->b1
,*bp
and*fp
.fp->f2
can aliasbp->b2
,*bp
and*fp
.fp->f3
can aliasbp->b3
,*bp
and*fp
.However,
-xalias_level=weak
imposes the following restrictions:
fp->f1
does not aliasbp->b2
orbp->b3
becausef1
has an offset of zero, which is different from that ofb2
(four bytes) andb3
(eight bytes).fp->f2
does not aliasbp->b1
orbp->b3
becausef2
has an offset of four bytes, which is different fromb1
(zero bytes) andb3
(eight bytes).fp->f3
does not aliasbp->b1
orbp->b2
becausef3
has an offset of eight bytes, which is different fromb1
(zero bytes) andb2
(four bytes).If Example 2 is compiled with the
-xalias_level=layout
options, the compiler assumes the following alias information:
*fp
and*bp
can alias each other.fp->f1
can aliasbp->b1
,*bp
, and*fp
.fp->f2
can aliasbp->b2
,*bp
, and*fp
.fp->f3
can aliasbp->b3
,*bp
, and*fp
.However,
-xalias_level=layout
imposes the following restrictions:
fp->f1
does not aliasbp->b2
orbp->b3
because fieldf1
corresponds to fieldb1
in the common initial sequence offoo
andbar
.fp->f2
does not aliasbp->b1
orbp->b3
becausef2
corresponds to fieldb2
in the common initial sequence offoo
andbar
.fp->f3
does not aliasbp->b1
orbp->b2
becausef3
corresponds to fieldb3
in the common initial sequence offoo
andbar
.If Example 2 is compiled with the
-xalias_level=strict
option, the compiler assumes the following alias information:
*fp
and*bp
can alias each other.fp->f1
can aliasbp->b1
,*bp
, and*fp
.fp->f2
can aliasbp->b2
,*bp
, and*fp
.fp->f3
can aliasbp->b3
,*bp
, and*fp
.However,
-xalias_level=strict
imposes the following restrictions:
fp->f1
does not aliasbp->b2
orbp->b3
because fieldf1
corresponds to fieldb1
in the common initial sequence offoo
andbar
.fp->f2
does not aliasbp->b1
orbp->b3
becausef2
corresponds to fieldb2
in the common initial sequence offoo
andbar
.fp->f3
does not aliasbp->b1
orbp->b2
becausef3
corresponds to fieldb3
in the common initial sequence offoo
andbar
.If Example 2 is compiled with the
-xalias_level=std
option, the compiler assumes the following alias information:
fp->f1
,fp->f2
,fp->f3
,bp->b1
,bp->b2
, andbp->b3
do not alias each other.If Example 2 is compiled with the
-xalias_level=strong
option, the compiler assumes the following alias information:
fp->f1
,fp->f2
,fp->f3
,bp->b1
,bp->b2
, andbp->b3
do not alias each other.Example 3
Consider the following example source code that demonstrates that certain levels of aliasing cannot handle interior pointers. For a definition of interior pointers see strong.
struct foo {int f1;struct bar *f2;struct bar *f3;int f4;int f5;struct bar fb[10];} *fp;struct barstruct bar *b2;struct bar *b3;int b4;} *bp;bp=(struct bar*)(&fp->f2);The dereference in Example 3 is not supported by
weak
,layout
,strict
, orstd
. After the pointer assignmentbp=(struct bar*)(&fp->f2)
, the following pair of memory accesses touches the same memory locations:
fp->f2
andbp->b2
access the same memory locationfp->f3
andbp->b3
access the same memory locationfp->f4
andbp->b4
access the same memory locationHowever, under options
weak
,layout
,strict
, andstd
, the compiler assumes thatfp->f2
andbp->b2
do not alias. The compiler makes this assumption becauseb2
has an offset of zero, which is different from the offset off2
(four bytes), andfoo
andbar
do not have a common initial sequence. Similarly, the compiler also assumes thatbp->b3
does not aliasfp->f3
, andbp->b4
does not aliasfp->f4
.Thus, the pointer assignment
bp=(struct bar*)(&fp->f2)
creates a situation in which the compiler's assumptions about alias information are incorrect. This may lead to incorrect optimization.Try compiling after you make the modifications shown in the following example.
After the pointer assignment
bp=(struct bar*)(&fp->f2)
, the following pair of memory accesses touches the same memory locations:
fp->f2
andbp->b2
fp->f3
andbp->b3
fp->f4
andbp->b4
By examining the changes shown in the preceding code example, you can see that the expression
fp->f2
is another form of the expressionfp->fb.b2
. Becausefp->fb
is of typebar
,fp->f2
accesses theb2
field ofbar
. Furthermore,bp->b2
also accesses theb2
field ofbar
. Therefore, the compiler assumes thatfp->f2
aliasesbp->b2
. Similarly, the compiler assumes thatfp->f3
aliasesbp->b3
, andfp->f4
aliasesbp->b4
. As a result, the aliasing assumed by the compiler matches the actual aliases caused by the pointer assignment.Example 4
Consider the following example source code.
struct foo {int f1;int f2;} *fp;struct bar {int b1;int b2;} *bp;struct cat {int c1;struct foo cf;int c2;int c3;} *cp;struct dog {int d1;int d2;struct bar db;int d3;} *dp;If Example 4 is compiled with the
-xalias_level=weak
option, the compiler assumes the following alias information:
fp->f1
can aliasbp->b1
,cp->c1
,dp->d1
,cp->cf.f1
, anddf->db.b1
.fp->f2
can aliasbp->b2
,cp->cf.f1
,dp->d2
,cp->cf.f2
,df->db.b2
,cp->c2
.bp->b1
can aliasfp->f1
,cp->c1
,dp->d1
,cp->cf.f1
, anddf->db.b1
.bp->b2
can aliasfp->f2
,cp->cf.f1
,dp->d2
,cp->cf.f1
, anddf->db.b2
.
fp->f2
can aliascp->c2
because*dp
can alias*cp
and*fp
can aliasdp->db
.
cp->c1
can aliasfp->f1
,bp->b1
,dp->d1
, anddp->db.b1
.cp->cf.f1
can aliasfp->f1
,fp->f2
,bp->b1
,bp->b2
,dp->d2
, anddp->d1
.
cp-
>cf.f1
does not aliasdp->db.b1
.
cp->cf.f2
can aliasfp->f2
,bp->b2
,dp->db.b1
, anddp->d2
.cp->c2
can aliasdp->db.b2
.
cp->c2
does not aliasdp->db.b1
andcp->c2
does not aliasdp->d3
.With respect to offsets,
cp->c2
can aliasdb->db.b1
only if*dp
aliasescp->cf
. However, if*dp
aliasescp->cf
, thendp->db.b1
must alias beyond the end offoo
cf
, which is prohibited by object restrictions. Therefore, the compiler assumes thatcp->c2
cannot aliasdb->db.b1
.Notice that
cp->c3
does not aliasdp->db.b2
. These memory references do not alias because the offsets of the fields of the types involved in the dereferences differ and do not overlap. Based on this, the compiler assumes they cannot alias.
dp->d1
can aliasfp->f1
,bp->b1
, andcp->c1
.dp->d2
can aliasfp->f2
,bp->b2
, andcp->cf.f1
.dp->db.b1
can aliasfp->f1
,bp->b1
, andcp->c1
.dp->db.b2
can aliasfp->f2
,bp->b2
,cp->c2
, andcp->cf.f1
.dp->d3
can aliascp->c3
.Notice that
dp->d3
does not aliascp->cf.f2
. These memory references do not alias because the offsets of the fields of the types involved in the dereferences differ and do not overlap. Based on this, the compiler assumes they cannot alias.If Example 4 is compiled with the
-xalias_level=layout
option, the compiler assumes only the following alias information:
fp->f1
,bp->b1
,cp->c1
anddp->d1
all can alias each other.fp->f2
,bp->b2
anddp->d2
all can alias each other.fp->f1
can aliascp->cf.f1
anddp->db.b1
.bp->b1
can aliascp->cf.f1
anddp->db.b1
.fp->f2
can aliascp->cf.f2
anddp->db.b2
.bp->b2
can aliascp->cf.f2
anddp->db.b2
.If Example 4 is compiled with the
-xalias_level=strict
option, the compiler assumes only the following alias information:
fp->f1
andbp->b1
can alias each other.fp->f2
andbp->b2
can alias each other.fp->f1
can aliascp->cf.f1
anddp->db.b1
.bp->b1
can aliascp->cf.f1
anddp->db.b1
.fp->f2
can aliascp->cf.f2
anddp->db.b2
.bp->b2
can aliascp->cf.f2
anddp->db.b2
.If Example 4 is compiled with the
-xalias_level=std
option, the compiler assumes only the following alias information:
fp->f1
can aliascp->cf.f1
.bp->b1
can aliasdp->db.b1
.fp->f2
can aliascp->cf.f2
.bp->b2
can aliasdp->db.b2
.Example 5
Consider the following example source code.
struct foo {short f1;short f2;int f3;} *fp;struct bar {int b1;int b2;} *bp;union moo {struct foo u_f;struct bar u_b;} u;Here are the compiler's assumptions based on the following alias levels:
- If Example 5 is compiled with the
-xalias_level=weak
option,fp->f3
andbp->b2
can alias each other.- If Example 5 is compiled with the
-xalias_level=layout
option, no fields can alias each other.- If Example 5 is compiled with the
-xalias_level=strict
option,fp->f3
andbp->b2
can alias each other.- If Example 5 is compiled with the
-xalias_level=std
option, no fields can alias each other.Example 6
Consider the following example source code.
struct bar;struct foo {struct foo *ffp;struct bar *fbp;} *fp;struct bar {struct bar *bbp;long b2;} *bp;Here are the compiler's assumptions based on the following alias levels:
- If Example 6 is compiled with the
-xalias_level=weak
option, onlyfp->ffp
andbp->bbp
can alias each other.- If Example 6 is compiled with the
-xalias_level=layout
option, onlyfp->ffp
andbp->bbp
can alias each other.- If Example 6 is compiled with the
-xalias_level=strict
option, no fields can alias because the two struct types are still different even after their tags are removed.- If Example 6 is compiled with the
-xalias_level=std
option, no fields can alias because the two types and the tags are not the same.Example 7
Consider the following example source code:
struct foo;struct bar;#pragma alias (struct foo, struct bar)struct foo {int f1;int f2;} *fp;struct bar {short b1;short b2;int b3;} *bp;The pragma in this example tells the compiler that
foo
andbar
are allowed to alias each other. The compiler makes the following assumptions about alias information:
fp->f1
can alias withbp->b1
,bp->b2
, andbp->b3
fp->f2
can alias withbp->b1
,bp->b2
, andbp->b3
Sun Microsystems, Inc. Copyright information. All rights reserved. Feedback |
Library | Contents | Previous | Next | Index |