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); }
/// <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); }
/// <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); }
/// <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); }
/// <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()); }
/// <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; }
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); } }
/// <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); }
/// <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); }
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); }
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); }
/// <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); }
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); } }
/// <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)); } }
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); }
/// <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); }
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); }
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); } } } }
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); }
public override BasicBlockTag GetImmediateDominator(BasicBlockTag block) { return(ImmediateDominators[block]); }
/// <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);
/// <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)); }
internal BasicBlockUpdate(BasicBlockTag tag) { this.Tag = tag; }
internal BasicBlockFlowUpdate(BasicBlockTag tag) : base(tag) { }
internal BasicBlockParametersUpdate(BasicBlockTag tag) : base(tag) { }
internal SetEntryPointUpdate(BasicBlockTag tag) : base(tag) { }
/// <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); }
/// <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)); }
/// <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]); }