Exemplo n.º 1
0
        private static BasicBlockTag IntersectImmediateDominators(
            BasicBlockTag b1, BasicBlockTag b2,
            Dictionary <BasicBlockTag, BasicBlockTag> idoms,
            Dictionary <BasicBlockTag, int> PostorderNums)
        {
            var finger1 = b1;
            var finger2 = b2;

            while (finger1 != finger2)
            {
                while (PostorderNums[finger1] < PostorderNums[finger2])
                {
                    finger1 = idoms[finger1];
                    if (finger1 == null)
                    {
                        return(finger2);
                    }
                }

                while (PostorderNums[finger2] < PostorderNums[finger1])
                {
                    finger2 = idoms[finger2];
                    if (finger2 == null)
                    {
                        return(finger1);
                    }
                }
            }
            return(finger1);
        }
Exemplo n.º 2
0
            /// <summary>
            /// Rewrites an instruction in a basic block.
            /// </summary>
            /// <param name="instruction">The instruction to rewrite.</param>
            /// <param name="block">The block that defines the instruction.</param>
            /// <param name="newInstruction">A rewritten instruction.</param>
            /// <returns>
            /// <c>true</c> if <paramref name="instruction"/> has been rewritten; otherwise <c>false</c>.
            /// </returns>
            private bool RewriteInstruction(
                Instruction instruction,
                BasicBlockTag block,
                out Instruction newInstruction)
            {
                var prototype = instruction.Prototype;

                if (prototype is LoadPrototype)
                {
                    var loadProto = (LoadPrototype)prototype;
                    var pointer   = loadProto.GetPointer(instruction);
                    if (eligibleAllocas.Contains(pointer))
                    {
                        newInstruction = Instruction.CreateCopy(
                            instruction.ResultType,
                            ReadVariable(pointer, block, instruction.ResultType));
                        return(true);
                    }
                }
                else if (prototype is StorePrototype)
                {
                    var storeProto = (StorePrototype)prototype;
                    var pointer    = storeProto.GetPointer(instruction);
                    if (eligibleAllocas.Contains(pointer))
                    {
                        var value = storeProto.GetValue(instruction);
                        WriteVariable(pointer, block, value);
                        newInstruction = Instruction.CreateCopy(instruction.ResultType, value);
                        return(true);
                    }
                }
                newInstruction = instruction;
                return(false);
            }
