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.ssa;
014
015 import java.util.Enumeration;
016 import java.util.HashMap;
017 import org.jikesrvm.VM;
018 import org.jikesrvm.compilers.opt.DefUse;
019 import org.jikesrvm.compilers.opt.OptimizingCompilerException;
020 import org.jikesrvm.compilers.opt.ir.ALoad;
021 import org.jikesrvm.compilers.opt.ir.AStore;
022 import org.jikesrvm.compilers.opt.ir.Attempt;
023 import org.jikesrvm.compilers.opt.ir.Binary;
024 import org.jikesrvm.compilers.opt.ir.CacheOp;
025 import org.jikesrvm.compilers.opt.ir.Call;
026 import org.jikesrvm.compilers.opt.ir.GuardedBinary;
027 import org.jikesrvm.compilers.opt.ir.GuardedUnary;
028 import org.jikesrvm.compilers.opt.ir.IfCmp;
029 import org.jikesrvm.compilers.opt.ir.InlineGuard;
030 import org.jikesrvm.compilers.opt.ir.MonitorOp;
031 import org.jikesrvm.compilers.opt.ir.Move;
032 import org.jikesrvm.compilers.opt.ir.New;
033 import org.jikesrvm.compilers.opt.ir.NewArray;
034 import org.jikesrvm.compilers.opt.ir.NullCheck;
035 import org.jikesrvm.compilers.opt.ir.BasicBlock;
036 import org.jikesrvm.compilers.opt.ir.IR;
037 import org.jikesrvm.compilers.opt.ir.Instruction;
038 import org.jikesrvm.compilers.opt.ir.OperandEnumeration;
039 import static org.jikesrvm.compilers.opt.ir.Operators.IG_PATCH_POINT;
040 import static org.jikesrvm.compilers.opt.ir.Operators.IR_PROLOGUE;
041 import static org.jikesrvm.compilers.opt.ir.Operators.PI;
042 import org.jikesrvm.compilers.opt.ir.Register;
043 import org.jikesrvm.compilers.opt.ir.Phi;
044 import org.jikesrvm.compilers.opt.ir.Prepare;
045 import org.jikesrvm.compilers.opt.ir.PutField;
046 import org.jikesrvm.compilers.opt.ir.PutStatic;
047 import org.jikesrvm.compilers.opt.ir.Unary;
048 import org.jikesrvm.compilers.opt.ir.ZeroCheck;
049 import org.jikesrvm.compilers.opt.ir.operand.ConditionOperand;
050 import org.jikesrvm.compilers.opt.ir.operand.ConstantOperand;
051 import org.jikesrvm.compilers.opt.ir.operand.DoubleConstantOperand;
052 import org.jikesrvm.compilers.opt.ir.operand.FloatConstantOperand;
053 import org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand;
054 import org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand;
055 import org.jikesrvm.compilers.opt.ir.operand.MethodOperand;
056 import org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand;
057 import org.jikesrvm.compilers.opt.ir.operand.Operand;
058 import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand;
059 import org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand;
060 import org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand;
061 import org.jikesrvm.compilers.opt.ir.operand.TypeOperand;
062 import org.jikesrvm.compilers.opt.ir.operand.UnreachableOperand;
063 import org.jikesrvm.compilers.opt.util.GraphNode;
064 import org.jikesrvm.compilers.opt.util.SpaceEffGraph;
065
066 /**
067 * This class implements the value graph used in global value numbering
068 * a la Alpern, Wegman and Zadeck. See Muchnick p.348 for a nice
069 * discussion.
070 *
071 * From Muchnick, "the <em>value graph</em> of a procedure is a
072 * labeled directed graph whose nodes are labeled with operators,
073 * function symbols, or constants, and whose edges represent
074 * generating assignments and point from an operator or function to
075 * its operands; the edges are labeled with natural numbers that
076 * indicate the operand postion that each operand has with repsect to
077 * the given operator or function."
078 */
079 final class ValueGraph {
080
081 /**
082 * Internal graph structure of the value graph.
083 */
084 private final SpaceEffGraph graph;
085 /**
086 * A mapping from name to value graph vertex.
087 */
088 private final HashMap<Object, ValueGraphVertex> nameMap;
089
090 /**
091 * Construct a value graph from an IR.
092 *
093 * <p><b> PRECONDITION:</b> The IR <em> must </em> be in SSA form.
094 * @param ir the IR
095 */
096 ValueGraph(IR ir) {
097 graph = new SpaceEffGraph();
098 nameMap = new HashMap<Object, ValueGraphVertex>();
099 // TODO!!: compute register lists incrementally
100 // we need register lists in order to call Register.getFirstDef()
101 DefUse.computeDU(ir);
102 // add value graph nodes for each symbolic register
103 addRegisterNodes(ir);
104 // go through the IR and add nodes and edges to the value graph
105 // for each instruction, as needed
106 for (Enumeration<Instruction> e = ir.forwardInstrEnumerator(); e.hasMoreElements();) {
107 Instruction s = e.nextElement();
108 processInstruction(s);
109 }
110
111 computeClosure();
112 }
113
114 /**
115 * Due to PI nodes and Moves, the initial label for a register may be
116 * another register. Fix up the value graph for cases where the initial
117 * register label was not removed.
118 */
119 private void computeClosure() {
120 for (Enumeration<GraphNode> e = enumerateVertices(); e.hasMoreElements();) {
121 ValueGraphVertex v = (ValueGraphVertex) e.nextElement();
122 if (v.getName() instanceof Register) {
123 if (v.getLabel() instanceof Register) {
124 if (v.getName() != v.getLabel()) {
125 ValueGraphVertex v2 = getVertex(v.getLabel());
126 if (VM.VerifyAssertions) {
127 if (v2.getName() instanceof Register &&
128 v2.getLabel() instanceof Register &&
129 v2.getLabel() != v2.getName()) {
130 VM._assert(false);
131 }
132 }
133 v.copyVertex(v2);
134 }
135 }
136 }
137 }
138 }
139
140 /**
141 * Enumerate the vertices in the value graph.
142 *
143 * @return an enumeration of the vertices in the value graph
144 */
145 public Enumeration<GraphNode> enumerateVertices() {
146 return graph.enumerateNodes();
147 }
148
149 /**
150 * Return the vertex which has a given name.
151 *
152 * @param name the name of the vertex
153 * @return the vertex with the name. null if none found.
154 */
155 public ValueGraphVertex getVertex(Object name) {
156 if (name instanceof RegisterOperand) {
157 name = ((RegisterOperand) name).asRegister().getRegister();
158 } else if (name instanceof IntConstantOperand) {
159 name = ((IntConstantOperand) name).value;
160 } else if (name instanceof FloatConstantOperand) {
161 name = ((FloatConstantOperand) name).value;
162 } else if (name instanceof LongConstantOperand) {
163 name = ((LongConstantOperand) name).value;
164 } else if (name instanceof DoubleConstantOperand) {
165 name = ((DoubleConstantOperand) name).value;
166 } else if (name instanceof ObjectConstantOperand) {
167 name = ((ObjectConstantOperand) name).value;
168 } else if (name instanceof TIBConstantOperand) {
169 name = ((TIBConstantOperand) name).value;
170 }
171 return nameMap.get(name);
172 }
173
174 /**
175 * Return a String representation of the value graph.
176 *
177 * @return a String representation of the value graph.
178 */
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 (OperandEnumeration e = s.getDefs(); e.hasMoreElements();) {
270 Operand current = e.next();
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 (OperandEnumeration e = s.getDefs(); e.hasMoreElements(); numArgs++) {
598 Register formal = ((RegisterOperand) e.next()).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 *
781 * Note: treat PI instructions like MOVES
782 *
783 * @param op the RegisterOperand
784 */
785 private Operand bypassMoves(Operand op) {
786 if (!op.isRegister()) return op;
787 Register r = op.asRegister().getRegister();
788 Instruction def = r.getFirstDef();
789 if (def == null) {
790 return op;
791 }
792 if (r.isPhysical()) {
793 return op;
794 }
795 if (Move.conforms(def)) {
796 // In a perfect world, this shouldn't happen. Copy propagation
797 // in SSA form should remove all 'normal' moves.
798 // We can't simply bypass this move, since it may lead to
799 // infinite mutual recursion.
800 return op;
801 } else if (def.operator == PI) {
802 return bypassMoves(GuardedUnary.getVal(def));
803 } else {
804 return op;
805 }
806 }
807 }