From 43b4339bead51caa042a2a687040b65f8b7cd1c1 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Tue, 28 Jun 2011 22:07:11 +0200 Subject: [PATCH] Simplify shift operators (<< and >>). Based on patch by Pent Ploompuu. --- .../ILAst/ILAstOptimizer.cs | 6 +++- .../ILAst/PeepholeTransform.cs | 35 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs index 42c2893e5..60da4cbea 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs @@ -42,6 +42,7 @@ namespace ICSharpCode.Decompiler.ILAst SimplifyTernaryOperator, SimplifyNullCoalescing, JoinBasicBlocks, + SimplifyShiftOperators, TransformDecimalCtorToConstant, SimplifyLdObjAndStObj, SimplifyCustomShortCircuit, @@ -131,7 +132,10 @@ namespace ICSharpCode.Decompiler.ILAst if (abortBeforeStep == ILAstOptimizationStep.JoinBasicBlocks) return; modified |= block.RunOptimization(new SimpleControlFlow(context, method).JoinBasicBlocks); - + + if (abortBeforeStep == ILAstOptimizationStep.SimplifyShiftOperators) return; + modified |= block.RunOptimization(SimplifyShiftOperators); + if (abortBeforeStep == ILAstOptimizationStep.TransformDecimalCtorToConstant) return; modified |= block.RunOptimization(TransformDecimalCtorToConstant); modified |= block.RunOptimization(SimplifyLdcI4ConvI8); diff --git a/ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs b/ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs index 88900a73b..b8110651b 100644 --- a/ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs +++ b/ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs @@ -868,5 +868,40 @@ namespace ICSharpCode.Decompiler.ILAst return false; } #endregion + + #region SimplifyShiftOperators + static bool SimplifyShiftOperators(List body, ILExpression expr, int pos) + { + // C# compiles "a << b" to "a << (b & 31)", so we will remove the "& 31" if possible. + bool modified = false; + SimplifyShiftOperators(expr, ref modified); + return modified; + } + + static void SimplifyShiftOperators(ILExpression expr, ref bool modified) + { + for (int i = 0; i < expr.Arguments.Count; i++) + SimplifyShiftOperators(expr.Arguments[i], ref modified); + if (expr.Code != ILCode.Shl && expr.Code != ILCode.Shr && expr.Code != ILCode.Shr_Un) + return; + var a = expr.Arguments[1]; + if (a.Code != ILCode.And || a.Arguments[1].Code != ILCode.Ldc_I4 || expr.InferredType == null) + return; + int mask; + switch (expr.InferredType.MetadataType) { + case MetadataType.Int32: + case MetadataType.UInt32: mask = 31; break; + case MetadataType.Int64: + case MetadataType.UInt64: mask = 63; break; + default: return; + } + if ((int)a.Arguments[1].Operand != mask) return; + var res = a.Arguments[0]; + res.ILRanges.AddRange(a.ILRanges); + res.ILRanges.AddRange(a.Arguments[1].ILRanges); + expr.Arguments[1] = res; + modified = true; + } + #endregion } }