为什么const在IL中长期转换成短路?

时间:2013-04-07 17:08:53

标签: .net il

简单的好奇心,这段代码

    private const long constLong = 16;
    private static long instanceLong = 16;

    static long constTest()
    { 
        long i = 4;
        return i + constLong;
    }

    static long instanceTest()
    {
        long i = 4;
        return i + instanceLong;
    }

产生这个IL:

.field private static literal int64 constLong = int64(16)
.field private static int64 instanceLong

.method private hidebysig static int64 constTest () cil managed 
{
    // Method begins at RVA 0x2068
    // Code size 9 (0x9)
    .maxstack 2
    .locals init (
        [0] int64 i
    )

    IL_0000: ldc.i4.4
    IL_0001: conv.i8
    IL_0002: stloc.0
    IL_0003: ldloc.0
    IL_0004: ldc.i4.s 16
    IL_0006: conv.i8
    IL_0007: add
    IL_0008: ret
} // end of method Program::constTest

.method private hidebysig static int64 instanceTest () cil managed 
{
    // Method begins at RVA 0x2080
    // Code size 11 (0xb)
    .maxstack 2
    .locals init (
        [0] int64 i
    )

    IL_0000: ldc.i4.4
    IL_0001: conv.i8
    IL_0002: stloc.0
    IL_0003: ldloc.0
    IL_0004: ldsfld int64 ConsoleApplication1.Program::instanceLong
    IL_0009: add
    IL_000a: ret
} // end of method Program::instanceTest

为什么constTest()有ldc.i4.s

    IL_0004: ldc.i4.s 16
    IL_0006: conv.i8

而不是ldc.i8

    IL_0004: ldc.i8 16

因为现在constTest()需要执行conv.i8

就像我说的,这是纯粹的好奇心。

3 个答案:

答案 0 :(得分:3)

这种方式更紧凑,请参阅提示标签。

IL_0000: ldc.i4.4
IL_0001: conv.i8
IL_0002: stloc.0

这需要ldc.i4.4一个字节和conv.i8一个字节:总共两个字节。

IL_0004: ldc.i4.s 16
IL_0006: conv.i8
IL_0007: add

ldc.i4.s16需要两个字节,conv.i8需要一个字节:总共三个字节。

并且ldc.i8 16将占用指令一个字节,操作数占用4个字节(16):总共5个字节。

但请记住,较短的IL并不意味着一旦它被JIT(或AOT'ed)更快(或更慢)原生。

答案 1 :(得分:1)

请记住,您正在查看IL,而不是最终的机器代码。 IL的目标是尽可能地捕获代码/程序员意图,以便JITTER可以执行最佳的优化。

如果JITTER这样做会引起关注,但编译器执行此操作时无需担心。

答案 2 :(得分:1)

简单的答案是'这是编译器生成代码的方式'。您必须记住,实际生成的本机代码可以在32位或64位CPU上运行。 IL被编译为目标指令集,因此:

  ldc.i4 4
  conv.i8

很可能成为64位CPU上的单个负载。