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); }