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.ssa; 014 015import java.util.Enumeration; 016import java.util.HashMap; 017import org.jikesrvm.VM; 018import org.jikesrvm.compilers.opt.DefUse; 019import org.jikesrvm.compilers.opt.OptimizingCompilerException; 020import org.jikesrvm.compilers.opt.ir.ALoad; 021import org.jikesrvm.compilers.opt.ir.AStore; 022import org.jikesrvm.compilers.opt.ir.Attempt; 023import org.jikesrvm.compilers.opt.ir.Binary; 024import org.jikesrvm.compilers.opt.ir.CacheOp; 025import org.jikesrvm.compilers.opt.ir.Call; 026import org.jikesrvm.compilers.opt.ir.GuardedBinary; 027import org.jikesrvm.compilers.opt.ir.GuardedUnary; 028import org.jikesrvm.compilers.opt.ir.IfCmp; 029import org.jikesrvm.compilers.opt.ir.InlineGuard; 030import org.jikesrvm.compilers.opt.ir.MonitorOp; 031import org.jikesrvm.compilers.opt.ir.Move; 032import org.jikesrvm.compilers.opt.ir.New; 033import org.jikesrvm.compilers.opt.ir.NewArray; 034import org.jikesrvm.compilers.opt.ir.NullCheck; 035import org.jikesrvm.compilers.opt.ir.BasicBlock; 036import org.jikesrvm.compilers.opt.ir.IR; 037import org.jikesrvm.compilers.opt.ir.Instruction; 038import static org.jikesrvm.compilers.opt.ir.Operators.IG_PATCH_POINT; 039import static org.jikesrvm.compilers.opt.ir.Operators.IR_PROLOGUE; 040import static org.jikesrvm.compilers.opt.ir.Operators.PI; 041import org.jikesrvm.compilers.opt.ir.Register; 042import org.jikesrvm.compilers.opt.ir.Phi; 043import org.jikesrvm.compilers.opt.ir.Prepare; 044import org.jikesrvm.compilers.opt.ir.PutField; 045import org.jikesrvm.compilers.opt.ir.PutStatic; 046import org.jikesrvm.compilers.opt.ir.Unary; 047import org.jikesrvm.compilers.opt.ir.ZeroCheck; 048import org.jikesrvm.compilers.opt.ir.operand.ConditionOperand; 049import org.jikesrvm.compilers.opt.ir.operand.ConstantOperand; 050import org.jikesrvm.compilers.opt.ir.operand.DoubleConstantOperand; 051import org.jikesrvm.compilers.opt.ir.operand.FloatConstantOperand; 052import org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand; 053import org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand; 054import org.jikesrvm.compilers.opt.ir.operand.MethodOperand; 055import org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand; 056import org.jikesrvm.compilers.opt.ir.operand.Operand; 057import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; 058import org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand; 059import org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand; 060import org.jikesrvm.compilers.opt.ir.operand.TypeOperand; 061import org.jikesrvm.compilers.opt.ir.operand.UnreachableOperand; 062import org.jikesrvm.compilers.opt.util.GraphNode; 063import org.jikesrvm.compilers.opt.util.SpaceEffGraph; 064 065/** 066 * This class implements the value graph used in global value numbering 067 * a la Alpern, Wegman and Zadeck. See Muchnick p.348 for a nice 068 * discussion. 069 * <p> 070 * From Muchnick, "the <em>value graph</em> of a procedure is a 071 * labeled directed graph whose nodes are labeled with operators, 072 * function symbols, or constants, and whose edges represent 073 * generating assignments and point from an operator or function to 074 * its operands; the edges are labeled with natural numbers that 075 * indicate the operand position that each operand has with respect to 076 * the given operator or function." 077 */ 078final class ValueGraph { 079 080 /** 081 * Internal graph structure of the value graph. 082 */ 083 private final SpaceEffGraph graph; 084 /** 085 * A mapping from name to value graph vertex. 086 */ 087 private final HashMap<Object, ValueGraphVertex> nameMap; 088 089 /** 090 * Construct a value graph from an IR. 091 * 092 * <p><b> PRECONDITION:</b> The IR <em> must </em> be in SSA form. 093 * @param ir the IR 094 */ 095 ValueGraph(IR ir) { 096 graph = new SpaceEffGraph(); 097 nameMap = new HashMap<Object, ValueGraphVertex>(); 098 // TODO!!: compute register lists incrementally 099 // we need register lists in order to call Register.getFirstDef() 100 DefUse.computeDU(ir); 101 // add value graph nodes for each symbolic register 102 addRegisterNodes(ir); 103 // go through the IR and add nodes and edges to the value graph 104 // for each instruction, as needed 105 for (Enumeration<Instruction> e = ir.forwardInstrEnumerator(); e.hasMoreElements();) { 106 Instruction s = e.nextElement(); 107 processInstruction(s); 108 } 109 110 computeClosure(); 111 } 112 113 /** 114 * Due to PI nodes and Moves, the initial label for a register may be 115 * another register. Fix up the value graph for cases where the initial 116 * register label was not removed. 117 */ 118 private void computeClosure() { 119 for (Enumeration<GraphNode> e = enumerateVertices(); e.hasMoreElements();) { 120 ValueGraphVertex v = (ValueGraphVertex) e.nextElement(); 121 if (v.getName() instanceof Register) { 122 if (v.getLabel() instanceof Register) { 123 if (v.getName() != v.getLabel()) { 124 ValueGraphVertex v2 = getVertex(v.getLabel()); 125 if (VM.VerifyAssertions) { 126 if (v2.getName() instanceof Register && 127 v2.getLabel() instanceof Register && 128 v2.getLabel() != v2.getName()) { 129 VM._assert(VM.NOT_REACHED); 130 } 131 } 132 v.copyVertex(v2); 133 } 134 } 135 } 136 } 137 } 138 139 /** 140 * Enumerate the vertices in the value graph. 141 * 142 * @return an enumeration of the vertices in the value graph 143 */ 144 public Enumeration<GraphNode> enumerateVertices() { 145 return graph.enumerateNodes(); 146 } 147 148 /** 149 * Return the vertex which has a given name. 150 * 151 * @param name the name of the vertex 152 * @return the vertex with the name. null if none found. 153 */ 154 public ValueGraphVertex getVertex(Object name) { 155 if (name instanceof RegisterOperand) { 156 name = ((RegisterOperand) name).asRegister().getRegister(); 157 } else if (name instanceof IntConstantOperand) { 158 name = ((IntConstantOperand) name).value; 159 } else if (name instanceof FloatConstantOperand) { 160 name = ((FloatConstantOperand) name).value; 161 } else if (name instanceof LongConstantOperand) { 162 name = ((LongConstantOperand) name).value; 163 } else if (name instanceof DoubleConstantOperand) { 164 name = ((DoubleConstantOperand) name).value; 165 } else if (name instanceof ObjectConstantOperand) { 166 name = ((ObjectConstantOperand) name).value; 167 } else if (name instanceof TIBConstantOperand) { 168 name = ((TIBConstantOperand) name).value; 169 } 170 return nameMap.get(name); 171 } 172 173 /** 174 * Return a String representation of the value graph. 175 * 176 * @return a String representation of the value graph. 177 */ 178 @Override 179 public String toString() { 180 // print the nodes 181 StringBuilder s = new StringBuilder("VALUE GRAPH: \n"); 182 for (Enumeration<GraphNode> n = graph.enumerateNodes(); n.hasMoreElements();) { 183 ValueGraphVertex node = (ValueGraphVertex) n.nextElement(); 184 s.append(node).append("\n"); 185 } 186 return s.toString(); 187 } 188 189 /** 190 * Add a node to the value graph for every symbolic register. 191 * 192 * <p><b>PRECONDITION:</b> register lists are computed and valid 193 * 194 * @param ir the governing IR 195 */ 196 private void addRegisterNodes(IR ir) { 197 for (Register reg = ir.regpool.getFirstSymbolicRegister(); reg != null; reg = reg.getNext()) { 198 findOrCreateVertex(reg); 199 } 200 } 201 202 /** 203 * Update the value graph to account for a given instruction. 204 * 205 * @param s the instruction in question 206 */ 207 private void processInstruction(Instruction s) { 208 // TODO: support all necessary types of instructions 209 if (s.isDynamicLinkingPoint()) { 210 processCall(s); 211 } else if (Move.conforms(s)) { 212 processMove(s); 213 } else if (s.operator() == PI) { 214 processPi(s); 215 } else if (New.conforms(s)) { 216 processNew(s); 217 } else if (NewArray.conforms(s)) { 218 processNewArray(s); 219 } else if (Unary.conforms(s)) { 220 processUnary(s); 221 } else if (GuardedUnary.conforms(s)) { 222 processGuardedUnary(s); 223 } else if (NullCheck.conforms(s)) { 224 processNullCheck(s); 225 } else if (ZeroCheck.conforms(s)) { 226 processZeroCheck(s); 227 } else if (Binary.conforms(s)) { 228 processBinary(s); 229 } else if (GuardedBinary.conforms(s)) { 230 processGuardedBinary(s); 231 } else if (InlineGuard.conforms(s)) { 232 processInlineGuard(s); 233 } else if (IfCmp.conforms(s)) { 234 processIfCmp(s); 235 } else if (Call.conforms(s)) { 236 processCall(s); 237 } else if (MonitorOp.conforms(s)) { 238 processCall(s); 239 } else if (Prepare.conforms(s)) { 240 processCall(s); 241 } else if (Attempt.conforms(s)) { 242 processCall(s); 243 } else if (CacheOp.conforms(s)) { 244 processCall(s); 245 } else if (ALoad.conforms(s)) { 246 processALoad(s); 247 } else if (PutField.conforms(s)) { 248 processPutField(s); 249 } else if (PutStatic.conforms(s)) { 250 processPutStatic(s); 251 } else if (AStore.conforms(s)) { 252 processAStore(s); 253 } else if (Phi.conforms(s)) { 254 processPhi(s); 255 } else if (s.operator() == IR_PROLOGUE) { 256 processPrologue(s); 257 } 258 } 259 260 /** 261 * Update the value graph to account for a given MOVE instruction. 262 * 263 * <p><b>PRECONDITION:</b> <code> Move.conforms(s); </code> 264 * 265 * @param s the instruction in question 266 */ 267 private void processMove(Instruction s) { 268 // ignore instructions that define physical registers 269 for (Enumeration<Operand> e = s.getDefs(); e.hasMoreElements();) { 270 Operand current = e.nextElement(); 271 if (current instanceof RegisterOperand && ((RegisterOperand) current).getRegister().isPhysical()) return; 272 } 273 274 Register result = Move.getResult(s).getRegister(); 275 ValueGraphVertex v = findOrCreateVertex(result); 276 Operand val = Move.getVal(s); 277 // bypass Move instructions that define the right-hand side 278 val = bypassMoves(val); 279 v.copyVertex(findOrCreateVertex(val)); 280 } 281 282 /** 283 * Update the value graph to account for a given PI instruction. 284 * 285 * <p><b>PRECONDITION:</b> <code> s.operator == PI </code> 286 * 287 * @param s the instruction in question 288 */ 289 private void processPi(Instruction s) { 290 Register result = GuardedUnary.getResult(s).getRegister(); 291 ValueGraphVertex v = findOrCreateVertex(result); 292 Operand val = GuardedUnary.getVal(s); 293 // bypass Move instructions that define the right-hand side 294 val = bypassMoves(val); 295 v.copyVertex(findOrCreateVertex(val)); 296 } 297 298 /** 299 * Update the value graph to account for a given NEW instruction. 300 * 301 * <p><b>PRECONDITION:</b> <code> New.conforms(s); </code> 302 * 303 * For a new instruction, we always create a new vertex. 304 * 305 * @param s the instruction in question 306 */ 307 private void processNew(Instruction s) { 308 RegisterOperand result = New.getResult(s); 309 ValueGraphVertex v = findOrCreateVertex(result.getRegister()); 310 // set the label for a NEW instruction to be the instruction itself 311 // so that no two NEW results get the same value number 312 v.setLabel(s, 0); 313 } 314 315 /** 316 * Update the value graph to account for a given NEWARRAY instruction. 317 * 318 * <p><b>PRECONDITION:</b> <code> NewArray.conforms(s); </code> 319 * 320 * For a newarray instruction, we always create a new vertex. 321 * 322 * @param s the instruction in question 323 */ 324 private void processNewArray(Instruction s) { 325 RegisterOperand result = NewArray.getResult(s); 326 ValueGraphVertex v = findOrCreateVertex(result.getRegister()); 327 // set the label for a NEW instruction to be the instruction itself 328 // so that no two NEW results get the same value number 329 v.setLabel(s, 0); 330 } 331 332 /** 333 * Update the value graph to account for a given PUTFIELD instruction. 334 * 335 * <p><b>PRECONDITION:</b> <code> PutField.conforms(s); </code> 336 * 337 * Make sure we have value graph nodes for a constant value 338 * 339 * @param s the instruction in question 340 */ 341 private void processPutField(Instruction s) { 342 Operand value = PutField.getValue(s); 343 if (value.isConstant()) { 344 findOrCreateVertex((ConstantOperand) value); 345 } 346 } 347 348 /** 349 * Update the value graph to account for a given PUTSTATIC instruction. 350 * 351 * <p><b>PRECONDITION:</b> <code> PutStatic.conforms(s); </code> 352 * 353 * Make sure we have value graph nodes for a constant value 354 * 355 * @param s the instruction in question 356 */ 357 private void processPutStatic(Instruction s) { 358 Operand value = PutStatic.getValue(s); 359 if (value.isConstant()) { 360 findOrCreateVertex((ConstantOperand) value); 361 } 362 } 363 364 /** 365 * Update the value graph to account for a given ASTORE instruction. 366 * 367 * <p><b>PRECONDITION:</b> <code> AStore.conforms(s); </code> 368 * 369 * Make sure we have value graph nodes for a constant value 370 * 371 * @param s the instruction in question 372 */ 373 private void processAStore(Instruction s) { 374 Operand value = AStore.getValue(s); 375 if (value.isConstant()) { 376 findOrCreateVertex((ConstantOperand) value); 377 } 378 Operand index = AStore.getIndex(s); 379 if (index.isConstant()) { 380 findOrCreateVertex((ConstantOperand) index); 381 } 382 } 383 384 /** 385 * Update the value graph to account for a given ALOAD instruction. 386 * 387 * <p><b>PRECONDITION:</b> <code> ALoad.conforms(s); </code> 388 * 389 * Make sure we have value graph nodes for a constant value 390 * 391 * @param s the instruction in question 392 */ 393 private void processALoad(Instruction s) { 394 Operand index = ALoad.getIndex(s); 395 if (index.isConstant()) { 396 findOrCreateVertex((ConstantOperand) index); 397 } 398 } 399 400 /** 401 * Update the value graph to account for a given Unary instruction. 402 * 403 * <p><b>PRECONDITION:</b> <code> Unary.conforms(s); </code> 404 * 405 * @param s the instruction in question 406 */ 407 private void processUnary(Instruction s) { 408 // label the vertex corresponding to the result with the operator 409 RegisterOperand result = Unary.getResult(s); 410 ValueGraphVertex v = findOrCreateVertex(result.getRegister()); 411 v.setLabel(s.operator(), 1); 412 // link node v to the operand it uses 413 Operand val = Unary.getVal(s); 414 // bypass Move instructions 415 val = bypassMoves(val); 416 link(v, findOrCreateVertex(val), 0); 417 } 418 419 /** 420 * Update the value graph to account for a given GuardedUnary instruction. 421 * 422 * <p><b>PRECONDITION:</b> <code> GuardedUnary.conforms(s); </code> 423 * 424 * Careful: we define two Guarded Unaries to be equivalent regardless of 425 * whether the guards are equivalent! 426 * 427 * @param s the instruction in question 428 */ 429 private void processGuardedUnary(Instruction s) { 430 // label the vertex corresponding to the result with the operator 431 RegisterOperand result = GuardedUnary.getResult(s); 432 ValueGraphVertex v = findOrCreateVertex(result.getRegister()); 433 v.setLabel(s.operator(), 1); 434 // link node v to the operand it uses 435 Operand val = GuardedUnary.getVal(s); 436 // bypass Move instructions 437 val = bypassMoves(val); 438 link(v, findOrCreateVertex(val), 0); 439 } 440 441 /** 442 * Update the value graph to account for a given NullCheck instruction. 443 * 444 * <p><b>PRECONDITION:</b> <code> NullCheck.conforms(s); </code> 445 * 446 * @param s the instruction in question 447 */ 448 private void processNullCheck(Instruction s) { 449 // label the vertex corresponding to the result with the operator 450 RegisterOperand result = NullCheck.getGuardResult(s); 451 ValueGraphVertex v = findOrCreateVertex(result.getRegister()); 452 v.setLabel(s.operator(), 1); 453 // link node v to the operand it uses 454 Operand val = NullCheck.getRef(s); 455 // bypass Move instructions 456 val = bypassMoves(val); 457 link(v, findOrCreateVertex(val), 0); 458 } 459 460 /** 461 * Update the value graph to account for a given NullCheck instruction. 462 * 463 * <p><b>PRECONDITION:</b> <code> ZeroCheck.conforms(s); </code> 464 * 465 * @param s the instruction in question 466 */ 467 private void processZeroCheck(Instruction s) { 468 // label the vertex corresponding to the result with the operator 469 RegisterOperand result = ZeroCheck.getGuardResult(s); 470 ValueGraphVertex v = findOrCreateVertex(result.getRegister()); 471 v.setLabel(s.operator(), 1); 472 // link node v to the operand it uses 473 Operand val = ZeroCheck.getValue(s); 474 // bypass Move instructions 475 val = bypassMoves(val); 476 link(v, findOrCreateVertex(val), 0); 477 } 478 479 /** 480 * Update the value graph to account for a given Binary instruction. 481 * 482 * <p><b>PRECONDITION:</b> <code> Binary.conforms(s); </code> 483 * 484 * @param s the instruction in question 485 */ 486 private void processBinary(Instruction s) { 487 // label the vertex corresponding to the result with the operator 488 RegisterOperand result = Binary.getResult(s); 489 ValueGraphVertex v = findOrCreateVertex(result.getRegister()); 490 v.setLabel(s.operator(), 2); 491 // link node v to the two operands it uses 492 // first link the first val 493 Operand val = Binary.getVal1(s); 494 val = bypassMoves(val); 495 link(v, findOrCreateVertex(val), 0); 496 Operand val2 = Binary.getVal2(s); 497 val2 = bypassMoves(val2); 498 link(v, findOrCreateVertex(val2), 1); 499 } 500 501 /** 502 * Update the value graph to account for a given GuardedBinary instruction. 503 * 504 * <p><b>PRECONDITION:</b> <code> GuardedBinary.conforms(s); </code> 505 * 506 * Careful: we define two Guarded Binaries to be equivalent regardless of 507 * whether the guards are equivalent! 508 * 509 * @param s the instruction in question 510 */ 511 private void processGuardedBinary(Instruction s) { 512 // label the vertex corresponding to the result with the operator 513 RegisterOperand result = GuardedBinary.getResult(s); 514 ValueGraphVertex v = findOrCreateVertex(result.getRegister()); 515 v.setLabel(s.operator(), 2); 516 // link node v to the two operands it uses 517 // first link the first val 518 Operand val = GuardedBinary.getVal1(s); 519 val = bypassMoves(val); 520 link(v, findOrCreateVertex(val), 0); 521 Operand val2 = GuardedBinary.getVal2(s); 522 val2 = bypassMoves(val2); 523 link(v, findOrCreateVertex(val2), 1); 524 } 525 526 /** 527 * Update the value graph to account for a given InlineGuard instruction. 528 * 529 * <p><b>PRECONDITION:</b> <code> InlineGuard.conforms(s); </code> 530 * 531 * @param s the instruction in question 532 */ 533 private void processInlineGuard(Instruction s) { 534 ValueGraphVertex v = new ValueGraphVertex(s); 535 graph.addGraphNode(v); 536 nameMap.put(s, v); 537 if (s.operator() == IG_PATCH_POINT) { 538 // the 'goal' is irrelevant for patch_point guards. 539 v.setLabel(s.operator(), 1); 540 link(v, findOrCreateVertex(bypassMoves(InlineGuard.getValue(s))), 0); 541 } else { 542 v.setLabel(s.operator(), 2); 543 link(v, findOrCreateVertex(bypassMoves(InlineGuard.getValue(s))), 0); 544 link(v, findOrCreateVertex(InlineGuard.getGoal(s)), 1); 545 } 546 } 547 548 /** 549 * Update the value graph to account for a given IfCmp instruction. 550 * 551 * <p><b>PRECONDITION:</b> <code> IfCmp.conforms(s); </code> 552 * 553 * @param s the instruction in question 554 */ 555 private void processIfCmp(Instruction s) { 556 ValueGraphVertex v = new ValueGraphVertex(s); 557 graph.addGraphNode(v); 558 nameMap.put(s, v); 559 v.setLabel(s.operator(), 3); 560 link(v, findOrCreateVertex(bypassMoves(IfCmp.getVal1(s))), 0); 561 link(v, findOrCreateVertex(bypassMoves(IfCmp.getVal2(s))), 1); 562 link(v, findOrCreateVertex(IfCmp.getCond(s)), 2); 563 } 564 565 /** 566 * Update the value graph to account for a given Phi instruction. 567 * 568 * <p><b>PRECONDITION:</b> <code> Phi.conforms(s); </code> 569 * 570 * @param s the instruction in question 571 */ 572 private void processPhi(Instruction s) { 573 // the label for a PHI instruction is the basic block 574 // in which it appears 575 Register result = Phi.getResult(s).asRegister().getRegister(); 576 ValueGraphVertex v = findOrCreateVertex(result); 577 BasicBlock bb = s.getBasicBlock(); 578 v.setLabel(bb, bb.getNumberOfIn()); 579 // link node v to all operands it uses 580 for (int i = 0; i < Phi.getNumberOfValues(s); i++) { 581 Operand val = Phi.getValue(s, i); 582 val = bypassMoves(val); 583 ValueGraphVertex target = findOrCreateVertex(val); 584 link(v, target, i); 585 } 586 } 587 588 /** 589 * Update the value graph to account for an IR_PROLOGUE instruction 590 * 591 * <p><b>PRECONDITION:</b> <code> Prologue.conforms(s); </code> 592 * 593 * @param s the instruction in question 594 */ 595 private void processPrologue(Instruction s) { 596 int numArgs = 0; 597 for (Enumeration<Operand> e = s.getDefs(); e.hasMoreElements(); numArgs++) { 598 Register formal = ((RegisterOperand) e.nextElement()).getRegister(); 599 ValueGraphVertex v = findOrCreateVertex(formal); 600 v.setLabel(new ValueGraphParamLabel(numArgs), 0); 601 } 602 } 603 604 /** 605 * Update the value graph to account for a given Call instruction. 606 * 607 * <p><b>PRECONDITION:</b> <code> Call.conforms(s); </code> 608 * 609 * @param s the instruction in question 610 */ 611 private void processCall(Instruction s) { 612 // do nothing. 613 // TODO: someday, maybe exploit interprocedural information 614 } 615 616 /** 617 * Find or create an ValueGraphVertex corresponding to a 618 * given variable. 619 * 620 * @param var The variable 621 * @return A value graph vertex corresponding to this variable 622 */ 623 private ValueGraphVertex findOrCreateVertex(Object var) { 624 if (var instanceof Register) { 625 return findOrCreateVertex((Register) var); 626 } else if (var instanceof RegisterOperand) { 627 return findOrCreateVertex(((RegisterOperand) var).getRegister()); 628 } else if (var instanceof ConstantOperand) { 629 return findOrCreateVertex((ConstantOperand) var); 630 } else if (var instanceof TypeOperand) { 631 return findOrCreateVertex((TypeOperand) var); 632 } else if (var instanceof MethodOperand) { 633 return findOrCreateVertex((MethodOperand) var); 634 } else if (var instanceof ConditionOperand) { 635 return findOrCreateVertex((ConditionOperand) var); 636 } else { 637 throw new OptimizingCompilerException("ValueGraph.findOrCreateVertex: unexpected type " + var.getClass()); 638 } 639 } 640 641 /** 642 * Find or create an ValueGraphVertex corresponding to a 643 * given register 644 * 645 * @param r the register 646 * @return a value graph vertex corresponding to this variable 647 */ 648 private ValueGraphVertex findOrCreateVertex(Register r) { 649 ValueGraphVertex v = getVertex(r); 650 if (v == null) { 651 v = new ValueGraphVertex(r); 652 v.setLabel(r, 0); 653 graph.addGraphNode(v); 654 nameMap.put(r, v); 655 } 656 return v; 657 } 658 659 /** 660 * Find or create an ValueGraphVertex corresponding to a 661 * given constant operand 662 * 663 * @param op the constant operand 664 * @return a value graph vertex corresponding to this variable 665 */ 666 private ValueGraphVertex findOrCreateVertex(ConstantOperand op) { 667 Object name; 668 if (op.isAddressConstant()) { 669 name = (VM.BuildFor32Addr) ? op.asAddressConstant().value.toInt() : op.asAddressConstant().value.toLong(); 670 } else if (op.isIntConstant()) { 671 name = op.asIntConstant().value; 672 } else if (op.isFloatConstant()) { 673 name = op.asFloatConstant().value; 674 } else if (op.isLongConstant()) { 675 name = op.asLongConstant().value; 676 } else if (op.isDoubleConstant()) { 677 name = op.asDoubleConstant().value; 678 } else if (op instanceof ObjectConstantOperand) { 679 name = op.asObjectConstant().value; 680 } else if (op instanceof TIBConstantOperand) { 681 name = op.asTIBConstant().value; 682 } else if (op.isNullConstant()) { 683 name = op; 684 } else if (op instanceof TrueGuardOperand) { 685 name = op; 686 } else if (op instanceof UnreachableOperand) { 687 name = op; 688 } else { 689 throw new OptimizingCompilerException("ValueGraph.findOrCreateVertex: unexpected constant operand: " + 690 op); 691 } 692 ValueGraphVertex v = getVertex(name); 693 if (v == null) { 694 v = new ValueGraphVertex(op); 695 v.setLabel(op, 0); 696 graph.addGraphNode(v); 697 nameMap.put(name, v); 698 } 699 return v; 700 } 701 702 /** 703 * Find or create an ValueGraphVertex corresponding to a 704 * given type operand 705 * 706 * @param op the operand in question 707 * @return a value graph vertex corresponding to this type 708 */ 709 private ValueGraphVertex findOrCreateVertex(TypeOperand op) { 710 Object name = op.getTypeRef(); 711 ValueGraphVertex v = getVertex(name); 712 if (v == null) { 713 v = new ValueGraphVertex(op); 714 v.setLabel(op, 0); 715 graph.addGraphNode(v); 716 nameMap.put(name, v); 717 } 718 return v; 719 } 720 721 /** 722 * Find or create an ValueGraphVertex corresponding to a 723 * given method operand 724 * 725 * @param op the operand in question 726 * @return a value graph vertex corresponding to this type 727 */ 728 private ValueGraphVertex findOrCreateVertex(MethodOperand op) { 729 Object name; 730 if (op.hasTarget()) { 731 name = op.getTarget(); 732 } else { 733 name = op.getMemberRef(); 734 } 735 ValueGraphVertex v = getVertex(name); 736 if (v == null) { 737 v = new ValueGraphVertex(op); 738 v.setLabel(op, 0); 739 graph.addGraphNode(v); 740 nameMap.put(name, v); 741 } 742 return v; 743 } 744 745 /** 746 * Find or create an ValueGraphVertex corresponding to a 747 * given method operand 748 * 749 * @param op the operand in question 750 * @return a value graph vertex corresponding to this type 751 */ 752 private ValueGraphVertex findOrCreateVertex(ConditionOperand op) { 753 Object name = op.value; // kludge. 754 ValueGraphVertex v = getVertex(name); 755 if (v == null) { 756 v = new ValueGraphVertex(op); 757 v.setLabel(op, 0); 758 graph.addGraphNode(v); 759 nameMap.put(name, v); 760 } 761 return v; 762 } 763 764 /** 765 * Link two vertices in the value graph 766 * 767 * @param src the def 768 * @param target the use 769 * @param pos the position of target in the set of uses 770 */ 771 private void link(ValueGraphVertex src, ValueGraphVertex target, int pos) { 772 ValueGraphEdge e = new ValueGraphEdge(src, target); 773 src.addTarget(target, pos); 774 graph.addGraphEdge(e); 775 } 776 777 /** 778 * Bypass MOVE instructions that def an operand: return the first def 779 * in the chain that is not the result of a MOVE instruction. 780 * <p> 781 * Note: treat PI instructions like MOVES 782 * 783 * @param op the RegisterOperand 784 * @return the first def in the chain that is not the result of 785 * move if it can be found, the original operand otherwise 786 */ 787 private Operand bypassMoves(Operand op) { 788 if (!op.isRegister()) return op; 789 Register r = op.asRegister().getRegister(); 790 Instruction def = r.getFirstDef(); 791 if (def == null) { 792 return op; 793 } 794 if (r.isPhysical()) { 795 return op; 796 } 797 if (Move.conforms(def)) { 798 // In a perfect world, this shouldn't happen. Copy propagation 799 // in SSA form should remove all 'normal' moves. 800 // We can't simply bypass this move, since it may lead to 801 // infinite mutual recursion. 802 return op; 803 } else if (def.operator() == PI) { 804 return bypassMoves(GuardedUnary.getVal(def)); 805 } else { 806 return op; 807 } 808 } 809}