У меня есть простая программа:
#include <cmath>
int main()
{
for (int i = 0; i < 50; ++i)
std::sqrt(i);
}
Clang 3.8 оптимизирует его в -O3
, но gcc 6.1. Он создает следующую сборку:
## Annotations in comments added after the question was answered,
## for the benefit of future readers.
main:
pushq %rbx
xorl %ebx, %ebx
jmp .L2
.L4:
pxor %xmm0, %xmm0 # break cvtsi2sd false dep on the old value of xmm0
pxor %xmm1, %xmm1 # xmm1 = 0.0
cvtsi2sd %ebx, %xmm0 # xmm0 = (double)i
ucomisd %xmm0, %xmm1 # scalar double comparison, setting flags
ja .L7 # if (0.0 > (double)i) sqrt(i); // The `a` = above. AT&T syntax reverses the order, but it jump if xmm1 above xmm0
.L2:
addl $1, %ebx # i++
cmpl $50, %ebx
jne .L4 # i != 50
xorl %eax, %eax
popq %rbx
ret # return 0
.L7:
call sqrt # only executed on i < 0. Otherwise gcc knows std::sqrt has no side effects.
jmp .L2
Если я правильно понимаю правило as-if, компилятору разрешено оптимизировать код, который не изменяет наблюдаемое поведение программы, которое включает в себя операции ввода-вывода и т.д. Я отказываюсь от результата std::sqrt
и не выполняйте ввода-вывода. Кроме того, у меня нет #pragma STDC FENV_ACCESS
в моей программе. Имеет ли std::sqrt
наблюдаемые побочные эффекты или есть еще одна причина, по которой GCC не оптимизирует вызов?
(Первоначальная версия этого вопроса имела верхнюю границу 10e50
, делая ее бесконечным циклом. То же самое происходит 50
, поэтому nvm комментарии об этом.)