diff --git a/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs b/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs index f035f521a..558caf95c 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs @@ -409,6 +409,31 @@ namespace ICSharpCode.Decompiler.ILAst } } + // Try to use single temporary variable insted of several if possilbe (especially useful for dup) + foreach(ByteCode byteCode in body) { + if (byteCode.StoreTo != null && byteCode.StoreTo.Count > 1) { + var locVars = byteCode.StoreTo; + // For each of the variables, find the location where it is loaded - there should be preciesly one + var loadedBy = locVars.Select(argVar => body.SelectMany(bc => bc.StackBefore).Where(s => s.LoadFrom == argVar).Single()).ToList(); + // We now know that all the variables have a single load, + // Let's make sure that they have also a single store - us + if (loadedBy.All(slot => slot.PushedBy.Length == 1 && slot.PushedBy[0] == byteCode)) { + // Great - we can reduce everything into single variable + ILVariable tmpVar = new ILVariable() { Name = string.Format("expr_{0:X2}", byteCode.Offset), IsGenerated = true }; + byteCode.StoreTo = new List() { tmpVar }; + foreach(ByteCode bc in body) { + for (int i = 0; i < bc.StackBefore.Count; i++) { + // Is it one of the variable to be merged? + if (locVars.Contains(bc.StackBefore[i].LoadFrom)) { + // Replace with the new temp variable + bc.StackBefore[i] = new StackSlot(bc.StackBefore[i].PushedBy, tmpVar); + } + } + } + } + } + } + // Split and convert the normal local variables ConvertLocalVariables(body);