Beispiel #1
0
        public void RewriteConditionals()
        {
            LogDebug(1, $"REWRITE CONDITIONALS: {Method.Name}");

            DumpBlocks();

            var foundConditionals = false;

            foreach (var block in BlockList.Blocks.ToArray())
            {
                if (block.LinkerConditional == null)
                {
                    continue;
                }
                RewriteLinkerConditional(block);
                block.LinkerConditional = null;
                foundConditionals       = true;
            }

            if (!foundConditionals)
            {
                return;
            }

            BlockList.ComputeOffsets();

            DumpBlocks();

            LogDebug(1, $"DONE REWRITING CONDITIONALS: {Method.Name}");

            Context.Options.OptimizerReport.MarkAsContainingConditionals(Method);

            EliminateDeadBlocks();
        }
Beispiel #2
0
        void RewriteLinkerConditional(BasicBlock block)
        {
            LogDebug(1, $"REWRITE LINKER CONDITIONAL: {block.LinkerConditional}");

            DumpBlocks();

            var conditional = block.LinkerConditional;

            block.LinkerConditional = null;

            conditional.RewriteConditional(ref block);

            BlockList.ComputeOffsets();

            DumpBlocks();

            LogDebug(1, $"DONE REWRITING LINKER CONDITIONAL");
        }
Beispiel #3
0
        void EliminateDeadBlocks(bool full = true)
        {
            if (!Context.Options.DeadCodeElimination)
            {
                return;
            }

            LogDebug(1, $"ELIMINATING DEAD BLOCKS");

            bool removed;
            bool first = true;

            do
            {
                if (first)
                {
                    first = false;
                }
                else
                {
                    Scan();
                }

                var flow = new FlowAnalysis(this);
                flow.Analyze();

                removed = false;
                var eliminator = new DeadCodeEliminator(this);
                removed |= eliminator.RemoveDeadBlocks();
                if (full)
                {
                    removed |= eliminator.RemoveDeadJumps();
                    removed |= eliminator.RemoveConstantJumps();
                }
                removed |= eliminator.RemoveUnusedVariables();

                if (removed)
                {
                    BlockList.ComputeOffsets();
                }

                LogDebug(1, $"ELIMINATING DEAD BLOCKS DONE: {removed}");
            } while (full && removed);
        }
Beispiel #4
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);
        }