From 69c77d75a5e3e8e41a5a6390710084f62bfe1ec9 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 20 Aug 2017 20:17:20 +0200 Subject: [PATCH] Try to get rid of some more gotos. --- .../IL/ControlFlow/ConditionDetection.cs | 23 +++++++++++++++++-- .../IL/Transforms/ExpressionTransforms.cs | 2 +- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs b/ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs index 3de3e2baf..9d40ac431 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs @@ -127,9 +127,28 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow targetBlock.ILRange = new Interval(offset, offset); } continue; // try to find more nested conditions - } else { - break; } + if (nestedTrueInst is Block nestedTrueBlock + && DetectExitPoints.CompatibleExitInstruction(exitInst, nestedTrueBlock.Instructions.Last()) + && targetBlock.HasFlag(InstructionFlags.EndPointUnreachable)) + { + // "if (...) { if (nestedCondition) { trueInst...; goto exitPoint; } falseInst...; } goto exitPoint;" + // -> "if (...) { if (!nestedCondition) { falseInst...; } trueInst... } goto exitPoint;" + // (only if end-point of 'falseInst...' is unreachable) + context.Step("Invert nested condition to reduce number of gotos", ifInst); + var nestedIfInst = (IfInstruction)targetBlock.Instructions[0]; + nestedIfInst.Condition = new LogicNot(nestedCondition); + nestedTrueBlock.Instructions.RemoveAt(nestedTrueBlock.Instructions.Count - 1); // remove nested goto exitPoint; + // remove falseInsts from outer block + var falseInsts = targetBlock.Instructions.Skip(1).ToArray(); + targetBlock.Instructions.RemoveRange(1, targetBlock.Instructions.Count - 1); + // add trueInsts to outer block + targetBlock.Instructions.AddRange(nestedTrueBlock.Instructions); + // add falseInsts to inner block + nestedTrueBlock.Instructions.ReplaceList(falseInsts); + nestedIfInst.Condition.AcceptVisitor(new ExpressionTransforms { context = context }); + } + break; } trueExitInst = targetBlock.Instructions.LastOrDefault(); diff --git a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs index 3f9e5a702..769ad2fe4 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs @@ -31,7 +31,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// public class ExpressionTransforms : ILVisitor, IBlockTransform { - ILTransformContext context; + internal ILTransformContext context; public void Run(Block block, BlockTransformContext context) {