Есть случаи, когда вы знаете, что определенное выражение с плавающей точкой всегда будет неотрицательным. Например, при вычислении длины вектора выполняется sqrt(a[0]*a[0] + ... + a[N-1]*a[N-1]) (примечание: мне известно о std::hypot, это не относится к вопросу), и выражение под квадратным корнем явно неотрицательно. Однако GCC выводит следующую сборку для sqrt(x*x):
mulss xmm0, xmm0
pxor xmm1, xmm1
ucomiss xmm1, xmm0
ja .L10
sqrtss xmm0, xmm0
ret
.L10:
jmp sqrtf
То есть он сравнивает результат x*x с нулем, а если результат неотрицательный, он выполняет инструкцию sqrtss, в противном случае он вызывает sqrtf.
Итак, мой вопрос: как я могу заставить GCC предположить, что x*x всегда неотрицателен, так что он пропускает сравнение и вызов sqrtf, не записывая встроенную сборку?
Я хочу подчеркнуть, что меня интересует локальное решение, а не такие вещи, как -ffast-math, -fno-math-errno или -ffinite-math-only (хотя они действительно решают проблему, благодаря ks1322, Гарольду и Эрику Постпишилу в комментарии).
Кроме того, "заставить GCC предполагать, что x*x неотрицателен", следует интерпретировать как assert(x*x >= 0.f), поэтому это также исключает случай, когда x*x является NaN.
Я в порядке с решениями для компиляторов, платформ, процессоров и т.д.