Browse Source

Try to inline stack variables that are only used in ldobj/stobj and hold a ldelema reference

pull/734/head
Siegfried Pammer 9 years ago
parent
commit
40819d2bfb
  1. 30
      ICSharpCode.Decompiler/IL/Transforms/TransformInlineAssignment.cs

30
ICSharpCode.Decompiler/IL/Transforms/TransformInlineAssignment.cs

@ -36,6 +36,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -36,6 +36,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms
this.context = context;
foreach (var block in function.Descendants.OfType<Block>()) {
for (int i = block.Instructions.Count - 1; i >= 0; i--) {
if (InlineLdElemaUsages(block, i)) {
block.Instructions.RemoveAt(i);
continue;
}
TransformInlineAssignmentStObj(block, i);
}
}
@ -107,5 +111,31 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -107,5 +111,31 @@ namespace ICSharpCode.Decompiler.IL.Transforms
block.Instructions.RemoveAt(i);
nextInst.ReplaceWith(new StLoc(stackVar, new StLoc(var, value)));
}
/// <code>
/// stloc s(ldelema)
/// usages of ldobj(ldloc s) or stobj(ldloc s, ...) in next instruction
/// -->
/// use ldelema instead of ldloc s
/// </code>
static bool InlineLdElemaUsages(Block block, int i)
{
var inst = block.Instructions[i] as StLoc;
if (inst == null || inst.Variable.Kind != VariableKind.StackSlot || !(inst.Value is LdElema))
return false;
var valueToCopy = inst.Value;
var nextInstruction = inst.Parent.Children.ElementAtOrDefault(inst.ChildIndex + 1);
if (nextInstruction == null)
return false;
var affectedUsages = nextInstruction.Descendants
.OfType<IInstructionWithVariableOperand>().Where(ins => ins.Variable == inst.Variable)
.Cast<ILInstruction>().ToArray();
if (affectedUsages.Any(ins => !(ins.Parent is StObj || ins.Parent is LdObj)))
return false;
foreach (var usage in affectedUsages) {
usage.ReplaceWith(valueToCopy.Clone());
}
return true;
}
}
}

Loading…
Cancel
Save