public void ReachingDefinitions() { var program = @" var i, m, j, n, a, u1, u2, u3, k; 1: i = m - 1; 2: j = n; 3: a = u1; for k = 0, 1 { i = i + 1; j = j - 1; if i < j a = u2; i = u3; } "; var graph = GenCFG(program); var algorithm = new LiveVariables(); _ = algorithm.Execute(graph); var iterationsFast = algorithm.Iterations; _ = algorithm.Execute(graph, false); var iterationsSlow = algorithm.Iterations; Assert.LessOrEqual(iterationsFast, iterationsSlow); }
public void LiveVariables() { var program = @" var a, b, c, i; for i = 1, b { input(a); c = c + a; print(c); if c < b c = c + 1; else { b = b - 1; print(b); print(c); } } print(c + a + b); "; var graph = GenCFG(program); var algorithm = new LiveVariables(); _ = algorithm.Execute(graph); var iterationsFast = algorithm.Iterations; _ = algorithm.Execute(graph, false); var iterationsSlow = algorithm.Iterations; Assert.LessOrEqual(iterationsFast, iterationsSlow); }
private List <(HashSet <string> IN, HashSet <string> OUT)> Execute(List <Instruction> TAC) { var cfg = GenCFG(TAC); var liveAct = new LiveVariables(); liveAct.ExecuteInternal(cfg); var listAct = liveAct.dictInOut .Select(x => x.Value) .Select(y => (y.IN as HashSet <string>, y.OUT as HashSet <string>)); return(listAct.ToList()); }
public static void DeleteDeadCode(ControlFlowGraph cfg) { var info = new LiveVariables().Execute(cfg); foreach (var block in cfg.GetCurrentBasicBlocks()) { var blockInfo = info[block].Out; (var wasChanged, var newInstructions) = DeleteDeadCodeWithDeadVars.DeleteDeadCode(block.GetInstructions(), blockInfo); if (wasChanged) { block.ClearInstructions(); block.AddRangeOfInstructions(newInstructions); } } }
private void Transform(FunctionDeclarationSyntax function, LiveVariables liveness) { var graph = function.ControlFlow; var builder = new ControlFlowGraphBuilder(graph.VariableDeclarations); foreach (var block in graph.BasicBlocks) { var blockBuilder = builder.NewBlock(); if (block.Number != blockBuilder.BlockNumber) { throw new Exception("New block number does not match old block number"); } foreach (var statement in block.ExpressionStatements) { // Copy the existing statement blockBuilder.Add(statement); var before = liveness.Before(statement); var after = liveness.After(statement); // dead = live before and not live after var dead = ((BitArray)after.Clone()).Not().And(before); foreach (var variableNumber in dead.TrueIndexes()) { var variable = graph.VariableDeclarations[variableNumber]; if (variable.Type is ObjectType type && type.IsOwned) { // The delete happens after the last statement var span = new TextSpan(statement.Span.End, 0); blockBuilder.AddDelete(new VariableReference(variableNumber, span), type, span); } } } // TODO what about if there is a variable delete after the terminator? blockBuilder.Add(block.Terminator); } function.ControlFlow = builder.Build(); }
public static void Main() { var FileName = @"../../../a.txt"; try { var Text = File.ReadAllText(FileName); var scanner = new Scanner(); scanner.SetSource(Text, 0); var parser = new Parser(scanner); var b = parser.Parse(); if (!b) { Console.WriteLine("Error"); } else { Console.WriteLine("Syntax tree built"); var fillParents = new FillParentsVisitor(); parser.root.Visit(fillParents); var pp = new PrettyPrintVisitor(); parser.root.Visit(pp); Console.WriteLine(pp.Text); ASTOptimizer.Optimize(parser); Console.WriteLine("\n\nAfter AST optimizations"); pp = new PrettyPrintVisitor(); parser.root.Visit(pp); Console.WriteLine(pp.Text); Console.WriteLine("\n\nThree address code"); var threeAddrCodeVisitor = new ThreeAddrGenVisitor(); parser.root.Visit(threeAddrCodeVisitor); var threeAddressCode = threeAddrCodeVisitor.Instructions; foreach (var instruction in threeAddressCode) { Console.WriteLine(instruction); } Console.WriteLine("\n\nOptimized three address code"); var optResult = ThreeAddressCodeOptimizer.OptimizeAll(threeAddressCode); foreach (var x in optResult) { Console.WriteLine(x); } Console.WriteLine("\n\nDivided three address code"); var divResult = BasicBlockLeader.DivideLeaderToLeader(optResult); foreach (var x in divResult) { foreach (var y in x.GetInstructions()) { Console.WriteLine(y); } Console.WriteLine("--------------"); } var cfg = new ControlFlowGraph(divResult); Console.WriteLine("\n\n Edge Classification"); Console.WriteLine("----------"); foreach (var pair in cfg.ClassifiedEdges) { Console.WriteLine(pair); } Console.WriteLine("----------"); foreach (var block in cfg.GetCurrentBasicBlocks()) { Console.WriteLine($"{cfg.VertexOf(block)} {block.GetInstructions()[0]}"); var children = cfg.GetChildrenBasicBlocks(cfg.VertexOf(block)); var childrenStr = string.Join(" | ", children.Select(v => v.block.GetInstructions()[0].ToString())); Console.WriteLine($" children: {childrenStr}"); var parents = cfg.GetParentsBasicBlocks(cfg.VertexOf(block)); var parentsStr = string.Join(" | ", parents.Select(v => v.block.GetInstructions()[0].ToString())); Console.WriteLine($" parents: {parentsStr}"); } /// /// LiveVariableAnalysisAlgorithm /// Console.WriteLine("------------"); Console.WriteLine(); var activeVariable = new LiveVariables(); var resActiveVariable = activeVariable.Execute(cfg); foreach (var x in resActiveVariable) { foreach (var y in x.Value.In) { Console.WriteLine("In " + y); } Console.WriteLine(); foreach (var y in x.Value.Out) { Console.WriteLine("Out " + y); } } Console.WriteLine(); Console.WriteLine(); Console.WriteLine("NatLoop"); var natLoops = NaturalLoop.GetAllNaturalLoops(cfg); foreach (var x in natLoops) { if (x.Count == 0) { continue; } //Console.WriteLine("Loop"); for (var i = 0; i < x.Count; i++) { Console.WriteLine("NumberBlock:" + i); foreach (var xfrom in x[i].GetInstructions()) { Console.WriteLine(xfrom.ToString()); } } Console.WriteLine(); Console.WriteLine("-------------"); } Console.WriteLine(" \nDone"); } } catch (FileNotFoundException) { Console.WriteLine("File {0} not found", FileName); } catch (LexException e) { Console.WriteLine("Lex Error. " + e.Message); } catch (SyntaxException e) { Console.WriteLine("Syntax Error. " + e.Message); } _ = Console.ReadLine(); }
public void LiveVariables() { var program = @" var a, b, c; input(b); a = b + 1; if a < c c = b - a; else c = b + a; print(c); "; var cfg = GenCFG(program); var resActiveVariable = new LiveVariables().Execute(cfg); var actual = cfg.GetCurrentBasicBlocks() .Select(z => resActiveVariable[z]) .Select(p => ((IEnumerable <string>)p.In, (IEnumerable <string>)p.Out)) .ToList(); var expected = new List <(IEnumerable <string>, IEnumerable <string>)>() { (new HashSet <string>() { "c" }, new HashSet <string>() { "c" }), (new HashSet <string>() { "c" }, new HashSet <string>() { "a", "b" }), (new HashSet <string>() { "a", "b" }, new HashSet <string>() { "c" }), (new HashSet <string>() { "a", "b" }, new HashSet <string>() { "c" }), (new HashSet <string>() { "c" }, new HashSet <string>() { }), (new HashSet <string>() { }, new HashSet <string>() { }) }; AssertSet(expected, actual); }
private static LiveVariables ComputeLiveness(ControlFlowGraph function, Edges edges) { var blocks = new Queue <BasicBlock>(); blocks.EnqueueRange(function.ExitBlocks); var liveVariables = new LiveVariables(function); var numberOfVariables = function.VariableDeclarations.Count; while (blocks.TryDequeue(out var block)) { var liveBeforeBlock = new BitArray(liveVariables.Before(block.Statements.First())); var liveAfterBlock = new BitArray(numberOfVariables); foreach (var successor in edges.From(block)) { liveAfterBlock.Or(liveVariables.Before(successor.Statements.Last())); } var liveAfterStatement = liveAfterBlock; foreach (var statement in block.Statements.Reverse()) { var liveSet = liveVariables.Before(statement); liveSet.Or(liveAfterStatement); switch (statement) { case AssignmentStatement assignment: KillVariables(liveSet, assignment.Place); EnlivenVariables(liveSet, assignment.Value); break; case ActionStatement action: EnlivenVariables(liveSet, action.Value); break; case DeleteStatement _: throw new InvalidOperationException("Delete statements are supposed to be added after liveness analysis"); //liveSet[deleteStatement.Place.CoreVariable()] = true; //break; case IfStatement _: case GotoStatement _: // We already or'ed together the live variables from successor blocks break; case ReturnStatement _: // No effect on variables? // TODO should we check the liveSet is empty? break; default: throw NonExhaustiveMatchException.For(statement); } // For the next statement liveAfterStatement = liveSet; } if (!liveBeforeBlock.ValuesEqual(liveVariables.Before(block.Statements.First()))) { foreach (var basicBlock in edges.To(block) .Where(fromBlock => !blocks.Contains(fromBlock)).ToList()) { blocks.Enqueue(basicBlock); } } } return(liveVariables); }