diff --git a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs index 0142a11e6..e395b584e 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs @@ -701,6 +701,7 @@ namespace ICSharpCode.Decompiler.ILAst case ILCode.Ldc_I8: case ILCode.Ldc_R4: case ILCode.Ldc_R8: + case ILCode.Ldc_Decimal: return true; default: return false; diff --git a/ICSharpCode.Decompiler/ILAst/ILInlining.cs b/ICSharpCode.Decompiler/ILAst/ILInlining.cs index 6ff065970..7257bf9ec 100644 --- a/ICSharpCode.Decompiler/ILAst/ILInlining.cs +++ b/ICSharpCode.Decompiler/ILAst/ILInlining.cs @@ -436,8 +436,8 @@ namespace ICSharpCode.Decompiler.ILAst } return true; default: - // abort, inlining is not possible - return false; + // instructions with no side-effects are safe (except for Ldloc and Ldloca which are handled separately) + return expr.HasNoSideEffects(); } } diff --git a/ICSharpCode.Decompiler/ILAst/NullableOperators.cs b/ICSharpCode.Decompiler/ILAst/NullableOperators.cs index 79ceca155..4b7b9b00a 100644 --- a/ICSharpCode.Decompiler/ILAst/NullableOperators.cs +++ b/ICSharpCode.Decompiler/ILAst/NullableOperators.cs @@ -236,7 +236,7 @@ namespace ICSharpCode.Decompiler.ILAst bool IsCustomOperator(string s) { - if (s.Length < 11 || !s.StartsWith("op_", StringComparison.Ordinal)) return false; + if (s.Length < 10 || !s.StartsWith("op_", StringComparison.Ordinal)) return false; switch (s) { case "op_Equality": return type == OperatorType.Equality; @@ -257,9 +257,12 @@ namespace ICSharpCode.Decompiler.ILAst case "op_ExclusiveOr": case "op_LeftShift": case "op_RightShift": - case "op_Negation": case "op_UnaryNegation": case "op_UnaryPlus": + case "op_LogicalNot": + case "op_OnesComplement": + case "op_Increment": + case "op_Decrement": return type == OperatorType.Other; default: return false; } @@ -332,8 +335,10 @@ namespace ICSharpCode.Decompiler.ILAst sealed class BooleanPattern : Pattern { + public static readonly Pattern False = new BooleanPattern(false), True = new BooleanPattern(true); + readonly object value; - public BooleanPattern(bool value) + BooleanPattern(bool value) : base(null) { this.value = Convert.ToInt32(value); @@ -420,23 +425,29 @@ namespace ICSharpCode.Decompiler.ILAst /* only one operand nullable */ // & (bool) - new ILPattern(ILCode.TernaryOp, Any, VariableA, new MethodPattern(ILCode.Newobj, ".ctor", new BooleanPattern(false))), + new ILPattern(ILCode.TernaryOp, Any, VariableA, new MethodPattern(ILCode.Newobj, ".ctor", BooleanPattern.False)), new ILPattern(ILCode.And, VariableA, Any), // | (bool) - new ILPattern(ILCode.TernaryOp, Any, new MethodPattern(ILCode.Newobj, ".ctor", new BooleanPattern(true)), VariableA), + new ILPattern(ILCode.TernaryOp, Any, new MethodPattern(ILCode.Newobj, ".ctor", BooleanPattern.True), VariableA), new ILPattern(ILCode.Or, VariableA, Any), // == true VariableAGetValueOrDefault & VariableAHasValue, - new ILPattern(ILCode.Ceq, VariableA, new BooleanPattern(true)), + new ILPattern(ILCode.Ceq, VariableA, BooleanPattern.True), // != true !VariableAGetValueOrDefault | !VariableAHasValue, - new ILPattern(ILCode.Cne, VariableA, new BooleanPattern(true)), + new ILPattern(ILCode.Cne, VariableA, BooleanPattern.True), // == false !VariableAGetValueOrDefault & VariableAHasValue, - new ILPattern(ILCode.Ceq, VariableA, new BooleanPattern(false)), + new ILPattern(ILCode.Ceq, VariableA, BooleanPattern.False), // != false VariableAGetValueOrDefault | !VariableAHasValue, - new ILPattern(ILCode.Cne, VariableA, new BooleanPattern(false)), + new ILPattern(ILCode.Cne, VariableA, BooleanPattern.False), + // ?? true + !VariableAHasValue | VariableAGetValueOrDefault, + new ILPattern(ILCode.NullCoalescing, VariableA, BooleanPattern.True), + // ?? false + VariableAHasValue & VariableAGetValueOrDefault, + new ILPattern(ILCode.NullCoalescing, VariableA, BooleanPattern.False), // null coalescing new ILPattern(ILCode.TernaryOp, VariableAHasValue, VariableAGetValueOrDefault, Any), new ILPattern(ILCode.NullCoalescing, VariableA, Any),