예제 #1
0
        bool TryMerge(BasicBlock first, BasicBlock second)
        {
            if (first.LinkerConditional != null || second.LinkerConditional != null)
            {
                return(false);
            }
            if (first.BranchType != BranchType.None)
            {
                return(false);
            }
            if (second.JumpOrigins.Count > 0)
            {
                return(false);
            }

            Scanner.LogDebug(1, $"MERGE BLOCK: {first} {second}");
            Scanner.DumpBlocks(1);
            Scanner.Context.Debug();

            CheckRemoveJumpOrigin(second);

            var position = Body.Instructions.IndexOf(second.FirstInstruction);

            foreach (var instruction in second.Instructions)
            {
                Body.Instructions.Insert(position++, instruction);
                first.AddInstruction(instruction);
            }

            CheckAddJumpOrigin(first);

            Scanner.LogDebug(1, $"MERGE BLOCK WITH NEXT #1");
            Scanner.DumpBlocks(1);
            Scanner.Context.Debug();

            DeleteBlock(ref second);

            Scanner.LogDebug(1, $"MERGE BLOCK WITH NEXT #2");
            Scanner.DumpBlocks(1);
            Scanner.Context.Debug();

            return(true);
        }
예제 #2
0
        public void InsertInstructionAt(ref BasicBlock block, int position, Instruction instruction)
        {
            if (position < 0 || position > block.Count)
            {
                throw new ArgumentOutOfRangeException(nameof(position));
            }

            int index;

            if (position == block.Count)
            {
                // Appending to the end.
                index = Body.Instructions.IndexOf(block.LastInstruction);
                Body.Instructions.Insert(index + 1, instruction);
                block.AddInstruction(instruction);
                CheckAddJumpOrigin(block);
                return;
            }

            index = Body.Instructions.IndexOf(block.Instructions [position]);
            Body.Instructions.Insert(index, instruction);

            if (position > 0)
            {
                block.InsertAt(position, instruction);
                if (position == block.Count - 1)
                {
                    CheckAddJumpOrigin(block);
                }
                return;
            }

            /*
             * Our logic assumes that the first instruction in a basic block will never change
             * (because basic blocks are referenced by their first instruction).
             */

            var instructions = block.Instructions.ToList();

            instructions.Insert(0, instruction);
            ReplaceBlock(ref block, instructions);
        }
예제 #3
0
        bool Scan()
        {
            LogDebug(1, $"SCAN: {Method}");

            BasicBlock bb = null;

            if (DebugLevel > 0)
            {
                Context.Debug();
            }

            if (!BlockList.Initialize())
            {
                return(false);
            }

            for (int i = 0; i < Method.Body.Instructions.Count; i++)
            {
                var instruction = Method.Body.Instructions [i];

                if (BlockList.TryGetBlock(instruction, out var newBB))
                {
                    if (bb != null && bb.BranchType != BranchType.None)
                    {
                        throw DebugHelpers.AssertFail(Method, bb, $"Found known basic block with unexpected branch type `{bb.BranchType}`");
                    }
                    LogDebug(2, $"  KNOWN BB: {newBB}");
                    bb = newBB;
                }
                else if (bb == null)
                {
                    bb = BlockList.NewBlock(instruction);
                    LogDebug(2, $"  NEW BB: {bb}");
                }
                else
                {
                    bb.AddInstruction(instruction);
                }

                var type = CecilHelper.GetBranchType(instruction);
                LogDebug(2, $"    {type}: {CecilHelper.Format (instruction)}");

                if (instruction.OpCode.OperandType == OperandType.InlineMethod)
                {
                    if (LinkerConditional.Scan(this, ref bb, ref i, instruction))
                    {
                        FoundConditionals = true;
                    }
                    continue;
                }

                switch (type)
                {
                case BranchType.None:
                    break;

                case BranchType.Conditional:
                case BranchType.False:
                case BranchType.True:
                case BranchType.Jump:
                    BlockList.AddJumpOrigin(bb, instruction, (Instruction)instruction.Operand);
                    bb = null;
                    break;

                case BranchType.Exit:
                case BranchType.Return:
                case BranchType.EndFinally:
                    bb = null;
                    break;

                case BranchType.Switch:
                    foreach (var label in (Instruction [])bb.LastInstruction.Operand)
                    {
                        BlockList.AddJumpOrigin(bb, instruction, label);
                    }
                    bb = null;
                    break;

                default:
                    throw new OptimizerAssertionException();
                }
            }

            BlockList.ComputeOffsets();

            DumpBlocks();

            if (Context.Options.AnalyzeAll || FoundConditionals || DebugLevel > 3)
            {
                EliminateDeadBlocks();
                DumpBlocks();
                return(true);
            }

            return(true);
        }