private void OptimizePatterns()
{
UpdateLabelRefCounts();
for (int i = 1; i < code.Count; i++)
{
if (code[i].opcode == OpCodes.Isinst
&& code[i + 1].opcode == OpCodes.Ldnull
&& code[i + 2].opcode == OpCodes.Cgt_Un
&& (code[i + 3].opcode == OpCodes.Brfalse || code[i + 3].opcode == OpCodes.Brtrue))
{
code.RemoveRange(i + 1, 2);
}
else if (code[i].opcode == OpCodes.Ldelem_I1
&& code[i + 1].opcode == OpCodes.Ldc_I4 && code[i + 1].ValueInt32 == 255
&& code[i + 2].opcode == OpCodes.And)
{
code[i] = new OpCodeWrapper(OpCodes.Ldelem_U1, null);
code.RemoveRange(i + 1, 2);
}
else if (code[i].opcode == OpCodes.Ldelem_I1
&& code[i + 1].opcode == OpCodes.Conv_I8
&& code[i + 2].opcode == OpCodes.Ldc_I8 && code[i + 2].ValueInt64 == 255
&& code[i + 3].opcode == OpCodes.And)
{
code[i] = new OpCodeWrapper(OpCodes.Ldelem_U1, null);
code.RemoveRange(i + 2, 2);
}
else if (code[i].opcode == OpCodes.Ldc_I4
&& code[i + 1].opcode == OpCodes.Ldc_I4
&& code[i + 2].opcode == OpCodes.And)
{
code[i] = new OpCodeWrapper(OpCodes.Ldc_I4, code[i].ValueInt32 & code[i + 1].ValueInt32);
code.RemoveRange(i + 1, 2);
}
else if (MatchCompare(i, OpCodes.Cgt, OpCodes.Clt_Un, Types.Double) // dcmpl
|| MatchCompare(i, OpCodes.Cgt, OpCodes.Clt_Un, Types.Single)) // fcmpl
{
PatchCompare(i, OpCodes.Ble_Un, OpCodes.Blt_Un, OpCodes.Bge, OpCodes.Bgt);
}
else if (MatchCompare(i, OpCodes.Cgt_Un, OpCodes.Clt, Types.Double) // dcmpg
|| MatchCompare(i, OpCodes.Cgt_Un, OpCodes.Clt, Types.Single)) // fcmpg
{
PatchCompare(i, OpCodes.Ble, OpCodes.Blt, OpCodes.Bge_Un, OpCodes.Bgt_Un);
}
else if (MatchCompare(i, OpCodes.Cgt, OpCodes.Clt, Types.Int64)) // lcmp
{
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].pseudo == CodeType.Label && code[i + 7].MatchLabel(code[i + 3]) && code[i + 7].Label.Temp == 1
&& code[i + 8].opcode == OpCodes.Div
&& code[i + 9].pseudo == CodeType.Label && code[i + 9].Label == code[i + 6].Label && code[i + 9].Label.Temp == 1)
{
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].pseudo == CodeType.Label && code[i + 8].MatchLabel(code[i + 4]) && code[i + 8].Label.Temp == 1
&& code[i + 9].opcode == OpCodes.Div
&& code[i + 10].pseudo == CodeType.Label && code[i + 10].MatchLabel(code[i + 7]) && code[i + 10].Label.Temp == 1)
{
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);
}
}
else if (code[i].opcode == OpCodes.Box
&& code[i + 1].opcode == OpCodes.Unbox && code[i + 1].Type == code[i].Type)
{
CodeEmitterLocal local = new CodeEmitterLocal(code[i].Type);
code[i] = new OpCodeWrapper(OpCodes.Stloc, local);
code[i + 1] = new OpCodeWrapper(OpCodes.Ldloca, local);
}
else if (i < code.Count - 13
&& code[i + 0].opcode == OpCodes.Box
&& code[i + 1].opcode == OpCodes.Dup
&& code[i + 2].opcode == OpCodes.Brtrue_S
&& code[i + 3].opcode == OpCodes.Pop
&& code[i + 4].opcode == OpCodes.Ldloca && code[i + 4].Local.LocalType == code[i + 0].Type
&& code[i + 5].opcode == OpCodes.Initobj && code[i + 5].Type == code[i + 0].Type
&& code[i + 6].opcode == OpCodes.Ldloc && code[i + 6].Local == code[i + 4].Local
&& code[i + 7].pseudo == CodeType.ReleaseTempLocal && code[i + 7].Local == code[i + 6].Local
&& code[i + 8].opcode == OpCodes.Br_S
&& code[i + 9].pseudo == CodeType.Label && code[i + 9].MatchLabel(code[i + 2]) && code[i + 9].Label.Temp == 1
&& code[i + 10].opcode == OpCodes.Unbox && code[i + 10].Type == code[i + 0].Type
&& code[i + 11].opcode == OpCodes.Ldobj && code[i + 11].Type == code[i + 0].Type
&& code[i + 12].pseudo == CodeType.Label && code[i + 12].MatchLabel(code[i + 8]) && code[i + 12].Label.Temp == 1)
{
code.RemoveRange(i, 13);
}
// NOTE intentionally not an else, because we want to optimize the code generated by the earlier compare optimization
if (i < code.Count - 6
&& code[i].opcode.FlowControl == FlowControl.Cond_Branch
&& code[i + 1].opcode == OpCodes.Ldc_I4 && code[i + 1].ValueInt32 == 1
&& code[i + 2].opcode == OpCodes.Br
&& code[i + 3].pseudo == CodeType.Label && code[i + 3].MatchLabel(code[i]) && code[i + 3].Label.Temp == 1
&& code[i + 4].opcode == OpCodes.Ldc_I4 && code[i + 4].ValueInt32 == 0
&& code[i + 5].pseudo == CodeType.Label && code[i + 5].MatchLabel(code[i + 2]) && code[i + 5].Label.Temp == 1)
{
if (code[i].opcode == OpCodes.Bne_Un)
{
code[i] = new OpCodeWrapper(OpCodes.Ceq, null);
code.RemoveRange(i + 1, 5);
}
else if (code[i].opcode == OpCodes.Beq)
{
code[i + 0] = new OpCodeWrapper(OpCodes.Ceq, null);
code[i + 1] = new OpCodeWrapper(OpCodes.Ldc_I4, 0);
code[i + 2] = new OpCodeWrapper(OpCodes.Ceq, null);
code.RemoveRange(i + 3, 3);
}
else if (code[i].opcode == OpCodes.Ble || code[i].opcode == OpCodes.Ble_Un)
{
code[i] = new OpCodeWrapper(OpCodes.Cgt, null);
code.RemoveRange(i + 1, 5);
}
else if (code[i].opcode == OpCodes.Blt)
{
code[i] = new OpCodeWrapper(OpCodes.Clt, null);
code[i + 1] = new OpCodeWrapper(OpCodes.Ldc_I4, 0);
code[i + 2] = new OpCodeWrapper(OpCodes.Ceq, null);
code.RemoveRange(i + 3, 3);
}
else if (code[i].opcode == OpCodes.Blt_Un)
{
code[i] = new OpCodeWrapper(OpCodes.Clt_Un, null);
code[i + 1] = new OpCodeWrapper(OpCodes.Ldc_I4, 0);
code[i + 2] = new OpCodeWrapper(OpCodes.Ceq, null);
code.RemoveRange(i + 3, 3);
}
else if (code[i].opcode == OpCodes.Bge || code[i].opcode == OpCodes.Bge_Un)
{
code[i] = new OpCodeWrapper(OpCodes.Clt, null);
code.RemoveRange(i + 1, 5);
}
else if (code[i].opcode == OpCodes.Bgt)
{
code[i] = new OpCodeWrapper(OpCodes.Cgt, null);
code[i + 1] = new OpCodeWrapper(OpCodes.Ldc_I4, 0);
code[i + 2] = new OpCodeWrapper(OpCodes.Ceq, null);
code.RemoveRange(i + 3, 3);
}
else if (code[i].opcode == OpCodes.Bgt_Un)
{
code[i] = new OpCodeWrapper(OpCodes.Cgt_Un, null);
code[i + 1] = new OpCodeWrapper(OpCodes.Ldc_I4, 0);
code[i + 2] = new OpCodeWrapper(OpCodes.Ceq, null);
code.RemoveRange(i + 3, 3);
}
}
}
}