当唯一允许使用的浮点指令是387个浮点指令时,几乎不可能(*)以合理的代价提供严格的IEEE 754语义。当您希望保持FPU在64位的意义上工作,以便long double类型可用于扩展精度时,这就特别困难了。通常的“解决方案”是在唯一可用的精度上进行中间计算,并在或多或少明确定义的情况下转换为较低的精度。
根据约瑟夫·S·迈尔斯(JosephS.Myers)在2008年邮寄至GCC邮件列表中提出的解释,最近版本的GCC在中间计算中处理过高的精度。据我所知,这种描述使用gcc -std=c99 -mno-sse2 -mfpmath=387编译的程序完全可以预测,直到最后一点。如果它不是偶然的,它是一个错误,它将被修复:约瑟夫S迈尔斯在他的帖子中声明的意图是使它可以预测。
是否记录了Clang如何处理超额精度(例如何时使用-mno-sse2选项),以及在何处?
编辑:这是夸大其词。当允许将有点烦人,但没那么难 FPU配置为使用53位重要值时,就可以模拟binary64。
根据R.的评论..。下面是我与最新版本Clang的简短交互日志:
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 _x@GOTPCREL(%rip), %rax
fstpl (%rax)
…发布于 2013-09-24 18:41:14
为了记录在案,下面是我通过实验发现的。下面的程序显示了使用Clang编译时的各种行为:
#include <stdio.h>
int r1, r2, r3, r4, r5, r6, r7;
double ten = 10.0;
int main(int c, char **v)
{
r1 = 0.1 == (1.0 / ten);
r2 = 0.1 == (1.0 / 10.0);
r3 = 0.1 == (double) (1.0 / ten);
r4 = 0.1 == (double) (1.0 / 10.0);
ten = 10.0;
r5 = 0.1 == (1.0 / ten);
r6 = 0.1 == (double) (1.0 / ten);
r7 = ((double) 0.1) == (1.0 / 10.0);
printf("r1=%d r2=%d r3=%d r4=%d r5=%d r6=%d r7=%d\n", r1, r2, r3, r4, r5, r6, r7);
}结果随优化级别的不同而不同:
$ clang -v
Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
$ clang -mno-sse2 -std=c99 t.c && ./a.out
r1=0 r2=1 r3=0 r4=1 r5=1 r6=0 r7=1
$ clang -mno-sse2 -std=c99 -O2 t.c && ./a.out
r1=0 r2=1 r3=0 r4=1 r5=1 r6=1 r7=1区分r5和r6的cast r5和r6在-O0以及变量r3和r4上没有影响。结果r1在所有优化级别上都与r5不同,而r6仅与-O2上的r3不同。
https://stackoverflow.com/questions/17663780
复制相似问题