Navigation Menu

Skip to content

Commit

Permalink
Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debu…
Browse files Browse the repository at this point in the history
…gger
  • Loading branch information
eusebiu committed Mar 12, 2011
2 parents 5b7debb + 8922977 commit 2da01ed
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 27 deletions.
73 changes: 66 additions & 7 deletions ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
Expand Up @@ -11,7 +11,7 @@ namespace ICSharpCode.Decompiler.ILAst
{
public enum ILAstOptimizationStep
{
SimpleGotoAndNopRemoval,
RemoveRedundantCode,
ReduceBranchInstructionSet,
InlineVariables,
CopyPropagation,
Expand Down Expand Up @@ -43,8 +43,8 @@ public void Optimize(DecompilerContext context, ILBlock method, ILAstOptimizatio
{
this.typeSystem = context.CurrentMethod.Module.TypeSystem;

if (abortBeforeStep == ILAstOptimizationStep.SimpleGotoAndNopRemoval) return;
SimpleGotoAndNopRemoval(method);
if (abortBeforeStep == ILAstOptimizationStep.RemoveRedundantCode) return;
RemoveRedundantCode(method);

if (abortBeforeStep == ILAstOptimizationStep.ReduceBranchInstructionSet) return;
foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>().ToList()) {
Expand Down Expand Up @@ -109,7 +109,7 @@ public void Optimize(DecompilerContext context, ILBlock method, ILAstOptimizatio
FlattenBasicBlocks(method);

if (abortBeforeStep == ILAstOptimizationStep.GotoRemoval) return;
SimpleGotoAndNopRemoval(method);
RemoveRedundantCode(method);
new GotoRemoval().RemoveGotos(method);

if (abortBeforeStep == ILAstOptimizationStep.DuplicateReturns) return;
Expand Down Expand Up @@ -137,7 +137,11 @@ public void Optimize(DecompilerContext context, ILBlock method, ILAstOptimizatio
GotoRemoval.RemoveRedundantCode(method);
}

void SimpleGotoAndNopRemoval(ILBlock method)
/// <summary>
/// Removes redundatant Br, Nop, Dup, Pop
/// </summary>
/// <param name="method"></param>
void RemoveRedundantCode(ILBlock method)
{
Dictionary<ILLabel, int> labelRefCount = new Dictionary<ILLabel, int>();
foreach (ILLabel target in method.GetSelfAndChildrenRecursive<ILExpression>().SelectMany(e => e.GetBranchTargets())) {
Expand All @@ -149,18 +153,32 @@ void SimpleGotoAndNopRemoval(ILBlock method)
List<ILNode> newBody = new List<ILNode>(body.Count);
for (int i = 0; i < body.Count; i++) {
ILLabel target;
ILExpression popExpr;
if (body[i].Match(ILCode.Br, out target) && i+1 < body.Count && body[i+1] == target) {
// Ignore the branch TODO: ILRanges
// Ignore the branch
if (labelRefCount[target] == 1)
i++; // Ignore the label as well
} else if (body[i].Match(ILCode.Nop)){
// Ignore nop TODO: ILRanges
// Ignore nop
} else if (body[i].Match(ILCode.Pop, out popExpr) && popExpr.HasNoSideEffects()) {
// Ignore pop
} else {
newBody.Add(body[i]);
}
}
block.Body = newBody;
}

// 'dup' removal
foreach (ILExpression expr in method.GetSelfAndChildrenRecursive<ILExpression>()) {
for (int i = 0; i < expr.Arguments.Count; i++) {
ILExpression child;
if (expr.Arguments[i].Match(ILCode.Dup, out child)) {
child.ILRanges.AddRange(expr.Arguments[i].ILRanges);
expr.Arguments[i] = child;
}
}
}
}

/// <summary>
Expand Down Expand Up @@ -1027,6 +1045,47 @@ public static bool CanFallThough(this ILNode node)
return true;
}

/// <summary>
/// The expression has no effect on the program and can be removed
/// if its return value is not needed.
/// </summary>
public static bool HasNoSideEffects(this ILExpression expr)
{
// Remember that if expression can throw an exception, it is a side effect

switch(expr.Code) {
case ILCode.Ldloc:
case ILCode.Ldloca:
case ILCode.Ldarg:
case ILCode.Ldstr:
case ILCode.Ldnull:
case ILCode.Ldc_I4:
case ILCode.Ldc_I8:
case ILCode.Ldc_R4:
case ILCode.Ldc_R8:
return true;
default:
return false;
}
}

/// <summary>
/// Can the expression be used as a statement in C#?
/// </summary>
public static bool CanBeExpressionStatement(this ILExpression expr)
{
switch(expr.Code) {
case ILCode.Call:
case ILCode.Calli:
case ILCode.Callvirt:
case ILCode.Newobj:
case ILCode.Newarr:
return true;
default:
return false;
}
}

public static V GetOrDefault<K,V>(this Dictionary<K, V> dict, K key)
{
V ret;
Expand Down
41 changes: 21 additions & 20 deletions ICSharpCode.Decompiler/ILAst/ILInlining.cs
Expand Up @@ -72,7 +72,6 @@ public void InlineAllInBlock(ILBlock block)
{
List<ILNode> body = block.Body;
for(int i = 0; i < body.Count - 1;) {
ILExpression nextExpr = body[i + 1] as ILExpression;
ILVariable locVar;
ILExpression expr;
if (body[i].Match(ILCode.Stloc, out locVar, out expr) && InlineOneIfPossible(block, i, aggressive: false)) {
Expand Down Expand Up @@ -127,14 +126,27 @@ public bool InlineOneIfPossible(ILBlock block, int pos, bool aggressive)
{
ILVariable v;
ILExpression inlinedExpression;
if (block.Body[pos].Match(ILCode.Stloc, out v, out inlinedExpression)
&& InlineIfPossible(v, inlinedExpression, block.Body.ElementAtOrDefault(pos+1), aggressive))
{
// Assign the ranges of the stloc instruction:
inlinedExpression.ILRanges.AddRange(((ILExpression)block.Body[pos]).ILRanges);
// Remove the stloc instruction:
block.Body.RemoveAt(pos);
return true;
if (block.Body[pos].Match(ILCode.Stloc, out v, out inlinedExpression)) {
if (InlineIfPossible(v, inlinedExpression, block.Body.ElementAtOrDefault(pos+1), aggressive)) {
// Assign the ranges of the stloc instruction:
inlinedExpression.ILRanges.AddRange(((ILExpression)block.Body[pos]).ILRanges);
// Remove the stloc instruction:
block.Body.RemoveAt(pos);
return true;
} else if (numLdloc.GetOrDefault(v) == 0 && numLdloca.GetOrDefault(v) == 0) {
// The variable is never loaded
if (inlinedExpression.HasNoSideEffects()) {
// Remove completely
block.Body.RemoveAt(pos);
return true;
} else if (inlinedExpression.CanBeExpressionStatement() && v.IsGenerated) {
// Assign the ranges of the stloc instruction:
inlinedExpression.ILRanges.AddRange(((ILExpression)block.Body[pos]).ILRanges);
// Remove the stloc, but keep the inner expression
block.Body[pos] = inlinedExpression;
return true;
}
}
}
return false;
}
Expand Down Expand Up @@ -282,17 +294,6 @@ bool IsSafeForInlineOver(ILExpression expr, ILExpression expressionBeingMoved)
/// </summary>
public void CopyPropagation()
{
// Perform 'dup' removal prior to copy propagation:
foreach (ILExpression expr in method.GetSelfAndChildrenRecursive<ILExpression>()) {
for (int i = 0; i < expr.Arguments.Count; i++) {
if (expr.Arguments[i].Code == ILCode.Dup) {
ILExpression child = expr.Arguments[i].Arguments[0];
child.ILRanges.AddRange(expr.Arguments[i].ILRanges);
expr.Arguments[i] = child;
}
}
}

foreach (ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) {
for (int i = 0; i < block.Body.Count; i++) {
ILVariable v;
Expand Down

0 comments on commit 2da01ed

Please sign in to comment.