Возможная ошибка компилятора C/С++ в Visual Studio 2013

Следующий код C или С++ должен иметь в качестве вывода "11,11,11", однако с помощью Visual Studio Professional 2013 (версия 12.0.40629.00 Обновление 5) вывод "11,0,0"! Это происходит только в сборке релиза и исчезает, когда оптимизация отключена. Является ли это ошибкой компилятора?

#include <stdio.h>

int main(void)
{
    int A[100] = { 0 };
    int row = 0;   // BUG disappears if we make this const or short or char...
    int ncols = 3; // BUG disappears if we make this const or short or char...

    for (int y = row; y <= row; ++y)
    {
        for (int x = 0; x < ncols; ++x)
        {
            const int index = y * ncols + x;

            //A[index] = 11;           // (no bug !)
            *(A + index) = 11;       // BUG!!!
            //*(A + y*ncols+x) = 11;   // (no bug !)
            //*(A + (y*ncols+x)) = 11; // BUG!!!
        }
    }

    for (int x = 0; x < ncols; ++x)
    {
        printf("%d,", A[x]);
    }

    return 0;
}

Ответ 1

Да, это, похоже, ошибка компилятора. В версии кода Win32 компилятор использует регистр esi для представления y и зарегистрировать edx для представления x. Поскольку @Ajay Brahmakshatriya правильно отметил в комментариях, похоже, что компилятор выполнил попытку обмена циклами (поменять внешний на внутренний), но в итоге появился неправильный код. Самая последняя инструкция условного перехода, которая должна представлять внутренний цикл [замененный], по какой-то причине передает управление местоположению, которое также проверяет esi. Эта проверка заканчивает итерации преждевременно.

0018206B  xor         esi,esi             ; This is `y`
0018206D  xor         edx,edx             ; This is `x`
...
00182070  test        esi,esi  
00182072  jg          main+5Ch (018209Ch) ; Exit from the outer cycle?

00182074  lea         eax,[edx+esi*2]     ; Recalculate the starting storage location
00182077  add         eax,esi             ; for the next cycle:
00182079  lea         ecx,[A]             ; eax = esi * 3 + edx
0018207F  lea         eax,[ecx+eax*4]     ; eax = &A[eax]
...
00182082  mov         ecx,1               ; It is not exactly clear to me what this is 
00182087  sub         ecx,esi             ; supposed to do, but when `esi` is `0`, it 
00182089  add         esi,ecx             ; leaves `ecx` as 1, which is correct 
                                          ; number of iterations for outer cycle
...
00182090  mov         dword ptr [eax],0Bh ; Storing the value
00182096  lea         eax,[eax+0Ch]       ; Updating the pointer for the next storage location 
00182099  dec         ecx  
0018209A  jne         main+50h (0182090h) ; Outer cycle [exchanged]

0018209C  inc         edx  
0018209D  cmp         edx,3  
001820A0  jl          main+30h (0182070h) ; Inner cycle [exchanged]: for some reason it
                                          ; jumps to `test esi,esi`, which is what
                                          ; suddenly terminates the iterations