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); } } }); } }
public void AddDBMapping(string dbKey, string cacheKey, ExpirationHint hint) { lock (_dbKeysMappingTbl.SyncRoot) { _dbKeysMappingTbl[dbKey] = new DependencyInformation(cacheKey, hint); } }
private void ForEachInitializer(IStatement source, NodeIndex target, DependencyGraph2 g, Action <IStatement> action) { Stack <IStatement> todo = new Stack <IStatement>(); todo.Push(source); while (todo.Count > 0) { IStatement source2 = todo.Pop(); DependencyInformation di2 = context.InputAttributes.Get <DependencyInformation>(source2); if (di2 == null) { context.Error("Dependency information not found for statement: " + source2); continue; } foreach (IStatement init in di2.Overwrites) { int initIndex = g.indexOfNode[init]; if (initIndex < target) { // found a valid initializer action(init); } else { // keep looking backward for a valid initializer todo.Push(init); } } } }
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); } } } }
public void IsPositiveFactorInfo() { FactorManager.FactorInfo info = FactorManager.GetFactorInfo(new Func <double, bool>(Factor.IsPositive)); Assert.True(info.IsDeterministicFactor); var parameterTypes = new Dictionary <string, Type> { ["isPositive"] = typeof(bool), ["x"] = typeof(Gaussian) }; MessageFcnInfo fcninfo = info.GetMessageFcnInfo(factorManager, "AverageConditional", "x", parameterTypes); Assert.True(fcninfo.NotSupportedMessage == null); CheckMessageFcnInfo(fcninfo, info); DependencyInformation depInfo = FactorManager.GetDependencyInfo(fcninfo.Method); Assert.Throws <NotSupportedException>(() => { fcninfo = info.GetMessageFcnInfo(factorManager, "AverageLogarithm", "x", parameterTypes); }); bool found = false; foreach (MessageFcnInfo fcninfo2 in info.GetMessageFcnInfos("AverageLogarithm", null, null)) { CheckMessageFcnInfo(fcninfo2, info); if (fcninfo2.TargetParameter.Equals("x")) { Assert.True(fcninfo2.NotSupportedMessage != null); found = true; } } Assert.True(found); fcninfo = info.GetMessageFcnInfo(factorManager, "LogAverageFactor", "", parameterTypes); CheckMessageFcnInfo(fcninfo, info); }
protected override IStatement DoConvertStatement(IStatement ist) { DependencyInformation di = context.InputAttributes.Get<DependencyInformation>(ist); if (di != null && !indexOfStatement.ContainsKey(ist)) { RemoveRedundantDependencies(ist, di); int index = indexOfStatement.Count; indexOfStatement.Add(ist, index); } IStatement st = base.DoConvertStatement(ist); return st; }
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)); }
internal void ToMessageTest() { FactorManager.FactorInfo info = FactorManager.GetFactorInfo(new Func <double, bool>(Factor.IsPositive)); var parameterTypes = new Dictionary <string, Type> { ["isPositive"] = typeof(bool), ["x"] = typeof(Gaussian) }; MessageFcnInfo fcninfo; fcninfo = info.GetMessageFcnInfo(factorManager, "LogEvidenceRatio2", "", parameterTypes); CheckMessageFcnInfo(fcninfo, info); DependencyInformation depInfo = FactorManager.GetDependencyInfo(fcninfo.Method); }
private void RemoveRedundantDependencies(IStatement ist, DependencyInformation di) { // collapse dependencies that have the same unique index. Dictionary <int, KeyValuePair <int, IStatement> > nodeOfUniqueIndex = new Dictionary <int, KeyValuePair <int, IStatement> >(); Set <IStatement> sourcesToRemove = new Set <IStatement>(ReferenceEqualityComparer <IStatement> .Instance); foreach (IStatement source in di.GetDependenciesOfType(DependencyType.Dependency)) { int sourceIndex; if (indexOfStatement.TryGetValue(source, out sourceIndex)) { int uniqueIndex = loopMergingInfo.GetIndexOf(source); KeyValuePair <int, IStatement> previousEntry; if (nodeOfUniqueIndex.TryGetValue(uniqueIndex, out previousEntry)) { int previousNode = previousEntry.Key; // ist depends on two equivalent statements. // only keep a dependency on the later statement. if (sourceIndex > previousNode) { // source is the later statement. nodeOfUniqueIndex[uniqueIndex] = new KeyValuePair <int, IStatement>(sourceIndex, source); sourcesToRemove.Add(previousEntry.Value); } else { // source is the earlier statement. sourcesToRemove.Add(source); } } else { nodeOfUniqueIndex.Add(uniqueIndex, new KeyValuePair <int, IStatement>(sourceIndex, source)); } } } if (sourcesToRemove.Count > 0) { if (debugBlock != null) { debugBlock.Statements.Add(Builder.CommentStmt($"dropping dependency of {ist} on {sourcesToRemove}")); } di.RemoveAll(sourcesToRemove.Contains); } }
public void IsPositiveFactorInfo() { FactorManager.FactorInfo info = FactorManager.GetFactorInfo(new Func <double, bool>(Factor.IsPositive)); Console.WriteLine(info); Assert.True(info.IsDeterministicFactor); IDictionary <string, Type> parameterTypes = new Dictionary <string, Type>(); parameterTypes["isPositive"] = typeof(bool); parameterTypes["x"] = typeof(Gaussian); MessageFcnInfo fcninfo = info.GetMessageFcnInfo(factorManager, "AverageConditional", "x", parameterTypes); Assert.True(fcninfo.NotSupportedMessage == null); CheckMessageFcnInfo(fcninfo, info); DependencyInformation depInfo = FactorManager.GetDependencyInfo(fcninfo.Method); Console.WriteLine("Dependencies:"); Console.WriteLine(StringUtil.ToString(depInfo.Dependencies)); Console.WriteLine("Requirements:"); Console.WriteLine(StringUtil.ToString(depInfo.Requirements)); try { fcninfo = info.GetMessageFcnInfo(factorManager, "AverageLogarithm", "x", parameterTypes); Assert.True(false, "did not throw exception"); } catch (NotSupportedException ex) { Console.WriteLine("Correctly failed with exception: " + ex); } bool found = false; foreach (MessageFcnInfo fcninfo2 in info.GetMessageFcnInfos("AverageLogarithm", null, null)) { CheckMessageFcnInfo(fcninfo2, info); if (fcninfo2.TargetParameter.Equals("x")) { Assert.True(fcninfo2.NotSupportedMessage != null); found = true; } } Assert.True(found); fcninfo = info.GetMessageFcnInfo(factorManager, "LogAverageFactor", "", parameterTypes); CheckMessageFcnInfo(fcninfo, info); }
//CodeTransformer ct = new CodeTransformer(); protected Node AddNode(GraphWriter g, IStatement ist, Stage stage) { if (ist is ICommentStatement) { return(null); } Node nd = GetNodeForStatement(ist, stage); if (nd != null) { nd.Label = Count + "," + nd.Label; Count++; return(nd); } DependencyInformation di = context.InputAttributes.Get <DependencyInformation>(ist); if ((di != null) && (di.IsOutput)) { return(null); } string s = Count + ". " + StatementLabel(ist); nd = g.AddNode("node" + Count); nd.UserData = Count++; SetNodeForStatement(ist, stage, nd); //if (di.IsOutput) nd.Fillcolor = Color.LightBlue; nd.Label = s; if (stage == Stage.Initialisation) { nd.FillColor = Color.LightGray; } if (ist is IExpressionStatement) { IExpressionStatement ies = (IExpressionStatement)ist; IAssignExpression iae = ies.Expression as IAssignExpression; if ((iae != null) && (iae.Target is IVariableDeclarationExpression)) { nd.BorderWidth = 2; } } nd.Shape = ShapeStyle.Box; nd.FontSize = 9; return(nd); }
/// <summary> /// Copy constructor. /// </summary> /// <param name="that"></param> public MessageFcnInfo(MessageFcnInfo that) { Method = that.Method; TargetParameter = that.TargetParameter; Suffix = that.Suffix; IsStochastic = that.IsStochastic; Dependencies = that.Dependencies; Requirements = that.Requirements; Triggers = that.Triggers; SkipIfAllUniform = that.SkipIfAllUniform; NotSupportedMessage = that.NotSupportedMessage; factorEdgeOfParameter = that.factorEdgeOfParameter; DependencyInfo = that.DependencyInfo; IsMultiplyAll = that.IsMultiplyAll; ReturnedParameterIndex = that.ReturnedParameterIndex; ReturnedInAllElementsParameterIndex = that.ReturnedInAllElementsParameterIndex; ResultParameterIndex = that.ResultParameterIndex; ResultIndexParameterIndex = that.ResultIndexParameterIndex; }
protected void AddDependencyEdges(Graph g, Node nd, DependencyInformation di, Stage stage, Stage parentStage) { foreach (IStatement source in di.GetDependenciesOfType(DependencyType.Dependency | DependencyType.Declaration)) { Node nd2 = GetNodeForStatement(source, stage); if (nd2 == null) { continue; } bool backwards = ((int)nd.UserData) < ((int)nd2.UserData); //Console.WriteLine("stage=" + stage + " " + nd.UserData + " " + nd2.UserData); Edge e; if (backwards) { e = g.AddEdge(nd.Attr.Id, nd2.Attr.Id); e.Attr.Color = Color.Red; e.Attr.ArrowheadAtSource = ArrowStyle.Normal; e.Attr.ArrowheadAtTarget = ArrowStyle.None; } else { e = g.AddEdge(nd2.Attr.Id, nd.Attr.Id); if (parentStage != stage) { e.Attr.Color = Color.LightGray; } } if (di.HasDependency(DependencyType.Trigger, source)) { e.Attr.LineWidth = 2; } if (di.HasDependency(DependencyType.Fresh, source)) { e.Attr.AddStyle(Style.Dashed); } if (di.HasDependency(DependencyType.Cancels, source)) { e.Attr.Color = Color.LightGray; } } //e.LabelText = StatementLabel(ist); e.Label.FontSize = 8; }
/// <summary> /// /// </summary> /// <returns> /// returns a hashtable containing 2 keys. /// 1. expire-items /// 2. resync-items /// against these 2, associated cache keys are returned. /// </returns> internal IDictionary GetExpiredKeys() { ClusteredArrayList sqlKeyList = _sqlConPool.GetExpiredKeys(); sqlKeyList.AddRange(_oledbConPool.GetExpiredKeys()); if (sqlKeyList != null && sqlKeyList.Count > 0) { HashVector cacheKeyList = new HashVector(); ClusteredArrayList expire = new ClusteredArrayList(); ClusteredArrayList resync = new ClusteredArrayList(); IEnumerator ie = sqlKeyList.GetEnumerator(); lock (_dbKeysMappingTbl.SyncRoot) { while (ie.MoveNext()) { if (_dbKeysMappingTbl.Contains(ie.Current)) { DependencyInformation depInfo = _dbKeysMappingTbl[ie.Current] as DependencyInformation; if (depInfo != null) { if (depInfo.Hint.NeedsReSync) { resync.Add(depInfo.CacheKey); } else { expire.Add(depInfo.CacheKey); } } } } cacheKeyList["expire-items"] = expire; cacheKeyList["resync-items"] = resync; return(cacheKeyList); } } return(new HashVector()); }
internal static IEnumerable <NodeIndex> GetOverwrites(BasicTransformContext context, IndexedGraph dependencyGraph, NodeIndex writer, List <IStatement> nodes, Dictionary <IStatement, int> indexOfNode) { IStatement ist = nodes[writer]; DependencyInformation di = context.InputAttributes.Get <DependencyInformation>(ist); if (di == null) { context.Error("Dependency information not found for statement: " + ist); di = new DependencyInformation(); } foreach (IStatement previousWriteStmt in di.Overwrites) { NodeIndex previousWriter = indexOfNode[previousWriteStmt]; if (previousWriter < writer) { yield return(previousWriter); } } }
protected void AddEdges(GraphWriter g, IStatement ist, Stage stage) { Node nd = GetNodeForStatement(ist, stage); if (nd == null) { return; } DependencyInformation di = context.InputAttributes.Get <DependencyInformation>(ist); if (di == null) { return; } AddDependencyEdges(g, nd, di, Stage.Initialisation, stage); if (stage != Stage.Initialisation) { AddDependencyEdges(g, nd, di, Stage.Update, stage); } }
protected void AddDependencyEdges(GraphWriter g, Node nd, DependencyInformation di, Stage stage, Stage parentStage) { foreach (IStatement source in di.GetDependenciesOfType(DependencyType.Dependency | DependencyType.Declaration)) { Node nd2 = GetNodeForStatement(source, stage); if (nd2 == null) { continue; } bool backwards = ((int)nd.UserData) < ((int)nd2.UserData); //Console.WriteLine("stage=" + stage + " " + nd.UserData + " " + nd2.UserData); Edge e; if (backwards) { e = g.AddEdge(nd.ID, nd2.ID); e.Color = Color.Red; e.Reverse = true; } else { e = g.AddEdge(nd2.ID, nd.ID); if (parentStage != stage) { e.Color = Color.LightGray; } } if (di.HasDependency(DependencyType.Trigger, source)) { e.Width = 2; } if (di.HasDependency(DependencyType.Fresh, source)) { e.Style = EdgeStyle.Dashed; } if (di.HasDependency(DependencyType.Cancels, source)) { e.Color = Color.LightGray; } } //e.Label = StatementLabel(ist); e.Label.FontSize = 8; }
public DependencyGraph2(BasicTransformContext context, IEnumerable <IStatement> inputs, BackEdgeHandling backEdgeHandling, Action <IWhileStatement> beginWhile, Action <IWhileStatement> endWhile, Action <IConditionStatement> beginFirstIterPost, Action <IConditionStatement> endFirstIterPost, Action <IStatement, NodeIndex> action) { Set <NodeIndex> nodesInCurrentWhile = new Set <EdgeIndex>(); int whileDepth = 0; // create a dependency graph where while loops are flattened (the while loops themselves are not nodes) // the graph will only contain read-after-write and write-after-alloc dependencies for now // add write-after-read dependencies isWriteAfterRead = dependencyGraph.CreateEdgeData(false); DeadCodeTransform.ForEachStatement(inputs, delegate(IWhileStatement iws) { beginWhile(iws); nodesInCurrentWhile.Clear(); whileDepth++; }, delegate(IWhileStatement iws) { // all duplicates in a while loop should share all targets foreach (KeyValuePair <IStatement, Set <NodeIndex> > entry in duplicates) { IStatement ist = entry.Key; Set <NodeIndex> set = entry.Value; Set <NodeIndex> targets = new Set <EdgeIndex>(); // collect all targets in the while loop foreach (NodeIndex node in set) { foreach (NodeIndex target in dependencyGraph.TargetsOf(node)) { if (nodesInCurrentWhile.Contains(target)) { targets.Add(target); } } } Set <NodeIndex> backEdgeTargets = null; if (!backEdges.TryGetValue(ist, out backEdgeTargets)) { backEdgeTargets = new Set <EdgeIndex>(); backEdges[ist] = backEdgeTargets; } // add all targets to all duplicates in the loop foreach (NodeIndex node in set) { if (!nodesInCurrentWhile.Contains(node)) { continue; } foreach (NodeIndex target in targets) { if (!dependencyGraph.ContainsEdge(node, target)) { if (backEdgeHandling == BackEdgeHandling.Include) { dependencyGraph.AddEdge(node, target); } else if (backEdgeHandling == BackEdgeHandling.Reverse) { if (!dependencyGraph.ContainsEdge(target, node)) { dependencyGraph.AddEdge(target, node); } } if (target < node) { if (backEdgeTargets == null && !backEdges.TryGetValue(ist, out backEdgeTargets)) { backEdgeTargets = new Set <EdgeIndex>(); backEdges[ist] = backEdgeTargets; } backEdgeTargets.Add(target); } } } } } endWhile(iws); whileDepth--; }, beginFirstIterPost, endFirstIterPost, delegate(IStatement ist) { DependencyInformation di = context.InputAttributes.Get <DependencyInformation>(ist); if (di == null) { context.Error("Dependency information not found for statement: " + ist); di = new DependencyInformation(); } NodeIndex targetIndex = dependencyGraph.AddNode(); Set <NodeIndex> backEdgeTargets; Set <NodeIndex> sources = new Set <NodeIndex>(); // for fast checking of duplicate sources foreach (IStatement source in di.GetDependenciesOfType(DependencyType.Dependency | DependencyType.Declaration)) { int sourceIndex; // we assume that the statements are already ordered properly to respect dependencies. // if the source is not in indexOfNode, then it must be a cyclic dependency in this while loop. if (indexOfNode.TryGetValue(source, out sourceIndex)) { if (!sources.Contains(sourceIndex)) { sources.Add(sourceIndex); EdgeIndex edge = dependencyGraph.AddEdge(sourceIndex, targetIndex); } } else { sourceIndex = -1; } if (sourceIndex == -1) { // add a back edge if (!backEdges.TryGetValue(source, out backEdgeTargets)) { backEdgeTargets = new Set <EdgeIndex>(); backEdges[source] = backEdgeTargets; } backEdgeTargets.Add(targetIndex); // add a dependency on the initializers of source Stack <IStatement> todo = new Stack <IStatement>(); todo.Push(source); while (todo.Count > 0) { IStatement source2 = todo.Pop(); DependencyInformation di2 = context.InputAttributes.Get <DependencyInformation>(source2); if (di2 == null) { context.Error("Dependency information not found for statement: " + source2); continue; } foreach (IStatement init in di2.Overwrites) { int initIndex; if (indexOfNode.TryGetValue(init, out initIndex)) { if (!sources.Contains(initIndex)) { sources.Add(initIndex); EdgeIndex edge = dependencyGraph.AddEdge(initIndex, targetIndex); } } else { todo.Push(init); } } } } } if (indexOfNode.ContainsKey(ist)) { Set <int> set; if (!duplicates.TryGetValue(ist, out set)) { set = new Set <int>(); duplicates[ist] = set; set.Add(indexOfNode[ist]); } set.Add(targetIndex); } // the same statement may appear multiple times. when looking up indexOfNode, we want to use the last occurrence of the statement. indexOfNode[ist] = targetIndex; // must do this at the end, in case the stmt depends on a previous occurrence of itself nodesInCurrentWhile.Add(targetIndex); nodes.Add(ist); if (backEdgeHandling != BackEdgeHandling.Ignore && backEdges.TryGetValue(ist, out backEdgeTargets)) { // now that ist has an index, we can fill in the back edges foreach (NodeIndex node in backEdgeTargets) { if (backEdgeHandling == BackEdgeHandling.Include) { if (dependencyGraph.ContainsEdge(targetIndex, node)) { throw new Exception("Internal: back edge already present"); } dependencyGraph.AddEdge(targetIndex, node); } else { // make a new edge, even if one exists. EdgeIndex edge = dependencyGraph.AddEdge(node, targetIndex); isWriteAfterRead[edge] = true; } } } action(ist, targetIndex); }); if (string.Empty.Length > 0) { // loop statements in their original order foreach (NodeIndex target in dependencyGraph.Nodes) { IStatement ist = nodes[target]; if (ist is IWhileStatement) { continue; } foreach (NodeIndex source in GetPreviousReaders(context, dependencyGraph, target, nodes, indexOfNode).ToReadOnlyList()) { if (source > target) { throw new Exception("Internal: source statement follows target"); } // make a new edge, even if one exists. EdgeIndex edge = dependencyGraph.AddEdge(source, target); isWriteAfterRead[edge] = true; } } } isWriteAfterWrite = dependencyGraph.CreateEdgeData(false); // loop statements in their original order foreach (NodeIndex target in dependencyGraph.Nodes) { IStatement ist = nodes[target]; if (ist is IWhileStatement) { continue; } foreach (NodeIndex source in GetOverwrites(context, dependencyGraph, target, nodes, indexOfNode).ToReadOnlyList()) { if (source > target) { throw new Exception("Internal: source statement follows target"); } if (dependencyGraph.ContainsEdge(source, target)) { foreach (EdgeIndex edge in dependencyGraph.EdgesLinking(source, target)) { isWriteAfterWrite[edge] = true; } } else { EdgeIndex edge = dependencyGraph.AddEdge(source, target); isWriteAfterWrite[edge] = true; } } } dependencyGraph.NodeCountIsConstant = true; dependencyGraph.IsReadOnly = true; for (int targetIndex = 0; targetIndex < dependencyGraph.Nodes.Count; targetIndex++) { IStatement ist = nodes[targetIndex]; DependencyInformation di = context.InputAttributes.Get <DependencyInformation>(ist); if (di == null) { continue; } if (di.IsOutput) { outputNodes.Add(targetIndex); } } }
protected override IStatement ConvertWhile(IWhileStatement iws) { bool wasInWhileLoop = this.inWhileLoop; if (!wasInWhileLoop) { // collect all statements in the body of this loop (and any nested loops). DeadCodeTransform.ForEachStatement(iws.Body.Statements, _ => { }, _ => { }, _ => { }, _ => { }, ist => { visitedStatements.Add(ist); }); // collect all IncrementStatement attributes in the body of this loop (and any nested loops). DeadCodeTransform.ForEachStatement(iws.Body.Statements, _ => { }, _ => { }, _ => { }, _ => { }, ist => { var incrementStatement = context.GetAttribute <IncrementStatement>(ist); if (incrementStatement != null) { DependencyInformation di = context.GetAttribute <DependencyInformation>(ist); if (di != null && !di.GetDependenciesOfType(DependencyType.Cancels).All(visitedStatements.Contains)) { // Remove increment statements whose Cancels input is not available, implying that there is no purpose in carrying out the increment. // This happens because IterationTransform ignores Cancels edges. replacements[ist] = null; } else { incrementStatements.Add(incrementStatement); } } }); ancestorIndexOfWhile = context.Depth - 1; } this.inWhileLoop = true; var ws = base.ConvertWhile(iws); this.inWhileLoop = wasInWhileLoop; if (!wasInWhileLoop) { incrementStatements.Clear(); } return(ws); }
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); }
/// <summary> /// Update the dependency information of all statements, assuming that the original statements have been permuted and duplicated, but not transformed. /// </summary> /// <param name="outputs"></param> private void PostProcessDependencies(ICollection <IStatement> outputs) { Dictionary <IStatement, int> indexOfStatement = new Dictionary <IStatement, NodeIndex>(ReferenceEqualityComparer <IStatement> .Instance); if (clonesOfStatement.Count == 0) { return; } DeadCodeTransform.ForEachStatement(outputs, _ => { }, _ => { }, _ => { }, _ => { }, ist => { 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.AddClones(clonesOfStatement); IStatement originalStatement; originalStatementOfClone.TryGetValue(ist, out originalStatement); // originalStatement is non-null iff ist is a clone IEnumerable <IStatement> clones; if (clonesOfStatement.TryGetValue(originalStatement ?? ist, out clones)) { // clones become Overwrites foreach (var clone in clones) { di2.Add(DependencyType.Overwrite, clone); } if (originalStatement != null) { di2.Add(DependencyType.Overwrite, originalStatement); } } // keep only the most recent overwrite that is not an allocation, and all overwrites that are allocations. IStatement mostRecentWriter = null; int mostRecentWriterIndex = 0; List <IStatement> allocations = new List <IStatement>(); foreach (var writer in di2.Overwrites) { int index; indexOfStatement.TryGetValue(writer, out index); if (index > mostRecentWriterIndex) { mostRecentWriterIndex = index; mostRecentWriter = writer; } if (di2.HasDependency(DependencyType.Declaration, writer)) { allocations.Add(writer); } } di2.Remove(DependencyType.Overwrite); // all allocations must remain as Overwrites foreach (var dep in allocations) { di2.Add(DependencyType.Overwrite, dep); } if (mostRecentWriter != null) { di2.Add(DependencyType.Overwrite, mostRecentWriter); } context.OutputAttributes.Remove <DependencyInformation>(ist); context.OutputAttributes.Set(ist, di2); } indexOfStatement[ist] = indexOfStatement.Count + 1; }); }
void ProcessStatements(IList <IStatement> outputs, IList <IStatement> outputDecls, IList <IStatement> inputs, Dictionary <IStatement, IStatement> replacements) { for (int i = 0; i < inputs.Count; i++) { IStatement ist = inputs[i]; if (ist is IWhileStatement) { IWhileStatement iws = (IWhileStatement)ist; IWhileStatement ws = Builder.WhileStmt(iws); bool doNotSchedule = context.InputAttributes.Has <DoNotSchedule>(iws); if (doNotSchedule) { // iws may contain nested while loops // TODO: make sure the new decls go in the right place ProcessStatements(ws.Body.Statements, outputDecls, iws.Body.Statements, replacements); } else { IReadOnlyList <IStatement> inputStmts = (IReadOnlyList <IStatement>)iws.Body.Statements; IStatement firstIterPostBlock = ForwardBackwardTransform.ExtractFirstIterationPostProcessingBlock(context, ref inputStmts); DependencyGraph g = new DependencyGraph(context, inputStmts, ignoreMissingNodes: true, ignoreRequirements: true); // look for cycles of initialized nodes and insert clones as needed Set <NodeIndex> nodesToClone = GetNodesToClone(g, g.dependencyGraph.Nodes); for (int node = 0; node < inputStmts.Count; node++) { IStatement st = inputStmts[node]; if (nodesToClone.Contains(node)) { cloneDecls.Clear(); cloneUpdates.Clear(); containers.Clear(); IStatement newStmt = ConvertStatement(st); IStatement declStmt = cloneDecls[0]; IStatement setToStmt = cloneUpdates[0]; outputDecls.AddRange(cloneDecls); DependencyInformation diNew = (DependencyInformation)context.InputAttributes.Get <DependencyInformation>(newStmt).Clone(); context.OutputAttributes.Remove <DependencyInformation>(newStmt); context.OutputAttributes.Set(newStmt, diNew); DependencyInformation diSet = new DependencyInformation(); diSet.Add(DependencyType.Dependency | DependencyType.Requirement, newStmt); context.OutputAttributes.Set(setToStmt, diSet); DependencyInformation diDecl = new DependencyInformation(); context.OutputAttributes.Set(declStmt, diDecl); foreach (IStatement writer in diNew.Overwrites) { diDecl.Add(DependencyType.Dependency, writer); diSet.Add(DependencyType.Overwrite, writer); } diNew.Remove(DependencyType.Overwrite); diNew.Add(DependencyType.Declaration | DependencyType.Dependency | DependencyType.Overwrite, declStmt); if (loopMergingInfo != null) { // update loopMergingInfo with the new statement int oldNode = loopMergingInfo.GetIndexOf(st); int newNode = loopMergingInfo.AddNode(newStmt); loopMergingInfo.InheritSourceConflicts(newNode, oldNode); int setToNode = loopMergingInfo.AddNode(setToStmt); loopMergingInfo.InheritTargetConflicts(setToNode, oldNode); int declNode = loopMergingInfo.AddNode(declStmt); } replacements[st] = setToStmt; context.InputAttributes.CopyObjectAttributesTo <InitialiseBackward>(st, context.OutputAttributes, setToStmt); st = newStmt; ws.Body.Statements.AddRange(cloneUpdates); } else { RegisterUnchangedStatement(st); } ws.Body.Statements.Add(st); } if (firstIterPostBlock != null) { ws.Body.Statements.Add(firstIterPostBlock); } } context.InputAttributes.CopyObjectAttributesTo(iws, context.OutputAttributes, ws); ist = ws; } else { RegisterUnchangedStatement(ist); } outputs.Add(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); }