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.ir; 014 015import java.util.Enumeration; 016 017import org.jikesrvm.VM; 018import org.jikesrvm.compilers.opt.util.SortedGraphNode; 019import org.jikesrvm.compilers.opt.util.SpaceEffGraph; 020import org.jikesrvm.compilers.opt.util.SpaceEffGraphNode; 021 022/** 023 * The Factored Control Flow Graph (FCFG). 024 * <p> 025 * Like a standard control flow graph (CFG), the FCFG is composed 026 * of {@link BasicBlock basic blocks} which in turn contain 027 * {@link Instruction instructions}. The critical difference between 028 * a FCFG and a CFG is in the definition of basic blocks. In the FCFG, 029 * a Potentially Excepting Instruction (PEI) does not necessarily end its 030 * basic block. Therefore, although instructions within a FCFG basic block 031 * have the expected dominance relationships, they do <em>not</em> have the 032 * same post-dominance relationships as they would under the traditional 033 * basic block formulation used in a CFG. 034 * We chose to use an FCFG because doing so significantly reduces the 035 * number of basic blocks and control flow graph edges, thus reducing 036 * the time and space costs of representing the FCFG and also 037 * increasing the effectiveness of local (within a single basic block) 038 * analysis. However, using an FCFG does complicate flow-sensitive 039 * global analaysis. Many analyses can be easily extended to 040 * work on the FCFG. For those analyses that cannot, we provide utilities 041 * ({@link IR#unfactor()}, {@link BasicBlock#unfactor(IR)}) 042 * to effectively convert the FCFG into a CFG. 043 * For a more detailed description of the FCFG and its implications for 044 * program analysis see the PASTE'99 paper by Choi et al. 045 * <a href="http://www.research.ibm.com/jalapeno/publication.html#paste99"> 046 * Efficient and Precise Modeling of Exceptions for the Analysis of Java Programs </a> 047 * <p> 048 * The nodes in the FCFG are components in two distinct 049 * orderings, the "main" one is the control flow relationship 050 * in which edges represent flow of control. 051 * The secondary ordering is a linearization of the blocks 052 * which represents the ordering of instructions in the generated code. 053 * Both of these relationships are represented using the fields inherited 054 * from {@link SpaceEffGraphNode}. 055 * The control flow edges are the primary relationship and are encoded by 056 * <code>In</code> and <code>Out</code> relations of 057 * {@link SpaceEffGraphNode} and the {@link #entry()} and {@link #exit()} 058 * functions of <code>ControlFlowGraph</code>. 059 * The linear order is secondary and is represented by the order of the 060 * nodes in the doubly linked list ({@link SpaceEffGraphNode#next} and 061 * {@link SpaceEffGraphNode#prev}) and the functions 062 * ({@link #firstInCodeOrder()}, {@link #lastInCodeOrder()}) 063 * of <code>ControlFlowGraph</code>. 064 * Utility functions are provided here and in {@link SpaceEffGraphNode} 065 * to manipulate these orderings. 066 * <p> 067 * Note: Clients that add or remove nodes must call {@link #compactNodeNumbering()} 068 * after they are done with the modifications to ensure that subsequent compiler phases 069 * can use the node numbering to index lookaside data structures for basic blocks. 070 * 071 * @see BasicBlock 072 * @see IR 073 */ 074public final class ControlFlowGraph extends SpaceEffGraph { 075 076 /** 077 * The distinguished exit node of the FCFG 078 */ 079 private final BasicBlock _exitNode; 080 081 /** 082 * Return the entry node of the FCFG. All reachable nodes 083 * can be found by doing a forward traversal from this node. 084 * 085 * @return the entry node of the FCFG 086 */ 087 public BasicBlock entry() { 088 return (BasicBlock) _firstNode; 089 } 090 091 /** 092 * Return the "exit" node of the FCFG. In a perfect world, 093 * we'd have the invariant that all nodes that are reachable in a 094 * forward traversal from cfgEntry() are exactly the same set of nodes 095 * as those that are reachable from cfgExit() via a reverse traversal, 096 * but that's currently not the case. Not all forward reachable nodes can 097 * be found by going backwards from exit. The issue is infinite loops 098 * (loops without normal exits). 099 * 100 * @return the exit node of the FCFG 101 */ 102 public BasicBlock exit() { 103 return _exitNode; 104 } 105 106 /** 107 * Return the first basic block with respect to 108 * the current code linearization order. 109 * 110 * @return the first basic block in the code order 111 */ 112 public BasicBlock firstInCodeOrder() { 113 return (BasicBlock) _firstNode; 114 } 115 116 /** 117 * Return the last basic block with respect to 118 * the current code linearization order. 119 * 120 * @return the last basic block in the code order 121 */ 122 public BasicBlock lastInCodeOrder() { 123 return (BasicBlock) _lastNode; 124 } 125 126 /** 127 * Return the node to start with for a topological traversal 128 * of the FCFG. 129 * Override {@link SpaceEffGraph#startNode(boolean)} 130 * to use entry and exit; we want topological traversals to be with 131 * respect to FCFG edges not the code linearization order 132 * 133 * @param forward {@code true} for forward traversal, {@code false} for reverse 134 * @return the node to use as the start of a topological traversal 135 */ 136 @Override 137 public SortedGraphNode startNode(boolean forward) { 138 if (forward) { 139 return entry(); 140 } else { 141 return exit(); 142 } 143 } 144 145 /** 146 * Densely numbers (0...n) all nodes in the FCFG. 147 * <p> 148 * Note: clients must call this method after they are done with adding 149 * or removing nodes. This allows subsequent phases to save additional 150 * information about BasicBlocks in arrays by using the node number 151 * as index. 152 * <p> 153 * This method overrides {@link SpaceEffGraph#compactNodeNumbering()} to also 154 * number the exit node. 155 */ 156 @Override 157 public void compactNodeNumbering() { 158 super.compactNodeNumbering(); 159 exit().setNumber(numberOfNodes++); 160 } 161 162 /** 163 * Builds the reverse topological order, i.e., the topsort order on the 164 * reverse graph. (This is not the same as reversing the topsort order 165 * of the forward graph.) 166 * 167 * @return the first node in the reverse topological ordering 168 */ 169 @Override 170 public SortedGraphNode buildRevTopSort() { 171 SortedGraphNode firstNode = super.buildRevTopSort(); 172 if (firstNode != null) { 173 174 // The CFG may have "end" nodes that are not reachable 175 // by all nodes. For example, a program with an infinite loop will not 176 // have a path from the loop to the exit node. Such nodes will not 177 // be in the reverseTopSort, but will be of interest. Thus, we now 178 // look for such nodes and add them to the revTopSort. 179 180 // We do this by visiting each basic block and checking to ensure 181 // that is marked with the sortMarker, if not we simply give it a 182 // number. 183 184 int sortMarker = firstNode.getSortMarker(); 185 int sortNumber = firstNode.getBackwardSortNumber() - 1; 186 for (BasicBlock block = firstInCodeOrder(); block != null; block = block.nextBasicBlockInCodeOrder()) { 187 188 if (block.getSortMarker() != sortMarker) { 189 // found a block that wasn't on the Reverse Top List, add it. 190 // It is not clear where it should go, so since it is convenient 191 // to add at the front, we add it at the front! 192 block.setSortMarker(sortMarker); 193 block.setBackwardSortNumber(sortNumber--); 194 195 // put block at the beginning of the list 196 block.setSortedNext(firstNode, false); 197 firstNode = block; 198 } 199 } 200 } 201 return firstNode; 202 } 203 204 /** 205 * @param number starting value for assigning node numbers 206 */ 207 public ControlFlowGraph(int number) { 208 _exitNode = BasicBlock.makeExit(); 209 numberOfNodes = number; 210 } 211 212 /** 213 * Add an FCFG edge from the given basic block to the exit node. 214 * 215 * @param bb basic block to link to the exit 216 */ 217 public void linkToExit(BasicBlock bb) { 218 bb.insertOut(exit()); 219 } 220 221 /** 222 * Remove a basic block from both the CFG and code ordering 223 * 224 * @param bb the block to remove 225 */ 226 public void removeFromCFGAndCodeOrder(BasicBlock bb) { 227 removeFromCFG(bb); 228 removeFromCodeOrder(bb); 229 } 230 231 /** 232 * Remove a basic block from the FCFG, leaving the code ordering unchanged. 233 * 234 * @param bb the block to remove 235 */ 236 public void removeFromCFG(BasicBlock bb) { 237 bb.deleteIn(); 238 bb.deleteOut(); 239 } 240 241 /** 242 * Remove a basic block from the code ordering, 243 * leaving the FCFG unchanged. 244 * 245 * @param bb the block to remove 246 */ 247 public void removeFromCodeOrder(BasicBlock bb) { 248 if (bb == _firstNode) { 249 _firstNode = bb.getNext(); 250 } 251 if (bb == _lastNode) { 252 _lastNode = bb.getPrev(); 253 } 254 bb.remove(); 255 } 256 257 /** 258 * Insert a block 'toAdd' not currently in the code ordering after 259 * a block 'old' that is currently in the code ordering. 260 * If necessary, _lastNode is updated. 261 * No impact on FCFG edges. 262 * 263 * @param old a block currently in the code ordering 264 * @param toAdd a block to add after old in the code ordering 265 */ 266 public void insertAfterInCodeOrder(BasicBlock old, BasicBlock toAdd) { 267 if (IR.SANITY_CHECK) VM._assert(toAdd.next == null); 268 if (IR.SANITY_CHECK) VM._assert(toAdd.prev == null); 269 SpaceEffGraphNode oldNext = old.next; 270 if (oldNext == null) { 271 if (IR.SANITY_CHECK) VM._assert(_lastNode == old); 272 old.append(toAdd); 273 _lastNode = toAdd; 274 } else { 275 old.append(toAdd); 276 toAdd.append(oldNext); 277 } 278 } 279 280 /** 281 * Insert a block 'toAdd' not currently in the code ordering before 282 * a block 'old' that is currently in the code ordering. 283 * If necessary, _firstNode is updated. 284 * No impact on FCFG edges. 285 * 286 * @param old a block currently in the code ordering 287 * @param toAdd a block to add before old in the code ordering 288 */ 289 public void insertBeforeInCodeOrder(BasicBlock old, BasicBlock toAdd) { 290 if (IR.SANITY_CHECK) VM._assert(toAdd.next == null); 291 if (IR.SANITY_CHECK) VM._assert(toAdd.prev == null); 292 SpaceEffGraphNode oldPrev = old.prev; 293 if (oldPrev == null) { 294 if (IR.SANITY_CHECK) VM._assert(_firstNode == old); 295 _firstNode = toAdd; 296 toAdd.append(old); 297 } else { 298 oldPrev.append(toAdd); 299 toAdd.append(old); 300 } 301 } 302 303 /** 304 * Add a block not currently in the code ordering to the end of the 305 * code ordering. 306 * No impact on FCFG edges. 307 * 308 * @param bb the block to add to the end of the code ordering 309 */ 310 public void addLastInCodeOrder(BasicBlock bb) { 311 if (IR.SANITY_CHECK) VM._assert(bb.next == null); 312 if (IR.SANITY_CHECK) VM._assert(bb.prev == null); 313 if (_firstNode == null) { 314 _firstNode = bb; 315 _lastNode = bb; 316 } else { 317 _lastNode.append(bb); 318 _lastNode = bb; 319 } 320 } 321 322 /** 323 * Make BB2 follow BB1 in the code ordering. 324 * If _lastNode == BB1, then update _lastNode appropriately 325 * No impact on FCFG edges. 326 * 327 * @param bb1 a basic block 328 * @param bb2 the basic block to follow bb1 in the code ordering 329 */ 330 public void linkInCodeOrder(BasicBlock bb1, BasicBlock bb2) { 331 if (IR.SANITY_CHECK) VM._assert(bb1.next == null); 332 if (IR.SANITY_CHECK) VM._assert(bb2.prev == null); 333 bb1.append(bb2); 334 if (bb1 == _lastNode) { 335 _lastNode = bb2; 336 } 337 } 338 339 /** 340 * Create a break in the code order between bb1 and bb2 341 * (bb1 and bb2 must be currently adjacent in the code order). 342 * No impact on FCFG edges. 343 * 344 * @param bb1 the first block 345 * @param bb2 the second block 346 */ 347 public void breakCodeOrder(BasicBlock bb1, BasicBlock bb2) { 348 if (IR.SANITY_CHECK) VM._assert(bb1.next == bb2); 349 if (IR.SANITY_CHECK) VM._assert(bb2.prev == bb1); 350 bb1.next = null; 351 bb2.prev = null; 352 } 353 354 /** 355 * Clear the code ordering information for the CFG.<p> 356 * NOTE: This method should only be called as part of a 357 * whole scale recomputation of the code order, for example 358 * by ReorderingPhase 359 */ 360 public void clearCodeOrder() { 361 SpaceEffGraphNode cur = _firstNode; 362 if (cur == null) return; 363 while (true) { 364 SpaceEffGraphNode next = cur.next; 365 if (next == null) break; 366 cur.next = null; 367 next.prev = null; 368 cur = next; 369 } 370 _firstNode = null; 371 _lastNode = null; 372 } 373 374 // Enumerate the nodes in the CFG, casting them to whatever concrete type 375 // the caller wants. 376 private static final class NodeEnumeration<T> implements Enumeration<T> { 377 private SpaceEffGraphNode _node; 378 private final SpaceEffGraphNode _end; 379 380 NodeEnumeration(ControlFlowGraph cfg) { 381 _node = cfg.entry(); 382 _end = cfg.exit(); 383 } 384 385 @Override 386 public boolean hasMoreElements() { 387 return _node != null; 388 } 389 390 @Override 391 @SuppressWarnings("unchecked") 392 // We cast to whatever the concrete type of the graph is 393 public T nextElement() { 394 SpaceEffGraphNode n = _node; 395 _node = n.getNext(); 396 if ((n != _end) && (_node == null)) { 397 _node = _end; 398 } 399 return (T) n; 400 } 401 } 402 403 public Enumeration<BasicBlock> basicBlocks() { 404 return new NodeEnumeration<BasicBlock>(this); 405 } 406}