| Alias Analysis Infrastructure in LLVM |
Written by Chris Lattner
| Introduction |
The AliasAnalysis class is the centerpiece of the LLVM Alias Analysis related infrastructure. This class is the common interface between clients of alias analysis information and the implementations providing it. In addition to simple alias analysis information, this class exposes Mod/Ref information from those implementations which can provide it, allowing for powerful analyses and transformations to work well together.
This document contains information necessary to successfully implement this interface, use it, and to test both sides. It also explains some of the finer points about what exactly results mean. If you feel that something is unclear or should be added, please let me know.
| AliasAnalysis Overview |
The AliasAnalysis interface exposes information about memory, represented in several different ways. In particular, memory objects are represented as a starting address and size, and function calls are represented as the actual call or invoke instructions that performs the call. The AliasAnalysis interface also exposes some helper methods which allow you to get mod/ref information for arbitrary instructions.
| Representation of Pointers |
Representing memory objects as a starting address and a size is critically important for precise Alias Analyses. For example, consider this (silly) C code:
int i;
char C[2];
char A[10];
/* ... */
for (i = 0; i != 10; ++i) {
C[0] = A[i]; /* One byte store */
C[1] = A[9-i]; /* One byte store */
}
In this case, the basicaa pass will disambiguate the stores to
C[0] and C[1] because they are accesses to two distinct
locations one byte apart, and the accesses are each one byte. In this case, the
LICM pass can use store motion to remove the stores from the loop. In
constrast, the following code:
int i;
char C[2];
char A[10];
/* ... */
for (i = 0; i != 10; ++i) {
((short*)C)[0] = A[i]; /* Two byte store! */
C[1] = A[9-i]; /* One byte store */
}
In this case, the two stores to C do alias each other, because the access to the
&C[0] element is a two byte access. If size information wasn't
available in the query, even the first case would have to conservatively assume
that the accesses alias.
| Must, May, and No Alias Responses |
The Must Alias response is trickier though. In LLVM, the Must Alias response may only be returned if the two memory objects are guaranteed to always start at exactly the same location. If two memory objects overlap, but do not start at the same location, MayAlias must be returned.
| The getModRefInfo methods |
| Writing a new AliasAnalysis Implementation |
| Different Pass styles |
In addition to the pass that you subclass, you should also inherit from the AliasAnalysis interface, of course, and use the RegisterAnalysisGroup template to register as an implementation of AliasAnalysis.
| Required initialization calls |
void getAnalysisUsage(AnalysisUsage &AU) const {
AliasAnalysis::getAnalysisUsage(AU);
// declare your dependencies here.
}
Additionally, your must invoke the InitializeAliasAnalysis method from
your analysis run method (run for a Pass,
runOnFunction for a FunctionPass, runOnBasicBlock for
a BasicBlockPass, or InitializeAliasAnalysis for an
ImmutablePass). For example (as part of a Pass):
bool run(Module &M) {
InitializeAliasAnalysis(this);
// Perform analysis here...
return false;
}
| Interfaces which may be specified |
| The AliasAnalysis chaining behavior |
| Efficiency Issues |
| Using AliasAnalysis results |
| Using the -load-vn Pass |
| Using the AliasSetTracker class |
First you initialize the AliasSetTracker by use the "add" methods to add information about various potentially aliasing instructions in the scope you are interested in. Once all of the alias sets are completed, your pass should simply iterate through the constructed alias sets, using the AliasSetTracker begin()/end() methods.
The AliasSets formed by the AliasSetTracker are guaranteed to be disjoint, calculate mod/ref information for the set, and keep track of whether or not all of the pointers in the set are Must aliases. The AliasSetTracker also makes sure that sets are properly folded due to call instructions, and can provide a list of pointers in each set.
As an example user of this, the Loop Invariant Code Motion pass uses AliasSetTrackers to build alias information about each loop nest. If an AliasSet in a loop is not modified, then all load instructions from that set may be hoisted out of the loop. If any alias sets are stored and are must alias sets, then the stores may be sunk to outside of the loop. Both of these transformations obviously only apply if the pointer argument is loop-invariant.
| Using the AliasAnalysis interface directly |
| Helpful alias analysis related tools |
| The -no-aa pass |
| The -print-alias-sets pass |
| The -count-aa pass |
$ opt -basicaa -count-aa -ds-aa -count-aa -licmWhich will print out how many queries (and what responses are returned) by the -licm pass (of the -ds-aa pass) and how many queries are made of the -basicaa pass by the -ds-aa pass. This can be useful when evaluating an alias analysis for precision.
| The -aa-eval pass |