Почему мой оптимизированный IL дважды хранит одно и то же значение в переменной save?

Исходный код представляет собой цикл for следующим образом:

public class ForLoop
{
    public static void Main()
    {
        var count = 0;

        for (var i = 0; i < 10; i = i++)
        {
            count++;
        }
    }
}

Я скомпилировал его с включенной оптимизацией (csc /o+ ForLoop.cs), но у ИЛ есть dupа затем два stloc.1 и ldloc.1,

.method public hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       22 (0x16)
  .maxstack  3
  .locals init (int32 V_0,
           int32 V_1)
  IL_0000:  ldc.i4.0
  IL_0001:  stloc.0
  IL_0002:  ldc.i4.0
  IL_0003:  stloc.1
  IL_0004:  br.s       IL_0010
  IL_0006:  ldloc.0
  IL_0007:  ldc.i4.1
  IL_0008:  add
  IL_0009:  stloc.0
  IL_000a:  ldloc.1
  IL_000b:  dup
  IL_000c:  ldc.i4.1
  IL_000d:  add
  IL_000e:  stloc.1
  IL_000f:  stloc.1
  IL_0010:  ldloc.1
  IL_0011:  ldc.i4.s   10
  IL_0013:  blt.s      IL_0006
  IL_0015:  ret
} // end of method ForLoop::Main

Инструкции как IL_000b дублировать i переменная в моем для цикла. Затем он добавляет 1 к нему, сохраняет результат, так что в стеке остается мое первоначальное значение i, предварительно доп. Затем он снова сохраняет его и загружает снова.

Это не кажется оптимальным или даже правильным.

Так почему он это делает?

1 ответ

Решение

Прежде всего, вы должны понимать, что i++ это на самом деле три операции:

  1. Получить значение i

  2. Добавьте один к значению и сохраните его.

  3. Вставьте новое значение обратно в i,

Во-вторых, ваш код неверен. Ваш цикл имеет i = i++ (а не обычный простой i++) именно поэтому вы видите дополнительные два задания.

Вы делаете три шага, упомянутых о плюс, сохраняя результат i++ а затем толкать его обратно в i,

Другие вопросы по тегам