/** * 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; } }