protected override void DoConvertMethodBody(IList <IStatement> outputs, IList <IStatement> inputs)
        {
            Dictionary <IStatement, IStatement> replacements = new Dictionary <IStatement, IStatement>(ReferenceEqualityComparer <IStatement> .Instance);

            ProcessStatements(outputs, outputs, inputs, replacements);
            // update all dependencies
            foreach (IStatement ist in outputs)
            {
                if (ist is IWhileStatement)
                {
                    IWhileStatement iws = (IWhileStatement)ist;
                    foreach (IStatement st in iws.Body.Statements)
                    {
                        DependencyInformation di2 = context.OutputAttributes.Get <DependencyInformation>(st);
                        if (di2 != null)
                        {
                            di2.Replace(replacements);
                        }
                    }
                }
                else
                {
                    DependencyInformation di = context.OutputAttributes.Get <DependencyInformation>(ist);
                    if (di != null)
                    {
                        di.Replace(replacements);
                    }
                }
            }
        }
 private void PostProcessDependencies(ICollection <IStatement> outputs)
 {
     if (replacements.Count > 0)
     {
         // contexts are bodies of innermost while statements
         DeadCodeTransform.ForEachStatement(outputs,
                                            delegate(IWhileStatement iws)
         {
         },
                                            delegate(IWhileStatement iws)
         {
         },
                                            _ =>
         {
         },
                                            _ =>
         {
         },
                                            delegate(IStatement ist)
         {
             if (replacements != null)
             {
                 DependencyInformation di = context.InputAttributes.Get <DependencyInformation>(ist);
                 if (di != null)
                 {
                     // must make a clone since this statement may appear in multiple contexts
                     DependencyInformation di2 = (DependencyInformation)di.Clone();
                     di2.Replace(replacements);
                     context.OutputAttributes.Remove <DependencyInformation>(ist);
                     context.OutputAttributes.Set(ist, di2);
                 }
             }
         });
     }
 }
        protected override IStatement DoConvertStatement(IStatement ist)
        {
            if (ist is IWhileStatement)
            {
                return(ConvertWhile((IWhileStatement)ist));
            }
            if (replacements.ContainsKey(ist))
            {
                return(null);
            }
            bool isIncrement = context.InputAttributes.Has <IncrementStatement>(ist);

            if (this.inWhileLoop == false)
            {
                if (isIncrement)
                {
                    replacements[ist] = null;
                    return(null);
                }
            }
            else if (incrementStatements.Count > 0)
            {
                var attr = context.GetAttribute <HasIncrement>(ist);
                if (attr != null && incrementStatements.Contains(attr.incrementStatement))
                {
                    // hoist this statement out of the while loop.
                    // TODO: hoisting ist is only valid if its requirements are met when hoisted.
                    context.AddStatementBeforeAncestorIndex(ancestorIndexOfWhile, ist);
                    return(null);
                }
                else if (isIncrement)
                {
                    // Add to the initializerSet (assuming the non-increment statement is hoisted).
                    // This will only work correctly if the non-increment is in DependencyInformation.Initializers.
                    // This code currently does nothing since InitializerSet is only attached later by SchedulingTransform.
                    var iws            = context.GetAncestor(ancestorIndexOfWhile);
                    var initializerSet = context.GetAttribute <InitializerSet>(iws);
                    if (initializerSet != null)
                    {
                        initializerSet.initializers.Add(ist);
                    }
                }
            }
            DependencyInformation di = context.GetAttribute <DependencyInformation>(ist);

            if (di != null)
            {
                di.Replace(replacements);
            }
            visitedStatements.Add(ist);
            return(base.DoConvertStatement(ist));
        }
        protected IList <IStatement> Schedule(IReadOnlyList <IStatement> isc)
        {
            DependencyGraph g = new DependencyGraph(context, isc, ignoreMissingNodes: false, ignoreRequirements: true, readAfterWriteOnly: true);

            // The uniform statements must be removed first, before doing the search backward from outputs.
            // This is important because it allows dependencies of uniform statements to be pruned.
            // For example, suppose A requires B and C, B is uniform.  This means that A is uniform and A will be pruned.
            // As a result, C doesn't need to be computed (even if it might be non-uniform).
            if (PruneUniformStmts)
            {
                g.PropagateUniformNodes();
            }

            // Propagate DependsOnIteration
            DependsOnIteration           attr    = null;
            DepthFirstSearch <NodeIndex> dfsIter = new DepthFirstSearch <EdgeIndex>(g.dependencyGraph.TargetsOf, g.nodeData);

            dfsIter.DiscoverNode += delegate(NodeIndex node) {
                if (!context.OutputAttributes.Has <DependsOnIteration>(isc[node]))
                {
                    context.OutputAttributes.Set(isc[node], attr);
                }
            };
            foreach (NodeIndex node in g.dependencyGraph.Nodes)
            {
                attr = context.GetAttribute <DependsOnIteration>(isc[node]);
                if (attr != null)
                {
                    dfsIter.SearchFrom(node);
                }
            }

            // search backward from the outputs to find statements that are relevant.
            DepthFirstSearch <NodeIndex> dfs = new DepthFirstSearch <NodeIndex>(
                PruneUniformStmts ? (Converter <int, IEnumerable <int> >)g.SourcesNeededForOutput : g.dependencyGraph.SourcesOf,
                g.nodeData);

            dfs.SearchFrom(g.outputNodes);
            List <NodeIndex> schedule = new List <NodeIndex>();

            foreach (NodeIndex node in g.dependencyGraph.Nodes)
            {
                // any statement found in the search is relevant.  other statements are pruned.
                if (dfs.IsVisited[node] == VisitState.Finished)
                {
                    schedule.Add(node);
                }
            }

            if (debug)
            {
                var             itdOut = context.FindOutputForAncestor <ITypeDeclaration, ITypeDeclaration>();
                IBlockStatement block  = Builder.BlockStmt();
                foreach (var line in StringUtil.Lines(g.dependencyGraph.ToString()))
                {
                    block.Statements.Add(Builder.CommentStmt(line));
                }
                foreach (NodeIndex node in g.dependencyGraph.Nodes)
                {
                    block.Statements.Add(Builder.CommentStmt($"{node} {isc[node]}"));
                }
                context.OutputAttributes.Add(itdOut, new DebugInfo()
                {
                    Transform = this,
                    Name      = "Graph",
                    Value     = block
                });
            }

            if (PruneUniformStmts)
            {
                // When statements are pruned from the code, they must also be pruned from the DependencyInformation attributes of all other statements that might refer to them.
                Dictionary <IStatement, IStatement> replacements = new Dictionary <IStatement, IStatement>(ReferenceEqualityComparer <IStatement> .Instance);
                foreach (NodeIndex targetIndex in g.dependencyGraph.Nodes)
                {
                    if (g.isUniform[targetIndex])
                    {
                        IStatement            ist = isc[targetIndex];
                        DependencyInformation di  = context.InputAttributes.Get <DependencyInformation>(ist);
                        // this is needed for detection of non-uniform initializers
                        di.IsUniform = true;
                    }
                    if (g.isUniform[targetIndex] && !g.isEssential[targetIndex])
                    {
                        NodeIndex source = g.FindInitializer(targetIndex);
                        if (source != targetIndex)
                        {
                            IStatement target      = isc[targetIndex];
                            IStatement replacement = isc[source];
                            replacements[target] = replacement;
                        }
                    }
                }
                foreach (NodeIndex targetIndex in schedule)
                {
                    IStatement            target = isc[targetIndex];
                    DependencyInformation di     = context.InputAttributes.Get <DependencyInformation>(target);
                    di.Replace(replacements);
                }
            }

            IList <IStatement> sc = Builder.StmtCollection();

            foreach (NodeIndex i in schedule)
            {
                IStatement st = isc[i];
                sc.Add(st);
            }
            return(sc);
        }