public static void ComputeDominators(LBlock[] blocks) { BitArray[] doms = new BitArray[blocks.Length]; for (int i = 0; i < doms.Length; i++) { doms[i] = new BitArray(doms.Length); } doms[0].Set(0, true); for (int i = 1; i < blocks.Length; i++) { for (int j = 0; j < blocks.Length; j++) { doms[i].SetAll(true); } } // Compute dominators. bool changed; do { changed = false; for (int i = 1; i < blocks.Length; i++) { LBlock block = blocks[i]; for (int j = 0; j < block.numPredecessors; j++) { LBlock pred = block.getPredecessor(j); BitArray u = new BitArray(doms[i]); doms[block.id].And(doms[pred.id]); doms[block.id].Set(block.id, true); if (!CompareBitArrays(doms[block.id], u)) { changed = true; } } } }while (changed); // Turn the bit vectors into lists. for (int i = 0; i < blocks.Length; i++) { LBlock block = blocks[i]; List <LBlock> list = new List <LBlock>(); for (int j = 0; j < blocks.Length; j++) { if (doms[block.id][j]) { list.Add(blocks[j]); } } block.setDominators(list.ToArray()); } }
public void scan(LBlock block) { for (var i = 0; i < block.numPredecessors; i++) { var pred = block.getPredecessor(i); // Has this block already been scanned? if (pred.loop == backedge_.loop) { continue; } pred = SkipContainedLoop(pred, backedge_.loop); // If this assert hits, there is probably a |break| keyword. //Debug.Assert(pred.loop == null || pred.loop == backedge_.loop); if (pred.loop != null) { continue; } stack_.Push(pred); } }
private ControlType findLoopJoinAndBody(NodeBlock header, NodeBlock effectiveHeader, out NodeBlock join, out NodeBlock body, out NodeBlock cond) { //Debug.Assert(effectiveHeader.lir.numSuccessors == 2); LBlock succ1 = effectiveHeader.lir.getSuccessor(0); LBlock succ2 = effectiveHeader.lir.getSuccessor(1); if (succ1.loop != header.lir || succ2.loop != header.lir) { //Debug.Assert(succ1.loop == header.lir || succ2.loop == header.lir); if (succ1.loop != header.lir) { join = graph_[succ1.id]; body = graph_[succ2.id]; } else { join = graph_[succ2.id]; body = graph_[succ1.id]; } cond = header; // If this is a self-loop, it is more correct to decompose it // to a do-while loop. This may not be source accurate in the // case of something like |while (x);| but it catches many more // source-accurate cases. if (header == effectiveHeader && BlockAnalysis.GetEmptyTarget(body) == header) { body = null; return(ControlType.DoWhileLoop); } return(ControlType.WhileLoop); } else { // Neither successor of the header exits the loop, so this is // probably a do-while loop. For now, assume it's simple. //Debug.Assert(header == effectiveHeader); LBlock backedge = header.lir.backedge; if (BlockAnalysis.GetEmptyTarget(graph_[backedge.id]) == header) { // Skip an empty block sitting in between the backedge and // the condition. //Debug.Assert(backedge.numPredecessors == 1); backedge = backedge.getPredecessor(0); } //Debug.Assert(backedge.numSuccessors == 2); succ1 = backedge.getSuccessor(0); succ2 = backedge.getSuccessor(1); body = header; cond = graph_[backedge.id]; if (succ1.loop != header.lir) { join = graph_[succ1.id]; } else { //Debug.Assert(succ2.loop != header.lir); join = graph_[succ2.id]; } return(ControlType.DoWhileLoop); } }
public void scan(LBlock block) { for (int i = 0; i < block.numPredecessors; i++) { LBlock pred = block.getPredecessor(i); // Has this block already been scanned? if (pred.loop == backedge_.loop) continue; pred = SkipContainedLoop(pred, backedge_.loop); // If this assert hits, there is probably a |break| keyword. //Debug.Assert(pred.loop == null || pred.loop == backedge_.loop); if (pred.loop != null) continue; stack_.Push(pred); } }
// 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); }