示例#1
0
        /// <summary>
        /// Return the common parent of the two expressions, and indicate if the expressions overlap
        /// </summary>
        /// <param name="eb1"></param>
        /// <param name="eb2"></param>
        /// <returns></returns>
        /// <remarks>
        /// When finding the common parent, we want to preserve any array slicing.  Indexing brackets are not removed if present in both expressions.
        /// Mismatching indices are replaced by AnyIndex.
        /// Examples:
        /// i = loop index inside the gate block
        /// j = loop index outside the gate block, or a method parameter
        /// (a,a[i]) => (a,true)
        /// (a,a[j]) => (a,true)
        /// (a[i],a[0]) => (a[*],true)
        /// (a[i],a[j]) => (a[*],true)
        /// (a[j],a[0]) => (a[*],assumeMatch)
        /// (a[0],a[1]) => (a[*],false)
        /// (a[0][0],a[1][0]) => (a[*][0],false)
        /// (a[0][0],a[1][1]) => (a[*][*],false)
        /// </remarks>
        private static ExpressionWithBindings GetCommonParent(ExpressionWithBindings eb1, ExpressionWithBindings eb2)
        {
            List <IExpression> prefixes1 = Recognizer.GetAllPrefixes(eb1.Expression);
            List <IExpression> prefixes2 = Recognizer.GetAllPrefixes(eb2.Expression);

            if (!prefixes1[0].Equals(prefixes2[0]))
            {
                throw new Exception("Expressions have no overlap: " + eb1 + "," + eb2);
            }
            IExpression parent = prefixes1[0];
            int         count  = System.Math.Min(prefixes1.Count, prefixes2.Count);

            for (int i = 1; i < count; i++)
            {
                IExpression prefix1 = prefixes1[i];
                IExpression prefix2 = prefixes2[i];
                if (prefix1 is IArrayIndexerExpression)
                {
                    IArrayIndexerExpression iaie1 = (IArrayIndexerExpression)prefix1;
                    if (prefix2 is IArrayIndexerExpression)
                    {
                        IArrayIndexerExpression iaie2 = (IArrayIndexerExpression)prefix2;
                        if (iaie1.Indices.Count != iaie2.Indices.Count)
                        {
                            throw new Exception("Array rank mismatch: " + eb1 + "," + eb2);
                        }
                        IList <IExpression> indices = Builder.ExprCollection();
                        for (int ind = 0; ind < iaie1.Indices.Count; ind++)
                        {
                            IExpression index1 = iaie1.Indices[ind];
                            IExpression index2 = iaie2.Indices[ind];
                            IExpression index  = Unify(index1, eb1.Bindings, index2, eb2.Bindings);
                            indices.Add(index);
                        }
                        parent = Builder.ArrayIndex(parent, indices);
                    }
                    else
                    {
                        break;
                    }
                }
                else
                {
                    throw new Exception("Unhandled expression type: " + prefix1);
                }
            }
            ExpressionWithBindings result = new ExpressionWithBindings();

            result.Expression = parent;
            if (eb1.Bindings.Count > 0 && eb2.Bindings.Count > 0)
            {
                result.Bindings.AddRange(eb1.Bindings);
                result.Bindings.AddRange(eb2.Bindings);
            }
            return(result);
        }
示例#2
0
 private void RemoveUsesOfDefs(GateBlock gateBlock)
 {
     foreach (KeyValuePair <IVariableDeclaration, ExpressionWithBindings> entry in gateBlock.variablesDefined)
     {
         IVariableDeclaration   ivd = entry.Key;
         ExpressionWithBindings eb  = entry.Value;
         if (gateBlock.variablesUsed.TryGetValue(ivd, out List <ExpressionWithBindings> ebs))
         {
             List <ExpressionWithBindings> keep = new List <ExpressionWithBindings>();
             foreach (ExpressionWithBindings eb2 in ebs)
             {
                 if (!CouldOverlap(eb, eb2))
                 {
                     keep.Add(eb2);
                 }
             }
             gateBlock.variablesUsed[ivd] = keep;
         }
     }
 }
