示例#1
0
        /// <summary>
        /// Replace a copy along a chain of variables (e.g. `b = a; c = b`) with a direct copy (e.g. `b = a; c = a`)
        /// </summary>
        /// <param name="cfg"></param>
        /// <param name="ssa"></param>
        /// <returns></returns>
        public static IControlFlowGraph FoldUnnecessaryCopies(this IControlFlowGraph cfg, ISingleStaticAssignmentTable ssa)
        {
            IControlFlowGraph InnerFold(IControlFlowGraph cfgi)
            {
                // Copy across vertices, modifying them in the process
                return(cfgi.Modify((a, b) =>
                {
                    // generate data flow graph for this block
                    var dfg = (IDataFlowGraph) new DataFlowGraph.DataFlowGraph(a, ssa);

                    // Count how many times each variable in the whole program is read
                    var readsInProgram = cfgi.FindReadCounts().ToDictionary(x => x.Item1, x => x.Item2);

                    // Find variables which are written in this block (we're in SSA, so everything is written exactly once)
                    var writesInBlock = a.FindWrites(ssa).ToHashSet();

                    // Find variables which are written in this block and read (just once) in this block
                    var copiesInBlock = (
                        from x in a.FindReadCounts()
                        where writesInBlock.Contains(x.Item1)
                        where x.Item2 == readsInProgram[x.Item1]
                        where x.Item2 == 1
                        where !x.Item1.IsExternal
                        select x.Item1
                        ).ToArray();

                    // Select a single var to optimise
                    var work = (
                        from op in dfg.Outputs
                        let ass = op.ToStatement() as Assignment
                                  where ass != null
                                  where copiesInBlock.Contains(ass.Left)
                                  where ass.Right is Variable
                                  select(ass, op)
                        ).FirstOrDefault();

                    // Early out if there is nothing to optimise
                    if (work == default)
                    {
                        a.CopyTo(b);
                        return;
                    }

                    // Select the variable to replace and the expression to replace it with
                    var varToReplace = work.ass.Left;
                    var expToSubstitute = work.ass.Right;

                    var modified = new SubstituteVariable(varToReplace, expToSubstitute).Visit(a);
                    foreach (var item in modified.Statements)
                    {
                        b.Add(item);
                    }
                }));
            }

            // Keep applying folding until no more folds are done
            return(cfg.Fixpoint(InnerFold));
        }
示例#2
0
        /// <summary>
        /// Replace expressions which result in a constant with the result
        /// </summary>
        /// <param name="cfg"></param>
        /// <param name="ssa"></param>
        /// <returns></returns>
        [NotNull] public static IControlFlowGraph FoldConstants([NotNull] this IControlFlowGraph cfg, ISingleStaticAssignmentTable ssa)
        {
            // Keep finding and replacing constants until nothing is found
            cfg = cfg.Fixpoint(c => {
                // Find variables which are assigned a value which is not tainted by external reads
                var constants = c.FindConstants(ssa);

                // Replace reads of a constant variable with the expression assigned to that variable
                c = c.VisitBlocks(() => new ReplaceConstantSubexpressions(constants));

                return(c);
            });

            // Replace constant subexpressions with their value
            cfg = cfg.VisitBlocks(() => new ConstantFoldingVisitor(true));

            return(cfg);
        }