Почему GCC выдает здесь другую сборку после указания изменчивости в -O0?C++

Программы на C++. Форум разработчиков
Anonymous
Почему GCC выдает здесь другую сборку после указания изменчивости в -O0?

Сообщение Anonymous »

При использовании godbolt x86-64 gcc 15.1 с -O1 следующий код:

Код: Выделить всё

int i = 2;

int main(int argc, char** argv)
{
while(i != 0) ;
}
генерирует

Код: Выделить всё

main:
mov     eax, DWORD PTR i[rip]
.L2:
test    eax, eax
jne     .L2
ret
i:
.long   2
Читаю только один раз. Делая меня нестабильным,

Код: Выделить всё

volatile int i = 2;

int main(int argc, char** argv)
{
while(i != 0) ;
}
генерирует

Код: Выделить всё

main:
.L2:
mov     eax, DWORD PTR i[rip]
test    eax, eax
jne     .L2
ret
i:
.long   2
чтение на каждой итерации цикла, а не только один раз. Пока хорошо. Но теперь передадим -O0, исходный пример

Код: Выделить всё

int i = 2;

int main(int argc, char** argv)
{
while(i != 0) ;
}
по-прежнему читает каждую итерацию сгенерированного цикла.

Код: Выделить всё

i:
.long   2
main:
push    rbp
mov     rbp, rsp
mov     DWORD PTR [rbp-4], edi
mov     QWORD PTR [rbp-16], rsi
nop
.L2:
mov     eax, DWORD PTR i[rip]
test    eax, eax
jne     .L2
mov     eax, 0
pop     rbp
ret
Что странно, это снова делает меня нестабильным с помощью

Код: Выделить всё

volatile int i = 2;

int main(int argc, char** argv)
{
while(i != 0) ;
}
gcc теперь генерирует новые инструкции setne al и test al, alпосле теста eax, eax

Код: Выделить всё

i:
.long   2
main:
push    rbp
mov     rbp, rsp
mov     DWORD PTR [rbp-4], edi
mov     QWORD PTR [rbp-16], rsi
nop
.L2:
mov     eax, DWORD PTR i[rip]
test    eax, eax
setne   al
test    al, al
jne     .L2
mov     eax, 0
pop     rbp
ret
Почему gcc это делает? Разве существующая сборка, созданная в примере энергонезависимой/-O0, уже не удовлетворяет требованиям изменчивых переменных? Что меняет добавление этих инструкций?

Подробнее здесь: https://stackoverflow.com/questions/798 ... tile-in-o0

Вернуться в «C++»