// Split critical edges in the graph. A critical edge is an edge which // is neither its successor's only predecessor, nor its predecessor's // only successor. Critical edges must be split to prevent copy-insertion // and code motion from affecting other edges. It is probably not strictly // needed here. public static void SplitCriticalEdges(LBlock[] blocks) { for (var i = 0; i < blocks.Length; i++) { var block = blocks[i]; if (block.numSuccessors < 2) { continue; } for (var j = 0; j < block.numSuccessors; j++) { var target = block.getSuccessor(j); if (target.numPredecessors < 2) { continue; } // Create a new block inheriting from the predecessor. var split = new LBlock(block.pc); var ins = new LGoto(target); LInstruction[] instructions = { ins }; split.setInstructions(instructions); block.replaceSuccessor(j, split); target.replacePredecessor(block, split); split.addPredecessor(block); } } }
public LBlock parse() { for (int i = 0; i < lir_.instructions.Count; i++) { LInstruction ins = lir_.instructions[i]; if (lir_.isTarget(ins.pc)) { // This instruction is the target of a basic block, so // finish the old one. LBlock next = lir_.blockOfTarget(ins.pc); // Multiple instructions could be at the same pc, // because of decomposition, so make sure we're not // transitioning to the same block. if (block_ != next) { // Add implicit control flow to make further algorithms easier. if (block_ != null) { //Debug.Assert(!pending_[pending_.Count - 1].isControl()); pending_.Add(new LGoto(next)); next.addPredecessor(block_); } // Fallthrough to the next block. transitionBlocks(next); } } // If there is no block present, we assume this is dead code. if (block_ == null) { continue; } pending_.Add(ins); switch (ins.op) { case Opcode.Return: { // A return terminates the current block. transitionBlocks(null); break; } case Opcode.Jump: { LJump jump = (LJump)ins; jump.target.addPredecessor(block_); transitionBlocks(null); break; } case Opcode.JumpCondition: { LJumpCondition jcc = (LJumpCondition)ins; jcc.trueTarget.addPredecessor(block_); jcc.falseTarget.addPredecessor(block_); // The next iteration will pick the false target up. //Debug.Assert(lir_.instructions[i + 1].pc == jcc.falseTarget.pc); transitionBlocks(null); break; } case Opcode.Switch: { LSwitch switch_ = (LSwitch)ins; for (int j = 0; j < switch_.numSuccessors; j++) { switch_.getSuccessor(j).addPredecessor(block_); } transitionBlocks(null); break; } } } return(lir_.entry); }
// Split critical edges in the graph. A critical edge is an edge which // is neither its successor's only predecessor, nor its predecessor's // only successor. Critical edges must be split to prevent copy-insertion // and code motion from affecting other edges. It is probably not strictly // needed here. public static void SplitCriticalEdges(LBlock[] blocks) { for (int i = 0; i < blocks.Length; i++) { LBlock block = blocks[i]; if (block.numSuccessors < 2) continue; for (int j = 0; j < block.numSuccessors; j++) { LBlock target = block.getSuccessor(j); if (target.numPredecessors < 2) continue; // Create a new block inheriting from the predecessor. LBlock split = new LBlock(block.pc); LGoto ins = new LGoto(target); LInstruction[] instructions = { ins }; split.setInstructions(instructions); block.replaceSuccessor(j, split); target.replacePredecessor(block, split); split.addPredecessor(block); } } }