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