зеркало из https://github.com/mono/ikvm-fork.git
More optimizations.
This commit is contained in:
Родитель
f30b42d0ca
Коммит
b4d6193115
|
@ -151,6 +151,13 @@ namespace IKVM.Internal
|
|||
this.data = data;
|
||||
}
|
||||
|
||||
internal bool Match(OpCodeWrapper other)
|
||||
{
|
||||
return other.pseudo == pseudo
|
||||
&& other.opcode == opcode
|
||||
&& (other.data == data || (data != null && data.Equals(other.data)));
|
||||
}
|
||||
|
||||
internal bool HasLabel
|
||||
{
|
||||
get { return data is CodeEmitterLabel; }
|
||||
|
@ -361,6 +368,11 @@ namespace IKVM.Internal
|
|||
codeEmitter.RealEmitPseudoOpCode(ilOffset, pseudo, data);
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return pseudo.ToString() + " " + data;
|
||||
}
|
||||
}
|
||||
|
||||
sealed class CalliWrapper
|
||||
|
@ -549,13 +561,23 @@ namespace IKVM.Internal
|
|||
{
|
||||
for (int i = 1; i < code.Count; i++)
|
||||
{
|
||||
if (code[i].pseudo == CodeType.Label
|
||||
&& code[i - 1].opcode == OpCodes.Br
|
||||
if (code[i].pseudo == CodeType.Label)
|
||||
{
|
||||
if (code[i - 1].opcode == OpCodes.Br
|
||||
&& code[i - 1].MatchLabel(code[i]))
|
||||
{
|
||||
code.RemoveAt(i - 1);
|
||||
i--;
|
||||
}
|
||||
else if (i >= 2
|
||||
&& code[i - 1].pseudo == CodeType.LineNumber
|
||||
&& code[i - 2].opcode == OpCodes.Br
|
||||
&& code[i - 2].MatchLabel(code[i]))
|
||||
{
|
||||
code.RemoveAt(i - 2);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1053,7 +1075,7 @@ namespace IKVM.Internal
|
|||
}
|
||||
}
|
||||
|
||||
private void BubblePopsAndReleaseTempLocals()
|
||||
private void SortPseudoOpCodes()
|
||||
{
|
||||
for (int i = 0; i < code.Count - 1; i++)
|
||||
{
|
||||
|
@ -1066,7 +1088,7 @@ namespace IKVM.Internal
|
|||
OpCodeWrapper temp = code[i];
|
||||
code[i] = code[i + 1];
|
||||
code[i + 1] = temp;
|
||||
i -= 2;
|
||||
i--;
|
||||
}
|
||||
break;
|
||||
case CodeType.BeginExceptionBlock:
|
||||
|
@ -1075,7 +1097,16 @@ namespace IKVM.Internal
|
|||
OpCodeWrapper temp = code[i];
|
||||
code[i] = code[i + 1];
|
||||
code[i + 1] = temp;
|
||||
i -= 2;
|
||||
i--;
|
||||
}
|
||||
break;
|
||||
case CodeType.Label:
|
||||
if (code[i + 1].pseudo == CodeType.BeginExceptionBlock)
|
||||
{
|
||||
OpCodeWrapper temp = code[i];
|
||||
code[i] = code[i + 1];
|
||||
code[i + 1] = temp;
|
||||
i--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1273,6 +1304,253 @@ namespace IKVM.Internal
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO can't we incorporate this in the above code?
|
||||
// remove exception blocks with empty try blocks
|
||||
// (which can happen if the try block is unreachable)
|
||||
for (int i = 0; i < code.Count; i++)
|
||||
{
|
||||
restart:
|
||||
if (code[i].pseudo == CodeType.BeginExceptionBlock)
|
||||
{
|
||||
for (int k = 0; ; k++)
|
||||
{
|
||||
switch (code[i + k].pseudo)
|
||||
{
|
||||
case CodeType.BeginCatchBlock:
|
||||
case CodeType.BeginFaultBlock:
|
||||
case CodeType.BeginFinallyBlock:
|
||||
int depth = 0;
|
||||
for (int j = i + 1; ; j++)
|
||||
{
|
||||
switch (code[j].pseudo)
|
||||
{
|
||||
case CodeType.BeginExceptionBlock:
|
||||
depth++;
|
||||
break;
|
||||
case CodeType.EndExceptionBlock:
|
||||
if (depth == 0)
|
||||
{
|
||||
code.RemoveRange(i, (j - i) + 1);
|
||||
goto restart;
|
||||
}
|
||||
depth--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
case CodeType.OpCode:
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
}
|
||||
next: ;
|
||||
}
|
||||
}
|
||||
|
||||
private void DeduplicateBranchSourceTargetCode()
|
||||
{
|
||||
for (int i = 0; i < code.Count; i++)
|
||||
{
|
||||
if (code[i].pseudo == CodeType.Label)
|
||||
{
|
||||
code[i].Label.Temp = i;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < code.Count; i++)
|
||||
{
|
||||
if (code[i].opcode == OpCodes.Br && code[i].HasLabel)
|
||||
{
|
||||
int source = i - 1;
|
||||
int target = code[i].Label.Temp - 1;
|
||||
while (source >= 0 && target >= 0)
|
||||
{
|
||||
switch (code[source].pseudo)
|
||||
{
|
||||
case CodeType.LineNumber:
|
||||
case CodeType.OpCode:
|
||||
break;
|
||||
default:
|
||||
goto break_while;
|
||||
}
|
||||
if (!code[source].Match(code[target]))
|
||||
{
|
||||
break;
|
||||
}
|
||||
switch (code[source].opcode.FlowControl)
|
||||
{
|
||||
case FlowControl.Branch:
|
||||
case FlowControl.Cond_Branch:
|
||||
goto break_while;
|
||||
}
|
||||
source--;
|
||||
target--;
|
||||
}
|
||||
break_while: ;
|
||||
source++;
|
||||
target++;
|
||||
if (source != i && target > 0 && source != target - 1)
|
||||
{
|
||||
// TODO for now we only do this optimization if there happens to be an appriopriate label
|
||||
if (code[target - 1].pseudo == CodeType.Label)
|
||||
{
|
||||
code[source] = new OpCodeWrapper(OpCodes.Br, code[target - 1].Label);
|
||||
for (int j = source + 1; j < i; j++)
|
||||
{
|
||||
// This is to make sure that any line numbers here are removed by DCE.
|
||||
// It may be better to fix DCE to remove unreachable line numbers.
|
||||
code[j] = new OpCodeWrapper(OpCodes.Nop, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OptimizeStackTransfer()
|
||||
{
|
||||
for (int i = 0; i < code.Count; i++)
|
||||
{
|
||||
if (code[i].opcode == OpCodes.Ldloc
|
||||
&& code[i + 1].opcode == OpCodes.Stloc
|
||||
&& code[i + 2].pseudo == CodeType.BeginExceptionBlock
|
||||
&& code[i + 3].opcode == OpCodes.Ldloc && code[i + 3].MatchLocal(code[i + 1])
|
||||
&& code[i + 4].pseudo == CodeType.ReleaseTempLocal && code[i + 4].MatchLocal(code[i + 3]))
|
||||
{
|
||||
code[i + 1] = code[i];
|
||||
code[i] = code[i + 2];
|
||||
code.RemoveRange(i + 2, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void MergeExceptionBlocks()
|
||||
{
|
||||
// The first loop will convert all Begin[Exception|Catch|Fault|Finally]Block and EndExceptionBlock
|
||||
// pseudo opcodes into a cyclic linked list (EndExceptionBlock links back to BeginExceptionBlock)
|
||||
// to allow for easy traversal in the next loop.
|
||||
int[] extra = new int[code.Count];
|
||||
Stack<int> stack = new Stack<int>();
|
||||
int currentBeginExceptionBlock = -1;
|
||||
int currentLast = -1;
|
||||
for (int i = 0; i < code.Count; i++)
|
||||
{
|
||||
switch (code[i].pseudo)
|
||||
{
|
||||
case CodeType.BeginExceptionBlock:
|
||||
stack.Push(currentBeginExceptionBlock);
|
||||
currentBeginExceptionBlock = i;
|
||||
currentLast = i;
|
||||
break;
|
||||
case CodeType.EndExceptionBlock:
|
||||
extra[currentLast] = i;
|
||||
extra[i] = currentBeginExceptionBlock;
|
||||
currentBeginExceptionBlock = stack.Pop();
|
||||
currentLast = currentBeginExceptionBlock;
|
||||
if (currentLast != -1)
|
||||
{
|
||||
while (extra[currentLast] != 0)
|
||||
{
|
||||
currentLast = extra[currentLast];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CodeType.BeginCatchBlock:
|
||||
case CodeType.BeginFaultBlock:
|
||||
case CodeType.BeginFinallyBlock:
|
||||
extra[currentLast] = i;
|
||||
currentLast = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Now we look for consecutive exception blocks that have the same fault handler
|
||||
for (int i = 0; i < code.Count - 1; i++)
|
||||
{
|
||||
if (code[i].pseudo == CodeType.EndExceptionBlock
|
||||
&& code[i + 1].pseudo == CodeType.BeginExceptionBlock)
|
||||
{
|
||||
if (IsFaultOnlyBlock(extra, extra[i]) && IsFaultOnlyBlock(extra, i + 1))
|
||||
{
|
||||
int beginFault1 = extra[extra[i]];
|
||||
int beginFault2 = extra[i + 1];
|
||||
int length1 = extra[beginFault1] - beginFault1;
|
||||
int length2 = extra[beginFault2] - beginFault2;
|
||||
if (length1 == length2 && MatchHandlers(beginFault1, beginFault2, length1))
|
||||
{
|
||||
// Check if the labels at the start of the handler are reachable from outside
|
||||
// of the new combined block.
|
||||
for (int j = i + 2; j < beginFault2; j++)
|
||||
{
|
||||
if (code[j].pseudo == CodeType.OpCode)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (code[j].pseudo == CodeType.Label)
|
||||
{
|
||||
if (HasBranchTo(0, extra[i], code[j].Label)
|
||||
|| HasBranchTo(beginFault2 + length2, code.Count, code[j].Label))
|
||||
{
|
||||
goto no_merge;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Merge the two blocks by overwritting the first fault block and
|
||||
// the BeginExceptionBlock of the second block.
|
||||
for (int j = beginFault1; j < i + 2; j++)
|
||||
{
|
||||
code[j] = new OpCodeWrapper(OpCodes.Nop, null);
|
||||
}
|
||||
// Repair the linking structure.
|
||||
extra[extra[i]] = beginFault2;
|
||||
extra[extra[beginFault2]] = extra[i];
|
||||
}
|
||||
}
|
||||
no_merge: ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasBranchTo(int start, int end, CodeEmitterLabel label)
|
||||
{
|
||||
for (int i = start; i < end; i++)
|
||||
{
|
||||
if (code[i].HasLabel)
|
||||
{
|
||||
if (code[i].Label == label)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (code[i].opcode == OpCodes.Switch)
|
||||
{
|
||||
foreach (CodeEmitterLabel swlbl in code[i].Labels)
|
||||
{
|
||||
if (swlbl == label)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool MatchHandlers(int beginFault1, int beginFault2, int length)
|
||||
{
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
if (!code[beginFault1 + i].Match(code[beginFault2 + i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool IsFaultOnlyBlock(int[] extra, int begin)
|
||||
{
|
||||
return code[extra[begin]].pseudo == CodeType.BeginFaultBlock
|
||||
&& code[extra[extra[begin]]].pseudo == CodeType.EndExceptionBlock;
|
||||
}
|
||||
|
||||
internal void DoEmit()
|
||||
|
@ -1280,16 +1558,20 @@ namespace IKVM.Internal
|
|||
OptimizePatterns();
|
||||
|
||||
#if STATIC_COMPILER
|
||||
for (int i = 0; i < 2; i++)
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
RemoveJumpNext();
|
||||
ChaseBranches();
|
||||
RemoveUnusedLabels();
|
||||
BubblePopsAndReleaseTempLocals();
|
||||
SortPseudoOpCodes();
|
||||
AnnihilatePops();
|
||||
AnnihilateStoreReleaseTempLocals();
|
||||
DeduplicateBranchSourceTargetCode();
|
||||
OptimizeStackTransfer();
|
||||
MergeExceptionBlocks();
|
||||
RemoveDeadCode();
|
||||
}
|
||||
//DumpMethod();
|
||||
|
||||
OptimizeEncodings();
|
||||
OptimizeBranchSizes();
|
||||
|
@ -1315,11 +1597,11 @@ namespace IKVM.Internal
|
|||
{
|
||||
if (code[i].pseudo == CodeType.OpCode)
|
||||
{
|
||||
Console.WriteLine(code[i].opcode.Name);
|
||||
Console.WriteLine(" " + code[i].opcode.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine(code[i].pseudo);
|
||||
Console.WriteLine(code[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче