private void CreateReducedVariableInformation(IVariableDeclaration ivd, HoistingInfo info) { int arrayDepth = info.maxDepthWhereDimensionCouldMatter.Length; var varInfo = VariableInformation.GetVariableInformation(context, ivd); var reducedVarInfo = VariableInformation.GetVariableInformation(context, info.newVariable); for (int bracket = 0; bracket < varInfo.sizes.Count; bracket++) { List <IExpression> newSizes = new List <IExpression>(); List <IVariableDeclaration> newIndexVars = new List <IVariableDeclaration>(); for (int dim = 0; dim < varInfo.sizes[bracket].Length; dim++) { if (info.maxDepthWhereDimensionCouldMatter[bracket][dim] == arrayDepth) { newSizes.Add(varInfo.sizes[bracket][dim]); if (varInfo.indexVars.Count > bracket && varInfo.indexVars[bracket].Length > dim) { newIndexVars.Add(varInfo.indexVars[bracket][dim]); } } } if (newSizes.Count > 0) { reducedVarInfo.sizes.Add(newSizes.ToArray()); reducedVarInfo.indexVars.Add(newIndexVars.ToArray()); } } }
protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie) { var indices = Recognizer.GetIndices(iaie, out IExpression target); if (target is IVariableReferenceExpression) { // Only convert indices that could matter. IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(target); HoistingInfo info = GetOrCreateHoistingInfo(ivd); int indexingDepth = indices.Count; for (int bracket = 0; bracket < indexingDepth; bracket++) { for (int dim = 0; dim < indices[bracket].Count; dim++) { if (info.maxDepthWhereDimensionCouldMatter.Length <= bracket || info.maxDepthWhereDimensionCouldMatter[bracket][dim] >= indexingDepth) { ConvertExpression(indices[bracket][dim]); } } } return(iaie); } else { return(base.ConvertArrayIndexer(iaie)); } }
private void SetDimensionMattersAtDepth(HoistingInfo info, int bracket, int dim, int depth) { var oldDepth = info.maxDepthWhereDimensionCouldMatter[bracket][dim]; if (depth > oldDepth) { info.maxDepthWhereDimensionCouldMatter[bracket][dim] = depth; anyChanged = true; } }
private HoistingInfo GetOrCreateHoistingInfo(IVariableDeclaration ivd) { HoistingInfo info; if (!infoOfVariable.TryGetValue(ivd, out info)) { info = new HoistingInfo(VariableInformation.GetVariableInformation(context, ivd)); infoOfVariable.Add(ivd, info); } return(info); }
private bool IsReducibleAtDepth(HoistingInfo info, int depth) { int arrayDepth = info.maxDepthWhereDimensionCouldMatter.Length; for (int bracket = depth; bracket < info.maxDepthWhereDimensionCouldMatter.Length; bracket++) { for (int dim = 0; dim < info.maxDepthWhereDimensionCouldMatter[bracket].Length; dim++) { if (info.maxDepthWhereDimensionCouldMatter[bracket][dim] != arrayDepth) { return(false); } } } return(true); }
private Type GetReducedType(Type type, HoistingInfo info) { int arrayDepth = info.maxDepthWhereDimensionCouldMatter.Length; Stack <Type> stack = new Stack <Type>(); for (int bracket = 0; bracket < arrayDepth; bracket++) { stack.Push(type); type = Util.GetElementType(type); } Type reducedType = type; for (int bracket = arrayDepth - 1; bracket >= 0; bracket--) { Type originalType = stack.Pop(); int reducedRank = info.maxDepthWhereDimensionCouldMatter[bracket].Count(d => d == arrayDepth); if (reducedRank > 0) { reducedType = Util.ChangeElementTypeAndRank(originalType, reducedType, reducedRank); } } return(reducedType); }
private void PromoteDimensions(HoistingInfo info) { int arrayDepth = info.maxDepthWhereDimensionCouldMatter.Length; bool previousBracketMattersAtArrayDepth = false; for (int bracket = arrayDepth - 1; bracket >= 0; bracket--) { bool bracketMattersAtArrayDepth = false; for (int dim = 0; dim < info.maxDepthWhereDimensionCouldMatter[bracket].Length; dim++) { int depth = info.maxDepthWhereDimensionCouldMatter[bracket][dim]; if (depth == arrayDepth) { bracketMattersAtArrayDepth = true; } else if (depth > 0 && previousBracketMattersAtArrayDepth) { info.maxDepthWhereDimensionCouldMatter[bracket][dim] = arrayDepth; bracketMattersAtArrayDepth = true; } } previousBracketMattersAtArrayDepth = bracketMattersAtArrayDepth; } }
protected override IExpression ConvertAssign(IAssignExpression iae) { IExpression target; var indices = Recognizer.GetIndices(iae.Target, out target); if (target is IVariableReferenceExpression || target is IVariableDeclarationExpression) { variablesInExpression.Clear(); ConvertExpression(iae.Expression); IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(target); HoistingInfo info = GetOrCreateHoistingInfo(ivd); int depth = indices.Count; bool rhsIsReducible = IsReducibleArrayCreateExpression(iae.Expression); if (!rhsIsReducible) { bool rhsIsCopy = Recognizer.IsStaticGenericMethod(iae.Expression, new Func <PlaceHolder, PlaceHolder, PlaceHolder>(ArrayHelper.SetTo)); if (rhsIsCopy) { IMethodInvokeExpression imie = (IMethodInvokeExpression)iae.Expression; var sourceExpr = imie.Arguments[1]; var sourceIndices = Recognizer.GetIndices(sourceExpr, out IExpression source); if (source is IVariableDeclaration) { IVariableDeclaration sourceVar = Recognizer.GetVariableDeclaration(source); HoistingInfo sourceInfo = GetOrCreateHoistingInfo(sourceVar); for (int bracket = indices.Count; bracket < info.maxDepthWhereDimensionCouldMatter.Length; bracket++) { int sourceBracket = sourceIndices.Count + bracket; for (int dim = 0; dim < info.maxDepthWhereDimensionCouldMatter[bracket].Length; dim++) { // the dimension matters if it matters in the source array. int sourceDepth = sourceInfo.maxDepthWhereDimensionCouldMatter[sourceBracket][dim]; SetDimensionMattersAtDepth(info, bracket, dim, sourceDepth); depth = System.Math.Max(depth, sourceDepth); } } } else { rhsIsCopy = false; } } if (!rhsIsCopy) { // all deeper dimensions matter for (int bracket = indices.Count; bracket < info.maxDepthWhereDimensionCouldMatter.Length; bracket++) { for (int dim = 0; dim < info.maxDepthWhereDimensionCouldMatter[bracket].Length; dim++) { int arrayDepth = info.maxDepthWhereDimensionCouldMatter.Length; SetDimensionMattersAtDepth(info, bracket, dim, arrayDepth); depth = System.Math.Max(depth, arrayDepth); } } } } // expand variablesInExpression based on correlations in the index expressions. // For example: // array[i][index[i][j]] = j // depends on i and j. bool changed; do { changed = false; for (int bracket = 0; bracket < indices.Count; bracket++) { for (int dim = 0; dim < indices[bracket].Count; dim++) { var index = indices[bracket][dim]; var indexVars = Recognizer.GetVariables(index).ToList(); if (variablesInExpression.ContainsAny(indexVars) && indexVars.Any(v => !variablesInExpression.Contains(v))) { variablesInExpression.AddRange(indexVars); changed = true; } } } } while (changed); for (int bracket = 0; bracket < indices.Count; bracket++) { for (int dim = 0; dim < indices[bracket].Count; dim++) { var index = indices[bracket][dim]; if (index is IVariableReferenceExpression) { IVariableDeclaration indexVar = Recognizer.GetVariableDeclaration(index); if (variablesInExpression.Contains(indexVar) || !unbrokenLoopVars.Contains(indexVar)) { // index is used on rhs or the loop is broken, so the dimension matters. SetDimensionMattersAtDepth(info, bracket, dim, depth); } } else { // index is not a loop counter, so the dimension matters. SetDimensionMattersAtDepth(info, bracket, dim, depth); } } } return(iae); } else { return(base.ConvertAssign(iae)); } }
protected override IExpression ConvertMethodInvoke(IMethodInvokeExpression imie) { if (imie.Arguments.Any(arg => arg is IAddressOutExpression)) { Set <IVariableDeclaration> oldVariablesInExpression = (Set <IVariableDeclaration>)variablesInExpression.Clone(); variablesInExpression.Clear(); ConvertExpression(imie.Method); foreach (var arg in imie.Arguments) { if (!(arg is IAddressOutExpression)) { ConvertExpression(arg); } } foreach (var arg in imie.Arguments) { if (arg is IAddressOutExpression iaoe) { var indices = Recognizer.GetIndices(iaoe.Expression, out IExpression target); if (target is IVariableReferenceExpression || target is IVariableDeclarationExpression) { IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(target); HoistingInfo info = GetOrCreateHoistingInfo(ivd); int arrayDepth = info.maxDepthWhereDimensionCouldMatter.Length; for (int bracket = 0; bracket < indices.Count; bracket++) { for (int dim = 0; dim < indices[bracket].Count; dim++) { var index = indices[bracket][dim]; if (index is IVariableReferenceExpression) { IVariableDeclaration indexVar = Recognizer.GetVariableDeclaration(index); if (variablesInExpression.Contains(indexVar) || !unbrokenLoopVars.Contains(indexVar)) { // index is used on rhs or the loop is broken, so the dimension matters. SetDimensionMattersAtDepth(info, bracket, dim, arrayDepth); } } else { // index is not a loop counter, so the dimension matters. SetDimensionMattersAtDepth(info, bracket, dim, arrayDepth); } } } // all deeper dimensions matter for (int bracket = indices.Count; bracket < arrayDepth; bracket++) { for (int dim = 0; dim < info.maxDepthWhereDimensionCouldMatter[bracket].Length; dim++) { SetDimensionMattersAtDepth(info, bracket, dim, arrayDepth); } } } } } variablesInExpression.AddRange(oldVariablesInExpression); return(imie); } else { return(base.ConvertMethodInvoke(imie)); } }