/**
  * Update the value graph to account for a given PI instruction.
  *
  * <p><b>PRECONDITION:</b> <code> s.operator == PI </code>
  *
  * @param s the instruction in question
  */
 private void processPi(Instruction s) {
   Register result = GuardedUnary.getResult(s).getRegister();
   ValueGraphVertex v = findOrCreateVertex(result);
   Operand val = GuardedUnary.getVal(s);
   // bypass Move instructions that define the right-hand side
   val = bypassMoves(val);
   v.copyVertex(findOrCreateVertex(val));
 }
 /**
  * Update the value graph to account for a given GuardedUnary instruction.
  *
  * <p><b>PRECONDITION:</b> <code> GuardedUnary.conforms(s); </code> Careful: we define two Guarded
  * Unaries to be equivalent regardless of whether the guards are equivalent!
  *
  * @param s the instruction in question
  */
 private void processGuardedUnary(Instruction s) {
   // label the vertex corresponding to the result with the operator
   RegisterOperand result = GuardedUnary.getResult(s);
   ValueGraphVertex v = findOrCreateVertex(result.getRegister());
   v.setLabel(s.operator(), 1);
   // link node v to the operand it uses
   Operand val = GuardedUnary.getVal(s);
   // bypass Move instructions
   val = bypassMoves(val);
   link(v, findOrCreateVertex(val), 0);
 }
 /**
  * Update the value graph to account for a given instruction.
  *
  * @param s the instruction in question
  */
 private void processInstruction(Instruction s) {
   // TODO: support all necessary types of instructions
   if (s.isDynamicLinkingPoint()) {
     processCall(s);
   } else if (Move.conforms(s)) {
     processMove(s);
   } else if (s.operator == PI) {
     processPi(s);
   } else if (New.conforms(s)) {
     processNew(s);
   } else if (NewArray.conforms(s)) {
     processNewArray(s);
   } else if (Unary.conforms(s)) {
     processUnary(s);
   } else if (GuardedUnary.conforms(s)) {
     processGuardedUnary(s);
   } else if (NullCheck.conforms(s)) {
     processNullCheck(s);
   } else if (ZeroCheck.conforms(s)) {
     processZeroCheck(s);
   } else if (Binary.conforms(s)) {
     processBinary(s);
   } else if (GuardedBinary.conforms(s)) {
     processGuardedBinary(s);
   } else if (InlineGuard.conforms(s)) {
     processInlineGuard(s);
   } else if (IfCmp.conforms(s)) {
     processIfCmp(s);
   } else if (Call.conforms(s)) {
     processCall(s);
   } else if (MonitorOp.conforms(s)) {
     processCall(s);
   } else if (Prepare.conforms(s)) {
     processCall(s);
   } else if (Attempt.conforms(s)) {
     processCall(s);
   } else if (CacheOp.conforms(s)) {
     processCall(s);
   } else if (ALoad.conforms(s)) {
     processALoad(s);
   } else if (PutField.conforms(s)) {
     processPutField(s);
   } else if (PutStatic.conforms(s)) {
     processPutStatic(s);
   } else if (AStore.conforms(s)) {
     processAStore(s);
   } else if (Phi.conforms(s)) {
     processPhi(s);
   } else if (s.operator() == IR_PROLOGUE) {
     processPrologue(s);
   }
 }
 /**
  * Bypass MOVE instructions that def an operand: return the first def in the chain that is not the
  * result of a MOVE instruction.
  *
  * <p>Note: treat PI instructions like MOVES
  *
  * @param op the RegisterOperand
  */
 private Operand bypassMoves(Operand op) {
   if (!op.isRegister()) return op;
   Register r = op.asRegister().getRegister();
   Instruction def = r.getFirstDef();
   if (def == null) {
     return op;
   }
   if (r.isPhysical()) {
     return op;
   }
   if (Move.conforms(def)) {
     //   In a perfect world, this shouldn't happen. Copy propagation
     //   in SSA form should remove all 'normal' moves.
     //   We can't simply bypass this move, since it may lead to
     //   infinite mutual recursion.
     return op;
   } else if (def.operator == PI) {
     return bypassMoves(GuardedUnary.getVal(def));
   } else {
     return op;
   }
 }