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]));
        }
예제 #2
0
        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);
        }
예제 #8
0
        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]));
        }
예제 #15
0
        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]));
        }
예제 #16
0
        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);
        }
예제 #20
0
        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]));
        }
예제 #24
0
        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;
 }