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