/// <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); }