* Changes to make NodeType be private to DSNode.
[oota-llvm.git] / lib / Analysis / DataStructure / DataStructureAA.cpp
1 //===- DataStructureAA.cpp - Data Structure Based Alias Analysis ----------===//
2 //
3 // This pass uses the top-down data structure graphs to implement a simple
4 // context sensitive alias analysis.
5 //
6 //===----------------------------------------------------------------------===//
7
8 #include "llvm/Analysis/DataStructure.h"
9 #include "llvm/Analysis/DSGraph.h"
10 #include "llvm/Analysis/AliasAnalysis.h"
11 #include "llvm/Module.h"
12
13 namespace {
14   class DSAA : public Pass, public AliasAnalysis {
15     TDDataStructures *TD;
16   public:
17     DSAA() : TD(0) {}
18
19     //------------------------------------------------
20     // Implement the Pass API
21     //
22
23     // run - Build up the result graph, representing the pointer graph for the
24     // program.
25     //
26     bool run(Module &M) {
27       InitializeAliasAnalysis(this);
28       TD = &getAnalysis<TDDataStructures>();
29       return false;
30     }
31
32     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
33       AliasAnalysis::getAnalysisUsage(AU);
34       AU.setPreservesAll();                    // Does not transform code...
35       AU.addRequired<TDDataStructures>();      // Uses TD Datastructures
36       AU.addRequired<AliasAnalysis>();         // Chains to another AA impl...
37     }
38
39     //------------------------------------------------
40     // Implement the AliasAnalysis API
41     //  
42
43     // alias - This is the only method here that does anything interesting...
44     AliasResult alias(const Value *V1, unsigned V1Size,
45                       const Value *V2, unsigned V2Size);
46   };
47
48   // Register the pass...
49   RegisterOpt<DSAA> X("ds-aa", "Data Structure Graph Based Alias Analysis");
50
51   // Register as an implementation of AliasAnalysis
52   RegisterAnalysisGroup<AliasAnalysis, DSAA> Y;
53 }
54
55 // getValueFunction - return the function containing the specified value if
56 // available, or null otherwise.
57 //
58 static const Function *getValueFunction(const Value *V) {
59   if (const Instruction *I = dyn_cast<Instruction>(V))
60     return I->getParent()->getParent();
61   else if (const Argument *A = dyn_cast<Argument>(V))
62     return A->getParent();
63   else if (const BasicBlock *BB = dyn_cast<BasicBlock>(V))
64     return BB->getParent();
65   return 0;
66 }
67
68 // alias - This is the only method here that does anything interesting...
69 AliasAnalysis::AliasResult DSAA::alias(const Value *V1, unsigned V1Size,
70                                        const Value *V2, unsigned V2Size) {
71   if (V1 == V2) return MustAlias;
72
73   const Function *F1 = getValueFunction(V1);
74   const Function *F2 = getValueFunction(V2);
75   assert((!F1 || !F2 || F1 == F2) && "Alias query for 2 different functions?");
76   
77   if (F2) F1 = F2;
78   if (F1) {
79     // Get the graph for a function...
80     DSGraph &G = TD->getDSGraph(*F1);
81     hash_map<Value*, DSNodeHandle> &GSM = G.getScalarMap();
82     hash_map<Value*, DSNodeHandle>::iterator I = GSM.find((Value*)V1);
83     if (I != GSM.end()) {
84       assert(I->second.getNode() && "Scalar map points to null node?");
85       hash_map<Value*, DSNodeHandle>::iterator J = GSM.find((Value*)V2);
86       if (J != GSM.end()) {
87         assert(J->second.getNode() && "Scalar map points to null node?");
88
89         DSNode  *N1 = I->second.getNode(),  *N2 = J->second.getNode();
90         unsigned O1 = I->second.getOffset(), O2 = J->second.getOffset();
91         
92         // We can only make a judgement of one of the nodes is complete...
93         if (!N1->isIncomplete() || !N2->isIncomplete()) {
94           if (N1 != N2)
95             return NoAlias;   // Completely different nodes.
96
97           // Both point to the same node and same offset, and there is only one
98           // physical memory object represented in the node, return must alias.
99           if (O1 == O2 && !N1->isMultiObject())
100             return MustAlias; // Exactly the same object & offset
101
102           // See if they point to different offsets...  if so, we may be able to
103           // determine that they do not alias...
104           if (O1 != O2) {
105             if (O2 < O1) {    // Ensure that O1 <= O2
106               std::swap(V1, V2);
107               std::swap(O1, O2);
108               std::swap(V1Size, V2Size);
109             }
110
111             // FIXME: This is not correct because we do not handle array
112             // indexing correctly with this check!
113             //if (O1+V1Size <= O2) return NoAlias;
114           }
115         }
116       }
117     }
118   }
119
120   // FIXME: we could improve on this by checking the globals graph for aliased
121   // global queries...
122   return getAnalysis<AliasAnalysis>().alias(V1, V1Size, V2, V2Size);
123 }