Почти невозможно (*) предоставить строгую семантику IEEE 754 по разумной цене, если разрешено использовать только команды с плавающей запятой, которые являются 387. Особенно сложно, если вы хотите, чтобы FPU работал над полным 64-битным значением, чтобы тип long double
был доступен для расширенной точности. Обычным "решением" является выполнение промежуточных вычислений с единственной доступной точностью и преобразование в более низкую точность в более или менее четко определенных случаях.
Последние версии GCC обрабатывают избыточную точность в промежуточных вычислениях в соответствии с интерпретацией, изложенной Джозефом С. Майерсом в 2008 сообщение в список рассылки GCC. Это описание делает программу, скомпилированную с gcc -std=c99 -mno-sse2 -mfpmath=387
полностью предсказуемой, до последней бит, насколько я понимаю. И если случайно это не так, это ошибка, и это будет исправлено: заявленное намерение Джозефа С. Майерса в его посте - сделать его предсказуемым.
Является ли это документированным, как Clang обрабатывает избыточную точность (скажем, когда используется опция -mno-sse2
) и где?
(*) EDIT: это преувеличение. Это немного раздражает, но не так сложно, чтобы эмулировать двоичный код64, когда разрешено настраивать FPU x87 для использования 53-битного значения.
Следуя комментарию R.. ниже, вот журнал короткого взаимодействия моего с самой последней версией Clang I:
Hexa:~ $ clang -v
Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn)
Target: x86_64-apple-darwin12.4.0
Thread model: posix
Hexa:~ $ cat fem.c
#include <stdio.h>
#include <math.h>
#include <float.h>
#include <fenv.h>
double x;
double y = 2.0;
double z = 1.0;
int main(){
x = y + z;
printf("%d\n", (int) FLT_EVAL_METHOD);
}
Hexa:~ $ clang -std=c99 -mno-sse2 fem.c
Hexa:~ $ ./a.out
0
Hexa:~ $ clang -std=c99 -mno-sse2 -S fem.c
Hexa:~ $ cat fem.s
…
movl $0, %esi
fldl _y(%rip)
fldl _z(%rip)
faddp %st(1)
movq [email protected](%rip), %rax
fstpl (%rax)
…