Skip to content

Commit

Permalink
0.6: Shorten branch instructions (smaller method size)
Browse files Browse the repository at this point in the history
  • Loading branch information
oleg-st committed Jun 29, 2021
1 parent 1709c7f commit 6197023
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 9 deletions.
58 changes: 50 additions & 8 deletions src/InlineMethod.Fody/InlineMethodWeaver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,10 @@ public class InlineMethodWeaver
private class LoadArgInfo
{
public int Index { get; }
public int InstructionIndex { get; }

public LoadArgInfo(int index, int instructionIndex)
public LoadArgInfo(int index)
{
Index = index;
InstructionIndex = instructionIndex;
}
}

Expand Down Expand Up @@ -433,6 +431,8 @@ private void FixInstructions()
// TODO: optimize (do once per parent method)
// fix targets, extend instructions
var instruction = _parentMethod.Body.Instructions.FirstOrDefault();
var offset = 0;
var shortBranchInstructions = new List<Instruction>();
while (instruction != null)
{
var nextInstruction = instruction.Next;
Expand All @@ -455,11 +455,54 @@ private void FixInstructions()
}
}

// extend short branch to long to avoid short operand overflow, TODO: choose short / long instruction
OpCodeHelper.ExtendBranchOpCode(instruction);
if (instruction.OpCode.OperandType == OperandType.ShortInlineBrTarget)
{
shortBranchInstructions.Add(instruction);
}

// extend short variable instructions to long if needed
OpCodeHelper.ExtendVariableOpCode(instruction);

instruction.Offset = offset;
offset += instruction.GetSize();

instruction = nextInstruction;
}

// extend short branch instructions if needed
bool wasExtended;
do
{
wasExtended = false;
for (var i = shortBranchInstructions.Count - 1; i >= 0; i--)
{
var shortBranchInstruction = shortBranchInstructions[i];
var target = (Instruction) shortBranchInstruction.Operand;
var diff = target.Offset - shortBranchInstruction.Offset - shortBranchInstruction.GetSize();
if (diff < sbyte.MinValue || diff > sbyte.MaxValue)
{
OpCodeHelper.ExtendBranchOpCode(shortBranchInstruction);
shortBranchInstructions.RemoveAt(i);
wasExtended = true;
}
}

if (wasExtended && shortBranchInstructions.Count > 0)
{
CalcParentMethodOffsets();
}
} while (wasExtended);
}

private void CalcParentMethodOffsets()
{
var instruction = _parentMethod.Body.Instructions.FirstOrDefault();
var offset = 0;
while (instruction != null)
{
var nextInstruction = instruction.Next;
instruction.Offset = offset;
offset += instruction.GetSize();
instruction = nextInstruction;
}
}
Expand Down Expand Up @@ -533,9 +576,8 @@ public void Process()

// inline body
var instructions = _method.Body.Instructions;
for (int instructionIndex = 0; instructionIndex < instructions.Count; instructionIndex++)
foreach (var instruction in instructions)
{
var instruction = instructions[instructionIndex];
var nextInstruction = instruction.Next;
Instruction newInstruction = null;

Expand All @@ -549,7 +591,7 @@ public void Process()
{
if (OpCodeHelper.IsLoadArg(instruction) && arg.IsDeferred)
{
_firstLoadArgs.Add(new LoadArgInfo(parameterDefinition.Sequence, instructionIndex));
_firstLoadArgs.Add(new LoadArgInfo(parameterDefinition.Sequence));
}
else
{
Expand Down
2 changes: 1 addition & 1 deletion src/InlineMethod/InlineMethod.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<PackageOutputPath>$(SolutionDir)/../nugets</PackageOutputPath>
<PackageProjectUrl>https://github.com/oleg-st/InlineMethod.Fody</PackageProjectUrl>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>0.5.1</Version>
<Version>0.6</Version>
</PropertyGroup>

<ItemGroup>
Expand Down

0 comments on commit 6197023

Please sign in to comment.