summaryrefslogtreecommitdiff
path: root/include/llvm/Analysis/ET-Forest.h
blob: 8bd5e447bca6db63e5c5712e377776a6a667cbff (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
//===- llvm/Analysis/ET-Forest.h - ET-Forest implementation -----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was written by Daniel Berlin from code written by Pavel Nejedy, and
// is distributed under the University of Illinois Open Source License. See
// LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the following classes:
//  1. ETNode:  A node in the ET forest.
//  2. ETOccurrence: An occurrence of the node in the splay tree
//  storing the DFS path information.
//
//  The ET-forest structure is described in:
//    D. D. Sleator and R. E. Tarjan. A data structure for dynamic trees.
//    J.  G'omput. System Sci., 26(3):362 381, 1983.
//
// Basically, the ET-Forest is storing the dominator tree (ETNode),
// and a splay tree containing the depth first path information for
// those nodes (ETOccurrence).  This enables us to answer queries
// about domination (DominatedBySlow), and ancestry (NCA) in
// logarithmic time, and perform updates to the information in
// logarithmic time.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_ANALYSIS_ETFOREST_H
#define LLVM_ANALYSIS_ETFOREST_H

#include <cassert>
#include <cstdlib>

namespace llvm {
class ETNode;

/// ETOccurrence - An occurrence for a node in the et tree
///
/// The et occurrence tree is really storing the sequences you get from
/// doing a DFS over the ETNode's.  It is stored as a modified splay
/// tree.
/// ET occurrences can occur at multiple places in the ordering depending
/// on how many ET nodes have it as their father.  To handle
/// this, they are separate from the nodes.
///
class ETOccurrence {
public:
  ETOccurrence(ETNode *n): OccFor(n), Parent(NULL), Left(NULL), Right(NULL),
    Depth(0), Min(0), MinOccurrence(this) {};

  void setParent(ETOccurrence *n) {
    assert(n != this && "Trying to set parent to ourselves");
    Parent = n;
  }

  // Add D to our current depth
  void setDepthAdd(int d) {
    Min += d;
    Depth += d;
  }
  
  // Reset our depth to D
  void setDepth(int d) {
    Min += d - Depth;
    Depth = d;
  }

  // Set Left to N
  void setLeft(ETOccurrence *n) {
    assert(n != this && "Trying to set our left to ourselves");
    Left = n;
    if (n)
      n->setParent(this);
  }
  
  // Set Right to N
  void setRight(ETOccurrence *n) {
    assert(n != this && "Trying to set our right to ourselves");
    Right = n;
    if (n)
      n->setParent(this);
  }
  
  // Splay us to the root of the tree
  void Splay(void);

  // Recompute the minimum occurrence for this occurrence.
  void recomputeMin(void) {
    ETOccurrence *themin = Left;
    
    // The min may be our Right, too.
    if (!themin || (Right && themin->Min > Right->Min))
      themin = Right;
    
    if (themin && themin->Min < 0) {
      Min = themin->Min + Depth;
      MinOccurrence = themin->MinOccurrence;
    } else {
      Min = Depth;
      MinOccurrence = this;
    }
  }
 private:
  friend class ETNode;

    // Node we represent
  ETNode *OccFor;

  // Parent in the splay tree
  ETOccurrence *Parent;

  // Left Son in the splay tree
  ETOccurrence *Left;

  // Right Son in the splay tree
  ETOccurrence *Right;

  // Depth of the node is the sum of the depth on the path to the
  // root.
  int Depth;

  // Subtree occurrence's minimum depth
  int Min;

  // Subtree occurrence with minimum depth
  ETOccurrence *MinOccurrence;
};


class ETNode {
public:
  ETNode(void *d) : data(d), DFSNumIn(-1), DFSNumOut(-1),
                    Father(NULL), Left(NULL),
                    Right(NULL), Son(NULL), ParentOcc(NULL) {   
    RightmostOcc = new ETOccurrence(this);
  };

  // This does *not* maintain the tree structure.
  // If you want to remove a node from the forest structure, use
  // removeFromForest()
  ~ETNode() {
    delete RightmostOcc;
    delete ParentOcc;
  }

  void removeFromForest() {
    // Split us away from all our sons.
    while (Son)
      Son->Split();
    
    // And then split us away from our father.
    if (Father)
      Father->Split();
  }

  // Split us away from our parents and children, so that we can be
  // reparented. NB: setFather WILL NOT DO WHAT YOU WANT IF YOU DO NOT
  // SPLIT US FIRST.
  void Split();

  // Set our parent node to the passed in node
  void setFather(ETNode *);
  
  // Nearest Common Ancestor of two et nodes.
  ETNode *NCA(ETNode *);
  
  // Return true if we are below the passed in node in the forest.
  bool Below(ETNode *);
  /*
   Given a dominator tree, we can determine whether one thing
   dominates another in constant time by using two DFS numbers:
  
   1. The number for when we visit a node on the way down the tree
   2. The number for when we visit a node on the way back up the tree
  
   You can view these as bounds for the range of dfs numbers the
   nodes in the subtree of the dominator tree rooted at that node
   will contain.
  
   The dominator tree is always a simple acyclic tree, so there are
   only three possible relations two nodes in the dominator tree have
   to each other:
  
   1. Node A is above Node B (and thus, Node A dominates node B)
  
        A
        |
        C
       / \ 
      B   D
  
  
   In the above case, DFS_Number_In of A will be <= DFS_Number_In of
   B, and DFS_Number_Out of A will be >= DFS_Number_Out of B.  This is
   because we must hit A in the dominator tree *before* B on the walk
   down, and we will hit A *after* B on the walk back up
  
   2. Node A is below node B (and thus, node B dominates node B)
       
        B
        |
        A
       / \ 
      C   D
  
   In the above case, DFS_Number_In of A will be >= DFS_Number_In of
   B, and DFS_Number_Out of A will be <= DFS_Number_Out of B.
  
   This is because we must hit A in the dominator tree *after* B on
   the walk down, and we will hit A *before* B on the walk back up
  
   3. Node A and B are siblings (and thus, neither dominates the other)
  
        C
        |
        D
       / \                        
      A   B
  
   In the above case, DFS_Number_In of A will *always* be <=
   DFS_Number_In of B, and DFS_Number_Out of A will *always* be <=
   DFS_Number_Out of B.  This is because we will always finish the dfs
   walk of one of the subtrees before the other, and thus, the dfs
   numbers for one subtree can't intersect with the range of dfs
   numbers for the other subtree.  If you swap A and B's position in
   the dominator tree, the comparison changes direction, but the point
   is that both comparisons will always go the same way if there is no
   dominance relationship.
  
   Thus, it is sufficient to write
  
   A_Dominates_B(node A, node B) {
      return DFS_Number_In(A) <= DFS_Number_In(B) &&
             DFS_Number_Out(A) >= DFS_Number_Out(B);
   }
  
   A_Dominated_by_B(node A, node B) {
     return DFS_Number_In(A) >= DFS_Number_In(A) &&
            DFS_Number_Out(A) <= DFS_Number_Out(B);
   }
  */
  bool DominatedBy(ETNode *other) const {
    return this->DFSNumIn >= other->DFSNumIn &&
           this->DFSNumOut <= other->DFSNumOut;
  }
  
  // This method is slower, but doesn't require the DFS numbers to
  // be up to date.
  bool DominatedBySlow(ETNode *other) {
    return this->Below(other);
  }

  void assignDFSNumber (int);
  
  bool hasFather() const {
    return Father != NULL;
  }

  // Do not let people play around with fathers.
  const ETNode *getFather() const {
    return Father;
  }

  template <typename T>
  T *getData() const {
    return static_cast<T*>(data);
  }
  
  unsigned getDFSNumIn() const {
    return DFSNumIn;
  }
  
  unsigned getDFSNumOut() const {
    return DFSNumOut;
  }

  const ETNode *getSon() const {
    return Son;
  }
  
  const ETNode *getBrother() const {
    return Left;
  }

 private:
  // Data represented by the node
  void *data;

  // DFS Numbers
  int DFSNumIn, DFSNumOut;

  // Father
  ETNode *Father;

  // Brothers.  Node, this ends up being a circularly linked list.
  // Thus, if you want to get all the brothers, you need to stop when
  // you hit node == this again.
  ETNode *Left, *Right;

  // First Son
  ETNode *Son;

  // Rightmost occurrence for this node
  ETOccurrence *RightmostOcc;

  // Parent occurrence for this node
  ETOccurrence *ParentOcc;
};
}  // end llvm namespace

#endif