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(); }
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"); }
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); }
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); }