protected static void LookAheadAfterConditional(BasicBlockList blocks, ref BasicBlock bb, ref int index) { if (index + 1 >= blocks.Body.Instructions.Count) { throw new OptimizerAssertionException(); } /* * Look ahead at the instruction immediately following the call to the * conditional support method (`IsWeakInstanceOf<T>()` or `IsFeatureSupported()`). * * If it's a branch, then we add it to the current block. Since the conditional * method leaves a `bool` value on the stack, the following instruction can never * be an unconditional branch. * * At the end of this method, the current basic block will always look like this: * * - (optional) simple load * - conditional call * - (optional) conditional branch. * * We will also close out the current block and start a new one after this. */ var next = blocks.Body.Instructions [index + 1]; var type = CecilHelper.GetBranchType(next); switch (type) { case BranchType.None: bb = null; break; case BranchType.False: case BranchType.True: blocks.AddJumpOrigin(bb, next, (Instruction)next.Operand); goto case BranchType.Return; case BranchType.Return: bb.AddInstruction(next); index++; bb = null; break; default: throw DebugHelpers.AssertFailUnexpected(blocks.Method, bb, type); } }
private void CollapseCycle(IReadOnlyCollection <BasicBlock> cycle) { var body_block = new BasicBlock(); body_block.AddInstruction(new Instruction("", "", curID.ToString(), "", "")); children.Add(body_block, new List <BasicBlock>()); var cycle_edges = new List <(BasicBlock, BasicBlock)>(); foreach (var cur_vertex in blocks) { if (!cycle.Contains(cur_vertex)) { var temp = children[cur_vertex].ToList(); foreach (var child in temp) { if (child == cycle.First()) { children[cur_vertex].Remove(child); children[cur_vertex].Add(body_block); } } } else { var temp = children[cur_vertex].ToList(); foreach (var child in temp) { if (child == cycle.First()) { children[body_block].Add(body_block); children[cur_vertex].Remove(child); } else if (!cycle.Contains(child)) { children[body_block].Add(child); children[cur_vertex].Remove(child); } else { cycle_edges.Add((cur_vertex, child)); children[cur_vertex].Remove(child); } } } } blocks.Add(body_block); foreach (var bblock in cycle) { blocks.Remove(bblock); children.Remove(bblock); } var innerRegions = cycle.Select(x => _regions[Block_to_region[x]]).ToList(); var innerEdged = cycle_edges.Select(x => (_regions[Block_to_region[x.Item1]], _regions[Block_to_region[x.Item2]])).ToList(); _regions.Add(new Region(innerRegions, innerEdged)); Block_to_region.Add(body_block, _regions.Count - 1); curID++; //add new node var cycle_block = new BasicBlock(); cycle_block.AddInstruction(new Instruction("", "", curID.ToString(), "", "")); blocks.Add(cycle_block); children.Add(cycle_block, new List <BasicBlock>()); //clear old node children[body_block].Remove(body_block); foreach (var child in children[body_block]) { children[cycle_block].Add(child); } foreach (var child_list in children) { if (child_list.Value.Remove(body_block)) { child_list.Value.Add(cycle_block); } } _regions.Add(new Region(new List <Region>() { _regions[Block_to_region[body_block]] }, new List <(Region, Region)>() { (_regions[Block_to_region[body_block]], _regions[Block_to_region[body_block]]) })); Block_to_region.Add(cycle_block, _regions.Count - 1); children.Remove(body_block); blocks.Remove(body_block); curID++; for (var i = 0; i < cycles.Count; i++) { var c = cycles[i].Count; cycles[i] = cycles[i].Except(cycle).ToList(); if (cycles[i].Count != c) { cycles[i].Add(cycle_block); } } }