Преимущество округления inline-ASM путем помещения значения float в переменную int

Я унаследовал довольно интересный кусок кода:

inline int round(float a)
{
  int i;
  __asm {
    fld   a
    fistp i
  }
  return i;
}

Моим первым побуждением было отказаться от него и заменить звонки на(int)std::round (до C ++ 11, будет использоватьstd::lround если бы это случилось сегодня), но через некоторое время я начал задаваться вопросом, может ли это все-таки иметь какое-то значение ...

Вариант использования этой функции - все значения в[-100, 100], так что дажеint8_t будет достаточно широким, чтобы вместить результат.fistpля @ требуется как минимум 32-битная переменная памяти, поэтому меньшеint32_t тратится впустую больше, чем больше.

Теперь совершенно очевидно, что приведение числа с плавающей точкой к int - не самый быстрый способ сделать что-либо, поскольку для этого режим округления должен быть переключен наtruncate, согласно стандарту, и обратно потом. C ++ 11 предлагаетstd::lroundункция @, которая устраняет эту конкретную проблему, но все же кажется более расточительной, учитывая, что значение передается float-> long-> int вместо того, чтобы напрямую прибыть туда, где и должно.

С другой стороны, с inline-ASM в функции компилятор не может оптимизироватьi в регистр (и даже если бы мог,fistp ожидает переменную памяти), поэтомуstd::lround не выглядит намного хуже ...

Однако наиболее актуальный вопрос, который у меня возникает, заключается в том, насколько безопасно предположить (как это делает эта функция), что режим округления всегда будетround-to-nearest, как это очевидно (без проверок). Какstd::lround должен гарантировать определенное поведение, не зависящее от режима округления, это предположение, пока оно выполняется, всегда делает inline-ASM лучшим вариантом.

Кроме того, мне совершенно неясно, установлен ли режим округленияstd::fesetround и используетсяstd::lround альтернативаstd::lrint и режим округления, используемый вfistp ASM-инструкция гарантированно будет одинаковой или хотя бы синхронной.

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

Теперь на вопросы:

Следуя более осознанному взгляду на эти или подобные вопросы, о которых я не задумывался, представляется ли целесообразным использовать эту функцию?

Насколько велик риск, если есть?

Существуют ли рассуждения о том, почему это не будет быстрее, чемstd::lround илиstd::lrint?

Может ли это быть улучшено без снижения производительности?

Изменились ли какие-либо из этих рассуждений, если программа была скомпилирована для x86-64?

Ответы на вопрос(1)

Ваш ответ на вопрос