Search code examples
c#.netcil

How to force compiler to use ldc.i8 IL instruction instead of ldc.i4 plus conv.i8?


This is my C# code:

const long pSize = 20;

No matter if I use x64 or Any CPU to build it in Release mode, I get below MSIL instructions:

  IL_0010:  ldc.i4.s   20
  IL_0012:  conv.i8

However, MSIL has ldc.i8 instruction. How to make compiler to use this?


Solution

  • MSIL has ldc.i8 instruction. How to make compiler to use this?

    You don't. That would be worse code.

    ldc.i4.s   20
    conv.i8
    

    is three bytes of code: two for the instructions and one for the constant. Whereas

    ldc.i8 20
    

    is nine bytes: one for the instruction and eight for the constant.

    The compiler is smart enough to avoid six unnecessary bytes. Remember, the speed of the code can be adversely affected by the number of page faults needed to load it into memory; generating code three times larger than it needs to be works against that goal.

    But wait, there's more, and it's all bad.

    The larger a basic block of code is, the more likely it is that a branch around it will be longer than fits in the compact branch instruction format. That means that this de-optimization can make branch instructions large, which in turn makes their basic blocks larger, and now maybe branches around them are not compact, and the whole thing can snowball.

    It's not just the six extra bytes; it's all the consequences of those six extra bytes making other code bigger; you have to account for that cost as well.

    The compiler is doing a good job. Let it do its work.

    If your heart is set on having a compiler that generates worse code, the source code of the compiler is available. Feel free to write a de-optimizing compiler if you really need one for some reason.