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.depgraph; 014 015import static org.jikesrvm.compilers.opt.depgraph.DepGraphConstants.CONTROL; 016import static org.jikesrvm.compilers.opt.depgraph.DepGraphConstants.EXCEPTION_E; 017import static org.jikesrvm.compilers.opt.depgraph.DepGraphConstants.EXCEPTION_MS; 018import static org.jikesrvm.compilers.opt.depgraph.DepGraphConstants.EXCEPTION_R; 019import static org.jikesrvm.compilers.opt.depgraph.DepGraphConstants.GUARD_ANTI; 020import static org.jikesrvm.compilers.opt.depgraph.DepGraphConstants.GUARD_OUTPUT; 021import static org.jikesrvm.compilers.opt.depgraph.DepGraphConstants.GUARD_TRUE; 022import static org.jikesrvm.compilers.opt.depgraph.DepGraphConstants.MEM_ANTI; 023import static org.jikesrvm.compilers.opt.depgraph.DepGraphConstants.MEM_OUTPUT; 024import static org.jikesrvm.compilers.opt.depgraph.DepGraphConstants.MEM_READS_KILL; 025import static org.jikesrvm.compilers.opt.depgraph.DepGraphConstants.MEM_TRUE; 026import static org.jikesrvm.compilers.opt.depgraph.DepGraphConstants.REG_ANTI; 027import static org.jikesrvm.compilers.opt.depgraph.DepGraphConstants.REG_MAY_DEF; 028import static org.jikesrvm.compilers.opt.depgraph.DepGraphConstants.REG_OUTPUT; 029import static org.jikesrvm.compilers.opt.depgraph.DepGraphConstants.REG_TRUE; 030import static org.jikesrvm.compilers.opt.ir.Operators.GET_CAUGHT_EXCEPTION; 031import static org.jikesrvm.compilers.opt.ir.Operators.GET_TIME_BASE; 032import static org.jikesrvm.compilers.opt.ir.Operators.IR_PROLOGUE; 033import static org.jikesrvm.compilers.opt.ir.Operators.SET_CAUGHT_EXCEPTION; 034import static org.jikesrvm.compilers.opt.ir.Operators.UNINT_BEGIN; 035import static org.jikesrvm.compilers.opt.ir.Operators.UNINT_END; 036 037import java.util.Enumeration; 038 039import org.jikesrvm.compilers.opt.ir.BasicBlock; 040import org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock; 041import org.jikesrvm.compilers.opt.ir.GenericPhysicalDefUse; 042import org.jikesrvm.compilers.opt.ir.IR; 043import org.jikesrvm.compilers.opt.ir.Instruction; 044import org.jikesrvm.compilers.opt.ir.LocationCarrier; 045import org.jikesrvm.compilers.opt.ir.Operator; 046import org.jikesrvm.compilers.opt.ir.Register; 047import org.jikesrvm.compilers.opt.ir.operand.LocationOperand; 048import org.jikesrvm.compilers.opt.ir.operand.Operand; 049import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; 050import org.jikesrvm.compilers.opt.liveness.LiveSet; 051import org.jikesrvm.compilers.opt.util.SpaceEffGraph; 052 053/** 054 * Dependence Graph for a single basic block in the program. 055 */ 056public class DepGraph extends SpaceEffGraph { 057 058 /** 059 * Set of variables that are live on entry to at least one catch block that 060 * is reachable via a PEI in currentBlock. 061 * This is an approximation of the more precise set, but can be done in 062 * linear time; doing the most precise thing (computing the set for 063 * every PEI and using each individual set to create the necessary 064 * dependences) is quadratic, and probably doesn't help very much anyways. 065 */ 066 private final LiveSet handlerLiveSet; 067 068 /** 069 * The basic block we are processing 070 */ 071 private final BasicBlock currentBlock; 072 073 /** 074 * The IR we are processing 075 */ 076 private final IR ir; 077 078 private final DepGraphNode[] depGraphNodes; 079 080 /** 081 * Constructor (computes the dependence graph!). 082 * 083 * @param ir the IR to compute the dependence graph for 084 * @param start instruction to start computation from 085 * @param end instruction to end computation at 086 * @param currentBlock the basic block that the instructions are living in 087 */ 088 public DepGraph(IR ir, Instruction start, Instruction end, BasicBlock currentBlock) { 089 this.currentBlock = currentBlock; 090 this.ir = ir; 091 this.depGraphNodes = new DepGraphNode[ir.regpool.getTotalNumberOfRegisters()]; 092 handlerLiveSet = new LiveSet(); 093 computeHandlerLiveSet(); 094 createNodes(start, end); 095 computeForwardDependences(start, end); 096 computeBackwardDependences(start, end); 097 computeControlAndBarrierDependences(start, end); 098 } 099 100 private DepGraphNode getDepGraphNode(Register r) { 101 return depGraphNodes[r.number]; 102 } 103 104 private void setDepGraphNodeForRegister(DepGraphNode dNode, Register r) { 105 depGraphNodes[r.number] = dNode; 106 } 107 108 private void clearDepGraphNodeForRegister(Register r) { 109 setDepGraphNodeForRegister(null, r); 110 } 111 112 /** 113 * Determine the set of variables live on entry to any handler 114 * block that is reachable from currentBlock 115 */ 116 private void computeHandlerLiveSet() { 117 if (ir.getHandlerLivenessComputed() && currentBlock.hasExceptionHandlers()) { 118 Enumeration<BasicBlock> e = currentBlock.getExceptionalOut(); 119 while (e.hasMoreElements()) { 120 ExceptionHandlerBasicBlock handlerBlock = (ExceptionHandlerBasicBlock) e.nextElement(); 121 handlerLiveSet.add(handlerBlock.getLiveSet()); 122 } 123 } 124 } 125 126 private void createNodes(Instruction start, Instruction end) { 127 for (Instruction p = start; ; p = p.nextInstructionInCodeOrder()) { 128 DepGraphNode pnode = createDepGraphNode(p); 129 addGraphNode(pnode); 130 if (p == end) { 131 break; 132 } 133 } 134 } 135 136 protected DepGraphNode createDepGraphNode(Instruction p) { 137 return new DepGraphNode(p); 138 } 139 140 /** 141 * Computes flow and output dependences by doing a forward 142 * traversal of the instructions from start to end. 143 * 144 * @param start start instruction 145 * @param end end instruction 146 */ 147 private void computeForwardDependences(Instruction start, Instruction end) { 148 boolean readsKill = ir.options.READS_KILL; 149 DepGraphNode lastStoreNode = null; 150 DepGraphNode lastExceptionNode = null; 151 DepGraphNode lastLoadNode = null; // only used if reads kill 152 153 clearRegisters(start, end); 154 155 for (DepGraphNode pnode = (DepGraphNode) firstNode(); pnode != null; pnode = 156 (DepGraphNode) pnode.getNext()) { 157 Instruction p = pnode.instruction(); 158 159 // (1) Add edges due to registers 160 int useMask = p.operator().implicitUses; 161 int defMask = p.operator().implicitDefs; 162 if (p.isTSPoint()) { 163 useMask |= GenericPhysicalDefUse.getMaskTSPUses(); 164 defMask |= GenericPhysicalDefUse.getMaskTSPDefs(); 165 } 166 for (Enumeration<Operand> uses = p.getUses(); uses.hasMoreElements();) { 167 computeForwardDependencesUse(uses.nextElement(), pnode, lastExceptionNode); 168 } 169 for (Enumeration<Register> uses = GenericPhysicalDefUse.enumerate(useMask, ir); uses.hasMoreElements();) { 170 Register r = uses.nextElement(); 171 computeImplicitForwardDependencesUse(r, pnode); 172 } 173 for (Enumeration<Operand> defs = p.getDefs(); defs.hasMoreElements();) { 174 computeForwardDependencesDef(defs.nextElement(), pnode, lastExceptionNode); 175 } 176 for (Enumeration<Register> defs = GenericPhysicalDefUse.enumerate(defMask, ir); defs.hasMoreElements();) { 177 Register r = defs.nextElement(); 178 computeImplicitForwardDependencesDef(r, pnode); 179 } 180 181 // (2) Add edges due to memory 182 boolean isStore = p.isImplicitStore(); 183 boolean isLoad = p.isImplicitLoad(); 184 if (isStore || isLoad) { 185 // If readsKill then add memory model memory dependence from prior load 186 // NOTE: In general alias relationships are not transitive and therefore 187 // we cannot exit this loop early. 188 if (readsKill && isLoad) { 189 for (DepGraphNode lnode = lastLoadNode; lnode != null; lnode = (DepGraphNode) lnode.getPrev()) { 190 if (lnode.instruction().isImplicitLoad() && 191 LocationOperand.mayBeAliased(getLocation(p), getLocation(lnode.instruction()))) { 192 lnode.insertOutEdge(pnode, MEM_READS_KILL); 193 } 194 } 195 lastLoadNode = pnode; 196 } 197 // Add output/flow memory dependence from prior potentially aliased stores. 198 // NOTE: In general alias relationships are not transitive and therefore 199 // we cannot exit this loop early. 200 for (DepGraphNode snode = lastStoreNode; snode != null; snode = (DepGraphNode) snode.getPrev()) { 201 if (snode.instruction().isImplicitStore() && 202 LocationOperand.mayBeAliased(getLocation(p), getLocation(snode.instruction()))) { 203 snode.insertOutEdge(pnode, isStore ? MEM_OUTPUT : MEM_TRUE); 204 } 205 } 206 if (isStore) { 207 lastStoreNode = pnode; 208 if (lastExceptionNode != null) { 209 lastExceptionNode.insertOutEdge(pnode, EXCEPTION_MS); 210 } 211 } 212 } 213 214 // (3) Add edges due to exception state/exceptional control flow. 215 if (p.isPEI()) { 216 if (lastExceptionNode != null) { 217 lastExceptionNode.insertOutEdge(pnode, EXCEPTION_E); 218 } 219 lastExceptionNode = pnode; 220 } 221 } 222 } 223 224 /** 225 * Computes anti dependences by doing a backwards 226 * traversal of the instructions from start to end. 227 * 228 * @param start start instruction 229 * @param end end instruction 230 */ 231 private void computeBackwardDependences(Instruction start, Instruction end) { 232 clearRegisters(start, end); 233 234 DepGraphNode lastStoreNode = null; 235 DepGraphNode lastExceptionNode = null; 236 for (DepGraphNode pnode = (DepGraphNode) lastNode(); pnode != null; pnode = 237 (DepGraphNode) pnode.getPrev()) { 238 Instruction p = pnode.instruction(); 239 240 // (1) Add edges due to registers 241 int useMask = p.operator().implicitUses; 242 int defMask = p.operator().implicitDefs; 243 if (p.isTSPoint()) { 244 useMask |= GenericPhysicalDefUse.getMaskTSPUses(); 245 defMask |= GenericPhysicalDefUse.getMaskTSPDefs(); 246 } 247 for (Enumeration<Operand> uses = p.getUses(); uses.hasMoreElements();) { 248 computeBackwardDependencesUse(uses.nextElement(), pnode, lastExceptionNode); 249 } 250 for (Enumeration<Register> uses = GenericPhysicalDefUse.enumerate(useMask, ir); uses.hasMoreElements();) { 251 Register r = uses.nextElement(); 252 computeImplicitBackwardDependencesUse(r, pnode); 253 } 254 for (Enumeration<Operand> defs = p.getDefs(); defs.hasMoreElements();) { 255 computeBackwardDependencesDef(defs.nextElement(), pnode, lastExceptionNode); 256 } 257 for (Enumeration<Register> defs = GenericPhysicalDefUse.enumerate(defMask, ir); defs.hasMoreElements();) { 258 Register r = defs.nextElement(); 259 computeImplicitBackwardDependencesDef(r, pnode); 260 } 261 262 // (2) Add edges due to memory 263 boolean isStore = p.isImplicitStore(); 264 boolean isLoad = p.isImplicitLoad(); 265 if (isStore) { 266 if (lastExceptionNode != null) { 267 pnode.insertOutEdge(lastExceptionNode, EXCEPTION_MS); 268 } 269 lastStoreNode = pnode; 270 } else if (isLoad) { 271 // NOTE: In general alias relationships are not transitive and therefore 272 // we cannot exit this loop early. 273 for (DepGraphNode snode = lastStoreNode; snode != null; snode = (DepGraphNode) snode.getNext()) { 274 if (snode.instruction().isImplicitStore() && 275 LocationOperand.mayBeAliased(getLocation(p), getLocation(snode.instruction()))) { 276 pnode.insertOutEdge(snode, MEM_ANTI); 277 } 278 } 279 } 280 281 if (p.isPEI()) { 282 lastExceptionNode = pnode; 283 } 284 } 285 } 286 287 /** 288 * Compute control and barrier (acquire/release) dependences 289 * in two passes (one forward, one reverse over the instructions 290 * from start to end. 291 * 292 * @param start start instruction 293 * @param end end instruction 294 */ 295 private void computeControlAndBarrierDependences(Instruction start, Instruction end) { 296 // (1) In a forward pass, we add the following dependences: 297 // a) No load instruction may rise above an acquire 298 // b) No instruction may rise above an UNINT_BEGIN (conservative), 299 // a yieldpoint (we placed the yieldpoints where we wanted them), 300 // a GET_CAUGHT_EXCEPTION, or an IR_PROLOGUE. 301 // c) No GC point may rise above an UNINT_END 302 DepGraphNode lastTotalBarrier = null; 303 DepGraphNode lastGCBarrier = null; 304 DepGraphNode lastAcquire = null; 305 for (DepGraphNode pnode = (DepGraphNode) firstNode(); pnode != null; pnode = 306 (DepGraphNode) pnode.getNext()) { 307 Instruction p = pnode.instruction(); 308 if (lastTotalBarrier != null) { 309 lastTotalBarrier.insertOutEdge(pnode, CONTROL); 310 } 311 if (lastGCBarrier != null) { 312 lastGCBarrier.insertOutEdge(pnode, CONTROL); 313 } 314 if (lastAcquire != null && p.isImplicitLoad()) { 315 lastAcquire.insertOutEdge(pnode, CONTROL); 316 } 317 Operator pop = p.operator(); 318 if (p.isYieldPoint() || pop == IR_PROLOGUE || pop == UNINT_BEGIN || pop == GET_TIME_BASE || pop == GET_CAUGHT_EXCEPTION) { 319 lastTotalBarrier = pnode; 320 } 321 if (pop == UNINT_END) { 322 lastGCBarrier = pnode; 323 } 324 if (p.isAcquire() || p.isDynamicLinkingPoint()) { 325 lastAcquire = pnode; 326 } 327 } 328 329 // (2) In a backward pass we add the following dependences: 330 // a) No store instruction may sink below a release. 331 // b) No instruction may sink below an UNINT_END (conservative), 332 // a branch/return, a SET_CAUGHT_EXCEPTION, or a yieldpoint 333 // (again want to pin yieldpoints). 334 // c) No GC point may sink below an UNINT_BEGIN 335 lastTotalBarrier = null; 336 lastGCBarrier = null; 337 DepGraphNode lastRelease = null; 338 for (DepGraphNode pnode = (DepGraphNode) lastNode(); pnode != null; pnode = 339 (DepGraphNode) pnode.getPrev()) { 340 Instruction p = pnode.instruction(); 341 if (lastTotalBarrier != null) { 342 pnode.insertOutEdge(lastTotalBarrier, CONTROL); 343 } 344 if (lastGCBarrier != null) { 345 pnode.insertOutEdge(lastGCBarrier, CONTROL); 346 } 347 if (lastRelease != null && p.isImplicitStore()) { 348 pnode.insertOutEdge(lastRelease, CONTROL); 349 } 350 Operator pop = p.operator(); 351 if (p.isBranch() || p.isReturn() || p.isYieldPoint() || pop == UNINT_END || pop == GET_TIME_BASE || pop == SET_CAUGHT_EXCEPTION) { 352 lastTotalBarrier = pnode; 353 } 354 if (pop == UNINT_BEGIN) { 355 lastGCBarrier = pnode; 356 } 357 if (p.isRelease() || p.isDynamicLinkingPoint()) { 358 lastRelease = pnode; 359 } 360 } 361 } 362 363 /** 364 * Compute forward dependences from a given use to a given node. 365 * @param op source operand 366 * @param destNode destination node 367 * @param lastExceptionNode node representing the last PEI 368 */ 369 private void computeForwardDependencesUse(Operand op, DepGraphNode destNode, 370 DepGraphNode lastExceptionNode) { 371 if (!(op instanceof RegisterOperand)) return; 372 RegisterOperand regOp = (RegisterOperand) op; 373 DepGraphNode sourceNode = getDepGraphNode(regOp.getRegister()); 374 375 // if there is an element in the regTableDef[regNum] slot, set 376 // the flow dependence edge. 377 if (sourceNode != null) { 378 if (regOp.getRegister().isValidation()) { 379 sourceNode.insertOutEdge(destNode, GUARD_TRUE); 380 } else { 381 for (Enumeration<Register> e = 382 GenericPhysicalDefUse.enumerate(GenericPhysicalDefUse.getMaskTSPDefs(), ir); e.hasMoreElements();) { 383 Register r = e.nextElement(); 384 if (regOp.getRegister() == r) { 385 sourceNode.insertOutEdge(destNode, REG_MAY_DEF); 386 return; 387 } 388 } 389 sourceNode.insertRegTrueOutEdge(destNode, regOp); 390 } 391 } 392 } 393 394 /** 395 * Compute forward dependences from a given def to a given node. 396 * @param op source operand 397 * @param destNode destination node 398 * @param lastExceptionNode node representing the last PEI 399 */ 400 private void computeForwardDependencesDef(Operand op, DepGraphNode destNode, 401 DepGraphNode lastExceptionNode) { 402 if (!(op instanceof RegisterOperand)) return; 403 RegisterOperand regOp = (RegisterOperand)op; 404 DepGraphNode sourceNode = getDepGraphNode(regOp.getRegister()); 405 406 if (sourceNode != null) { 407 // create output dependence edge from sourceNode to destNode. 408 int type = regOp.getRegister().isValidation() ? GUARD_OUTPUT : REG_OUTPUT; 409 sourceNode.insertOutEdge(destNode, type); 410 } 411 412 // pin the def below the previous exception node if the register 413 // being defined may be live in some reachable catch block 414 if (lastExceptionNode != null && regOp.getRegister().spansBasicBlock() && currentBlock.hasExceptionHandlers()) { 415 if (!ir.getHandlerLivenessComputed() || handlerLiveSet.contains(regOp.getRegister())) { 416 lastExceptionNode.insertOutEdge(destNode, EXCEPTION_R); 417 } 418 } 419 420 setDepGraphNodeForRegister(destNode, regOp.getRegister()); 421 } 422 423 /** 424 * Compute backward dependences from a given use to a given node. 425 * @param op source operand 426 * @param destNode destination node 427 * @param lastExceptionNode node representing the last PEI 428 */ 429 private void computeBackwardDependencesUse(Operand op, DepGraphNode destNode, 430 DepGraphNode lastExceptionNode) { 431 if (!(op instanceof RegisterOperand)) return; 432 RegisterOperand regOp = (RegisterOperand) op; 433 DepGraphNode sourceNode = getDepGraphNode(regOp.getRegister()); 434 if (sourceNode != null) { 435 int type = regOp.getRegister().isValidation() ? GUARD_ANTI : REG_ANTI; 436 // create antidependence edge. 437 // NOTE: sourceNode contains the def and destNode contains the use. 438 destNode.insertOutEdge(sourceNode, type); 439 } 440 } 441 442 /** 443 * Compute backward dependences from a given def to a given node. 444 * @param op source operand 445 * @param destNode destination node 446 * @param lastExceptionNode node representing the last PEI 447 */ 448 private void computeBackwardDependencesDef(Operand op, DepGraphNode destNode, 449 DepGraphNode lastExceptionNode) { 450 if (!(op instanceof RegisterOperand)) return; 451 RegisterOperand regOp = (RegisterOperand) op; 452 453 // pin the def above the next exception node if the register 454 // being defined may be live in some reachable catch block 455 if (lastExceptionNode != null && regOp.getRegister().spansBasicBlock() && currentBlock.hasExceptionHandlers()) { 456 if (!ir.getHandlerLivenessComputed() || handlerLiveSet.contains(regOp.getRegister())) { 457 destNode.insertOutEdge(lastExceptionNode, EXCEPTION_R); 458 } 459 } 460 setDepGraphNodeForRegister(destNode, regOp.getRegister()); 461 } 462 463 /** 464 * Compute implicit forward dependences from a given register use 465 * to a given node. 466 * @param r source register 467 * @param destNode destination node 468 */ 469 private void computeImplicitForwardDependencesUse(Register r, DepGraphNode destNode) { 470 DepGraphNode sourceNode = getDepGraphNode(r); 471 if (sourceNode != null) { 472 for (Enumeration<Register> e = 473 GenericPhysicalDefUse.enumerate(GenericPhysicalDefUse.getMaskTSPDefs(), ir); e.hasMoreElements();) { 474 Register r2 = e.nextElement(); 475 if (r == r2) { 476 sourceNode.insertOutEdge(destNode, REG_MAY_DEF); 477 return; 478 } 479 } 480 sourceNode.insertOutEdge(destNode, REG_TRUE); 481 } 482 } 483 484 /** 485 * Compute implicit forward dependences from a given register def 486 * to a given node. 487 * @param r source register 488 * @param destNode destination node 489 */ 490 private void computeImplicitForwardDependencesDef(Register r, DepGraphNode destNode) { 491 DepGraphNode sourceNode = getDepGraphNode(r); 492 if (sourceNode != null) { 493 sourceNode.insertOutEdge(destNode, REG_OUTPUT); 494 } 495 setDepGraphNodeForRegister(destNode, r); 496 } 497 498 /** 499 * Compute implicit backward dependences from a given register use 500 * to a given node. 501 * @param r source register 502 * @param destNode destination node 503 */ 504 private void computeImplicitBackwardDependencesUse(Register r, DepGraphNode destNode) { 505 DepGraphNode sourceNode = getDepGraphNode(r); 506 if (sourceNode != null) { 507 // create antidependence edge. 508 // NOTE: sourceNode contains the def and destNode contains the use. 509 destNode.insertOutEdge(sourceNode, REG_ANTI); 510 } 511 } 512 513 /** 514 * Compute implicit backward dependences from a given register def 515 * to a given node. 516 * @param r source register 517 * @param destNode destination node 518 */ 519 private void computeImplicitBackwardDependencesDef(Register r, DepGraphNode destNode) { 520 setDepGraphNodeForRegister(destNode, r); 521 } 522 523 /** 524 * Get the location of a given load or store instruction. 525 * @param s the instruction to get the location from. 526 * 527 * @return a location or {@code null} 528 */ 529 private LocationOperand getLocation(Instruction s) { 530 // This extra conforms check wouldn't be necessary if the DepGraph 531 // code was distinguishing between explict load/stores which have 532 // locations and implicit load/stores which don't. 533 return LocationCarrier.conforms(s) ? LocationCarrier.getLocation(s) : null; 534 } 535 536 /** 537 * Initialize (clear) the dNode field in Register for all registers 538 * in this basic block by setting them to null. 539 * Handles both explicit and implict use/defs. 540 * @param start the first opt instruction in the region 541 * @param end the last opt instruction in the region 542 */ 543 private void clearRegisters(Instruction start, Instruction end) { 544 for (Instruction p = start; ; p = p.nextInstructionInCodeOrder()) { 545 for (Enumeration<Operand> ops = p.getOperands(); ops.hasMoreElements();) { 546 Operand op = ops.nextElement(); 547 if (op instanceof RegisterOperand) { 548 RegisterOperand rOp = (RegisterOperand) op; 549 clearDepGraphNodeForRegister(rOp.getRegister()); 550 } 551 } 552 if (p == end) break; 553 } 554 for (Enumeration<Register> e = GenericPhysicalDefUse.enumerateAllImplicitDefUses(ir); e.hasMoreElements();) { 555 Register r = e.nextElement(); 556 clearDepGraphNodeForRegister(r); 557 } 558 } 559 560 /** 561 * Print the dependence graph to standard out. 562 */ 563 public void printDepGraph() { 564 System.out.println(toString()); 565 System.out.println("-----------------------------------"); 566 } 567}