private void CLRv4_x64_JIT_Workaround()
{
for (int i = 0; i < code.Count - 2; i++)
{
// This is a workaround for https://connect.microsoft.com/VisualStudio/feedback/details/566946/x64-jit-optimization-bug
//
// Testing shows that the bug appears to be very specific and requires a comparison of a method argument with zero.
// For example, the problem goes away when the method argument is first assigned to a local variable and then
// the comparison (and subsequent use) is done against the local variable.
//
// This means we only have to detect these specific patterns:
//
// ldc.i8 0x0 ldarg
// ldarg ldc.i8 0x0
// beq/bne beq/bne
//
// The workaround is to replace ldarg with ldarga/ldind.i8. Looking at the generated code by the x86 and x64 JITs
// this appears to be as efficient as the ldarg and it avoids the x64 bug.
if (code[i].opcode == OpCodes.Ldc_I8 && code[i].ValueInt64 == 0)
{
short arg;
int m;
if (i > 0 && MatchLdarg(code[i - 1], out arg) && IsBranchEqNe(code[i + 1].opcode))
{
m = i - 1;
}
else if (MatchLdarg(code[i + 1], out arg) && IsBranchEqNe(code[i + 2].opcode))
{
m = i + 1;
}
else
{
continue;
}
code[m] = new OpCodeWrapper(OpCodes.Ldarga, arg);
code.Insert(m + 1, new OpCodeWrapper(OpCodes.Ldind_I8, null));
}
}
}