private static void ForEachMatchingLoopVariable( List <IStatement> containersOfSource, List <IStatement> containersOfTarget, Action <IVariableDeclaration, IForStatement, IForStatement> action) { for (int i = 0; i < System.Math.Min(containersOfTarget.Count, containersOfSource.Count); i++) { if (containersOfTarget[i] is IForStatement) { if (!(containersOfSource[i] is IForStatement)) { break; } IForStatement afs = (IForStatement)containersOfTarget[i]; IForStatement bfs = (IForStatement)containersOfSource[i]; IVariableDeclaration loopVar = Recognizer.LoopVariable(afs); if (Recognizer.LoopVariable(bfs) != loopVar) { break; } // both loops use the same variable. action(loopVar, afs, bfs); } else if (!Containers.ContainersAreEqual(containersOfTarget[i], containersOfSource[i])) { break; } } }
private IList <IStatement> UnwrapStatement(IStatement ist, IList <IStatement> newContainers, IList <int> newPriority, int stmtIndex, bool keepNested) { List <IStatement> stmtContainers = new List <IStatement>(); IList <IStatement> core = UnwrapStatement(ist, stmtContainers); int[] priority = GetPriorities(stmtContainers); int[] openPriority = Util.ArrayInit(openContainers.Count, i => - 1); int highestNewPriority = 0; // determine the set of open containers which can be kept for (int j = 0; j < stmtContainers.Count; j++) { IStatement container = stmtContainers[j]; if (container is IBrokenForStatement) { continue; } bool found = false; for (int i = 0; i < openContainers.Count; i++) { IStatement openContainer = openContainers[i]; if (Containers.ContainersAreEqual(openContainer, container)) { found = true; if (CanAddToContainer(openContainer, stmtIndex)) { openPriority[i] = priority[j]; } break; } } if (!found && priority[j] > highestNewPriority) { highestNewPriority = priority[j]; } } // priority of containers: // 1. a sequential container that is already open, and its parent containers (whether they are sequential or not). // 2. a new sequential container and its parent containers. // 3. a container that is already open. if (keepNested) { // close all open containers whose priority is lower than highestNewPriority for (int i = openContainers.Count - 1; i >= 0; i--) { if (openPriority[i] < highestNewPriority) { openPriority[i] = -1; } else { break; } } // close all containers beyond the first closed one for (int i = 0; i < openContainers.Count; i++) { if (openPriority[i] == -1) { RemoveLast(openContainers, i); break; } } } else { List <IStatement> keptContainers = new List <IStatement>(); for (int i = 0; i < openContainers.Count; i++) { if (openPriority[i] >= 0) { keptContainers.Add(openContainers[i]); } } openContainers.Clear(); openContainers.AddRange(keptContainers); } List <KeyValuePair <int, IStatement> > newContainersWithPriority = new List <KeyValuePair <int, IStatement> >(); for (int j = 0; j < stmtContainers.Count; j++) { IStatement container = stmtContainers[j]; bool found = false; for (int i = 0; i < openContainers.Count; i++) { IStatement openContainer = openContainers[i]; if (Containers.ContainersAreEqual(openContainer, container)) { if (openPriority[i] >= 0) { found = true; } break; } } if (!found) { newContainersWithPriority.Add(new KeyValuePair <int, IStatement>(priority[j], container)); } } newContainers.Clear(); newPriority.Clear(); foreach (var kvp in newContainersWithPriority.OrderByDescending(kvp => kvp.Key)) { newPriority.Add(kvp.Key); newContainers.Add(kvp.Value); } return(core); }
protected override IExpression ConvertMethodInvoke(IMethodInvokeExpression imie) { IExpression result = base.ConvertMethodInvoke(imie); if (result is IMethodInvokeExpression) { imie = (IMethodInvokeExpression)result; } else { return(result); } if (UseJaggedSubarray && Recognizer.IsStaticGenericMethod(imie, new Func <IReadOnlyList <PlaceHolder>, IReadOnlyList <int>, IReadOnlyList <PlaceHolder> >(Collection.Subarray))) { // check for the form Subarray(arrayExpr, indices[i]) where arrayExpr does not depend on i IExpression arrayExpr = imie.Arguments[0]; IExpression arg1 = imie.Arguments[1]; if (arg1 is IArrayIndexerExpression) { IArrayIndexerExpression index = (IArrayIndexerExpression)arg1; if (index.Indices.Count == 1 && index.Indices[0] is IVariableReferenceExpression) { // index has the form indices[i] List <IStatement> targetLoops = Containers.GetLoopsNeededForExpression(context, arrayExpr, -1, false); List <IStatement> indexLoops = Containers.GetLoopsNeededForExpression(context, index.Target, -1, false); Set <IStatement> parentLoops = new Set <IStatement>(); parentLoops.AddRange(targetLoops); parentLoops.AddRange(indexLoops); IVariableReferenceExpression innerIndex = (IVariableReferenceExpression)index.Indices[0]; IForStatement innerLoop = Recognizer.GetLoopForVariable(context, innerIndex); foreach (IStatement loop in parentLoops) { if (Containers.ContainersAreEqual(loop, innerLoop)) { // arrayExpr depends on i return(imie); } } IVariableDeclaration arrayVar = Recognizer.GetVariableDeclaration(arrayExpr); // If the variable is not stochastic, return if (arrayVar == null) { return(imie); } VariableInformation arrayInfo = VariableInformation.GetVariableInformation(context, arrayVar); if (!arrayInfo.IsStochastic) { return(imie); } object indexVar = Recognizer.GetDeclaration(index); VariableInformation indexInfo = VariableInformation.GetVariableInformation(context, indexVar); int depth = Recognizer.GetIndexingDepth(index); IExpression resultSize = indexInfo.sizes[depth][0]; var indices = Recognizer.GetIndices(index); int replaceCount = 0; resultSize = indexInfo.ReplaceIndexVars(context, resultSize, indices, null, ref replaceCount); indexInfo.DefineIndexVarsUpToDepth(context, depth + 1); IVariableDeclaration resultIndex = indexInfo.indexVars[depth][0]; Type arrayType = arrayExpr.GetExpressionType(); Type elementType = Util.GetElementType(arrayType); // create a new variable arrayExpr_indices = JaggedSubarray(arrayExpr, indices) string name = ToString(arrayExpr) + "_" + ToString(index.Target); var stmts = Builder.StmtCollection(); var arrayIndices = Recognizer.GetIndices(arrayExpr); var bracket = Builder.ExprCollection(); bracket.Add(Builder.ArrayIndex(index, Builder.VarRefExpr(resultIndex))); arrayIndices.Add(bracket); IExpression loopSize = Recognizer.LoopSizeExpression(innerLoop); IVariableDeclaration temp = arrayInfo.DeriveArrayVariable(stmts, context, name, resultSize, resultIndex, arrayIndices); VariableInformation tempInfo = VariableInformation.GetVariableInformation(context, temp); stmts.Clear(); IVariableDeclaration newvd = tempInfo.DeriveArrayVariable(stmts, context, name, loopSize, Recognizer.GetVariableDeclaration(innerIndex)); if (!context.InputAttributes.Has <DerivedVariable>(newvd)) { context.InputAttributes.Set(newvd, new DerivedVariable()); } IExpression rhs = Builder.StaticGenericMethod(new Func <IReadOnlyList <PlaceHolder>, int[][], PlaceHolder[][]>(Collection.JaggedSubarray), new Type[] { elementType }, arrayExpr, index.Target); context.InputAttributes.CopyObjectAttributesTo <Algorithm>(newvd, context.OutputAttributes, rhs); stmts.Add(Builder.AssignStmt(Builder.VarRefExpr(newvd), rhs)); // Reduce memory consumption by declaring the clone outside of unnecessary loops. // This way, the item is cloned outside the loop and then replicated, instead of replicating the entire array and cloning the item. Containers containers = new Containers(context); containers = RemoveReferencesTo(containers, innerIndex); containers = Containers.RemoveUnusedLoops(containers, context, rhs); if (context.InputAttributes.Has <DoNotSendEvidence>(arrayVar)) { containers = Containers.RemoveStochasticConditionals(containers, context); } // To put the declaration in the desired containers, we find an ancestor which includes as many of the containers as possible, // then wrap the declaration with the remaining containers. int ancIndex = containers.GetMatchingAncestorIndex(context); Containers missing = containers.GetContainersNotInContext(context, ancIndex); stmts = Containers.WrapWithContainers(stmts, missing.outputs); context.AddStatementsBeforeAncestorIndex(ancIndex, stmts); context.InputAttributes.Set(newvd, containers); // convert into arrayExpr_indices[i] IExpression newExpr = Builder.ArrayIndex(Builder.VarRefExpr(newvd), innerIndex); newExpr = Builder.StaticGenericMethod(new Func <PlaceHolder, PlaceHolder>(Clone.Copy <PlaceHolder>), new Type[] { newExpr.GetExpressionType() }, newExpr); return(newExpr); } } } return(imie); }
/// <summary> /// Add localInfo for expr to the current containerInfo. /// </summary> /// <param name="decl"></param> /// <param name="expr"></param> /// <param name="localInfo"></param> /// <param name="closedContainer"></param> protected LocalInfo AddLocalInfo(object decl, IExpression expr, LocalInfo localInfo, IForStatement closedContainer) { if (containerInfos.Count == 0) { return(localInfo); } ContainerInfo containerInfo = containerInfos.Peek(); UsageInfo usageInfo; if (!containerInfo.usageInfoOfVariable.TryGetValue(decl, out usageInfo)) { usageInfo = new UsageInfo(); containerInfo.usageInfoOfVariable[decl] = usageInfo; } LocalInfo info; if (!usageInfo.localInfos.TryGetValue(expr, out info)) { info = localInfo.Clone(); info.containingStatements.IntersectWith(openContainers); IVariableDeclaration loopVar = Recognizer.LoopVariable(closedContainer); int index = info.containers.inputs.FindIndex(container => Containers.ContainersAreEqual(container, closedContainer, allowBrokenLoops: true, ignoreLoopDirection: true)); bool conditionsContainLoopVar = info.containers.inputs.Skip(index + 1).Any(container => Recognizer.GetVariables(GetContainerExpression(container)).Contains(loopVar)); IStatement replacement = null; if (conditionsContainLoopVar) { replacement = Builder.BrokenForStatement(closedContainer); info.containingStatements.Add(replacement); } else { var loopSize = Recognizer.LoopSizeExpression(closedContainer); bool loopMustExecute = false; if (loopSize is ILiteralExpression ile) { int loopSizeAsInt = (int)ile.Value; if (loopSizeAsInt > 0) { loopMustExecute = true; } } if (!loopMustExecute) { var condition = Builder.BinaryExpr(loopSize, BinaryOperator.GreaterThan, Builder.LiteralExpr(0)); replacement = Builder.CondStmt(condition, Builder.BlockStmt()); } } if (info.containers.inputs.Contains(replacement)) { replacement = null; } if (replacement == null) { info.containers = info.containers.Where(container => !Containers.ContainersAreEqual(container, closedContainer, true, true)); } else { // this only replaces containers.inputs info.containers = info.containers.Replace(container => !Containers.ContainersAreEqual(container, closedContainer, true, true) ? container : replacement); } int previousCount = info.containers.Count; info.containers = Containers.RemoveInvalidConditions(info.containers, context); if (info.containers.Count != previousCount && expr is IArrayIndexerExpression) { // when dropping conditionals, we need to show that if the indices were valid inside the conditionals, they remain valid outside the conditionals. // This is automatically true if the indices match the indexVars. expr = GetPrefixIndexedByIndexVars(expr); } usageInfo.localInfos[expr] = info; } else { info.Add(localInfo); } info.appearsInNestedLoop = true; return(info); }