Moved ldiv/idiv optimization to new model.

This commit is contained in:
jfrijters 2010-10-01 04:41:06 +00:00
Родитель 00136506eb
Коммит 2bc060e265
1 изменённых файлов: 89 добавлений и 87 удалений

Просмотреть файл

@ -176,6 +176,21 @@ namespace IKVM.Internal
this.data = data;
}
internal CodeEmitterLabel Label
{
get { return (CodeEmitterLabel)data; }
}
internal int ValueInt32
{
get { return (int)data; }
}
internal long ValueInt64
{
get { return (long)data; }
}
internal int Size
{
get
@ -748,6 +763,55 @@ namespace IKVM.Internal
{
PatchCompare(i, OpCodes.Ble, OpCodes.Blt, OpCodes.Bge, OpCodes.Bgt);
}
else if (i < code.Count - 10
&& code[i].opcode == OpCodes.Ldc_I4
&& code[i + 1].opcode == OpCodes.Dup
&& code[i + 2].opcode == OpCodes.Ldc_I4_M1
&& code[i + 3].opcode == OpCodes.Bne_Un_S
&& code[i + 4].opcode == OpCodes.Pop
&& code[i + 5].opcode == OpCodes.Neg
&& code[i + 6].opcode == OpCodes.Br_S
&& code[i + 7].type == CodeType.Label && code[i + 7].Label == code[i + 3].Label
&& code[i + 8].opcode == OpCodes.Div
&& code[i + 9].type == CodeType.Label && code[i + 9].Label == code[i + 6].Label)
{
int divisor = code[i].ValueInt32;
if (divisor == -1)
{
code[i] = code[i + 5];
code.RemoveRange(i + 1, 9);
}
else
{
code[i + 1] = code[i + 8];
code.RemoveRange(i + 2, 8);
}
}
else if (i < code.Count - 11
&& code[i].opcode == OpCodes.Ldc_I8
&& code[i + 1].opcode == OpCodes.Dup
&& code[i + 2].opcode == OpCodes.Ldc_I4_M1
&& code[i + 3].opcode == OpCodes.Conv_I8
&& code[i + 4].opcode == OpCodes.Bne_Un_S
&& code[i + 5].opcode == OpCodes.Pop
&& code[i + 6].opcode == OpCodes.Neg
&& code[i + 7].opcode == OpCodes.Br_S
&& code[i + 8].type == CodeType.Label && code[i + 8].Label == code[i + 4].Label
&& code[i + 9].opcode == OpCodes.Div
&& code[i + 10].type == CodeType.Label && code[i + 10].Label == code[i + 7].Label)
{
long divisor = code[i].ValueInt64;
if (divisor == -1)
{
code[i] = code[i + 6];
code.RemoveRange(i + 1, 10);
}
else
{
code[i + 1] = code[i + 9];
code.RemoveRange(i + 2, 9);
}
}
}
}
@ -1380,12 +1444,12 @@ namespace IKVM.Internal
internal void LazyEmitLdc_I4(int i)
{
PushStack(new ConstIntExpr(i));
Emit(OpCodes.Ldc_I4, i);
}
internal void LazyEmitLdc_I8(long l)
{
PushStack(new ConstLongExpr(l));
Emit(OpCodes.Ldc_I8, l);
}
internal void LazyEmitLdstr(string str)
@ -1398,33 +1462,17 @@ namespace IKVM.Internal
// we need to special case dividing by -1, because the CLR div instruction
// throws an OverflowException when dividing Int32.MinValue by -1, and
// Java just silently overflows
ConstIntExpr v = PeekStack() as ConstIntExpr;
if(v != null)
{
if(v.i == -1)
{
PopStack();
Emit(OpCodes.Neg);
}
else
{
Emit(OpCodes.Div);
}
}
else
{
Emit(OpCodes.Dup);
Emit(OpCodes.Ldc_I4_M1);
CodeEmitterLabel label = DefineLabel();
Emit(OpCodes.Bne_Un_S, label);
Emit(OpCodes.Pop);
Emit(OpCodes.Neg);
CodeEmitterLabel label2 = DefineLabel();
Emit(OpCodes.Br_S, label2);
MarkLabel(label);
Emit(OpCodes.Div);
MarkLabel(label2);
}
Emit(OpCodes.Dup);
Emit(OpCodes.Ldc_I4_M1);
CodeEmitterLabel label = DefineLabel();
Emit(OpCodes.Bne_Un_S, label);
Emit(OpCodes.Pop);
Emit(OpCodes.Neg);
CodeEmitterLabel label2 = DefineLabel();
Emit(OpCodes.Br_S, label2);
MarkLabel(label);
Emit(OpCodes.Div);
MarkLabel(label2);
}
internal void LazyEmit_ldiv()
@ -1432,34 +1480,18 @@ namespace IKVM.Internal
// we need to special case dividing by -1, because the CLR div instruction
// throws an OverflowException when dividing Int32.MinValue by -1, and
// Java just silently overflows
ConstLongExpr v = PeekStack() as ConstLongExpr;
if(v != null)
{
if(v.l == -1)
{
PopStack();
Emit(OpCodes.Neg);
}
else
{
Emit(OpCodes.Div);
}
}
else
{
Emit(OpCodes.Dup);
Emit(OpCodes.Ldc_I4_M1);
Emit(OpCodes.Conv_I8);
CodeEmitterLabel label = DefineLabel();
Emit(OpCodes.Bne_Un_S, label);
Emit(OpCodes.Pop);
Emit(OpCodes.Neg);
CodeEmitterLabel label2 = DefineLabel();
Emit(OpCodes.Br_S, label2);
MarkLabel(label);
Emit(OpCodes.Div);
MarkLabel(label2);
}
Emit(OpCodes.Dup);
Emit(OpCodes.Ldc_I4_M1);
Emit(OpCodes.Conv_I8);
CodeEmitterLabel label = DefineLabel();
Emit(OpCodes.Bne_Un_S, label);
Emit(OpCodes.Pop);
Emit(OpCodes.Neg);
CodeEmitterLabel label2 = DefineLabel();
Emit(OpCodes.Br_S, label2);
MarkLabel(label);
Emit(OpCodes.Div);
MarkLabel(label2);
}
internal void LazyEmit_instanceof(Type type)
@ -1706,35 +1738,5 @@ namespace IKVM.Internal
ilgen.Emit(OpCodes.Ldobj, Type);
}
}
sealed class ConstIntExpr : Expr
{
internal readonly int i;
internal ConstIntExpr(int i)
{
this.i = i;
}
internal override void Emit(CodeEmitter ilgen)
{
ilgen.Emit(OpCodes.Ldc_I4, i);
}
}
sealed class ConstLongExpr : Expr
{
internal readonly long l;
internal ConstLongExpr(long l)
{
this.l = l;
}
internal override void Emit(CodeEmitter ilgen)
{
ilgen.Emit(OpCodes.Ldc_I8, l);
}
}
}
}