From 71149caffdf89ccd818bab54f358ea74cbff84e8 Mon Sep 17 00:00:00 2001 From: pentp Date: Fri, 22 Apr 2011 21:26:46 +0300 Subject: [PATCH 1/2] Remove temporary local variables generated by the C# compiler for instance method calls on immutable value type values --- ICSharpCode.Decompiler/ILAst/ILInlining.cs | 33 +++++++++++++--------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/ICSharpCode.Decompiler/ILAst/ILInlining.cs b/ICSharpCode.Decompiler/ILAst/ILInlining.cs index 647f035a7..78c2e54cd 100644 --- a/ICSharpCode.Decompiler/ILAst/ILInlining.cs +++ b/ICSharpCode.Decompiler/ILAst/ILInlining.cs @@ -169,7 +169,10 @@ namespace ICSharpCode.Decompiler.ILAst bool InlineIfPossible(ILVariable v, ILExpression inlinedExpression, ILNode next, bool aggressive) { // ensure the variable is accessed only a single time - if (!(numStloc.GetOrDefault(v) == 1 && numLdloc.GetOrDefault(v) == 1 && numLdloca.GetOrDefault(v) == 0)) + if (numStloc.GetOrDefault(v) != 1) + return false; + int ldloc = numLdloc.GetOrDefault(v); + if (ldloc > 1 || ldloc + numLdloca.GetOrDefault(v) != 1) return false; if (next is ILCondition) @@ -180,7 +183,12 @@ namespace ICSharpCode.Decompiler.ILAst ILExpression parent; int pos; if (FindLoadInNext(next as ILExpression, v, inlinedExpression, out parent, out pos) == true) { - if (!aggressive && !v.IsGenerated && !NonAggressiveInlineInto((ILExpression)next, parent, inlinedExpression)) + if (ldloc == 0) + { + if (!IsGeneratedValueTypeTemporary((ILExpression)next, parent, pos, v)) + return false; + } + else if (!aggressive && !v.IsGenerated && !NonAggressiveInlineInto((ILExpression)next, parent, inlinedExpression)) return false; // Assign the ranges of the ldloc instruction: @@ -192,6 +200,15 @@ namespace ICSharpCode.Decompiler.ILAst } return false; } + + /// + /// Is this a temporary variable generated by the C# compiler for instance method calls on immutable value type values + /// + bool IsGeneratedValueTypeTemporary(ILExpression next, ILExpression parent, int pos, ILVariable v) + { + return pos == 0 && v.Type != null && v.Type.IsValueType && next.Code == ILCode.Stloc + && (parent.Code == ILCode.Call || parent.Code == ILCode.Callvirt) && ((MethodReference)parent.Operand).HasThis; + } bool NonAggressiveInlineInto(ILExpression next, ILExpression parent, ILExpression inlinedExpression) { @@ -214,16 +231,6 @@ namespace ICSharpCode.Decompiler.ILAst } } - /// - /// Gets whether 'expressionBeingMoved' can be inlined into 'expr'. - /// - public bool CanInlineInto(ILExpression expr, ILVariable v, ILExpression expressionBeingMoved) - { - ILExpression parent; - int pos; - return FindLoadInNext(expr, v, expressionBeingMoved, out parent, out pos) == true; - } - /// /// Finds the position to inline to. /// @@ -242,7 +249,7 @@ namespace ICSharpCode.Decompiler.ILAst ILExpression arg = expr.Arguments[i]; - if (arg.Code == ILCode.Ldloc && arg.Operand == v) { + if ((arg.Code == ILCode.Ldloc || arg.Code == ILCode.Ldloca) && arg.Operand == v) { parent = expr; pos = i; return true; From 8c161e51cdd309833485077514cd7b0e7838154a Mon Sep 17 00:00:00 2001 From: pentp Date: Sun, 24 Apr 2011 00:32:47 +0300 Subject: [PATCH 2/2] fix changes --- ICSharpCode.Decompiler/ILAst/ILInlining.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ICSharpCode.Decompiler/ILAst/ILInlining.cs b/ICSharpCode.Decompiler/ILAst/ILInlining.cs index 0b5d642df..ea88c3206 100644 --- a/ICSharpCode.Decompiler/ILAst/ILInlining.cs +++ b/ICSharpCode.Decompiler/ILAst/ILInlining.cs @@ -231,6 +231,16 @@ namespace ICSharpCode.Decompiler.ILAst return false; } } + + /// + /// Gets whether 'expressionBeingMoved' can be inlined into 'expr'. + /// + public bool CanInlineInto(ILExpression expr, ILVariable v, ILExpression expressionBeingMoved) + { + ILExpression parent; + int pos; + return FindLoadInNext(expr, v, expressionBeingMoved, out parent, out pos) == true; + } /// /// Finds the position to inline to.