Browse Source

Simple goto and nop removal

pull/70/head
David Srbecký 15 years ago
parent
commit
efd04b31d8
  1. 36
      ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs

36
ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs

@ -11,6 +11,7 @@ namespace ICSharpCode.Decompiler.ILAst
{ {
public enum ILAstOptimizationStep public enum ILAstOptimizationStep
{ {
SimpleGotoAndNopRemoval,
InlineVariables, InlineVariables,
ReduceBranchInstructionSet, ReduceBranchInstructionSet,
YieldReturn, YieldReturn,
@ -35,7 +36,11 @@ namespace ICSharpCode.Decompiler.ILAst
public void Optimize(DecompilerContext context, ILBlock method, ILAstOptimizationStep abortBeforeStep = ILAstOptimizationStep.None) public void Optimize(DecompilerContext context, ILBlock method, ILAstOptimizationStep abortBeforeStep = ILAstOptimizationStep.None)
{ {
if (abortBeforeStep == ILAstOptimizationStep.SimpleGotoAndNopRemoval) return;
SimpleGotoAndNopRemoval(method);
if (abortBeforeStep == ILAstOptimizationStep.InlineVariables) return; if (abortBeforeStep == ILAstOptimizationStep.InlineVariables) return;
// Works better are simple goto removal because of the following pattern: stloc X; br Next; Next:; ldloc X
InlineVariables(method); InlineVariables(method);
if (abortBeforeStep == ILAstOptimizationStep.ReduceBranchInstructionSet) return; if (abortBeforeStep == ILAstOptimizationStep.ReduceBranchInstructionSet) return;
@ -82,6 +87,7 @@ namespace ICSharpCode.Decompiler.ILAst
FlattenBasicBlocks(method); FlattenBasicBlocks(method);
if (abortBeforeStep == ILAstOptimizationStep.GotoRemoval) return; if (abortBeforeStep == ILAstOptimizationStep.GotoRemoval) return;
SimpleGotoAndNopRemoval(method);
new GotoRemoval().RemoveGotos(method); new GotoRemoval().RemoveGotos(method);
if (abortBeforeStep == ILAstOptimizationStep.DuplicateReturns) return; if (abortBeforeStep == ILAstOptimizationStep.DuplicateReturns) return;
@ -99,6 +105,32 @@ namespace ICSharpCode.Decompiler.ILAst
GotoRemoval.RemoveRedundantCode(method); GotoRemoval.RemoveRedundantCode(method);
} }
void SimpleGotoAndNopRemoval(ILBlock method)
{
Dictionary<ILLabel, int> labelRefCount = new Dictionary<ILLabel, int>();
foreach (ILLabel target in method.GetSelfAndChildrenRecursive<ILExpression>().SelectMany(e => e.GetBranchTargets())) {
labelRefCount[target] = labelRefCount.GetOrDefault(target) + 1;
}
foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>().ToList()) {
List<ILNode> body = block.Body;
List<ILNode> newBody = new List<ILNode>(body.Count);
for (int i = 0; i < body.Count; i++) {
ILLabel target;
if (body[i].Match(ILCode.Br, out target) && i+1 < body.Count && body[i+1] == target) {
// Ignore the branch TODO: ILRanges
if (labelRefCount[target] == 1)
i++; // Ignore the label as well
} else if (body[i].Match(ILCode.Nop)){
// Ignore nop TODO: ILRanges
} else {
newBody.Add(body[i]);
}
}
block.Body = newBody;
}
}
void InlineVariables(ILBlock method) void InlineVariables(ILBlock method)
{ {
// Analyse the whole method // Analyse the whole method
@ -217,10 +249,6 @@ namespace ICSharpCode.Decompiler.ILAst
/// </summary> /// </summary>
void SplitToBasicBlocks(ILBlock block) void SplitToBasicBlocks(ILBlock block)
{ {
// Remve no-ops
// TODO: Assign the no-op range to someting
block.Body = block.Body.Where(n => !(n is ILExpression && ((ILExpression)n).Code == ILCode.Nop)).ToList();
List<ILNode> basicBlocks = new List<ILNode>(); List<ILNode> basicBlocks = new List<ILNode>();
ILBasicBlock basicBlock = new ILBasicBlock() { ILBasicBlock basicBlock = new ILBasicBlock() {

Loading…
Cancel
Save