1 // LoopFinder.java, created Tue Jun 15 23:15:07 1999 by bdemsky
2 // Licensed under the terms of the GNU GPL; see COPYING for details.
3 // Copyright 1999 by Brian Demsky
5 package Analysis.Loops;
7 import IR.Flat.FlatMethod;
8 import IR.Flat.FlatNode;
9 import java.util.HashSet;
11 import java.util.Stack;
12 import java.util.Hashtable;
13 import java.util.Iterator;
15 * <code>LoopFinder</code> implements Dominator Tree Loop detection.
17 * @author Brian Demsky <bdemsky@mit.edu>
18 * @version $Id: LoopFinder.java,v 1.2 2009/03/27 09:02:25 bdemsky Exp $
21 public class LoopFinder implements Loops {
29 /** Creates a new LoopFinder object.
30 * This call takes an HCode and a CFGrapher
31 * and returns a LoopFinder object
35 public LoopFinder(FlatMethod hc) {
37 this.dominator=new DomTree(hc,false);
42 /**This method is for internal use only.
43 *It returns a Loopfinder object at any level,
44 *but it doesn't regenerate the internal tree
45 *so any external calls would result in garbage.*/
47 private LoopFinder(FlatMethod hc, DomTree dt, Loop root, Loop ptr) {
55 /*-----------------------------*/
57 /** This method returns the Root level loop for a given <code>HCode</code>.
58 * Does the same thing as the constructor call, but for an existing
59 * LoopFinder object.*/
61 public Loops getRootloop(FlatMethod hc) {
64 return new LoopFinder(hc,dominator,root,root);
67 /** This method returns the entry point of the loop.
68 * For the natural loops we consider, that is simply the header.
69 * It returns a <code>Set</code> of <code>HCodeElement</code>s.*/
71 public Set loopEntrances() {
72 HashSet entries=new HashSet();
74 entries.add(ptr.header);
79 /**Returns a <code>Set</code> with all of the <code>HCodeElement</code>s of the loop and
80 *loops included entirely within this loop. */
82 public Set loopIncElements() {
84 HashSet A=new HashSet(ptr.entries);
88 /** Returns all of the <code>HCodeElement</code>s of this loop that aren't in a nested
89 * loop. This returns a <code>Set</code> of <code>HCodeElement</code>s.*/
91 public Set loopExcElements() {
93 HashSet A=new HashSet(ptr.entries);
94 HashSet todo=new HashSet();
96 todo.addAll(ptr.children);
99 while(!todo.isEmpty()) {
100 Loop currptr=(Loop)todo.iterator().next();
101 todo.remove(currptr);
102 todo.addAll(currptr.children);
103 A.removeAll(currptr.entries);
108 /** Returns a <code>Set</code> of loops that are nested inside of this loop.*/
110 public Set nestedLoops() {
112 HashSet L=new HashSet();
113 Iterator iterate=ptr.children.iterator();
114 while (iterate.hasNext())
115 L.add(new LoopFinder(hc,dominator,root,(Loop) iterate.next()));
119 /** Returns the <code>Loops</code> that contains this loop.
120 * If this is the top level loop, this call returns a null pointer.*/
122 public Loops parentLoop() {
124 if (ptr.parent!=null)
125 return new LoopFinder(hc,dominator,root,ptr.parent);
129 /*---------------------------*/
130 // public information accessor methods.
132 /*---------------------------*/
136 /** Main analysis method. */
139 //Have we analyzed this set before?
140 //If so, don't do it again!!!
143 //Did the caller hand us a bogus object?
144 //If so, throw it something
148 //Set up the top level loop, so we can fill it with HCodeElements
153 //Set up a WorkSet for storing loops before we build the
155 setofloops=new HashSet();
160 //Build the nested loop tree
167 //go through set of generated loops
168 while(!setofloops.isEmpty()) {
170 Loop A=(Loop) setofloops.iterator().next();
171 setofloops.remove(A);
173 //Add it to the tree, complain if oddness
174 if (addnode(A, root)!=1)
175 System.out.println("Evil Error in LoopFinder while building tree.");
179 //Adds a node to the tree...Its recursive
181 int addnode(Loop A, Loop treenode) {
182 //Only need to go deeper if the header is contained in this loop
183 if (treenode.entries.contains(A.header))
185 //Do we share headers?
186 if (treenode.header!=A.header) {
188 //No... Loop through our children to see if they want this
191 //Use integers for tri-state:
192 //0=not stored here, 1=stored and everything is good
193 //2=combined 2 natural loops with same header...need cleanup
196 Iterator iterate=treenode.children.iterator();
197 Loop temp=new Loop();
198 while (iterate.hasNext()) {
199 temp=(Loop) iterate.next();
200 stored=addnode(A,temp);
201 if (stored!=0) break;
204 //See what our children did for us
207 //We get a new child...
208 treenode.children.add(A);
212 //Need to do cleanup for case 0 or 2
213 //temp points to the new child
217 //Have to make sure that none of the nodes under this one
218 //are children of the new node
220 Iterator iterate2=treenode.children.iterator();
221 temp.parent=treenode;
223 //Loop through the children
224 while (iterate2.hasNext()) {
225 Loop temp2=(Loop)iterate2.next();
227 //Don't look at the new node...otherwise we will create
228 //a unreachable subtree
231 //If the new node has a childs header
232 //give the child up to it...
234 if (temp.entries.contains(temp2.header)) {
235 temp.children.add(temp2);
241 //We fixed everything...let our parents know
244 //need to combine loops
245 while (!A.entries.isEmpty()) {
246 FlatNode node=(FlatNode)A.entries.iterator().next();
247 A.entries.remove(node);
248 treenode.entries.add(node);
250 //let the previous caller know that they have stuff todo
253 //We aren't adopting the new node
257 void findloopheaders(FlatNode current_nodeOrig) {
258 Stack stk = new Stack();
259 stk.push( current_nodeOrig );
260 while( ! stk.isEmpty() ){
261 FlatNode current_node = (FlatNode) stk.pop();
262 //look at the current node
265 //add it to the all inclusive root loop
266 root.entries.add(current_node);
268 //See if those we dominate are backedges
269 stk.addAll(dominator.children(current_node));
273 void visit(FlatNode q) {
275 HashSet B=new HashSet();
277 //Loop through all of our outgoing edges
278 for (int i=0;i<q.numNext();i++) {
280 FlatNode temp_to=q.getNext(i);
282 //Go up the dominator tree until
283 //we hit the root element or we
284 //find the node we jump back too
287 temp=dominator.idom(temp);
290 //If we found the node we jumped back to
296 A.entries.add(temp); //Push the header
298 B.add(q); //Put the backedge in the todo list
300 //Starting with the backedge, work on the incoming edges
301 //until we get back to the loop header...
302 //Then we have the entire natural loop
304 while(!B.isEmpty()) {
305 FlatNode newnode=(FlatNode)B.iterator().next();
308 //Add all of the new incoming edges that we haven't already
310 for (int j=0;j<newnode.numPrev();j++) {
311 FlatNode from=newnode.getPrev(j);
312 if (!A.entries.contains(from))
316 //push the new node on our list of nodes in the loop
317 A.entries.add(newnode);
326 //Structure for building internal trees...
329 public HashSet entries=new HashSet();
330 public FlatNode header;
331 //Elements of the WorkSet of children are
333 public HashSet children=new HashSet();