public void removeUse(int index, DNode node) { DUse use = null; foreach (var u in uses) { if (u.index == index && u.node == node) { use = u; break; } } //Debug.Assert(use != null); uses.Remove(use); }
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 bool AnalyzeHeapNode(NodeBlock block, DHeap node) { // Easy case: compiler needed a lvalue. if (node.uses.Count == 2) { DUse lastUse = node.uses.Last(); DUse firstUse = node.uses.First(); if ((lastUse.node.type == NodeType.Call || lastUse.node.type == NodeType.SysReq) && firstUse.node.type == NodeType.Store && firstUse.index == 0) { lastUse.node.replaceOperand(lastUse.index, firstUse.node.getOperand(1)); return(true); } if ((lastUse.node.type == NodeType.Call || lastUse.node.type == NodeType.SysReq) && firstUse.node.type == NodeType.MemCopy && firstUse.index == 0) { // heap -> memcpy always reads from DAT + constant DMemCopy memcopy = (DMemCopy)firstUse.node; DConstant cv = (DConstant)memcopy.from; DInlineArray ia = new DInlineArray(cv.value, memcopy.bytes); block.nodes.insertAfter(node, ia); lastUse.node.replaceOperand(lastUse.index, ia); // Give the inline array some type information. Signature signature = SignatureOf(lastUse.node); TypeUnit tu = TypeUnit.FromArgument(signature.args[lastUse.index]); ia.addType(tu); return(true); } } return(false); }
private void renameBlock(NodeBlock block) { for (NodeList.iterator iter = block.nodes.begin(); iter.more();) { DNode node = iter.node; switch (node.type) { case NodeType.TempName: case NodeType.Jump: case NodeType.JumpCondition: case NodeType.Store: case NodeType.Return: case NodeType.IncDec: case NodeType.DeclareStatic: case NodeType.Switch: { iter.next(); continue; } case NodeType.DeclareLocal: { DDeclareLocal decl = (DDeclareLocal)node; if (decl.var == null) { if (decl.uses.Count <= 1) { // 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); } block.nodes.remove(iter); continue; } DTempName name = new DTempName(graph_.tempName()); node.replaceAllUsesWith(name); name.init(decl.value); block.nodes.replace(iter, name); } iter.next(); continue; } case NodeType.SysReq: case NodeType.Call: { // Calls are statements or expressions, so we can't // remove them if they have no uses. if (node.uses.Count <= 1) { if (node.uses.Count == 1) { block.nodes.remove(iter); } else { iter.next(); } continue; } break; } case NodeType.Constant: { // Constants can be deeply copied. block.nodes.remove(iter); continue; } default: { if (node.uses.Count <= 1) { // This node has one or zero uses, so instead of // renaming it, we remove it from the instruction // stream. This way the source printer will deep- // print it instead of using its 'SSA' name. block.nodes.remove(iter); continue; } break; } } // If we've reached here, the expression has more than one use // and we have to wrap it in some kind of name, lest we // duplicate it in the expression tree which may be illegal. DTempName replacement = new DTempName(graph_.tempName()); node.replaceAllUsesWith(replacement); replacement.init(node); block.nodes.replace(iter, replacement); iter.next(); } }