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}