Beispiel #1
0
        /// <summary>
        /// Tries to replace a return flow with a branch to
        /// the entry point.
        /// </summary>
        /// <param name="block">
        /// A block that ends in return flow.
        /// </param>
        /// <param name="returnValue">
        /// The value returned by the return flow.
        /// </param>
        /// <param name="graph">
        /// The graph that defines the block.
        /// </param>
        /// <param name="method">
        /// The method that is being optimized.
        /// </param>
        /// <param name="ordering">
        /// An instruction ordering model.
        /// </param>
        /// <returns>
        /// <c>true</c> if the return has been replaced with a branch
        /// to the entry point by this method; otherwise, <c>false</c>.
        /// </returns>
        private bool TryReplaceWithBranchToEntry(
            BasicBlockBuilder block,
            Instruction returnValue,
            FlowGraphBuilder graph,
            IMethod method,
            InstructionOrdering ordering)
        {
            var      insnsToEliminate = new HashSet <ValueTag>();
            ValueTag callTag          = null;

            // Jump through copy instructions.
            while (returnValue.Prototype is CopyPrototype)
            {
                callTag = ((CopyPrototype)returnValue.Prototype).GetCopiedValue(returnValue);
                insnsToEliminate.Add(callTag);
                if (!graph.ContainsInstruction(callTag))
                {
                    // We encountered a basic block parameter, which we can't really
                    // peek through. Abort.
                    return(false);
                }
                returnValue = graph.GetInstruction(callTag).Instruction;
            }

            if ((callTag == null || graph.GetValueParent(callTag).Tag == block.Tag) &&
                IsSelfCallPrototype(returnValue.Prototype, method))
            {
                // Now all we have to do is make sure that there is no instruction
                // that must run after the call.
                if (callTag != null)
                {
                    var selection = graph.GetInstruction(callTag).NextInstructionOrNull;
                    while (selection != null)
                    {
                        if (ordering.MustRunBefore(callTag, selection))
                        {
                            // Aw, snap. Looks like we can't reorder the call, which
                            // means no tail call elimination. Abort.
                            return(false);
                        }
                        selection = selection.NextInstructionOrNull;
                    }
                }

                // Remove some instructions.
                foreach (var tag in insnsToEliminate)
                {
                    graph.RemoveInstruction(tag);
                }

                // Turn the return flow into a jump.
                block.Flow = new JumpFlow(graph.EntryPointTag, returnValue.Arguments);
                return(true);
            }
            else
            {
                return(false);
            }
        }
 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);
     }
 }
 private void ReorderArguments(
     Instruction instruction,
     BasicBlockTag block,
     LinkedListNode <ValueTag> insertionPoint,
     InstructionOrdering ordering,
     FlowGraph graph)
 {
     ReorderArguments(
         GetOrderedArguments(instruction),
         block,
         insertionPoint,
         ordering,
         graph);
 }