Почему неиспользуемые параметры не отбрасываются компилятором? - PullRequest
2 голосов
/ 25 октября 2019

Я немного поиграл с Compiler Explorer (Godbolt) и заметил кое-что, что я не могу объяснить.

Предположим, у нас есть функция

int answer(){
    return 42;
}

Сборка выглядит следующим образом (Clang 9, но другие компиляторы ведут себя аналогично):

    push    rbp
    mov     rbp, rsp
    mov     eax, 42 
    pop     rbp
    ret

Что довольноразумный. Теперь, если мы добавим в функцию параметр UNUSED, например:

int answer( double d ){ // or even without name
    return 42;
}

, сборка изменится на:

push    rbp
mov     rbp, rsp
movsd   qword ptr [rbp - 8], xmm0
mov     eax, 42
pop     rbp
ret

Мой вопрос: почему компилятор не пропускает перемещение двойногопотому что он явно не используется (и компилятор знает об этом, потому что предоставляет предупреждения для этого). В чем причина этого?

Ответы [ 2 ]

4 голосов
/ 25 октября 2019

Я предлагаю вам ввести -O1 в поле опций компилятора, вы увидите оптимизированный результат:

mov  eax, 42
ret

Вы можете видеть, что ничего не сделано с параметром в этой версии. Кроме того, ни один стековый фрейм не создается и не разрушается, просто выполняется «загрузка значения возврата и выход».

Нет особых причин для оптимизации, если это не указано пользователем (даже если эта спецификация обусловленанекоторый уровень оптимизации по умолчанию, который может иметь ваша среда).

3 голосов
/ 25 октября 2019

Мой вопрос: почему компилятор не пропускает перемещение двойника, потому что он явно не используется

Потому что это оптимизация, а вы не сказали компиляторудля оптимизации.

На самом деле есть веская причина для , а не оптимизации такого рода вещей вообще, за исключением тех случаев, когда спрашивают: намного проще отлаживать неоптимизированную сборку, как это, потому что локальные параметрыпеременные и фреймы стеков располагаются стандартным образом.

Когда вы попытаетесь запустить оптимизированную сборку через отладчик, вы увидите, что, например, может быть не в состояниипокажет вам значение аргумента double внутри функции: даже если он не используется, вы можете захотеть посмотреть, как была вызвана функция (подробности того, что отладчик может показать в оптимизированном коде, будут зависеть от компилятора, версия и опции, но это общая идея).

...