public static bool Parse(ControlFlowGraph cfg, SharedData data) { List<AALocalDecl> usedLocals = GetUsedLocals.Parse(cfg.Method.GetBlock(), data); List<ControlFlowGraph.Node> modifications = new List<ControlFlowGraph.Node>(); foreach (ControlFlowGraph.Node node in cfg.Nodes) { if (node.Statement is ALocalDeclStm) { AALocalDecl decl = (AALocalDecl) ((ALocalDeclStm) node.Statement).GetLocalDecl(); if (!usedLocals.Contains(decl)) { modifications.Add(node); } } else { break; } } foreach (ControlFlowGraph.Node node in modifications) { cfg.Remove(node); node.Statement.Parent().RemoveChild(node.Statement); } return modifications.Count > 0; }
private static void Join(ControlFlowGraph.Node node) { foreach (ControlFlowGraph.Node successor in node.Successors) { node.LiveVariables.Union(successor.LiveVariables); } }
public static void CalculateLiveVariables(ControlFlowGraph cfg, SharedData data) { //First, generate lists of what is used in each node Dictionary<ControlFlowGraph.Node, List<AALocalDecl>> usedVars = new Dictionary<ControlFlowGraph.Node, List<AALocalDecl>>(); foreach (ControlFlowGraph.Node node in cfg.Nodes) { node.LiveVariables.Clear(); PExp exp = node.Expression; if (exp == null) usedVars[node] = new List<AALocalDecl>(); else { GetUsedVariables variableFinder = new GetUsedVariables(data); exp.Apply(variableFinder); usedVars[node] = variableFinder.UsedLocals; } } bool changed = true; while (changed) { changed = false; foreach (ControlFlowGraph.Node node in cfg.Nodes) { int count = node.LiveVariables.Count; Join(node); node.LiveVariables.Subtract(GetAssignedTo(node, data)); node.LiveVariables.Union(usedVars[node]); changed |= count != node.LiveVariables.Count; } } }
public static ControlFlowGraph Create(AMethodDecl method) { ControlFlowGraph graph = new ControlFlowGraph(method); CFGGenerator generator = new CFGGenerator(); method.GetBlock().Apply(generator); graph.Nodes = new List<Node>(generator.Nodes.Count); graph.Nodes.AddRange(generator.Nodes); return graph; }
public static bool Parse(ControlFlowGraph cfg, SharedData data, out bool redoLivenessAnalysis) { bool changed = false; redoLivenessAnalysis = false; Dictionary<ControlFlowGraph.Node, List<ASimpleInvokeExp>> Modifications = new Dictionary<ControlFlowGraph.Node, List<ASimpleInvokeExp>>(); 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()]; //If the variable is not live at any successors, remove this assignment bool inUse = false; foreach (ControlFlowGraph.Node successor in node.Successors) { if (successor.LiveVariables.Contains(decl)) { inUse = true; break; } } if (!inUse) { //Move method invokes out GetMethodInvokes getter = new GetMethodInvokes(); exp.GetExp().Apply(getter); //Might also have to redo because we removed a reference to a variable in the right side //if (getter.Invokes.Count > 0) redoLivenessAnalysis = true; Modifications[node] = getter.Invokes; changed = true; } } } } foreach (KeyValuePair<ControlFlowGraph.Node, List<ASimpleInvokeExp>> pair in Modifications) { ControlFlowGraph.Node node = pair.Key; foreach (ASimpleInvokeExp invoke in pair.Value) { AExpStm stm = new AExpStm(new TSemicolon(";"), invoke); AABlock pBlock = (AABlock) node.Statement.Parent(); pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(node.Statement), stm); cfg.Insert(node, stm); } cfg.Remove(node); node.Statement.Parent().RemoveChild(node.Statement); } return changed; }
public static void Parse(ControlFlowGraph graph ) { for (int i = 1; i < graph.Nodes.Count; i++) { ControlFlowGraph.Node n = graph.Nodes[i]; if (n.Predecessors.Count == 0) { n.Statement.Parent().RemoveChild(n.Statement); graph.Remove(n); i--; } } }
private static List<AALocalDecl> GetAssignedTo(ControlFlowGraph.Node node, SharedData data) { if (node.Statement is ALocalDeclStm) return new List<AALocalDecl>(){(AALocalDecl) ((ALocalDeclStm)node.Statement).GetLocalDecl()}; PExp exp = node.Expression; if (exp != null && exp is AAssignmentExp) { AAssignmentExp aExp = (AAssignmentExp) exp; if (aExp.GetLvalue() is ALocalLvalue) return new List<AALocalDecl>(){data.LocalLinks[(ALocalLvalue) aExp.GetLvalue()]}; } return new List<AALocalDecl>(); }
public static bool Parse(ControlFlowGraph cfg, SharedData data) { //List of locals by type List <List <AALocalDecl> > locals = new List <List <AALocalDecl> >(); //Locals -> cfg node Dictionary <AALocalDecl, ControlFlowGraph.Node> localNodes = new Dictionary <AALocalDecl, ControlFlowGraph.Node>(); foreach (AALocalDecl formal in cfg.Method.GetFormals()) { bool added = false; foreach (List <AALocalDecl> list in locals) { if (Util.TypesEqual(list[0].GetType(), formal.GetType(), data)) { list.Add(formal); added = true; break; } } if (!added) { locals.Add(new List <AALocalDecl>() { formal }); } } foreach (ControlFlowGraph.Node node in cfg.Nodes) { //Locals have been moved to the top if (!(node.Statement is ALocalDeclStm)) { break; } AALocalDecl decl = (AALocalDecl)((ALocalDeclStm)node.Statement).GetLocalDecl(); localNodes[decl] = node; bool added = false; foreach (List <AALocalDecl> list in locals) { if (Util.TypesEqual(list[0].GetType(), decl.GetType(), data)) { list.Add(decl); added = true; break; } } if (!added) { locals.Add(new List <AALocalDecl>() { decl }); } } bool joinedSomething = false; foreach (List <AALocalDecl> list in locals) { for (int i = 0; i < list.Count; i++) { for (int j = i + 1; j < list.Count; j++) { //Can't join if both are formals if (list[i].Parent() is AMethodDecl && list[j].Parent() is AMethodDecl) { continue; } //Can't join if both are live at the same time bool canJoin = true; foreach (ControlFlowGraph.Node cfgNode in cfg.Nodes) { if (cfgNode.LiveVariables.Contains(list[i]) && cfgNode.LiveVariables.Contains(list[j])) { canJoin = false; break; } } if (!canJoin) { continue; } joinedSomething = true; Join(list[i], list[j], cfg, localNodes, data); list.RemoveAt(j); j--; } } } return(joinedSomething); }
private static void Join(AALocalDecl decl1, AALocalDecl decl2, ControlFlowGraph cfg, Dictionary<AALocalDecl, ControlFlowGraph.Node> localNodes, SharedData data) { //Remove decl2 from cfg //decl2 can't be a formal, since formals was first in the list, and two formals wont be joined. ControlFlowGraph.Node cfgNode2 = localNodes[decl2]; cfg.Remove(cfgNode2); //Remove decl2 from the ast cfgNode2.Statement.Parent().RemoveChild(cfgNode2.Statement); //Go through cfg and make live decl2 variables become live decl1 variables.)); foreach (ControlFlowGraph.Node cfgNode in cfg.Nodes) { if (cfgNode.LiveVariables.Contains(decl2)) { cfgNode.LiveVariables.Remove(decl2); cfgNode.LiveVariables.Add(decl1); } } //Rename all refferences to decl2 to be decl1 LinkedList<ALocalLvalue> keys = new LinkedList<ALocalLvalue>(); foreach (KeyValuePair<ALocalLvalue, AALocalDecl> pair in data.LocalLinks) { if (pair.Value == decl2) keys.AddLast(pair.Key); } foreach (ALocalLvalue key in keys) { data.LocalLinks[key] = decl1; } }
public static bool Parse(ControlFlowGraph cfg, SharedData data) { //List of locals by type List<List<AALocalDecl>> locals = new List<List<AALocalDecl>>(); //Locals -> cfg node Dictionary<AALocalDecl, ControlFlowGraph.Node> localNodes = new Dictionary<AALocalDecl, ControlFlowGraph.Node>(); foreach (AALocalDecl formal in cfg.Method.GetFormals()) { bool added = false; foreach (List<AALocalDecl> list in locals) { if (Util.TypesEqual(list[0].GetType(), formal.GetType(), data)) { list.Add(formal); added = true; break; } } if (!added) locals.Add(new List<AALocalDecl>(){formal}); } foreach (ControlFlowGraph.Node node in cfg.Nodes) { //Locals have been moved to the top if (!(node.Statement is ALocalDeclStm)) break; AALocalDecl decl = (AALocalDecl) ((ALocalDeclStm) node.Statement).GetLocalDecl(); localNodes[decl] = node; bool added = false; foreach (List<AALocalDecl> list in locals) { if (Util.TypesEqual(list[0].GetType(), decl.GetType(), data)) { list.Add(decl); added = true; break; } } if (!added) locals.Add(new List<AALocalDecl>() {decl}); } bool joinedSomething = false; foreach (List<AALocalDecl> list in locals) { for (int i = 0; i < list.Count; i++) { for (int j = i + 1; j < list.Count; j++) { //Can't join if both are formals if (list[i].Parent() is AMethodDecl && list[j].Parent() is AMethodDecl) continue; //Can't join if both are live at the same time bool canJoin = true; foreach (ControlFlowGraph.Node cfgNode in cfg.Nodes) { if (cfgNode.LiveVariables.Contains(list[i]) && cfgNode.LiveVariables.Contains(list[j])) { canJoin = false; break; } } if (!canJoin) continue; joinedSomething = true; Join(list[i], list[j], cfg, localNodes, data); list.RemoveAt(j); j--; } } } return joinedSomething; }
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; }