Here is the example with comments:
class Program
{
// first version of structure
public struct D1
{
public double d;
public int f
Vilx's conjecture is correct. What "CanCompareBits" does is checks to see whether the value type in question is "tightly packed" in memory. A tightly packed struct is compared by simply comparing the binary bits that make up the structure; a loosely packed structure is compared by calling Equals on all the members.
This explains SLaks' observation that it repros with structs that are all doubles; such structs are always tightly packed.
Unfortunately as we've seen here, that introduces a semantic difference because bitwise comparison of doubles and Equals comparison of doubles gives different results.