Exemplo n.º 3
0
        /// <summary>
        /// Tries to find the last common dominator of a sequence of blocks.
        /// </summary>
        /// <param name="blocks">A sequence of blocks.</param>
        /// <param name="dominator">
        /// The last common dominator for <paramref name="blocks"/>.
        /// </param>
        /// <returns>
        /// <c>true</c> if <paramref name="blocks"/> have one or more common dominators; otherwise, <c>false</c>.
        /// </returns>
        public bool TryFindCommonDominator(
            IEnumerable <BasicBlockTag> blocks,
            out BasicBlockTag dominator)
        {
            var doms = blocks.Select(GetDominators).ToArray();

            if (doms.Length == 0)
            {
                dominator = null;
                return(false);
            }

            int minLength = doms.Select(xs => xs.Count).Min();

            for (int i = 0; i < minLength; i++)
            {
                if (doms.Any(xs => xs[i] != doms[0][i]))
                {
                    if (i > 0)
                    {
                        dominator = doms[0][i - 1];
                        return(true);
                    }
                    else
                    {
                        dominator = null;
                        return(false);
                    }
                }
            }
            dominator = doms[0][minLength - 1];
            return(true);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Fuses two fusible basic blocks.
        /// </summary>
        /// <param name="head">The 'head' block.</param>
        /// <param name="tail">The 'tail' block.</param>
        private static void FuseBlocks(BasicBlockBuilder head, BasicBlockTag tail)
        {
            var jump = (JumpFlow)head.Flow;

            // Replace branch parameters by their respective arguments.
            var replacements = new Dictionary <ValueTag, ValueTag>();

            foreach (var pair in jump.Branch.ZipArgumentsWithParameters(head.Graph))
            {
                replacements.Add(pair.Key, pair.Value.ValueOrNull);
            }
            head.Graph.ReplaceUses(replacements);

            // Move instructions around.
            var tailBlock = head.Graph.GetBasicBlock(tail);

            foreach (var instruction in tailBlock.NamedInstructions)
            {
                instruction.MoveTo(head);
            }

            // Update the block's flow.
            head.Flow = tailBlock.Flow;

            // Delete the 'tail' block.
            head.Graph.RemoveBasicBlock(tail);
        }
Exemplo n.º 5
0
        /// <inheritdoc/>
        public override FlowGraph Apply(FlowGraph graph)
        {
            var           builder    = graph.ToBuilder();
            BasicBlockTag entryThunk = null;

            foreach (var block in builder.BasicBlocks)
            {
                var flow = block.Flow;
                foreach (var branch in block.Flow.Branches)
                {
                    if (branch.Target == graph.EntryPointTag)
                    {
                        if (entryThunk == null)
                        {
                            entryThunk = CreateEntryPointThunk(builder);
                            break;
                        }
                    }
                }
                if (entryThunk != null)
                {
                    break;
                }
            }
            if (entryThunk != null)
            {
                builder.EntryPointTag = entryThunk;
            }
            return(builder.ToImmutable());
        }
Exemplo n.º 6
0
 /// <summary>
 /// Creates an exception handler that will catch
 /// only exceptions that inherit from a list of types.
 /// </summary>
 /// <param name="landingPad">
 /// The landing pad to redirect flow to when an exception gets thrown.
 /// </param>
 /// <param name="handledExceptionTypes">
 /// The list of exception types that are handled.
 /// Subtypes of these types are also handled.
 /// </param>
 public CilCatchHandler(
     BasicBlockTag landingPad,
     IReadOnlyList <IType> handledExceptionTypes)
 {
     this.landingPadTag = landingPad;
     this.handledTypes  = handledExceptionTypes;
 }
Exemplo n.º 7
0
            private ValueTag ReadVariableRecursive(
                ValueTag variable,
                BasicBlockTag block,
                IType type)
            {
                if (!IsSealed(block))
                {
                    // The block reading the variable has not been
                    // sealed yet. That's fine. Just add an entry to
                    // the list of incomplete phis.
                    var val = new ValueTag(variable.Name + ".phi");
                    incompletePhis[block][variable] = new BlockParameter(type, val);
                    WriteVariable(variable, block, val);
                    return(val);
                }

                var preds = predecessors.GetPredecessorsOf(block).ToArray();

                if (preds.Length == 1)
                {
                    // There's just one predecessor, so we definitely
                    // won't be needing a block parameter/phi here.
                    return(ReadVariable(variable, preds[0], type));
                }
                else
                {
                    // Create a parameter/phi, then figure out what
                    // its arguments are.
                    var val = new ValueTag(variable.Name + ".phi");
                    WriteVariable(variable, block, val);
                    val = AddPhiOperands(variable, block, val, type);
                    WriteVariable(variable, block, val);
                    return(val);
                }
            }
Exemplo n.º 8
0
 /// <summary>
 /// Tells if a particular block is strictly dominated by another block,
 /// that is, if control cannot flow to the block unless it first flowed
 /// through the dominator block.
 /// </summary>
 /// <param name="block">
 /// A block that might be dominated by <paramref name="dominator"/>.
 /// </param>
 /// <param name="dominator">
 /// A block that might dominate <paramref name="block"/>.
 /// </param>
 /// <returns>
 /// <c>true</c> if <paramref name="block"/> is strictly dominated by
 /// <paramref name="dominator"/>; otherwise, <c>false</c>.
 /// </returns>
 public virtual bool IsStrictlyDominatedBy(BasicBlockTag block, BasicBlockTag dominator)
 {
     do
     {
         block = GetImmediateDominator(block);
     } while (block != null && block != dominator);
     return(block == dominator);
 }
Exemplo n.º 9
0
 /// <summary>
 /// Checks if the given basic block can be sealed.
 /// </summary>
 private bool CanSealBlock(BasicBlockTag block)
 {
     foreach (var tag in predecessors.GetPredecessorsOf(block))
     {
         if (!IsFilled(tag))
         {
             return(false);
         }
     }
     return(true);
 }
Exemplo n.º 10
0
 private static void ReorderArguments(
     IEnumerable <ValueTag> arguments,
     BasicBlockTag block,
     LinkedListNode <ValueTag> insertionPoint,
     InstructionOrdering ordering,
     FlowGraph graph)
 {
     foreach (var arg in arguments.Reverse())
     {
         TryReorder(arg, block, ref insertionPoint, graph);
     }
 }
Exemplo n.º 11
0
 private void ReorderArguments(
     Instruction instruction,
     BasicBlockTag block,
     LinkedListNode <ValueTag> insertionPoint,
     InstructionOrdering ordering,
     FlowGraph graph)
 {
     ReorderArguments(
         GetOrderedArguments(instruction),
         block,
         insertionPoint,
         ordering,
         graph);
 }
Exemplo n.º 12
0
        internal IReadOnlyList <BasicBlockTag> GetDominators(
            BasicBlockTag block)
        {
            var blockDoms = new List <BasicBlockTag>();
            var idom      = block;

            do
            {
                blockDoms.Add(idom);
                idom = GetImmediateDominator(idom);
            } while (idom != null);
            blockDoms.Reverse();
            return(blockDoms);
        }
Exemplo n.º 13
0
            /// <summary>
            /// Seals the given block. A block can be sealed when all of its
            /// predecessors have been filled.
            /// </summary>
            private void SealBlock(BasicBlockTag block)
            {
                if (IsSealed(block))
                {
                    // Don't seal the same block twice.
                    return;
                }

                foreach (var pair in incompletePhis[block])
                {
                    // Resolve phi operands now.
                    AddPhiOperands(pair.Key, block, pair.Value.Tag, pair.Value.Type);
                }

                incompletePhis.Remove(block);
            }
Exemplo n.º 14
0
        private HashSet <BasicBlockTag> GetReachableBlocksImpl(BasicBlockTag source)
        {
            HashSet <BasicBlockTag> reachable;

            if (results.TryGetValue(source, out reachable))
            {
                return(reachable);
            }
            else
            {
                reachable = new HashSet <BasicBlockTag>();
                AddReachableBlocks(source, reachable);
                results[source] = reachable;
                return(reachable);
            }
        }
Exemplo n.º 15
0
            /// <summary>
            /// Gets the value assigned to a variable.
            /// </summary>
            /// <param name="variable">
            /// The variable to read from.
            /// </param>
            /// <param name="block">
            /// The block that reads from the variable.
            /// </param>
            /// <param name="type">
            /// The variable's type.
            /// </param>
            /// <returns>
            /// The value stored in the variable.
            /// </returns>
            private ValueTag ReadVariable(
                ValueTag variable,
                BasicBlockTag block,
                IType type)
            {
                ValueTag value;

                if (currentDef[variable].TryGetValue(block, out value))
                {
                    return(value);
                }
                else
                {
                    return(ReadVariableRecursive(variable, block, type));
                }
            }
Exemplo n.º 16
0
        private static void SortPostorder(
            FlowGraph graph,
            BasicBlockTag tag,
            HashSet <BasicBlockTag> processed,
            List <BasicBlockTag> results)
        {
            if (!processed.Add(tag))
            {
                return;
            }

            foreach (var child in graph.GetBasicBlock(tag).Flow.BranchTargets)
            {
                SortPostorder(graph, child, processed, results);
            }

            results.Add(tag);
        }
Exemplo n.º 17
0
        /// <summary>
        /// Tries to move an instruction from its
        /// current location to just before another instruction.
        /// </summary>
        /// <param name="instruction">
        /// The instruction to try and move.
        /// </param>
        /// <param name="block">
        /// The block that defines the insertion point.
        /// </param>
        /// <param name="insertionPoint">
        /// An instruction to which the instruction should
        /// be moved. It must be defined in the same basic
        /// block as <paramref name="instruction"/>.
        /// </param>
        /// <param name="graph">
        /// The graph that defines both instructions.
        /// </param>
        /// <returns>
        /// <c>true</c> if <paramref name="instruction"/> was
        /// successfully reordered; otherwise, <c>false</c>.
        /// </returns>
        private static bool TryReorder(
            ValueTag instruction,
            BasicBlockTag block,
            ref LinkedListNode <ValueTag> insertionPoint,
            FlowGraph graph)
        {
            if (graph.GetValueParent(instruction).Tag != block ||
                !graph.ContainsInstruction(instruction))
            {
                return(false);
            }

            // Grab the ordering to which we should adhere.
            var ordering = graph.GetAnalysisResult <InstructionOrdering>();

            // Start at the linked list node belonging to the instruction
            // to move and work our way toward the insertion point.
            // Check the must-run-before relation as we traverse the list.
            var instructionNode = GetInstructionNode(instruction, insertionPoint);
            var currentNode     = instructionNode;

            while (currentNode != insertionPoint)
            {
                if (ordering.MustRunBefore(instruction, currentNode.Value))
                {
                    // Aw snap, we encountered a dependency.
                    // Time to abandon ship.
                    return(false);
                }

                currentNode = currentNode.Next;
            }

            // Looks like we can reorder the instruction!
            if (insertionPoint != instructionNode)
            {
                insertionPoint.List.Remove(instructionNode);
                insertionPoint.List.AddBefore(insertionPoint, instructionNode);
            }
            insertionPoint = instructionNode;
            return(true);
        }
Exemplo n.º 18
0
        internal static bool TryGetFusibleTail(
            BasicBlockTag head,
            FlowGraph graph,
            BasicBlockPredecessors predecessors,
            out BasicBlockTag tail)
        {
            var block    = graph.GetBasicBlock(head);
            var jumpFlow = block.Flow as JumpFlow;

            if (jumpFlow != null && graph.EntryPointTag != jumpFlow.Branch.Target)
            {
                var preds = predecessors.GetPredecessorsOf(jumpFlow.Branch.Target).ToArray();
                if (preds.Length == 1 && preds[0] == block.Tag)
                {
                    tail = jumpFlow.Branch.Target;
                    return(true);
                }
            }
            tail = null;
            return(false);
        }
Exemplo n.º 19
0
        private void AddReachableBlocks(
            BasicBlockTag source,
            HashSet <BasicBlockTag> reachable)
        {
            // Try to re-use existing results if possible.
            HashSet <BasicBlockTag> existingReachability;

            if (results.TryGetValue(source, out existingReachability))
            {
                reachable.UnionWith(existingReachability);
            }
            else
            {
                foreach (var branch in Graph.GetBasicBlock(source).Flow.Branches)
                {
                    if (reachable.Add(branch.Target))
                    {
                        AddReachableBlocks(branch.Target, reachable);
                    }
                }
            }
        }
Exemplo n.º 20
0
            private ValueTag AddPhiOperands(
                ValueTag variable,
                BasicBlockTag block,
                ValueTag phi,
                IType type)
            {
                // Define a block parameter.
                var blockBuilder = graphBuilder.GetBasicBlock(block);
                var blockParam   = new BlockParameter(type, phi);

                blockBuilder.AppendParameter(blockParam);

                // Add an argument to all blocks that refer to the block.
                foreach (var pred in predecessors.GetPredecessorsOf(block))
                {
                    var predBlock        = graphBuilder.GetBasicBlock(pred);
                    var modifiedBranches = new List <Branch>();
                    foreach (var branch in predBlock.Flow.Branches)
                    {
                        if (branch.Target == block)
                        {
                            modifiedBranches.Add(
                                branch.AddArgument(
                                    ReadVariable(variable, pred, type)));
                        }
                        else
                        {
                            modifiedBranches.Add(branch);
                        }
                    }
                    predBlock.Flow = predBlock.Flow.WithBranches(modifiedBranches);
                }

                // The original algorithm states that we should
                // remove trivial phis here, but maybe that's best
                // left to a separate copy propagation pass.
                return(phi);
            }
Exemplo n.º 21
0
 public override BasicBlockTag GetImmediateDominator(BasicBlockTag block)
 {
     return(ImmediateDominators[block]);
 }
Exemplo n.º 22
0
 /// <summary>
 /// Gets a block's immediate dominator, that is, the block
 /// that dominates this block such that there is no intermediate
 /// block that is dominated by the immediate dominator and also
 /// dominates the given block.
 /// </summary>
 /// <param name="block">
 /// A block to find an immediate dominator for.
 /// </param>
 /// <returns>
 /// The tag of the immediate dominator block if it exists; otherwise, <c>null</c>.
 /// </returns>
 public abstract BasicBlockTag GetImmediateDominator(BasicBlockTag block);
Exemplo n.º 23
0
 /// <summary>
 /// Tests if one block is a predecessor of another.
 /// </summary>
 /// <param name="potentialPredecessor">
 /// The tag of a block that might be a predecessor of <paramref name="block"/>,
 /// that is, the block to examine for predecessorness here.
 /// </param>
 /// <param name="block">
 /// The tag of a basic block in the flow graph.
 /// </param>
 /// <returns>
 /// <c>true</c> if <paramref name="potentialPredecessor"/> is a predecessor of
 /// <paramref name="block"/>; otherwise; <c>false</c>.
 /// </returns>
 public bool IsPredecessorOf(BasicBlockTag potentialPredecessor, BasicBlockTag block)
 {
     return(predecessorDict[block].Contains(potentialPredecessor));
 }
Exemplo n.º 24
0
 internal BasicBlockUpdate(BasicBlockTag tag)
 {
     this.Tag = tag;
 }
Exemplo n.º 25
0
 internal BasicBlockFlowUpdate(BasicBlockTag tag)
     : base(tag)
 {
 }
Exemplo n.º 26
0
 internal BasicBlockParametersUpdate(BasicBlockTag tag)
     : base(tag)
 {
 }
Exemplo n.º 27
0
 internal SetEntryPointUpdate(BasicBlockTag tag)
     : base(tag)
 {
 }
Exemplo n.º 28
0
        /// <summary>
        /// Computes a mapping from basic block tags to their immediate
        /// dominators. The entry point block mapped to <c>null</c>.
        /// </summary>
        private static IReadOnlyDictionary <BasicBlockTag, BasicBlockTag> GetImmediateDominators(
            FlowGraph graph)
        {
            // Based on "A Simple, Fast Dominance Algorithm" by
            // Keith D. Cooper, Timothy J. Harvey, and Ken Kennedy
            // (http://www.cs.rice.edu/~keith/Embed/dom.pdf)

            var preds = graph.GetAnalysisResult <BasicBlockPredecessors>();
            var idoms = new Dictionary <BasicBlockTag, BasicBlockTag>();

            foreach (var block in graph.BasicBlockTags)
            {
                idoms[block] = null;
            }

            var postorderSort = SortPostorder(graph).ToArray();
            var postorderNums = new Dictionary <BasicBlockTag, int>();

            for (int i = 0; i < postorderSort.Length; i++)
            {
                var item = postorderSort[i];
                postorderNums[item] = i;
            }

            idoms[graph.EntryPointTag] = graph.EntryPointTag;

            bool changed = true;

            while (changed)
            {
                changed = false;
                for (int i = postorderSort.Length - 1; i >= 0; i--)
                {
                    var b = postorderSort[i];
                    if (b == graph.EntryPointTag)
                    {
                        continue;
                    }

                    BasicBlockTag newIdom = null;
                    foreach (var p in preds.GetPredecessorsOf(b))
                    {
                        if (!postorderNums.ContainsKey(p))
                        {
                            continue;
                        }

                        if (newIdom == null)
                        {
                            newIdom = p;
                        }
                        else if (idoms[p] != null)
                        {
                            newIdom = IntersectImmediateDominators(
                                p, newIdom, idoms, postorderNums);
                        }
                    }

                    if (idoms[b] != newIdom)
                    {
                        idoms[b] = newIdom;
                        changed  = true;
                    }
                }
            }

            idoms[graph.EntryPointTag] = null;

            return(idoms);
        }
Exemplo n.º 29
0
 /// <summary>
 /// Tells if a particular block is dominated by another block,
 /// that is, if control cannot flow to the block unless it first flowed
 /// through the dominator block or if the blocks are equal.
 /// </summary>
 /// <param name="block">
 /// A block that might be dominated by <paramref name="dominator"/>.
 /// </param>
 /// <param name="dominator">
 /// A block that might dominate <paramref name="block"/>.
 /// </param>
 /// <returns>
 /// <c>true</c> if <paramref name="block"/> is strictly dominated by
 /// <paramref name="dominator"/> or <paramref name="block"/> equals
 /// <paramref name="dominator"/>; otherwise, <c>false</c>.
 /// </returns>
 public bool IsDominatedBy(BasicBlockTag block, BasicBlockTag dominator)
 {
     return(block == dominator || IsStrictlyDominatedBy(block, dominator));
 }
Exemplo n.º 30
0
 /// <summary>
 /// Gets the set of all predecessors of a basic block with a particular tag.
 /// </summary>
 /// <param name="block">The tag of the basic block to examine.</param>
 /// <returns>A set of predecessors.</returns>
 public IEnumerable <BasicBlockTag> GetPredecessorsOf(BasicBlockTag block)
 {
     return(predecessorDict[block]);
 }