示例#3
0
        internal static bool CouldOverlap(ExpressionWithBindings eb1, ExpressionWithBindings eb2)
        {
            var emptyBindings = (IEnumerable <IReadOnlyCollection <ConditionBinding> >) new[] { new ConditionBinding[0] };
            IEnumerable <IReadOnlyCollection <ConditionBinding> > bindings1 = (eb1.Bindings.Count > 0) ?
                                                                              eb1.Bindings : emptyBindings;
            IEnumerable <IReadOnlyCollection <ConditionBinding> > bindings2 = (eb2.Bindings.Count > 0) ?
                                                                              eb2.Bindings : emptyBindings;

            foreach (IReadOnlyCollection <ConditionBinding> binding1 in bindings1)
            {
                foreach (IReadOnlyCollection <ConditionBinding> binding2 in bindings2)
                {
                    // TODO: investigate whether we need to provide local var predicate.
                    if (Recognizer.MutatingFirstAffectsSecond(eb1.Expression, eb2.Expression, binding1, binding2, ivd => false))
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
示例#4
0
        /// <summary>
        /// Add expr to currentBlock.variablesDefined or currentBlock.variablesUsed
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="isDef"></param>
        /// <param name="conditionContext"></param>
        protected void ProcessUse(IExpression expr, bool isDef, List <ConditionBinding> conditionContext)
        {
            IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(expr);

            if (ivd == null)
            {
                return;
            }
            if (!CodeRecognizer.IsStochastic(context, ivd))
            {
                return;
            }
            if (gateBlockContext.Count == 0)
            {
                return;
            }
            GateBlock currentBlock   = gateBlockContext[gateBlockContext.Count - 1];
            GateBlock gateBlockOfVar = context.InputAttributes.Get <GateBlock>(ivd);

            if (gateBlockOfVar == currentBlock)
            {
                return;                                 // local variable of the gateBlock
            }
            ExpressionWithBindings eb = new ExpressionWithBindings();

            eb.Expression = ReplaceLocalIndices(currentBlock, expr);
            List <ConditionBinding> bindings = FilterConditionContext(currentBlock, conditionContext);

            if (bindings.Count > 0)
            {
                eb.Bindings.Add(bindings);
            }
            //eb.Containers = Containers.InsideOf(context, GetAncestorIndexOfGateBlock(currentBlock));
            if (isDef)
            {
                ExpressionWithBindings eb2;
                if (!currentBlock.variablesDefined.TryGetValue(ivd, out eb2))
                {
                    currentBlock.variablesDefined[ivd] = eb;
                }
                else
                {
                    // all definitions of the same variable must have a common parent
                    currentBlock.variablesDefined[ivd] = GetCommonParent(eb, eb2);
                }
            }
            else
            {
                List <ExpressionWithBindings> ebs;
                if (!currentBlock.variablesUsed.TryGetValue(ivd, out ebs))
                {
                    ebs = new List <ExpressionWithBindings>();
                    ebs.Add(eb);
                    currentBlock.variablesUsed[ivd] = ebs;
                }
                else
                {
                    // collect all uses that overlap with eb, and replace with their common parent
                    List <ExpressionWithBindings> notOverlapping = new List <ExpressionWithBindings>();
                    while (true)
                    {
                        foreach (ExpressionWithBindings eb2 in ebs)
                        {
                            ExpressionWithBindings parent = GetCommonParent(eb, eb2);
                            if (CouldOverlap(eb, eb2))
                            {
                                eb = parent;
                            }
                            else
                            {
                                notOverlapping.Add(eb2);
                            }
                        }
                        if (notOverlapping.Count == ebs.Count)
                        {
                            break;                                    // nothing overlaps
                        }
                        // eb must have changed, so try again using the new eb
                        ebs.Clear();
                        ebs.AddRange(notOverlapping);
                        notOverlapping.Clear();
                    }
                    ebs.Add(eb);
                    currentBlock.variablesUsed[ivd] = ebs;
                }
            }
        }
示例#5
0
        /// <summary>
        /// Return the common parent of the two expressions, and indicate if the expressions overlap
        /// </summary>
        /// <param name="eb1"></param>
        /// <param name="eb2"></param>
        /// <returns></returns>
        /// <remarks>
        /// When finding the common parent, we want to preserve any array slicing.  Indexing brackets are not removed if present in both expressions.
        /// Mismatching indices are replaced by AnyIndex.
        /// Examples:
        /// i = loop index inside the gate block
        /// j = loop index outside the gate block, or a method parameter
        /// (a,a[i]) => (a,true)
        /// (a,a[j]) => (a,true)
        /// (a[i],a[0]) => (a[*],true)
        /// (a[i],a[j]) => (a[*],true)
        /// (a[j],a[0]) => (a[*],assumeMatch)
        /// (a[0],a[1]) => (a[*],false)
        /// (a[0][0],a[1][0]) => (a[*][0],false)
        /// (a[0][0],a[1][1]) => (a[*][*],false)
        /// </remarks>
        private static ExpressionWithBindings GetCommonParent(ExpressionWithBindings eb1, ExpressionWithBindings eb2)
        {
            List <IExpression> prefixes1 = Recognizer.GetAllPrefixes(eb1.Expression);
            List <IExpression> prefixes2 = Recognizer.GetAllPrefixes(eb2.Expression);

            if (!prefixes1[0].Equals(prefixes2[0]))
            {
                throw new Exception("Expressions have no overlap: " + eb1 + "," + eb2);
            }
            IExpression parent = prefixes1[0];
            int         count  = System.Math.Min(prefixes1.Count, prefixes2.Count);

            for (int i = 1; i < count; i++)
            {
                IExpression prefix1 = prefixes1[i];
                IExpression prefix2 = prefixes2[i];
                if (prefix1 is IArrayIndexerExpression iaie1)
                {
                    if (prefix2 is IArrayIndexerExpression iaie2)
                    {
                        if (iaie1.Indices.Count != iaie2.Indices.Count)
                        {
                            throw new Exception("Array rank mismatch: " + eb1 + "," + eb2);
                        }
                        IList <IExpression> indices = Builder.ExprCollection();
                        for (int ind = 0; ind < iaie1.Indices.Count; ind++)
                        {
                            IExpression index1 = iaie1.Indices[ind];
                            IExpression index2 = iaie2.Indices[ind];
                            IExpression index  = Unify(index1, eb1.Bindings, index2, eb2.Bindings);
                            indices.Add(index);
                        }
                        parent = Builder.ArrayIndex(parent, indices);
                    }
                    else
                    {
                        break;
                    }
                }
                else
                {
                    throw new Exception("Unhandled expression type: " + prefix1);
                }
            }
            ExpressionWithBindings result = new ExpressionWithBindings();

            result.Expression = parent;
            if (eb1.Bindings.Count > 0 && eb2.Bindings.Count > 0)
            {
                result.Bindings.AddRange(eb1.Bindings);
                result.Bindings.AddRange(eb2.Bindings);
            }
            return(result);

            // Returns an expression equal to expr1 and expr2 under their respective bindings, or null if the expressions are not equal.
            IExpression Unify(
                IExpression expr1,
                IEnumerable <IReadOnlyCollection <ConditionBinding> > bindings1,
                IExpression expr2,
                IEnumerable <IReadOnlyCollection <ConditionBinding> > bindings2)
            {
                if (expr1.Equals(expr2))
                {
                    return(expr1);
                }
                foreach (IReadOnlyCollection <ConditionBinding> binding2 in bindings2)
                {
                    IExpression expr1b = ReplaceExpression(binding2, expr1);
                    if (expr1b.Equals(expr2))
                    {
                        return(expr1);
                    }
                }
                foreach (IReadOnlyCollection <ConditionBinding> binding1 in bindings1)
                {
                    IExpression expr2b = ReplaceExpression(binding1, expr2);
                    if (expr2b.Equals(expr1))
                    {
                        return(expr2);
                    }
                }
                bool lift = false;

                if (lift)
                {
                    IExpression lifted1 = GetLiftedExpression(expr1, bindings1);
                    IExpression lifted2 = GetLiftedExpression(expr2, bindings2);
                    if (lifted1 != null && lifted1.Equals(lifted2))
                    {
                        return(lifted1);
                    }
                }
                return(Builder.StaticMethod(new Func <int>(GateAnalysisTransform.AnyIndex)));

                IExpression GetLiftedExpression(IExpression expr, IEnumerable <IReadOnlyCollection <ConditionBinding> > bindings)
                {
                    IExpression lifted = null;

                    foreach (IReadOnlyCollection <ConditionBinding> binding in bindings)
                    {
                        IExpression lhs = null;
                        foreach (ConditionBinding b in binding)
                        {
                            if (b.rhs.Equals(expr))
                            {
                                lhs = b.lhs;
                            }
                        }
                        if (lifted == null)
                        {
                            lifted = lhs;
                        }
                        else if (lhs == null || !lifted.Equals(lhs))
                        {
                            return(null);
                        }
                    }
                    return(lifted);
                }
            }
        }
示例#6
0
        /// <summary>
        /// Add expr to currentBlock.variablesDefined or currentBlock.variablesUsed
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="isDef"></param>
        /// <param name="conditionContext"></param>
        protected void ProcessUse(IExpression expr, bool isDef, List <ConditionBinding> conditionContext)
        {
            IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(expr);

            if (ivd == null)
            {
                return;
            }
            if (!CodeRecognizer.IsStochastic(context, ivd))
            {
                return;
            }
            if (gateBlockContext.Count == 0)
            {
                return;
            }
            GateBlock currentBlock   = gateBlockContext[gateBlockContext.Count - 1];
            GateBlock gateBlockOfVar = context.InputAttributes.Get <GateBlock>(ivd);

            if (gateBlockOfVar == currentBlock)
            {
                return;                                 // local variable of the gateBlock
            }
            ExpressionWithBindings eb = new ExpressionWithBindings(ReplaceLocalIndices(currentBlock, expr), FilterConditionContext(currentBlock));

            if (isDef)
            {
                if (currentBlock.variablesDefined.TryGetValue(ivd, out ExpressionWithBindings eb2))
                {
                    // all definitions of the same variable must have a common parent
                    currentBlock.variablesDefined[ivd] = GetCommonParent(eb, eb2);
                }
                else
                {
                    currentBlock.variablesDefined[ivd] = eb;
                }
            }
            else
            {
                if (currentBlock.variablesUsed.TryGetValue(ivd, out List <ExpressionWithBindings> ebs))
                {
                    // collect all uses that overlap with eb, and replace with their common parent
                    List <ExpressionWithBindings> notOverlapping = new List <ExpressionWithBindings>();
                    while (true)
                    {
                        foreach (ExpressionWithBindings eb2 in ebs)
                        {
                            if (CouldOverlap(eb, eb2, ignoreBindings: GateTransform.DeterministicEnterExit))
                            {
                                eb = GetCommonParent(eb, eb2);
                            }
                            else
                            {
                                notOverlapping.Add(eb2);
                            }
                        }
                        if (notOverlapping.Count == ebs.Count)
                        {
                            break;                                    // nothing overlaps
                        }
                        // eb must have changed, so try again using the new eb
                        ebs.Clear();
                        ebs.AddRange(notOverlapping);
                        notOverlapping.Clear();
                    }
                    ebs.Add(eb);
                    currentBlock.variablesUsed[ivd] = ebs;
                }
                else
                {
                    currentBlock.variablesUsed[ivd] = new List <ExpressionWithBindings> {
                        eb
                    };
                }
            }

            List <ConditionBinding> FilterConditionContext(GateBlock gateBlock)
            {
                return(conditionContext
                       .Where(binding => !CodeRecognizer.IsStochastic(context, binding.lhs) &&
                              !ContainsLocalVars(gateBlock, binding.lhs) &&
                              !ContainsLocalVars(gateBlock, binding.rhs))
                       .ToList());
            }
        }