// From Engineering a Compiler (Cooper, Torczon) public static bool IsReducible(LBlock[] blocks) { // Copy the graph into a temporary mutable structure. var rblocks = new RBlock[blocks.Length]; for (var i = 0; i < blocks.Length; i++) { rblocks[i] = new RBlock(i); } for (var i = 0; i < blocks.Length; i++) { var block = blocks[i]; var rblock = rblocks[i]; for (var j = 0; j < block.numPredecessors; j++) { rblock.predecessors.Add(rblocks[block.getPredecessor(j).id]); } for (var j = 0; j < block.numSuccessors; j++) { rblock.successors.Add(rblocks[block.getSuccessor(j).id]); } } // Okay, start reducing. var queue = new LinkedList <RBlock>(rblocks); for (; ;) { var deleteQueue = new List <RBlock>(); foreach (var rblock in queue) { // Transformation T1, remove self-edges. if (rblock.predecessors.Contains(rblock)) { rblock.predecessors.Remove(rblock); } if (rblock.successors.Contains(rblock)) { rblock.successors.Remove(rblock); } // Transformation T2, remove blocks with one predecessor, // reroute successors' predecessors. if (rblock.predecessors.Count == 1) { // Mark this node for removal since C# sucks and can't delete during iteration. deleteQueue.Add(rblock); var predecessor = rblock.predecessors[0]; // Delete the edge from pred -> me predecessor.successors.Remove(rblock); for (var i = 0; i < rblock.successors.Count; i++) { var successor = rblock.successors[i]; //Debug.Assert(successor.predecessors.Contains(rblock)); successor.predecessors.Remove(rblock); if (!successor.predecessors.Contains(predecessor)) { successor.predecessors.Add(predecessor); } if (!predecessor.successors.Contains(successor)) { predecessor.successors.Add(successor); } } } } if (deleteQueue.Count == 0) { break; } foreach (var rblock in deleteQueue) { queue.Remove(rblock); } } // If the graph reduced to one node, it was reducible. return(queue.Count == 1); }
// From Engineering a Compiler (Cooper, Torczon) public static bool IsReducible(LBlock[] blocks) { // Copy the graph into a temporary mutable structure. RBlock[] rblocks = new RBlock[blocks.Length]; for (int i = 0; i < blocks.Length; i++) rblocks[i] = new RBlock(i); for (int i = 0; i < blocks.Length; i++) { LBlock block = blocks[i]; RBlock rblock = rblocks[i]; for (int j = 0; j < block.numPredecessors; j++) rblock.predecessors.Add(rblocks[block.getPredecessor(j).id]); for (int j = 0; j < block.numSuccessors; j++) rblock.successors.Add(rblocks[block.getSuccessor(j).id]); } // Okay, start reducing. LinkedList<RBlock> queue = new LinkedList<RBlock>(rblocks); for (;;) { List<RBlock> deleteQueue = new List<RBlock>(); foreach (RBlock rblock in queue) { // Transformation T1, remove self-edges. if (rblock.predecessors.Contains(rblock)) rblock.predecessors.Remove(rblock); if (rblock.successors.Contains(rblock)) rblock.successors.Remove(rblock); // Transformation T2, remove blocks with one predecessor, // reroute successors' predecessors. if (rblock.predecessors.Count == 1) { // Mark this node for removal since C# sucks and can't delete during iteration. deleteQueue.Add(rblock); RBlock predecessor = rblock.predecessors[0]; // Delete the edge from pred -> me predecessor.successors.Remove(rblock); for (int i = 0; i < rblock.successors.Count; i++) { RBlock successor = rblock.successors[i]; //Debug.Assert(successor.predecessors.Contains(rblock)); successor.predecessors.Remove(rblock); if (!successor.predecessors.Contains(predecessor)) successor.predecessors.Add(predecessor); if (!predecessor.successors.Contains(successor)) predecessor.successors.Add(successor); } } } if (deleteQueue.Count == 0) break; foreach (RBlock rblock in deleteQueue) queue.Remove(rblock); } // If the graph reduced to one node, it was reducible. return queue.Count == 1; }