Browse Source

Simplify shift operators (<< and >>).

Based on patch by Pent Ploompuu.
pull/252/head
Daniel Grunwald 15 years ago
parent
commit
43b4339bea
  1. 4
      ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
  2. 35
      ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs

4
ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs

@ -42,6 +42,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -42,6 +42,7 @@ namespace ICSharpCode.Decompiler.ILAst
SimplifyTernaryOperator,
SimplifyNullCoalescing,
JoinBasicBlocks,
SimplifyShiftOperators,
TransformDecimalCtorToConstant,
SimplifyLdObjAndStObj,
SimplifyCustomShortCircuit,
@ -132,6 +133,9 @@ namespace ICSharpCode.Decompiler.ILAst @@ -132,6 +133,9 @@ 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);

35
ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs

@ -868,5 +868,40 @@ namespace ICSharpCode.Decompiler.ILAst @@ -868,5 +868,40 @@ namespace ICSharpCode.Decompiler.ILAst
return false;
}
#endregion
#region SimplifyShiftOperators
static bool SimplifyShiftOperators(List<ILNode> 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
}
}

Loading…
Cancel
Save