public static bool HasMoreThanOneUses(PStm statement, AALocalDecl decl, SharedData data, out ALocalLvalue lvalue) { GetUses uses = new GetUses(decl, data); statement.Apply(uses); lvalue = uses.lvalue; return(uses.count > 1); }
public static bool Parse(ControlFlowGraph cfg, SharedData data) { Dictionary <PStm, ControlFlowGraph.Node> statementNodes = new Dictionary <PStm, ControlFlowGraph.Node>(); //Dictionary<ControlFlowGraph.Node, List<AALocalDecl>> uses = new Dictionary<ControlFlowGraph.Node, List<AALocalDecl>>(); foreach (ControlFlowGraph.Node node in cfg.Nodes) { statementNodes[node.Statement] = node; /*GetUses getUses = new GetUses(); * node.Statement.Apply(getUses); * uses[node] = getUses.Uses;*/ } foreach (ControlFlowGraph.Node node in cfg.Nodes) { if (node.Expression is AAssignmentExp) { AAssignmentExp exp = (AAssignmentExp)node.Expression; if (exp.GetLvalue() is ALocalLvalue) { AALocalDecl decl = data.LocalLinks[(ALocalLvalue)exp.GetLvalue()]; bool dontMove = false; LocalChecker.ModifyData declModData = LocalChecker.GetLocalData(node.Expression, data); /*1: Search for unique use of decl * Stop if you find an assignment to decl * Stop if decl is not live * Cancel if you find two uses of decl (also within one statement) */ ControlFlowGraph.Node useNode = null; LinkedList <ControlFlowGraph.Node> nextNodes = new LinkedList <ControlFlowGraph.Node>(); LinkedList <ControlFlowGraph.Node> visitedNodes = new LinkedList <ControlFlowGraph.Node>(); foreach (var successor in node.Successors) { nextNodes.AddLast(successor); } while (nextNodes.Count > 0) { ControlFlowGraph.Node successor = nextNodes.First.Value; nextNodes.RemoveFirst(); visitedNodes.AddLast(successor); LocalChecker.ModifyData succData = LocalChecker.GetLocalData(successor.Expression, data); //Stop if decl is not live if (!successor.LiveVariables.Contains(decl)) { continue; } //Check if this node uses it) if (succData.Locals.ContainsKey(decl)) { var val = succData.Locals[decl]; if (val.Reads) { if (useNode == null) { useNode = successor; } else { //Cancel if we found two uses dontMove = true; break; } } //Stop if it writes to the variable if (val.Writes) { continue; } } foreach (ControlFlowGraph.Node nextSucc in successor.Successors) { if (visitedNodes.Contains(nextSucc)) { continue; } nextNodes.AddLast(nextSucc); } } ALocalLvalue usedLvalue; if (dontMove || useNode == null || //Cancel if there are two uses of the local within same statement GetUses.HasMoreThanOneUses(useNode.Statement, decl, data, out usedLvalue)) { continue; } /*2: Search back from found statement, to ensure unique assignment * Stop if assignment reached * Cancel if start of method is reached * Cancel if any statement reads/writes to a variable used in the statement (where one of them writes) * Cancel if another assignment to x is found (including local decls) */ visitedNodes.Clear(); nextNodes.Clear(); foreach (ControlFlowGraph.Node predecessor in useNode.Predecessors) { nextNodes.AddLast(predecessor); } while (nextNodes.Count > 0) { ControlFlowGraph.Node predecessor = nextNodes.First.Value; nextNodes.RemoveFirst(); visitedNodes.AddLast(predecessor); LocalChecker.ModifyData predData = LocalChecker.GetLocalData(predecessor.Expression, data); //Stop if assignment reached if (predecessor == node) { continue; } //Cancel if this statement writes to decl if (predData.Locals.ContainsKey(decl) && predData.Locals[decl].Writes || predecessor.Statement is ALocalDeclStm && ((ALocalDeclStm)predecessor.Statement).GetLocalDecl() == decl) { dontMove = true; break; } //Cancel if any statement reads/writes to a variable used in the statement (where one of them writes) if (declModData.Conflicts(predData)) { dontMove = true; break; } //Cancel if start of method is reached if (predecessor.Predecessors.Count == 0) { dontMove = true; break; } foreach (ControlFlowGraph.Node nextPred in predecessor.Predecessors) { if (visitedNodes.Contains(nextPred)) { continue; } nextNodes.AddLast(nextPred); } } if (dontMove) { continue; } //Move it cfg.Remove(node); node.Statement.Parent().RemoveChild(node.Statement); usedLvalue.Parent().ReplaceBy(exp.GetExp()); //We now need to redo liveness analysis return(true); } } } return(false); }
public static bool HasMoreThanOneUses(PStm statement, AALocalDecl decl, SharedData data, out ALocalLvalue lvalue) { GetUses uses = new GetUses(decl, data); statement.Apply(uses); lvalue = uses.lvalue; return uses.count > 1; }