001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Eclipse Public License (EPL);
005     *  You may not use this file except in compliance with the License. You
006     *  may obtain a copy of the License at
007     *
008     *      http://www.opensource.org/licenses/eclipse-1.0.php
009     *
010     *  See the COPYRIGHT.txt file distributed with this work for information
011     *  regarding copyright ownership.
012     */
013    package org.jikesrvm.compilers.opt.controlflow;
014    
015    import java.util.Enumeration;
016    import java.util.HashSet;
017    import java.util.Iterator;
018    import org.jikesrvm.compilers.opt.ir.BasicBlock;
019    import org.jikesrvm.compilers.opt.ir.IR;
020    import org.jikesrvm.util.BitVector;
021    
022    /**
023     * This class holds data associated with a basic block as computed by the
024     * Lengauer-Tarjan dominator calculation.
025     * @see LTDominators
026     */
027    class LTDominatorInfo {
028      static final boolean DEBUG = false;
029    
030      private int semiDominator;
031      /** the immediate dominator */
032      private BasicBlock dominator;
033      private BasicBlock parent;
034      private final HashSet<BasicBlock> bucket;
035      private BasicBlock label;
036      private BasicBlock ancestor;
037      // Used to keep the trees balanced, during path compression
038      private int size;
039      private BasicBlock child;
040    
041      // used to capture activation record state to avoid the use of recursion
042      // in Step 1 of the LT algorithm
043      // A null value will signal that we have not started to process this
044      // block, otherwise, we'll skip the (redundant)
045      // initialization step for the block
046      //  See LTDominators.DFS() for details
047      private Enumeration<BasicBlock> bbEnum;
048    
049      /**
050       * @param block the basic block this info is associated with
051       */
052      LTDominatorInfo(BasicBlock block) {
053        semiDominator = 0;
054        dominator = null;
055        parent = null;
056        bucket = new HashSet<BasicBlock>();
057        ancestor = null;
058        label = block;
059        size = 1;
060        child = null;
061        bbEnum = null;
062      }
063    
064      /**
065       *   This method returns the set of blocks that dominates the passed
066       *   block, i.e., it answers the question "Who dominates me?"
067       *
068       *   @param block the block of interest
069       *   @param ir    the governing ir
070       *   @return a BitVector containing those blocks that dominate the passed one
071       */
072      public BitVector dominators(BasicBlock block, IR ir) {
073        // Currently this set is computed on demand.  We may want to cache
074        // the result for reuse.  The cost of computing is the height of the
075        // the dominator tree.
076        BitVector dominators = new BitVector(ir.getMaxBasicBlockNumber() + 1);
077        dominators.set(block.getNumber());
078        while ((block = getIdom(block)) != null) {
079          dominators.set(block.getNumber());
080        }
081        return dominators;
082      }
083    
084      /**
085       *   This method determines if the 1st parameter (block) is dominated by
086       *   the 2nd parameter (master), i.e., must control pass through "master"
087       *   before reaching "block"
088       *
089       *   @param block the block we care about
090       *   @param master the potential dominating block
091       *   @return whether master dominates block
092       */
093      public static boolean isDominatedBy(BasicBlock block, BasicBlock master) {
094        if (block == master) {
095          return true;
096        }
097        // walk up the dominator tree looking for the passed block
098        block = getIdom(block);
099        while (block != null && block != master) {
100          block = getIdom(block);
101        }
102        // If we found the master, the condition is true
103        return block == master;
104      }
105    
106      /**
107       * Sets the semidominator for this node
108       * @param value the new value
109       */
110      public void setSemiDominator(int value) {
111        semiDominator = value;
112      }
113    
114      /**
115       * Returns the semidomintor for this node
116       * @return the semidomintor for this node
117       */
118      public int getSemiDominator() {
119        return semiDominator;
120      }
121    
122      /**
123       * Sets the immediate dominator for this node
124       * @param value the value to set
125       */
126      public void setDominator(BasicBlock value) {
127        dominator = value;
128      }
129    
130      /**
131       * Returns the immediate dominator for this node
132       * @return the immediate dominator for this node
133       */
134      public BasicBlock getDominator() {
135        return dominator;
136      }
137    
138      /**
139       * Sets the parent of this block
140       * @param value the value
141       */
142      public void setParent(BasicBlock value) {
143        parent = value;
144      }
145    
146      /**
147       * Returns the parent of this block
148       * @return the parent of this block
149       */
150      public BasicBlock getParent() {
151        return parent;
152      }
153    
154      /**
155       * Returns an iterator over this block's bucket
156       * @return an iterator over this block's bucket
157       */
158      public Iterator<BasicBlock> getBucketIterator() {
159        return bucket.iterator();
160      }
161    
162      /**
163       * Removes the passed block from the bucket for this node
164       * @param block the block to remove from the bucket
165       */
166      public void removeFromBucket(BasicBlock block) {
167        bucket.remove(block);
168      }
169    
170      /**
171       * Adds the passed block from the bucket for this node
172       * @param block the block to add to our bucket
173       */
174      public void addToBucket(BasicBlock block) {
175        bucket.add(block);
176      }
177    
178      /**
179       * Sets the ancestor for the value passed
180       * @param value the ancestor value
181       */
182      public void setAncestor(BasicBlock value) {
183        ancestor = value;
184      }
185    
186      /**
187       * Returns the ancestor for this block
188       * @return the ancestor for this block
189       */
190      public BasicBlock getAncestor() {
191        return ancestor;
192      }
193    
194      /**
195       * sets the label
196       * @param value the label
197       */
198      public void setLabel(BasicBlock value) {
199        label = value;
200      }
201    
202      /**
203       * returns the label
204       * @return the label
205       */
206      public BasicBlock getLabel() {
207        return label;
208      }
209    
210      /**
211       * sets the size
212       * @param value the size
213       */
214      public void setSize(int value) {
215        size = value;
216      }
217    
218      /**
219       * returns the size
220       * @return the size
221       */
222      public int getSize() {
223        return size;
224      }
225    
226      /**
227       * sets the child field
228       * @param value the child value
229       */
230      public void setChild(BasicBlock value) {
231        child = value;
232      }
233    
234      /**
235       * returns the child
236       * @return the child
237       */
238      public BasicBlock getChild() {
239        return child;
240      }
241    
242      /**
243       * Helper method to return the Info field associated with a block
244       * @return the basic block enumeration, could be null
245       */
246      public Enumeration<BasicBlock> getEnum() {
247        return bbEnum;
248      }
249    
250      /**
251       * set the basic block enum field
252       * @param bbEnum basic block enum
253       */
254      public void setEnum(Enumeration<BasicBlock> bbEnum) {
255        this.bbEnum = bbEnum;
256      }
257    
258      /**
259       * Helper method to return the Info field associated with a block
260       * @param block the block of interest
261       * @return the LTInfo info
262       */
263      public static LTDominatorInfo getInfo(BasicBlock block) {
264        return (LTDominatorInfo) block.scratchObject;
265      }
266    
267      /**
268       * return the immediate dominator of a basic block.
269       * Note: the dominator info must be pre-calculated
270       * @param bb the basic block in question
271       * @return bb's immediate dominator
272       */
273      public static BasicBlock getIdom(BasicBlock bb) {
274        return getInfo(bb).dominator;
275      }
276    
277      /**
278       * Prints a string version of objection
279       */
280      @Override
281      public String toString() {
282        return super.toString() + " [Parent: " + parent + " SDom: " + semiDominator + " Dom: " + dominator + "]";
283      }
284    }