public void LoopIndexAssignmentToVariableDeclaredInsideForLoopWithSuccessor() { var source = @"int i; for(i = 0; i < 10; i++) { var x = j; } var y = i;"; var cfg = CreateControlFlowGraph(source); var analysis = LoopDependenceAnalysis.Analyze(cfg, "j"); var xAssignment = cfg.Nodes.Where(statement => (statement.Instruction as Assignment)?.Left.ToString().Equals("x") == true).Single(); Assert.AreEqual(7, analysis.Entry[xAssignment].Count); Assert.AreEqual("{i@, i@, j != 0, j@, j|, j+, x@}", GetString(analysis.Entry[xAssignment])); // x@ here because of the declaration Assert.AreEqual(10, analysis.Exit[xAssignment].Count); Assert.AreEqual("{i@, i@, j != 0, j@, j|, j+, x != 0, x@, x|, x+}", GetString(analysis.Exit[xAssignment])); var iIncrementation = cfg.Nodes.Where(statement => (statement.Instruction as Assignment)?.Left.ToString().Equals("i") == true).Skip(1).Single(); Assert.AreEqual(10, analysis.Entry[iIncrementation].Count); Assert.AreEqual("{i@, i@, j != 0, j@, j|, j+, x != 0, x@, x|, x+}", GetString(analysis.Entry[iIncrementation])); Assert.AreEqual(9, analysis.Exit[iIncrementation].Count); Assert.AreEqual("{i@, j != 0, j@, j|, j+, x != 0, x@, x|, x+}", GetString(analysis.Exit[iIncrementation])); var yAssignment = cfg.Nodes.Where(statement => (statement.Instruction as Assignment)?.Left.ToString().Equals("y") == true).Single(); Assert.AreEqual(11, analysis.Entry[yAssignment].Count); Assert.AreEqual("{i@, i@, j != 0, j@, j|, j+, x != 0, x@, x|, x+, y@}", GetString(analysis.Entry[yAssignment])); Assert.AreEqual(11, analysis.Exit[yAssignment].Count); Assert.AreEqual("{i@, i@, j != 0, j@, j|, j+, x != 0, x@, x|, x+, y@}", GetString(analysis.Exit[yAssignment])); Assert.AreEqual(11, analysis.Entry[cfg.End].Count); Assert.AreEqual("{i@, i@, j != 0, j@, j|, j+, x != 0, x@, x|, x+, y@}", GetString(analysis.Entry[cfg.End])); Assert.AreEqual(11, analysis.Exit[cfg.End].Count); Assert.AreEqual("{i@, i@, j != 0, j@, j|, j+, x != 0, x@, x|, x+, y@}", GetString(analysis.Exit[cfg.End])); }
public void MergeOfDistinctDefinitionsWithSameInformation() { var source = @"if(1 == 1) { x = j + 1; } else { x = j + 2 } y = x;"; var cfg = CreateControlFlowGraph(source); var analysis = LoopDependenceAnalysis.Analyze(cfg, "j"); var plusOneAssignment = cfg.Nodes .Where(statement => statement.Instruction is Assignment assignment && assignment.Right.ToString().Equals("j + 2")) .Single(); var plusTwoAssignment = cfg.Nodes .Where(statement => statement.Instruction is Assignment assignment && assignment.Right.ToString().Equals("j + 2")) .Single(); var xAssignment = cfg.Nodes .Where(statement => statement.Instruction is Assignment assignment && assignment.Right.ToString().Equals("x")) .Single(); Assert.AreEqual(4, analysis.Entry[plusOneAssignment].Count); Assert.AreEqual("{j != 0, j@, j|, j+}", GetString(analysis.Entry[plusOneAssignment])); Assert.AreEqual(8, analysis.Exit[plusOneAssignment].Count); Assert.AreEqual("{j != 0, j@, j|, j+, x != 0, x@, x|, x+}", GetString(analysis.Exit[plusOneAssignment])); Assert.AreEqual(4, analysis.Entry[plusTwoAssignment].Count); Assert.AreEqual("{j != 0, j@, j|, j+}", GetString(analysis.Entry[plusTwoAssignment])); Assert.AreEqual(8, analysis.Exit[plusTwoAssignment].Count); Assert.AreEqual("{j != 0, j@, j|, j+, x != 0, x@, x|, x+}", GetString(analysis.Exit[plusTwoAssignment])); Assert.AreEqual(6, analysis.Entry[xAssignment].Count); Assert.AreEqual("{j != 0, j@, j|, j+, x@, x@}", GetString(analysis.Entry[xAssignment])); Assert.AreEqual(7, analysis.Exit[xAssignment].Count); Assert.AreEqual("{j != 0, j@, j|, j+, x@, x@, y@}", GetString(analysis.Exit[xAssignment])); }
/// <summary> /// Checks that there are no conflicting read and write accesses to arrays. /// </summary> /// <param name="loopIndex">The loop index of the loop that is subject for parallelization.</param> /// <param name="controlFlowGraph">The control flow graph of the body of the loop.</param> /// <param name="aliasAnalysis">A prelimary applied alias analysis already fed with possible aliases outside of the loop.</param> /// <param name="callGraph">The graph identifying the calls of methods for interprocedural analysis.</param> /// <param name="procedures">The control flow graphs of the invoked methods.</param> /// <returns><code>True</code> if there are no conflicting accesses to arrays.</returns> public static bool HasConflictingAccesses(string loopIndex, ControlFlowGraph controlFlowGraph, AliasAnalysis aliasAnalysis, CallGraph callGraph, IEnumerable <ControlFlowGraph> procedures) { var loopDependenceAnalysis = LoopDependenceAnalysis.Analyze(controlFlowGraph, loopIndex, callGraph, procedures); var arrayAccesses = ArrayAccessCollector.Collect(new[] { controlFlowGraph }.Concat(procedures).SelectMany(graph => graph.Nodes)); var verifier = new ArrayAccessVerifier(loopDependenceAnalysis, aliasAnalysis, arrayAccesses); return(verifier._ContainsLoopCarriedDependencies()); }
/// <summary> /// Checks that there are no conflicting read and write accesses to arrays. /// </summary> /// <param name="loopIndex">The loop index of the loop that is subject for parallelization.</param> /// <param name="controlFlowGraph">The control flow graph of the body of the loop.</param> /// <param name="aliasAnalysis">A prelimary applied alias analysis already fed with possible aliases outside of the loop.</param> /// <returns><code>True</code> if there are no conflicting accesses to arrays.</returns> public static bool HasConflictingAccesses(string loopIndex, ControlFlowGraph controlFlowGraph, AliasAnalysis aliasAnalysis) { var loopDependenceAnalysis = LoopDependenceAnalysis.Analyze(controlFlowGraph, loopIndex); var arrayAccesses = ArrayAccessCollector.Collect(controlFlowGraph); var verifier = new ArrayAccessVerifier(loopDependenceAnalysis, aliasAnalysis, arrayAccesses); return(verifier._ContainsLoopCarriedDependencies()); }
public void EmptyWhileLoop() { var source = @"while(1 == 2) { }"; var cfg = CreateControlFlowGraph(source); var analysis = LoopDependenceAnalysis.Analyze(cfg, "j"); Assert.AreEqual(4, analysis.Exit[cfg.Start].Count); Assert.AreEqual(4, analysis.Entry[cfg.End].Count); Assert.AreEqual("{j != 0, j@, j|, j+}", GetString(analysis.Entry[cfg.End])); }
public void DeclaredWithNegationOfLoopIndex() { var source = @"var x = -i;"; var cfg = CreateControlFlowGraph(source); var analysis = LoopDependenceAnalysis.Analyze(cfg, "i"); var assignment = cfg.Nodes.Where(statement => statement.Instruction is Assignment).Single(); Assert.AreEqual(5, analysis.Entry[assignment].Count); Assert.AreEqual(8, analysis.Exit[assignment].Count); Assert.AreEqual("{i != 0, i@, i|, i+, x-, x != 0, x@, x|}", GetString(analysis.Exit[assignment])); }
public void EmptyBodyWithoutLoopIndex() { var source = @""; var cfg = CreateControlFlowGraph(source); var analysis = LoopDependenceAnalysis.Analyze(cfg, null); Assert.AreEqual(2, analysis.Entry.Count); Assert.AreEqual(2, analysis.Exit.Count); Assert.AreEqual(0, analysis.Entry[cfg.Start].Count); Assert.AreEqual(0, analysis.Exit[cfg.Start].Count); Assert.AreEqual(0, analysis.Entry[cfg.End].Count); Assert.AreEqual(0, analysis.Exit[cfg.End].Count); }
public void ConstantInsideIfBodyAndLoopIndexAfter() { var source = @"if(1 == 1) { x = 13; } x = j;"; var cfg = CreateControlFlowGraph(source); var analysis = LoopDependenceAnalysis.Analyze(cfg, "j"); var assignments = cfg.Nodes.Where(statement => statement.Instruction is Assignment).ToList(); Assert.AreEqual(4, analysis.Entry[assignments[0]].Count); Assert.AreEqual(8, analysis.Exit[assignments[0]].Count); Assert.AreEqual("{j != 0, j@, j|, j+, x != 0, x/, x@, x+}", GetString(analysis.Exit[assignments[0]])); Assert.AreEqual(8, analysis.Entry[assignments[1]].Count); Assert.AreEqual(8, analysis.Exit[assignments[1]].Count); Assert.AreEqual("{j != 0, j@, j|, j+, x != 0, x@, x|, x+}", GetString(analysis.Exit[assignments[1]])); }
public void DeclaredWithLoopIndexAndOverwrittenWithZero() { var source = @"var x = i; x = 0;"; var cfg = CreateControlFlowGraph(source); var analysis = LoopDependenceAnalysis.Analyze(cfg, "i"); var assignments = cfg.Nodes.Where(statement => statement.Instruction is Assignment).ToList(); Assert.AreEqual(5, analysis.Entry[assignments[0]].Count); Assert.AreEqual(8, analysis.Exit[assignments[0]].Count); Assert.AreEqual("{i != 0, i@, i|, i+, x != 0, x@, x|, x+}", GetString(analysis.Exit[assignments[0]])); Assert.AreEqual(8, analysis.Entry[assignments[1]].Count); Assert.AreEqual(7, analysis.Exit[assignments[1]].Count); Assert.AreEqual("{i != 0, i@, i|, i+, x = 0, x/, x@}", GetString(analysis.Exit[assignments[1]])); }
public void EmptyBodyWithLoopIndex() { var source = @""; var cfg = CreateControlFlowGraph(source); var analysis = LoopDependenceAnalysis.Analyze(cfg, "i"); Assert.AreEqual(2, analysis.Entry.Count); Assert.AreEqual(2, analysis.Exit.Count); Assert.AreEqual(4, analysis.Entry[cfg.Start].Count); Assert.AreEqual(4, analysis.Exit[cfg.Start].Count); Assert.AreEqual("{i != 0, i@, i|, i+}", GetString(analysis.Exit[cfg.Start])); Assert.AreEqual(4, analysis.Entry[cfg.End].Count); Assert.AreEqual(4, analysis.Exit[cfg.End].Count); }
public void EmptyForLoop() { var source = @"for(var i = 0; i < 10; i++) { }"; var cfg = CreateControlFlowGraph(source); var analysis = LoopDependenceAnalysis.Analyze(cfg, "j"); Assert.AreEqual(4, analysis.Exit[cfg.Start].Count); var incrementation = cfg.Nodes.Where(statement => statement.Instruction is Assignment).Skip(1).Single(); Assert.AreEqual(6, analysis.Entry[incrementation].Count); Assert.AreEqual(5, analysis.Exit[incrementation].Count); Assert.AreEqual("{i@, j != 0, j@, j|, j+}", GetString(analysis.Exit[incrementation])); Assert.AreEqual(6, analysis.Entry[cfg.End].Count); Assert.AreEqual("{i@, i@, j != 0, j@, j|, j+}", GetString(analysis.Entry[cfg.End])); }
public void ConstantZeroAssignment() { var source = @"x = 0;"; var cfg = CreateControlFlowGraph(source); var analysis = LoopDependenceAnalysis.Analyze(cfg, "i"); Assert.AreEqual(3, analysis.Entry.Count); Assert.AreEqual(3, analysis.Exit.Count); var declaration = cfg.Nodes.Where(node => node.Instruction is Assignment).Single(); Assert.AreEqual(4, analysis.Entry[declaration].Count); Assert.AreEqual(7, analysis.Exit[declaration].Count); Assert.AreEqual("{i != 0, i@, i|, i+, x = 0, x/, x@}", GetString(analysis.Exit[declaration])); Assert.AreEqual(7, analysis.Entry[cfg.End].Count); Assert.AreEqual(7, analysis.Exit[cfg.End].Count); }
public void WhileLoopWithAssignmentPriorAndInside() { var source = @"x = 3; while(1 == 2) { x = j; }"; var cfg = CreateControlFlowGraph(source); var analysis = LoopDependenceAnalysis.Analyze(cfg, "j"); var assignments = cfg.Nodes.Where(statement => statement.Instruction is Assignment).ToList(); Assert.AreEqual(4, analysis.Entry[assignments[0]].Count); Assert.AreEqual(8, analysis.Exit[assignments[0]].Count); Assert.AreEqual("{j != 0, j@, j|, j+, x != 0, x/, x@, x+}", GetString(analysis.Exit[assignments[0]])); Assert.AreEqual(6, analysis.Entry[assignments[1]].Count); Assert.AreEqual("{j != 0, j@, j|, j+, x@, x@}", GetString(analysis.Entry[assignments[1]])); Assert.AreEqual(8, analysis.Exit[assignments[1]].Count); Assert.AreEqual("{j != 0, j@, j|, j+, x != 0, x@, x|, x+}", GetString(analysis.Exit[assignments[1]])); Assert.AreEqual(6, analysis.Entry[cfg.End].Count); Assert.AreEqual("{j != 0, j@, j|, j+, x@, x@}", GetString(analysis.Entry[cfg.End])); }
public void LoopIndexLostThroughRecursion() { var invokerSource = @"Method(i);"; var invokerCfg = CreateControlFlowGraph(invokerSource); var methodSource = @" class Test { private int Method(int x) { if(x > 0) { return Method(x - 1); } return x; } }"; var semanticModel = DocumentFactory.Create().CreateSemanticModel(methodSource); var methodCode = semanticModel.SyntaxTree.GetRoot().DescendantNodes() .OfType <MethodDeclarationSyntax>() .Select(declaration => CodeFactory.CreateMethod(declaration, semanticModel)) .Single(); var methodCfg = ControlFlowGraphFactory.Create(methodCode, "Method", true); var procedureCfgs = new Dictionary <string, ControlFlowGraph> { { "Method", methodCfg } }; var callGraph = CallGraphFactory.Create(invokerCfg, procedureCfgs); var analysis = LoopDependenceAnalysis.Analyze(invokerCfg, "i", callGraph, procedureCfgs.Values); // Outer body Assert.AreEqual(4, analysis.Entry[invokerCfg.Start].Count); Assert.AreEqual("{i != 0, i@, i|, i+}", GetString(analysis.Entry[invokerCfg.Start])); Assert.AreEqual(10, analysis.Exit[invokerCfg.End].Count); Assert.AreEqual("{$arg_Method_0 != 0, $arg_Method_0@, $arg_Method_0|, $arg_Method_0+, $result_Method@, $result_Method@, i != 0, i@, i|, i+}", GetString(analysis.Exit[invokerCfg.End])); // invoked method Assert.AreEqual(2, analysis.Entry[methodCfg.Start].Count); Assert.AreEqual("{$arg_Method_0@, $arg_Method_0@}", GetString(analysis.Entry[methodCfg.Start])); Debug.WriteLine(GetString(analysis.Exit[methodCfg.End])); Assert.AreEqual(5, analysis.Exit[methodCfg.End].Count); Assert.AreEqual("{$arg_Method_0@, $arg_Method_0@, $result_Method@, $result_Method@, x@}", GetString(analysis.Exit[methodCfg.End])); }
public void SinglePositiveConstantAssignmentInsideIfBody() { // Note: there is no need to remove the information about the assignment of x // when leaving the if-body. Either the variable has been assigned earlier which leads // to different declaring nodes, or it has been declared outside of the loop which would // lead to a race condition anyway (previous step of the analysis). var source = @"if(1 == 1) { x = 13; }"; var cfg = CreateControlFlowGraph(source); var analysis = LoopDependenceAnalysis.Analyze(cfg, "j"); Assert.AreEqual(4, analysis.Exit[cfg.Start].Count); var assignment = cfg.Nodes.Where(statement => statement.Instruction is Assignment).Single(); Assert.AreEqual(4, analysis.Entry[assignment].Count); Assert.AreEqual(8, analysis.Exit[assignment].Count); Assert.AreEqual("{j != 0, j@, j|, j+, x != 0, x/, x@, x+}", GetString(analysis.Exit[assignment])); Assert.AreEqual(8, analysis.Entry[cfg.End].Count); Assert.AreEqual("{j != 0, j@, j|, j+, x != 0, x/, x@, x+}", GetString(analysis.Entry[cfg.End])); }
public void AssignmentsOfDifferentConstantsPriorAndInsideIfBody() { var source = @"x = 5; if(1 == 1) { x = 13; }"; var cfg = CreateControlFlowGraph(source); var analysis = LoopDependenceAnalysis.Analyze(cfg, "j"); Assert.AreEqual(4, analysis.Exit[cfg.Start].Count); var assignments = cfg.Nodes.Where(statement => statement.Instruction is Assignment).ToList(); Assert.AreEqual(4, analysis.Entry[assignments[0]].Count); Assert.AreEqual(8, analysis.Exit[assignments[0]].Count); Assert.AreEqual("{j != 0, j@, j|, j+, x != 0, x/, x@, x+}", GetString(analysis.Exit[assignments[0]])); Assert.AreEqual(8, analysis.Entry[assignments[1]].Count); Assert.AreEqual(8, analysis.Exit[assignments[1]].Count); Assert.AreEqual("{j != 0, j@, j|, j+, x != 0, x/, x@, x+}", GetString(analysis.Exit[assignments[1]])); Assert.AreEqual(6, analysis.Entry[cfg.End].Count); Assert.AreEqual("{j != 0, j@, j|, j+, x@, x@}", GetString(analysis.Entry[cfg.End])); }
public void LoopIndexAndRegularPassingWithExchangeRemovesInformation() { var invokerSource = @"var a = 0; var b = Recursive(i, a);"; var invokerCfg = CreateControlFlowGraph(invokerSource); var methodSource = @" class Test { private void Recursive(int x, int y) { if(x > y) { Recursive(y, x); } return x; } }"; var semanticModel = DocumentFactory.Create().CreateSemanticModel(methodSource); var methodCode = semanticModel.SyntaxTree.GetRoot().DescendantNodes() .OfType <MethodDeclarationSyntax>() .Select(declaration => CodeFactory.CreateMethod(declaration, semanticModel)) .Single(); var methodCfg = ControlFlowGraphFactory.Create(methodCode, "Recursive", true); var procedureCfgs = new Dictionary <string, ControlFlowGraph> { { "Recursive", methodCfg } }; var callGraph = CallGraphFactory.Create(invokerCfg, procedureCfgs); var analysis = LoopDependenceAnalysis.Analyze(invokerCfg, "i", callGraph, procedureCfgs.Values); // Outer body Assert.AreEqual(4, analysis.Entry[invokerCfg.Start].Count); Assert.AreEqual("{i != 0, i@, i|, i+}", GetString(analysis.Entry[invokerCfg.Start])); Assert.AreEqual(16, analysis.Exit[invokerCfg.End].Count); Assert.AreEqual("{$arg_Recursive_0 != 0, $arg_Recursive_0@, $arg_Recursive_0|, $arg_Recursive_0+, $arg_Recursive_1 = 0, $arg_Recursive_1/, $arg_Recursive_1@, $result_Recursive@, a = 0, a/, a@, b@, i != 0, i@, i|, i+}", GetString(analysis.Exit[invokerCfg.End])); // invoked method Assert.AreEqual(4, analysis.Entry[methodCfg.Start].Count); Assert.AreEqual("{$arg_Recursive_0@, $arg_Recursive_0@, $arg_Recursive_1@, $arg_Recursive_1@}", GetString(analysis.Entry[methodCfg.Start])); Assert.AreEqual(7, analysis.Exit[methodCfg.End].Count); Assert.AreEqual("{$arg_Recursive_0@, $arg_Recursive_0@, $arg_Recursive_1@, $arg_Recursive_1@, $result_Recursive@, x@, y@}", GetString(analysis.Exit[methodCfg.End])); }
public void UnknownInvocationTargetDoesNotTransferInformation() { var source = @"var x = Method(i);"; var cfg = CreateControlFlowGraph(source); var analysis = LoopDependenceAnalysis.Analyze(cfg, "i"); Assert.AreEqual(4, analysis.Entry[cfg.Start].Count); var declaration = cfg.Nodes.Where(statement => statement.Instruction is Declaration d && d.Name.Equals("x")).Single(); Assert.AreEqual(4, analysis.Entry[declaration].Count); Assert.AreEqual("{i != 0, i@, i|, i+}", GetString(analysis.Entry[declaration])); Assert.AreEqual(5, analysis.Exit[declaration].Count); Assert.AreEqual("{i != 0, i@, i|, i+, x@}", GetString(analysis.Exit[declaration])); var assignment = cfg.Nodes.Where(statement => statement.Instruction is Assignment a && a.Left.ToString().Equals("x")).Single(); Assert.AreEqual(5, analysis.Entry[assignment].Count); Assert.AreEqual("{i != 0, i@, i|, i+, x@}", GetString(analysis.Entry[assignment])); Assert.AreEqual(5, analysis.Exit[assignment].Count); Assert.AreEqual("{i != 0, i@, i|, i+, x@}", GetString(analysis.Exit[assignment])); }
public void ConstantPositiveNumberDeclaration() { var source = @"var x = 30;"; var cfg = CreateControlFlowGraph(source); var analysis = LoopDependenceAnalysis.Analyze(cfg, "i"); Assert.AreEqual(4, analysis.Entry.Count); Assert.AreEqual(4, analysis.Exit.Count); var assignment = cfg.Nodes.Where(node => node.Instruction is Assignment).Single(); Assert.AreEqual(5, analysis.Entry[assignment].Count); Assert.AreEqual("{i != 0, i@, i|, i+, x@}", GetString(analysis.Entry[assignment])); Assert.AreEqual(8, analysis.Exit[assignment].Count); Assert.IsTrue(analysis.Exit[assignment].Any(descriptor => descriptor.Kind is NotZero)); Assert.IsTrue(analysis.Exit[assignment].Any(descriptor => descriptor.Kind is Positive)); Assert.IsTrue(analysis.Exit[assignment].Any(descriptor => descriptor.Kind is LoopIndependent)); Assert.AreEqual("{i != 0, i@, i|, i+, x != 0, x/, x@, x+}", GetString(analysis.Exit[assignment])); Assert.AreEqual(8, analysis.Entry[cfg.End].Count); Assert.AreEqual(8, analysis.Exit[cfg.End].Count); }
public void AssignmentsOfLoopIndexInIfAndConstantInsideElseBody() { var source = @"if(1 == 1) { x = j; } else { x = 13; }"; var cfg = CreateControlFlowGraph(source); var analysis = LoopDependenceAnalysis.Analyze(cfg, "j"); Assert.AreEqual(4, analysis.Exit[cfg.Start].Count); var indexAssignment = GetNodeWithSyntax(cfg, "Assignment: x = j"); Assert.AreEqual(4, analysis.Entry[indexAssignment].Count); Assert.AreEqual(8, analysis.Exit[indexAssignment].Count); Assert.AreEqual("{j != 0, j@, j|, j+, x != 0, x@, x|, x+}", GetString(analysis.Exit[indexAssignment])); var constantAssignment = GetNodeWithSyntax(cfg, "Assignment: x = 13"); Assert.AreEqual(4, analysis.Entry[constantAssignment].Count); Assert.AreEqual(8, analysis.Exit[constantAssignment].Count); Assert.AreEqual("{j != 0, j@, j|, j+, x != 0, x/, x@, x+}", GetString(analysis.Exit[constantAssignment])); Assert.AreEqual(6, analysis.Entry[cfg.End].Count); Assert.AreEqual("{j != 0, j@, j|, j+, x@, x@}", GetString(analysis.Entry[cfg.End])); }
public void LoopIndexPassingToSingleArgumentWithReturnValue() { var invokerSource = @"var a = Method(i);"; var invokerCfg = CreateControlFlowGraph(invokerSource); var methodSource = @" class Test { private void Method(int x) { return x; } }"; var semanticModel = DocumentFactory.Create().CreateSemanticModel(methodSource); var methodCode = semanticModel.SyntaxTree.GetRoot().DescendantNodes() .OfType <MethodDeclarationSyntax>() .Select(declaration => CodeFactory.CreateMethod(declaration, semanticModel)) .Single(); var methodCfg = ControlFlowGraphFactory.Create(methodCode, "Method", true); var procedureCfgs = new Dictionary <string, ControlFlowGraph> { { "Method", methodCfg } }; var callGraph = CallGraphFactory.Create(invokerCfg, procedureCfgs); var analysis = LoopDependenceAnalysis.Analyze(invokerCfg, "i", callGraph, procedureCfgs.Values); // Outer body Assert.AreEqual(4, analysis.Entry[invokerCfg.Start].Count); Assert.AreEqual("{i != 0, i@, i|, i+}", GetString(analysis.Entry[invokerCfg.Start])); Assert.AreEqual(16, analysis.Exit[invokerCfg.End].Count); Assert.AreEqual("{$arg_Method_0 != 0, $arg_Method_0@, $arg_Method_0|, $arg_Method_0+, $result_Method != 0, $result_Method@, $result_Method|, $result_Method+, a != 0, a@, a|, a+, i != 0, i@, i|, i+}", GetString(analysis.Exit[invokerCfg.End])); // invoked method Assert.AreEqual(4, analysis.Entry[methodCfg.Start].Count); Assert.AreEqual("{$arg_Method_0 != 0, $arg_Method_0@, $arg_Method_0|, $arg_Method_0+}", GetString(analysis.Entry[methodCfg.Start])); Assert.AreEqual(12, analysis.Exit[methodCfg.End].Count); Assert.AreEqual("{$arg_Method_0 != 0, $arg_Method_0@, $arg_Method_0|, $arg_Method_0+, $result_Method != 0, $result_Method@, $result_Method|, $result_Method+, x != 0, x@, x|, x+}", GetString(analysis.Exit[methodCfg.End])); }
public void AssignmentOfLoopIndex() { var source = @"x = i;"; var cfg = CreateControlFlowGraph(source); var analysis = LoopDependenceAnalysis.Analyze(cfg, "i"); Assert.AreEqual(3, analysis.Entry.Count); Assert.AreEqual(3, analysis.Exit.Count); var declaration = cfg.Nodes.Where(node => node.Instruction is Assignment).Single(); Assert.AreEqual(4, analysis.Entry[declaration].Count); Assert.AreEqual(8, analysis.Exit[declaration].Count); Assert.AreEqual(2, analysis.Exit[declaration].Count(descriptor => descriptor.Kind is NotZero)); Assert.AreEqual(2, analysis.Exit[declaration].Count(descriptor => descriptor.Kind is LoopDependent)); Assert.AreEqual(2, analysis.Exit[declaration].Count(descriptor => descriptor.Kind is Positive)); Assert.AreEqual(2, analysis.Exit[declaration].Count(descriptor => descriptor.Kind is Definition)); Assert.AreEqual(4, analysis.Exit[declaration].Count(descriptor => descriptor.Name.Equals("x"))); Assert.AreEqual(4, analysis.Exit[declaration].Count(descriptor => descriptor.Name.Equals("i"))); Assert.AreEqual("{i != 0, i@, i|, i+, x != 0, x@, x|, x+}", GetString(analysis.Exit[declaration])); Assert.AreEqual(8, analysis.Entry[cfg.End].Count); Assert.AreEqual(8, analysis.Exit[cfg.End].Count); }
public void ForLoopWithAssignmentInsideAndAfterLoop() { var source = @"x = 0; for(var i = 0; i < 10; ++i) { x = x + 1; } var y = j - x;"; var cfg = CreateControlFlowGraph(source); var analysis = LoopDependenceAnalysis.Analyze(cfg, "j"); var xAssigned0 = cfg.Nodes .Where(statement => statement.Instruction is Assignment assignment && assignment.Left.ToString().Equals("x") && assignment.Right.ToString().Equals("0")) .Single(); var xAssignedPlus1 = cfg.Nodes .Where(statement => statement.Instruction is Assignment assignment && assignment.Right.ToString().Equals("x + 1")) .Single(); var yAssigned = cfg.Nodes .Where(statement => statement.Instruction is Assignment assignment && assignment.Right.ToString().Equals("j - x")) .Single(); Assert.AreEqual(4, analysis.Entry[xAssigned0].Count); Assert.AreEqual("{j != 0, j@, j|, j+}", GetString(analysis.Entry[xAssigned0])); Assert.AreEqual(7, analysis.Exit[xAssigned0].Count); Assert.AreEqual("{j != 0, j@, j|, j+, x = 0, x/, x@}", GetString(analysis.Exit[xAssigned0])); Assert.AreEqual(8, analysis.Entry[xAssignedPlus1].Count); Assert.AreEqual("{i@, i@, j != 0, j@, j|, j+, x@, x@}", GetString(analysis.Entry[xAssignedPlus1])); Assert.AreEqual(7, analysis.Exit[xAssignedPlus1].Count); Assert.AreEqual("{i@, i@, j != 0, j@, j|, j+, x@}", GetString(analysis.Exit[xAssignedPlus1])); Assert.AreEqual(9, analysis.Entry[yAssigned].Count); Assert.AreEqual("{i@, i@, j != 0, j@, j|, j+, x@, x@, y@}", GetString(analysis.Entry[yAssigned])); Assert.AreEqual(9, analysis.Exit[yAssigned].Count); Assert.AreEqual("{i@, i@, j != 0, j@, j|, j+, x@, x@, y@}", GetString(analysis.Exit[yAssigned])); Assert.AreEqual(9, analysis.Exit[cfg.End].Count); Assert.AreEqual("{i@, i@, j != 0, j@, j|, j+, x@, x@, y@}", GetString(analysis.Exit[cfg.End])); }
public void NestedIfStatementsOverwritingDefinitions() { var source = @" var x = 0; if(1 == 1) { x = 1; if(2 == 2) { x = 2; } var y = 3; } var z = x;"; var cfg = CreateControlFlowGraph(source); var analysis = LoopDependenceAnalysis.Analyze(cfg, null); var zeroAssignment = cfg.Nodes .Where(statement => statement.Instruction is Assignment assignment && assignment.Right.ToString().Equals("0")) .Single(); var oneAssignment = cfg.Nodes .Where(statement => statement.Instruction is Assignment assignment && assignment.Right.ToString().Equals("1")) .Single(); var twoAssignment = cfg.Nodes .Where(statement => statement.Instruction is Assignment assignment && assignment.Right.ToString().Equals("2")) .Single(); var threeAssignment = cfg.Nodes .Where(statement => statement.Instruction is Assignment assignment && assignment.Right.ToString().Equals("3")) .Single(); var xAssignment = cfg.Nodes .Where(statement => statement.Instruction is Assignment assignment && assignment.Right.ToString().Equals("x")) .Single(); Assert.AreEqual(0, analysis.Entry[cfg.Start].Count); Assert.AreEqual(0, analysis.Exit[cfg.Start].Count); Assert.AreEqual(1, analysis.Entry[zeroAssignment].Count); Assert.AreEqual("{x@}", GetString(analysis.Entry[zeroAssignment])); Assert.AreEqual(3, analysis.Exit[zeroAssignment].Count); Assert.AreEqual("{x = 0, x/, x@}", GetString(analysis.Exit[zeroAssignment])); Assert.AreEqual(3, analysis.Entry[oneAssignment].Count); Assert.AreEqual("{x = 0, x/, x@}", GetString(analysis.Entry[oneAssignment])); Assert.AreEqual(5, analysis.Exit[oneAssignment].Count); Assert.AreEqual("{x != 0, x = 1, x/, x@, x+}", GetString(analysis.Exit[oneAssignment])); Assert.AreEqual(5, analysis.Entry[twoAssignment].Count); Assert.AreEqual("{x != 0, x = 1, x/, x@, x+}", GetString(analysis.Entry[twoAssignment])); Assert.AreEqual(4, analysis.Exit[twoAssignment].Count); Assert.AreEqual("{x != 0, x/, x@, x+}", GetString(analysis.Exit[twoAssignment])); Assert.AreEqual(3, analysis.Entry[threeAssignment].Count); Assert.AreEqual("{x@, x@, y@}", GetString(analysis.Entry[threeAssignment])); Assert.AreEqual(6, analysis.Exit[threeAssignment].Count); Assert.AreEqual("{x@, x@, y != 0, y/, y@, y+}", GetString(analysis.Exit[threeAssignment])); Assert.AreEqual(8, analysis.Entry[xAssignment].Count); Assert.AreEqual("{x@, x@, x@, y != 0, y/, y@, y+, z@}", GetString(analysis.Entry[xAssignment])); Assert.AreEqual(8, analysis.Exit[xAssignment].Count); Assert.AreEqual("{x@, x@, x@, y != 0, y/, y@, y+, z@}", GetString(analysis.Exit[xAssignment])); Assert.AreEqual(8, analysis.Entry[cfg.End].Count); Assert.AreEqual("{x@, x@, x@, y != 0, y/, y@, y+, z@}", GetString(analysis.Entry[cfg.End])); Assert.AreEqual(8, analysis.Exit[cfg.End].Count); Assert.AreEqual("{x@, x@, x@, y != 0, y/, y@, y+, z@}", GetString(analysis.Exit[cfg.End])); }
private ArrayAccessVerifier(LoopDependenceAnalysis loopDependenceAnalysis, AliasAnalysis aliasAnalysis, ISet <ArrayAccess> arrayAccesses) { _loopDependenceAnalysis = loopDependenceAnalysis; _aliasAnalysis = aliasAnalysis; _arrayAccesses = arrayAccesses; }