private List <IStatement> Schedule(DependencyGraph g, IList <IStatement> stmts, bool createFirstIterPostBlocks) { List <IStatement> output = new List <IStatement>(); List <StatementBlock> blocks = new List <StatementBlock>(); List <NodeIndex> currentBlock = null; DirectedGraphFilter <NodeIndex, EdgeIndex> graph2 = new DirectedGraphFilter <NodeIndex, EdgeIndex>(g.dependencyGraph, edge => !g.isDeleted[edge]); StrongComponents2 <NodeIndex> scc = new StrongComponents2 <NodeIndex>(graph2.SourcesOf, graph2); scc.AddNode += delegate(NodeIndex node) { currentBlock.Add(node); }; scc.BeginComponent += delegate() { currentBlock = new List <int>(); }; scc.EndComponent += delegate() { bool isCyclic = false; if (currentBlock.Count == 1) { NodeIndex node = currentBlock[0]; foreach (NodeIndex source in graph2.SourcesOf(node)) { if (source == node) { isCyclic = true; break; } } } else { isCyclic = true; } if (isCyclic) { blocks.Add(new Loop() { indices = currentBlock }); } else { blocks.Add(new StraightLine() { indices = currentBlock }); } }; scc.SearchFrom(graph2.Nodes); //scc.SearchFrom(g.outputNodes); bool check = false; if (check) { // check that there are no edges from a later component to an earlier component Set <NodeIndex> earlierNodes = new Set <int>(); foreach (StatementBlock block in blocks) { earlierNodes.AddRange(block.indices); foreach (NodeIndex node in block.indices) { foreach (NodeIndex source in graph2.SourcesOf(node)) { if (!earlierNodes.Contains(source)) { Console.WriteLine(g.NodeToString(node) + Environment.NewLine + " depends on later node " + g.NodeToString(source)); Error("Internal error: Strong components are not ordered properly"); } } } } } Set <NodeIndex> nodesToMove = new Set <NodeIndex>(); Dictionary <Loop, IBlockStatement> firstIterPostprocessing = null; if (createFirstIterPostBlocks) { firstIterPostprocessing = GetFirstIterPostprocessing(blocks, graph2, stmts, nodesToMove); } IVariableDeclaration iteration = Builder.VarDecl("iteration", typeof(int)); IndexedProperty <NodeIndex, bool> isUniform = graph2.CreateNodeData <bool>(true); foreach (StatementBlock block in blocks) { if (block is Loop) { foreach (NodeIndex i in block.indices) { isUniform[i] = false; } IWhileStatement ws = Builder.WhileStmt(Builder.LiteralExpr(true)); IList <IStatement> whileBody = ws.Body.Statements; if (ContainsIterationStatement(stmts, block.indices)) { List <IStatement> nodes = new List <IStatement>(); foreach (NodeIndex i in block.indices) { IStatement ist = stmts[i]; if (!context.InputAttributes.Has <IterationStatement>(ist)) { nodes.Add(ist); } } // build a new dependency graph with the dummy iteration statement removed DependencyGraph g2 = new DependencyGraph(context, nodes, ignoreMissingNodes: true, ignoreRequirements: true); List <IStatement> sc3 = Schedule(g2, nodes, false); if (sc3.Count == 1 && sc3[0] is IWhileStatement) { ws = (IWhileStatement)sc3[0]; } else { // The statements in the outer loop are not strongly connected. // Since we want the next transform to only process strong components, // we mark the outer while loop as DoNotSchedule, leaving only the // inner while loops to be scheduled. // add all statements in sc3 to whileBody, but remove while loops around a single statement. foreach (IStatement ist in sc3) { if (ist is IWhileStatement) { IWhileStatement iws2 = (IWhileStatement)ist; if (iws2.Body.Statements.Count == 1) { whileBody.AddRange(iws2.Body.Statements); continue; } } whileBody.Add(ist); } context.OutputAttributes.Set(ws, new DoNotSchedule()); } } else // !ContainsIterationStatement { foreach (NodeIndex i in block.indices) { IStatement st = stmts[i]; whileBody.Add(st); DependencyInformation di = context.InputAttributes.Get <DependencyInformation>(st); di.AddClones(clonesOfStatement); } RegisterUnchangedStatements(whileBody); } Loop loop = (Loop)block; if (firstIterPostprocessing != null && firstIterPostprocessing.ContainsKey(loop)) { var thenBlock = firstIterPostprocessing[loop]; var iterIsZero = Builder.BinaryExpr(BinaryOperator.ValueEquality, Builder.VarRefExpr(iteration), Builder.LiteralExpr(0)); var firstIterPostStmt = Builder.CondStmt(iterIsZero, thenBlock); context.OutputAttributes.Set(firstIterPostStmt, new FirstIterationPostProcessingBlock()); whileBody.Add(firstIterPostStmt); } output.Add(ws); } else { // not cyclic foreach (NodeIndex i in block.indices) { IStatement st = stmts[i]; if (!nodesToMove.Contains(i)) { output.Add(st); DependencyInformation di = context.InputAttributes.Get <DependencyInformation>(st); di.AddClones(clonesOfStatement); } isUniform[i] = g.IsUniform(i, source => !isUniform[source]); if (isUniform[i] != g.isUniform[i]) { Assert.IsTrue(isUniform[i]); g.isUniform[i] = isUniform[i]; DependencyInformation di = context.InputAttributes.Get <DependencyInformation>(st); di.IsUniform = isUniform[i]; } // mark sources of output statements (for SchedulingTransform) if (g.outputNodes.Contains(i)) { foreach (NodeIndex source in graph2.SourcesOf(i)) { IStatement sourceSt = stmts[source]; if (!context.InputAttributes.Has <OutputSource>(sourceSt)) { context.OutputAttributes.Set(sourceSt, new OutputSource()); } } } } } } return(output); }
public void GraphSearchTest() { // this is the example graph at http://www.codeproject.com/cs/miscctrl/quickgraph.asp Graph <BasicNode> g = new Graph <BasicNode>(); BasicNode u = new BasicNode("u"); BasicNode v = new BasicNode("v"); BasicNode w = new BasicNode("w"); BasicNode x = new BasicNode("x"); BasicNode y = new BasicNode("y"); BasicNode z = new BasicNode("z"); g.Nodes.Add(u); g.Nodes.Add(v); g.Nodes.Add(w); g.Nodes.Add(x); g.Nodes.Add(y); g.Nodes.Add(z); g.AddEdge(u, v); g.AddEdge(u, x); g.AddEdge(v, y); g.AddEdge(y, x); g.AddEdge(x, v); g.AddEdge(w, u); g.AddEdge(w, y); g.AddEdge(w, z); DepthFirstSearch <BasicNode> dfs = new DepthFirstSearch <BasicNode>(g); dfs.DiscoverNode += delegate(BasicNode node) { Console.WriteLine("discover " + node); }; dfs.FinishNode += delegate(BasicNode node) { Console.WriteLine("finish " + node); }; dfs.DiscoverEdge += delegate(Edge <BasicNode> edge) { Console.WriteLine("discover " + edge); }; dfs.TreeEdge += delegate(Edge <BasicNode> edge) { Console.WriteLine("tree edge " + edge); }; dfs.FinishTreeEdge += delegate(Edge <BasicNode> edge) { Console.WriteLine("finish tree edge " + edge); }; dfs.CrossEdge += delegate(Edge <BasicNode> edge) { Console.WriteLine("cross edge " + edge); }; dfs.BackEdge += delegate(Edge <BasicNode> edge) { Console.WriteLine("back edge " + edge); }; Console.WriteLine("dfs from u:"); dfs.SearchFrom(u); Console.WriteLine(); Console.WriteLine("dfs from w:"); dfs.SearchFrom(w); Console.WriteLine(); dfs.Clear(); Console.WriteLine("cleared dfs from w:"); dfs.SearchFrom(w); Console.WriteLine(); Console.WriteLine("bfs:"); BreadthFirstSearch <BasicNode> bfs = new BreadthFirstSearch <BasicNode>(g); IndexedProperty <BasicNode, double> distance = g.CreateNodeData <double>(Double.PositiveInfinity); bfs.DiscoverNode += delegate(BasicNode node) { Console.WriteLine("discover " + node); }; bfs.FinishNode += delegate(BasicNode node) { Console.WriteLine("finish " + node); }; bfs.TreeEdge += delegate(Edge <BasicNode> edge) { Console.WriteLine("tree edge " + edge); distance[edge.Target] = distance[edge.Source] + 1; }; // compute distances from w distance[w] = 0; bfs.SearchFrom(w); Console.WriteLine("distances from w:"); foreach (BasicNode node in g.Nodes) { Console.WriteLine("[" + node + "] " + distance[node]); } Assert.Equal(2.0, distance[x]); Console.WriteLine(); Console.WriteLine("distances from w:"); DistanceSearch <BasicNode> dists = new DistanceSearch <BasicNode>(g); dists.SetDistance += delegate(BasicNode node, int dist) { Console.WriteLine("[" + node + "] " + dist); }; dists.SearchFrom(w); Console.WriteLine(); BasicNode start = z, end; (new PseudoPeripheralSearch <BasicNode>(g)).SearchFrom(ref start, out end); Console.WriteLine("pseudo-peripheral nodes: " + start + "," + end); StrongComponents <BasicNode> scc = new StrongComponents <BasicNode>(g); int count = 0; scc.AddNode += delegate(BasicNode node) { Console.Write(" " + node); }; scc.BeginComponent += delegate() { Console.Write("["); count++; }; scc.EndComponent += delegate() { Console.Write("]"); }; Console.Write("strong components reachable from w (topological order): "); scc.SearchFrom(w); Assert.Equal(4, count); Console.WriteLine(); count = 0; StrongComponents2 <BasicNode> scc2 = new StrongComponents2 <BasicNode>(g); scc2.AddNode += delegate(BasicNode node) { Console.Write(" " + node); }; scc2.BeginComponent += delegate() { Console.Write("["); count++; }; scc2.EndComponent += delegate() { Console.Write("]"); }; Console.Write("strong components reachable from w (rev topological order): "); scc2.SearchFrom(w); Assert.Equal(4, count); Console.WriteLine(); #if false Console.WriteLine("CyclicDependencySort:"); List <BasicNode> schedule = CyclicDependencySort <BasicNode> .Schedule(g, delegate(BasicNode node, ICollection <BasicNode> available) { if (node == x) { return(available.Contains(u)); } else { return(false); } }, g.Nodes); foreach (BasicNode node in schedule) { Console.Write(node + " "); } Console.WriteLine(); Assert.Equal <int>(6, schedule.Count); // order should be: w u x v y z (z can be re-ordered) Assert.Equal <BasicNode>(w, schedule[0]); Assert.Equal <BasicNode>(u, schedule[1]); //Assert.Equal<BasicNode>(z,schedule[5]); #endif }