public void propagate() { for (int i = graph_.numBlocks - 1; i >= 0; i--) { block_ = graph_[i]; for (NodeList.reverse_iterator iter = block_.nodes.rbegin(); iter.more(); iter.next()) { iter.node.accept(this); } } }
private static void AnalyzeHeapUsage(NodeBlock block) { for (NodeList.reverse_iterator riter = block.nodes.rbegin(); riter.more(); riter.next()) { if (riter.node.type == NodeType.Heap) { if (AnalyzeHeapNode(block, (DHeap)riter.node)) { block.nodes.remove(riter); } } } }
public static void RemoveGuards(NodeGraph graph) { for (int i = graph.numBlocks - 1; i >= 0; i--) { NodeBlock block = graph[i]; for (NodeList.reverse_iterator iter = block.nodes.rbegin(); iter.more();) { if (iter.node.guard) { //Debug.Assert(iter.node.idempotent); iter.node.removeFromUseChains(); block.nodes.remove(iter); continue; } iter.next(); } } }
private static void RemoveDeadCodeInBlock(NodeBlock block) { for (NodeList.reverse_iterator iter = block.nodes.rbegin(); iter.more();) { if (iter.node.type == NodeType.DeclareLocal) { DDeclareLocal decl = (DDeclareLocal)iter.node; if (decl.var == null && (decl.uses.Count == 0 || (decl.uses.Count == 1 && decl.value != null))) { // This was probably just a stack temporary. if (decl.uses.Count == 1) { DUse use = decl.uses.First.Value; use.node.replaceOperand(use.index, decl.value); } iter.node.removeFromUseChains(); block.nodes.remove(iter); continue; } } if ((iter.node.type == NodeType.Store && iter.node.getOperand(0).type == NodeType.Heap && iter.node.getOperand(0).uses.Count == 1)) { iter.node.removeFromUseChains(); block.nodes.remove(iter); } if (!iter.node.idempotent || iter.node.guard || iter.node.uses.Count > 0) { iter.next(); continue; } iter.node.removeFromUseChains(); block.nodes.remove(iter); } }
private static void CoalesceLoadStores(NodeBlock block) { for (NodeList.reverse_iterator riter = block.nodes.rbegin(); riter.more(); riter.next()) { if (riter.node.type != NodeType.Store) { continue; } DStore store = (DStore)riter.node; DNode coalesce = null; if (store.rhs.type == NodeType.Binary) { DBinary rhs = (DBinary)store.rhs; if (rhs.lhs.type == NodeType.Load) { DLoad load = (DLoad)rhs.lhs; if (load.from == store.lhs) { coalesce = rhs.rhs; } else if (load.from.type == NodeType.ArrayRef && store.lhs.type == NodeType.Load) { DArrayRef aref = (DArrayRef)load.from; load = (DLoad)store.lhs; if (aref.abase == load && aref.index.type == NodeType.Constant && ((DConstant)aref.index).value == 0) { coalesce = rhs.rhs; store.replaceOperand(0, aref); } } } if (coalesce != null) { store.makeStoreOp(rhs.spop); } } else if (store.rhs.type == NodeType.Load && store.rhs.getOperand(0) == store.lhs) { // AWFUL PATTERN MATCHING AHEAD. // This *looks* like a dead store, but there is probably // something in between the load and store that changes // the reference. We assume this has to be an incdec. if (store.prev.type == NodeType.IncDec && store.prev.getOperand(0) == store.rhs) { // This detects a weird case in ucp.smx: // v0 = ArrayRef // v1 = Load(v0) // -- Dec(v1) // -- Store(v0, v1) // This appears to be: // *ref = (--*ref) // But, this should suffice: // --*ref store.removeFromUseChains(); block.nodes.remove(riter); //Debug.Assert(riter.node.type == NodeType.IncDec); riter.node.replaceOperand(0, riter.node.getOperand(0).getOperand(0)); } } if (coalesce != null) { store.replaceOperand(1, coalesce); } } }
private static bool CollapseArrayReferences(NodeBlock block) { bool changed = false; for (NodeList.reverse_iterator iter = block.nodes.rbegin(); iter.more(); iter.next()) { DNode node = iter.node; if (node.type == NodeType.Store || node.type == NodeType.Load) { if (node.getOperand(0).type != NodeType.ArrayRef && IsArray(node.getOperand(0).typeSet)) { DConstant index0 = new DConstant(0); DArrayRef aref0 = new DArrayRef(node.getOperand(0), index0, 0); block.nodes.insertBefore(node, index0); block.nodes.insertBefore(node, aref0); node.replaceOperand(0, aref0); continue; } } if (node.type != NodeType.Binary) { continue; } DBinary binary = (DBinary)node; if (binary.spop != SPOpcode.add) { continue; } if (binary.lhs.type == NodeType.LocalRef) { //Debug.Assert(true); } // Check for an array index. DNode abase = GuessArrayBase(binary.lhs, binary.rhs); if (abase == null) { continue; } DNode index = (abase == binary.lhs) ? binary.rhs : binary.lhs; if (!IsReallyLikelyArrayCompute(binary, abase)) { continue; } // Multi-dimensional arrays are indexed like: // x[y] => x + x[y] // // We recognize this and just remove the add, ignoring the // underlying representation of the array. if (index.type == NodeType.Load && index.getOperand(0) == abase) { node.replaceAllUsesWith(index); node.removeFromUseChains(); block.nodes.remove(iter); changed = true; continue; } // Otherwise, create a new array reference. DArrayRef aref = new DArrayRef(abase, index); iter.node.replaceAllUsesWith(aref); iter.node.removeFromUseChains(); block.nodes.remove(iter); block.nodes.insertBefore(iter.node, aref); changed = true; } return(changed); }