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.HashSet;
016 import java.util.Iterator;
017 import org.jikesrvm.compilers.opt.ir.BasicBlock;
018 import org.jikesrvm.compilers.opt.ir.BasicBlockEnumeration;
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 BasicBlockEnumeration 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 BasicBlockEnumeration 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(BasicBlockEnumeration 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 public String toString() {
281 return super.toString() + " [Parent: " + parent + " SDom: " + semiDominator + " Dom: " + dominator + "]";
282 }
283 }