Exemple #1
0
        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);
            }
        }
Exemple #2
0
        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);
                }
            }
        }