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 017 import org.jikesrvm.compilers.opt.ir.BasicBlock; 018 import org.jikesrvm.compilers.opt.ir.IR; 019 import org.jikesrvm.compilers.opt.util.Tree; 020 import org.jikesrvm.compilers.opt.util.TreeNode; 021 import org.jikesrvm.util.BitVector; 022 023 /** 024 * This class provides the abstraction of a dominator tree 025 * 026 * <p>TODO: we do not support IRs with exception handlers. 027 */ 028 public class DominatorTree extends Tree { 029 /** 030 * {@code true} if we are computing regular dominators, {@code false} for post-dominators 031 */ 032 private final boolean forward; 033 034 /** 035 * The governing IR 036 */ 037 private final IR ir; 038 039 /** 040 * A structure used to quickly index into the DominatorVertex tree 041 */ 042 private DominatorTreeNode[] dominatorInfoMap; 043 044 /** 045 * Build a dominator tree from an IR. NOTE: the dominator 046 * information MUST be computed BEFORE calling this method! 047 * We assume the scratch object of each basic block contains 048 * the LTDominatorInfo object holding this information. 049 * 050 * @param ir the governing IR 051 * @param forward are we building regular dominators or post-dominators? 052 */ 053 public static void perform(IR ir, boolean forward) { 054 // control for debugging messages. 055 final boolean DEBUG = false; 056 057 if (forward) { 058 ir.HIRInfo.dominatorTree = new DominatorTree(ir, forward); 059 if (ir.options.PRINT_DOMINATORS) { 060 if (DEBUG) { 061 System.out.println("Here is the CFG for method " + ir.method.getName() + "\n" + ir.cfg); 062 } 063 System.out.println("Here is the Dominator Tree for method " + 064 ir.method.getName() + "\n" + 065 ir.HIRInfo.dominatorTree); 066 } 067 } else { 068 ir.HIRInfo.postDominatorTree = new DominatorTree(ir, forward); 069 if (ir.options.PRINT_POST_DOMINATORS) { 070 if (DEBUG) { 071 System.out.println("Here is the CFG for method " + ir.method.getName() + "\n" + ir.cfg); 072 } 073 System.out.println("Here is the Post-Dominator Tree for method " + 074 ir.method.getName() + "\n" + 075 ir.HIRInfo.postDominatorTree); 076 } 077 } 078 } 079 080 /** 081 * Build a dominator tree from an IR. NOTE: the dominator 082 * information MUST be computed BEFORE calling this 083 * constructor! 084 * 085 * @param ir the governing IR 086 * @param forward are we building regular dominators or post-dominators? 087 */ 088 public DominatorTree(IR ir, boolean forward) { 089 this.ir = ir; 090 this.forward = forward; 091 092 // The query methods of dominator information, such as 093 // getDominanceFrontier, dominates, and domFrontierEnumerator 094 // all use ir.getBasicBlock(int). This method relies on 095 // the basic block map being up to date. Here we ensure this 096 // property, even though it is needed for computing the dominator 097 // tree. 098 ir.resetBasicBlockMap(); 099 100 // allocate the dominator vertex map 101 dominatorInfoMap = new DominatorTreeNode[ir.getMaxBasicBlockNumber() + 1]; 102 103 // allocate the tree and root node 104 // Step 1: add all basic blocks to the tree as nodes 105 for (Enumeration<BasicBlock> bbEnum = ir.cfg.basicBlocks(); bbEnum.hasMoreElements();) { 106 BasicBlock block = bbEnum.nextElement(); 107 // We treat the exit node as not being part of the CFG 108 if (!forward || !block.isExit()) { 109 addNode(block); 110 } 111 } 112 113 // Step 2: set the root value 114 setRoot(dominatorInfoMap[getFirstNode().getNumber()]); 115 116 // Step 3: Walk the nodes, for each node create link with parent 117 // Leaf nodes have no links to add 118 for (Enumeration<BasicBlock> bbEnum = ir.cfg.basicBlocks(); bbEnum.hasMoreElements();) { 119 BasicBlock block = bbEnum.nextElement(); 120 // skip the exit node 121 if (forward && block.isExit()) { 122 continue; 123 } 124 125 // get the tree node corresponding to "block" 126 DominatorTreeNode blockNode = dominatorInfoMap[block.getNumber()]; 127 128 // if parent = null, this is the root of the tree, nothing to do 129 if (LTDominatorInfo.getInfo(block) == null) { 130 System.out.println("info field is null for block: " + block); 131 } 132 BasicBlock parent = LTDominatorInfo.getInfo(block).getDominator(); 133 if (parent != null) { 134 DominatorTreeNode parentNode = dominatorInfoMap[parent.getNumber()]; 135 136 // tell the parent they have a child 137 parentNode.addChild(blockNode); 138 } 139 } // for loop 140 } // method 141 142 /** 143 * Get the first node, either entry or exit 144 * depending on which way we are viewing the graph 145 * @return the entry node or exit node 146 */ 147 private BasicBlock getFirstNode() { 148 if (forward) { 149 return ir.cfg.entry(); 150 } else { 151 return ir.cfg.exit(); 152 } 153 } 154 155 /** 156 * Enumerate the children of the vertex corresponding to a basic 157 * block 158 * 159 * @param bb the basic block 160 * @return an Enumeration of bb's children 161 */ 162 public Enumeration<TreeNode> getChildren(BasicBlock bb) { 163 DominatorTreeNode node = dominatorInfoMap[bb.getNumber()]; 164 return node.getChildren(); 165 } 166 167 /** 168 * Return the parent of the vertex corresponding to a basic 169 * block 170 * 171 * @param bb the basic block 172 * @return bb's parent 173 */ 174 public BasicBlock getParent(BasicBlock bb) { 175 DominatorTreeNode node = dominatorInfoMap[bb.getNumber()]; 176 return ((DominatorTreeNode) node.getParent()).getBlock(); 177 } 178 179 /** 180 * Return the (already calculated) dominance frontier for 181 * a basic block 182 * 183 * @param bb the basic block 184 * @return a BitVector representing the dominance frontier 185 */ 186 public BitVector getDominanceFrontier(BasicBlock bb) { 187 DominatorTreeNode info = dominatorInfoMap[bb.getNumber()]; 188 return info.getDominanceFrontier(); 189 } 190 191 /** 192 * Return the (already calculated) dominance frontier for 193 * a basic block 194 * 195 * @param number the number of the basic block 196 * @return a BitVector representing the dominance frontier 197 */ 198 public BitVector getDominanceFrontier(int number) { 199 return getDominanceFrontier(ir.getBasicBlock(number)); 200 } 201 202 /** 203 * Does basic block number b dominate all basic blocks in a set? 204 * 205 * @param b the number of the basic block to test 206 * @param bits BitVector representation of the set of basic blocks to test 207 * @return true or false 208 */ 209 public boolean dominates(int b, BitVector bits) { 210 for (int i = 0; i < bits.length(); i++) { 211 if (!bits.get(i)) { 212 continue; 213 } 214 if (!dominates(b, i)) { 215 return false; 216 } 217 } 218 return true; 219 } 220 221 /** 222 * Does basic block number "master" dominate basic block number "slave"? 223 * 224 * @param master the number of the proposed "master" basic block 225 * @param slave the number of the proposed "slave block 226 * @return "master dominates slave" 227 */ 228 public boolean dominates(int master, int slave) { 229 BasicBlock masterBlock = ir.getBasicBlock(master); 230 BasicBlock slaveBlock = ir.getBasicBlock(slave); 231 DominatorTreeNode masterNode = dominatorInfoMap[masterBlock.getNumber()]; 232 DominatorTreeNode slaveNode = dominatorInfoMap[slaveBlock.getNumber()]; 233 return slaveNode.isDominatedBy(masterNode); 234 } 235 236 /** 237 * Does basic block number "master" dominate basic block number "slave"? 238 * 239 * @param master the number of the proposed "master" basic block 240 * @param slave the number of the proposed "slave block 241 * @return "master dominates slave" 242 */ 243 public boolean dominates(BasicBlock master, BasicBlock slave) { 244 DominatorTreeNode masterNode = dominatorInfoMap[master.getNumber()]; 245 DominatorTreeNode slaveNode = dominatorInfoMap[slave.getNumber()]; 246 return slaveNode.isDominatedBy(masterNode); 247 } 248 249 /** 250 * Creates dominator tree nodes for the passed block and adds them to the 251 * map. 252 * @param b the basic block 253 */ 254 private void addNode(BasicBlock b) { 255 DominatorTreeNode node = new DominatorTreeNode(b); 256 dominatorInfoMap[b.getNumber()] = node; 257 } 258 259 /** 260 * Return the distance from the root of the dominator tree to a given 261 * basic block 262 * 263 * @param b the basic block in question 264 * @return <code>b</code>'s depth 265 */ 266 public int depth(BasicBlock b) { 267 return dominatorInfoMap[b.getNumber()].getDepth(); 268 } 269 270 /** 271 * Return the deepest common dominance ancestor of blocks <code>a</code> and <code>b</code> 272 * 273 * @param a The first basic block 274 * @param b The second basic block 275 * @return the deepest common dominance ancestor of blocks <code>a</code> 276 * and <code>b</code> 277 */ 278 public BasicBlock deepestCommonAncestor(BasicBlock a, BasicBlock b) { 279 DominatorTreeNode n_a = dominatorInfoMap[a.getNumber()]; 280 DominatorTreeNode n_b = dominatorInfoMap[b.getNumber()]; 281 while (n_a != n_b) { 282 if (n_a.getDepth() > n_b.getDepth()) { 283 n_a = (DominatorTreeNode) n_a.getParent(); 284 } else { 285 n_b = (DominatorTreeNode) n_b.getParent(); 286 } 287 } 288 return n_a.getBlock(); 289 } 290 291 }